Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1630 lines
47 KiB

  1. // MdKey.cpp
  2. #include "stdafx.h"
  3. #define INITGUID
  4. #define _WIN32_DCOM
  5. #undef DEFINE_GUID // Added for NT5 migration
  6. #include <ole2.h>
  7. #include <coguid.h>
  8. #include "iadmw.h"
  9. #include "iiscnfg.h"
  10. #include "mdkey.h"
  11. #include "iwamreg.h"
  12. #include "strfn.h"
  13. #define TIMEOUT_VALUE 5000
  14. INT_PTR CALLBACK pSecureRetryIgnoreAllDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  15. extern BOOL g_bGlobalWriteUnSecuredIfFailed_All;
  16. CMDKey::CMDKey():
  17. m_cCoInits(0)
  18. {
  19. m_pcCom = NULL;
  20. m_hKey = NULL;
  21. _tcscpy(m_szCurrentNodeName, _T(""));
  22. }
  23. CMDKey::~CMDKey()
  24. {
  25. this->Close();
  26. // while there are outstanding coinits, close them
  27. while ( m_cCoInits > 0 && !(m_cCoInits < 0) )
  28. DoCoUnInit();
  29. }
  30. HRESULT CMDKey::DoCoInitEx()
  31. {
  32. HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  33. // track our calls to coinit
  34. if ( SUCCEEDED(hRes) )
  35. {
  36. m_cCoInits++;
  37. }
  38. return hRes;
  39. }
  40. void CMDKey::DoCoUnInit()
  41. {
  42. HRESULT hRes = NOERROR;
  43. // if there are outstanding coinits, uninit one
  44. if ( m_cCoInits > 0 )
  45. {
  46. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().Start.")));
  47. CoUninitialize();
  48. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().End.")));
  49. m_cCoInits--;
  50. }
  51. // we shouldn't ever have a negative count. But just in case...
  52. ASSERT( m_cCoInits >= 0 );
  53. if ( m_cCoInits < 0 )
  54. {
  55. // something is seriously wrong here. Prevent looping
  56. // by going straight to zero, and write an error to the log.
  57. m_cCoInits = 0;
  58. iisDebugOut((LOG_TYPE_WARN, _T("WARNING: CoInits in mdkey have gone negative")));
  59. }
  60. }
  61. // function: EnumKeys
  62. //
  63. // Enumerates the keys under the node that is open
  64. //
  65. // Parameters:
  66. // pchMDName - The resulting name of the key enumeated
  67. // dwIndex - Index of Item to enumerate
  68. // pszSubKeyPath - The subkey of the item to open
  69. BOOL
  70. CMDKey::EnumKeys( LPWSTR pchMDName, DWORD dwIndex, LPTSTR pszSubKeyPath )
  71. {
  72. WCHAR szSubKeyPath[_MAX_PATH] = L"";
  73. #if defined(UNICODE) || defined(_UNICODE)
  74. _tcscpy(szSubKeyPath, pszSubKeyPath);
  75. #else
  76. if ( MultiByteToWideChar( CP_ACP, 0, pszSubKeyPath, -1, szSubKeyPath, _MAX_PATH) == 0 )
  77. {
  78. return FALSE;
  79. }
  80. #endif
  81. return SUCCEEDED( m_pcCom->EnumKeys(m_hKey, szSubKeyPath, pchMDName, dwIndex) );
  82. }
  83. HRESULT CMDKey::OpenNode(LPCTSTR pchSubKeyPath, BOOL bSupressErrorMessage )
  84. {
  85. HRESULT hRes = ERROR_SUCCESS;
  86. IClassFactory * pcsfFactory = NULL;
  87. BOOL b = FALSE;
  88. m_pcCom = NULL;
  89. m_hKey = NULL;
  90. WCHAR szSubKeyPath[_MAX_PATH];
  91. pszFailedAPI = NULL;
  92. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  93. if ( !pchSubKeyPath || !(*pchSubKeyPath) )
  94. {
  95. *szSubKeyPath = L'\0';
  96. }
  97. else
  98. {
  99. #if defined(UNICODE) || defined(_UNICODE)
  100. _tcscpy(szSubKeyPath, pchSubKeyPath);
  101. #else
  102. MultiByteToWideChar( CP_ACP, 0, pchSubKeyPath, -1, szSubKeyPath, _MAX_PATH);
  103. #endif
  104. }
  105. hRes = DoCoInitEx();
  106. if ( FAILED(hRes) && !bSupressErrorMessage )
  107. {
  108. iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx() failed, hRes=%x\n"), hRes));
  109. }
  110. hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
  111. if ( FAILED(hRes) )
  112. {
  113. if ( !bSupressErrorMessage )
  114. {
  115. MyMessageBox(NULL, _T("CoGetClassObject"), hRes, MB_OK | MB_SETFOREGROUND);
  116. }
  117. }
  118. else
  119. {
  120. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
  121. pcsfFactory->Release();
  122. if ( FAILED(hRes) )
  123. {
  124. if ( !bSupressErrorMessage )
  125. {
  126. MyMessageBox(NULL, _T("CoCreateInstance"), hRes, MB_OK | MB_SETFOREGROUND);
  127. }
  128. }
  129. else
  130. {
  131. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  132. hRes = m_pcCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
  133. if ( FAILED(hRes))
  134. {
  135. if ( ( hRes != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND) ) && !bSupressErrorMessage )
  136. {
  137. MyMessageBox(NULL, _T("OpenKey"), hRes, MB_OK | MB_SETFOREGROUND);
  138. }
  139. }
  140. else
  141. {
  142. b = TRUE;
  143. }
  144. } // end of CoCreateInstance
  145. } // end of CoGetClassObject
  146. if (!b) {this->Close();}
  147. return hRes;
  148. }
  149. HRESULT CMDKey::CreateNode(METADATA_HANDLE hKeyBase, LPCTSTR pchSubKeyPath)
  150. {
  151. HRESULT hRes = ERROR_SUCCESS;
  152. IClassFactory * pcsfFactory = NULL;
  153. BOOL b = FALSE;
  154. m_pcCom = NULL;
  155. m_hKey = NULL;
  156. WCHAR szSubKeyPath[_MAX_PATH];
  157. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  158. pszFailedAPI = NULL;
  159. if ( !pchSubKeyPath || !(*pchSubKeyPath) )
  160. {
  161. *szSubKeyPath = L'\0';
  162. }
  163. else
  164. {
  165. #if defined(UNICODE) || defined(_UNICODE)
  166. _tcscpy(szSubKeyPath, pchSubKeyPath);
  167. #else
  168. MultiByteToWideChar( CP_ACP, 0, pchSubKeyPath, -1, szSubKeyPath, _MAX_PATH);
  169. #endif
  170. }
  171. hRes = DoCoInitEx();
  172. if (FAILED(hRes))
  173. {
  174. iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx() failed, hRes=%x\n"), hRes));
  175. }
  176. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().Start.")));
  177. hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
  178. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().End.")));
  179. if (FAILED(hRes))
  180. {
  181. MyMessageBox(NULL, _T("CoGetClassObject"), hRes, MB_OK | MB_SETFOREGROUND);
  182. }
  183. else
  184. {
  185. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
  186. pcsfFactory->Release();
  187. if (FAILED(hRes))
  188. {
  189. MyMessageBox(NULL, _T("CreateInstance"), hRes, MB_OK | MB_SETFOREGROUND);
  190. }
  191. else
  192. {
  193. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  194. hRes = m_pcCom->OpenKey(hKeyBase,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
  195. if (FAILED(hRes))
  196. {
  197. if (hRes == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))
  198. {
  199. METADATA_HANDLE RootHandle;
  200. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  201. hRes = m_pcCom->OpenKey(hKeyBase,L"",METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&RootHandle);
  202. hRes = m_pcCom->AddKey(RootHandle, szSubKeyPath);
  203. if (FAILED(hRes))
  204. {
  205. MyMessageBox(NULL, _T("AddKey"), hRes, MB_OK | MB_SETFOREGROUND);
  206. }
  207. hRes = m_pcCom->CloseKey(RootHandle);
  208. if (FAILED(hRes))
  209. {
  210. MyMessageBox(NULL, _T("CloseKey of the AddKey"), hRes, MB_OK | MB_SETFOREGROUND);
  211. }
  212. else
  213. {
  214. // open it again to set m_hKey
  215. _tcscpy(m_szCurrentNodeName, pchSubKeyPath);
  216. hRes = m_pcCom->OpenKey(hKeyBase,szSubKeyPath,METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,TIMEOUT_VALUE,&m_hKey);
  217. if (FAILED(hRes))
  218. {
  219. MyMessageBox(NULL, _T("OpenKey"), hRes, MB_OK | MB_SETFOREGROUND);
  220. }
  221. else
  222. {
  223. b = TRUE;
  224. }
  225. }
  226. }
  227. else
  228. {
  229. iisDebugOut((LOG_TYPE_ERROR, _T("calling OpenKey()...failed....something other than ERROR_PATH_NOT_FOUND\n")));
  230. MyMessageBox(NULL, _T("OpenKey"), hRes, MB_OK | MB_SETFOREGROUND);
  231. }
  232. }
  233. else
  234. {
  235. b = TRUE;
  236. } // end of OpenKey
  237. } // end of CoCreateInstance
  238. } // end of CoGetClassObject
  239. if (!b) {this->Close();}
  240. return hRes;
  241. }
  242. HRESULT CMDKey::ForceWriteMetabaseToDisk()
  243. {
  244. HRESULT hRes = ERROR_SUCCESS;
  245. IClassFactory * pcsfFactory = NULL;
  246. m_pcCom = NULL;
  247. hRes = DoCoInitEx();
  248. if (FAILED(hRes))
  249. {
  250. iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx() failed, hRes=%x\n"), hRes));
  251. }
  252. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().Start.")));
  253. hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
  254. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoGetClassObject().End.")));
  255. if (FAILED(hRes))
  256. {
  257. MyMessageBox(NULL, _T("CoGetClassObject"), hRes, MB_OK | MB_SETFOREGROUND);
  258. }
  259. else
  260. {
  261. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) &m_pcCom);
  262. pcsfFactory->Release();
  263. if (FAILED(hRes))
  264. {
  265. MyMessageBox(NULL, _T("CoCreateInstance"), hRes, MB_OK | MB_SETFOREGROUND);
  266. }
  267. else
  268. {
  269. if (m_pcCom)
  270. {
  271. hRes = m_pcCom->SaveData();
  272. iisDebugOut((LOG_TYPE_TRACE, _T("CMDKey::ForceWriteMetabaseToDisk():Return=0x%x.\n"),hRes));
  273. }
  274. } // end of CoCreateInstance
  275. } // end of CoGetClassObject
  276. return hRes;
  277. }
  278. HRESULT CMDKey::Close()
  279. {
  280. HRESULT hRes = ERROR_SUCCESS;
  281. if (m_pcCom)
  282. {
  283. if (m_hKey){hRes = m_pcCom->CloseKey(m_hKey);}
  284. hRes = m_pcCom->Release();
  285. }
  286. DoCoUnInit();
  287. m_pcCom = NULL;
  288. m_hKey = NULL;
  289. _tcscpy(m_szCurrentNodeName, _T(""));
  290. return hRes;
  291. }
  292. BOOL CMDKey::IsEmpty( PWCHAR pszSubString )
  293. {
  294. int ReturnIndex;
  295. METADATA_RECORD mdrData;
  296. DWORD dwRequiredDataLen = 0;
  297. HRESULT hRes = ERROR_SUCCESS;
  298. UCHAR ReturnBuf[256];
  299. for(ReturnIndex=0;ReturnIndex<sizeof(ReturnBuf);ReturnIndex++)ReturnBuf[ReturnIndex]=0xff;
  300. MD_SET_DATA_RECORD(&mdrData, 0, METADATA_NO_ATTRIBUTES, 0, 0, sizeof(ReturnBuf), (PBYTE) ReturnBuf)
  301. hRes = m_pcCom->EnumData(m_hKey, pszSubString, &mdrData, 0, &dwRequiredDataLen);
  302. if (FAILED(hRes))
  303. {
  304. if(hRes == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS) || hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER) )
  305. {
  306. return TRUE;
  307. }
  308. else
  309. {
  310. MyMessageBox(NULL, _T("EnumData"), hRes, MB_OK | MB_SETFOREGROUND);
  311. }
  312. }
  313. return (hRes != ERROR_SUCCESS);
  314. }
  315. int CMDKey::GetNumberOfSubKeys( PWCHAR pszSubString )
  316. {
  317. int i=0;
  318. HRESULT hRes = ERROR_SUCCESS;
  319. WCHAR NameBuf[METADATA_MAX_NAME_LEN];
  320. while (hRes == ERROR_SUCCESS)
  321. {
  322. hRes = m_pcCom->EnumKeys(m_hKey, pszSubString, NameBuf, i++);
  323. }
  324. if (hRes == RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS))
  325. {
  326. return (--i);
  327. }
  328. else
  329. {
  330. MyMessageBox(NULL, _T("EnumKeys"), hRes, MB_OK | MB_SETFOREGROUND);
  331. return (0);
  332. }
  333. }
  334. #if !defined(UNICODE) && !defined(_UNICODE)
  335. void MyMultiByteToWideChar( char *sData, WCHAR *wData, int cbBufSize, BOOL fMultiSZ)
  336. {
  337. MultiByteToWideChar( CP_ACP, 0, sData, -1, wData, cbBufSize );
  338. while (fMultiSZ)
  339. {
  340. sData = _tcsninc( sData, _tcslen(sData)) + 1;
  341. while (*wData++);
  342. if (*sData)
  343. {
  344. MultiByteToWideChar( CP_ACP, 0, sData, -1, wData, cbBufSize );
  345. }
  346. else
  347. {
  348. *wData = L'\0';
  349. break;
  350. }
  351. }
  352. return;
  353. }
  354. void MyWideCharToMultiByte( WCHAR *wData, char *sData, int cbBufSize, BOOL fMultiSZ)
  355. {
  356. WideCharToMultiByte( CP_ACP, 0, wData, -1, sData, cbBufSize, NULL, NULL );
  357. while (fMultiSZ)
  358. {
  359. while (*wData++);
  360. sData = _tcsninc( sData, _tcslen(sData)) + 1;
  361. if (*wData)
  362. {
  363. WideCharToMultiByte( CP_ACP, 0, wData, -1, sData, cbBufSize, NULL, NULL );
  364. }
  365. else
  366. {
  367. *sData = '\0';
  368. break;
  369. }
  370. }
  371. return;
  372. }
  373. #endif // not unicode
  374. HRESULT CMDKey::SetData(DWORD id,DWORD attr,DWORD uType,DWORD dType,DWORD cbLen, LPBYTE pbData,PWCHAR pszSubString )
  375. {
  376. HRESULT hRes = ERROR_SUCCESS;
  377. METADATA_RECORD mdrData;
  378. BUFFER bufData;
  379. WCHAR *pData = (WCHAR *)pbData;
  380. int iPlsDoNoEncryption = FALSE;
  381. switch (dType)
  382. {
  383. case STRING_METADATA:
  384. case EXPANDSZ_METADATA:
  385. #if defined(UNICODE) || defined(_UNICODE)
  386. pData = (WCHAR *)pbData;
  387. #else
  388. if ( ! (bufData.Resize(cbLen * sizeof(WCHAR))) )
  389. {
  390. // insufficient memory
  391. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetData() failed to allocate memory.\n")));
  392. hRes = RETURNCODETOHRESULT(GetLastError());
  393. goto SetData_Exit;
  394. }
  395. pData = (WCHAR *)(bufData.QueryPtr());
  396. MyMultiByteToWideChar( (LPTSTR)pbData, pData, cbLen, FALSE);
  397. cbLen = cbLen * sizeof(WCHAR);
  398. #endif
  399. break;
  400. case MULTISZ_METADATA:
  401. #if defined(UNICODE) || defined(_UNICODE)
  402. pData = (WCHAR *)pbData;
  403. #else
  404. if ( ! (bufData.Resize(cbLen * sizeof(WCHAR))) )
  405. {
  406. // insufficient memory
  407. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetData() failed to allocate memory.\n")));
  408. hRes = RETURNCODETOHRESULT(GetLastError());
  409. goto SetData_Exit;
  410. }
  411. pData = (WCHAR *)(bufData.QueryPtr());
  412. MyMultiByteToWideChar( (LPTSTR)pbData, pData, cbLen, TRUE );
  413. cbLen = cbLen * sizeof(WCHAR);
  414. #endif
  415. break;
  416. default:
  417. break;
  418. }
  419. //DisplayStringForMetabaseID(id);
  420. //_tcscpy(m_szCurrentNodeName, _T(""));
  421. TCHAR lpReturnString[50];
  422. ReturnStringForMetabaseID(id, lpReturnString);
  423. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("CMDKey::SetData[%s:%d:%s].\n"), m_szCurrentNodeName, id, lpReturnString));
  424. MD_SET_DATA_RECORD(&mdrData, id, attr, uType, dType, cbLen, (LPBYTE)pData);
  425. hRes = m_pcCom->SetData(m_hKey, pszSubString, &mdrData);
  426. if (FAILED(hRes))
  427. {
  428. // Check if it failed...
  429. // if it failed and the METADATA_SECURE flag is set, then
  430. // check if we can retry without the METADATA_SECURE flag!
  431. if ( attr & METADATA_SECURE )
  432. {
  433. if (TRUE == g_bGlobalWriteUnSecuredIfFailed_All)
  434. {
  435. iPlsDoNoEncryption = TRUE;
  436. }
  437. else
  438. {
  439. if (TRUE == DialogBoxParam((HINSTANCE) g_MyModuleHandle, MAKEINTRESOURCE(IDD_ENCRYPTED_WRITE_ERROR_DIALOG), NULL, pSecureRetryIgnoreAllDlgProc, (LPARAM)hRes))
  440. {
  441. iPlsDoNoEncryption = TRUE;
  442. }
  443. }
  444. if (TRUE == iPlsDoNoEncryption)
  445. {
  446. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetData() failed on a encrypt entry. try to write it out unencrypted.\n")));
  447. attr &= ~METADATA_SECURE;
  448. MD_SET_DATA_RECORD(&mdrData, id, attr, uType, dType, cbLen, (LPBYTE)pData);
  449. hRes = m_pcCom->SetData(m_hKey, pszSubString, &mdrData);
  450. if (FAILED(hRes))
  451. {
  452. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetData() failed on write on encrypt entry as unencrypted.\n")));
  453. }
  454. else
  455. {
  456. iisDebugOut((LOG_TYPE_TRACE, _T("CMDKey::SetData() success on write on encrypt entry as unencrypted.\n")));
  457. }
  458. // set the attr back to what it was
  459. attr &= ~METADATA_SECURE;
  460. }
  461. }
  462. }
  463. goto SetData_Exit;
  464. SetData_Exit:
  465. if (FAILED(hRes))
  466. {
  467. MyMessageBox(NULL, IDS_SETDATA_ERROR, (int) hRes, MB_OK | MB_SETFOREGROUND);
  468. }
  469. return hRes;
  470. }
  471. BOOL CMDKey::GetData(DWORD id,DWORD *pdwAttr,DWORD *pdwUType,DWORD *pdwDType,DWORD *pcbLen,LPBYTE pbData,DWORD BufSize,LPCWSTR pszSubString )
  472. {
  473. return GetData(id,pdwAttr,pdwUType,pdwDType,pcbLen,pbData,BufSize,0,0,0,pszSubString);
  474. }
  475. BOOL
  476. CMDKey::GetData(CMDValue &Value, DWORD dwId, LPCWSTR pszSubString )
  477. {
  478. DWORD dwAttr;
  479. DWORD dwUType;
  480. DWORD dwDType;
  481. DWORD cbLen = 0;
  482. BUFFER bufData;
  483. if (!GetData(dwId,&dwAttr,&dwUType,&dwDType,&cbLen,(LPBYTE) bufData.QueryPtr(),bufData.QuerySize(),0,0,0,pszSubString))
  484. {
  485. // Resize to Accomodate the big value
  486. if (!bufData.Resize(cbLen))
  487. {
  488. return FALSE;
  489. }
  490. if (!GetData(dwId,&dwAttr,&dwUType,&dwDType,&cbLen,(LPBYTE) bufData.QueryPtr(),bufData.QuerySize(),0,0,0,pszSubString))
  491. {
  492. // Even with the new size buffer we could not retrieve the value
  493. return FALSE;
  494. }
  495. }
  496. return ( Value.SetValue(dwId,dwAttr,dwUType,dwDType,cbLen,(LPVOID) bufData.QueryPtr()) );
  497. }
  498. BOOL
  499. CMDKey::SetData(CMDValue &Value, DWORD dwId, PWCHAR pszSubString )
  500. {
  501. return SUCCEEDED( SetData(dwId,
  502. Value.GetAttributes(),
  503. Value.GetUserType(),
  504. Value.GetDataType(),
  505. Value.GetDataLen(),
  506. (LPBYTE) Value.GetData(),
  507. pszSubString ) );
  508. }
  509. // Note: only use to access the AnonyName and AnonyPassword,
  510. // buffer size 256 is big enough here
  511. BOOL CMDKey::GetData(DWORD id,DWORD *pdwAttr,DWORD *pdwUType,DWORD *pdwDType,DWORD *pcbLen,LPBYTE pbData,DWORD BufSize,DWORD dwAttributes,DWORD dwUType,DWORD dwDType,LPCWSTR pszSubString )
  512. {
  513. BOOL fReturn = FALSE;
  514. HRESULT hRes = ERROR_SUCCESS;
  515. METADATA_RECORD mdrData;
  516. DWORD dwRequiredDataLen = 0;
  517. LPBYTE ReturnBuf=NULL;
  518. int ReturnBufSize;
  519. // if we are just trying to get the size of the field, just do that.
  520. if ( !pbData || (BufSize == 0) )
  521. {
  522. MD_SET_DATA_RECORD(&mdrData, id, dwAttributes, dwUType, dwDType, 0, NULL);
  523. hRes = m_pcCom->GetData(m_hKey, pszSubString, &mdrData, &dwRequiredDataLen);
  524. *pcbLen = dwRequiredDataLen;
  525. fReturn = (hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER));
  526. goto GetData_Exit;
  527. }
  528. #if defined(UNICODE) || defined(_UNICODE)
  529. ReturnBufSize = BufSize;
  530. #else
  531. ReturnBufSize = 2 * BufSize;
  532. #endif
  533. ReturnBuf = (LPBYTE)LocalAlloc(LPTR, ReturnBufSize);
  534. if (!ReturnBuf)
  535. {
  536. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::GetData() failed to allocate memory.\n")));
  537. ReturnBuf = NULL;
  538. goto GetData_Exit;
  539. }
  540. //DisplayStringForMetabaseID(id);
  541. TCHAR lpReturnString[50];
  542. ReturnStringForMetabaseID(id, lpReturnString);
  543. iisDebugOut((LOG_TYPE_TRACE, _T("CMDKey::GetData[%s:%d:%s].\n"), m_szCurrentNodeName, id, lpReturnString));
  544. MD_SET_DATA_RECORD(&mdrData, id, dwAttributes, dwUType, dwDType, ReturnBufSize, (PBYTE) ReturnBuf);
  545. hRes = m_pcCom->GetData(m_hKey, pszSubString, &mdrData, &dwRequiredDataLen);
  546. if (FAILED(hRes))
  547. {
  548. if (hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER))
  549. {
  550. #if defined(UNICODE) || defined(_UNICODE)
  551. *pcbLen = dwRequiredDataLen;
  552. #else
  553. *pcbLen = dwRequiredDataLen / 2;
  554. #endif
  555. }
  556. else
  557. {
  558. *pcbLen = 0;
  559. if ( (hRes != RETURNCODETOHRESULT(MD_ERROR_DATA_NOT_FOUND) ) &&
  560. (hRes != RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND) )
  561. )
  562. {
  563. MyMessageBox(NULL, IDS_GETDATA_ERROR, (int) hRes, MB_OK | MB_SETFOREGROUND);
  564. }
  565. }
  566. goto GetData_Exit;
  567. }
  568. // --------
  569. // We have successfully retrieved the data at this point
  570. // --------
  571. *pdwAttr = mdrData.dwMDAttributes;
  572. *pdwUType = mdrData.dwMDUserType;
  573. *pdwDType = mdrData.dwMDDataType;
  574. *pcbLen = mdrData.dwMDDataLen; // number of SBCS chars + ending \0
  575. switch (*pdwDType)
  576. {
  577. case STRING_METADATA:
  578. case EXPANDSZ_METADATA:
  579. #if defined(UNICODE) || defined(_UNICODE)
  580. memcpy(pbData, mdrData.pbMDData, *pcbLen);
  581. #else
  582. *pcbLen = (*pcbLen) / sizeof(WCHAR);
  583. WideCharToMultiByte(CP_ACP,0,(WCHAR *)(mdrData.pbMDData),-1,(LPSTR)pbData,*pcbLen, NULL, NULL);
  584. #endif
  585. fReturn = TRUE;
  586. break;
  587. case MULTISZ_METADATA:
  588. #if defined(UNICODE) || defined(_UNICODE)
  589. memcpy(pbData, mdrData.pbMDData, *pcbLen);
  590. #else
  591. *pcbLen = (*pcbLen) / sizeof(WCHAR);
  592. MyWideCharToMultiByte((WCHAR *)(mdrData.pbMDData),(LPSTR)pbData, *pcbLen, TRUE);
  593. #endif
  594. fReturn = TRUE;
  595. break;
  596. default:
  597. memcpy(pbData, mdrData.pbMDData, *pcbLen);
  598. fReturn = TRUE;
  599. break;
  600. }
  601. GetData_Exit:
  602. if(ReturnBuf) {LocalFree(ReturnBuf);}
  603. return fReturn;
  604. }
  605. HRESULT CMDKey::DeleteData(DWORD id, DWORD dType, PWCHAR pszSubString)
  606. {
  607. HRESULT hRes = ERROR_SUCCESS;
  608. TCHAR lpReturnString[50];
  609. ReturnStringForMetabaseID(id, lpReturnString);
  610. iisDebugOut((LOG_TYPE_TRACE, _T("CMDKey::DeleteData[%s:%d:%s].\n"), m_szCurrentNodeName, id, lpReturnString));
  611. hRes = m_pcCom->DeleteData(m_hKey, pszSubString, id, dType);
  612. return hRes;
  613. }
  614. HRESULT CMDKey::DeleteNode(LPCTSTR pchSubKeyPath)
  615. {
  616. HRESULT hRes = ERROR_SUCCESS;
  617. WCHAR szSubKeyPath[_MAX_PATH];
  618. if ( pchSubKeyPath && (*pchSubKeyPath) )
  619. {
  620. #if defined(UNICODE) || defined(_UNICODE)
  621. _tcscpy(szSubKeyPath, pchSubKeyPath);
  622. #else
  623. MultiByteToWideChar( CP_ACP, 0, pchSubKeyPath, -1, szSubKeyPath, _MAX_PATH );
  624. #endif
  625. iisDebugOut((LOG_TYPE_TRACE, _T("CMDKey::DeleteNode[%s:%s].\n"), m_szCurrentNodeName, szSubKeyPath));
  626. hRes = m_pcCom->DeleteKey(m_hKey, szSubKeyPath);
  627. }
  628. return hRes;
  629. }
  630. CMDKeyIter::CMDKeyIter(CMDKey &cmdKey)
  631. {
  632. m_hKey = cmdKey.GetMDKeyHandle();
  633. m_pcCom = cmdKey.GetMDKeyICOM();
  634. m_dwBuffer = _MAX_PATH;
  635. Reset();
  636. m_pBuffer = new WCHAR [m_dwBuffer];
  637. }
  638. CMDKeyIter::~CMDKeyIter()
  639. {
  640. delete [] m_pBuffer;
  641. }
  642. LONG CMDKeyIter::Next(CString *pcsName, PWCHAR pwcsSubString)
  643. {
  644. TCHAR tchData[_MAX_PATH];
  645. HRESULT hRes = ERROR_SUCCESS;
  646. hRes = m_pcCom->EnumKeys(m_hKey, pwcsSubString, m_pBuffer, m_index);
  647. if (FAILED(hRes))
  648. {
  649. return 1;
  650. }
  651. else
  652. {
  653. #if defined(UNICODE) || defined(_UNICODE)
  654. _tcscpy(tchData, m_pBuffer);
  655. #else
  656. WideCharToMultiByte(CP_ACP,0,m_pBuffer,-1,(LPSTR)tchData,_MAX_PATH, NULL, NULL);
  657. #endif
  658. *pcsName = tchData;
  659. m_index++;
  660. return 0;
  661. }
  662. }
  663. int CreateInProc(LPCTSTR lpszPath, int iUseOOPPool)
  664. {
  665. int iReturn = FALSE;
  666. TCHAR lpszKeyPath[_MAX_PATH];
  667. WCHAR wchKeyPath[_MAX_PATH];
  668. HRESULT hr = NOERROR;
  669. IWamAdmin2* pIWamAdmin = NULL;
  670. DWORD dwAppMode = eAppRunInProc;
  671. if (iUseOOPPool) {dwAppMode = eAppRunOutProcInDefaultPool;}
  672. if (lpszPath[0] == _T('/'))
  673. {
  674. _tcscpy(lpszKeyPath, lpszPath);
  675. }
  676. else
  677. {
  678. lpszKeyPath[0] = _T('/');
  679. _tcscpy(_tcsinc(lpszKeyPath), lpszPath);
  680. }
  681. if (lpszKeyPath[(_tcslen(lpszKeyPath)-1)] != _T('/')) {_tcscat(lpszKeyPath, _T("/"));}
  682. #if defined(UNICODE) || defined(_UNICODE)
  683. _tcscpy(wchKeyPath, lpszKeyPath);
  684. #else
  685. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpszKeyPath, -1, (LPWSTR)wchKeyPath, _MAX_PATH);
  686. #endif
  687. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoInitializeEx().Start.")));
  688. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  689. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoInitializeEx().End.")));
  690. if (FAILED(hr))
  691. {
  692. iisDebugOut((LOG_TYPE_ERROR, _T("CreateInProc: CoInitializeEx() failed, hr=%x\n"), hr));
  693. MesssageBoxErrors_MTS(IDS_MTS_DOING_CREATEINPROC,hr);
  694. }
  695. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoCreateInstance().Start.")));
  696. hr = CoCreateInstance(CLSID_WamAdmin,NULL,CLSCTX_SERVER,IID_IWamAdmin2,(void **)&pIWamAdmin);
  697. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoCreateInstance().End.")));
  698. if (SUCCEEDED(hr))
  699. {
  700. hr = pIWamAdmin->AppCreate2(wchKeyPath, dwAppMode);
  701. pIWamAdmin->Release();
  702. if (FAILED(hr))
  703. {
  704. iisDebugOut((LOG_TYPE_ERROR, _T("Create in-proc(type=%d) app on path %s failed, err=%x.\n"), dwAppMode, lpszKeyPath, hr));
  705. MyMessageBox(NULL, _T("CreateInProc:Error Creating Transaction Server InProc App."), hr, MB_OK | MB_SETFOREGROUND);
  706. MesssageBoxErrors_MTS(IDS_MTS_DOING_CREATEINPROC,hr);
  707. }
  708. else
  709. {
  710. iReturn = TRUE;
  711. }
  712. }
  713. else
  714. {
  715. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to CoCreateInstance of WamAdmin object. err=%x.\n"), hr));
  716. MyMessageBox(NULL, _T("CreateInProc:CoCreateInstance"), hr, MB_OK | MB_SETFOREGROUND);
  717. MesssageBoxErrors_MTS(IDS_MTS_DOING_CREATEINPROC,hr);
  718. }
  719. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().Start.")));
  720. CoUninitialize();
  721. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().End.")));
  722. return iReturn;
  723. }
  724. void CreateInProc_Wrap(LPCTSTR lpszPath, int iUseOOPPool)
  725. {
  726. BOOL bDisplayMsgOnErrFlag = TRUE;
  727. int iReturn = FALSE;
  728. int bFinishedFlag = FALSE;
  729. UINT iMsg = NULL;
  730. do
  731. {
  732. iisDebugOut((LOG_TYPE_TRACE, _T("CreateInProc_Wrap(): %s\n"), lpszPath));
  733. iReturn = CreateInProc(lpszPath, iUseOOPPool);
  734. if (iReturn == TRUE)
  735. {
  736. break;
  737. }
  738. else
  739. {
  740. if (bDisplayMsgOnErrFlag == TRUE)
  741. {
  742. iMsg = MyMessageBox( NULL, IDS_RETRY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND );
  743. switch ( iMsg )
  744. {
  745. case IDIGNORE:
  746. iReturn = TRUE;
  747. goto CreateInProc_Wrap_Exit;
  748. case IDABORT:
  749. iReturn = FALSE;
  750. goto CreateInProc_Wrap_Exit;
  751. case IDRETRY:
  752. break;
  753. default:
  754. break;
  755. }
  756. }
  757. else
  758. {
  759. // return whatever err happened
  760. goto CreateInProc_Wrap_Exit;
  761. }
  762. }
  763. } while (iReturn != TRUE);
  764. CreateInProc_Wrap_Exit:
  765. return;
  766. }
  767. void DeleteInProc(LPCTSTR lpszPath)
  768. {
  769. TCHAR lpszKeyPath[_MAX_PATH];
  770. WCHAR wchKeyPath[_MAX_PATH];
  771. HRESULT hr = NOERROR;
  772. IWamAdmin* pIWamAdmin = NULL;
  773. iisDebugOut((LOG_TYPE_TRACE, _T("DeleteInProc():Start.%s\n"), lpszPath));
  774. if (lpszPath[0] == _T('/'))
  775. {
  776. _tcscpy(lpszKeyPath, lpszPath);
  777. }
  778. else
  779. {
  780. lpszKeyPath[0] = _T('/');
  781. _tcscpy(_tcsinc(lpszKeyPath), lpszPath);
  782. }
  783. #if defined(UNICODE) || defined(_UNICODE)
  784. _tcscpy(wchKeyPath, lpszKeyPath);
  785. #else
  786. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpszKeyPath, -1, (LPWSTR)wchKeyPath, _MAX_PATH);
  787. #endif
  788. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoInitializeEx().Start.")));
  789. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  790. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoInitializeEx().End.")));
  791. if (FAILED(hr))
  792. {
  793. iisDebugOut((LOG_TYPE_ERROR, _T("DeleteInProc: CoInitializeEx() failed, hr=%x\n"), hr));
  794. }
  795. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoCreateInstance().Start.")));
  796. hr = CoCreateInstance(CLSID_WamAdmin,NULL,CLSCTX_SERVER,IID_IWamAdmin,(void **)&pIWamAdmin);
  797. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoCreateInstance().End.")));
  798. if (SUCCEEDED(hr))
  799. {
  800. iisDebugOut((LOG_TYPE_TRACE, _T("DeleteInProc():Calling AppDelete now.%s\n"), lpszKeyPath));
  801. hr = pIWamAdmin->AppDelete(wchKeyPath, TRUE);
  802. pIWamAdmin->Release();
  803. if (FAILED(hr))
  804. {
  805. iisDebugOut((LOG_TYPE_ERROR, _T("Delete in-proc app on path %s failed, err=%x.\n"), lpszKeyPath, hr));
  806. }
  807. }
  808. else
  809. {
  810. iisDebugOut((LOG_TYPE_ERROR, _T("DeleteInProc:CoCreateInstance() failed. err=%x.\n"), hr));
  811. }
  812. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().Start.")));
  813. CoUninitialize();
  814. //iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ole32:CoUninitialize().End.")));
  815. iisDebugOut_End1(_T("DeleteInProc"),(LPTSTR) lpszPath,LOG_TYPE_TRACE);
  816. return;
  817. }
  818. INT_PTR CALLBACK pSecureRetryIgnoreAllDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  819. {
  820. HWND hTextWording = NULL;
  821. CString csErrMsg;
  822. HRESULT hErrorCode;
  823. TCHAR pMsg[_MAX_PATH] = _T("");
  824. HRESULT nNetErr;
  825. DWORD dwFormatReturn = 0;
  826. switch (msg)
  827. {
  828. case WM_INITDIALOG:
  829. uiCenterDialog(hDlg);
  830. hTextWording = GetDlgItem(hDlg, IDC_STATIC2);
  831. hErrorCode = (HRESULT) lParam;
  832. nNetErr = (HRESULT) hErrorCode;
  833. dwFormatReturn = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,NULL, hErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),pMsg, _MAX_PATH, NULL);
  834. if ( dwFormatReturn == 0)
  835. {
  836. if (nNetErr >= NERR_BASE)
  837. {
  838. HMODULE hDll = (HMODULE)LoadLibrary(_T("netmsg.dll"));
  839. if (hDll)
  840. {
  841. dwFormatReturn = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE,hDll, hErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),pMsg, _MAX_PATH, NULL);
  842. FreeLibrary(hDll);
  843. }
  844. }
  845. }
  846. if (dwFormatReturn) {csErrMsg.Format(_T("0x%x=%s"), hErrorCode, pMsg);}
  847. else{csErrMsg.Format(_T("%s\n\nErrorCode=0x%x."), hErrorCode);}
  848. SetWindowText(hTextWording, csErrMsg);
  849. UpdateWindow(hDlg);
  850. break;
  851. case WM_COMMAND:
  852. switch (wParam)
  853. {
  854. case IDCANCEL:
  855. EndDialog(hDlg, (int)wParam);
  856. return FALSE;
  857. case IDRETRY:
  858. EndDialog(hDlg, (int)wParam);
  859. return FALSE;
  860. break;
  861. case IDWRITEUNENCRYPTED:
  862. EndDialog(hDlg, (int)wParam);
  863. return TRUE;
  864. break;
  865. case IDWRITEUNENCRYPTEDALL:
  866. g_bGlobalWriteUnSecuredIfFailed_All = TRUE;
  867. EndDialog(hDlg, (int)wParam);
  868. return TRUE;
  869. break;
  870. }
  871. break;
  872. }
  873. return FALSE;
  874. }
  875. //-----------------------------------------------------------------------------
  876. // get a multi-sz data block and immediately parse it into a CStringList
  877. HRESULT CMDKey::GetMultiSzAsStringList (
  878. DWORD dwMDIdentifier,
  879. DWORD *uType,
  880. DWORD *attributes,
  881. CStringList& szStrList,
  882. LPCWSTR pszSubString OPTIONAL )
  883. {
  884. HRESULT hRes = ERROR_SUCCESS;
  885. METADATA_RECORD mdrData;
  886. // make sure the key is open
  887. if ( NULL == m_hKey )
  888. {
  889. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: GetMultiSzAsStringList on unopened node.%s\n"), _T("")));
  890. return -1;
  891. }
  892. // get the paths. The loop accounts for a buffer that is too small...
  893. DWORD dwMDBufferSize = 1024;
  894. PWCHAR pwchBuffer = NULL;
  895. do
  896. {
  897. if ( pwchBuffer )
  898. {
  899. delete pwchBuffer;
  900. pwchBuffer = NULL;
  901. }
  902. pwchBuffer = new WCHAR[dwMDBufferSize];
  903. if (pwchBuffer == NULL)
  904. {
  905. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  906. }
  907. // prepare the metadata parameter block
  908. MD_SET_DATA_RECORD(&mdrData, dwMDIdentifier, *attributes,
  909. *uType, MULTISZ_METADATA, dwMDBufferSize, pwchBuffer);
  910. // make the call to get the data
  911. // If the buffer is too small, the correct size will be put into dwMDBufferSize
  912. hRes = m_pcCom->GetData(
  913. m_hKey,
  914. pszSubString,
  915. &mdrData,
  916. &dwMDBufferSize
  917. );
  918. // Set the attributes return.
  919. *attributes = mdrData.dwMDAttributes;
  920. *uType = mdrData.dwMDUserType;
  921. }
  922. while( HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER);
  923. // if there were any failures, go to the cleanup code now...
  924. if ( SUCCEEDED(hRes) )
  925. {
  926. // at this point, we have the data we want. Time to convert it into a CString list.
  927. if (pwchBuffer)
  928. {
  929. // to make prefix stop yelling at me
  930. if (pwchBuffer[0])
  931. {
  932. ConvertWDoubleNullListToStringList(pwchBuffer, szStrList);
  933. }
  934. }
  935. }
  936. // clean up
  937. if ( pwchBuffer )
  938. delete pwchBuffer;
  939. if ( FAILED(hRes) )
  940. {
  941. if (hRes != MD_ERROR_DATA_NOT_FOUND)
  942. {
  943. iisDebugOut((LOG_TYPE_WARN, _T("CMDKey::GetMultiSzAsStringList() failed. err=%x.\n"), hRes));
  944. }
  945. }
  946. return hRes;
  947. }
  948. //-----------------------------------------------------------------------------
  949. // take a CStringList and set it into metadata as a multi-sz
  950. HRESULT CMDKey::SetMultiSzAsStringList (
  951. DWORD dwMDIdentifier,
  952. DWORD uType,
  953. DWORD attributes,
  954. CStringList& szStrList,
  955. PWCHAR pszSubString OPTIONAL )
  956. {
  957. HRESULT hRes = ERROR_SUCCESS;
  958. METADATA_RECORD mdrData;
  959. // make sure the key is open
  960. if ( NULL == m_hKey )
  961. {
  962. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: SetMultiSzAsStringList on unopened node.%s\n"), _T("")));
  963. return -1;
  964. }
  965. DWORD dwMDBufferSize = 0;
  966. PWCHAR pwchBuffer = NULL;
  967. // convert the cstringlist into a wide multisz data block.
  968. hRes = ConvertStringListToWDoubleNullList(
  969. szStrList,
  970. dwMDBufferSize,
  971. pwchBuffer
  972. );
  973. if ( FAILED(hRes) )
  974. {
  975. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: SetMultiSzAsStringList Convert to null list.%x\n"), hRes));
  976. return hRes;
  977. }
  978. // the buffer is expressed in wide characters. Change it to bytes...
  979. dwMDBufferSize *= sizeof(WCHAR);
  980. // prepare the metadata parameter block
  981. MD_SET_DATA_RECORD(&mdrData, dwMDIdentifier, attributes,
  982. uType, MULTISZ_METADATA, dwMDBufferSize, pwchBuffer);
  983. // make the call to get the data
  984. hRes = m_pcCom->SetData(
  985. m_hKey,
  986. pszSubString,
  987. &mdrData
  988. );
  989. // clean up
  990. FreeMem( pwchBuffer );
  991. if ( FAILED(hRes) )
  992. {
  993. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetMultiSzAsStringList()-SetData failed. err=%x.\n"), hRes));
  994. }
  995. return hRes;
  996. }
  997. //-----------------------------------------------------------------------------
  998. // get all the sub keys that have a certain property on them and return the
  999. // sub-paths in a cstring list object. The cstring list should be instantiated
  1000. // by the caller and deleted by the same.
  1001. HRESULT CMDKey::GetDataPaths(
  1002. DWORD dwMDIdentifier,
  1003. DWORD dwMDDataType,
  1004. CStringList& szPathList,
  1005. PWCHAR pszSubString )
  1006. {
  1007. HRESULT hRes = ERROR_SUCCESS;
  1008. // make sure the key is open
  1009. if ( NULL == m_hKey )
  1010. {
  1011. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: GetDataPaths on unopened node.%s\n"), _T("")));
  1012. return -1;
  1013. }
  1014. // get the paths. The loop accounts for a buffer that is too small...
  1015. DWORD dwMDBufferSize = 512;
  1016. PWCHAR pwchBuffer = NULL;
  1017. do
  1018. {
  1019. if ( pwchBuffer )
  1020. {
  1021. delete pwchBuffer;
  1022. pwchBuffer = NULL;
  1023. }
  1024. pwchBuffer = new WCHAR[dwMDBufferSize];
  1025. if (pwchBuffer == NULL)
  1026. {
  1027. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1028. }
  1029. // If the buffer is too small, the correct size will be put into dwMDBufferSize
  1030. hRes = m_pcCom->GetDataPaths(
  1031. m_hKey,
  1032. pszSubString,
  1033. dwMDIdentifier,
  1034. dwMDDataType,
  1035. dwMDBufferSize,
  1036. pwchBuffer,
  1037. &dwMDBufferSize
  1038. );
  1039. }
  1040. while( HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER);
  1041. // if there were any failures, go to the cleanup code now...
  1042. if ( SUCCEEDED(hRes) )
  1043. {
  1044. // at this point, we have the data we want. Time to convert it into a CString list.
  1045. ConvertWDoubleNullListToStringList(pwchBuffer, szPathList);
  1046. }
  1047. // clean up
  1048. if ( pwchBuffer )
  1049. delete pwchBuffer;
  1050. if ( FAILED(hRes) )
  1051. {
  1052. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::GetDataPaths() failed. err=%x.\n"), hRes));
  1053. }
  1054. return hRes;
  1055. }
  1056. //-----------------------------------------------------------------------------
  1057. // get a multi-sz data block and immediately parse it into a CStringList
  1058. HRESULT CMDKey::GetStringAsCString (
  1059. DWORD dwMDIdentifier,
  1060. DWORD uType,
  1061. DWORD attributes,
  1062. CString& szStr,
  1063. PWCHAR pszSubString OPTIONAL,
  1064. int iStringType OPTIONAL)
  1065. {
  1066. HRESULT hRes = ERROR_SUCCESS;
  1067. METADATA_RECORD mdrData;
  1068. // make sure the key is open
  1069. if ( NULL == m_hKey )
  1070. {
  1071. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: GetStringAsCString on unopened node.%s\n"), _T("")));
  1072. return -1;
  1073. }
  1074. // get the string. The loop accounts for a buffer that is too small...
  1075. DWORD dwMDBufferSize = 255;
  1076. PWCHAR pwchBuffer = NULL;
  1077. do
  1078. {
  1079. if ( pwchBuffer )
  1080. {
  1081. delete pwchBuffer;
  1082. pwchBuffer = NULL;
  1083. }
  1084. pwchBuffer = new WCHAR[dwMDBufferSize + 1];
  1085. ZeroMemory( pwchBuffer, (dwMDBufferSize + 1) * sizeof(WCHAR) );
  1086. if (pwchBuffer == NULL)
  1087. {
  1088. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1089. }
  1090. // prepare the metadata parameter block
  1091. MD_SET_DATA_RECORD(&mdrData, dwMDIdentifier, attributes,
  1092. uType, STRING_METADATA, dwMDBufferSize, pwchBuffer);
  1093. // make the call to get the data
  1094. // If the buffer is too small, the correct size will be put into dwMDBufferSize
  1095. hRes = m_pcCom->GetData(
  1096. m_hKey,
  1097. pszSubString,
  1098. &mdrData,
  1099. &dwMDBufferSize
  1100. );
  1101. }
  1102. while( HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER);
  1103. // if there were any failures, go to the cleanup code now...
  1104. if ( SUCCEEDED(hRes) )
  1105. {
  1106. // at this point, we have the data we want. Time to convert it into a CString.
  1107. szStr = pwchBuffer;
  1108. }
  1109. // clean up
  1110. if ( pwchBuffer )
  1111. delete pwchBuffer;
  1112. if ( FAILED(hRes) && !MD_ERROR_DATA_NOT_FOUND)
  1113. {
  1114. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::GetStringAsCString() failed. err=%x.\n"), hRes));
  1115. }
  1116. return hRes;
  1117. }
  1118. //-----------------------------------------------------------------------------
  1119. // take a CStringList and set it into metadata as a multi-sz
  1120. HRESULT CMDKey::SetCStringAsString (
  1121. DWORD dwMDIdentifier,
  1122. DWORD uType,
  1123. DWORD attributes,
  1124. CString& szStr,
  1125. PWCHAR pszSubString OPTIONAL,
  1126. int iStringType OPTIONAL)
  1127. {
  1128. HRESULT hRes = ERROR_SUCCESS;
  1129. METADATA_RECORD mdrData;
  1130. // make sure the key is open
  1131. if ( NULL == m_hKey )
  1132. {
  1133. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: SetCStringAsString on unopened node.%s\n"), _T("")));
  1134. return -1;
  1135. }
  1136. DWORD dwMDBufferSize = 0;
  1137. PWCHAR pwchBuffer = NULL;
  1138. // convert the cstring into a wide string data block.
  1139. pwchBuffer = AllocWideString( (LPCTSTR)szStr );
  1140. // Calculate the size of the buffer in bytes, not wide characters....
  1141. dwMDBufferSize = (szStr.GetLength() + 1) * sizeof(WCHAR);
  1142. // prepare the metadata parameter block
  1143. MD_SET_DATA_RECORD(&mdrData, dwMDIdentifier, attributes,
  1144. uType, STRING_METADATA, dwMDBufferSize, pwchBuffer);
  1145. // make the call to get the data
  1146. hRes = m_pcCom->SetData(
  1147. m_hKey,
  1148. pszSubString,
  1149. &mdrData
  1150. );
  1151. // clean up
  1152. FreeMem( pwchBuffer );
  1153. if ( FAILED(hRes) )
  1154. {
  1155. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::SetCStringAsString()-SetData failed. err=%x.\n"), hRes));
  1156. }
  1157. return hRes;
  1158. }
  1159. HRESULT CMDKey::GetDword(
  1160. DWORD dwMDIdentifier,
  1161. DWORD uType,
  1162. DWORD attributes,
  1163. DWORD& MyDword,
  1164. PWCHAR pszSubString OPTIONAL
  1165. )
  1166. {
  1167. HRESULT hRes = ERROR_SUCCESS;
  1168. METADATA_RECORD mdrData;
  1169. DWORD dwMDBufferSize = 255;
  1170. LPBYTE Buffer = NULL;
  1171. // make sure the key is open
  1172. if ( NULL == m_hKey )
  1173. {
  1174. iisDebugOut((LOG_TYPE_ERROR, _T("FAILED: GetDword on unopened node.\n")));
  1175. return -1;
  1176. }
  1177. // get the data. The loop accounts for a buffer that is too small...
  1178. do
  1179. {
  1180. if ( Buffer )
  1181. {
  1182. delete Buffer;
  1183. Buffer = NULL;
  1184. }
  1185. Buffer = (LPBYTE)LocalAlloc(LPTR, dwMDBufferSize);
  1186. if (Buffer == NULL)
  1187. {
  1188. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1189. }
  1190. // prepare the metadata parameter block
  1191. MD_SET_DATA_RECORD(&mdrData, dwMDIdentifier, attributes, uType, DWORD_METADATA, dwMDBufferSize, Buffer);
  1192. // make the call to get the data
  1193. // If the buffer is too small, the correct size will be put into dwMDBufferSize
  1194. hRes = m_pcCom->GetData(m_hKey,pszSubString,&mdrData,&dwMDBufferSize);
  1195. }
  1196. while( HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER);
  1197. // if there were any failures, go to the cleanup code now...
  1198. if ( SUCCEEDED(hRes) )
  1199. {
  1200. // at this point, we have the data we want. Time to convert it into a dword.
  1201. MyDword = (DWORD) *mdrData.pbMDData;
  1202. }
  1203. // clean up
  1204. if ( Buffer )
  1205. LocalFree(Buffer);
  1206. if ( FAILED(hRes) && !MD_ERROR_DATA_NOT_FOUND)
  1207. {
  1208. iisDebugOut((LOG_TYPE_ERROR, _T("CMDKey::GetDword() failed. err=%x.\n"), hRes));
  1209. }
  1210. return hRes;
  1211. }
  1212. HRESULT CMDKey::RenameNode(LPCTSTR pszMDPath,LPCTSTR pszMDNewName)
  1213. {
  1214. HRESULT hRes = ERROR_SUCCESS;
  1215. if (m_pcCom)
  1216. {
  1217. WCHAR wszPath1[_MAX_PATH];
  1218. WCHAR wszPath2[_MAX_PATH];
  1219. #if defined(UNICODE) || defined(_UNICODE)
  1220. _tcscpy(wszPath1, pszMDPath);
  1221. _tcscpy(wszPath2, pszMDNewName);
  1222. #else
  1223. MultiByteToWideChar( CP_ACP, 0, pszMDPath, -1, wszPath1, _MAX_PATH);
  1224. MultiByteToWideChar( CP_ACP, 0, pszMDNewName, -1, wszPath2, _MAX_PATH);
  1225. #endif
  1226. hRes = m_pcCom->RenameKey(m_hKey,wszPath1,wszPath2);
  1227. if ( FAILED(hRes) && !MD_ERROR_DATA_NOT_FOUND)
  1228. {
  1229. iisDebugOut((LOG_TYPE_WARN, _T("CMDKey::RenameNode(%s,%s) failed. err=%x.\n"), pszMDPath,pszMDNewName,hRes));
  1230. }
  1231. }
  1232. return hRes;
  1233. };
  1234. // function: CreateABO
  1235. //
  1236. // Create an ABO object to use. If this is called and succeeds,
  1237. // you must call CloseABO
  1238. //
  1239. HRESULT
  1240. CMDKey::CreateABO( IMSAdminBase **ppcABO )
  1241. {
  1242. HRESULT hRes = ERROR_SUCCESS;
  1243. IClassFactory *pcsfFactory = NULL;
  1244. hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1245. if ( FAILED(hRes) )
  1246. {
  1247. return hRes;
  1248. }
  1249. hRes = CoGetClassObject(GETAdminBaseCLSID(TRUE), CLSCTX_SERVER, NULL, IID_IClassFactory, (void**) &pcsfFactory);
  1250. if ( SUCCEEDED(hRes) )
  1251. {
  1252. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **) ppcABO );
  1253. pcsfFactory->Release();
  1254. }
  1255. if ( FAILED( hRes ) )
  1256. {
  1257. CoUninitialize();
  1258. }
  1259. return hRes;
  1260. }
  1261. // function: CloseABO
  1262. //
  1263. // Close the ABO object
  1264. //
  1265. void
  1266. CMDKey::CloseABO( IMSAdminBase *pcABO )
  1267. {
  1268. ASSERT( pcABO != NULL );
  1269. pcABO->Release();
  1270. CoUninitialize();
  1271. }
  1272. // Backup
  1273. //
  1274. // Backup the metabase without a password
  1275. //
  1276. BOOL
  1277. CMDKey::Backup( LPWSTR szBackupName,
  1278. DWORD dwVersion,
  1279. DWORD dwFlags )
  1280. {
  1281. BOOL bRet = FALSE;
  1282. IMSAdminBase *pcABO;
  1283. if ( FAILED( CreateABO( &pcABO ) ) )
  1284. {
  1285. // Failed to create ABO
  1286. return FALSE;
  1287. }
  1288. bRet = SUCCEEDED( pcABO->Backup( szBackupName, dwVersion, dwFlags ) );
  1289. CloseABO( pcABO );
  1290. return bRet;
  1291. }
  1292. // DeleteBackup
  1293. //
  1294. // Delete a backup
  1295. //
  1296. BOOL
  1297. CMDKey::DeleteBackup( LPWSTR szBackupName,
  1298. DWORD dwVersion /* = MD_BACKUP_HIGHEST_VERSION */ )
  1299. {
  1300. BOOL bRet = FALSE;
  1301. IMSAdminBase *pcABO;
  1302. if ( FAILED( CreateABO( &pcABO ) ) )
  1303. {
  1304. // Failed to create ABO
  1305. return FALSE;
  1306. }
  1307. bRet = SUCCEEDED( pcABO->DeleteBackup( szBackupName, dwVersion ) );
  1308. CloseABO( pcABO );
  1309. return bRet;
  1310. }
  1311. CMDValue::CMDValue()
  1312. :
  1313. m_dwId(0),
  1314. m_dwAttributes(0),
  1315. m_dwUserType(0),
  1316. m_dwDataType(0),
  1317. m_cbDataLen(0)
  1318. {
  1319. }
  1320. CMDValue::~CMDValue()
  1321. {
  1322. }
  1323. // function: CMDValue::SetValue
  1324. //
  1325. // Set the value of the class to what the pointer points to
  1326. //
  1327. DWORD
  1328. CMDValue::SetValue(DWORD dwId,
  1329. DWORD dwAttributes,
  1330. DWORD dwUserType,
  1331. DWORD dwDataType,
  1332. DWORD cbDataLen,
  1333. LPVOID pbData)
  1334. {
  1335. if ( cbDataLen > m_bufData.QuerySize() )
  1336. {
  1337. if (!m_bufData.Resize(cbDataLen))
  1338. {
  1339. // Failed to Resize Data
  1340. return FALSE;
  1341. }
  1342. }
  1343. memcpy( m_bufData.QueryPtr(), pbData, cbDataLen );
  1344. m_dwId = dwId;
  1345. m_dwAttributes = dwAttributes;
  1346. m_dwUserType = dwUserType;
  1347. m_dwDataType = dwDataType;
  1348. m_cbDataLen = cbDataLen;
  1349. return TRUE;
  1350. }
  1351. // function: CMDValue::SetValue
  1352. //
  1353. // Set the value of the class the value of the string. So if
  1354. // dwDataType is DWORD, we must first convert to DWORD before
  1355. // Setting the value
  1356. //
  1357. DWORD
  1358. CMDValue::SetValue(DWORD dwId,
  1359. DWORD dwAttributes,
  1360. DWORD dwUserType,
  1361. DWORD dwDataType,
  1362. DWORD cbDataLen,
  1363. LPTSTR szDataString)
  1364. {
  1365. if (dwDataType == DWORD_METADATA)
  1366. {
  1367. DWORD dwValue;
  1368. dwValue = _ttoi(szDataString);
  1369. return SetValue(dwId, dwAttributes, dwUserType, dwDataType, sizeof(DWORD), (LPVOID) &dwValue);
  1370. }
  1371. return SetValue(dwId, dwAttributes, dwUserType, dwDataType, cbDataLen, (LPVOID) szDataString);
  1372. }
  1373. // function: SetValue
  1374. //
  1375. // Set the value to a DWORD
  1376. //
  1377. DWORD
  1378. CMDValue::SetValue(DWORD dwId,
  1379. DWORD dwAttributes,
  1380. DWORD dwUserType,
  1381. DWORD dwValue)
  1382. {
  1383. return SetValue( dwId,
  1384. dwAttributes,
  1385. dwUserType,
  1386. DWORD_METADATA, // Data Type
  1387. sizeof( DWORD ), // Size
  1388. (LPVOID) &dwValue ); // Data
  1389. }
  1390. BOOL
  1391. CMDValue::IsEqual(DWORD dwDataType, DWORD cbDataLen, LPVOID pbData)
  1392. {
  1393. if ( (dwDataType != m_dwDataType) ||
  1394. ( cbDataLen != m_cbDataLen )
  1395. )
  1396. {
  1397. return FALSE;
  1398. }
  1399. return ( memcmp(pbData,m_bufData.QueryPtr(),cbDataLen) == 0 );
  1400. }
  1401. BOOL
  1402. CMDValue::IsEqual(DWORD dwDataType, DWORD cbDataLen, DWORD dwData)
  1403. {
  1404. return IsEqual(dwDataType,cbDataLen,(LPVOID) &dwData);
  1405. }
  1406. // function: AddNode
  1407. //
  1408. // Add a node in the metabase
  1409. //
  1410. HRESULT
  1411. CMDKey::AddNode( LPWSTR szNodeName )
  1412. {
  1413. return m_pcCom->AddKey( m_hKey, szNodeName );
  1414. }