509 lines
15 KiB
C++
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);
|
|
}
|