2025-04-27 07:49:33 -04:00

509 lines
15 KiB
C++

#include "main.h"
#include "iadmw.h"
#define TIMEOUT_VALUE 5000
#if defined(UNICODE) || defined(_UNICODE)
#else
void MyMultiByteToWideChar( char *sData, WCHAR *wData, int cbBufSize, BOOL fMultiSZ)
{
MultiByteToWideChar( CP_ACP, 0, sData, -1, wData, cbBufSize );
while (fMultiSZ)
{
sData = _tcsninc( sData, _tcslen(sData)) + 1;
while (*wData++);
if (*sData)
{
MultiByteToWideChar( CP_ACP, 0, sData, -1, wData, cbBufSize );
}
else
{
*wData = L'\0';
break;
}
}
return;
}
void MyWideCharToMultiByte( WCHAR *wData, char *sData, int cbBufSize, BOOL fMultiSZ)
{
WideCharToMultiByte( CP_ACP, 0, wData, -1, sData, cbBufSize, NULL, NULL );
while (fMultiSZ)
{
while (*wData++);
sData = _tcsninc( sData, _tcslen(sData)) + 1;
if (*wData)
{
WideCharToMultiByte( CP_ACP, 0, wData, -1, sData, cbBufSize, NULL, NULL );
}
else
{
*sData = '\0';
break;
}
}
return;
}
#endif // unicode
CMDKey::CMDKey():
m_cCoInits(0)
{
m_pcCom = NULL;
m_hKey = NULL;
}
CMDKey::~CMDKey()
{
this->Close();
// while there are outstanding coinits, close them
while ( m_cCoInits > 0 && !(m_cCoInits < 0) )
DoCoUnInit();
}
HRESULT CMDKey::DoCoInitEx()
{
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
// track our calls to coinit
if ( SUCCEEDED(hRes) )
{
m_cCoInits++;
}
return hRes;
}
void CMDKey::DoCoUnInit()
{
HRESULT hRes = NOERROR;
// if there are outstanding coinits, uninit one
if ( m_cCoInits > 0 )
{
////iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().Start.")));
CoUninitialize();
////iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().End.")));
m_cCoInits--;
}
// we shouldn't ever have a negative count. But just in case...
//ASSERT( m_cCoInits >= 0 );
if ( m_cCoInits < 0 )
{
// something is seriously wrong here. Prevent looping
// by going straight to zero, and write an error to the log.
m_cCoInits = 0;
//iisDebugOut((LOG_TYPE_WARN, _T("WARNING: CoInits in mdkey have gone negative")));
}
}
HRESULT CMDKey::OpenNode(LPCTSTR pchSubKeyPath)
{
HRESULT hRes = ERROR_SUCCESS;
IClassFactory * pcsfFactory = NULL;
BOOL b = FALSE;
m_pcCom = NULL;
m_hKey = NULL;
WCHAR szSubKeyPath[_MAX_PATH];
pszFailedAPI = NULL;
if ( !pchSubKeyPath || !(*pchSubKeyPath) )
{
*szSubKeyPath = L'\0';
}
else
{
#if defined(UNICODE) || defined(_UNICODE)
_tcscpy(szSubKeyPath, pchSubKeyPath);
#else
MultiByteToWideChar( CP_ACP, 0, pchSubKeyPath, -1, szSubKeyPath, _MAX_PATH);
#endif
}
hRes = DoCoInitEx();
if (FAILED(hRes))
{
printf("CMDKey::OpenNode failed at DoCoInitEx");
}
hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
if (FAILED(hRes))
{
printf("CMDKey::OpenNode failed at CoGetClassObject");
}
else
{
hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
pcsfFactory->Release();
if (FAILED(hRes))
{
printf("CMDKey::OpenNode failed at pcsfFactory->CreateInstance");
}
else
{
hRes = m_pcCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
if (FAILED(hRes))
{
if (hRes != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))
{
printf("CMDKey::OpenNode failed at OpenKey");
}
}
else
{
b = TRUE;
}
} // end of CoCreateInstance
} // end of CoGetClassObject
if (!b) {this->Close();}
return hRes;
}
HRESULT CMDKey::ForceWriteMetabaseToDisk()
{
HRESULT hRes = ERROR_SUCCESS;
IClassFactory * pcsfFactory = NULL;
m_pcCom = NULL;
hRes = DoCoInitEx();
if (FAILED(hRes))
{
printf("ForceWriteMetabaseToDisk failed at DoCoInitEx\n");
}
hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
if (FAILED(hRes))
{
printf("ForceWriteMetabaseToDisk failed at CoGetClassObject\n");
}
else
{
hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
pcsfFactory->Release();
if (FAILED(hRes))
{
printf("ForceWriteMetabaseToDisk failed at CreateInstance\n");
}
else
{
if (m_pcCom)
{
hRes = m_pcCom->SaveData();
printf("ForceWriteMetabaseToDisk Success.\n");
}
} // end of CoCreateInstance
} // end of CoGetClassObject
return hRes;
}
HRESULT CMDKey::Close()
{
HRESULT hRes = ERROR_SUCCESS;
if (m_pcCom)
{
if (m_hKey){hRes = m_pcCom->CloseKey(m_hKey);}
hRes = m_pcCom->Release();
}
DoCoUnInit();
m_pcCom = NULL;
m_hKey = NULL;
return hRes;
}
HRESULT CMDKey::SetData(DWORD id,DWORD attr,DWORD uType,DWORD dType,DWORD cbLen, LPBYTE pbData,PWCHAR pszSubString )
{
HRESULT hRes = ERROR_SUCCESS;
METADATA_RECORD mdrData;
BUFFER bufData;
WCHAR *pData = (WCHAR *)pbData;
int iPlsDoNoEncryption = FALSE;
switch (dType)
{
case STRING_METADATA:
case EXPANDSZ_METADATA:
#if defined(UNICODE) || defined(_UNICODE)
pData = (WCHAR *)pbData;
#else
if ( ! (bufData.Resize(cbLen * sizeof(WCHAR))) )
{
// insufficient memory
hRes = RETURNCODETOHRESULT(GetLastError());
goto SetData_Exit;
}
pData = (WCHAR *)(bufData.QueryPtr());
MyMultiByteToWideChar( (LPTSTR)pbData, pData, cbLen, FALSE);
cbLen = cbLen * sizeof(WCHAR);
#endif
break;
case MULTISZ_METADATA:
#if defined(UNICODE) || defined(_UNICODE)
pData = (WCHAR *)pbData;
#else
if ( ! (bufData.Resize(cbLen * sizeof(WCHAR))) )
{
// insufficient memory
hRes = RETURNCODETOHRESULT(GetLastError());
goto SetData_Exit;
}
pData = (WCHAR *)(bufData.QueryPtr());
MyMultiByteToWideChar( (LPTSTR)pbData, pData, cbLen, TRUE );
cbLen = cbLen * sizeof(WCHAR);
#endif
break;
default:
break;
}
if (cbLen >= 0)
{
MD_SET_DATA_RECORD(&mdrData, id, attr, uType, dType, cbLen, (LPBYTE)pData);
hRes = m_pcCom->SetData(m_hKey, pszSubString, &mdrData);
if (FAILED(hRes))
{
// Check if it failed...
// if it failed and the METADATA_SECURE flag is set, then
// check if we can retry without the METADATA_SECURE flag!
if ( attr & METADATA_SECURE )
{
iPlsDoNoEncryption = TRUE;
if (TRUE == iPlsDoNoEncryption)
{
attr &= ~METADATA_SECURE;
MD_SET_DATA_RECORD(&mdrData, id, attr, uType, dType, cbLen, (LPBYTE)pData);
hRes = m_pcCom->SetData(m_hKey, pszSubString, &mdrData);
// set the attr back to what it was
attr &= ~METADATA_SECURE;
}
}
}
}
goto SetData_Exit;
SetData_Exit:
return hRes;
}
// Note: only use to access the AnonyName and AnonyPassword,
// buffer size 256 is big enough here
BOOL CMDKey::GetData(DWORD id,DWORD *pdwAttr,DWORD *pdwUType,DWORD *pdwDType,DWORD *pcbLen,LPBYTE pbData,DWORD BufSize,DWORD dwAttributes,DWORD dwUType,DWORD dwDType,PWCHAR pszSubString )
{
int ReturnIndex;
BOOL fReturn = FALSE;
HRESULT hRes = ERROR_SUCCESS;
METADATA_RECORD mdrData;
DWORD dwRequiredDataLen = 0;
LPBYTE ReturnBuf=NULL;
int ReturnBufSize;
// if we are just trying to get the size of the field, just do that.
if ( !pbData || (BufSize == 0) )
{
MD_SET_DATA_RECORD(&mdrData, id, dwAttributes, dwUType, dwDType, 0, NULL);
hRes = m_pcCom->GetData(m_hKey, pszSubString, &mdrData, &dwRequiredDataLen);
*pcbLen = dwRequiredDataLen;
fReturn = (hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER));
goto GetData_Exit;
}
#if defined(UNICODE) || defined(_UNICODE)
ReturnBufSize = BufSize;
#else
ReturnBufSize = 2 * BufSize;
#endif
ReturnBuf = (LPBYTE)LocalAlloc(LPTR, ReturnBufSize);
if (!ReturnBuf)
{
ReturnBuf = NULL;
goto GetData_Exit;
}
//DisplayStringForMetabaseID(id);
MD_SET_DATA_RECORD(&mdrData, id, dwAttributes, dwUType, dwDType, ReturnBufSize, (PBYTE) ReturnBuf);
hRes = m_pcCom->GetData(m_hKey, pszSubString, &mdrData, &dwRequiredDataLen);
if (FAILED(hRes))
{
if (hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER))
{
#if defined(UNICODE) || defined(_UNICODE)
*pcbLen = dwRequiredDataLen;
#else
*pcbLen = dwRequiredDataLen / 2;
#endif
}
else
{
*pcbLen = 0;
if (hRes != MD_ERROR_DATA_NOT_FOUND)
{
MessageBox(NULL, _T("GETDATA_ERROR"), NULL, MB_OK | MB_SETFOREGROUND);
}
}
goto GetData_Exit;
}
// --------
// We have successfully retrieved the data at this point
// --------
*pdwAttr = mdrData.dwMDAttributes;
*pdwUType = mdrData.dwMDUserType;
*pdwDType = mdrData.dwMDDataType;
*pcbLen = mdrData.dwMDDataLen; // number of SBCS chars + ending \0
switch (*pdwDType)
{
case STRING_METADATA:
case EXPANDSZ_METADATA:
#if defined(UNICODE) || defined(_UNICODE)
memcpy(pbData, mdrData.pbMDData, *pcbLen);
#else
*pcbLen = (*pcbLen) / sizeof(WCHAR);
WideCharToMultiByte(CP_ACP,0,(WCHAR *)(mdrData.pbMDData),-1,(LPSTR)pbData,*pcbLen, NULL, NULL);
#endif
fReturn = TRUE;
break;
case MULTISZ_METADATA:
#if defined(UNICODE) || defined(_UNICODE)
memcpy(pbData, mdrData.pbMDData, *pcbLen);
#else
*pcbLen = (*pcbLen) / sizeof(WCHAR);
MyWideCharToMultiByte((WCHAR *)(mdrData.pbMDData),(LPSTR)pbData, *pcbLen, TRUE);
#endif
fReturn = TRUE;
break;
default:
memcpy(pbData, mdrData.pbMDData, *pcbLen);
fReturn = TRUE;
break;
}
GetData_Exit:
if(ReturnBuf) {LocalFree(ReturnBuf);}
return fReturn;
}
HRESULT CMDKey::CreateNode(METADATA_HANDLE hKeyBase, LPCTSTR pchSubKeyPath)
{
HRESULT hRes = ERROR_SUCCESS;
IClassFactory * pcsfFactory = NULL;
BOOL b = FALSE;
m_pcCom = NULL;
m_hKey = NULL;
WCHAR szSubKeyPath[_MAX_PATH];
pszFailedAPI = NULL;
if ( !pchSubKeyPath || !(*pchSubKeyPath) )
{
*szSubKeyPath = L'\0';
}
else
{
#if defined(UNICODE) || defined(_UNICODE)
_tcscpy(szSubKeyPath, pchSubKeyPath);
#else
MultiByteToWideChar( CP_ACP, 0, pchSubKeyPath, -1, szSubKeyPath, _MAX_PATH);
#endif
}
hRes = DoCoInitEx();
if (FAILED(hRes))
{
//iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx() failed, hRes=%x\n"), hRes));
}
//iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().Start.")));
hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
//iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().End.")));
if (FAILED(hRes))
{
///MyMessageBox(NULL, _T("CoGetClassObject"), hRes, MB_OK | MB_SETFOREGROUND);
}
else
{
hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
pcsfFactory->Release();
if (FAILED(hRes))
{
//MyMessageBox(NULL, _T("CreateInstance"), hRes, MB_OK | MB_SETFOREGROUND);
}
else
{
hRes = m_pcCom->OpenKey(hKeyBase,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
if (FAILED(hRes))
{
if (hRes == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))
{
METADATA_HANDLE RootHandle;
hRes = m_pcCom->OpenKey(hKeyBase,L"",METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&RootHandle);
hRes = m_pcCom->AddKey(RootHandle, szSubKeyPath);
if (FAILED(hRes))
{
//MyMessageBox(NULL, _T("AddKey"), hRes, MB_OK | MB_SETFOREGROUND);
}
hRes = m_pcCom->CloseKey(RootHandle);
if (FAILED(hRes))
{
//MyMessageBox(NULL, _T("CloseKey of the AddKey"), hRes, MB_OK | MB_SETFOREGROUND);
}
else
{
// open it again to set m_hKey
hRes = m_pcCom->OpenKey(hKeyBase,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
if (FAILED(hRes))
{
//MyMessageBox(NULL, _T("OpenKey"), hRes, MB_OK | MB_SETFOREGROUND);
}
else
{
b = TRUE;
}
}
}
else
{
//iisDebugOut((LOG_TYPE_ERROR, _T("calling OpenKey()...failed....something other than ERROR_PATH_NOT_FOUND\n")));
//MyMessageBox(NULL, _T("OpenKey"), hRes, MB_OK | MB_SETFOREGROUND);
}
}
else
{
b = TRUE;
} // end of OpenKey
} // end of CoCreateInstance
} // end of CoGetClassObject
if (!b) {this->Close();}
return hRes;
}
BOOL CMDKey::GetData(DWORD id,DWORD *pdwAttr,DWORD *pdwUType,DWORD *pdwDType,DWORD *pcbLen,LPBYTE pbData,DWORD BufSize,PWCHAR pszSubString )
{
return GetData(id,pdwAttr,pdwUType,pdwDType,pcbLen,pbData,BufSize,0,0,0,pszSubString);
}