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.

3757 lines
116 KiB

  1. //***************************************************************
  2. // IISSCO50.cpp : Implementation of CIISSCO50
  3. // Author: Russ Gibfried
  4. //***************************************************************
  5. #include "stdafx.h"
  6. #include "IISSCOv50.h"
  7. #include "IISSCO50.h"
  8. #include "macrohelpers.h"
  9. #include "MessageFile\message.h"
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CIISSCO50
  12. // Provider Action handlers should be implemented here with the following prototypes:
  13. // HRESULT CIISSCO50::Action();
  14. // HRESULT CIISSCO50::ActionRollback();
  15. HRESULT CIISSCO50::FinalConstruct( )
  16. {
  17. HRESULT hr = S_OK;
  18. LONG lRes;
  19. HKEY hkey = NULL;
  20. WCHAR szLibReg[1024];
  21. DWORD dwPathSize = 0;
  22. // Open the registry key where IISScoMessageFile.dll (in EventLog)
  23. lRes = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  24. L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\IISSCOv50",
  25. 0, KEY_ALL_ACCESS, &hkey );
  26. if (lRes != ERROR_SUCCESS)
  27. goto LocalCleanup;
  28. // Get the Path size of EventMessageFile.
  29. lRes = RegQueryValueEx( hkey, L"EventMessageFile", NULL,
  30. NULL, NULL, &dwPathSize );
  31. if (lRes != ERROR_SUCCESS)
  32. goto LocalCleanup;
  33. // Get the value of EventMessageFile. This is set when IISScoMessageFile.dll is registered
  34. lRes = RegQueryValueEx( hkey, L"EventMessageFile", NULL,
  35. NULL, (LPBYTE)szLibReg, &dwPathSize );
  36. if (lRes != ERROR_SUCCESS)
  37. goto LocalCleanup;
  38. RegCloseKey( hkey );
  39. g_ErrorModule = LoadLibrary( szLibReg );
  40. if (g_ErrorModule == NULL)
  41. {
  42. hr = E_OUTOFMEMORY;
  43. }
  44. return hr;
  45. LocalCleanup:
  46. RegCloseKey( hkey );
  47. return E_FAIL;
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // CIISSCO50::CreateWebSite_Execute
  51. // Author: Russ Gibfried
  52. // Params: [in] none
  53. // [out] none
  54. // Purpose: Called by MAPS framework when is encounters an action
  55. // tag: CreateWebSite. Code creates and IIS 5 web site
  56. //
  57. //-------------------------------------------------------------
  58. HRESULT CIISSCO50::CreateWebSite_Execute( IXMLDOMNode *pXMLNode )
  59. {
  60. TRACE_ENTER(L"CIISSCO50::CreateWebSite");
  61. CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
  62. CComBSTR bstrRoot; // root directory path: c:/inetpub
  63. CComBSTR bstrServer; // Server name; localhost if black
  64. CComBSTR bstrSiteName; // site name; www.mysite.com
  65. CComBSTR bstrHost; // Web Hostname
  66. CComBSTR bstrPort; // Web port number
  67. CComBSTR bstrIP; // Web IP address
  68. CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
  69. CComBSTR bServerNumber; // WebSite number: 3
  70. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  71. CComBSTR bstrStart; // Start site when done? TRUE/FALSE
  72. CComBSTR bstrConfigPath; // Created sites ADsPath: /W3SVC/3
  73. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  74. HRESULT hr = S_OK;
  75. // Get node in format: <executeData><Website number=''><Root />...
  76. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  77. // Debug code to view passed in Node
  78. CComBSTR bstrDebug;
  79. hr = pNode->get_xml(&bstrDebug);
  80. ATLTRACE(_T("\t>>> xml = : %ls\n"), bstrDebug.m_str);
  81. // Get properties from XML
  82. hr = GetInputAttr(pNode, L"./Website", L"number", bServerNumber);
  83. hr = GetInputParam(pNode,L"./Website/Root", bstrRoot);
  84. hr = GetInputParam(pNode,L"./Website/Server", bstrServer);
  85. hr = GetInputParam(pNode,L"./Website/SiteName", bstrSiteName);
  86. hr = GetInputParam(pNode,L"./Website/HostName", bstrHost);
  87. hr = GetInputParam(pNode,L"./Website/PortNumber", bstrPort);
  88. hr = GetInputParam(pNode,L"./Website/IPAddress", bstrIP);
  89. hr = GetInputParam(pNode,L"./Website/StartOnCreate", bstrStart);
  90. //hr = GetInputParam(pNode,L"./Website/FilePermissions", bFilePermissions);
  91. // Create a IIS metabase path. ex. IIS://localhost/W3SVC
  92. bWebADsPath = IIS_PREFIX;
  93. if ( bstrServer.Length() == 0 )
  94. bstrServer = IIS_LOCALHOST;
  95. bWebADsPath.AppendBSTR(bstrServer);
  96. bWebADsPath.Append(IIS_W3SVC);
  97. // Step .5: If port number missing, set to default (ie, 80)
  98. if ( bstrPort.Length() == 0 )
  99. bstrPort = IIS_DEFAULT_WEB_PORT;
  100. if ( IsPositiveInteger(bstrPort) )
  101. {
  102. // Step 1: Create the ServerBinding string then check bindings to make sure
  103. // there is not a duplicate server
  104. hr = CreateBindingString(bstrIP, bstrPort, bstrHost, bstrSBindings);
  105. hr = CheckBindings(bWebADsPath, bstrSBindings);
  106. if (SUCCEEDED(hr) )
  107. {
  108. // Step 2: Get Next available Server Number
  109. if ( bServerNumber.Length() == 0 )
  110. hr = GetNextIndex(bWebADsPath,bServerNumber);
  111. // Step 3: Create the Web Site on given path, ServerNumber.
  112. if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISWEBSERVER,bWebADsPath, bServerNumber, bstrConfigPath);
  113. IIsScoLogFailure();
  114. // Step 4: Create a Virtual directory on new IIsWebServer configPath
  115. if (SUCCEEDED(hr))
  116. {
  117. CComBSTR bstrVDirAdsPath;
  118. hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
  119. IIsScoLogFailure();
  120. // Step 5: set each property; ie, server bindings
  121. // Bind to ADs object
  122. CComPtr<IADs> pADs;
  123. if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
  124. if ( FAILED(hr) )
  125. {
  126. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  127. IIsScoLogFailure();
  128. }
  129. // Set "ServerComment" property
  130. if (SUCCEEDED(hr) && bstrSiteName.Length() > 0 )
  131. {
  132. hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
  133. IIsScoLogFailure();
  134. }
  135. // Set "ServerBindings" property
  136. if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
  137. IIsScoLogFailure();
  138. // Step 6: Start Server if required IIS_FALSE
  139. bstrStart.ToUpper();
  140. if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
  141. {
  142. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
  143. IIsScoLogFailure();
  144. hr = IIsServerAction(bstrConfigPath,start);
  145. IIsScoLogFailure();
  146. }
  147. else
  148. {
  149. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
  150. IIsScoLogFailure();
  151. }
  152. // Step 7: write output to ConfigPath node <ConfigPath>/W3SVC/n</ConfigPath>
  153. if (SUCCEEDED(hr) )
  154. {
  155. CComBSTR bstrXML1 = IIS_W3SVC;
  156. bstrXML1.Append(L"/");
  157. bstrXML1.AppendBSTR(bServerNumber.m_str);
  158. // Helper function to write to DOM
  159. hr = PutElement(pNode, L"./Website/ConfigPath", bstrXML1.m_str);
  160. IIsScoLogFailure();
  161. }
  162. // If there is a failure, then deleted the web site created in step 3
  163. else
  164. {
  165. // First delete any webseites that were created in the method. Do this here because a RollBack
  166. // will only get called on a completed previous <step>, not a failed step.
  167. DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
  168. }
  169. } // end if Step 4
  170. } // end if 'CheckBindings'
  171. }
  172. else
  173. {
  174. hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
  175. }
  176. // If there is a failure.
  177. if ( FAILED(hr) )
  178. {
  179. // Log failure.
  180. IIsScoLogFailure();
  181. }
  182. else
  183. {
  184. // WebSite successfully created. Set Rollback data incase another step fails
  185. // a a ROllBack is initiated.
  186. CComVariant varData1(bWebADsPath);
  187. CComVariant varData2(bServerNumber);
  188. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
  189. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_SERVERNUMBER, varData2);
  190. }
  191. TRACE_EXIT(L"CIISSCO50::CreateWebSite");
  192. return hr;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////
  195. // CIISSCO50::CreateWebSite_Rollback
  196. // Author: Russ Gibfried
  197. // Params: [in] none
  198. // [out] none
  199. // Purpose: Called by MAPS framework when is encounters a failure during
  200. // 'CreateWebSite'. The Rollback deletes the WebSite if it exists.
  201. //-------------------------------------------------------------
  202. HRESULT CIISSCO50::CreateWebSite_Rollback( IXMLDOMNode *pXMLNode )
  203. {
  204. TRACE_ENTER(L"CIISSCO50::CreateWebSiteRollback");
  205. HRESULT hr = S_OK;
  206. CComBSTR bWebADsPath; // AdsPath: IIS://server/W3SVC
  207. CComBSTR bServerNumber; // Web server number
  208. CComBSTR bstrConfigPath; // Complete ADsPath to check: IIS://localhost/W3SVC/1
  209. CComVariant varWebADsPath;
  210. CComVariant varServerNumber;
  211. // Read ADsWebPath and ServerNumber to form: IIS://localhost/W3SVC/1
  212. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varWebADsPath);
  213. if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_SERVERNUMBER, &varServerNumber);
  214. if (SUCCEEDED(hr) )
  215. {
  216. bServerNumber = varServerNumber.bstrVal;
  217. bWebADsPath = varWebADsPath.bstrVal;
  218. if ( bServerNumber.Length() > 0 )
  219. {
  220. bstrConfigPath = bWebADsPath.Copy();
  221. bstrConfigPath.Append(L"/");
  222. bstrConfigPath.AppendBSTR(bServerNumber.m_str);
  223. // Step 1: ShutDown Server
  224. hr = IIsServerAction(bstrConfigPath,stop);
  225. // Step 2: Delete the server
  226. if (SUCCEEDED(hr) ) hr = DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
  227. IIsScoLogFailure();
  228. }
  229. else
  230. {
  231. hr = E_SCO_IIS_INVALID_INDEX;
  232. }
  233. }
  234. else
  235. {
  236. hr = E_SCO_IIS_INVALID_INDEX;
  237. }
  238. // Log failure.
  239. IIsScoLogFailure();
  240. TRACE_EXIT(L"CIISSCO50::CreateWebSiteRollback");
  241. return hr;
  242. }
  243. ///////////////////////////////////////////////////////////////////////////////
  244. // CIISSCO50::DeleteWebSite_Execute
  245. // Author: Russ Gibfried
  246. // Params: [in] none
  247. // [out] none
  248. // Purpose: Called by MAPS framework when is encounters an action
  249. // tag: DeleteWebSite. Code deletes a IIS 5 web site
  250. //
  251. //-------------------------------------------------------------
  252. HRESULT CIISSCO50::DeleteWebSite_Execute( IXMLDOMNode *pXMLNode )
  253. {
  254. TRACE_ENTER(L"CIISSCO50::DeleteWebSite");
  255. CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
  256. CComBSTR bstrServer; // Server name; localhost if black
  257. CComBSTR bServerNumber; // WebSite number: 3
  258. CComBSTR bstrConfigPath; // Full configuartion path: IIS://localhost/W3SVC/3
  259. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  260. HRESULT hr = S_OK;
  261. // Get node in format: <executeData><Website number=''><Root />...
  262. CComBSTR bstrDebug;
  263. //hr = pXMLNode->get_xml(&bstrDebug);
  264. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  265. hr = pNode->get_xml(&bstrDebug);
  266. ATLTRACE(_T("\t>>> xml = : %ls\n"), bstrDebug.m_str);
  267. // Get properties from XML
  268. hr = GetInputAttr(pNode, L"./Website", L"number", bServerNumber);
  269. hr = GetInputParam(pNode,L"./Website/Server", bstrServer);
  270. // Create a IIS metabase path. ex. IIS://localhost/W3SVC
  271. bWebADsPath = IIS_PREFIX;
  272. if ( bstrServer.Length() == 0 )
  273. bstrServer = IIS_LOCALHOST;
  274. bWebADsPath.AppendBSTR(bstrServer);
  275. bWebADsPath.Append(IIS_W3SVC);
  276. // CreateFull configuartion path: IIS://localhost/W3SVC/3
  277. bstrConfigPath = bWebADsPath.Copy();
  278. bstrConfigPath.Append(L"/");
  279. bstrConfigPath.AppendBSTR(bServerNumber.m_str);
  280. if ( bServerNumber.Length() > 0 )
  281. {
  282. // Step 1: ShutDown Server
  283. hr = IIsServerAction(bstrConfigPath,stop);
  284. IIsScoLogFailure();
  285. // Step 2: Delete the server
  286. if (SUCCEEDED(hr) ) hr = DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
  287. IIsScoLogFailure();
  288. if ( SUCCEEDED(hr) )
  289. {
  290. // DeleteSite successfully. Set Rollback data to be whole xml node
  291. // incase another step in SCO fails a RollBack is required.
  292. CComBSTR webXML;
  293. hr = pNode->get_xml(&webXML);
  294. // convert BSTR to Variant and save in RollbackData
  295. CComVariant varData(webXML);
  296. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
  297. }
  298. }
  299. else
  300. {
  301. hr = E_SCO_IIS_INVALID_INDEX;
  302. }
  303. if ( FAILED(hr) )
  304. IIsScoLogFailure();
  305. TRACE_EXIT(L"CIISSCO50::DeleteWebSite");
  306. return hr;
  307. }
  308. ///////////////////////////////////////////////////////////////////////////////
  309. // CIISSCO50::DeleteWebSite_Rollback
  310. // Author: Russ Gibfried
  311. // Params: [in] none
  312. // [out] none
  313. // Purpose: Called by MAPS framework when is encounters a failure during
  314. // 'DeleteWebSite'. The Rollback recreates the WebSite if it can.
  315. // MAPS returns data in the format: <executeData><Website number=''>...
  316. //-------------------------------------------------------------
  317. HRESULT CIISSCO50::DeleteWebSite_Rollback( IXMLDOMNode *pXMLNode )
  318. {
  319. //hr = m_pProvHelper->GetRollbackData(L"key", &varData );
  320. TRACE_ENTER(L"CIISSCO50::DeleteWebSiteRollback");
  321. CComBSTR bWebADsPath; // adsPath: IIS://server/W3SVC
  322. CComBSTR bstrRoot; // root directory path: c:/inetpub
  323. CComBSTR bstrServer; // Server name; localhost if black
  324. CComBSTR bstrSiteName; // site name; www.mysite.com
  325. CComBSTR bstrHost; // Web Hostname
  326. CComBSTR bstrPort; // Web port number
  327. CComBSTR bstrIP; // Web IP address
  328. CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
  329. CComBSTR bServerNumber; // WebSite number: 3
  330. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  331. CComBSTR bstrStart; // Start site when done? TRUE/FALSE
  332. CComBSTR bConfigPath; // Initial <ConfigPath> value: /W3SVC/3
  333. CComBSTR bstrConfigPath; // Created sites ADsPath: /W3SVC/3
  334. CComVariant xmlString; // Variant string returned by MAPS
  335. CComPtr<IXMLDOMDocument> pDoc; // xml document
  336. CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
  337. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  338. HRESULT hr = S_OK;
  339. // Get RollBack data. Will bein form: <executeData><Website number=''>...
  340. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
  341. // load xml string into XML Dom
  342. if ( xmlString.bstrVal != NULL )
  343. {
  344. hr = CoCreateInstance(
  345. __uuidof(DOMDocument),
  346. NULL,
  347. CLSCTX_ALL,
  348. __uuidof(IXMLDOMDocument),
  349. (LPVOID*)&pDoc);
  350. VARIANT_BOOL bSuccess = VARIANT_FALSE;
  351. hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
  352. if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
  353. {
  354. // Check that there is a <Website> tag
  355. hr = pDoc->getElementsByTagName(L"Website",&pNodeList);
  356. long numChild = 0;
  357. if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
  358. if ( numChild > 0 )
  359. {
  360. // Get the next node which is <Website number=''>
  361. hr = pNodeList->nextNode(&pNode);
  362. // Get Server number from attribute map <Website number=2">
  363. if (SUCCEEDED(hr) )
  364. {
  365. hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
  366. if ( !IsPositiveInteger(bServerNumber) )
  367. {
  368. //hr = GetElement(pNode, L"ConfigPath", bConfigPath);
  369. hr = ParseBSTR(bConfigPath,L'/', 2, 99, bServerNumber);
  370. }
  371. // Check Server number is valid
  372. if ( !IsPositiveInteger(bServerNumber) )
  373. {
  374. hr = E_SCO_IIS_INVALID_INDEX;
  375. IIsScoLogFailure();
  376. }
  377. }
  378. // Get properties from XML
  379. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Root", bstrRoot);
  380. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Server", bstrServer);
  381. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./SiteName", bstrSiteName);
  382. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./HostName", bstrHost);
  383. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./PortNumber", bstrPort);
  384. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./IPAddress", bstrIP);
  385. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./StartOnCreate", bstrStart);
  386. //if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./FilePermissions", bFilePermissions);
  387. // Create a IIS metabase path. ex. IIS://localhost/W3SVC
  388. bWebADsPath = IIS_PREFIX;
  389. if ( bstrServer.Length() == 0 )
  390. bstrServer = IIS_LOCALHOST;
  391. bWebADsPath.AppendBSTR(bstrServer);
  392. bWebADsPath.Append(IIS_W3SVC);
  393. // Step .5: If port number missing, set to default (ie, 80)
  394. if ( bstrPort.Length() == 0 )
  395. bstrPort = IIS_DEFAULT_WEB_PORT;
  396. if ( IsPositiveInteger(bstrPort) )
  397. {
  398. // Step 1: Create the ServerBinding string then check bindings to make sure
  399. // there is not a duplicate server
  400. CreateBindingString(bstrIP, bstrPort, bstrHost, bstrSBindings);
  401. if (SUCCEEDED(hr) ) hr = CheckBindings(bWebADsPath, bstrSBindings);
  402. IIsScoLogFailure();
  403. // Step 2: Recreate Web Server
  404. if (SUCCEEDED(hr) )
  405. {
  406. // Step 3: Create the Web Site on given path, ServerNumber.
  407. if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISWEBSERVER,bWebADsPath, bServerNumber, bstrConfigPath);
  408. IIsScoLogFailure();
  409. // Step 4: Create a Virtual directory on new IIsWebServer configPath
  410. if (SUCCEEDED(hr))
  411. {
  412. CComBSTR bstrVDirAdsPath;
  413. hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR, bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
  414. IIsScoLogFailure();
  415. // Step 5: set each property; ie, server bindings
  416. // Bind to ADs object
  417. CComPtr<IADs> pADs;
  418. if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
  419. if ( FAILED(hr) )
  420. {
  421. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  422. }
  423. // Set "ServerComment" property
  424. if (SUCCEEDED(hr) && bstrSiteName.Length() > 0 )
  425. {
  426. hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
  427. IIsScoLogFailure();
  428. }
  429. if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
  430. IIsScoLogFailure();
  431. // Step 6: Start Server if required IIS_FALSE
  432. bstrStart.ToUpper();
  433. if ( SUCCEEDED(hr) )
  434. {
  435. if ( !StringCompare(bstrStart, IIS_FALSE) )
  436. {
  437. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
  438. IIsScoLogFailure();
  439. hr = IIsServerAction(bstrConfigPath,start);
  440. IIsScoLogFailure();
  441. }
  442. else
  443. {
  444. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
  445. IIsScoLogFailure();
  446. }
  447. }
  448. // If there is a failure, 'IIsScoLogFailure' macro will log error
  449. if ( FAILED(hr) )
  450. {
  451. // First delete any webseites that were created in the method. Do this here because a RollBack
  452. // will only get called on a completed previous <step>, not a failed step.
  453. DeleteIIs50Site(IIS_IISWEBSERVER,bWebADsPath,bServerNumber);
  454. }
  455. } // if Step 4
  456. } // if Step 3
  457. }
  458. else
  459. {
  460. hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
  461. IIsScoLogFailure();
  462. } // portnumber positive
  463. } // if hasChild
  464. } // if isSuccessfull
  465. }
  466. // Log failure.
  467. if ( FAILED(hr))
  468. IIsScoLogFailure();
  469. TRACE_EXIT(L"CIISSco50Obj::DeleteWebSiteRollback");
  470. return hr;
  471. }
  472. ///////////////////////////////////////////////////////////////////////////////
  473. // CIISSCO50::CreateFTPSite_Execute
  474. // Author: Russ Gibfried
  475. // Params: [in] none
  476. // [out] none
  477. // Purpose: Called by MAPS framework when is encounters an action
  478. // tag: CreateFTPSite. Code creates a IIS 5 ftp site
  479. //
  480. //-------------------------------------------------------------
  481. HRESULT CIISSCO50::CreateFTPSite_Execute( IXMLDOMNode *pXMLNode )
  482. {
  483. TRACE_ENTER(L"CIISSCO50::CreateFTPSite");
  484. HRESULT hr = S_OK;
  485. CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
  486. CComBSTR bstrRoot; // root directory path: c:/inetpub
  487. CComBSTR bstrServer; // Server name; localhost if black
  488. CComBSTR bstrSiteName; // site name; www.mysite.com
  489. CComBSTR bstrPort; // Web port number
  490. CComBSTR bstrIP; // Web IP address
  491. CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
  492. CComBSTR bServerNumber; // WebSite number: 3
  493. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  494. CComBSTR bstrStart; // Start site when done? TRUE/FALSE
  495. CComBSTR bstrConfigPath; // Created sites ADsPath: /MSFTPSVC/3
  496. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  497. // Get node in format: <executeData><FTPsite number=''><Root />...
  498. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  499. // Get properties from XML
  500. hr = GetInputAttr(pNode, L"./FTPsite", L"number", bServerNumber);
  501. hr = GetInputParam(pNode,L"./FTPsite/Root", bstrRoot);
  502. hr = GetInputParam(pNode,L"./FTPsite/Server", bstrServer);
  503. hr = GetInputParam(pNode,L"./FTPsite/SiteName", bstrSiteName);
  504. hr = GetInputParam(pNode,L"./FTPsite/PortNumber", bstrPort);
  505. hr = GetInputParam(pNode,L"./FTPsite/IPAddress", bstrIP);
  506. hr = GetInputParam(pNode,L"./FTPsite/StartOnCreate", bstrStart);
  507. //hr = GetInputParam(pNode,L"./FTPsite/FilePermissions", bFilePermissions);
  508. // Create a IIS metabase path. ex. IIS://localhost/MSFTPSVC
  509. bFTPADsPath = IIS_PREFIX;
  510. if ( bstrServer.Length() == 0 )
  511. bstrServer = IIS_LOCALHOST;
  512. bFTPADsPath.AppendBSTR(bstrServer);
  513. bFTPADsPath.Append(IIS_MSFTPSVC);
  514. // Step .5: If port number missing, set to default (ie, 21)
  515. if ( bstrPort.Length() == 0 )
  516. bstrPort = IIS_DEFAULT_FTP_PORT;
  517. if ( IsPositiveInteger(bstrPort) )
  518. {
  519. // Step 1: Create the ServerBinding string to make sure not a duplicate server
  520. hr = CreateBindingString(bstrIP, bstrPort, L"", bstrSBindings);
  521. hr = CheckBindings(bFTPADsPath, bstrSBindings);
  522. if (SUCCEEDED(hr) )
  523. {
  524. // Step 2: Get Next available Server Index
  525. if ( bServerNumber.Length() == 0 )
  526. hr = GetNextIndex(bFTPADsPath,bServerNumber);
  527. // Step 3: Create the Web Site on given path, ServerNumber.
  528. if (SUCCEEDED(hr)) hr = CreateIIs50Site(IIS_IISFTPSERVER,bFTPADsPath, bServerNumber, bstrConfigPath);
  529. if (SUCCEEDED(hr))
  530. {
  531. // Step 4: Create a Virtual directory on new IIsWebServer configPath
  532. CComBSTR bstrVDirAdsPath;
  533. hr = CreateIIs50VDir(IIS_FTPVDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
  534. IIsScoLogFailure();
  535. // Step 5: set each property
  536. CComPtr<IADs> pADs;
  537. if (SUCCEEDED(hr)) hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
  538. if (SUCCEEDED(hr))
  539. {
  540. // Set "ServerComment" property
  541. if (bstrSiteName.Length() > 0 )
  542. {
  543. hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
  544. IIsScoLogFailure();
  545. }
  546. // Set "ServerBindings"
  547. if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
  548. IIsScoLogFailure();
  549. // Step 6: Start Server if required IIS_FALSE
  550. bstrStart.ToUpper();
  551. if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
  552. {
  553. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
  554. IIsScoLogFailure();
  555. hr = IIsServerAction(bstrConfigPath,start);
  556. IIsScoLogFailure();
  557. }
  558. else
  559. {
  560. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
  561. IIsScoLogFailure();
  562. }
  563. // Step 7: write ConfigPath to output.
  564. if (SUCCEEDED(hr) )
  565. {
  566. CComBSTR bstrXML1 = IIS_MSFTPSVC;
  567. bstrXML1.Append(L"/");
  568. bstrXML1.AppendBSTR(bServerNumber.m_str);
  569. // Helper function to write to DOM
  570. hr = PutElement(pNode, L"./FTPsite/ConfigPath", bstrXML1.m_str);
  571. IIsScoLogFailure();
  572. }
  573. }
  574. else
  575. {
  576. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  577. IIsScoLogFailure();
  578. } // end step 4
  579. // If something failed between steps 5-7, delete FTP site created in step 3
  580. if ( FAILED(hr) )
  581. {
  582. // First delete any ftp sites that were created in the method. Do this here because a RollBack
  583. // will only get called on a completed previous <step>, not a failed step.
  584. DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
  585. }
  586. } // end if L"CreateFTPSite: Could not create FTP site."
  587. } // end if FTP ServerBindings already existed."
  588. }
  589. else
  590. {
  591. // L"CreateFTPSite: Port number must be positive value."
  592. hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
  593. }
  594. // If there is a failure.
  595. if ( FAILED(hr) )
  596. {
  597. // L"CreateFTPSite failed."
  598. IIsScoLogFailure();
  599. }
  600. else
  601. {
  602. // FTP Site successfully created. Set Rollback data incase another step fails
  603. CComVariant varData1(bFTPADsPath);
  604. CComVariant varData2(bServerNumber);
  605. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
  606. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_SERVERNUMBER, varData2);
  607. }
  608. TRACE_EXIT(L"CIISSCO50::CreateFTPSite");
  609. return hr;
  610. }
  611. ///////////////////////////////////////////////////////////////////////////////
  612. // CIISSCO50::CreateFTPSite_Rollback
  613. // Author: Russ Gibfried
  614. // Params: [in] none
  615. // [out] none
  616. // Purpose: Called by MAPS framework when is encounters a failure during
  617. // 'CreateFTPSite'. The Rollback deletes the ftp if it can.
  618. //-------------------------------------------------------------
  619. HRESULT CIISSCO50::CreateFTPSite_Rollback( IXMLDOMNode *pXMLNode )
  620. {
  621. TRACE_ENTER(L"CIISSCO50::CreateFTPSiteRollback");
  622. HRESULT hr = S_OK;
  623. CComBSTR bFTPADsPath; // AdsPath: IIS://server/MSFTPSVC
  624. CComBSTR bServerNumber; // Web server number
  625. CComBSTR bstrConfigPath; // Complete ADsPath to check: IIS://localhost/MSFTPSVC/1
  626. CComVariant varFTPADsPath;
  627. CComVariant varServerNumber;
  628. // Read ADsFTPPath and ServerNumber to form: IIS://localhost/MSFTPSVC/1
  629. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varFTPADsPath);
  630. if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_SERVERNUMBER, &varServerNumber);
  631. if (SUCCEEDED(hr) )
  632. {
  633. bServerNumber = varServerNumber.bstrVal;
  634. bFTPADsPath = varFTPADsPath.bstrVal;
  635. bstrConfigPath = bFTPADsPath.Copy();
  636. bstrConfigPath.Append(L"/");
  637. bstrConfigPath.AppendBSTR(bServerNumber.m_str);
  638. }
  639. // Step 1: ShutDown Server
  640. if (SUCCEEDED(hr)) hr = IIsServerAction(bstrConfigPath,stop);
  641. // Only a warning if can't stop/start server given correct server path
  642. // Step 2: Delete the server
  643. hr = DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
  644. IIsScoLogFailure();
  645. TRACE_EXIT(L"CIISSCO50::CreateFTPSiteRollback");
  646. return hr;
  647. }
  648. ///////////////////////////////////////////////////////////////////////////////
  649. // CIISSCO50::DeleteFTPSite_Execute
  650. // Author: Russ Gibfried
  651. // Params: [in] none
  652. // [out] none
  653. // Purpose: Called by MAPS framework when is encounters an action
  654. // tag: DeleteFTPSite. Code deletes a IIS 5 ftp site
  655. //
  656. //-------------------------------------------------------------
  657. HRESULT CIISSCO50::DeleteFTPSite_Execute( IXMLDOMNode *pXMLNode )
  658. {
  659. TRACE_ENTER(L"CIISSCO50::DeleteFTPSite");
  660. CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
  661. CComBSTR bstrServer; // Server name; localhost if blank
  662. CComBSTR bServerNumber; // WebSite number: 3
  663. CComBSTR bstrConfigPath; // Full configuartion path: IIS://localhost/MSFTPSVC/3
  664. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  665. HRESULT hr = S_OK;
  666. // Get node in format: <executeData><FTPsite number=''><Root />...
  667. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  668. // Get properties from XML
  669. hr = GetInputAttr(pNode, L"./FTPsite", L"number", bServerNumber);
  670. hr = GetInputParam(pNode,L"./FTPsite/Server", bstrServer);
  671. // Step .5: Make sure Server Number is a positive integer
  672. if ( IsPositiveInteger(bServerNumber) )
  673. {
  674. // Create a IIS metabase path. ex. IIS://localhost/MSFTPSVC
  675. bFTPADsPath = IIS_PREFIX;
  676. if ( bstrServer.Length() == 0 )
  677. bstrServer = IIS_LOCALHOST;
  678. bFTPADsPath.AppendBSTR(bstrServer);
  679. bFTPADsPath.Append(IIS_MSFTPSVC);
  680. // Create metabase path to object: IIS://localhost/MSFTPSVC/1
  681. bstrConfigPath = bFTPADsPath.Copy();
  682. bstrConfigPath.Append(L"/");
  683. bstrConfigPath.AppendBSTR(bServerNumber.m_str);
  684. // Step 1: ShutDown Server
  685. hr = IIsServerAction(bstrConfigPath,stop);
  686. // Only a warning if can't stop/start server
  687. // Step 2: Delete the server
  688. hr = DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
  689. IIsScoLogFailure();
  690. }
  691. else
  692. {
  693. // L"DeleteFTPSite: Invalid Server number."
  694. hr = E_SCO_IIS_INVALID_INDEX;
  695. IIsScoLogFailure();
  696. }
  697. // If there is a failure
  698. if ( FAILED(hr) )
  699. {
  700. // L"DeleteFTPSite failed."
  701. IIsScoLogFailure();
  702. }
  703. else
  704. {
  705. // DeleteSite successfully. Set Rollback data to be whole xml node
  706. // incase another step in SCO fails a RollBack is required.
  707. CComBSTR webXML;
  708. hr = pNode->get_xml(&webXML);
  709. // convert BSTR to Variant and save in RollbackData
  710. CComVariant varData(webXML);
  711. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
  712. }
  713. TRACE_EXIT(L"CIISSCO50::DeleteFTPSite");
  714. return hr;
  715. }
  716. ///////////////////////////////////////////////////////////////////////////////
  717. // CIISSCO50::DeleteFTPSite_Rollback
  718. // Author: Russ Gibfried
  719. // Params: [in] none
  720. // [out] none
  721. // Purpose: Called by MAPS framework when is encounters a failure during
  722. // 'DeleteFTPSite'. The Rollback recreates the ftp Site if it can.
  723. //-------------------------------------------------------------
  724. HRESULT CIISSCO50::DeleteFTPSite_Rollback( IXMLDOMNode *pXMLNode )
  725. {
  726. TRACE_ENTER(L"CIISSCO50::DeleteFTPSiteRollback");
  727. CComBSTR bFTPADsPath; // adsPath: IIS://server/MSFTPSVC
  728. CComBSTR bstrRoot; // root directory path: c:/inetpub
  729. CComBSTR bstrServer; // Server name; localhost if black
  730. CComBSTR bstrSiteName; // site name; www.mysite.com
  731. CComBSTR bstrPort; // Web port number
  732. CComBSTR bstrIP; // Web IP address
  733. CComBSTR bstrSBindings; // Server bindings: IP:Post:HostName
  734. CComBSTR bServerNumber; // WebSite number: 3
  735. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  736. CComBSTR bstrStart; // Start site when done? TRUE/FALSE
  737. CComBSTR bConfigPath; // Initial <ConfigPath> value: /MSFTPSVC/3
  738. CComBSTR bstrConfigPath; // Created sites ADsPath: /MSFTPSVC/3
  739. CComVariant xmlString;
  740. CComPtr<IXMLDOMDocument> pDoc; // xml document
  741. CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
  742. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  743. HRESULT hr = S_OK;
  744. // Get RollBack data. Will bein form: <executeData><Website number=''>...
  745. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
  746. // load xml string into XML Dom
  747. if ( xmlString.bstrVal != NULL )
  748. {
  749. hr = CoCreateInstance(
  750. __uuidof(DOMDocument),
  751. NULL,
  752. CLSCTX_ALL,
  753. __uuidof(IXMLDOMDocument),
  754. (LPVOID*)&pDoc);
  755. VARIANT_BOOL bSuccess = VARIANT_FALSE;
  756. if ( SUCCEEDED(hr) ) hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
  757. if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
  758. {
  759. // Check that there is a <FTPSite number= > tag
  760. hr = pDoc->getElementsByTagName(L"FTPsite",&pNodeList);
  761. long numChild = 0;
  762. if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
  763. if ( numChild > 0 )
  764. {
  765. hr = pNodeList->nextNode(&pNode);
  766. // Get Server number from attribute map <FTPSite number=2">
  767. if (SUCCEEDED(hr) ) hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
  768. // Check Server number is valid
  769. if ( !IsPositiveInteger(bServerNumber) )
  770. {
  771. // L"DeleteFTPSiteRollback: FTP Server Number missing."
  772. hr = E_SCO_IIS_INVALID_INDEX;
  773. IIsScoLogFailure();
  774. }
  775. // Get properties from XML
  776. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Root", bstrRoot);
  777. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./Server", bstrServer);
  778. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./SiteName", bstrSiteName);
  779. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./PortNumber", bstrPort);
  780. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./IPAddress", bstrIP);
  781. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./StartOnCreate", bstrStart);
  782. //if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./FilePermissions", bFilePermissions);
  783. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./ConfigPath", bConfigPath);
  784. // Create a IIS metabase path. ex. IIS://localhost/W3SVC
  785. bFTPADsPath = IIS_PREFIX;
  786. if ( bstrServer.Length() == 0 )
  787. bstrServer = IIS_LOCALHOST;
  788. bFTPADsPath.AppendBSTR(bstrServer);
  789. bFTPADsPath.Append(IIS_MSFTPSVC);
  790. // Step .5: If port number missing, set to default (ie, 21)
  791. if ( bstrPort.Length() == 0 )
  792. bstrPort = IIS_DEFAULT_FTP_PORT;
  793. if ( IsPositiveInteger(bstrPort) )
  794. {
  795. // Step 1: Create the ServerBinding string to make sure not a duplicate server
  796. hr = CreateBindingString(bstrIP, bstrPort, L"", bstrSBindings);
  797. if (SUCCEEDED(hr)) hr = CheckBindings(bFTPADsPath, bstrSBindings);
  798. IIsScoLogFailure();
  799. // Step 2 Recreate FTP Server
  800. if (SUCCEEDED(hr) )
  801. {
  802. // Step 3: Create the Web Site on given path, ServerNumber.
  803. hr = CreateIIs50Site(IIS_IISFTPSERVER,bFTPADsPath, bServerNumber, bstrConfigPath);
  804. IIsScoLogFailure();
  805. // Step 4: Create a Virtual directory on new IIsFtpVirtualDir configPath
  806. if (SUCCEEDED(hr) )
  807. {
  808. CComBSTR bstrVDirAdsPath;
  809. hr = CreateIIs50VDir(IIS_FTPVDIR,bstrConfigPath,L"ROOT", L"Default Application", bstrRoot, bstrVDirAdsPath);
  810. IIsScoLogFailure();
  811. // Step 5 - set properties
  812. if (SUCCEEDED(hr) )
  813. {
  814. CComPtr<IADs> pADs;
  815. hr = ADsGetObject(bstrConfigPath, IID_IADs, (void**) &pADs );
  816. if ( FAILED(hr) )
  817. {
  818. // L"DeleteFTPSiteRollback: Create FTP adsi object failed."
  819. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  820. IIsScoLogFailure();
  821. }
  822. else
  823. {
  824. // Set "ServerComment" property
  825. if (bstrSiteName.Length() > 0 )
  826. {
  827. hr = SetMetaPropertyValue(pADs, L"ServerComment", bstrSiteName);
  828. IIsScoLogFailure();
  829. }
  830. // Set "ServerBindings"
  831. if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerBindings", bstrSBindings);
  832. IIsScoLogFailure();
  833. // Step 6: Start Server if required IIS_FALSE
  834. bstrStart.ToUpper();
  835. if ( SUCCEEDED(hr) && !StringCompare(bstrStart, IIS_FALSE) )
  836. {
  837. hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_TRUE);
  838. IIsScoLogFailure();
  839. hr = IIsServerAction(bstrConfigPath,start);
  840. IIsScoLogFailure();
  841. }
  842. else
  843. {
  844. if (SUCCEEDED(hr)) hr = SetMetaPropertyValue(pADs, L"ServerAutoStart", IIS_FALSE);
  845. IIsScoLogFailure();
  846. }
  847. } // end if Step 5
  848. }
  849. // If failure, delete the FTP site
  850. if ( FAILED(hr))
  851. {
  852. DeleteIIs50Site(IIS_IISFTPSERVER,bFTPADsPath,bServerNumber);
  853. }
  854. } // end step 4
  855. } // end if Step 2
  856. }
  857. else
  858. {
  859. // L"DeleteWebSiteRollback: Port number not a positive integer."
  860. hr = E_SCO_IIS_PORTNUMBER_NOT_VALID;
  861. } // step .5 portnumber positive
  862. } // if numChild > 0
  863. } // if isSuccessfull
  864. }
  865. if ( FAILED(hr) )
  866. {
  867. // DeleteFTPSiteRollback failed."
  868. IIsScoLogFailure();
  869. }
  870. TRACE_EXIT(L"CIISSCO50::DeleteFTPSiteRollback");
  871. return hr;
  872. }
  873. ///////////////////////////////////////////////////////////////////////////////
  874. // CIISSCO50::CreateVDir_Execute
  875. // Author: Russ Gibfried
  876. // Params: [in] none
  877. // [out] none
  878. // Purpose: Called by MAPS framework when is encounters an action
  879. // tag: CreateVDir. Code creates a IIS 5 Virtual Directory
  880. //
  881. //-------------------------------------------------------------
  882. HRESULT CIISSCO50::CreateVDir_Execute( IXMLDOMNode *pXMLNode )
  883. {
  884. TRACE_ENTER(L"CIISSCO50::CreateVDir");
  885. CComBSTR bstrConfigPath; // adsPath: IIS://server/W3SVC/1/ROOT/MyDir
  886. CComBSTR bServerNumber; // Server number
  887. CComBSTR bstrServer; // Server name; localhost if blank
  888. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  889. CComBSTR bstrDirPath; // root directory path: c:/inetpub
  890. CComBSTR bstrVDirName; // Virtual Directory name; MyDir
  891. CComBSTR bstrFriendlyName; // Display name or AppFriendlyName
  892. CComBSTR bstrAppCreate; // AppCreate flag -- TRUE/FALSE
  893. CComBSTR bstrIsoLevel; // AppIsolationLevel
  894. CComBSTR bstrAccessRead; // AccessFalgs - AccessRead = TRUE/FALSE
  895. CComBSTR bstrAccessScript; // AccessFalgs - AccessScript = TRUE/FALSE
  896. CComBSTR bstrAccessWrite; // AccessFalgs - AccessWrite = TRUE/FALSE
  897. CComBSTR bstrAccessExecute; // AccessFalgs - AccessExecute = TRUE/FALSE
  898. CComPtr<IXMLDOMNode> pNode; // xml node. will be <executeData><VirtualDirectory>
  899. HRESULT hr = S_OK;
  900. // Get node in format: <executeData><VirtualDirectory number=''><Root />...
  901. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  902. // Get properties from XML
  903. hr = GetInputAttr(pNode,L"./VirtualDirectory", L"number", bServerNumber);
  904. hr = GetInputParam(pNode,L"./VirtualDirectory/Server", bstrServer);
  905. //hr = GetInputParam(pNode,L"./VirtualDirectory/FilePermissions", bFilePermissions);
  906. hr = GetInputParam(pNode,L"./VirtualDirectory/Path", bstrDirPath);
  907. hr = GetInputParam(pNode,L"./VirtualDirectory/VDirName", bstrVDirName);
  908. hr = GetInputParam(pNode,L"./VirtualDirectory/DisplayName", bstrFriendlyName);
  909. hr = GetInputParam(pNode,L"./VirtualDirectory/AppCreate", bstrAppCreate);
  910. hr = GetInputParam(pNode,L"./VirtualDirectory/AppIsolationLevel", bstrIsoLevel);
  911. hr = GetInputParam(pNode,L"./VirtualDirectory/AccessRead", bstrAccessRead);
  912. hr = GetInputParam(pNode,L"./VirtualDirectory/AccessScript", bstrAccessScript);
  913. hr = GetInputParam(pNode,L"./VirtualDirectory/AccessWrite", bstrAccessWrite);
  914. hr = GetInputParam(pNode,L"./VirtualDirectory/AccessExecute", bstrAccessExecute);
  915. // Step 1: Get Server number where VDir will be created
  916. if ( !IsPositiveInteger(bServerNumber))
  917. {
  918. // "CreateVDir: Server number missing."
  919. hr = E_SCO_IIS_INVALID_INDEX;
  920. IIsScoLogFailure();
  921. }
  922. else
  923. {
  924. // Step 2: Construct the Metabase path that VDir will be created on.
  925. // ex) IIS://localhost/W3SVC/1/ROOT
  926. bstrConfigPath = IIS_PREFIX;
  927. // append server name, W3SVC and server number
  928. if ( bstrServer.Length() == 0 )
  929. bstrServer = IIS_LOCALHOST;
  930. bstrConfigPath.AppendBSTR(bstrServer);
  931. bstrConfigPath.Append(IIS_W3SVC);
  932. bstrConfigPath.Append(L"/");
  933. bstrConfigPath.AppendBSTR(bServerNumber);
  934. // if there is a VDir name, then it must be under 'ROOT'
  935. if ( bstrVDirName.Length() == 0 )
  936. {
  937. bstrVDirName = IIS_VROOT;
  938. }
  939. else
  940. {
  941. bstrConfigPath.Append(L"/");
  942. bstrConfigPath.Append(IIS_VROOT);
  943. }
  944. //Step 2: Get the AppFriendlyName
  945. if ( bstrFriendlyName.Length() == 0 )
  946. bstrFriendlyName = IIS_VDEFAULT_APP;
  947. // Step 3: Create a Virtual directory on new IIsWebServer configPath
  948. CComBSTR bstrVDirAdsPath;
  949. hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,bstrVDirName, bstrFriendlyName, bstrDirPath, bstrVDirAdsPath);
  950. IIsScoLogFailure();
  951. if ( SUCCEEDED(hr))
  952. {
  953. // Step 4: set each of the properties
  954. // Set the server bindings
  955. CComPtr<IADs> pADs;
  956. if (SUCCEEDED(hr)) hr = ADsGetObject( bstrVDirAdsPath,IID_IADs, (void **)&pADs);
  957. if ( FAILED(hr))
  958. {
  959. // "CreateVDir: Failed to create IADs object for VDir path."
  960. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  961. IIsScoLogFailure();
  962. }
  963. // Bug# 453928 -- Default AppIsolationLevel is 2
  964. if ( !IsPositiveInteger(bstrIsoLevel))
  965. bstrIsoLevel = IIS_DEFAULT_APPISOLATED;
  966. // Set AppIsolationLevel -- 'AppIsolated'
  967. if (SUCCEEDED(hr)) hr = SetVDirProperty(pADs, L"AppIsolated",bstrIsoLevel);
  968. IIsScoLogFailure();
  969. // Set AccessFlags'
  970. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  971. {
  972. hr = SetVDirProperty(pADs, L"AccessRead",bstrAccessRead);
  973. IIsScoLogFailure();
  974. }
  975. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  976. {
  977. hr = SetVDirProperty(pADs, L"AccessScript",bstrAccessScript);
  978. IIsScoLogFailure();
  979. }
  980. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  981. {
  982. hr = SetVDirProperty(pADs, L"AccessWrite",bstrAccessWrite);
  983. IIsScoLogFailure();
  984. }
  985. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  986. {
  987. hr = SetVDirProperty(pADs, L"AccessExecute",bstrAccessExecute);
  988. IIsScoLogFailure();
  989. }
  990. // Step 5: If AppCreate is FALSE, then remove the following properties.
  991. // Bug# 453923
  992. bstrAppCreate.ToUpper();
  993. if ( SUCCEEDED(hr) && StringCompare(bstrAppCreate, IIS_FALSE) )
  994. {
  995. hr = DeleteMetaPropertyValue(pADs, L"AppIsolated");
  996. if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppRoot");
  997. if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppFriendlyName");
  998. IIsScoLogFailure();
  999. }
  1000. // If there is a failure.
  1001. if ( FAILED(hr) )
  1002. {
  1003. // First delete any virtual directories that were created in the method. Do this here because a RollBack
  1004. // will only get called on a completed previous <step>, not a failed step.
  1005. DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
  1006. }
  1007. else
  1008. {
  1009. CComBSTR bstrXML1;
  1010. // ParseBSTR
  1011. // Input: IIS://MyServer/W3SVC/1/ROOT/MyDir
  1012. // Output: /W3SVC/1/ROOT/MyDir
  1013. hr = ParseBSTR(bstrVDirAdsPath,bstrServer, 1, 99,bstrXML1);
  1014. // Matches line: <output type="WebSiteOutput" root="VirtualDirectory">
  1015. hr = PutElement(pNode, L"./VirtualDirectory/ConfigPath", bstrXML1.m_str);
  1016. }
  1017. }
  1018. }
  1019. // If there is a failure.
  1020. if ( FAILED(hr) )
  1021. {
  1022. // CreateVDir failed.
  1023. IIsScoLogFailure();
  1024. }
  1025. else
  1026. {
  1027. // WebSite successfully created. Set Rollback data incase another step fails
  1028. // a a ROllBack is initiated.
  1029. CComVariant varData1(bstrConfigPath);
  1030. CComVariant varData2(bstrVDirName);
  1031. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_ADSPATH, varData1);
  1032. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_VNAME, varData2);
  1033. }
  1034. TRACE_EXIT(L"CIISSCO50::CreateVDir");
  1035. return hr;
  1036. }
  1037. ///////////////////////////////////////////////////////////////////////////////
  1038. // CIISSCO50::CreateVDir_Rollback
  1039. // Author: Russ Gibfried
  1040. // Params: [in] none
  1041. // [out] none
  1042. // Purpose: Called by MAPS framework when is encounters a failure during
  1043. // 'CreateVDir'. The Rollback deletes the virtual directory if it can.
  1044. //-------------------------------------------------------------
  1045. HRESULT CIISSCO50::CreateVDir_Rollback( IXMLDOMNode *pXMLNode )
  1046. {
  1047. TRACE_ENTER(L"CIISSCO50::CreateVDirRollback");
  1048. HRESULT hr = S_OK;
  1049. CComBSTR bstrVDirName; // Virtual Directory name, ie, MyDir
  1050. CComBSTR bstrConfigPath; // Complete ADsPath to VDir: IIS://localhost/W3SVC/1/ROOT
  1051. CComVariant varConfigPath;
  1052. CComVariant varVDirName;
  1053. // Read ADsWebPath and ServerNumber to form: IIS://localhost/W3SVC/1
  1054. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_ADSPATH, &varConfigPath);
  1055. if (SUCCEEDED(hr) ) hr = m_pProvHelper->GetRollbackData(IIS_ROLL_VNAME, &varVDirName);
  1056. if ( SUCCEEDED(hr))
  1057. {
  1058. bstrVDirName = varVDirName.bstrVal;
  1059. bstrConfigPath = varConfigPath.bstrVal;
  1060. // Step 1: Delete the VDir
  1061. hr = DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
  1062. IIsScoLogFailure();
  1063. }
  1064. else
  1065. {
  1066. // "CreateVDirRollback: Failed to retrieve rollback properties."
  1067. hr = E_SCO_IIS_MISSING_FIELD;
  1068. IIsScoLogFailure();
  1069. }
  1070. TRACE_EXIT(L"CIISSCO50::CreateVDirRollback");
  1071. return hr;
  1072. }
  1073. ///////////////////////////////////////////////////////////////////////////////
  1074. // CIISSCO50::DeleteVDir_Execute
  1075. // Author: Russ Gibfried
  1076. // Params: [in] none
  1077. // [out] none
  1078. // Purpose: Called by MAPS framework when is encounters an action
  1079. // tag: DeleteVDir. Code deletes a IIS 5 virtual directory
  1080. //
  1081. //-------------------------------------------------------------
  1082. HRESULT CIISSCO50::DeleteVDir_Execute( IXMLDOMNode *pXMLNode )
  1083. {
  1084. TRACE_ENTER(L"CIISSCO50::DeleteVDir");
  1085. CComBSTR bstrServer; // Server name; localhost if blank
  1086. CComBSTR bstrVDirName; // VDir name
  1087. CComBSTR bServerNumber; // WebSite number: 3
  1088. CComBSTR bstrConfigPath; // Full configuartion path: IIS://server/W3SVC/1/ROOT/MyDir
  1089. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  1090. HRESULT hr = S_OK;
  1091. CComBSTR bstrDebug;
  1092. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  1093. hr = pNode->get_xml(&bstrDebug);
  1094. ATLTRACE(_T("\t>>>DeleteVDir_Execute: xml = : %ls\n"), bstrDebug.m_str);
  1095. // Get properties from XML
  1096. hr = GetInputAttr(pNode, L"./VirtualDirectory", L"number", bServerNumber);
  1097. hr = GetInputParam(pNode,L"./VirtualDirectory/Server", bstrServer);
  1098. hr = GetInputParam(pNode,L"./VirtualDirectory/VDirName", bstrVDirName);
  1099. // Step 1: Get Server number where VDir will be created
  1100. if ( !IsPositiveInteger(bServerNumber) )
  1101. {
  1102. hr = E_SCO_IIS_INVALID_INDEX;
  1103. IIsScoLogFailure();
  1104. }
  1105. if (SUCCEEDED(hr))
  1106. {
  1107. // Step 2: Construct the Metabase path that VDir will be created on.
  1108. // ex) IIS://localhost/W3SVC/1/ROOT
  1109. bstrConfigPath = IIS_PREFIX;
  1110. // append server name, W3SVC and server number
  1111. if ( bstrServer.Length() == 0 )
  1112. bstrServer = IIS_LOCALHOST;
  1113. bstrConfigPath.AppendBSTR(bstrServer);
  1114. bstrConfigPath.Append(IIS_W3SVC);
  1115. bstrConfigPath.Append("/");
  1116. bstrConfigPath.AppendBSTR(bServerNumber);
  1117. // if there is a VDir name, then it must be under 'ROOT'
  1118. if ( bstrVDirName.Length() == 0 )
  1119. {
  1120. bstrVDirName = IIS_VROOT;
  1121. }
  1122. else
  1123. {
  1124. bstrConfigPath.Append(L"/");
  1125. bstrConfigPath.Append(IIS_VROOT);
  1126. }
  1127. // Step 2: Delete the server
  1128. if (SUCCEEDED(hr)) hr = DeleteIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath, bstrVDirName);
  1129. IIsScoLogFailure();
  1130. }
  1131. // If there is a failure
  1132. if ( FAILED(hr) )
  1133. {
  1134. // "DeleteVDir failed."
  1135. IIsScoLogFailure();
  1136. }
  1137. else
  1138. {
  1139. // DeleteSite successfully. Set Rollback data to be whole xml node
  1140. // incase another step in SCO fails a RollBack is required.
  1141. CComBSTR webXML;
  1142. hr = pNode->get_xml(&webXML);
  1143. // convert BSTR to Variant and save in RollbackData
  1144. CComVariant varData(webXML);
  1145. hr = m_pProvHelper->SetRollbackData(IIS_ROLL_XNODE, varData);
  1146. }
  1147. TRACE_EXIT(L"CIISSCO50::DeleteVDir");
  1148. return hr;
  1149. }
  1150. ///////////////////////////////////////////////////////////////////////////////
  1151. // CIISSCO50::DeleteVDir_Rollback
  1152. // Author: Russ Gibfried
  1153. // Params: [in] none
  1154. // [out] none
  1155. // Purpose: Called by MAPS framework when is encounters a failure during
  1156. // 'DeleteVDir'. The Rollback recreates the virtual directory if it can.
  1157. //-------------------------------------------------------------
  1158. HRESULT CIISSCO50::DeleteVDir_Rollback( IXMLDOMNode *pXMLNode )
  1159. {
  1160. TRACE_ENTER(L"CIISSCO50::DeleteVDirRollback");
  1161. CComBSTR bstrConfigPath; // adsPath: IIS://server/W3SVC/1/ROOT/MyDir
  1162. CComBSTR bServerNumber; // Server number
  1163. CComBSTR bstrServer; // Server name; localhost if blank
  1164. //CComBSTR bFilePermissions; // File permissions: domain\user:F
  1165. CComBSTR bstrDirPath; // root directory path: c:/inetpub
  1166. CComBSTR bstrVDirName; // Virtual Directory name; MyDir
  1167. CComBSTR bstrFriendlyName; // Display name or AppFriendlyName
  1168. CComBSTR bstrAppCreate; // AppCreate flag -- TRUE/FALSE
  1169. CComBSTR bstrIsoLevel; // AppIsolationLevel
  1170. CComBSTR bstrAccessRead; // AccessFalgs - AccessRead = TRUE/FALSE
  1171. CComBSTR bstrAccessScript; // AccessFalgs - AccessScript = TRUE/FALSE
  1172. CComBSTR bstrAccessWrite; // AccessFalgs - AccessWrite = TRUE/FALSE
  1173. CComBSTR bstrAccessExecute; // AccessFalgs - AccessExecute = TRUE/FALSE
  1174. CComVariant xmlString;
  1175. CComPtr<IXMLDOMDocument> pDoc; // xml document
  1176. CComPtr<IXMLDOMNodeList> pNodeList; // xml node list <website>
  1177. CComPtr<IXMLDOMNode> pNode; // xml node <website>
  1178. HRESULT hr = S_OK;
  1179. // Get RollBack data. Will bein form: <executeData><Website number=''>...
  1180. hr = m_pProvHelper->GetRollbackData(IIS_ROLL_XNODE, &xmlString);
  1181. // load xml string into XML Dom
  1182. if ( xmlString.bstrVal != NULL )
  1183. {
  1184. hr = CoCreateInstance(
  1185. __uuidof(DOMDocument),
  1186. NULL,
  1187. CLSCTX_ALL,
  1188. __uuidof(IXMLDOMDocument),
  1189. (LPVOID*)&pDoc);
  1190. VARIANT_BOOL bSuccess = VARIANT_FALSE;
  1191. hr = pDoc->loadXML(xmlString.bstrVal, &bSuccess);
  1192. if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
  1193. {
  1194. hr = pDoc->getElementsByTagName(XML_NODE_VDIR,&pNodeList);
  1195. long numChild = 0;
  1196. if (SUCCEEDED(hr)) hr = pNodeList->get_length(&numChild);
  1197. if ( numChild > 0 )
  1198. {
  1199. hr = pNodeList->nextNode(&pNode);
  1200. // Get Server number from attribute map <VirtualDirectory number=2">
  1201. if (SUCCEEDED(hr) ) hr = GetInputAttr(pNode, L"", L"number", bServerNumber);
  1202. IIsScoLogFailure();
  1203. // Check Server number is valid
  1204. if ( !IsPositiveInteger(bServerNumber) )
  1205. {
  1206. hr = E_SCO_IIS_INVALID_INDEX;
  1207. IIsScoLogFailure();
  1208. }
  1209. // Get properties from XML
  1210. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/Server", bstrServer);
  1211. //if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/FilePermissions", bFilePermissions);
  1212. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/Path", bstrDirPath);
  1213. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/VDirName", bstrVDirName);
  1214. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/DisplayName", bstrFriendlyName);
  1215. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AppCreate", bstrAppCreate);
  1216. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AppIsolationLevel", bstrIsoLevel);
  1217. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessRead", bstrAccessRead);
  1218. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessScript", bstrAccessScript);
  1219. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessWrite", bstrAccessWrite);
  1220. if (SUCCEEDED(hr) ) hr = GetInputParam(pNode, L"./VirtualDirectory/AccessExecute", bstrAccessExecute);
  1221. // Create a IIS metabase path. ex. IIS://localhost/W3SVC/1/ROOT
  1222. bstrConfigPath = IIS_PREFIX;
  1223. // append server name, W3SVC and server number
  1224. if ( bstrServer.Length() == 0 )
  1225. bstrServer = IIS_LOCALHOST;
  1226. bstrConfigPath.AppendBSTR(bstrServer);
  1227. bstrConfigPath.Append(IIS_W3SVC);
  1228. bstrConfigPath.Append(L"/");
  1229. bstrConfigPath.AppendBSTR(bServerNumber);
  1230. // if there is a VDir name, then it must be under 'ROOT'
  1231. if ( bstrVDirName.Length() == 0 )
  1232. {
  1233. bstrVDirName = IIS_VROOT;
  1234. }
  1235. else
  1236. {
  1237. bstrConfigPath.Append(L"/");
  1238. bstrConfigPath.Append(IIS_VROOT);
  1239. }
  1240. //Step 2: Get the AppFriendlyName
  1241. if ( bstrFriendlyName.Length() == 0 )
  1242. bstrFriendlyName = IIS_VDEFAULT_APP;
  1243. // Step 3: Create a Virtual directory on new IIsWebServer configPath
  1244. CComBSTR bstrVDirAdsPath;
  1245. hr = CreateIIs50VDir(IIS_IISWEBVIRTUALDIR,bstrConfigPath,bstrVDirName, bstrFriendlyName, bstrDirPath, bstrVDirAdsPath);
  1246. IIsScoLogFailure();
  1247. if ( SUCCEEDED(hr))
  1248. {
  1249. // Step 4: set each of the properties
  1250. // Set the server bindings
  1251. CComPtr<IADs> pADs;
  1252. hr = ADsGetObject( bstrVDirAdsPath,IID_IADs, (void **)&pADs);
  1253. if ( FAILED(hr) )
  1254. {
  1255. // "DeleteVDirRollback: Failed to create IADs object for VDir path."
  1256. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  1257. IIsScoLogFailure();
  1258. }
  1259. // Bug# 453928 -- Default AppIsolationLevel is 2
  1260. if ( !IsPositiveInteger(bstrIsoLevel))
  1261. bstrIsoLevel = IIS_DEFAULT_APPISOLATED;
  1262. // Set AppIsolationLevel -- 'AppIsolated'
  1263. if (SUCCEEDED(hr)) hr = SetVDirProperty(pADs, L"AppIsolated",bstrIsoLevel);
  1264. IIsScoLogFailure();
  1265. // Set AccessFlags'
  1266. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  1267. {
  1268. hr = SetVDirProperty(pADs, L"AccessRead",bstrAccessRead);
  1269. IIsScoLogFailure();
  1270. }
  1271. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  1272. {
  1273. hr = SetVDirProperty(pADs, L"AccessScript",bstrAccessScript);
  1274. IIsScoLogFailure();
  1275. }
  1276. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  1277. {
  1278. hr = SetVDirProperty(pADs, L"AccessWrite",bstrAccessWrite);
  1279. IIsScoLogFailure();
  1280. }
  1281. if ( bstrAccessRead.Length() > 0 && SUCCEEDED(hr))
  1282. {
  1283. hr = SetVDirProperty(pADs, L"AccessExecute",bstrAccessExecute);
  1284. IIsScoLogFailure();
  1285. }
  1286. // Step 5: If AppCreate is FALSE, then remove the following properties.
  1287. bstrAppCreate.ToUpper();
  1288. if ( SUCCEEDED(hr) && StringCompare(bstrAppCreate, IIS_FALSE) )
  1289. {
  1290. hr = DeleteMetaPropertyValue(pADs, L"AppIsolated");
  1291. if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppRoot");
  1292. if SUCCEEDED(hr) hr = DeleteMetaPropertyValue(pADs, L"AppFriendlyName");
  1293. IIsScoLogFailure();
  1294. }
  1295. } // end if step 3
  1296. }
  1297. else
  1298. {
  1299. // L"DeleteVDirRollback: VirtualDirectory child node missing from XML DOM Rollback data."
  1300. IIsScoLogFailure();
  1301. } // end if child node
  1302. }
  1303. else
  1304. {
  1305. // L"DeleteVDirRollback: Could not load XML DOM from Rollback data."
  1306. IIsScoLogFailure();
  1307. } // end if loadXML
  1308. }
  1309. else
  1310. {
  1311. // L"DeleteVDirRollback: xml string from Rollback data NULL."
  1312. IIsScoLogFailure();
  1313. } // end if xmlString != NULL
  1314. // "DeleteVDirRollback failed."
  1315. if ( FAILED(hr) )
  1316. IIsScoLogFailure();
  1317. TRACE_EXIT(L"CIISSCO50::DeleteVDirRollback");
  1318. return hr;
  1319. }
  1320. ///////////////////////////////////////////////////////////////////////////////
  1321. // CIISSCO50::SetConfigProperty_Execute
  1322. // Author: Russ Gibfried
  1323. // Params: [in] none
  1324. // [out] none
  1325. // Purpose: Called by MAPS framework to set a IIS property value.
  1326. //-------------------------------------------------------------
  1327. HRESULT CIISSCO50::SetConfigProperty_Execute( IXMLDOMNode *pXMLNode )
  1328. {
  1329. TRACE_ENTER(L"CIISSCO50::SetConfigProperty");
  1330. HRESULT hr = S_OK;
  1331. CComBSTR bstrPathXML; // metabase path
  1332. CComBSTR bstrPropertyXML; // IIS property to set
  1333. CComBSTR bstrNewValueXML; // new property value
  1334. CComBSTR bstrOldValue; // current value for roll-back
  1335. CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
  1336. CComPtr<IXMLDOMNode> pNode;
  1337. CComBSTR propertyXML;
  1338. // Get node in format: <executeData><Website number=''><Root />...
  1339. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  1340. CComBSTR bstrDebug;
  1341. hr = pNode->get_xml(&bstrDebug);
  1342. ATLTRACE(_T("\t>>>SetConfigProperty_Execute: xml = : %ls\n"), bstrDebug.m_str);
  1343. // Step 1: Get the metabase path, property name and pointer to Property Node
  1344. hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
  1345. if (SUCCEEDED(hr)) hr = GetInputAttr(pNode, L"./Property", L"name", bstrPropertyXML);
  1346. if (SUCCEEDED(hr)) hr = GetInputParam(pNode, L"./Property", bstrNewValueXML);
  1347. // Step 2: Get current value
  1348. if (SUCCEEDED(hr))
  1349. {
  1350. // Create a IIS metabase path. ex. IIS://W3SVC/MyServer/1
  1351. bstrAdsiPath = IIS_PREFIX;
  1352. bstrAdsiPath.AppendBSTR(bstrPathXML);
  1353. // Bind to ADs object
  1354. CComPtr<IADs> pADs;
  1355. hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
  1356. if (SUCCEEDED(hr))
  1357. {
  1358. hr = GetMetaPropertyValue(pADs, bstrPropertyXML, bstrOldValue);
  1359. IIsScoLogFailure();
  1360. //Step 3: Set property data
  1361. if (SUCCEEDED(hr))
  1362. {
  1363. hr = SetMetaPropertyValue(pADs, bstrPropertyXML, bstrNewValueXML);
  1364. IIsScoLogFailure();
  1365. } // End if 'GetIIsPropertyValue'
  1366. }
  1367. else
  1368. {
  1369. // "SetConfigProperty: Failed to bind to ADs object."
  1370. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  1371. IIsScoLogFailure();
  1372. }
  1373. }
  1374. else
  1375. {
  1376. hr = E_SCO_IIS_MISSING_FIELD;
  1377. } //End if 'Step 2'
  1378. // If there is a failure
  1379. if ( FAILED(hr) )
  1380. {
  1381. // SetConfigProperty Failed
  1382. IIsScoLogFailure();
  1383. }
  1384. else
  1385. {
  1386. // convert BSTR to Variant and save in RollbackData
  1387. CComVariant varData1(bstrAdsiPath);
  1388. hr = m_pProvHelper->SetRollbackData(L"ConfigPath", varData1);
  1389. // convert BSTR to Variant and save in RollbackData
  1390. CComVariant varData2(bstrPropertyXML);
  1391. hr = m_pProvHelper->SetRollbackData(L"Property", varData2);
  1392. // convert BSTR to Variant and save in RollbackData
  1393. CComVariant varData3(bstrOldValue);
  1394. hr = m_pProvHelper->SetRollbackData(L"Value", varData3);
  1395. }
  1396. TRACE_EXIT(L"CIISSCO50::SetConfigProperty");
  1397. return hr;
  1398. }
  1399. ///////////////////////////////////////////////////////////////////////////////
  1400. // CIISSCO50::SetConfigProperty_Rollback
  1401. // Author: Russ Gibfried
  1402. // Params: [in] none
  1403. // [out] none
  1404. // Purpose: Called by MAPS framework to rollback a failed called
  1405. // tp 'SetMbProperty' above.
  1406. //-------------------------------------------------------------
  1407. HRESULT CIISSCO50::SetConfigProperty_Rollback( IXMLDOMNode *pXMLNode )
  1408. {
  1409. TRACE_EXIT(L"CIISSCO50::SetConfigPropertyRollback");
  1410. HRESULT hr = S_OK;
  1411. CComBSTR bstrAdsiPath;
  1412. CComBSTR bstrPropertyXML;
  1413. CComBSTR bstrOldValue;
  1414. // Get Rollback values, then convert from variants to BSTRs
  1415. CComVariant varAdsiPath;
  1416. hr = m_pProvHelper->GetRollbackData(L"ConfigPath", &varAdsiPath);
  1417. CComVariant varPropertyXML;
  1418. if (SUCCEEDED(hr)) hr = m_pProvHelper->GetRollbackData(L"Property", &varPropertyXML);
  1419. CComVariant varOldValue;
  1420. if (SUCCEEDED(hr)) hr = m_pProvHelper->GetRollbackData(L"Value", &varOldValue);
  1421. if (SUCCEEDED(hr))
  1422. {
  1423. // Convert to BSTRs
  1424. bstrAdsiPath = varAdsiPath.bstrVal;
  1425. bstrPropertyXML = varPropertyXML.bstrVal;
  1426. bstrOldValue = varOldValue.bstrVal;
  1427. // Bind to ADs object
  1428. CComPtr<IADs> pADs;
  1429. hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
  1430. if (SUCCEEDED(hr))
  1431. {
  1432. hr = SetMetaPropertyValue(pADs, bstrPropertyXML, bstrOldValue);
  1433. IIsScoLogFailure();
  1434. }
  1435. else
  1436. {
  1437. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  1438. IIsScoLogFailure();
  1439. }
  1440. }
  1441. else
  1442. {
  1443. // "SetConfigPropertyRollback: Failed to retrieve required rollback property ."
  1444. hr = E_SCO_IIS_MISSING_FIELD;
  1445. IIsScoLogFailure();
  1446. }
  1447. // Log failure -- SetConfigPropertyRollback Failed
  1448. if ( FAILED(hr) )
  1449. IIsScoLogFailure();
  1450. TRACE_EXIT(L"CIISSCO50::SetConfigPropertyRollback");
  1451. return hr;
  1452. }
  1453. ///////////////////////////////////////////////////////////////////////////////
  1454. // CIISSCO50::GetConfigProperty_Execute
  1455. // Method: GetConfigProperty
  1456. // Author: Russ Gibfried
  1457. // Params: [in] none
  1458. // [out] none
  1459. // Purpose: Called by MAPS framework to get a IIS property value.
  1460. //-------------------------------------------------------------
  1461. HRESULT CIISSCO50::GetConfigProperty_Execute( IXMLDOMNode *pXMLNode )
  1462. {
  1463. TRACE_ENTER(L"CIISSco50Obj::GetConfigProperty");
  1464. HRESULT hr = S_OK;
  1465. CComBSTR bstrPathXML; // metabase path
  1466. CComBSTR bstrPropertyXML; // IIS property to set
  1467. CComBSTR bstrValue; // property value
  1468. CComBSTR bstrAdsiPath; // complete IIS metabase path
  1469. CComPtr<IXMLDOMNode> pNode; // xml node <property>
  1470. // Get node in format: <executeData><Website number=''><Root />...
  1471. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  1472. CComBSTR bstrDebug;
  1473. hr = pNode->get_xml(&bstrDebug);
  1474. ATLTRACE(_T("\t>>>GetConfigProperty_Execute: xml = : %ls\n"), bstrDebug.m_str);
  1475. // Step 1: Get the metabase path, property name and pointer to Property Node
  1476. hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
  1477. hr = GetInputAttr(pNode, L"./Property", L"name", bstrPropertyXML);
  1478. // Step 2: Get current value
  1479. if (SUCCEEDED(hr))
  1480. {
  1481. // Create a IIS metabase path. ex. IIS://W3SVC/MyServer/1
  1482. bstrAdsiPath.Append(IIS_PREFIX);
  1483. bstrAdsiPath.AppendBSTR(bstrPathXML);
  1484. // Bind to ADs object
  1485. CComPtr<IADs> pADs;
  1486. hr = ADsGetObject(bstrAdsiPath, IID_IADs, (void**) &pADs );
  1487. if (SUCCEEDED(hr))
  1488. {
  1489. hr = GetMetaPropertyValue(pADs, bstrPropertyXML, bstrValue);
  1490. if (SUCCEEDED(hr))
  1491. {
  1492. // Set the element value
  1493. hr = PutElement(pNode, L"./Property", bstrValue.m_str);
  1494. // Debug render the xml
  1495. CComBSTR bstring;
  1496. hr = pNode->get_xml(&bstring);
  1497. ATLTRACE(_T("\tGetConfigProperty: %ws\n"), bstring);
  1498. IIsScoLogFailure();
  1499. }
  1500. else
  1501. {
  1502. // "GetConfigProperty: Failed to get property."
  1503. hr = E_SCO_IIS_GET_PROPERTY_FAILED;
  1504. IIsScoLogFailure();
  1505. } // End if 'GetIIsPropertyValue'
  1506. }
  1507. else
  1508. {
  1509. // "GetConfigProperty: Failed to bind to ADs object."
  1510. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  1511. IIsScoLogFailure();
  1512. }
  1513. }
  1514. else
  1515. {
  1516. // "GetConfigProperty: Input values missing."
  1517. hr = E_SCO_IIS_MISSING_FIELD;
  1518. IIsScoLogFailure();
  1519. }
  1520. // GetConfigProperty failed
  1521. if ( FAILED(hr) )
  1522. IIsScoLogFailure();
  1523. TRACE_EXIT(L"CIISSco50Obj::GetConfigProperty");
  1524. return hr;
  1525. }
  1526. ///////////////////////////////////////////////////////////////////////////////
  1527. // CIISSCO50::EnumConfig_Execute
  1528. // Params: [in] none
  1529. // [out] none
  1530. // Purpose: Called by MAPS framework to list properties on a given adsi path.
  1531. // It will also list subnodes
  1532. // This is analogous to adsutil enum /w3svc/1
  1533. //-------------------------------------------------------------
  1534. HRESULT CIISSCO50::EnumConfig_Execute( IXMLDOMNode *pXMLNode )
  1535. {
  1536. TRACE_ENTER(L"CIISSCO50::EnumConfig");
  1537. HRESULT hr = S_OK;
  1538. CComBSTR bstrPathXML; // metabase path
  1539. CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
  1540. CComBSTR bstrIsInherit; // True or false to check inheritable properties
  1541. CComPtr<IXMLDOMNode> pNode;
  1542. CComPtr<IXMLDOMNode> pConfigNode;
  1543. CComPtr<IXMLDOMNode> pTemp;
  1544. CComBSTR xmlString;
  1545. // Get node in format: <executeData><Website number=''><Root />...
  1546. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  1547. CComBSTR bstrDebug;
  1548. hr = pNode->get_xml(&bstrDebug);
  1549. ATLTRACE(_T("\t>>>EnumConfig_Execute: xml = : %ls\n"), bstrDebug.m_str);
  1550. // Step .5: Get isInheritable flag. If blank, then default = TRUE
  1551. hr = GetInputAttr(pNode, L"./ConfigPath", XML_ATT_ISINHERITABLE, bstrIsInherit);
  1552. // Step 1: Get the metabase path
  1553. hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
  1554. if (SUCCEEDED(hr))
  1555. {
  1556. // Step 2 Create a IIS metabase path to find properties on. ex. IIS://W3SVC/MyServer/1
  1557. bstrAdsiPath = IIS_PREFIX;
  1558. bstrAdsiPath.AppendBSTR(bstrPathXML);
  1559. // Step 3: Returns map of all properties set on this path (not inherited)
  1560. Map myProps;
  1561. hr = EnumPropertyValue(bstrAdsiPath, bstrIsInherit, myProps);
  1562. if (SUCCEEDED(hr) )
  1563. {
  1564. // Step 4: Create the <ConfigPath> element and append to pNode
  1565. xmlString = "<ConfigPath name='";
  1566. xmlString.AppendBSTR(bstrAdsiPath);
  1567. xmlString.Append(L"'></ConfigPath>");
  1568. hr = AppendElement(pNode,xmlString,pConfigNode);
  1569. if ( SUCCEEDED(hr))
  1570. {
  1571. // Iterate through property Map and append to pNode
  1572. Map::iterator it;
  1573. for (it=myProps.begin(); it != myProps.end(); it++)
  1574. {
  1575. // Create property element: <Property name='myProp'>ItsValue</Property>
  1576. xmlString = "<Property name='";
  1577. xmlString.AppendBSTR((*it).first);
  1578. xmlString.Append(L"'>");
  1579. xmlString.AppendBSTR((*it).second);
  1580. xmlString.Append(L"</Property>");
  1581. hr = AppendElement(pConfigNode,xmlString,pTemp);
  1582. pTemp = NULL;
  1583. }
  1584. }
  1585. else
  1586. {
  1587. // "EnumConfig: Call to AppendElement failed."
  1588. IIsScoLogFailure();
  1589. }
  1590. // Step 5: Get a List of subnodes and append to pNode
  1591. Map myNode;
  1592. int iCount = 0;
  1593. hr = EnumPaths(false,bstrAdsiPath,myNode);
  1594. if (SUCCEEDED(hr) )
  1595. {
  1596. // Iterate through subnodes and append to pNode
  1597. Map::iterator it;
  1598. for (it=myNode.begin(); it != myNode.end(); it++)
  1599. {
  1600. // In this case, skip the first element since it will
  1601. // be the <ConfigPath> already listed above.
  1602. if ( iCount != 0 )
  1603. {
  1604. xmlString = "<ConfigPath name='";
  1605. xmlString.AppendBSTR((*it).first);
  1606. xmlString.Append(L"' />");
  1607. hr = AppendElement(pNode,xmlString,pTemp);
  1608. pTemp = NULL;
  1609. }
  1610. iCount++;
  1611. }
  1612. }
  1613. else
  1614. {
  1615. // "EnumConfig: Failed to enumerate paths."
  1616. IIsScoLogFailure();
  1617. }
  1618. }
  1619. else
  1620. {
  1621. // "EnumConfig: Failed to enumerate properties."
  1622. IIsScoLogFailure();
  1623. }
  1624. }
  1625. else
  1626. {
  1627. // "EnumConfig: Input parameter missing."
  1628. hr = E_SCO_IIS_MISSING_FIELD;
  1629. IIsScoLogFailure();
  1630. } //End if 'Step 2'
  1631. TRACE_EXIT(L"CIISSco50Obj::EnumConfig");
  1632. return hr;
  1633. }
  1634. ///////////////////////////////////////////////////////////////////////////////
  1635. // CIISSCO50::EnumConfigRecursive_Execute
  1636. // Author: Russ Gibfried
  1637. // Params: [in] none
  1638. // [out] none
  1639. // Purpose: Called by MAPS framework to list properties on a given adsi path plus
  1640. // recursively list all subnodes and their properties
  1641. // This is analogous to adsutil enum_all /w3svc/1
  1642. // Note: Only mandatory and optional properties specifically set
  1643. // on a given node are listed since listing all inherited properties
  1644. // would result in a huge output to MAPS
  1645. //-------------------------------------------------------------
  1646. HRESULT CIISSCO50::EnumConfigRecursive_Execute( IXMLDOMNode *pXMLNode )
  1647. {
  1648. TRACE_ENTER(L"CIISSCO50::EnumConfigRecursive");
  1649. HRESULT hr = S_OK;
  1650. CComBSTR bstrPathXML; // metabase path
  1651. CComBSTR bstrAdsiPath; // adsi path: IIS:// + bstrPathXML
  1652. CComBSTR bstrIsInherit; // isInheritable flag (default is true)
  1653. CComPtr<IXMLDOMNode> pNode;
  1654. CComPtr<IXMLDOMNode> pConfigNode;
  1655. CComPtr<IXMLDOMNode> pTemp;
  1656. CComBSTR xmlString;
  1657. Map myNode; // map of adsi paths
  1658. Map myProps; // map of property/values
  1659. Map::iterator it1;
  1660. Map::iterator it2;
  1661. // Get node in format: <executeData><Website number=''><Root />...
  1662. hr = pXMLNode->selectSingleNode( L"//executeXml/executeData", &pNode );
  1663. CComBSTR bstrDebug;
  1664. hr = pNode->get_xml(&bstrDebug);
  1665. ATLTRACE(_T("\t>>>EnumConfigRecursive_Execute: xml = : %ls\n"), bstrDebug.m_str);
  1666. // Step .5: Get isInheritable flag. If blank, then default = TRUE
  1667. hr = GetInputAttr(pNode, L"./ConfigPath", XML_ATT_ISINHERITABLE, bstrIsInherit);
  1668. // Step 1: Get the metabase path
  1669. hr = GetInputAttr(pNode, L"./ConfigPath", L"name", bstrPathXML);
  1670. if (SUCCEEDED(hr))
  1671. {
  1672. // Step 2 Create a IIS metabase path to find properties on. ex. IIS://W3SVC/MyServer/1
  1673. bstrAdsiPath = IIS_PREFIX;
  1674. bstrAdsiPath.AppendBSTR(bstrPathXML);
  1675. // Step 3: Get a list of all nodes; 'true' for recursive
  1676. hr = EnumPaths(true,bstrAdsiPath,myNode);
  1677. if (SUCCEEDED(hr) )
  1678. {
  1679. // Iterate through subnodes and append to pNode
  1680. for (it1=myNode.begin(); it1 != myNode.end(); it1++)
  1681. {
  1682. xmlString = "<ConfigPath name='";
  1683. xmlString.AppendBSTR((*it1).first);
  1684. xmlString.Append(L"'></ConfigPath>");
  1685. hr = AppendElement(pNode,xmlString,pConfigNode);
  1686. // Step 4: Returns map of all properties set on this path (not inherited)
  1687. if ( SUCCEEDED(hr))
  1688. {
  1689. myProps.clear();
  1690. // Pass in the path from map (ie, IIS:/w3svc/localhost/1/root )
  1691. hr = EnumPropertyValue((*it1).first,bstrIsInherit, myProps);
  1692. if (SUCCEEDED(hr) )
  1693. {
  1694. // Iterate through property Map and append to pNode
  1695. for (it2=myProps.begin(); it2 != myProps.end(); it2++)
  1696. {
  1697. // Create property element: <Property name='myProp'>ItsValue</Property>
  1698. xmlString = "<Property name='";
  1699. xmlString.AppendBSTR((*it2).first);
  1700. xmlString.Append(L"'>");
  1701. xmlString.AppendBSTR((*it2).second);
  1702. xmlString.Append(L"</Property>");
  1703. hr = AppendElement(pConfigNode,xmlString,pTemp);
  1704. pTemp = NULL;
  1705. }
  1706. // Done with pConfigNode so set it to NULL
  1707. pConfigNode = NULL;
  1708. }
  1709. else
  1710. {
  1711. // "EnumConfigRecursive: Call to EnumPropertyValue failed."
  1712. IIsScoLogFailure();
  1713. }
  1714. }
  1715. else
  1716. {
  1717. // "EnumConfigRecursive: Call to AppendElement failed."
  1718. IIsScoLogFailure();
  1719. }
  1720. } // end for myNode
  1721. }
  1722. else
  1723. {
  1724. // "EnumConfigRecursive: Failed to enumerate paths."
  1725. IIsScoLogFailure();
  1726. }
  1727. }
  1728. else
  1729. {
  1730. // "EnumConfigRecursive: Input parameter missing."
  1731. hr = E_SCO_IIS_MISSING_FIELD;
  1732. IIsScoLogFailure();
  1733. } //End if 'Step 2'
  1734. TRACE_EXIT(L"CIISSCO50::EnumConfigRecursive");
  1735. return hr;
  1736. }
  1737. //--------------------------- ADSI Helper Methods ------------------------------//
  1738. //-----------------------------------------------------------
  1739. // Method: GetMetaPropertyValue
  1740. // Author: Russ Gibfried
  1741. // Params: [in] pADs -- IADs pointer to metabase path for property value
  1742. // bstrName -- name or property
  1743. // [out] pVal -- value of property
  1744. // Purpose: Return value of particular property
  1745. //-------------------------------------------------------------
  1746. HRESULT CIISSCO50::GetMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName, CComBSTR& pVal)
  1747. {
  1748. HRESULT hr;
  1749. CComVariant var;
  1750. CComBSTR bValue;
  1751. hr = pADs->Get(bstrName, &var);
  1752. if (SUCCEEDED(hr))
  1753. {
  1754. switch (var.vt)
  1755. { case VT_EMPTY:
  1756. {
  1757. break;
  1758. }
  1759. case VT_NULL:
  1760. {
  1761. break;
  1762. }
  1763. case VT_I4:
  1764. {
  1765. hr = var.ChangeType(VT_BSTR);
  1766. if ( SUCCEEDED(hr) ) pVal = V_BSTR(&var);
  1767. break;
  1768. }
  1769. case VT_BSTR:
  1770. {
  1771. pVal = V_BSTR(&var);
  1772. break;
  1773. }
  1774. case VT_BOOL:
  1775. {
  1776. if (var.boolVal == 0)
  1777. {
  1778. pVal = L"False";
  1779. }
  1780. else
  1781. {
  1782. pVal = L"True";
  1783. }
  1784. break;
  1785. }
  1786. case VT_ARRAY|VT_VARIANT: // SafeArray of Variants
  1787. {
  1788. LONG lstart, lend;
  1789. SAFEARRAY *sa = V_ARRAY( &var );
  1790. VARIANT varItem;
  1791. // Get the lower and upper bound
  1792. hr = SafeArrayGetLBound( sa, 1, &lstart );
  1793. hr = SafeArrayGetUBound( sa, 1, &lend );
  1794. // Now iterate and print the content
  1795. VariantInit(&varItem);
  1796. CComBSTR bString;
  1797. for ( long idx=lstart; idx <= lend; idx++ )
  1798. {
  1799. hr = SafeArrayGetElement( sa, &idx, &varItem );
  1800. pVal = V_BSTR(&varItem);
  1801. VariantClear(&varItem);
  1802. }
  1803. break;
  1804. }
  1805. case VT_DISPATCH:
  1806. {
  1807. //if (!_wcsicmp(bstrName, L"ipsecurity"))
  1808. break;
  1809. }
  1810. default:
  1811. { break;
  1812. }
  1813. }
  1814. }
  1815. if ( FAILED(hr))
  1816. hr = E_SCO_IIS_GET_PROPERTY_FAILED;
  1817. return hr;
  1818. }
  1819. //-----------------------------------------------------------
  1820. // Method: SetMetaPropertyValue
  1821. // Author: Russ Gibfried
  1822. // Params: [in] pADs -- pointer to metabase path object; ie 'IIS://MachineName/W3SVC/1'
  1823. // bstrName -- name or property
  1824. // bstrValue -- property value to set
  1825. // [out] none
  1826. // Purpose: Set the value of particular a particular property
  1827. //-------------------------------------------------------------
  1828. HRESULT CIISSCO50::SetMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName, CComBSTR bstrValue)
  1829. {
  1830. HRESULT hr = E_SCO_IIS_SET_PROPERTY_FAILED;
  1831. hr = pADs->Put(bstrName, CComVariant(bstrValue));
  1832. if (SUCCEEDED(hr))
  1833. {
  1834. hr = pADs->SetInfo();
  1835. }
  1836. return hr;
  1837. }
  1838. //-----------------------------------------------------------
  1839. // Method: DeleteMetaPropertyValue
  1840. // Author: Russ Gibfried
  1841. // Params: [in] pADs -- pointer to metabase path object; ie 'IIS://MachineName/W3SVC/1'
  1842. // bstrName -- name or property
  1843. // bstrValue -- property value to set
  1844. // [out] none
  1845. // Purpose: Set the value of particular a particular property
  1846. //-------------------------------------------------------------
  1847. HRESULT CIISSCO50::DeleteMetaPropertyValue(CComPtr<IADs> pADs, CComBSTR bstrName)
  1848. {
  1849. HRESULT hr = E_SCO_IIS_SET_PROPERTY_FAILED;
  1850. VARIANT vProp;
  1851. VariantInit(&vProp);
  1852. hr = pADs->PutEx(1, bstrName, vProp); // 1 = Clear
  1853. if (SUCCEEDED(hr))
  1854. {
  1855. hr = pADs->SetInfo();
  1856. }
  1857. VariantClear(&vProp);
  1858. return hr;
  1859. }
  1860. //-----------------------------------------------------------
  1861. // Method: CreateIIs50Site
  1862. // Author: Russ Gibfried
  1863. // Params: [in] bstrType -- 'Type' of site, ie 'IIsWebServer' or 'IIsFtpServer
  1864. // bWebADsPath -- AdsPath, ex. IIS:/localhost/w3svc
  1865. // bSiteIndex -- Site number, ie, 1
  1866. // [out] bstrConfigPath -- craeted adsi path, ex. IIS://localhost/W3SVC/1
  1867. // Purpose: Set the value of particular a particular property
  1868. //-------------------------------------------------------------
  1869. HRESULT CIISSCO50::CreateIIs50Site(CComBSTR bstrType,CComBSTR bWebADsPath,
  1870. CComBSTR bServerNumber,CComBSTR &bstrConfigPath)
  1871. {
  1872. HRESULT hr = S_OK;
  1873. CComPtr<IADs> pADs;
  1874. CComPtr<IADsContainer> pCont;
  1875. IDispatch* pDisp;
  1876. CComVariant var;
  1877. // Bind to a domain object: 'IIS://MachineName/W3SVC'
  1878. hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
  1879. if (SUCCEEDED(hr))
  1880. {
  1881. //Create a virtual web server
  1882. hr = pCont->Create(bstrType,bServerNumber,&pDisp);
  1883. if ( SUCCEEDED(hr))
  1884. {
  1885. // Get the newly created ConfigPath value
  1886. hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
  1887. if ( SUCCEEDED(hr))
  1888. {
  1889. // Release the IDispath pointer
  1890. pDisp->Release();
  1891. // Get the newly created ADsPath for this Server
  1892. if (SUCCEEDED(hr)) hr = pADs->get_ADsPath(&bstrConfigPath);
  1893. hr = pADs->SetInfo();
  1894. // Return the correct HRESULT depending is Web Site of FTP Site
  1895. if (FAILED(hr))
  1896. {
  1897. if (StringCompare(bstrType,IIS_IISWEBSERVER))
  1898. {
  1899. hr = E_SCO_IIS_CREATE_WEB_FAILED;
  1900. }
  1901. else
  1902. {
  1903. hr = E_SCO_IIS_CREATE_FTP_FAILED;
  1904. }
  1905. }
  1906. }
  1907. } // end if Create
  1908. else
  1909. {
  1910. // Return the correct HRESULT depending is Web Site of FTP Site
  1911. if (StringCompare(bstrType,IIS_IISWEBSERVER))
  1912. {
  1913. hr = E_SCO_IIS_CREATE_WEB_FAILED;
  1914. }
  1915. else
  1916. {
  1917. hr = E_SCO_IIS_CREATE_FTP_FAILED;
  1918. }
  1919. }
  1920. } // end if ADsGetObject
  1921. else
  1922. {
  1923. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  1924. }
  1925. return hr;
  1926. }
  1927. //-----------------------------------------------------------
  1928. // Method: DeleteIIs50Site
  1929. // Author: Russ Gibfried
  1930. // Params: [in] bstrType -- 'Type' of site, ie 'IIsWebServer' or 'IIsFtpServer
  1931. // bWebADsPath -- server adsi path ex. IIS://localhost/W3SVC
  1932. // bServerNumber -- Server index number to delete
  1933. // Purpose: Delete a Web or FTP server
  1934. //-------------------------------------------------------------
  1935. HRESULT CIISSCO50::DeleteIIs50Site(CComBSTR bstrType,CComBSTR bWebADsPath,CComBSTR bServerNumber)
  1936. {
  1937. HRESULT hr = S_OK;
  1938. CComPtr<IADsContainer> pCont;
  1939. // Bind to a domain object: 'IIS://MachineName/W3SVC'
  1940. hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
  1941. //Delete a virtual web server
  1942. if (SUCCEEDED(hr))
  1943. {
  1944. hr = pCont->Delete(bstrType,bServerNumber);
  1945. if (FAILED(hr))
  1946. {
  1947. // Return the correct HRESULT depending is Web Site of FTP Site
  1948. if (StringCompare(bstrType,IIS_IISWEBSERVER))
  1949. {
  1950. hr = E_SCO_IIS_DELETE_WEB_FAILED;
  1951. }
  1952. else
  1953. {
  1954. hr = E_SCO_IIS_DELETE_FTP_FAILED;
  1955. }
  1956. }
  1957. }
  1958. else
  1959. {
  1960. hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
  1961. }
  1962. return hr;
  1963. }
  1964. //-----------------------------------------------------------
  1965. // Method: CreateIIs50VDir
  1966. // Author: Russ Gibfried
  1967. // Params: [in] bstrType -- 'Type' of site, ie 'IIsWebVirtualDir"
  1968. // bWebADsPath -- IIS://localhost/W3SVC/1
  1969. // bVDirName -- url, ex. 'ROOT'
  1970. // bAppFriendName -- 'Default Application'
  1971. // bVDirPath -- url, ex. c:/inetpub/myDir
  1972. //
  1973. // [out] bstrConfigPath -- created adsi path, ex. IIS://localhost/W3SVC/1/ROOT
  1974. // Purpose: Set the value of particular a particular property
  1975. //-------------------------------------------------------------
  1976. HRESULT CIISSCO50::CreateIIs50VDir(CComBSTR bstrType,CComBSTR bWebADsPath, CComBSTR bVDirName,
  1977. CComBSTR bAppFriendName, CComBSTR bVDirPath,CComBSTR &bstrConfigPath)
  1978. {
  1979. HRESULT hr = S_OK;
  1980. CComPtr<IADs> pADs;
  1981. CComPtr<IADsContainer> pCont;
  1982. IDispatch* pDisp;
  1983. CComVariant var;
  1984. // Bind to a domain object: 'IIS://MachineName/W3SVC/1'
  1985. hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
  1986. if (SUCCEEDED(hr))
  1987. {
  1988. //Create a virtual directory for web server
  1989. hr = pCont->Create(bstrType,bVDirName,&pDisp);
  1990. if ( SUCCEEDED(hr))
  1991. {
  1992. // Get the newly created ConfigPath value
  1993. hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
  1994. if ( SUCCEEDED(hr))
  1995. {
  1996. // Release the IDispath pointer
  1997. pDisp->Release();
  1998. // Set Root path and AccessRead
  1999. if (SUCCEEDED(hr)) hr = pADs->Put(L"Path",CComVariant(bVDirPath));
  2000. if (SUCCEEDED(hr)) hr = pADs->Put(L"AccessRead",CComVariant(L"TRUE"));
  2001. // Get the newly created ADsPath for this Server
  2002. if (SUCCEEDED(hr)) hr = pADs->get_ADsPath(&bstrConfigPath);
  2003. // Set the info
  2004. if (SUCCEEDED(hr)) hr = pADs->SetInfo();
  2005. //-----------------------------------------------------
  2006. // RG: Now call AppCreate through IDispatch to set the application
  2007. // Note: This only seems to work for 'IIsWebVirtualDir'??
  2008. //-----------------------------------------------------
  2009. if ( bstrType == "IIsWebVirtualDir" && SUCCEEDED(hr) )
  2010. {
  2011. DISPID dispid;
  2012. LPOLESTR str = OLESTR("AppCreate");
  2013. // Get a pointer to IDispatch from object
  2014. hr = pCont->GetObject(bstrType,bVDirName,&pDisp);
  2015. // See if object supports 'AppCreate' and dispid
  2016. if (SUCCEEDED(hr)) hr = pDisp->GetIDsOfNames(IID_NULL, &str, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  2017. // Set the parameters
  2018. VARIANT myVars[1];
  2019. VariantInit(&myVars[0]);
  2020. myVars[0].vt = VT_BOOL;
  2021. myVars[0].boolVal = true;
  2022. DISPPARAMS params = {myVars,0,1,0};
  2023. // Invoke 'AppCreate'
  2024. if (SUCCEEDED(hr)) hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  2025. DISPATCH_METHOD,&params, NULL, NULL, NULL);
  2026. // Cleanup
  2027. if (SUCCEEDED(hr)) hr = pDisp->Release();
  2028. //VariantClear(&myVars);
  2029. // Set AppFriendlyName
  2030. if (SUCCEEDED(hr)) hr = pADs->Put(L"AppFriendlyName",CComVariant(bAppFriendName));
  2031. // Set the info
  2032. if (SUCCEEDED(hr)) hr = pADs->SetInfo();
  2033. }
  2034. // Check for failure
  2035. if ( FAILED(hr)) hr = E_SCO_IIS_CREATE_VDIR_FAILED;
  2036. }
  2037. else
  2038. {
  2039. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  2040. }
  2041. } // end if Create
  2042. else
  2043. {
  2044. hr = E_SCO_IIS_CREATE_VDIR_FAILED;
  2045. }
  2046. } // end if ADsGetObject
  2047. else
  2048. {
  2049. hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
  2050. }
  2051. return hr;
  2052. }
  2053. //-----------------------------------------------------------
  2054. // Method: DeleteIIs50VDir
  2055. // Author: Russ Gibfried
  2056. // Params: [in] bstrType -- 'Type' of site, ie 'IIsWebVirtualDir"
  2057. // bWebADsPath -- IIS://localhost/W3SVC/1
  2058. // bVDirName -- url, ex. 'ROOT'
  2059. //
  2060. // [out] bstrConfigPath -- created adsi path, ex. IIS://localhost/W3SVC/1/ROOT
  2061. // Purpose: Set the value of particular a particular property
  2062. //-------------------------------------------------------------
  2063. HRESULT CIISSCO50::DeleteIIs50VDir(CComBSTR bstrType,CComBSTR bWebADsPath, CComBSTR bVDirName)
  2064. {
  2065. HRESULT hr = S_OK;
  2066. CComPtr<IADsContainer> pCont;
  2067. IDispatch* pDisp;
  2068. // Bind to a domain object: 'IIS://MachineName/W3SVC/1'
  2069. hr = ADsGetObject( bWebADsPath,IID_IADsContainer, (void **)&pCont);
  2070. if (SUCCEEDED(hr))
  2071. {
  2072. //-----------------------------------------------------
  2073. // RG: Now call AppDelete through IDispatch to set the application
  2074. //-----------------------------------------------------
  2075. DISPID dispid;
  2076. LPOLESTR str = OLESTR("AppDelete");
  2077. // Get a pointer to IDispatch from object
  2078. if (SUCCEEDED(hr)) hr = pCont->GetObject(bstrType,bVDirName,&pDisp);
  2079. // See if object supports 'AppCreate' and dispid
  2080. if (SUCCEEDED(hr)) hr = pDisp->GetIDsOfNames(IID_NULL, &str, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
  2081. // Set the parameters
  2082. //VARIANT myVars[1];
  2083. //VariantInit(&myVars[0]);
  2084. //myVars[0].vt = VT_BOOL;
  2085. ///myVars[0].boolVal = true;
  2086. DISPPARAMS params = {NULL,NULL,0,0};
  2087. // Invoke 'AppCreate'
  2088. if (SUCCEEDED(hr)) hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  2089. DISPATCH_METHOD,&params, NULL, NULL, NULL);
  2090. // Cleanup
  2091. if (SUCCEEDED(hr)) hr = pDisp->Release();
  2092. //VariantClear(&myVars);
  2093. //Delete the virtual directory at VDirName
  2094. if (SUCCEEDED(hr)) hr = pCont->Delete(bstrType,bVDirName);
  2095. if ( FAILED(hr) )
  2096. hr = E_SCO_IIS_DELETE_VDIR_FAILED;
  2097. } // end if ADsGetObject
  2098. else
  2099. {
  2100. hr = E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
  2101. }
  2102. return hr;
  2103. }
  2104. //-----------------------------------------------------------
  2105. // Method: SetVDirProperty
  2106. // Author: Russ Gibfried
  2107. // Params: [in]
  2108. // pADs -- pointer to ADs object for something like IIS://localhost/W3SVC/1/ROOT
  2109. // bVDirProperty -- , ex. 'AuthFlags'
  2110. // bVDirValue -- property value
  2111. //
  2112. // [out] none
  2113. // Purpose: Set the value of particular a particular property for a Virtual Directory
  2114. //-------------------------------------------------------------
  2115. HRESULT CIISSCO50::SetVDirProperty(CComPtr<IADs> pADs, CComBSTR bVDirProperty,CComBSTR bVDirValue)
  2116. {
  2117. HRESULT hr = E_FAIL;
  2118. // Bind to a domain object: 'IIS://MachineName/W3SVC/1/ROOT'
  2119. if ( pADs != NULL )
  2120. {
  2121. // Set the property
  2122. hr = pADs->Put(bVDirProperty,CComVariant(bVDirValue));
  2123. // Set the info
  2124. if (SUCCEEDED(hr)) hr = pADs->SetInfo();
  2125. } // end if ADsGetObject
  2126. if ( FAILED(hr))
  2127. hr = E_SCO_IIS_SET_PROPERTY_FAILED;
  2128. return hr;
  2129. }
  2130. //-----------------------------------------------------------
  2131. // Method: EnumPaths
  2132. // Author: Russ Gibfried
  2133. // Params: [in] bRecursive -- Boolean; true to recursely iterate through subnodes
  2134. // bstrPath -- metabase path for key to Enumerate
  2135. // [out] variant SafeArray
  2136. // Purpose: Enumerate the keys/nodes for a given ADsPath
  2137. // Example: IIS://localhost/W3SVC/1 yields IISCertMapper and Root
  2138. //-------------------------------------------------------------
  2139. HRESULT CIISSCO50::EnumPaths(BOOL bRecursive,CComBSTR bstrPath, Map& mVar)
  2140. {
  2141. //initialize
  2142. HRESULT hr = E_FAIL;
  2143. IADs *pADs;
  2144. CComPtr<IADsContainer> pCont;
  2145. VARIANT var;
  2146. ULONG lFetch;
  2147. IDispatch *pDisp;
  2148. IEnumVARIANT *pEnum;
  2149. // Get the container object for given ADsPath
  2150. hr = ADsGetObject(bstrPath, IID_IADsContainer, (void**) &pCont );
  2151. if ( SUCCEEDED(hr))
  2152. {
  2153. //add to Map
  2154. mVar[bstrPath] = bstrPath;
  2155. // Create a Enum object in container
  2156. hr = ADsBuildEnumerator(pCont, &pEnum);
  2157. // Walk through all providers
  2158. while (hr == S_OK)
  2159. {
  2160. hr = ADsEnumerateNext(pEnum,1,&var,&lFetch);
  2161. if ( lFetch == 1)
  2162. {
  2163. pDisp = V_DISPATCH(&var);
  2164. pDisp->QueryInterface(IID_IADs, (void**)&pADs);
  2165. pDisp->Release();
  2166. BSTR bstr;
  2167. pADs->get_ADsPath(&bstr);
  2168. pADs->Release();
  2169. // true if we are to recursively navigate lower nodes
  2170. if ( bRecursive )
  2171. {
  2172. EnumPaths(bRecursive,bstr, mVar);
  2173. }
  2174. else
  2175. {
  2176. mVar[bstr] = bstr;
  2177. }
  2178. SysFreeString(bstr);
  2179. }
  2180. }
  2181. if ( pEnum )
  2182. ADsFreeEnumerator(pEnum);
  2183. }
  2184. else
  2185. {
  2186. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  2187. }
  2188. return hr;
  2189. }
  2190. //-----------------------------------------------------------
  2191. // Method: EnumPropertyValue
  2192. // Author: Russ Gibfried
  2193. // Params: [in] bstrPath -- metabase path for key to Enumerate
  2194. // [in] bstrIsInHerit -- True/False if required to display inheritable properties
  2195. // [out] variant SafeArray
  2196. // Purpose: Make sure IIS://localhost/W3SVC/2
  2197. //-------------------------------------------------------------
  2198. HRESULT CIISSCO50::EnumPropertyValue(CComBSTR bstrPath, CComBSTR bstrIsInHerit, Map& mVar)
  2199. {
  2200. //initialize
  2201. HRESULT hr = S_OK;
  2202. CComPtr<IADs> pADs;
  2203. CComPtr<IADsClass> pCls;
  2204. CComBSTR bstrSchema;
  2205. CComPtr<IISBaseObject> pBase;
  2206. // variables for SafeArray or properties
  2207. LONG lstart, lend;
  2208. CComBSTR bstrProperty;
  2209. CComBSTR bstrValue;
  2210. // Set bstrIsInHerit to uppercase
  2211. bstrIsInHerit.ToUpper();
  2212. // Bind to a domain object -- this will give us schema, class and name
  2213. hr = ADsGetObject(bstrPath, IID_IADs, (void**) &pADs );
  2214. if ( SUCCEEDED(hr)) hr = pADs->get_Schema(&bstrSchema);
  2215. if ( SUCCEEDED(hr))
  2216. {
  2217. // Bind to IIS Admin Object so we can determine if properties are inherited or not
  2218. hr = ADsGetObject(bstrPath, IID_IISBaseObject, (void**) &pBase );
  2219. if ( SUCCEEDED(hr))
  2220. {
  2221. // Bind to schema object and get all optional properties
  2222. hr = ADsGetObject(bstrSchema,IID_IADsClass, (void**)&pCls);
  2223. if ( SUCCEEDED(hr))
  2224. {
  2225. //********** Get Mandatory Properties ************************
  2226. VARIANT varProperty;
  2227. VariantInit(&varProperty);
  2228. hr = pCls->get_MandatoryProperties(&varProperty);
  2229. // iterate through properties
  2230. if ( SUCCEEDED(hr))
  2231. {
  2232. VARIANT varItem;
  2233. SAFEARRAY *sa = V_ARRAY( &varProperty );
  2234. hr = SafeArrayGetLBound( sa, 1, &lstart );
  2235. hr = SafeArrayGetUBound( sa, 1, &lend );
  2236. VariantInit(&varItem);
  2237. // For loop through properties
  2238. for ( long idx=lstart; idx <= lend; idx++ )
  2239. {
  2240. // Get a property
  2241. hr = SafeArrayGetElement( sa, &idx, &varItem );
  2242. bstrProperty = V_BSTR(&varItem);
  2243. VariantClear(&varItem);
  2244. // if isInheriable = false, then properties must be set on path
  2245. if ( SUCCEEDED(hr) && !StringCompare(bstrIsInHerit, IIS_FALSE) )
  2246. {
  2247. // True -- just return property
  2248. hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
  2249. if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
  2250. }
  2251. else
  2252. {
  2253. // False -- Check if property set on this path
  2254. if ( EnumIsSet(pBase,bstrPath,bstrProperty))
  2255. {
  2256. // This property was set on this path. Get the value and add to map
  2257. hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
  2258. if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
  2259. }
  2260. }
  2261. } // end For
  2262. }
  2263. //********** Repeat for Optional Properties ************************
  2264. VariantClear(&varProperty);
  2265. VariantInit(&varProperty);
  2266. hr = pCls->get_OptionalProperties(&varProperty);
  2267. // iterate through properties
  2268. if ( SUCCEEDED(hr))
  2269. {
  2270. VARIANT varItem;
  2271. SAFEARRAY *sa = V_ARRAY( &varProperty );
  2272. hr = SafeArrayGetLBound( sa, 1, &lstart );
  2273. hr = SafeArrayGetUBound( sa, 1, &lend );
  2274. VariantInit(&varItem);
  2275. // For loop through properties
  2276. for ( long idx=lstart; idx <= lend; idx++ )
  2277. {
  2278. // Get a property
  2279. hr = SafeArrayGetElement( sa, &idx, &varItem );
  2280. bstrProperty = V_BSTR(&varItem);
  2281. VariantClear(&varItem);
  2282. // if isInheriable = false, then properties must be set on path
  2283. if ( SUCCEEDED(hr) && !StringCompare(bstrIsInHerit, IIS_FALSE) )
  2284. {
  2285. // True -- just return property
  2286. hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
  2287. if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
  2288. }
  2289. else
  2290. {
  2291. // False -- Check if property set on this path
  2292. if ( EnumIsSet(pBase,bstrPath,bstrProperty))
  2293. {
  2294. // This property was set on this path. Get the value and add to map
  2295. hr = GetMetaPropertyValue(pADs, bstrProperty, bstrValue);
  2296. if ( SUCCEEDED(hr) ) mVar[bstrProperty] = bstrValue;
  2297. }
  2298. }
  2299. } // end For
  2300. } // end if
  2301. VariantClear(&varProperty);
  2302. }
  2303. else
  2304. {
  2305. // failed to bind to schema
  2306. hr = E_SCO_IIS_ADSCLASS_CREATE_FAILED;
  2307. }
  2308. }
  2309. else
  2310. {
  2311. // failed to bind to IIS BaseObject
  2312. hr = E_SCO_IIS_BASEADMIN_CREATE_FAILED;
  2313. }
  2314. }
  2315. else
  2316. {
  2317. // failed to bind to ADs Object
  2318. hr = E_SCO_IIS_ADS_CREATE_FAILED;
  2319. }
  2320. return hr;
  2321. }
  2322. //-----------------------------------------------------------
  2323. // Method: EnumIsSet
  2324. // Params: [in] pBase -- pointer to IISBaseObject for given 'bstrPath'
  2325. // bstrPath -- adsi Path; IIS://localhost/W3SVC/2
  2326. // bstrProperty -- property found in schema for this path
  2327. // [out] Boolean - True is the property was set for given path and not
  2328. // inherited from another key.
  2329. // Purpose: Function checks the paths returned by 'GetDataPaths' for a given property
  2330. // to current path to determine if property was actually set at this path.
  2331. //
  2332. // Note: You can easily extend this function by adding a flag to only check
  2333. // for inheritable properties, all properties or non-inheritable.
  2334. //-------------------------------------------------------------
  2335. BOOL CIISSCO50::EnumIsSet(CComPtr<IISBaseObject> pBase, CComBSTR bstrPath, CComBSTR bstrProperty)
  2336. {
  2337. VARIANT pvPaths; // list of paths returned by 'GetDataPaths'
  2338. VARIANT *varPath; // property path
  2339. SAFEARRAY *PathArray; // SafeArray to hold pvPaths
  2340. BOOL bFound = false;
  2341. HRESULT hr;
  2342. // Get Property paths
  2343. VariantInit(&pvPaths);
  2344. VariantClear(&pvPaths);
  2345. // Check if this is a inheritable property
  2346. hr = pBase->GetDataPaths(bstrProperty,1,&pvPaths);
  2347. if ( SUCCEEDED(hr) )
  2348. {
  2349. //Any property
  2350. PathArray = pvPaths.parray;
  2351. varPath = (VARIANT*)PathArray->pvData;
  2352. if ( varPath->vt == VT_BSTR)
  2353. {
  2354. if ( !_wcsicmp(varPath->bstrVal,bstrPath.m_str) )
  2355. {
  2356. // This property was set on this path.
  2357. bFound = true;
  2358. }
  2359. }
  2360. }
  2361. // Check if this is not an inheritable property
  2362. else
  2363. {
  2364. VariantClear(&pvPaths);
  2365. VariantInit(&pvPaths);
  2366. hr = pBase->GetDataPaths(bstrProperty,0,&pvPaths);
  2367. if ( SUCCEEDED(hr) )
  2368. {
  2369. //Inheritable property
  2370. PathArray = pvPaths.parray;
  2371. varPath = (VARIANT*)PathArray->pvData;
  2372. if ( varPath->vt == VT_BSTR)
  2373. {
  2374. if ( !_wcsicmp(varPath->bstrVal,bstrPath.m_str))
  2375. {
  2376. // This property was set on this path. Get the value and add to map
  2377. bFound = true;
  2378. }
  2379. }
  2380. } // end if GetDataPaths -- IIS_ANY_PROPERTY
  2381. } // end if GetDataPaths -- IIS_INHERITABLE_ONLY
  2382. VariantClear(&pvPaths);
  2383. return bFound;
  2384. }
  2385. //-----------------------------------------------------------
  2386. // Method: IIsServerAction
  2387. // Author: Russ Gibfried
  2388. // Params: [in] bWebADsPath -- IIS://localhost/W3SVC/1
  2389. // action -- Start, Stop or Pause
  2390. //
  2391. // [out] HRESULT
  2392. // Purpose: Start, stop or pause a web site
  2393. //-------------------------------------------------------------
  2394. HRESULT CIISSCO50::IIsServerAction(CComBSTR bWebADsPath,IIsAction action)
  2395. {
  2396. HRESULT hr = E_FAIL;
  2397. CComPtr<IADsServiceOperations> pService;
  2398. // Bind to a domain object: 'IIS://MachineName/W3SVC/1'
  2399. hr = ADsGetObject( bWebADsPath,IID_IADsServiceOperations, (void **)&pService);
  2400. if (SUCCEEDED(hr))
  2401. {
  2402. // Perform the action on the server
  2403. switch ( action )
  2404. {
  2405. // Start the server
  2406. case start:
  2407. hr = pService->Start();
  2408. break;
  2409. // Stop the server
  2410. case stop:
  2411. hr = pService->Stop();
  2412. break;
  2413. // Pause the Server
  2414. case pause:
  2415. hr = pService->Pause();
  2416. break;
  2417. default:
  2418. break;
  2419. } // end switch
  2420. } // end if
  2421. else
  2422. {
  2423. hr = E_SCO_IIS_ADSSERVICE_CREATE_FAILED;
  2424. }
  2425. return hr;
  2426. }
  2427. //-----------------------------------------------------------
  2428. // Method: GetNextIndex
  2429. // Author: Russ Gibfried
  2430. // Params: [in] bstrPath -- metabase path for IIsWebService
  2431. // bstrName -- name or property
  2432. // bstrValue -- property value to set
  2433. // [out] none
  2434. // Purpose: Set the value of particular a particular property
  2435. //-------------------------------------------------------------
  2436. HRESULT CIISSCO50::GetNextIndex(CComBSTR bstrPath, CComBSTR& pIndex)
  2437. {
  2438. // initialize
  2439. HRESULT hr = S_OK;
  2440. CComPtr<IADs> pObj;
  2441. long lCount = 1;
  2442. CComVariant var = lCount;
  2443. // initialize starting path: IIS://MyServer/W3SVC/
  2444. CComBSTR tempPath = bstrPath.Copy();
  2445. tempPath.Append(L"/");
  2446. // Append 1 to starting path: IIS://MyServer/W3SVC/1
  2447. var.ChangeType(VT_BSTR);
  2448. tempPath.Append(var.bstrVal);
  2449. // Loop through each server until fails, then we have the next server number
  2450. try
  2451. {
  2452. while ( SUCCEEDED( ADsGetObject( tempPath,IID_IADs, (void **)&pObj) ))
  2453. {
  2454. lCount++;
  2455. tempPath = bstrPath.Copy();
  2456. tempPath.Append(L"/");
  2457. var = lCount;
  2458. var.ChangeType(VT_BSTR);
  2459. tempPath.Append(var.bstrVal);
  2460. pObj = NULL;
  2461. }
  2462. }
  2463. catch(...)
  2464. {
  2465. // unhandled exception
  2466. hr=E_FAIL;
  2467. }
  2468. var.ChangeType(VT_BSTR);
  2469. ChkAllocBstr(pIndex,var.bstrVal);
  2470. return hr;
  2471. }
  2472. //------------------------------------------------------------------------------
  2473. // Method: CreateBindingString
  2474. // Author: Russ Gibfried
  2475. // Params: [in] bstrIP -- site IP
  2476. // bstrPort -- site port
  2477. // bstrHostName -- site HostName
  2478. // [out] bstrString -- server binding string
  2479. // Purpose: Creates a binding string in the format IP:Port:Hostname.
  2480. // Used in other methods to check existing server bindings and
  2481. // set new bindings. Both the IP and Hostname parameter of the string are optional.
  2482. //-------------------------------------------------------------------------------
  2483. HRESULT CIISSCO50::CreateBindingString(CComBSTR bstrIP,CComBSTR bstrPort,
  2484. CComBSTR bstrHostName,CComBSTR& bstrString)
  2485. {
  2486. bstrString.AppendBSTR(bstrIP);
  2487. bstrString.Append(L":");
  2488. bstrString.AppendBSTR(bstrPort);
  2489. bstrString.Append(L":");
  2490. bstrString.AppendBSTR(bstrHostName);
  2491. return 0;
  2492. }
  2493. //------------------------------------------------------------------------------
  2494. // Method: CheckBindings
  2495. // Author: Russ Gibfried
  2496. // Params: [in] bWebADsPath -- ADs path to bind to search
  2497. // bstrNewBindings -- site IP
  2498. // [out] none
  2499. // Purpose: This compares current server bindings to the requested new bindings
  2500. // to make sure there is not a duplicate server already running. Binding
  2501. // string format is IP:Port:Hostname.
  2502. //
  2503. // Note Both the IP and Hostname parameter of the string are optional.
  2504. // Any unspecified parameters default to an all-inclusive wildcard.
  2505. //
  2506. // Metabase Path Key Type
  2507. // /LM/MSFTPSVC/N IIsFtpServer
  2508. // /LM/W3SVC/N IIsWebServer
  2509. //-------------------------------------------------------------------------------
  2510. HRESULT CIISSCO50::CheckBindings(CComBSTR bWebADsPath, CComBSTR bstrNewBindings)
  2511. {
  2512. // initialize
  2513. HRESULT hr = E_FAIL;
  2514. CComPtr<IADsContainer> pCont;
  2515. IADs* pADs;
  2516. CComVariant vBindings;
  2517. BSTR bstr;
  2518. IEnumVARIANT* pEnum;
  2519. LPUNKNOWN pUnk;
  2520. VARIANT var;
  2521. IDispatch *pDisp;
  2522. ULONG lFetch;
  2523. VariantInit(&var);
  2524. // Get a container to IIsWebService object
  2525. hr = ADsGetObject(bWebADsPath, IID_IADsContainer, (void**) &pCont );
  2526. if ( !SUCCEEDED(hr) )
  2527. {
  2528. return E_SCO_IIS_ADSCONTAINER_CREATE_FAILED;
  2529. }
  2530. // Get an enumeration of all objects below it
  2531. pCont->get__NewEnum(&pUnk);
  2532. pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
  2533. pUnk->Release();
  2534. // Now Enumerate through objects
  2535. hr = pEnum->Next(1, &var, &lFetch);
  2536. while(hr == S_OK)
  2537. {
  2538. if (lFetch == 1)
  2539. {
  2540. pDisp = V_DISPATCH(&var);
  2541. pDisp->QueryInterface(IID_IADs, (void**)&pADs);
  2542. pDisp->Release();
  2543. pADs->get_Class(&bstr); // Debug to see Class
  2544. SysFreeString(bstr);
  2545. hr = pADs->Get(L"ServerBindings",&vBindings);
  2546. // Check server bindings for this class
  2547. if ( SUCCEEDED(hr) )
  2548. {
  2549. LONG lstart, lend;
  2550. SAFEARRAY *sa = V_ARRAY( &vBindings );
  2551. VARIANT varItem;
  2552. // Get the lower and upper bound
  2553. hr = SafeArrayGetLBound( sa, 1, &lstart );
  2554. hr = SafeArrayGetUBound( sa, 1, &lend );
  2555. // Now iterate and print the content
  2556. VariantInit(&varItem);
  2557. CComBSTR bString;
  2558. for ( long idx=lstart; idx <= lend; idx++ )
  2559. {
  2560. hr = SafeArrayGetElement( sa, &idx, &varItem );
  2561. bString = V_BSTR(&varItem);
  2562. VariantClear(&varItem);
  2563. }
  2564. // Checkbindings. If match then fail;
  2565. if ( bstrNewBindings == bString)
  2566. {
  2567. hr = E_SCO_IIS_DUPLICATE_SITE;
  2568. pEnum->Release();
  2569. VariantClear(&var);
  2570. goto Leave;
  2571. }
  2572. } // end if 'bindings'
  2573. } // end if 'enum'
  2574. VariantClear(&var);
  2575. hr = pEnum->Next(1, &var, &lFetch);
  2576. }; // end while
  2577. pEnum->Release();
  2578. Leave:
  2579. return hr;
  2580. }
  2581. //-----------------------------------------------------------
  2582. // Method: AddBackSlashesToString
  2583. // Author: Russ Gibfried
  2584. // Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
  2585. //
  2586. // [out] bString -- 'redmond\\bob:F'
  2587. // Purpose: If string has only one backslash, add two since backslash is an
  2588. // escape character.
  2589. //-------------------------------------------------------------
  2590. void CIISSCO50::AddBackSlashesToString(CComBSTR& bString)
  2591. {
  2592. // initialize variables
  2593. size_t start, length, db; // string counters
  2594. start = 0; // start of string
  2595. db = 0; // index if '\\' found ( db = double backslash)
  2596. // Convert the BSTR to a std:string
  2597. USES_CONVERSION;
  2598. std::string s = OLE2A(bString.m_str);
  2599. std::string temp1,temp2,temp3 = "";
  2600. length = s.length();
  2601. // Loop through string looking for single slashes
  2602. for (size_t pos = s.find("\\")+1; pos < length; pos = s.find("\\", pos+2)+1)
  2603. {
  2604. // pos = 0 when it goes off end of string
  2605. if ( pos == 0 ) break;
  2606. // find location of double slash
  2607. db = s.find("\\\\",pos-2)+1;
  2608. // pos is the location of a single slash, if it matches db then we really have
  2609. // the first part of a double slash; so skip
  2610. if ( pos != db )
  2611. {
  2612. // replace the single slash with a double '\\'
  2613. temp1 = s.substr(start,pos-1);
  2614. temp2 = s.substr(pos,length);
  2615. s = temp1 + "\\\\" + temp2;
  2616. }
  2617. }
  2618. // return
  2619. bString = A2BSTR(s.c_str());
  2620. }
  2621. //-----------------------------------------------------------
  2622. // Method: ParseBSTR
  2623. // Author: Russ Gibfried
  2624. // Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
  2625. // delim -- deliminator; ie ':' or 'IIS://'
  2626. // iFirstPiece -- starting piece of BSTR to return; ie 1
  2627. // iLastPiece -- ending piece of BSTR to return; ie 99
  2628. //
  2629. // [out] pVal -- piece of BSTR; ie, 'redmond\bob'
  2630. // Purpose: uses std:string functionality to parse an BSTR given a deliminator
  2631. // and which part of BSTR should be returned.
  2632. // ex) bString = "IIS://localhost/W3SVC/1/ROOT/1
  2633. // (bString,1,99,'host') --> /W3SVC/1/ROOT/1
  2634. // (bString,2,3,'/') --> localhost
  2635. // (bString,4,99,'/') --> 1
  2636. // (bString,2,4,'/') --> localhost/W3SVC
  2637. //-------------------------------------------------------------
  2638. HRESULT CIISSCO50::ParseBSTR(CComBSTR bString,CComBSTR sDelim, int iFirstPiece, int iLastPiece,CComBSTR &pVal)
  2639. {
  2640. // ------ initialize variables ------------------
  2641. // start = begining of substring
  2642. // end = end of substring
  2643. // count = counter of number of deliminators found
  2644. // done = variable to end while loop for each piece
  2645. // length = length of original string
  2646. //--------------------------------------
  2647. HRESULT hr = S_OK;
  2648. size_t start,end;
  2649. int iCount, done, iLength;
  2650. done = start = end = 0;
  2651. iCount = 0; // first piece to look for.
  2652. // If last piece is not greater that fist then end
  2653. if ( iLastPiece < iFirstPiece)
  2654. done=1;
  2655. USES_CONVERSION;
  2656. // deliminator
  2657. std::string myDelim = OLE2A(sDelim.m_str);
  2658. long iDelimLen = myDelim.length();
  2659. // my string
  2660. std::string myString = OLE2A(bString.m_str);
  2661. iLength = myString.length();
  2662. // temp and new string
  2663. std::string newString = "";
  2664. std::string tmpString = "";
  2665. while (!done)
  2666. {
  2667. // find the start of the piece
  2668. end = myString.find(myDelim,start);
  2669. if ( iCount >= iFirstPiece && iCount <= (iLastPiece-1))
  2670. {
  2671. //we want this piece
  2672. tmpString = myString.substr(start,end-start);
  2673. newString.append(tmpString);
  2674. // if iCount < iLastPiece and we're not at the end, then append deliminator too
  2675. if ( iCount < (iLastPiece-1) && end < iLength)
  2676. newString.append(myDelim);
  2677. }
  2678. // if we have gone passed end of string quit, else increment
  2679. // deliminator and string counters.
  2680. if ( end >= iLength || iCount >= (iLastPiece-1))
  2681. {
  2682. done = 1;
  2683. }
  2684. else
  2685. {
  2686. start = end + iDelimLen; // increment start
  2687. iCount++;
  2688. }
  2689. }
  2690. //convert string back to BSTR -- A2BSTR
  2691. pVal = A2BSTR(newString.c_str());
  2692. return hr;
  2693. }
  2694. //-----------------------------------------------------------
  2695. // Method: NumberOfDelims
  2696. // Author: Russ Gibfried
  2697. // Params: [in] bString -- BSTR to parse; ie 'redmond\bob:F'
  2698. // sDelim -- deliminator to find
  2699. //
  2700. // [out] int -- number of deliminators found in string
  2701. // Purpose: Return the number of deliminators found in a string. This is used
  2702. // by 'PutElement'
  2703. //-------------------------------------------------------------
  2704. int CIISSCO50::NumberOfDelims(CComBSTR& bString, CComBSTR bDelim)
  2705. {
  2706. // initialize variables
  2707. int iCount = 0;
  2708. int length;
  2709. // Convert the BSTR to a std:string
  2710. USES_CONVERSION;
  2711. std::string s = OLE2A(bString.m_str);
  2712. std::string sDelim = OLE2A(bDelim.m_str);
  2713. length = s.length();
  2714. // Loop through string looking for deliminator
  2715. for (size_t pos = s.find(sDelim)+1; pos < length; pos = s.find(sDelim, pos+2)+1)
  2716. {
  2717. // pos = 0 when it goes off end of string
  2718. if ( pos == 0 ) break;
  2719. iCount++;
  2720. }
  2721. // return
  2722. return iCount;
  2723. }
  2724. /* --------------------- XML Helper Methods ------------------------------- */
  2725. //-----------------------------------------------------------
  2726. // Method: GetElementValueByAttribute
  2727. // Author: Russ Gibfried
  2728. // Params: [in] elementName -- element name to look for
  2729. // [out] pVal -- value of element
  2730. // Purpose: Return value of particular element in XML document
  2731. // <Property name="someName">someValue</Property>
  2732. //-------------------------------------------------------------
  2733. HRESULT CIISSCO50::GetElementValueByAttribute(CComPtr<IXMLDOMNode> pTopNode,CComBSTR elementName, CComBSTR attributeName, CComBSTR& pVal)
  2734. {
  2735. HRESULT hr = S_OK;
  2736. CComPtr<IXMLDOMNodeList> pNodeList; // List of nodes matching elementName
  2737. CComPtr<IXMLDOMNode> pNode; // individual node
  2738. CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
  2739. CComPtr<IXMLDOMNode> pXMLElement;
  2740. // Get a node list, ie, all <Property> tags
  2741. if (S_OK == (hr = pTopNode->selectNodes(elementName,&pNodeList)))
  2742. {
  2743. // Get the number of nodes and loop through them looking for
  2744. // specific Property found in attribute 'name='
  2745. long lLength;
  2746. pNodeList->get_length(&lLength);
  2747. for ( int i=0; i < lLength; i++)
  2748. {
  2749. // Get a node
  2750. hr = pNodeList->get_item(i,&pNode);
  2751. if ( SUCCEEDED(hr))
  2752. {
  2753. //Get 'name' attribute of this nodes <Property> tag
  2754. hr = pNode->get_attributes(&pAttributeMap);
  2755. if ( SUCCEEDED(hr))
  2756. {
  2757. BSTR bstrProperty = SysAllocString(L"");
  2758. hr = pAttributeMap->getNamedItem(L"name",&pXMLElement);
  2759. if (SUCCEEDED(hr)) hr = pXMLElement->get_text(&bstrProperty);
  2760. if (SUCCEEDED(hr))
  2761. {
  2762. // If the property in attribute name is the same as passed in, then get value
  2763. if ( bstrProperty == attributeName.m_str)
  2764. {
  2765. // Setup a BSTR to get element value
  2766. BSTR bstrTemp = SysAllocString(L"");
  2767. hr = pXMLElement->get_text(&bstrTemp);
  2768. // Copy BSTR to CComBSTR and free it
  2769. if (SUCCEEDED(hr)) hr = pVal.CopyTo(&bstrTemp);
  2770. SysFreeString(bstrTemp);
  2771. i = lLength;
  2772. }
  2773. } // end if attribute
  2774. } // end if node
  2775. } //end if pNode
  2776. } // end for
  2777. }
  2778. else
  2779. {
  2780. // element name doesn't exists
  2781. hr = E_FAIL;
  2782. }
  2783. return hr;
  2784. }
  2785. //-----------------------------------------------------------
  2786. // Method: GetInputAttr
  2787. // Author: Russ Gibfried
  2788. // Params: [in] pTopNode -- xml Node pointer
  2789. // AttributeName -- attribute name to look for
  2790. // elementName -- element name
  2791. // [out] pVal -- value of attribute
  2792. // Purpose: Select a tag based on its name (elementName) and
  2793. // Return the value of particular attribute in XML document
  2794. //-------------------------------------------------------------
  2795. HRESULT CIISSCO50::GetInputAttr(CComPtr<IXMLDOMNode> pTopNode, CComBSTR elementName, CComBSTR AttributeName, CComBSTR& pVal)
  2796. {
  2797. HRESULT hr = E_FAIL;
  2798. CComPtr<IXMLDOMNamedNodeMap> pAttributeMap;
  2799. CComPtr<IXMLDOMNode> pNode;
  2800. CComPtr<IXMLDOMNode> pXMLElement;
  2801. if ( pTopNode != NULL )
  2802. {
  2803. // if elementName = "", then at current node
  2804. if ( elementName.Length() == 0 )
  2805. {
  2806. pNode = pTopNode;
  2807. hr = S_OK;
  2808. }
  2809. else
  2810. {
  2811. // Get the node of the element we are looking for ie, "./Website"
  2812. hr = pTopNode->selectSingleNode(elementName,&pNode);
  2813. }
  2814. // Get the attribute value
  2815. if (SUCCEEDED(hr) && pNode != NULL)
  2816. {
  2817. //Get 'name' attribute of this nodes <Property name=''> tag
  2818. hr = pNode->get_attributes(&pAttributeMap);
  2819. if ( SUCCEEDED(hr))
  2820. {
  2821. // Return the attributes value
  2822. hr = pAttributeMap->getNamedItem(AttributeName,&pXMLElement);
  2823. if (SUCCEEDED(hr)) hr = pXMLElement->get_text(&pVal);
  2824. }
  2825. }
  2826. }
  2827. if ( FAILED(hr) ) hr = E_SCO_IIS_XML_ATTRIBUTE_MISSING;
  2828. return hr;
  2829. }
  2830. //-----------------------------------------------------------
  2831. // Method: GetInputParam
  2832. // Author: Russ Gibfried
  2833. // Params: [in] elementName -- element name to look for. ie IpAddress
  2834. // [out] pVal -- value of element ie. 10.2.1.10
  2835. // Purpose: Return value of particular element in XML document
  2836. // ex) <IpAddress>10.2.1.10</IpAddress>
  2837. //-------------------------------------------------------------
  2838. HRESULT CIISSCO50::GetInputParam(CComPtr<IXMLDOMNode> pNode,CComBSTR elementName,CComBSTR& pVal)
  2839. {
  2840. HRESULT hr = E_FAIL;
  2841. CComPtr<IXMLDOMNode> pXMLElement;
  2842. if ( pNode != NULL )
  2843. {
  2844. if (S_OK == (hr = pNode->selectSingleNode(elementName,&pXMLElement)))
  2845. {
  2846. pXMLElement->get_text(&pVal);
  2847. }
  2848. }
  2849. return hr;
  2850. }
  2851. //-----------------------------------------------------------
  2852. // Method: PutElement
  2853. // Author: Russ Gibfried
  2854. // Params: [in] pNode -- xml node pointer
  2855. // elementName -- element name to look for
  2856. // [in] newVal -- new value of element
  2857. // Purpose: Return HRESULT
  2858. //-------------------------------------------------------------
  2859. HRESULT CIISSCO50::PutElement(CComPtr<IXMLDOMNode> pNode, CComBSTR elementName, CComBSTR newVal)
  2860. {
  2861. HRESULT hr = S_OK;
  2862. CComPtr<IXMLDOMDocument> pDoc;
  2863. CComPtr<IXMLDOMNode> pNewNode;
  2864. CComPtr<IXMLDOMNode> pLastChild;
  2865. CComPtr<IXMLDOMNode> pTempNode;
  2866. if ( pNode != NULL )
  2867. {
  2868. // Find the Element 'elementName'
  2869. if (S_OK != (hr = pNode->selectSingleNode(elementName,&pNewNode)))
  2870. {
  2871. // Could not find element so create new node and add to DOM
  2872. hr = CoCreateInstance(
  2873. __uuidof(DOMDocument),
  2874. NULL,
  2875. CLSCTX_ALL,
  2876. __uuidof(IXMLDOMDocument),
  2877. (LPVOID*)&pDoc);
  2878. // Get the node name from the element path. ie, './WebSite/ConfigPath' yields 'ConfigPath'
  2879. int iCount = NumberOfDelims(elementName, L"/");
  2880. CComBSTR bstrElement;
  2881. if ( SUCCEEDED(hr)) hr = ParseBSTR(elementName, L"/", iCount, 99, bstrElement);
  2882. // Create the new node
  2883. VARIANT vtTemp;
  2884. vtTemp.vt = VT_I2;
  2885. vtTemp.iVal = NODE_ELEMENT;
  2886. if ( SUCCEEDED(hr)) hr = pDoc->createNode(vtTemp,bstrElement,NULL, &pNewNode);
  2887. // Insert text in new node
  2888. if ( SUCCEEDED(hr)) hr= pNewNode->put_text(newVal.m_str);
  2889. // Get the last child node
  2890. if ( SUCCEEDED(hr)) hr = pNode->get_lastChild(&pLastChild);
  2891. // Append our new node to the end of the last child node
  2892. if ( SUCCEEDED(hr)) hr = pLastChild->appendChild(pNewNode,&pTempNode);
  2893. // Debug code to verify node built correctly.
  2894. if ( SUCCEEDED(hr))
  2895. {
  2896. CComBSTR bstrDebug;
  2897. hr = pNode->get_xml(&bstrDebug);
  2898. ATLTRACE(_T("\t>>>PutElement: xml = : %ls\n"), bstrDebug.m_str);
  2899. }
  2900. }
  2901. else
  2902. {
  2903. hr = pNewNode->put_text(newVal.m_str);
  2904. }
  2905. }
  2906. return hr;
  2907. }
  2908. //-----------------------------------------------------------
  2909. // Method: AppendElement
  2910. // Author: Russ Gibfried
  2911. // Params: [in] pNode -- xml node pointer
  2912. // xmlString -- well formed XML fragment; ie <Property></Property>
  2913. // [out] pNewNode -- xml pointer to new node
  2914. // Purpose: Return HRESULT
  2915. // Appends a XML tag to the end of a given node.
  2916. //-------------------------------------------------------------
  2917. HRESULT CIISSCO50::AppendElement(CComPtr<IXMLDOMNode> pNode, CComBSTR xmlString,CComPtr<IXMLDOMNode>& pNewNode)
  2918. {
  2919. HRESULT hr = E_FAIL;
  2920. CComPtr<IXMLDOMDocument> pDoc;
  2921. CComPtr<IXMLDOMElement> pNewElement;
  2922. VARIANT_BOOL bSuccess = VARIANT_FALSE;
  2923. if ( pNode != NULL )
  2924. {
  2925. // Load string into XML Document
  2926. hr = CoCreateInstance(
  2927. __uuidof(DOMDocument),
  2928. NULL,
  2929. CLSCTX_ALL,
  2930. __uuidof(IXMLDOMDocument),
  2931. (LPVOID*)&pDoc);
  2932. if (SUCCEEDED(hr)) hr = pDoc->loadXML(xmlString, &bSuccess);
  2933. if ( SUCCEEDED(hr) && bSuccess != VARIANT_FALSE)
  2934. {
  2935. // Get the document element
  2936. hr = pDoc->get_documentElement(&pNewElement);
  2937. if ( SUCCEEDED(hr))
  2938. {
  2939. // append new element to XML node passed in
  2940. hr = pNode->appendChild(pNewElement,&pNewNode);
  2941. }
  2942. }
  2943. }
  2944. return hr;
  2945. }
  2946. //-----------------------------------------------------------
  2947. // Method: GetNodeLength
  2948. // Author: Russ Gibfried
  2949. // Params: [in] pNode -- pointer to xml node
  2950. // elementName -- element name to look for
  2951. // [out] iLength -- number of elements matching that name
  2952. // Purpose: Return HRESULT
  2953. //-------------------------------------------------------------
  2954. HRESULT CIISSCO50::GetNodeLength(CComPtr<IXMLDOMNode> pTopNode, CComBSTR elementName, long *lLength)
  2955. {
  2956. // initialize variables
  2957. HRESULT hr = S_OK;
  2958. CComPtr<IXMLDOMNodeList> pXMLNode;
  2959. long lTemp = 0;
  2960. lLength = &lTemp;
  2961. // Get a node list, ie, all <Property> tags
  2962. if (S_OK == (hr = pTopNode->selectNodes(elementName,&pXMLNode)))
  2963. {
  2964. pXMLNode->get_length(lLength);
  2965. }
  2966. return hr;
  2967. }
  2968. //-----------------------------------------------------------
  2969. // Method: IsPositiveInteger
  2970. // Author: Russ Gibfried
  2971. // Params: [in]
  2972. // bstrPort -- port number as a string
  2973. // [out] Boolean - True if the port is a positive integer
  2974. // Purpose: Function checks if the port or server number is a posivive integer
  2975. // and less than 20,000
  2976. //
  2977. //-------------------------------------------------------------
  2978. BOOL CIISSCO50::IsPositiveInteger(CComBSTR bstrPort)
  2979. {
  2980. BOOL bInteger = false;
  2981. long iPort = 0;
  2982. CComVariant var(bstrPort.m_str);
  2983. // We're
  2984. var.ChangeType(VT_I4);
  2985. iPort = var.lVal;
  2986. if ( iPort > 0 && iPort <= IIS_SERVER_MAX)
  2987. bInteger = true;
  2988. return bInteger;
  2989. }
  2990. //-----------------------------------------------------------
  2991. // Method: StringCompare
  2992. // Author: Russ Gibfried
  2993. // Params: [in] bString1 -- BSTR string1
  2994. // bString2 -- BSTR string2
  2995. //
  2996. // [out] Boolean - True/False if string1 and string2 equal
  2997. // Purpose: Compares to strings and returns 'true' if they are equal.
  2998. //-------------------------------------------------------------
  2999. BOOL CIISSCO50::StringCompare(CComBSTR bstrString1, CComBSTR bstrString2)
  3000. {
  3001. // initialize variables
  3002. bool bEqual = false;
  3003. bEqual = (wcscmp(bstrString1.m_str, bstrString2.m_str) == 0) ? true : false;
  3004. return bEqual;
  3005. }