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.

3075 lines
94 KiB

  1. #include <stdio.h>
  2. #define INITGUID // must be before iadmw.h
  3. #include <iadmw.h> // Interface header
  4. //#include <iiscnfg.h> // MD_ & IIS_MD_ defines
  5. #include <iiscnfgp.h> // MD_ & IIS_MD_ defines
  6. #define REASONABLE_TIMEOUT 1000
  7. #define MD_ISAPI_RESTRICTION_LIST (IIS_MD_HTTP_BASE+163)
  8. #define MD_CGI_RESTRICTION_LIST (IIS_MD_HTTP_BASE+164)
  9. #define MD_RESTRICTION_LIST_CUSTOM_DESC (IIS_MD_HTTP_BASE+165)
  10. void ShowHelp(void);
  11. LPSTR StripWhitespace(LPSTR pszString);
  12. BOOL OpenMetabaseAndDoStuff(WCHAR * wszVDir, WCHAR * wszDir, int iTrans);
  13. BOOL GetVdirPhysicalPath(IMSAdminBase *pIMSAdminBase,WCHAR * wszVDir,WCHAR *wszStringPathToFill);
  14. BOOL AddVirtualDir(IMSAdminBase *pIMSAdminBase, WCHAR * wszVDir, WCHAR * wszDir);
  15. BOOL RemoveVirtualDir(IMSAdminBase *pIMSAdminBase, WCHAR * wszVDir);
  16. HRESULT LoadAllData(IMSAdminBase * pmb, METADATA_HANDLE hMetabase,WCHAR *subdir, BYTE **buf, DWORD *size,DWORD *count);
  17. HRESULT AddVirtualServer(UINT iServerNum, UINT iServerPort, WCHAR * wszDefaultVDirDir);
  18. HRESULT DelVirtualServer(UINT iServerNum);
  19. HRESULT AddRemoveIISRestrictionListEntry(WCHAR * wszFilePath,BOOL bBinaryIsISAPI,BOOL bEnableThisBinary);
  20. HRESULT AddRemoveIISCustomDescriptionEntry(WCHAR * wszFilePathInput,WCHAR * wszDescription,BOOL bCannotBeRemovedByUser, BOOL bAddToList);
  21. BOOL OpenMetabaseAndDoExport(void);
  22. BOOL OpenMetabaseAndDoImport(void);
  23. BOOL OpenMetabaseAndGetVersion(void);
  24. HRESULT RemoteOpenMetabaseAndCallExport(
  25. const WCHAR *pcszMachineName,
  26. const WCHAR *pcszUserName,
  27. const WCHAR *pcszDomain,
  28. const WCHAR *pcszPassword
  29. );
  30. inline HRESULT SetBlanket(LPUNKNOWN pIUnk)
  31. {
  32. return CoSetProxyBlanket( pIUnk,
  33. RPC_C_AUTHN_WINNT, // NTLM authentication service
  34. RPC_C_AUTHZ_NONE, // default authorization service...
  35. NULL, // no mutual authentication
  36. RPC_C_AUTHN_LEVEL_CONNECT, // authentication level
  37. RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
  38. NULL, // use current token
  39. EOAC_NONE ); // no special capabilities
  40. }
  41. #define TRANS_ADD 0
  42. #define TRANS_DEL 1
  43. #define TRANS_PRINT_PATH 2
  44. #define TRANS_ADD_VIRTUAL_SERVER 4
  45. #define TRANS_DEL_VIRTUAL_SERVER 8
  46. #define TRANS_ADD_ISAPI_RESTRICT 16
  47. #define TRANS_DEL_ISAPI_RESTRICT 32
  48. #define TRANS_ADD_CGI_RESTRICT 64
  49. #define TRANS_DEL_CGI_RESTRICT 128
  50. #define TRANS_ADD_CUSTOM_DESCRIPTION 256
  51. #define TRANS_DEL_CUSTOM_DESCRIPTION 512
  52. #define TRANS_EXPORT_CONFIG 1024
  53. #define TRANS_GET_VERSION 2048
  54. int __cdecl main(int argc,char *argv[])
  55. {
  56. BOOL fRet = FALSE;
  57. int argno;
  58. char * pArg = NULL;
  59. char * pCmdStart = NULL;
  60. WCHAR wszPrintString[MAX_PATH];
  61. char szTempString[MAX_PATH];
  62. int iGotParamC = FALSE;
  63. int iGotParamI = FALSE;
  64. int iGotParamS = FALSE;
  65. int iGotParamL = FALSE;
  66. int iGotParamM = FALSE;
  67. int iGotParamN = FALSE;
  68. int iGotParamP = FALSE;
  69. int iGotParamV = FALSE;
  70. int iDoDelete = FALSE;
  71. int iDoWebPath = FALSE;
  72. int iDoExport = FALSE;
  73. int iDoImport = FALSE;
  74. int iDoVersion = FALSE;
  75. int iTrans = 0;
  76. WCHAR wszDirPath[MAX_PATH];
  77. WCHAR wszVDirName[MAX_PATH];
  78. WCHAR wszTempString_C[MAX_PATH];
  79. WCHAR wszTempString_I[MAX_PATH];
  80. WCHAR wszTempString_S[MAX_PATH];
  81. WCHAR wszTempString_L[MAX_PATH];
  82. WCHAR wszTempString_M[MAX_PATH];
  83. WCHAR wszTempString_N[MAX_PATH];
  84. WCHAR wszTempString_P[MAX_PATH];
  85. wszDirPath[0] = '\0';
  86. wszVDirName[0] = '\0';
  87. wszTempString_C[0] = '\0';
  88. wszTempString_I[0] = '\0';
  89. wszTempString_S[0] = '\0';
  90. wszTempString_L[0] = '\0';
  91. wszTempString_M[0] = '\0';
  92. wszTempString_N[0] = '\0';
  93. wszTempString_P[0] = '\0';
  94. for(argno=1; argno<argc; argno++)
  95. {
  96. if ( argv[argno][0] == '-' || argv[argno][0] == '/' )
  97. {
  98. switch (argv[argno][1])
  99. {
  100. case 'd':
  101. case 'D':
  102. iDoDelete = TRUE;
  103. break;
  104. case 'o':
  105. case 'O':
  106. iDoWebPath = TRUE;
  107. break;
  108. case 'x':
  109. case 'X':
  110. iDoExport = TRUE;
  111. break;
  112. case 'y':
  113. case 'Y':
  114. iDoImport = TRUE;
  115. break;
  116. case 'z':
  117. case 'Z':
  118. iDoVersion = TRUE;
  119. break;
  120. case 'c':
  121. case 'C':
  122. // Get the string for this flag
  123. pArg = CharNextA(argv[argno]);
  124. pArg = CharNextA(pArg);
  125. if (*pArg == ':')
  126. {
  127. pArg = CharNextA(pArg);
  128. // Check if it's quoted
  129. if (*pArg == '\"')
  130. {
  131. pArg = CharNextA(pArg);
  132. pCmdStart = pArg;
  133. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  134. }
  135. else
  136. {
  137. pCmdStart = pArg;
  138. while (*pArg){pArg = CharNextA(pArg);}
  139. }
  140. *pArg = '\0';
  141. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  142. // Convert to unicode
  143. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_C, 50);
  144. iGotParamC = TRUE;
  145. }
  146. break;
  147. case 'i':
  148. case 'I':
  149. // Get the string for this flag
  150. pArg = CharNextA(argv[argno]);
  151. pArg = CharNextA(pArg);
  152. if (*pArg == ':')
  153. {
  154. pArg = CharNextA(pArg);
  155. // Check if it's quoted
  156. if (*pArg == '\"')
  157. {
  158. pArg = CharNextA(pArg);
  159. pCmdStart = pArg;
  160. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  161. }
  162. else
  163. {
  164. pCmdStart = pArg;
  165. while (*pArg){pArg = CharNextA(pArg);}
  166. }
  167. *pArg = '\0';
  168. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  169. // Convert to unicode
  170. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_I, 50);
  171. iGotParamI = TRUE;
  172. }
  173. break;
  174. case 's':
  175. case 'S':
  176. // Get the string for this flag
  177. pArg = CharNextA(argv[argno]);
  178. pArg = CharNextA(pArg);
  179. if (*pArg == ':')
  180. {
  181. pArg = CharNextA(pArg);
  182. // Check if it's quoted
  183. if (*pArg == '\"')
  184. {
  185. pArg = CharNextA(pArg);
  186. pCmdStart = pArg;
  187. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  188. }
  189. else
  190. {
  191. pCmdStart = pArg;
  192. while (*pArg){pArg = CharNextA(pArg);}
  193. }
  194. *pArg = '\0';
  195. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  196. // Convert to unicode
  197. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_S, 50);
  198. iGotParamS = TRUE;
  199. }
  200. break;
  201. case 'm':
  202. case 'M':
  203. // Get the string for this flag
  204. pArg = CharNextA(argv[argno]);
  205. pArg = CharNextA(pArg);
  206. if (*pArg == ':')
  207. {
  208. pArg = CharNextA(pArg);
  209. // Check if it's quoted
  210. if (*pArg == '\"')
  211. {
  212. pArg = CharNextA(pArg);
  213. pCmdStart = pArg;
  214. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  215. }
  216. else
  217. {
  218. pCmdStart = pArg;
  219. while (*pArg){pArg = CharNextA(pArg);}
  220. }
  221. *pArg = '\0';
  222. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  223. // Convert to unicode
  224. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_M, _MAX_PATH);
  225. iGotParamM = TRUE;
  226. }
  227. break;
  228. case 'n':
  229. case 'N':
  230. // Get the string for this flag
  231. pArg = CharNextA(argv[argno]);
  232. pArg = CharNextA(pArg);
  233. if (*pArg == ':')
  234. {
  235. pArg = CharNextA(pArg);
  236. // Check if it's quoted
  237. if (*pArg == '\"')
  238. {
  239. pArg = CharNextA(pArg);
  240. pCmdStart = pArg;
  241. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  242. }
  243. else
  244. {
  245. pCmdStart = pArg;
  246. while (*pArg){pArg = CharNextA(pArg);}
  247. }
  248. *pArg = '\0';
  249. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  250. // Convert to unicode
  251. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_N, 50);
  252. iGotParamN = TRUE;
  253. }
  254. break;
  255. case 'l':
  256. case 'L':
  257. // Get the string for this flag
  258. pArg = CharNextA(argv[argno]);
  259. pArg = CharNextA(pArg);
  260. if (*pArg == ':')
  261. {
  262. pArg = CharNextA(pArg);
  263. // Check if it's quoted
  264. if (*pArg == '\"')
  265. {
  266. pArg = CharNextA(pArg);
  267. pCmdStart = pArg;
  268. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  269. }
  270. else
  271. {
  272. pCmdStart = pArg;
  273. while (*pArg){pArg = CharNextA(pArg);}
  274. }
  275. *pArg = '\0';
  276. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  277. // Convert to unicode
  278. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_L, 50);
  279. iGotParamL = TRUE;
  280. }
  281. break;
  282. case 'p':
  283. case 'P':
  284. // Get the string for this flag
  285. pArg = CharNextA(argv[argno]);
  286. pArg = CharNextA(pArg);
  287. if (*pArg == ':')
  288. {
  289. pArg = CharNextA(pArg);
  290. // Check if it's quoted
  291. if (*pArg == '\"')
  292. {
  293. pArg = CharNextA(pArg);
  294. pCmdStart = pArg;
  295. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  296. }
  297. else
  298. {
  299. pCmdStart = pArg;
  300. while (*pArg){pArg = CharNextA(pArg);}
  301. }
  302. *pArg = '\0';
  303. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  304. // Convert to unicode
  305. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszTempString_P, 50);
  306. iGotParamP = TRUE;
  307. }
  308. break;
  309. case 'v':
  310. case 'V':
  311. // Get the string for this flag
  312. pArg = CharNextA(argv[argno]);
  313. pArg = CharNextA(pArg);
  314. if (*pArg == ':')
  315. {
  316. pArg = CharNextA(pArg);
  317. // Check if it's quoted
  318. if (*pArg == '\"')
  319. {
  320. pArg = CharNextA(pArg);
  321. pCmdStart = pArg;
  322. while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
  323. }
  324. else
  325. {
  326. pCmdStart = pArg;
  327. while (*pArg){pArg = CharNextA(pArg);}
  328. }
  329. *pArg = '\0';
  330. lstrcpyA(szTempString, StripWhitespace(pCmdStart));
  331. // Convert to unicode
  332. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szTempString, -1, (LPWSTR) wszVDirName, 50);
  333. iGotParamV = TRUE;
  334. }
  335. break;
  336. case '?':
  337. goto main_exit_with_help;
  338. break;
  339. } //switch
  340. } // if
  341. else
  342. {
  343. if ( *wszDirPath == '\0' )
  344. {
  345. // if no arguments, then get the filename portion
  346. MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPWSTR) wszDirPath, MAX_PATH);
  347. }
  348. }
  349. }
  350. if (iDoExport)
  351. {
  352. OpenMetabaseAndDoExport();
  353. /*
  354. RemoteOpenMetabaseAndCallExport(
  355. L"\\\\remotemachine", // pcszMachineName
  356. L"administrator", //pcszUserName
  357. L"domain1", //pcszDomain
  358. L"thepasword" //pcszPassword
  359. );
  360. */
  361. goto main_exit_gracefully;
  362. }
  363. if (iDoImport)
  364. {
  365. OpenMetabaseAndDoImport();
  366. }
  367. if (iDoVersion)
  368. {
  369. OpenMetabaseAndGetVersion();
  370. }
  371. // Check for custom description list being set.
  372. if (iGotParamN)
  373. {
  374. // we need the filename too
  375. if (*wszDirPath == '\0')
  376. {
  377. // sorry, we need parameter
  378. goto main_exit_with_help;
  379. }
  380. if (*wszTempString_N == '\0')
  381. {
  382. // sorry, we need parameter
  383. goto main_exit_with_help;
  384. }
  385. iTrans = TRANS_ADD_CUSTOM_DESCRIPTION;
  386. if (_wcsicmp(wszTempString_N, L"del") == 0)
  387. {
  388. iTrans = TRANS_DEL_CUSTOM_DESCRIPTION;
  389. }
  390. else if (_wcsicmp(wszTempString_N, L"add") == 0)
  391. {
  392. iTrans = TRANS_ADD_CUSTOM_DESCRIPTION;
  393. if (!iGotParamM)
  394. {
  395. // sorry, we need parameter
  396. goto main_exit_with_help;
  397. }
  398. // make sure we've got one of these entries
  399. if (*wszTempString_M == '\0')
  400. {
  401. // sorry, we need parameter
  402. goto main_exit_with_help;
  403. }
  404. if (!iGotParamL)
  405. {
  406. // sorry, we need parameter
  407. goto main_exit_with_help;
  408. }
  409. // make sure we've got one of these entries
  410. if (*wszTempString_L == '\0')
  411. {
  412. // sorry, we need parameter
  413. goto main_exit_with_help;
  414. }
  415. }
  416. else
  417. {
  418. goto main_exit_with_help;
  419. }
  420. if (TRANS_ADD_CUSTOM_DESCRIPTION == iTrans)
  421. {
  422. BOOL bCannotBeRemovedByUser = FALSE;
  423. if (_wcsicmp(wszTempString_L, L"1") == 0)
  424. {
  425. bCannotBeRemovedByUser = TRUE;
  426. }
  427. AddRemoveIISCustomDescriptionEntry(wszDirPath,wszTempString_M,bCannotBeRemovedByUser,TRUE);
  428. }
  429. else
  430. {
  431. AddRemoveIISCustomDescriptionEntry(wszDirPath,NULL,TRUE,FALSE);
  432. }
  433. goto main_exit_gracefully;
  434. }
  435. // Check for cgi restriction list being set.
  436. if (iGotParamC)
  437. {
  438. // we need the filename too
  439. if (*wszDirPath == '\0')
  440. {
  441. // sorry, we need parameter
  442. goto main_exit_with_help;
  443. }
  444. if (*wszTempString_C == '\0')
  445. {
  446. // sorry, we need parameter
  447. goto main_exit_with_help;
  448. }
  449. iTrans = TRANS_ADD_CGI_RESTRICT;
  450. if (_wcsicmp(wszTempString_C, L"del") == 0)
  451. {
  452. iTrans = TRANS_DEL_CGI_RESTRICT;
  453. }
  454. else if (_wcsicmp(wszTempString_C, L"add") == 0)
  455. {
  456. iTrans = TRANS_ADD_CGI_RESTRICT;
  457. }
  458. else
  459. {
  460. goto main_exit_with_help;
  461. }
  462. if (TRANS_ADD_CGI_RESTRICT == iTrans)
  463. {
  464. AddRemoveIISRestrictionListEntry(wszDirPath,FALSE,TRUE);
  465. }
  466. else
  467. {
  468. AddRemoveIISRestrictionListEntry(wszDirPath,FALSE,FALSE);
  469. }
  470. goto main_exit_gracefully;
  471. }
  472. // Check for isapi restriction list being set.
  473. if (iGotParamI)
  474. {
  475. // we need the filename too
  476. if (*wszDirPath == '\0')
  477. {
  478. // sorry, we need parameter
  479. goto main_exit_with_help;
  480. }
  481. if (*wszTempString_I == '\0')
  482. {
  483. // sorry, we need parameter
  484. goto main_exit_with_help;
  485. }
  486. iTrans = TRANS_ADD_ISAPI_RESTRICT;
  487. if (_wcsicmp(wszTempString_I, L"del") == 0)
  488. {
  489. iTrans = TRANS_DEL_ISAPI_RESTRICT;
  490. }
  491. else if (_wcsicmp(wszTempString_I, L"add") == 0)
  492. {
  493. iTrans = TRANS_ADD_ISAPI_RESTRICT;
  494. }
  495. else
  496. {
  497. goto main_exit_with_help;
  498. }
  499. if (TRANS_ADD_ISAPI_RESTRICT == iTrans)
  500. {
  501. AddRemoveIISRestrictionListEntry(wszDirPath,TRUE,TRUE);
  502. }
  503. else
  504. {
  505. AddRemoveIISRestrictionListEntry(wszDirPath,TRUE,FALSE);
  506. }
  507. goto main_exit_gracefully;
  508. }
  509. iTrans = TRANS_ADD_VIRTUAL_SERVER;
  510. if (TRUE == iGotParamS)
  511. {
  512. HRESULT hr;
  513. UINT iServerNum = 100;
  514. if (iDoDelete)
  515. {
  516. iTrans = TRANS_DEL_VIRTUAL_SERVER;
  517. if (*wszTempString_S == '\0')
  518. {
  519. // sorry, we need something in here
  520. goto main_exit_with_help;
  521. }
  522. iServerNum = _wtoi(wszTempString_S);
  523. hr = DelVirtualServer(iServerNum);
  524. if (FAILED(hr))
  525. {
  526. wsprintf(wszPrintString,L"FAILED to remove virtual server: W3SVC/%d\n", iServerNum);
  527. wprintf(wszPrintString);
  528. fRet = TRUE;
  529. }
  530. else
  531. {
  532. wsprintf(wszPrintString,L"SUCCESS:removed virtual server: W3SVC/%d\n", iServerNum);
  533. wprintf(wszPrintString);
  534. fRet = FALSE;
  535. }
  536. goto main_exit_gracefully;
  537. }
  538. else
  539. {
  540. if (TRUE == iGotParamP)
  541. {
  542. UINT iServerPort = 81;
  543. // we need the filename too
  544. if (*wszDirPath == '\0')
  545. {
  546. // sorry, we need all 3 parameters
  547. goto main_exit_with_help;
  548. }
  549. if (*wszTempString_S == '\0')
  550. {
  551. // sorry, we need all 3 parameters
  552. goto main_exit_with_help;
  553. }
  554. if (*wszTempString_P == '\0')
  555. {
  556. // sorry, we need all 3 parameters
  557. goto main_exit_with_help;
  558. }
  559. iServerNum = _wtoi(wszTempString_S);
  560. iServerPort = _wtoi(wszTempString_P);
  561. hr = AddVirtualServer(iServerNum, iServerPort, wszDirPath);
  562. if (FAILED(hr))
  563. {
  564. wsprintf(wszPrintString,L"FAILED to create virtual server: W3SVC/%d=%s, port=%d. err=0x%x\n", iServerNum, wszDirPath, iServerPort,hr);
  565. wprintf(wszPrintString);
  566. fRet = TRUE;
  567. }
  568. else
  569. {
  570. wsprintf(wszPrintString,L"SUCCESS:created virtual server: W3SVC/%d=%s, port=%d\n", iServerNum, wszDirPath, iServerPort);
  571. wprintf(wszPrintString);
  572. fRet = FALSE;
  573. }
  574. goto main_exit_gracefully;
  575. }
  576. }
  577. }
  578. iTrans = TRANS_ADD;
  579. if (iDoWebPath)
  580. {
  581. iTrans = TRANS_PRINT_PATH;
  582. }
  583. else
  584. {
  585. if (iDoDelete)
  586. {
  587. iTrans = TRANS_DEL;
  588. if (FALSE == iGotParamV)
  589. {
  590. // sorry, we need at parameter -v
  591. goto main_exit_with_help;
  592. }
  593. }
  594. else if (FALSE == iGotParamV || *wszDirPath == '\0')
  595. {
  596. // sorry, we need both parameters
  597. goto main_exit_with_help;
  598. }
  599. }
  600. fRet = OpenMetabaseAndDoStuff(wszVDirName, wszDirPath, iTrans);
  601. main_exit_gracefully:
  602. exit(fRet);
  603. main_exit_with_help:
  604. ShowHelp();
  605. exit(fRet);
  606. }
  607. void
  608. ShowHelp()
  609. {
  610. wprintf(L"Creates/Removes an IIS virtual directory to default web site\n\n");
  611. wprintf(L"IISVDIR [FullPath] [-v:VDirName] [-d] [-o] [-c:add or del] [-i:add or del] [-m:description] [-n:add or del] [-l:1 or 0] [-x]\n\n");
  612. wprintf(L"Instructions for add\\delete virtual directory:\n");
  613. wprintf(L" FullPath DOS path where vdir will point to (required for add)\n");
  614. wprintf(L" -v:vdirname The virtual dir name (required for both add\\delete)\n");
  615. wprintf(L" -d If set will delete vdir. if not set will add\n");
  616. wprintf(L" -o If set will printout web root path\n\n");
  617. wprintf(L"Instructions for add\\delete virtual server:\n");
  618. wprintf(L" FullPath DOS path where default vdir will point to in the virtual server (required for add)\n");
  619. wprintf(L" -s:sitenum For adding virtual server: The virtual server site number (required for both add\\delete)\n");
  620. wprintf(L" -p:portnum For adding virtual server: The virtual server port number (required for add)\n");
  621. wprintf(L" -d If set will delete virtual server. if not set will add\n");
  622. wprintf(L"Instructions for add\\delete entry from isapi/cgi restriction list:\n");
  623. wprintf(L" FullPath Full and filename path to binary which will be either add or deleted from isapi/cgi restrict list\n");
  624. wprintf(L" -c:add Ensures that the Fullpath will be enabled in the CGI restriction list\n");
  625. wprintf(L" -c:del Ensures that the Fullpath will be disabled in the CGI restriction list\n");
  626. wprintf(L" -i:add Ensures that the Fullpath will be enabled in the ISAPI restriction list\n");
  627. wprintf(L" -i:del Ensures that the Fullpath will be disabled in the ISAPI restriction list\n");
  628. wprintf(L"Instructions for add\\delete entry from custom description list (for isapi/cgi restriction list):\n");
  629. wprintf(L" FullPath Full and filename path to binary which will be either add or deleted from custom description list\n");
  630. wprintf(L" -m:Description Friendly description of FullPath\n");
  631. wprintf(L" -n:add Ensures that the Fullpath will be in the custom description list with the specified desciption\n");
  632. wprintf(L" -n:del Ensures that the Fullpath will not be in the custom description list\n");
  633. wprintf(L" -l:1 or 0 Specifies weather this entry can be removed by the user\n");
  634. wprintf(L"Instructions for exporting metabase config to a file:\n");
  635. wprintf(L" -x: Ensures export will happen\n");
  636. wprintf(L"\n");
  637. wprintf(L"Add Example: IISVDIR c:\\MyGroup\\MyStuff -v:Stuff\n");
  638. wprintf(L"Del Example: IISVDIR -v:Stuff -d\n");
  639. wprintf(L"Get Example: IISVDIR -o\n");
  640. wprintf(L"Add Virtual Server Example: IISVDIR c:\\MyGroup\\MyStuff -s:200 -p:81\n");
  641. wprintf(L"Del Virtual Server Example: IISVDIR -s:200 -d\n");
  642. wprintf(L"Add ISAPI restriction list Example: IISVDIR c:\\MyGroup\\MyStuff\\myisapi.dll -i:add\n");
  643. wprintf(L"Del ISAPI restriction list Example: IISVDIR c:\\MyGroup\\MyStuff\\myisapi.dll -i:del\n");
  644. wprintf(L"Add CGI restriction list Example: IISVDIR c:\\MyGroup\\MyStuff\\myCgi.exe -c:add\n");
  645. wprintf(L"Del CGI restriction list Example: IISVDIR c:\\MyGroup\\MyStuff\\myCgi.exe -c:del\n");
  646. wprintf(L"Add Custom Description list Example: IISVDIR c:\\MyGroup\\MyStuff\\myisapi.dll -m:MyDescription -n:add -l:0\n");
  647. wprintf(L"Del Custom Description list Example: IISVDIR c:\\MyGroup\\MyStuff\\myisapi.dll -n:del\n");
  648. wprintf(L"Export Example: IISVDIR -x\n");
  649. return;
  650. }
  651. LPSTR StripWhitespace( LPSTR pszString )
  652. {
  653. LPSTR pszTemp = NULL;
  654. if ( pszString == NULL )
  655. {
  656. return NULL;
  657. }
  658. while ( *pszString == ' ' || *pszString == '\t' )
  659. {
  660. pszString += 1;
  661. }
  662. // Catch case where string consists entirely of whitespace or empty string.
  663. if ( *pszString == '\0' )
  664. {
  665. return pszString;
  666. }
  667. pszTemp = pszString;
  668. pszString += lstrlenA(pszString) - 1;
  669. while ( *pszString == ' ' || *pszString == '\t' )
  670. {
  671. *pszString = '\0';
  672. pszString -= 1;
  673. }
  674. return pszTemp;
  675. }
  676. // Calculate the size of a Multi-String in WCHAR, including the ending 2 '\0's.
  677. int GetMultiStrSize(LPWSTR p)
  678. {
  679. int c = 0;
  680. while (1)
  681. {
  682. if (*p)
  683. {
  684. p++;
  685. c++;
  686. }
  687. else
  688. {
  689. c++;
  690. if (*(p+1))
  691. {
  692. p++;
  693. }
  694. else
  695. {
  696. c++;
  697. break;
  698. }
  699. }
  700. }
  701. return c;
  702. }
  703. // This walks the multi-sz and returns a pointer between
  704. // the last string of a multi-sz and the second terminating NULL
  705. LPCWSTR GetEndOfMultiSz(LPCWSTR szMultiSz)
  706. {
  707. LPCWSTR lpTemp = szMultiSz;
  708. do
  709. {
  710. lpTemp += wcslen(lpTemp);
  711. lpTemp++;
  712. } while (*lpTemp != L'\0');
  713. return(lpTemp);
  714. }
  715. void DumpWstrInMultiStr(LPWSTR pMultiStr)
  716. {
  717. LPWSTR pTempMultiStr = pMultiStr;
  718. while (1)
  719. {
  720. if (pTempMultiStr)
  721. {
  722. // display value
  723. wprintf(L" %s\r\n",pTempMultiStr);
  724. // then increment until we hit another null.
  725. while (*pTempMultiStr)
  726. {
  727. pTempMultiStr++;
  728. }
  729. // check for the ending \0\0
  730. if ( *(pTempMultiStr+1) == NULL)
  731. {
  732. break;
  733. }
  734. else
  735. {
  736. pTempMultiStr++;
  737. }
  738. }
  739. }
  740. return;
  741. }
  742. BOOL OpenMetabaseAndDoStuff(WCHAR * wszVDir,WCHAR * wszDir,int iTrans)
  743. {
  744. BOOL fRet = FALSE;
  745. HRESULT hr;
  746. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  747. WCHAR wszPrintString[MAX_PATH + MAX_PATH];
  748. if( FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )) ||
  749. FAILED (::CoCreateInstance(CLSID_MSAdminBase,
  750. NULL,
  751. CLSCTX_ALL,
  752. IID_IMSAdminBase,
  753. (void **)&pIMSAdminBase)))
  754. {
  755. return FALSE;
  756. }
  757. switch (iTrans)
  758. {
  759. case TRANS_DEL:
  760. if( RemoveVirtualDir( pIMSAdminBase, wszVDir))
  761. {
  762. hr = pIMSAdminBase->SaveData();
  763. if( SUCCEEDED( hr ))
  764. {
  765. fRet = TRUE;
  766. }
  767. }
  768. if (TRUE == fRet)
  769. {
  770. wsprintf(wszPrintString,L"SUCCESS:removed vdir=%s\n", wszVDir);
  771. wprintf(wszPrintString);
  772. }
  773. else
  774. {
  775. wsprintf(wszPrintString,L"FAILED to remove vdir=%s, err=0x%x\n", wszVDir, hr);
  776. wprintf(wszPrintString);
  777. }
  778. break;
  779. case TRANS_ADD:
  780. if( AddVirtualDir( pIMSAdminBase, wszVDir, wszDir))
  781. {
  782. hr = pIMSAdminBase->SaveData();
  783. if( SUCCEEDED( hr ))
  784. {
  785. fRet = TRUE;
  786. }
  787. }
  788. if (TRUE == fRet)
  789. {
  790. wsprintf(wszPrintString,L"SUCCESS: %s=%s", wszVDir, wszDir);
  791. wprintf(wszPrintString);
  792. }
  793. else
  794. {
  795. wsprintf(wszPrintString,L"FAILED to set: %s=%s, err=0x%x", wszVDir, wszDir, hr);
  796. wprintf(wszPrintString);
  797. }
  798. break;
  799. default:
  800. WCHAR wszRootPath[MAX_PATH];
  801. if (TRUE == GetVdirPhysicalPath(pIMSAdminBase,wszVDir,(WCHAR *) wszRootPath))
  802. {
  803. fRet = TRUE;
  804. if (_wcsicmp(wszVDir, L"") == 0)
  805. {
  806. wsprintf(wszPrintString,L"/=%s", wszRootPath);
  807. }
  808. else
  809. {
  810. wsprintf(wszPrintString,L"%s=%s", wszVDir, wszRootPath);
  811. }
  812. wprintf(wszPrintString);
  813. }
  814. else
  815. {
  816. wprintf(L"FAILED to get root path");
  817. }
  818. break;
  819. }
  820. if (pIMSAdminBase)
  821. {
  822. pIMSAdminBase->Release();
  823. pIMSAdminBase = NULL;
  824. }
  825. CoUninitialize();
  826. return fRet;
  827. }
  828. BOOL GetVdirPhysicalPath(IMSAdminBase *pIMSAdminBase,WCHAR * wszVDir,WCHAR *wszStringPathToFill)
  829. {
  830. HRESULT hr;
  831. BOOL fRet = FALSE;
  832. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  833. METADATA_RECORD mr;
  834. WCHAR szTmpData[MAX_PATH];
  835. DWORD dwMDRequiredDataLen;
  836. // open key to ROOT on website #1 (default)
  837. hr = pIMSAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  838. L"/LM/W3SVC/1",
  839. METADATA_PERMISSION_READ,
  840. REASONABLE_TIMEOUT,
  841. &hMetabase);
  842. if( FAILED( hr ))
  843. {
  844. return FALSE;
  845. }
  846. // Get the physical path for the WWWROOT
  847. mr.dwMDIdentifier = MD_VR_PATH;
  848. mr.dwMDAttributes = 0;
  849. mr.dwMDUserType = IIS_MD_UT_FILE;
  850. mr.dwMDDataType = STRING_METADATA;
  851. mr.dwMDDataLen = sizeof( szTmpData );
  852. mr.pbMDData = reinterpret_cast<unsigned char *>(szTmpData);
  853. // if nothing specified get the root.
  854. if (_wcsicmp(wszVDir, L"") == 0)
  855. {
  856. WCHAR wszTempDir[MAX_PATH];
  857. wsprintf(wszTempDir,L"/ROOT/%s", wszVDir);
  858. hr = pIMSAdminBase->GetData( hMetabase, wszTempDir, &mr, &dwMDRequiredDataLen );
  859. }
  860. else
  861. {
  862. hr = pIMSAdminBase->GetData( hMetabase, L"/ROOT", &mr, &dwMDRequiredDataLen );
  863. }
  864. pIMSAdminBase->CloseKey( hMetabase );
  865. if( SUCCEEDED( hr ))
  866. {
  867. wcscpy(wszStringPathToFill,szTmpData);
  868. fRet = TRUE;
  869. }
  870. pIMSAdminBase->CloseKey( hMetabase );
  871. return fRet;
  872. }
  873. BOOL AddVirtualDir(IMSAdminBase *pIMSAdminBase,WCHAR * wszVDir,WCHAR * wszDir)
  874. {
  875. HRESULT hr;
  876. BOOL fRet = FALSE;
  877. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  878. WCHAR wszTempPath[MAX_PATH];
  879. DWORD dwMDRequiredDataLen = 0;
  880. DWORD dwAccessPerm = 0;
  881. METADATA_RECORD mr;
  882. // Attempt to open the virtual dir set on Web server #1 (default server)
  883. hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  884. L"/LM/W3SVC/1/ROOT",
  885. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  886. REASONABLE_TIMEOUT,
  887. &hMetabase );
  888. // Create the key if it does not exist.
  889. if( FAILED( hr ))
  890. {
  891. return FALSE;
  892. }
  893. fRet = TRUE;
  894. mr.dwMDIdentifier = MD_VR_PATH;
  895. mr.dwMDAttributes = 0;
  896. mr.dwMDUserType = IIS_MD_UT_FILE;
  897. mr.dwMDDataType = STRING_METADATA;
  898. mr.dwMDDataLen = sizeof( wszTempPath );
  899. mr.pbMDData = reinterpret_cast<unsigned char *>(wszTempPath);
  900. // see if MD_VR_PATH exists.
  901. hr = pIMSAdminBase->GetData( hMetabase, wszVDir, &mr, &dwMDRequiredDataLen );
  902. if( FAILED( hr ))
  903. {
  904. fRet = FALSE;
  905. if( hr == MD_ERROR_DATA_NOT_FOUND ||
  906. HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND )
  907. {
  908. // Write both the key and the values if GetData() failed with any of the two errors.
  909. pIMSAdminBase->AddKey( hMetabase, wszVDir );
  910. mr.dwMDIdentifier = MD_VR_PATH;
  911. mr.dwMDAttributes = METADATA_INHERIT;
  912. mr.dwMDUserType = IIS_MD_UT_FILE;
  913. mr.dwMDDataType = STRING_METADATA;
  914. mr.dwMDDataLen = (wcslen(wszDir) + 1) * sizeof(WCHAR);
  915. mr.pbMDData = reinterpret_cast<unsigned char *>(wszDir);
  916. // Write MD_VR_PATH value
  917. hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr );
  918. fRet = SUCCEEDED( hr );
  919. // Set the default authentication method
  920. if( fRet )
  921. {
  922. DWORD dwAuthorization = MD_AUTH_NT; // NTLM only.
  923. mr.dwMDIdentifier = MD_AUTHORIZATION;
  924. mr.dwMDAttributes = METADATA_INHERIT; // need to inherit so that all subdirs are also protected.
  925. mr.dwMDUserType = IIS_MD_UT_FILE;
  926. mr.dwMDDataType = DWORD_METADATA;
  927. mr.dwMDDataLen = sizeof(DWORD);
  928. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAuthorization);
  929. // Write MD_AUTHORIZATION value
  930. hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr );
  931. fRet = SUCCEEDED( hr );
  932. }
  933. }
  934. }
  935. // In the following, do the stuff that we always want to do to the virtual dir, regardless of Admin's setting.
  936. if( fRet )
  937. {
  938. dwAccessPerm = MD_ACCESS_READ | MD_ACCESS_SCRIPT;
  939. mr.dwMDIdentifier = MD_ACCESS_PERM;
  940. mr.dwMDAttributes = METADATA_INHERIT; // Make it inheritable so all subdirectories will have the same rights.
  941. mr.dwMDUserType = IIS_MD_UT_FILE;
  942. mr.dwMDDataType = DWORD_METADATA;
  943. mr.dwMDDataLen = sizeof(DWORD);
  944. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAccessPerm);
  945. // Write MD_ACCESS_PERM value
  946. hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr );
  947. fRet = SUCCEEDED( hr );
  948. }
  949. if( fRet )
  950. {
  951. PWCHAR szDefLoadFile = L"Default.htm,Default.asp";
  952. mr.dwMDIdentifier = MD_DEFAULT_LOAD_FILE;
  953. mr.dwMDAttributes = 0; // no need for inheritence
  954. mr.dwMDUserType = IIS_MD_UT_FILE;
  955. mr.dwMDDataType = STRING_METADATA;
  956. mr.dwMDDataLen = (wcslen(szDefLoadFile) + 1) * sizeof(WCHAR);
  957. mr.pbMDData = reinterpret_cast<unsigned char *>(szDefLoadFile);
  958. // Write MD_DEFAULT_LOAD_FILE value
  959. hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr );
  960. fRet = SUCCEEDED( hr );
  961. }
  962. if( fRet )
  963. {
  964. PWCHAR wszKeyType = IIS_CLASS_WEB_VDIR_W;
  965. mr.dwMDIdentifier = MD_KEY_TYPE;
  966. mr.dwMDAttributes = 0; // no need for inheritence
  967. mr.dwMDUserType = IIS_MD_UT_SERVER;
  968. mr.dwMDDataType = STRING_METADATA;
  969. mr.dwMDDataLen = (wcslen(wszKeyType) + 1) * sizeof(WCHAR);
  970. mr.pbMDData = reinterpret_cast<unsigned char *>(wszKeyType);
  971. // Write MD_DEFAULT_LOAD_FILE value
  972. hr = pIMSAdminBase->SetData( hMetabase, wszVDir, &mr );
  973. fRet = SUCCEEDED( hr );
  974. }
  975. pIMSAdminBase->CloseKey( hMetabase );
  976. return fRet;
  977. }
  978. BOOL RemoveVirtualDir(IMSAdminBase *pIMSAdminBase,WCHAR * wszVDir)
  979. {
  980. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  981. HRESULT hr;
  982. // Attempt to open the virtual dir set on Web server #1 (default server)
  983. hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  984. L"/LM/W3SVC/1/ROOT",
  985. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  986. REASONABLE_TIMEOUT,
  987. &hMetabase );
  988. if( FAILED( hr ))
  989. {
  990. return FALSE;
  991. }
  992. // We don't check the return value since the key may already
  993. // not exist and we could get an error for that reason.
  994. pIMSAdminBase->DeleteKey( hMetabase, wszVDir );
  995. pIMSAdminBase->CloseKey( hMetabase );
  996. return TRUE;
  997. }
  998. HRESULT LoadAllData(IMSAdminBase * pmb,
  999. METADATA_HANDLE hMetabase,
  1000. WCHAR *subdir,
  1001. BYTE **buf,
  1002. DWORD *size,
  1003. DWORD *count) {
  1004. DWORD dataSet;
  1005. DWORD neededSize;
  1006. HRESULT hr;
  1007. //
  1008. // Try to get the property names.
  1009. //
  1010. hr = pmb->GetAllData(hMetabase,
  1011. subdir,
  1012. METADATA_NO_ATTRIBUTES,
  1013. ALL_METADATA,
  1014. ALL_METADATA,
  1015. count,
  1016. &dataSet,
  1017. *size,
  1018. *buf,
  1019. &neededSize);
  1020. if (!SUCCEEDED(hr))
  1021. {
  1022. DWORD code = ERROR_INSUFFICIENT_BUFFER;
  1023. if (hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER))
  1024. {
  1025. delete *buf;
  1026. *buf = 0;
  1027. *size = neededSize;
  1028. *buf = new BYTE[neededSize];
  1029. hr = pmb->GetAllData(hMetabase,
  1030. subdir,
  1031. METADATA_NO_ATTRIBUTES,
  1032. ALL_METADATA,
  1033. ALL_METADATA,
  1034. count,
  1035. &dataSet,
  1036. *size,
  1037. *buf,
  1038. &neededSize);
  1039. }
  1040. }
  1041. return hr;
  1042. }
  1043. const DWORD getAllBufSize = 4096*2;
  1044. HRESULT OpenMetabaseAndGetAllData(void)
  1045. {
  1046. HRESULT hr = E_FAIL;
  1047. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  1048. WCHAR wszPrintString[MAX_PATH + MAX_PATH];
  1049. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  1050. DWORD bufSize = getAllBufSize;
  1051. BYTE *buf = new BYTE[bufSize];
  1052. DWORD count=0;
  1053. DWORD linesize =0;
  1054. BYTE *pBuf1=NULL;
  1055. BYTE *pBuf2=NULL;
  1056. if( FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )) ||
  1057. FAILED (::CoCreateInstance(CLSID_MSAdminBase,
  1058. NULL,
  1059. CLSCTX_ALL,
  1060. IID_IMSAdminBase,
  1061. (void **)&pIMSAdminBase)))
  1062. {
  1063. wprintf(L"CoCreateInstance. FAILED. code=0x%x\n",hr);
  1064. return hr;
  1065. }
  1066. // Attempt to open the virtual dir set on Web server #1 (default server)
  1067. hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1068. L"/Schema/Properties",
  1069. METADATA_PERMISSION_READ,
  1070. REASONABLE_TIMEOUT,
  1071. &hMetabase );
  1072. if( FAILED( hr ))
  1073. {
  1074. wprintf(L"pIMSAdminBase->OpenKey. FAILED. code=0x%x\n",hr);
  1075. goto OpenMetabaseAndGetAllData_Exit;
  1076. }
  1077. hr = LoadAllData(pIMSAdminBase, hMetabase, L"Names", &buf, &bufSize, &count);
  1078. if( FAILED( hr ))
  1079. {
  1080. wprintf(L"LoadAllData: FAILED. code=0x%x\n",hr);
  1081. goto OpenMetabaseAndGetAllData_Exit;
  1082. }
  1083. wprintf(L"LoadAllData: Succeeded. bufSize=0x%x, count=0x%x, buf=%p, end of buf=%p\n",bufSize,count,buf,buf+bufSize);
  1084. wprintf(L"Here is the last 1000 bytes, that the client received.\n");
  1085. linesize = 0;
  1086. pBuf1 = buf+bufSize - 1000;
  1087. for (int i=0;pBuf1<buf+bufSize;pBuf1++,i++)
  1088. {
  1089. if (NULL == *pBuf1)
  1090. {
  1091. wprintf(L".");
  1092. }
  1093. else
  1094. {
  1095. wprintf(L"%c",*pBuf1);
  1096. }
  1097. linesize++;
  1098. if (linesize >= 16)
  1099. {
  1100. linesize=0;
  1101. wprintf(L"\n");
  1102. }
  1103. }
  1104. wprintf(L"\n");
  1105. hr = S_OK;
  1106. OpenMetabaseAndGetAllData_Exit:
  1107. if (pIMSAdminBase)
  1108. {
  1109. pIMSAdminBase->Release();
  1110. pIMSAdminBase = NULL;
  1111. }
  1112. CoUninitialize();
  1113. return hr;
  1114. }
  1115. HRESULT DelVirtualServer(UINT iServerNum)
  1116. {
  1117. HRESULT hr = E_FAIL;
  1118. return hr;
  1119. }
  1120. // iServerNum the virtual server number
  1121. // iServerPort the virtual server port (port 80 is the default site's port,so you can't use this and you can't use one that is already in use)
  1122. // wszDir the physical directory where the default site is located
  1123. HRESULT AddVirtualServer(UINT iServerNum, UINT iServerPort, WCHAR * wszDefaultVDirDir)
  1124. {
  1125. HRESULT hr = E_FAIL;
  1126. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  1127. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  1128. METADATA_RECORD mr;
  1129. WCHAR wszMetabasePath[_MAX_PATH];
  1130. WCHAR wszMetabasePathRoot[10];
  1131. WCHAR wszData[_MAX_PATH];
  1132. DWORD dwData = 0;
  1133. METADATA_HANDLE hKeyBase = METADATA_MASTER_ROOT_HANDLE;
  1134. if( FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )) ||
  1135. FAILED (::CoCreateInstance(CLSID_MSAdminBase,
  1136. NULL,
  1137. CLSCTX_ALL,
  1138. IID_IMSAdminBase,
  1139. (void **)&pIMSAdminBase)))
  1140. {
  1141. wprintf(L"CoCreateInstance. FAILED. code=0x%x\n",hr);
  1142. return hr;
  1143. }
  1144. // Create the new node
  1145. wsprintf(wszMetabasePath,L"LM/W3SVC/%i",iServerNum);
  1146. // try to open the specified metabase node, it might already exist
  1147. hr = pIMSAdminBase->OpenKey(hKeyBase,
  1148. wszMetabasePath,
  1149. METADATA_PERMISSION_READ,
  1150. REASONABLE_TIMEOUT,
  1151. &hMetabase);
  1152. if (hr == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))
  1153. {
  1154. hr = pIMSAdminBase->CloseKey(hMetabase);
  1155. // open the metabase root handle
  1156. hr = pIMSAdminBase->OpenKey(hKeyBase,
  1157. L"",
  1158. METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,
  1159. REASONABLE_TIMEOUT,&hMetabase);
  1160. if( FAILED( hr ))
  1161. {
  1162. // if we can't even open the root handle, then we're pretty hosed
  1163. wprintf(L"1OpenKey. FAILED. code=0x%x\n",hr);
  1164. goto AddVirtualServer_Exit;
  1165. }
  1166. // and add our node
  1167. hr = pIMSAdminBase->AddKey(hMetabase, wszMetabasePath);
  1168. if (FAILED(hr))
  1169. {
  1170. wprintf(L"AddKey. FAILED. code=0x%x\n",hr);
  1171. pIMSAdminBase->CloseKey(hMetabase);
  1172. goto AddVirtualServer_Exit;
  1173. }
  1174. else
  1175. {
  1176. hr = pIMSAdminBase->CloseKey(hMetabase);
  1177. if (FAILED(hr))
  1178. {
  1179. goto AddVirtualServer_Exit;
  1180. }
  1181. else
  1182. {
  1183. // open it again
  1184. hr = pIMSAdminBase->OpenKey(hKeyBase,
  1185. wszMetabasePath,
  1186. METADATA_PERMISSION_WRITE | METADATA_PERMISSION_READ,
  1187. REASONABLE_TIMEOUT,
  1188. &hMetabase);
  1189. if (FAILED(hr))
  1190. {
  1191. wprintf(L"2OpenKey. FAILED. code=0x%x\n",hr);
  1192. pIMSAdminBase->CloseKey(hMetabase);
  1193. goto AddVirtualServer_Exit;
  1194. }
  1195. }
  1196. }
  1197. }
  1198. else
  1199. {
  1200. if (FAILED(hr))
  1201. {
  1202. wprintf(L"3OpenKey. FAILED. code=0x%x\n",hr);
  1203. goto AddVirtualServer_Exit;
  1204. }
  1205. else
  1206. {
  1207. // we were able to open the path, so it must already exist!
  1208. hr = ERROR_ALREADY_EXISTS;
  1209. pIMSAdminBase->CloseKey(hMetabase);
  1210. goto AddVirtualServer_Exit;
  1211. }
  1212. }
  1213. // We should have a brand new Key now...
  1214. //
  1215. // Create stuff in the node of this path!
  1216. //
  1217. //
  1218. // /LM/W3SVC/1/KeyType
  1219. //
  1220. memset( (PVOID)wszData, 0, sizeof(wszData));
  1221. wcscpy(wszData,IIS_CLASS_WEB_SERVER_W);
  1222. mr.dwMDIdentifier = MD_KEY_TYPE;
  1223. mr.dwMDAttributes = 0; // no need for inheritence
  1224. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1225. mr.dwMDDataType = STRING_METADATA;
  1226. mr.dwMDDataLen = (wcslen(wszData) + 1) * sizeof(WCHAR);
  1227. mr.pbMDData = reinterpret_cast<unsigned char *>(wszData);
  1228. hr = pIMSAdminBase->SetData( hMetabase, L"", &mr );
  1229. if (FAILED(hr))
  1230. {
  1231. wprintf(L"SetData[MD_KEY_TYPE]. FAILED. code=0x%x\n",hr);
  1232. }
  1233. //
  1234. // /W3SVC/1/ServerBindings
  1235. //
  1236. memset( (PVOID)wszData, 0, sizeof(wszData));
  1237. wsprintf(wszData, L":%d:", iServerPort);
  1238. mr.dwMDIdentifier = MD_SERVER_BINDINGS;
  1239. mr.dwMDAttributes = METADATA_INHERIT;
  1240. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1241. mr.dwMDDataType = MULTISZ_METADATA;
  1242. mr.dwMDDataLen = GetMultiStrSize(wszData) * sizeof(WCHAR);
  1243. mr.pbMDData = reinterpret_cast<unsigned char *>(wszData);
  1244. hr = pIMSAdminBase->SetData( hMetabase, L"", &mr );
  1245. if (FAILED(hr))
  1246. {
  1247. wprintf(L"SetData[MD_SERVER_BINDINGS]. FAILED. code=0x%x\n",hr);
  1248. }
  1249. //
  1250. // /W3SVC/1/SecureBindings
  1251. //
  1252. memset( (PVOID)wszData, 0, sizeof(wszData));
  1253. wcscpy(wszData, L" ");
  1254. mr.dwMDIdentifier = MD_SECURE_BINDINGS;
  1255. mr.dwMDAttributes = METADATA_INHERIT;
  1256. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1257. mr.dwMDDataType = MULTISZ_METADATA;
  1258. mr.dwMDDataLen = GetMultiStrSize(wszData) * sizeof(WCHAR);
  1259. mr.pbMDData = reinterpret_cast<unsigned char *>(wszData);
  1260. hr = pIMSAdminBase->SetData( hMetabase, L"", &mr );
  1261. if (FAILED(hr))
  1262. {
  1263. wprintf(L"SetData[MD_SECURE_BINDINGS]. FAILED. code=0x%x\n",hr);
  1264. }
  1265. //
  1266. // Create stuff in the /Root node of this path!
  1267. //
  1268. wcscpy(wszMetabasePathRoot, L"/Root");
  1269. wcscpy(wszData,IIS_CLASS_WEB_VDIR_W);
  1270. // W3SVC/3/Root/KeyType
  1271. mr.dwMDIdentifier = MD_KEY_TYPE;
  1272. mr.dwMDAttributes = 0; // no need for inheritence
  1273. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1274. mr.dwMDDataType = STRING_METADATA;
  1275. mr.dwMDDataLen = (wcslen(wszData) + 1) * sizeof(WCHAR);
  1276. mr.pbMDData = reinterpret_cast<unsigned char *>(wszData);
  1277. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1278. if (FAILED(hr))
  1279. {
  1280. wprintf(L"SetData[MD_KEY_TYPE]. FAILED. code=0x%x\n",hr);
  1281. }
  1282. // W3SVC/3/Root/VrPath
  1283. mr.dwMDIdentifier = MD_VR_PATH;
  1284. mr.dwMDAttributes = METADATA_INHERIT;
  1285. mr.dwMDUserType = IIS_MD_UT_FILE;
  1286. mr.dwMDDataType = STRING_METADATA;
  1287. mr.dwMDDataLen = (wcslen(wszDefaultVDirDir) + 1) * sizeof(WCHAR);
  1288. mr.pbMDData = reinterpret_cast<unsigned char *>(wszDefaultVDirDir);
  1289. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1290. if (FAILED(hr))
  1291. {
  1292. wprintf(L"SetData[MD_VR_PATH]. FAILED. code=0x%x\n",hr);
  1293. }
  1294. // W3SVC/3/Root/Authorizaton
  1295. dwData = MD_AUTH_ANONYMOUS | MD_AUTH_NT;
  1296. mr.dwMDIdentifier = MD_AUTHORIZATION;
  1297. mr.dwMDAttributes = METADATA_INHERIT;
  1298. mr.dwMDUserType = IIS_MD_UT_FILE;
  1299. mr.dwMDDataType = DWORD_METADATA;
  1300. mr.dwMDDataLen = sizeof(DWORD);
  1301. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwData);
  1302. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1303. if (FAILED(hr))
  1304. {
  1305. wprintf(L"SetData[MD_AUTHORIZATION]. FAILED. code=0x%x\n",hr);
  1306. }
  1307. // W3SVC/3/Root/AccessPerm
  1308. dwData = MD_ACCESS_SCRIPT | MD_ACCESS_READ;
  1309. mr.dwMDIdentifier = MD_ACCESS_PERM;
  1310. mr.dwMDAttributes = METADATA_INHERIT;
  1311. mr.dwMDUserType = IIS_MD_UT_FILE;
  1312. mr.dwMDDataType = DWORD_METADATA;
  1313. mr.dwMDDataLen = sizeof(DWORD);
  1314. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwData);
  1315. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1316. if (FAILED(hr))
  1317. {
  1318. wprintf(L"SetData[MD_ACCESS_PERM]. FAILED. code=0x%x\n",hr);
  1319. }
  1320. // W3SVC/3/Root/DirectoryBrowsing
  1321. dwData = MD_DIRBROW_SHOW_DATE
  1322. | MD_DIRBROW_SHOW_TIME
  1323. | MD_DIRBROW_SHOW_SIZE
  1324. | MD_DIRBROW_SHOW_EXTENSION
  1325. | MD_DIRBROW_LONG_DATE
  1326. | MD_DIRBROW_LOADDEFAULT;
  1327. // | MD_DIRBROW_ENABLED;
  1328. mr.dwMDIdentifier = MD_DIRECTORY_BROWSING;
  1329. mr.dwMDAttributes = METADATA_INHERIT;
  1330. mr.dwMDUserType = IIS_MD_UT_FILE;
  1331. mr.dwMDDataType = DWORD_METADATA;
  1332. mr.dwMDDataLen = sizeof(DWORD);
  1333. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwData);
  1334. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1335. if (FAILED(hr))
  1336. {
  1337. wprintf(L"SetData[MD_DIRECTORY_BROWSING]. FAILED. code=0x%x\n",hr);
  1338. }
  1339. /*
  1340. dwData = 0;
  1341. mr.dwMDIdentifier = MD_SERVER_AUTOSTART;
  1342. mr.dwMDAttributes = METADATA_INHERIT;
  1343. mr.dwMDUserType = IIS_MD_UT_FILE;
  1344. mr.dwMDDataType = DWORD_METADATA;
  1345. mr.dwMDDataLen = sizeof(DWORD);
  1346. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwData);
  1347. hr = pIMSAdminBase->SetData( hMetabase, wszMetabasePathRoot, &mr );
  1348. if (FAILED(hr)) {
  1349. wprintf(L"SetData[MD_SERVER_AUTOSTART]. FAILED. code=0x%x\n",hr);
  1350. }
  1351. */
  1352. pIMSAdminBase->CloseKey(hMetabase);
  1353. AddVirtualServer_Exit:
  1354. if (pIMSAdminBase)
  1355. {
  1356. pIMSAdminBase->Release();
  1357. pIMSAdminBase = NULL;
  1358. }
  1359. CoUninitialize();
  1360. return hr;
  1361. }
  1362. // returns 0 if not found
  1363. // returns 1 if StrToFind is found but StrToFind2 is not found
  1364. // returns 2 if StrToFind is found and StrToFind2 is found
  1365. INT FindWstrInMultiStrSpecial(LPWSTR pMultiStr, LPWSTR StrToFind, LPWSTR StrToFind2)
  1366. {
  1367. INT iReturn = 0;
  1368. LPWSTR pTempMultiStr = pMultiStr;
  1369. DWORD dwCharCount = 0;
  1370. while (1)
  1371. {
  1372. if (pTempMultiStr)
  1373. {
  1374. // The 1st entry should be
  1375. // the type. so it will be either 1 or a number.
  1376. // so let's skip till the next null.
  1377. // then increment until we hit another null.
  1378. while (*pTempMultiStr)
  1379. {
  1380. pTempMultiStr++;
  1381. dwCharCount++;
  1382. }
  1383. // check for the ending \0\0
  1384. if ( *(pTempMultiStr+1) == NULL)
  1385. {
  1386. break;
  1387. }
  1388. else
  1389. {
  1390. pTempMultiStr++;
  1391. dwCharCount++;
  1392. }
  1393. // compare this value to the imput value
  1394. if (0 == _wcsicmp((const wchar_t *) pTempMultiStr,StrToFind))
  1395. {
  1396. iReturn = 1;
  1397. }
  1398. // so let's skip till the next null.
  1399. // then increment until we hit another null.
  1400. while (*pTempMultiStr)
  1401. {
  1402. pTempMultiStr++;
  1403. dwCharCount++;
  1404. }
  1405. // check for the ending \0\0
  1406. if ( *(pTempMultiStr+1) == NULL)
  1407. {
  1408. break;
  1409. }
  1410. else
  1411. {
  1412. pTempMultiStr++;
  1413. dwCharCount++;
  1414. }
  1415. // check for an exact match.
  1416. if (0 != iReturn)
  1417. {
  1418. // compare this value to the imput value
  1419. if (StrToFind2 != NULL)
  1420. {
  1421. if (0 == _wcsicmp((const wchar_t *) pTempMultiStr,StrToFind2))
  1422. {
  1423. iReturn = 2;
  1424. break;
  1425. }
  1426. }
  1427. break;
  1428. }
  1429. // so let's skip till the next null.
  1430. // then increment until we hit another null.
  1431. while (*pTempMultiStr)
  1432. {
  1433. pTempMultiStr++;
  1434. dwCharCount++;
  1435. }
  1436. // check for the ending \0\0
  1437. if ( *(pTempMultiStr+1) == NULL)
  1438. {
  1439. break;
  1440. }
  1441. else
  1442. {
  1443. pTempMultiStr++;
  1444. dwCharCount++;
  1445. }
  1446. // Check if we screwed up somehow and are in an infinite loop.
  1447. // could happen if we don't find an ending \0\0
  1448. if (dwCharCount > 32000)
  1449. {
  1450. break;
  1451. }
  1452. }
  1453. }
  1454. return iReturn;
  1455. }
  1456. BOOL FindWstrInMultiStr(LPWSTR pMultiStr, LPWSTR StrToFind)
  1457. {
  1458. BOOL bFound = FALSE;
  1459. LPWSTR pTempMultiStr = pMultiStr;
  1460. DWORD dwCharCount = 0;
  1461. while (1)
  1462. {
  1463. if (pTempMultiStr)
  1464. {
  1465. // compare this value to the imput value
  1466. if (0 == _wcsicmp((const wchar_t *) pTempMultiStr,StrToFind))
  1467. {
  1468. bFound = TRUE;
  1469. break;
  1470. }
  1471. // then increment until we hit another null.
  1472. while (*pTempMultiStr)
  1473. {
  1474. pTempMultiStr++;
  1475. dwCharCount++;
  1476. }
  1477. // check for the ending \0\0
  1478. if ( *(pTempMultiStr+1) == NULL)
  1479. {
  1480. break;
  1481. }
  1482. else
  1483. {
  1484. pTempMultiStr++;
  1485. dwCharCount++;
  1486. }
  1487. // Check if we screwed up somehow and are in an infinite loop.
  1488. // could happen if we don't find an ending \0\0
  1489. if (dwCharCount > 32000)
  1490. {
  1491. break;
  1492. }
  1493. }
  1494. }
  1495. return bFound;
  1496. }
  1497. BOOL RemoveWstrInMultiStr(LPWSTR pMultiStr, LPWSTR StrToFind)
  1498. {
  1499. BOOL bFound = FALSE;
  1500. LPWSTR pTempMultiStr = pMultiStr;
  1501. DWORD dwCharCount = 0;
  1502. while (1)
  1503. {
  1504. if (pTempMultiStr)
  1505. {
  1506. // compare this value to the imput value
  1507. if (0 == _wcsicmp((const wchar_t *) pTempMultiStr,StrToFind))
  1508. {
  1509. LPWSTR pLastDoubleNull = NULL;
  1510. LPWSTR pBeginPath = pTempMultiStr;
  1511. bFound = TRUE;
  1512. // then increment until we hit another null.
  1513. while (*pTempMultiStr)
  1514. {
  1515. pTempMultiStr++;
  1516. }
  1517. pTempMultiStr++;
  1518. // Find the last double null.
  1519. pLastDoubleNull = pTempMultiStr;
  1520. if (*pLastDoubleNull)
  1521. {
  1522. while (1)
  1523. {
  1524. if (NULL == *pLastDoubleNull && NULL == *(pLastDoubleNull+1))
  1525. {
  1526. break;
  1527. }
  1528. pLastDoubleNull++;
  1529. }
  1530. pLastDoubleNull++;
  1531. }
  1532. // check if we are the last entry.
  1533. if (pLastDoubleNull == pTempMultiStr)
  1534. {
  1535. // set everything to nulls
  1536. memset(pBeginPath,0,(pLastDoubleNull-pBeginPath) * sizeof(WCHAR));
  1537. }
  1538. else
  1539. {
  1540. // move everything behind it to where we are.
  1541. memmove(pBeginPath,pTempMultiStr, (pLastDoubleNull - pTempMultiStr) * sizeof(WCHAR));
  1542. // and set everything behind that to nulls
  1543. memset(pBeginPath + (pLastDoubleNull - pTempMultiStr),0,(pTempMultiStr-pBeginPath) * sizeof(WCHAR));
  1544. }
  1545. break;
  1546. }
  1547. // then increment until we hit another null.
  1548. while (*pTempMultiStr)
  1549. {
  1550. pTempMultiStr++;
  1551. dwCharCount++;
  1552. }
  1553. // check for the ending \0\0
  1554. if ( *(pTempMultiStr+1) == NULL)
  1555. {
  1556. break;
  1557. }
  1558. else
  1559. {
  1560. pTempMultiStr++;
  1561. dwCharCount++;
  1562. }
  1563. // Check if we screwed up somehow and are in an infinite loop.
  1564. // could happen if we don't find an ending \0\0
  1565. if (dwCharCount > 32000)
  1566. {
  1567. break;
  1568. }
  1569. }
  1570. }
  1571. return bFound;
  1572. }
  1573. BOOL IsAllowAllByDefault(LPWSTR pMultiStr)
  1574. {
  1575. BOOL bFound = FALSE;
  1576. if (pMultiStr)
  1577. {
  1578. if (0 == _wcsicmp((const wchar_t *) pMultiStr,L"1"))
  1579. {
  1580. bFound = TRUE;
  1581. }
  1582. }
  1583. return bFound;
  1584. }
  1585. // returns TRUE if we need to write to metabase
  1586. // returns bAddToList = true if we need to add to the list
  1587. // returns bAddToList = false if we need to remove from the list
  1588. // returns FALSE if we don't need to write to metabase
  1589. //
  1590. BOOL IsAddRemoveOrDoNothing(LPWSTR pMultiStr,LPWSTR wszFilePath,BOOL bEnableThisBinary,BOOL * bAddToList)
  1591. {
  1592. BOOL bReturn = FALSE;
  1593. BOOL bAllowAllByDefault = FALSE;
  1594. BOOL bFound = FALSE;
  1595. if (!bAddToList || !pMultiStr || !wszFilePath)
  1596. {
  1597. return FALSE;
  1598. }
  1599. // set flag to see if we are in deny all by default
  1600. // or if we are in enable all by default..
  1601. if (TRUE == IsAllowAllByDefault((WCHAR *) pMultiStr))
  1602. {
  1603. bAllowAllByDefault = TRUE;
  1604. }
  1605. // Loop thru the data to see if we are already present...
  1606. //
  1607. // data looks like this:
  1608. // 0 or 1\0
  1609. // fileentry1\0
  1610. // filenetry2\0
  1611. // last fileentry\0\0
  1612. //
  1613. bFound = FindWstrInMultiStr((WCHAR *) pMultiStr,wszFilePath);
  1614. // Make some decisions
  1615. if (bEnableThisBinary)
  1616. {
  1617. if (bFound)
  1618. {
  1619. if (bAllowAllByDefault)
  1620. {
  1621. // trying to enable
  1622. // the list is allow by default
  1623. // it's in the list, so that means it's currently not enabled..
  1624. // We need to remove it from the list!
  1625. *bAddToList = FALSE;
  1626. bReturn = TRUE;
  1627. goto IsAddRemoveOrDoNothing_Exit;
  1628. }
  1629. else
  1630. {
  1631. // trying to enable
  1632. // the list is deny by default
  1633. // it's in the list. so that means it's currently already enabled!
  1634. // do nothing! get out, things are groovy.
  1635. bReturn = FALSE;
  1636. goto IsAddRemoveOrDoNothing_Exit;
  1637. }
  1638. }
  1639. else
  1640. {
  1641. if (bAllowAllByDefault)
  1642. {
  1643. // trying to enable
  1644. // the list is allow by default
  1645. // it's not in the list
  1646. // so that means it's currently already enabled!
  1647. // do nothing! get out. things are groovy.
  1648. bReturn = FALSE;
  1649. goto IsAddRemoveOrDoNothing_Exit;
  1650. }
  1651. else
  1652. {
  1653. // trying to enable
  1654. // the list is deny by default
  1655. // it's not in the list
  1656. // so that means we need to add it to the list
  1657. *bAddToList = TRUE;
  1658. bReturn = TRUE;
  1659. goto IsAddRemoveOrDoNothing_Exit;
  1660. }
  1661. }
  1662. }
  1663. else
  1664. {
  1665. if (bFound)
  1666. {
  1667. if (bAllowAllByDefault)
  1668. {
  1669. // trying to disable
  1670. // the list is allow by default
  1671. // it's in the list, so that means it's currently disabled already
  1672. // do nothing! get out. things are groovy.
  1673. bReturn = FALSE;
  1674. goto IsAddRemoveOrDoNothing_Exit;
  1675. }
  1676. else
  1677. {
  1678. // trying to disable
  1679. // the list is deny by default
  1680. // it's in the list. so that means currently it is enabled, so
  1681. // we want to make sure to remove it from the list
  1682. // so that it will be denied.
  1683. *bAddToList = FALSE;
  1684. bReturn = TRUE;
  1685. goto IsAddRemoveOrDoNothing_Exit;
  1686. }
  1687. }
  1688. else
  1689. {
  1690. if (bAllowAllByDefault)
  1691. {
  1692. // trying to disable
  1693. // the list is allow by default
  1694. // it's not in the list
  1695. // so that means it's currently being allowed
  1696. // we need to add it to the list so that it will be denied
  1697. *bAddToList = TRUE;
  1698. bReturn = TRUE;
  1699. goto IsAddRemoveOrDoNothing_Exit;
  1700. }
  1701. else
  1702. {
  1703. // trying to disable
  1704. // the list is deny by default
  1705. // it's in the list, so that means it's currently disabled already
  1706. // do nothing! get out. things are groovy.
  1707. bReturn = FALSE;
  1708. goto IsAddRemoveOrDoNothing_Exit;
  1709. }
  1710. }
  1711. }
  1712. IsAddRemoveOrDoNothing_Exit:
  1713. return bReturn;
  1714. }
  1715. // wszFilePath = is the fully qualified path to the binary which will be enabled or disabled
  1716. // bBinaryIsISAPI = is the flag which determines which metabase setting to set
  1717. // when set to TRUE it will perform action on the ISAPI restriction list
  1718. // when set to FALSE it will perform action on the CGI restriction list
  1719. // bEnableThisBinary = is the flag which determines weather the binary should be allowed to run or not.
  1720. // when set to TRUE it will ensure that the specified binary will be allowed to run
  1721. // when set to FALSE it will ensure that the specified binary will not be allowed to run
  1722. // will figure out what is the right thing to do from what current metabase settings is
  1723. HRESULT AddRemoveIISRestrictionListEntry(WCHAR * wszFilePathInput,BOOL bBinaryIsISAPI,BOOL bEnableThisBinary)
  1724. {
  1725. HRESULT hr = E_FAIL;
  1726. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  1727. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  1728. METADATA_RECORD mr;
  1729. BYTE * pbDataOld = NULL;
  1730. BYTE * pbDataNew = NULL;
  1731. DWORD dwMDRequiredDataLen = 0;
  1732. DWORD dwNewEntryLength = 0;
  1733. DWORD dwNewTotalLength = 0;
  1734. DWORD dwOldByteLength = 0;
  1735. BOOL bAddToList = FALSE;
  1736. WCHAR * wszFilePath = NULL;
  1737. // Convert any env vars to hard coded paths
  1738. LPWSTR pch = wcschr( (LPWSTR) wszFilePathInput, L'%');
  1739. if (pch)
  1740. {
  1741. // determine the length of the expanded string
  1742. DWORD len = ::ExpandEnvironmentStrings(wszFilePathInput, 0, 0);
  1743. if (!len)
  1744. {
  1745. return hr;
  1746. }
  1747. wszFilePath = (WCHAR *) GlobalAlloc(GPTR, (len + 1) * sizeof(WCHAR));
  1748. DWORD len1 = ExpandEnvironmentStrings((LPWSTR) wszFilePathInput,const_cast<wchar_t*>(wszFilePath),len);
  1749. if (len1 != len)
  1750. {
  1751. if (wszFilePath)
  1752. {
  1753. GlobalFree(wszFilePath);wszFilePath = NULL;
  1754. }
  1755. return hr;
  1756. }
  1757. }
  1758. else
  1759. {
  1760. wszFilePath = wszFilePathInput;
  1761. }
  1762. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1763. if (hr == RPC_E_CHANGED_MODE)
  1764. {
  1765. // fine. try again
  1766. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  1767. }
  1768. if (FAILED(hr))
  1769. {
  1770. return hr;
  1771. }
  1772. hr = CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase,(void **)&pIMSAdminBase);
  1773. if (FAILED(hr))
  1774. {
  1775. goto AddRemoveIISRestrictionListEntry_Exit;
  1776. }
  1777. // open the specified metabase node
  1778. hr = pIMSAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  1779. L"LM/W3SVC",
  1780. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1781. REASONABLE_TIMEOUT,
  1782. &hMetabase);
  1783. if (FAILED(hr))
  1784. {
  1785. hMetabase = NULL;
  1786. goto AddRemoveIISRestrictionListEntry_Exit;
  1787. }
  1788. if (bBinaryIsISAPI)
  1789. {
  1790. mr.dwMDIdentifier = MD_ISAPI_RESTRICTION_LIST;
  1791. }
  1792. else
  1793. {
  1794. mr.dwMDIdentifier = MD_CGI_RESTRICTION_LIST;
  1795. }
  1796. mr.dwMDAttributes = 0; // no need for inheritence
  1797. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1798. mr.dwMDDataType = MULTISZ_METADATA;
  1799. mr.dwMDDataLen = 0;
  1800. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataOld);
  1801. // first we need to figure out how much space we need
  1802. hr = pIMSAdminBase->GetData(hMetabase, L"", &mr, &dwMDRequiredDataLen);
  1803. if(FAILED(hr))
  1804. {
  1805. // if there isn't a value there that we need to update
  1806. // then create one
  1807. if( hr == MD_ERROR_DATA_NOT_FOUND || HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND )
  1808. {
  1809. WCHAR wszDefaultData[4];
  1810. // set to "allow all by default"
  1811. memset( (PVOID)wszDefaultData, 0, sizeof(wszDefaultData));
  1812. wcscpy(wszDefaultData, L"1");
  1813. if (bBinaryIsISAPI)
  1814. {
  1815. mr.dwMDIdentifier = MD_ISAPI_RESTRICTION_LIST;
  1816. }
  1817. else
  1818. {
  1819. mr.dwMDIdentifier = MD_CGI_RESTRICTION_LIST;
  1820. }
  1821. mr.dwMDAttributes = 0; // no need for inheritence
  1822. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1823. mr.dwMDDataType = MULTISZ_METADATA;
  1824. mr.dwMDDataLen = GetMultiStrSize(wszDefaultData) * sizeof(WCHAR);
  1825. mr.pbMDData = reinterpret_cast<unsigned char *>(wszDefaultData);
  1826. // Write value
  1827. hr = pIMSAdminBase->SetData(hMetabase, L"", &mr);
  1828. // find out how much space we need.
  1829. mr.dwMDDataLen = 0;
  1830. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataOld);
  1831. hr = pIMSAdminBase->GetData(hMetabase, L"", &mr, &dwMDRequiredDataLen);
  1832. if(FAILED(hr))
  1833. {
  1834. goto AddRemoveIISRestrictionListEntry_Exit;
  1835. }
  1836. }
  1837. else
  1838. {
  1839. goto AddRemoveIISRestrictionListEntry_Exit;
  1840. }
  1841. }
  1842. pbDataOld = (BYTE *) GlobalAlloc(GPTR, dwMDRequiredDataLen);
  1843. if (!pbDataOld)
  1844. {
  1845. hr = E_OUTOFMEMORY;
  1846. goto AddRemoveIISRestrictionListEntry_Exit;
  1847. }
  1848. // do the real call to get the data from the metabase
  1849. mr.dwMDDataLen = dwMDRequiredDataLen;
  1850. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataOld);
  1851. hr = pIMSAdminBase->GetData(hMetabase, L"", &mr, &dwMDRequiredDataLen);
  1852. if (FAILED(hr))
  1853. {
  1854. goto AddRemoveIISRestrictionListEntry_Exit;
  1855. }
  1856. if (FALSE == IsAddRemoveOrDoNothing((WCHAR *) pbDataOld, wszFilePath, bEnableThisBinary, &bAddToList))
  1857. {
  1858. hr = S_OK;
  1859. goto AddRemoveIISRestrictionListEntry_Exit;
  1860. }
  1861. if (bAddToList)
  1862. {
  1863. // Recalc the amount of space we'll need to add this entry into the list
  1864. dwOldByteLength = GetMultiStrSize( (WCHAR*) pbDataOld) * sizeof(WCHAR);
  1865. dwNewEntryLength = wcslen(wszFilePath) * sizeof(WCHAR);
  1866. dwNewTotalLength = dwOldByteLength + dwNewEntryLength + 2;
  1867. // Alloc enough space for the old data and the new data.
  1868. // Don't use realloc here, because for somereason it would fail in
  1869. // certain test runs.
  1870. pbDataNew = (BYTE *) GlobalAlloc(GPTR, dwNewTotalLength);
  1871. if (!pbDataNew)
  1872. {
  1873. hr = E_OUTOFMEMORY;
  1874. goto AddRemoveIISRestrictionListEntry_Exit;
  1875. }
  1876. // copy the old data...
  1877. memcpy(pbDataNew,pbDataOld,dwOldByteLength);
  1878. // append on the new data
  1879. memcpy((pbDataNew + dwOldByteLength) - 2,wszFilePath,dwNewEntryLength);
  1880. memset((pbDataNew + dwOldByteLength + dwNewEntryLength) - 2,0,4);
  1881. // free the old data
  1882. if (pbDataOld)
  1883. {
  1884. GlobalFree(pbDataOld);
  1885. pbDataOld = NULL;
  1886. }
  1887. }
  1888. else
  1889. {
  1890. dwOldByteLength = GetMultiStrSize( (WCHAR*) pbDataOld) * sizeof(WCHAR);
  1891. // Don't use realloc here, because for somereason it would fail in
  1892. // certain test runs.
  1893. pbDataNew = (BYTE *) GlobalAlloc(GPTR, dwOldByteLength);
  1894. if (!pbDataNew)
  1895. {
  1896. hr = E_OUTOFMEMORY;
  1897. goto AddRemoveIISRestrictionListEntry_Exit;
  1898. }
  1899. // copy the old data...
  1900. memcpy(pbDataNew,pbDataOld,dwOldByteLength);
  1901. // free the old data
  1902. if (pbDataOld)
  1903. {
  1904. GlobalFree(pbDataOld);
  1905. pbDataOld = NULL;
  1906. }
  1907. // remove an entry from the list
  1908. if (FALSE == RemoveWstrInMultiStr((WCHAR *) pbDataNew,wszFilePath))
  1909. {
  1910. // we were not able to find the value in the string
  1911. hr = S_OK;
  1912. goto AddRemoveIISRestrictionListEntry_Exit;
  1913. }
  1914. else
  1915. {
  1916. // keep removing till it's all gone
  1917. BOOL bRet = TRUE;
  1918. do
  1919. {
  1920. bRet = RemoveWstrInMultiStr((WCHAR *) pbDataNew,wszFilePath);
  1921. } while (bRet);
  1922. }
  1923. // other wise pbDataOld is updated with the new data
  1924. // proceed to write the new data out
  1925. }
  1926. // Write the new data out
  1927. if (bBinaryIsISAPI)
  1928. {
  1929. mr.dwMDIdentifier = MD_ISAPI_RESTRICTION_LIST;
  1930. }
  1931. else
  1932. {
  1933. mr.dwMDIdentifier = MD_CGI_RESTRICTION_LIST;
  1934. }
  1935. mr.dwMDAttributes = 0; // no need for inheritence
  1936. mr.dwMDUserType = IIS_MD_UT_SERVER;
  1937. mr.dwMDDataType = MULTISZ_METADATA;
  1938. mr.dwMDDataLen = GetMultiStrSize((WCHAR*)pbDataNew) * sizeof(WCHAR);
  1939. mr.pbMDData = reinterpret_cast<unsigned char *> (pbDataNew);
  1940. //DumpWstrInMultiStr((WCHAR *) pbDataNew);
  1941. hr = pIMSAdminBase->SetData(hMetabase, L"", &mr);
  1942. AddRemoveIISRestrictionListEntry_Exit:
  1943. if (FAILED(hr))
  1944. {
  1945. wprintf(L"Failed to %s '%s' to/from %s\r\n",
  1946. bEnableThisBinary ? L"Enable" : L"Disable",
  1947. wszFilePath,
  1948. bBinaryIsISAPI ? L"MD_ISAPI_RESTRICTION_LIST" : L"MD_CGI_RESTRICTION_LIST"
  1949. );
  1950. }
  1951. else
  1952. {
  1953. wprintf(L"Succeeded to %s '%s' to/from %s\r\n",
  1954. bEnableThisBinary ? L"Enable" : L"Disable",
  1955. wszFilePath,
  1956. bBinaryIsISAPI ? L"MD_ISAPI_RESTRICTION_LIST" : L"MD_CGI_RESTRICTION_LIST"
  1957. );
  1958. }
  1959. if (hMetabase)
  1960. {
  1961. pIMSAdminBase->CloseKey(hMetabase);
  1962. hMetabase = NULL;
  1963. }
  1964. if (pIMSAdminBase)
  1965. {
  1966. pIMSAdminBase->Release();
  1967. pIMSAdminBase = NULL;
  1968. }
  1969. if (pbDataOld)
  1970. {
  1971. GlobalFree(pbDataOld);
  1972. pbDataOld = NULL;
  1973. }
  1974. if (pbDataNew)
  1975. {
  1976. GlobalFree(pbDataNew);
  1977. pbDataNew = NULL;
  1978. }
  1979. CoUninitialize();
  1980. return hr;
  1981. }
  1982. BOOL
  1983. DeleteEntryFromMultiSZ3Pair(
  1984. LPCWSTR ptstrMultiSZ,
  1985. LPCWSTR ptstrKey
  1986. )
  1987. /*++
  1988. Routine Description:
  1989. Search for the specified key in MultiSZ key-value 3 string pairs
  1990. looks like:
  1991. 1,c:\mydir\myfilename.dll,mydescription
  1992. 1,c:\mydir\myfilename.dll,mydescription
  1993. 1,c:\mydir\myfilename.dll,mydescription
  1994. Arguments:
  1995. ptstrMultiSZ - Points to the data to be searched
  1996. ptstrKey - Specifies the key string
  1997. Return Value:
  1998. Pointer to the value string corresponding to the specified
  1999. key string; NULL if the specified key string is not found
  2000. --*/
  2001. {
  2002. LPWSTR pPointer1 = NULL;
  2003. LPWSTR pPointer2 = NULL;
  2004. LPWSTR pPointer3 = NULL;
  2005. LPWSTR pPointer4 = NULL;
  2006. LPCWSTR pPointerEnd = NULL;
  2007. pPointerEnd = GetEndOfMultiSz((LPCWSTR) ptstrMultiSZ);
  2008. // Advanced past beginning nulls if any.
  2009. while (*ptstrMultiSZ == NULL)
  2010. {
  2011. ptstrMultiSZ++;
  2012. }
  2013. // make sure 1st entry is at least a single digit
  2014. // if not, then let's skip until we find one
  2015. while (*ptstrMultiSZ != NULL)
  2016. {
  2017. if (wcslen(ptstrMultiSZ) < 2)
  2018. {
  2019. break;
  2020. }
  2021. ptstrMultiSZ += wcslen(ptstrMultiSZ) + 1;
  2022. }
  2023. while (*ptstrMultiSZ != NULL)
  2024. {
  2025. // Assign pointer to the 1st entry
  2026. pPointer1 = (LPWSTR) ptstrMultiSZ;
  2027. // Advance to the first key...
  2028. ptstrMultiSZ += wcslen(ptstrMultiSZ) + 1;
  2029. pPointer2 = (LPWSTR) ptstrMultiSZ;
  2030. if (ptstrMultiSZ && *ptstrMultiSZ)
  2031. {
  2032. ptstrMultiSZ += wcslen(ptstrMultiSZ) + 1;
  2033. pPointer3 = (LPWSTR) ptstrMultiSZ;
  2034. //
  2035. // If the current string matches the specified key string,
  2036. // then return the corresponding value string
  2037. //
  2038. if (_wcsicmp(pPointer2, ptstrKey) == 0)
  2039. {
  2040. // we found our entry, delete it and get out
  2041. // Get the beginning of the next entry..
  2042. ptstrMultiSZ += wcslen(ptstrMultiSZ) + 1;
  2043. if (*ptstrMultiSZ != NULL)
  2044. {
  2045. ULONG_PTR dwTotalSizeOfDeletion = dwTotalSizeOfDeletion = (ULONG_PTR) ptstrMultiSZ - (ULONG_PTR)pPointer1;
  2046. // erase this memory
  2047. memset(pPointer1, 0, dwTotalSizeOfDeletion);
  2048. // move trailing memory over erased memory (overwritting it)
  2049. memmove(pPointer1, ptstrMultiSZ, ((ULONG_PTR) pPointerEnd - (ULONG_PTR) ptstrMultiSZ));
  2050. // erase stuff behind it.
  2051. memset((void*) ((ULONG_PTR) pPointerEnd - (ULONG_PTR) dwTotalSizeOfDeletion), 0, dwTotalSizeOfDeletion);
  2052. }
  2053. else
  2054. {
  2055. *pPointer1 = NULL;
  2056. *pPointer1++ = NULL;
  2057. }
  2058. return TRUE;
  2059. }
  2060. //
  2061. // Otherwise, advance to the next 3 string pair
  2062. //
  2063. ptstrMultiSZ += wcslen(ptstrMultiSZ) + 1;
  2064. }
  2065. }
  2066. return FALSE;
  2067. }
  2068. // wszFilePath =
  2069. // wszDescription =
  2070. HRESULT AddRemoveIISCustomDescriptionEntry(WCHAR * wszFilePathInput,WCHAR * wszDescription,BOOL bCannotBeRemovedByUser,BOOL bAddToList)
  2071. {
  2072. HRESULT hr = E_FAIL;
  2073. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  2074. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  2075. METADATA_RECORD mr;
  2076. BYTE * pbDataOld = NULL;
  2077. BYTE * pbDataNew = NULL;
  2078. DWORD dwMDRequiredDataLen = 0;
  2079. DWORD dwNewEntryLength = 0;
  2080. DWORD dwNewTotalLength = 0;
  2081. DWORD dwOldByteLength = 0;
  2082. WCHAR * wszFilePath = NULL;
  2083. INT iFound = 0;
  2084. // Convert any env vars to hard coded paths
  2085. LPWSTR pch = wcschr( (LPWSTR) wszFilePathInput, L'%');
  2086. if (pch)
  2087. {
  2088. // determine the length of the expanded string
  2089. DWORD len = ::ExpandEnvironmentStrings(wszFilePathInput, 0, 0);
  2090. if (!len)
  2091. {
  2092. return hr;
  2093. }
  2094. wszFilePath = (WCHAR *) GlobalAlloc(GPTR, (len + 1) * sizeof(WCHAR));
  2095. DWORD len1 = ExpandEnvironmentStrings((LPWSTR) wszFilePathInput,const_cast<wchar_t*>(wszFilePath),len);
  2096. if (len1 != len)
  2097. {
  2098. if (wszFilePath)
  2099. {
  2100. GlobalFree(wszFilePath);wszFilePath = NULL;
  2101. }
  2102. return hr;
  2103. }
  2104. }
  2105. else
  2106. {
  2107. wszFilePath = wszFilePathInput;
  2108. }
  2109. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  2110. if (hr == RPC_E_CHANGED_MODE)
  2111. {
  2112. // fine. try again
  2113. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  2114. }
  2115. if (FAILED(hr))
  2116. {
  2117. return hr;
  2118. }
  2119. hr = CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase,(void **)&pIMSAdminBase);
  2120. if (FAILED(hr))
  2121. {
  2122. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2123. }
  2124. // open the specified metabase node
  2125. hr = pIMSAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  2126. L"LM/W3SVC",
  2127. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  2128. REASONABLE_TIMEOUT,
  2129. &hMetabase);
  2130. if (FAILED(hr))
  2131. {
  2132. hMetabase = NULL;
  2133. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2134. }
  2135. mr.dwMDIdentifier = MD_RESTRICTION_LIST_CUSTOM_DESC;
  2136. mr.dwMDAttributes = 0; // no need for inheritence
  2137. mr.dwMDUserType = IIS_MD_UT_SERVER;
  2138. mr.dwMDDataType = MULTISZ_METADATA;
  2139. mr.dwMDDataLen = 0;
  2140. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataOld);
  2141. // first we need to figure out how much space we need
  2142. hr = pIMSAdminBase->GetData(hMetabase, L"", &mr, &dwMDRequiredDataLen);
  2143. if(FAILED(hr))
  2144. {
  2145. // if there isn't a value there that we need to update
  2146. // then create one
  2147. if( hr == MD_ERROR_DATA_NOT_FOUND || HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND )
  2148. {
  2149. if (bAddToList)
  2150. {
  2151. // make enough room for the new entry...
  2152. dwNewTotalLength = 2 * sizeof(WCHAR); // char + 1null
  2153. dwNewTotalLength = dwNewTotalLength + ((wcslen(wszFilePathInput) + 1) * sizeof(WCHAR)); // string + 1 null
  2154. dwNewTotalLength = dwNewTotalLength + ((wcslen(wszDescription) + 2) * sizeof(WCHAR)); // string + 1 null and 1 ending null
  2155. pbDataNew = (BYTE *) GlobalAlloc(GPTR, dwNewTotalLength);
  2156. if (!pbDataNew)
  2157. {
  2158. hr = E_OUTOFMEMORY;
  2159. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2160. }
  2161. // set to empty
  2162. memset(pbDataNew, 0, dwNewTotalLength);
  2163. // create the entry
  2164. if (bCannotBeRemovedByUser)
  2165. {
  2166. memcpy(pbDataNew,L"1",sizeof(WCHAR));
  2167. }
  2168. else
  2169. {
  2170. memcpy(pbDataNew,L"0",sizeof(WCHAR));
  2171. }
  2172. // append on the new data
  2173. dwNewEntryLength = ((wcslen(wszFilePathInput) + 1) * sizeof(WCHAR));
  2174. memcpy((pbDataNew + (sizeof(WCHAR) * 2)),wszFilePath, dwNewEntryLength);
  2175. memcpy((pbDataNew + (sizeof(WCHAR) * 2) + dwNewEntryLength),wszDescription,((wcslen(wszDescription) + 1) * sizeof(WCHAR)));
  2176. memset((pbDataNew + (sizeof(WCHAR) * 2) + dwNewEntryLength + ((wcslen(wszDescription) + 1) * sizeof(WCHAR))),0,2);
  2177. mr.dwMDIdentifier = MD_RESTRICTION_LIST_CUSTOM_DESC;
  2178. mr.dwMDAttributes = 0; // no need for inheritence
  2179. mr.dwMDUserType = IIS_MD_UT_SERVER;
  2180. mr.dwMDDataType = MULTISZ_METADATA;
  2181. mr.dwMDDataLen = GetMultiStrSize((WCHAR*) pbDataNew) * sizeof(WCHAR);
  2182. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataNew);
  2183. // Write value
  2184. hr = pIMSAdminBase->SetData(hMetabase, L"", &mr);
  2185. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2186. }
  2187. else
  2188. {
  2189. // we don't need to do anything else
  2190. // there are no entries, so there is nothing to remove
  2191. hr = S_OK;
  2192. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2193. }
  2194. }
  2195. else
  2196. {
  2197. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2198. }
  2199. }
  2200. pbDataOld = (BYTE *) GlobalAlloc(GPTR, dwMDRequiredDataLen);
  2201. if (!pbDataOld)
  2202. {
  2203. hr = E_OUTOFMEMORY;
  2204. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2205. }
  2206. // do the real call to get the data from the metabase
  2207. mr.dwMDDataLen = dwMDRequiredDataLen;
  2208. mr.pbMDData = reinterpret_cast<unsigned char *>(pbDataOld);
  2209. hr = pIMSAdminBase->GetData(hMetabase, L"", &mr, &dwMDRequiredDataLen);
  2210. if (FAILED(hr))
  2211. {
  2212. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2213. }
  2214. iFound = FindWstrInMultiStrSpecial((WCHAR *) pbDataOld,wszFilePath,NULL);
  2215. if (0 == iFound)
  2216. {
  2217. if (!bAddToList)
  2218. {
  2219. // the entry doesn't exist
  2220. // so we don't have to remove it
  2221. hr = S_OK;
  2222. //wprintf(L"found = 0, skip remove!!\r\n");
  2223. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2224. }
  2225. // otherwise, proceed to add the entry....
  2226. }
  2227. else if (2 == iFound)
  2228. {
  2229. if (bAddToList)
  2230. {
  2231. // there already is an entry there
  2232. // so we can exit and don't have to do anything
  2233. //wprintf(L"found = 2, skip adding!!\r\n");
  2234. hr = S_OK;
  2235. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2236. }
  2237. // otherwise, proceed to remove the entry....
  2238. }
  2239. else
  2240. {
  2241. // we must have a 1
  2242. // which means we found the filename but the description is different...
  2243. //wprintf(L"%s found only filename!!! pbDataOld=%p\n",wszFilePath,pbDataOld);
  2244. // proceed to update the entry
  2245. // Write some code to update the description...
  2246. }
  2247. if (bAddToList)
  2248. {
  2249. //wprintf(L"doing add!\r\n");
  2250. DWORD dwTempLen = 0;
  2251. // Recalc the amount of space we'll need to add this entry into the list
  2252. dwOldByteLength = GetMultiStrSize( (WCHAR*) pbDataOld) * sizeof(WCHAR);
  2253. dwNewEntryLength = (
  2254. (sizeof(WCHAR) * 2) +
  2255. ((wcslen(wszFilePath) + 1) * sizeof(WCHAR)) +
  2256. ((wcslen(wszDescription) + 1) * sizeof(WCHAR))
  2257. );
  2258. dwNewTotalLength = dwOldByteLength + dwNewEntryLength + (sizeof(WCHAR)); // string + 1 null and 1 ending null
  2259. // Alloc enough space for the old data and the new data.
  2260. // Don't use realloc here, because for somereason it would fail in
  2261. // certain test runs.
  2262. pbDataNew = (BYTE *) GlobalAlloc(GPTR, dwNewTotalLength);
  2263. if (!pbDataNew)
  2264. {
  2265. hr = E_OUTOFMEMORY;
  2266. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2267. }
  2268. // set to empty
  2269. memset(pbDataNew, 0, dwNewTotalLength);
  2270. // copy the old data...
  2271. memcpy(pbDataNew,pbDataOld,dwOldByteLength);
  2272. // append entry #1 on to the new data -- backup over the double nulls
  2273. dwTempLen = dwOldByteLength - 2;
  2274. if (bCannotBeRemovedByUser)
  2275. {memcpy((pbDataNew + dwTempLen),L"1",sizeof(WCHAR));}
  2276. else
  2277. {memcpy((pbDataNew + dwTempLen),L"0",sizeof(WCHAR));}
  2278. memset((pbDataNew + dwTempLen + sizeof(WCHAR)),0,2);
  2279. dwTempLen = dwTempLen + sizeof(WCHAR) + sizeof(WCHAR);
  2280. // append entry #2
  2281. dwNewEntryLength = ((wcslen(wszFilePath) + 1) * sizeof(WCHAR));
  2282. memcpy((pbDataNew + dwTempLen),wszFilePath,dwNewEntryLength);
  2283. dwTempLen = dwTempLen + dwNewEntryLength;
  2284. // append entry #3
  2285. dwNewEntryLength = ((wcslen(wszDescription) + 1) * sizeof(WCHAR));
  2286. memcpy((pbDataNew + dwTempLen),wszDescription,dwNewEntryLength);
  2287. dwTempLen = dwTempLen + dwNewEntryLength;
  2288. // make sure it ends with double nulls
  2289. memset((pbDataNew + dwTempLen),0,4);
  2290. // free the old data
  2291. if (pbDataOld)
  2292. {
  2293. GlobalFree(pbDataOld);
  2294. pbDataOld = NULL;
  2295. }
  2296. }
  2297. else
  2298. {
  2299. dwOldByteLength = GetMultiStrSize( (WCHAR*) pbDataOld) * sizeof(WCHAR);
  2300. // Don't use realloc here, because for somereason it would fail in
  2301. // certain test runs.
  2302. pbDataNew = (BYTE *) GlobalAlloc(GPTR, dwOldByteLength);
  2303. if (!pbDataNew)
  2304. {
  2305. hr = E_OUTOFMEMORY;
  2306. goto AddRemoveIISCustomDescriptionEntry_Exit;
  2307. }
  2308. // copy the old data...
  2309. memcpy(pbDataNew,pbDataOld,dwOldByteLength);
  2310. // free the old data
  2311. if (pbDataOld)
  2312. {
  2313. GlobalFree(pbDataOld);
  2314. pbDataOld = NULL;
  2315. }
  2316. BOOL bDeletedSomething = FALSE;
  2317. do
  2318. {
  2319. bDeletedSomething = DeleteEntryFromMultiSZ3Pair((LPCWSTR) pbDataNew,wszFilePath);
  2320. } while (bDeletedSomething);
  2321. // other wise pbDataOld is updated with the new data
  2322. // proceed to write the new data out
  2323. }
  2324. // Write the new data out
  2325. mr.dwMDIdentifier = MD_RESTRICTION_LIST_CUSTOM_DESC;
  2326. mr.dwMDAttributes = 0; // no need for inheritence
  2327. mr.dwMDUserType = IIS_MD_UT_SERVER;
  2328. mr.dwMDDataType = MULTISZ_METADATA;
  2329. mr.dwMDDataLen = GetMultiStrSize((WCHAR*)pbDataNew) * sizeof(WCHAR);
  2330. mr.pbMDData = reinterpret_cast<unsigned char *> (pbDataNew);
  2331. DumpWstrInMultiStr((WCHAR *) pbDataNew);
  2332. hr = pIMSAdminBase->SetData(hMetabase, L"", &mr);
  2333. AddRemoveIISCustomDescriptionEntry_Exit:
  2334. if (FAILED(hr))
  2335. {
  2336. wprintf(L"Failed to %s '%s'\r\n",
  2337. bAddToList ? L"Add" : L"Remove",
  2338. wszFilePath
  2339. );
  2340. }
  2341. else
  2342. {
  2343. wprintf(L"Succeeded to %s '%s'\r\n",
  2344. bAddToList ? L"Add" : L"Remove",
  2345. wszFilePath
  2346. );
  2347. }
  2348. if (hMetabase)
  2349. {
  2350. pIMSAdminBase->CloseKey(hMetabase);
  2351. hMetabase = NULL;
  2352. }
  2353. if (pIMSAdminBase)
  2354. {
  2355. pIMSAdminBase->Release();
  2356. pIMSAdminBase = NULL;
  2357. }
  2358. if (pbDataOld)
  2359. {
  2360. GlobalFree(pbDataOld);
  2361. pbDataOld = NULL;
  2362. }
  2363. if (pbDataNew)
  2364. {
  2365. GlobalFree(pbDataNew);
  2366. pbDataNew = NULL;
  2367. }
  2368. CoUninitialize();
  2369. return hr;
  2370. }
  2371. BOOL OpenMetabaseAndDoExport(void)
  2372. {
  2373. BOOL fRet = FALSE;
  2374. HRESULT hr;
  2375. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  2376. IMSAdminBase2 *pIMSAdminBase2 = NULL; // Metabase interface pointer
  2377. WCHAR wszExportPassword[_MAX_PATH];
  2378. WCHAR wszExportFileName[_MAX_PATH];
  2379. WCHAR wszMetabaseNodeToExport[_MAX_PATH];
  2380. wcscpy(wszExportFileName,L"c:\\TestExport.xml");
  2381. wcscpy(wszExportPassword,L"TestPassword");
  2382. wcscpy(wszMetabaseNodeToExport,L"/LM/W3SVC/1");
  2383. if (FAILED (hr = CoInitializeEx( NULL, COINIT_MULTITHREADED )))
  2384. {
  2385. if (FAILED (hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )))
  2386. {
  2387. return FALSE;
  2388. }
  2389. }
  2390. if (FAILED (hr = ::CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase,(void **)&pIMSAdminBase)))
  2391. {
  2392. goto OpenMetabaseAndDoExport_Exit;
  2393. }
  2394. if (SUCCEEDED(hr = pIMSAdminBase->QueryInterface(IID_IMSAdminBase2, (void **)&pIMSAdminBase2)))
  2395. {
  2396. SetBlanket(pIMSAdminBase2);
  2397. hr = pIMSAdminBase2->Export(wszExportPassword,wszExportFileName,wszMetabaseNodeToExport,MD_EXPORT_INHERITED);
  2398. pIMSAdminBase2->Release();
  2399. pIMSAdminBase2 = NULL;
  2400. }
  2401. if (FAILED(hr))
  2402. {
  2403. wprintf(L"Failed to Export to file:%s,err=0x%x\r\n",wszExportFileName,hr);
  2404. }
  2405. else
  2406. {
  2407. wprintf(L"Succeeded to Export to file:%s\r\n",wszExportFileName);
  2408. fRet = TRUE;
  2409. }
  2410. OpenMetabaseAndDoExport_Exit:
  2411. if (pIMSAdminBase)
  2412. {
  2413. pIMSAdminBase->Release();
  2414. pIMSAdminBase = NULL;
  2415. }
  2416. CoUninitialize();
  2417. return fRet;
  2418. }
  2419. BOOL OpenMetabaseAndDoImport(void)
  2420. {
  2421. BOOL fRet = FALSE;
  2422. HRESULT hr;
  2423. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  2424. IMSAdminBase2 *pIMSAdminBase2 = NULL; // Metabase interface pointer
  2425. WCHAR wszExportPassword[_MAX_PATH];
  2426. WCHAR wszImportFileName[_MAX_PATH];
  2427. WCHAR wszMetabaseNode1[_MAX_PATH];
  2428. WCHAR wszMetabaseNode2[_MAX_PATH];
  2429. wcscpy(wszImportFileName,L"c:\\TestExport.xml");
  2430. wcscpy(wszExportPassword,L"TestPassword");
  2431. wcscpy(wszMetabaseNode1,L"/LM/W3SVC/1");
  2432. wcscpy(wszMetabaseNode2,L"/LM/W3SVC/100");
  2433. if (FAILED (hr = CoInitializeEx( NULL, COINIT_MULTITHREADED )))
  2434. {
  2435. if (FAILED (hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )))
  2436. {
  2437. return FALSE;
  2438. }
  2439. }
  2440. if (FAILED (hr = ::CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase,(void **)&pIMSAdminBase)))
  2441. {
  2442. goto OpenMetabaseAndDoExport_Exit;
  2443. }
  2444. if (SUCCEEDED(hr = pIMSAdminBase->QueryInterface(IID_IMSAdminBase2, (void **)&pIMSAdminBase2)))
  2445. {
  2446. SetBlanket(pIMSAdminBase2);
  2447. hr = pIMSAdminBase2->Import(wszExportPassword,wszImportFileName,wszMetabaseNode1,wszMetabaseNode2,MD_IMPORT_NODE_ONLY);
  2448. pIMSAdminBase2->Release();
  2449. pIMSAdminBase2 = NULL;
  2450. }
  2451. if (FAILED(hr))
  2452. {
  2453. wprintf(L"Failed to Export to file:%s,err=0x%x\r\n",wszImportFileName,hr);
  2454. }
  2455. else
  2456. {
  2457. wprintf(L"Succeeded to Export to file:%s\r\n",wszImportFileName);
  2458. fRet = TRUE;
  2459. }
  2460. OpenMetabaseAndDoExport_Exit:
  2461. if (pIMSAdminBase)
  2462. {
  2463. pIMSAdminBase->Release();
  2464. pIMSAdminBase = NULL;
  2465. }
  2466. CoUninitialize();
  2467. return fRet;
  2468. }
  2469. BOOL GetIISVersion_Internal_iiscnfgp(IMSAdminBase *pIMSAdminBase,DWORD * dwReturnedMajorVersion,DWORD * dwReturnedMinorVersion)
  2470. {
  2471. HRESULT hr;
  2472. BOOL fRet = FALSE;
  2473. METADATA_HANDLE hMetabase = NULL; // handle to metabase
  2474. METADATA_RECORD mr;
  2475. WCHAR szTmpData[MAX_PATH];
  2476. DWORD dwMDRequiredDataLen;
  2477. // open key
  2478. hr = pIMSAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  2479. L"/LM/W3SVC/Info",
  2480. METADATA_PERMISSION_READ,
  2481. REASONABLE_TIMEOUT,
  2482. &hMetabase);
  2483. if( FAILED( hr ))
  2484. {
  2485. return FALSE;
  2486. }
  2487. //#define MD_SERVER_VERSION_MAJOR (IIS_MD_SERVER_BASE+101 )
  2488. //#define MD_SERVER_VERSION_MINOR (IIS_MD_SERVER_BASE+102 )
  2489. DWORD pdwValue = 0;
  2490. mr.dwMDIdentifier = MD_SERVER_VERSION_MAJOR;
  2491. mr.dwMDAttributes = 0;
  2492. mr.dwMDUserType = IIS_MD_UT_SERVER;
  2493. mr.dwMDDataType = DWORD_METADATA;
  2494. mr.dwMDDataLen = sizeof(pdwValue);
  2495. mr.pbMDData = reinterpret_cast<unsigned char *>(&pdwValue);
  2496. pdwValue = 0;
  2497. dwMDRequiredDataLen = 0;
  2498. *dwReturnedMajorVersion = 0;
  2499. hr = pIMSAdminBase->GetData( hMetabase, L"", &mr, &dwMDRequiredDataLen );
  2500. if( SUCCEEDED( hr ))
  2501. {
  2502. *dwReturnedMajorVersion = pdwValue;
  2503. }
  2504. mr.dwMDIdentifier = MD_SERVER_VERSION_MINOR;
  2505. mr.pbMDData = reinterpret_cast<unsigned char *>(&pdwValue);
  2506. pdwValue = 0;
  2507. dwMDRequiredDataLen = 0;
  2508. *dwReturnedMinorVersion = 0;
  2509. hr = pIMSAdminBase->GetData( hMetabase, L"", &mr, &dwMDRequiredDataLen );
  2510. if( SUCCEEDED( hr ))
  2511. {
  2512. *dwReturnedMinorVersion = pdwValue;
  2513. }
  2514. WCHAR wszPrintString[MAX_PATH];
  2515. wsprintf(wszPrintString,L"MajorVer=%d,MinorVer=%d\n", *dwReturnedMajorVersion, *dwReturnedMinorVersion);
  2516. wprintf(wszPrintString);
  2517. pIMSAdminBase->CloseKey( hMetabase );
  2518. if( SUCCEEDED( hr ))
  2519. {
  2520. fRet = TRUE;
  2521. }
  2522. pIMSAdminBase->CloseKey( hMetabase );
  2523. return fRet;
  2524. }
  2525. BOOL OpenMetabaseAndGetVersion()
  2526. {
  2527. BOOL fRet = FALSE;
  2528. HRESULT hr;
  2529. IMSAdminBase *pIMSAdminBase = NULL; // Metabase interface pointer
  2530. if( FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )) ||
  2531. FAILED (::CoCreateInstance(CLSID_MSAdminBase,
  2532. NULL,
  2533. CLSCTX_ALL,
  2534. IID_IMSAdminBase,
  2535. (void **)&pIMSAdminBase)))
  2536. {
  2537. return FALSE;
  2538. }
  2539. DWORD dwMajorVersion,dwMinorVersion=0;
  2540. GetIISVersion_Internal_iiscnfgp(pIMSAdminBase,&dwMajorVersion,&dwMinorVersion);
  2541. if (pIMSAdminBase)
  2542. {
  2543. pIMSAdminBase->Release();
  2544. pIMSAdminBase = NULL;
  2545. }
  2546. CoUninitialize();
  2547. return fRet;
  2548. }
  2549. HRESULT RemoteOpenMetabaseAndCallExport(
  2550. const WCHAR *pcszMachineName,
  2551. const WCHAR *pcszUserName,
  2552. const WCHAR *pcszDomain,
  2553. const WCHAR *pcszPassword
  2554. )
  2555. {
  2556. HRESULT hr = E_FAIL;
  2557. IMSAdminBase *pIMSAdminBase = NULL;
  2558. IMSAdminBase2 *pIMSAdminBase2 = NULL;
  2559. COSERVERINFO svrInfo;
  2560. COAUTHINFO AuthInfo;
  2561. COAUTHIDENTITY AuthId;
  2562. ZeroMemory(&svrInfo, sizeof(COSERVERINFO));
  2563. ZeroMemory(&AuthInfo, sizeof(COAUTHINFO));
  2564. ZeroMemory(&AuthId, sizeof(COAUTHIDENTITY));
  2565. AuthId.User = (USHORT*) pcszUserName;
  2566. AuthId.UserLength = wcslen (pcszUserName);
  2567. AuthId.Domain = (USHORT*)pcszDomain;
  2568. AuthId.DomainLength = wcslen (pcszDomain);
  2569. AuthId.Password = (USHORT*)pcszPassword;
  2570. AuthId.PasswordLength = wcslen (pcszPassword);
  2571. AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  2572. AuthInfo.dwAuthnSvc = RPC_C_AUTHN_WINNT;
  2573. AuthInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
  2574. AuthInfo.pwszServerPrincName = NULL;
  2575. // RPC_C_AUTHN_LEVEL_DEFAULT 0
  2576. // RPC_C_AUTHN_LEVEL_NONE 1
  2577. // RPC_C_AUTHN_LEVEL_CONNECT 2
  2578. // RPC_C_AUTHN_LEVEL_CALL 3
  2579. // RPC_C_AUTHN_LEVEL_PKT 4
  2580. // RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5
  2581. // RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6
  2582. //AuthInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  2583. AuthInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
  2584. AuthInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
  2585. AuthInfo.pAuthIdentityData = &AuthId;
  2586. AuthInfo.dwCapabilities = EOAC_NONE;
  2587. svrInfo.dwReserved1 = 0;
  2588. svrInfo.dwReserved2 = 0;
  2589. svrInfo.pwszName = (LPWSTR) pcszMachineName;
  2590. svrInfo.pAuthInfo = &AuthInfo;
  2591. if(FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))
  2592. {
  2593. if(FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
  2594. {
  2595. wprintf(L"CoInitializeEx failed:hr=0x%x\r\n",hr);
  2596. return hr;
  2597. }
  2598. }
  2599. MULTI_QI res[1] =
  2600. {
  2601. {&IID_IMSAdminBase, NULL, 0}
  2602. };
  2603. // CLSCTX_INPROC_SERVER = 1,
  2604. // CLSCTX_INPROC_HANDLER = 2,
  2605. // CLSCTX_LOCAL_SERVER = 4
  2606. // CLSCTX_REMOTE_SERVER = 16
  2607. // CLSCTX_NO_CODE_DOWNLOAD = 400
  2608. // CLSCTX_NO_FAILURE_LOG = 4000
  2609. // #define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)
  2610. // #define CLSCTX_ALL (CLSCTX_INPROC_HANDLER | CLSCTX_SERVER)
  2611. if (FAILED(hr = CoCreateInstanceEx(CLSID_MSAdminBase,NULL,CLSCTX_ALL,&svrInfo,1,res)))
  2612. {
  2613. wprintf(L"CoCreateInstanceEx failed:hr=0x%x\r\n",hr);
  2614. goto RemoteOpenMetabaseAndCallExport_Exit;
  2615. }
  2616. pIMSAdminBase = (IMSAdminBase *)res[0].pItf;
  2617. {
  2618. hr = ::CoSetProxyBlanket(
  2619. pIMSAdminBase,
  2620. AuthInfo.dwAuthnSvc,
  2621. AuthInfo.dwAuthzSvc,
  2622. AuthInfo.pwszServerPrincName,
  2623. AuthInfo.dwAuthnLevel,
  2624. AuthInfo.dwImpersonationLevel,
  2625. AuthInfo.pAuthIdentityData,
  2626. AuthInfo.dwCapabilities
  2627. );
  2628. if (FAILED(hr))
  2629. {
  2630. wprintf(L"CoSetProxyBlanket failed:hr=0x%x\r\n",hr);
  2631. goto RemoteOpenMetabaseAndCallExport_Exit;
  2632. }
  2633. // There is a remote IUnknown interface that lurks behind IUnknown.
  2634. // If that is not set, then the Release call can return access denied.
  2635. IUnknown * pUnk = NULL;
  2636. hr = pIMSAdminBase->QueryInterface(IID_IUnknown, (void **)&pUnk);
  2637. if(FAILED(hr))
  2638. {
  2639. wprintf(L"QueryInterface failed:hr=0x%x\r\n",hr);
  2640. return hr;
  2641. }
  2642. hr = ::CoSetProxyBlanket(
  2643. pUnk,
  2644. AuthInfo.dwAuthnSvc,
  2645. AuthInfo.dwAuthzSvc,
  2646. AuthInfo.pwszServerPrincName,
  2647. AuthInfo.dwAuthnLevel,
  2648. AuthInfo.dwImpersonationLevel,
  2649. AuthInfo.pAuthIdentityData,
  2650. AuthInfo.dwCapabilities
  2651. );
  2652. if (FAILED(hr))
  2653. {
  2654. wprintf(L"CoSetProxyBlanket2 failed:hr=0x%x\r\n",hr);
  2655. goto RemoteOpenMetabaseAndCallExport_Exit;
  2656. }
  2657. pUnk->Release();pUnk = NULL;
  2658. }
  2659. if (FAILED(hr = pIMSAdminBase->QueryInterface(IID_IMSAdminBase2, (void **)&pIMSAdminBase2)))
  2660. {
  2661. wprintf(L"QueryInterface2 failed:hr=0x%x\r\n",hr);
  2662. goto RemoteOpenMetabaseAndCallExport_Exit;
  2663. }
  2664. hr = ::CoSetProxyBlanket(
  2665. pIMSAdminBase2,
  2666. AuthInfo.dwAuthnSvc,
  2667. AuthInfo.dwAuthzSvc,
  2668. AuthInfo.pwszServerPrincName,
  2669. AuthInfo.dwAuthnLevel,
  2670. AuthInfo.dwImpersonationLevel,
  2671. AuthInfo.pAuthIdentityData,
  2672. AuthInfo.dwCapabilities
  2673. );
  2674. if (FAILED(hr))
  2675. {
  2676. wprintf(L"CoSetProxyBlanket3 failed:hr=0x%x\r\n",hr);
  2677. goto RemoteOpenMetabaseAndCallExport_Exit;
  2678. }
  2679. hr = pIMSAdminBase2->Export(L"testing",L"c:\\testing.xml333",L"LM/W3SVC/1",0);
  2680. if (FAILED(hr))
  2681. {
  2682. wprintf(L"pIMSAdminBase2->Export failed:ret=0x%x\r\n",hr);
  2683. }
  2684. RemoteOpenMetabaseAndCallExport_Exit:
  2685. if (SUCCEEDED(hr))
  2686. {
  2687. wprintf(L"RemoteOpenMetabaseAndCallExport:SUCCEEDED!!!! :hr=0x%x\r\n",hr);
  2688. }
  2689. if (pIMSAdminBase2)
  2690. {
  2691. pIMSAdminBase2->Release();
  2692. pIMSAdminBase2 = NULL;
  2693. }
  2694. if (pIMSAdminBase)
  2695. {
  2696. pIMSAdminBase->Release();
  2697. pIMSAdminBase = NULL;
  2698. }
  2699. CoUninitialize();
  2700. return hr;
  2701. }