Source code of Windows XP (NT5)
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.

2826 lines
72 KiB

  1. /*===================================================================
  2. Microsoft IIS
  3. Microsoft Confidential.
  4. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  5. Component: WAMREG
  6. File: WamAdm.cpp
  7. Implementation of WamAdm object, including ClassFactory, IWamAdm,
  8. IMSAdminReplication
  9. Owner: LeiJin
  10. Note:
  11. WamAdm implementation
  12. ===================================================================*/
  13. #include "common.h"
  14. #include "iiscnfg.h"
  15. #include "iwamreg.h"
  16. #include "WamAdm.h"
  17. #include "auxfunc.h"
  18. #include "wmrgexp.h"
  19. #include "dbgutil.h"
  20. #include "mtxrepli.c"
  21. #include "mtxrepl.h"
  22. #ifdef _IIS_6_0
  23. #include "string.hxx"
  24. #include "multisz.hxx"
  25. #include "w3ctrlps.h"
  26. #include "iiscnfgp.h"
  27. #endif // _IIS_6_0
  28. #define ReleaseInterface(p) if (p) { p->Release(); p = NULL; }
  29. const LPCWSTR APPPOOLPATH = L"/LM/W3SVC/AppPools/";
  30. #ifndef DBGERROR
  31. #define DBGERROR(args) ((void)0) /* Do Nothing */
  32. #endif
  33. #ifndef DBGWARN
  34. #define DBGWARN(args) ((void)0) /* Do Nothing */
  35. #endif
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CWamAdmin
  38. /*===================================================================
  39. CWamAdmin
  40. Constructor
  41. Parameter:
  42. NONE.
  43. Return:
  44. ===================================================================*/
  45. CWamAdmin::CWamAdmin()
  46. : m_cRef(1)
  47. {
  48. InterlockedIncrement((long *)&g_dwRefCount);
  49. }
  50. /*===================================================================
  51. ~CWamAdmin
  52. Constructor
  53. Parameter:
  54. NONE.
  55. Return:
  56. ===================================================================*/
  57. CWamAdmin::~CWamAdmin()
  58. {
  59. InterlockedDecrement((long *)&g_dwRefCount);
  60. }
  61. /*===================================================================
  62. CWamAdmin::QueryInterface
  63. QueryInterface, CWamAdmin supports 2 interfaces, one is IID_IWamAdmin,
  64. the other is IID_IMSAdminReplication.
  65. Parameter:
  66. riid
  67. ppv pointer to Interface pointer
  68. Return: HRESULT
  69. ===================================================================*/
  70. STDMETHODIMP CWamAdmin::QueryInterface(REFIID riid, void ** ppv)
  71. {
  72. if (riid == IID_IUnknown || riid == IID_IWamAdmin)
  73. {
  74. *ppv = static_cast<IWamAdmin*>(this);
  75. }
  76. else if (riid == IID_IWamAdmin2)
  77. {
  78. *ppv = static_cast<IWamAdmin2*>(this);
  79. }
  80. else if (riid == IID_IMSAdminReplication)
  81. {
  82. *ppv = static_cast<IMSAdminReplication*>(this);
  83. }
  84. #ifdef _IIS_6_0
  85. else if (riid == IID_IIISApplicationAdmin)
  86. {
  87. *ppv = static_cast<IIISApplicationAdmin*>(this);
  88. }
  89. #endif //_IIS_6_0
  90. else
  91. {
  92. *ppv = NULL;
  93. return E_NOINTERFACE;
  94. }
  95. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  96. return NOERROR;
  97. }
  98. /*===================================================================
  99. CWamAdmin::AddRef
  100. Parameter:
  101. NONE
  102. Return: HRESULT
  103. ===================================================================*/
  104. STDMETHODIMP_(ULONG) CWamAdmin::AddRef( )
  105. {
  106. return InterlockedIncrement(&m_cRef);
  107. }
  108. /*===================================================================
  109. CWamAdmin::Release
  110. Parameter:
  111. NONE
  112. Return: HRESULT
  113. ===================================================================*/
  114. STDMETHODIMP_(ULONG) CWamAdmin::Release( )
  115. {
  116. if (InterlockedDecrement(&m_cRef) == 0)
  117. {
  118. delete this;
  119. return 0;
  120. }
  121. return m_cRef;
  122. }
  123. /*===================================================================
  124. CWamAdmin::AppCreate
  125. Create an application on szMDPath. The fInProc indicates whether the
  126. result application is in-proc or out-proc. If There is already an application
  127. existed on szMDPath, AppCreate will remove the old application if fInProc does not
  128. match with existing application. Otherwise, it is no-op.
  129. Parameter:
  130. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  131. fInProc TRUE if wants to have an InProc application,
  132. FALSE if wants to have an outproc application.
  133. Return: HRESULT
  134. ===================================================================*/
  135. STDMETHODIMP CWamAdmin::AppCreate(LPCWSTR szMDPath, BOOL fInProc)
  136. {
  137. DWORD dwAppMode = (fInProc) ?
  138. eAppRunInProc : eAppRunOutProcIsolated;
  139. return AppCreate2(szMDPath, dwAppMode);
  140. }
  141. /*===================================================================
  142. CWamAdmin::AppDelete
  143. Delete an application on a Metabase Path. If there is no application existed
  144. before, it is no-op.
  145. Parameter:
  146. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  147. fRecursive TRUE if wants to delete applications from all sub nodes of szMDPath,
  148. FALSE otherwise.
  149. Return: HRESULT
  150. ===================================================================*/
  151. STDMETHODIMP CWamAdmin::AppDelete(LPCWSTR szMDPath, BOOL fRecursive)
  152. {
  153. return PrivateDeleteApplication(szMDPath,
  154. fRecursive,
  155. FALSE, // Recoverable?
  156. FALSE); // RemoveAppPool?
  157. }
  158. HRESULT
  159. CWamAdmin::PrivateDeleteApplication
  160. (
  161. LPCWSTR szMDPath,
  162. BOOL fRecursive,
  163. BOOL fRecoverable,
  164. BOOL fRemoveAppPool
  165. )
  166. {
  167. HRESULT hr = NOERROR;
  168. DWORD dwAppMode;
  169. WamRegMetabaseConfig MDConfig;
  170. LPWSTR pwszFormattedPath = NULL;
  171. if (szMDPath == NULL)
  172. {
  173. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  174. }
  175. //
  176. // Refer to function comment of FormatMetabasePath.
  177. //
  178. hr = FormatMetabasePath(szMDPath, &pwszFormattedPath);
  179. if (FAILED(hr))
  180. {
  181. return hr;
  182. }
  183. if (!g_WamRegGlobal.FAppPathAllowConfig(pwszFormattedPath))
  184. {
  185. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  186. }
  187. // Acquire a Lock
  188. g_WamRegGlobal.AcquireAdmWriteLock();
  189. if (!fRecursive)
  190. {
  191. hr = g_WamRegGlobal.DeleteApp(pwszFormattedPath, fRecoverable, fRemoveAppPool);
  192. if (hr == MD_ERROR_DATA_NOT_FOUND)
  193. {
  194. hr = NOERROR;
  195. }
  196. if (FAILED(hr))
  197. {
  198. DBGPRINTF((DBG_CONTEXT, "Failed to Delete on path %S, hr = %08x\n",
  199. szMDPath,
  200. hr));
  201. }
  202. }
  203. else
  204. {
  205. HRESULT hrT = NOERROR;
  206. DWORD dwSizePrefix;
  207. WCHAR* pbBufferTemp = NULL;
  208. DWORD dwBufferSizeTemp = 0;
  209. dwSizePrefix = wcslen(pwszFormattedPath);
  210. hr = MDConfig.MDGetPropPaths(pwszFormattedPath, MD_APP_ISOLATED, &pbBufferTemp, &dwBufferSizeTemp);
  211. if (SUCCEEDED(hr) && pbBufferTemp)
  212. {
  213. WCHAR* pszString = NULL;
  214. WCHAR* pszMetabasePath = NULL;
  215. for (pszString = (LPWSTR)pbBufferTemp;
  216. *pszString != (WCHAR)'\0' && SUCCEEDED(hr);
  217. pszString += (wcslen(pszString) + 1))
  218. {
  219. hr = g_WamRegGlobal.ConstructFullPath(pwszFormattedPath,
  220. dwSizePrefix,
  221. pszString,
  222. &pszMetabasePath
  223. );
  224. if (SUCCEEDED(hr))
  225. {
  226. if (!g_WamRegGlobal.FIsW3SVCRoot(pszMetabasePath))
  227. {
  228. hr = g_WamRegGlobal.DeleteApp(pszMetabasePath, fRecoverable, fRemoveAppPool);
  229. if (FAILED(hr))
  230. {
  231. DBGPRINTF((DBG_CONTEXT, "Failed to Delete on path %S, hr = %08x\n",
  232. pszString,
  233. hr));
  234. break;
  235. }
  236. }
  237. delete [] pszMetabasePath;
  238. pszMetabasePath = NULL;
  239. }
  240. else
  241. {
  242. DBGPRINTF((DBG_CONTEXT, "Failed to DeleteRecoverable, hr = %08x\n",
  243. pszString,
  244. hr));
  245. }
  246. }
  247. delete [] pbBufferTemp;
  248. pbBufferTemp = NULL;
  249. }
  250. else
  251. {
  252. DBGPRINTF((DBG_CONTEXT, "Delete: GetPropPaths failed hr = %08x\n", hr));
  253. }
  254. }
  255. // Release a Lock
  256. g_WamRegGlobal.ReleaseAdmWriteLock();
  257. if (pwszFormattedPath != szMDPath)
  258. {
  259. delete [] pwszFormattedPath;
  260. pwszFormattedPath = NULL;
  261. }
  262. return hr;
  263. }
  264. /*===================================================================
  265. CWamAdmin::AppUnLoad
  266. UnLoad an application on a Metabase Path. If there is no application running
  267. it returns NOERROR.
  268. For non-administrators we prevent them from unloading applications
  269. in the pool. If the recursive flag is set, we will silently
  270. ignore failures due to insufficient access.
  271. Parameter:
  272. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  273. fRecursive TRUE if wants to unload applications from all sub nodes of szMDPath,
  274. FALSE otherwise.
  275. Return: HRESULT
  276. ===================================================================*/
  277. STDMETHODIMP CWamAdmin::AppUnLoad(LPCWSTR szMDPath, BOOL fRecursive)
  278. {
  279. HRESULT hr = NOERROR;
  280. DWORD dwCallBack = 0;
  281. WamRegMetabaseConfig MDConfig;
  282. DWORD dwAppIsolated = 0;
  283. BOOL bIsAdmin = TRUE;
  284. if (szMDPath == NULL || *szMDPath == L'\0')
  285. {
  286. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  287. }
  288. bIsAdmin = MDConfig.HasAdminAccess();
  289. // Acquire a Lock
  290. g_WamRegGlobal.AcquireAdmWriteLock();
  291. if (fRecursive)
  292. {
  293. DWORD dwSizePrefix = wcslen(szMDPath);;
  294. WCHAR* pbBufferTemp = NULL;
  295. DWORD dwBufferSizeTemp = 0;
  296. hr = MDConfig.MDGetPropPaths( szMDPath,
  297. MD_APP_ISOLATED,
  298. &pbBufferTemp,
  299. &dwBufferSizeTemp);
  300. if (SUCCEEDED(hr))
  301. {
  302. WCHAR* pszString = NULL;
  303. WCHAR* pszMetabasePath = NULL;
  304. BOOL bDoUnload;
  305. for( pszString = (LPWSTR)pbBufferTemp;
  306. *pszString != (WCHAR)'\0' && SUCCEEDED(hr);
  307. pszString += (wcslen(pszString) + 1))
  308. {
  309. bDoUnload = TRUE;
  310. hr = g_WamRegGlobal.ConstructFullPath(szMDPath,
  311. dwSizePrefix,
  312. pszString,
  313. &pszMetabasePath
  314. );
  315. if( SUCCEEDED(hr) && !bIsAdmin )
  316. {
  317. hr = MDConfig.MDGetDWORD( pszMetabasePath,
  318. MD_APP_ISOLATED,
  319. &dwAppIsolated );
  320. DBG_ASSERT( SUCCEEDED(hr) );
  321. if( SUCCEEDED(hr) && eAppRunOutProcInDefaultPool == dwAppIsolated )
  322. {
  323. // Do not unload
  324. bDoUnload = FALSE;
  325. DBGPRINTF((DBG_CONTEXT,
  326. "Insufficient Access to unload Application %S, hr = %08x\n",
  327. pszMetabasePath,
  328. hr));
  329. }
  330. }
  331. if( SUCCEEDED(hr) && bDoUnload )
  332. {
  333. hr = g_WamRegGlobal.W3ServiceUtil( pszMetabasePath,
  334. APPCMD_UNLOAD,
  335. &dwCallBack);
  336. }
  337. if( pszMetabasePath )
  338. {
  339. delete [] pszMetabasePath;
  340. pszMetabasePath = NULL;
  341. }
  342. } // for each application
  343. }
  344. if (pbBufferTemp != NULL)
  345. {
  346. delete [] pbBufferTemp;
  347. pbBufferTemp = NULL;
  348. }
  349. }
  350. else
  351. {
  352. if( !bIsAdmin )
  353. {
  354. // Non recursive
  355. hr = MDConfig.MDGetDWORD( szMDPath,
  356. MD_APP_ISOLATED,
  357. &dwAppIsolated );
  358. if( SUCCEEDED(hr) && eAppRunOutProcInDefaultPool == dwAppIsolated )
  359. {
  360. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  361. DBGPRINTF((DBG_CONTEXT,
  362. "Insufficient Access to unload Application %S, hr = %08x\n",
  363. szMDPath,
  364. hr));
  365. }
  366. }
  367. if( SUCCEEDED(hr) )
  368. {
  369. hr = g_WamRegGlobal.W3ServiceUtil(szMDPath, APPCMD_UNLOAD, &dwCallBack);
  370. }
  371. }
  372. // Release a Lock
  373. g_WamRegGlobal.ReleaseAdmWriteLock();
  374. return hr;
  375. }
  376. /*===================================================================
  377. CWamAdmin::AppGetStatus
  378. GetStatus an application on a Metabase Path. If there is an application on the
  379. metabase path, and the application is currently running, the dwStatus is set to
  380. APPSTATUS_RUNNING, if the application is not running, the dwStatus is set to
  381. APPSTATUS_STOPPED, if there is no application defined on the metabase path, the
  382. dwStatus is set to APPSTATUS_NOTDEFINED.
  383. Parameter:
  384. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  385. pdwAppStatus pointer DWORD buffer contains status result.
  386. Return: HRESULT
  387. NOERROR if succeeded.
  388. ===================================================================*/
  389. STDMETHODIMP CWamAdmin::AppGetStatus(LPCWSTR szMDPath, DWORD* pdwAppStatus)
  390. {
  391. HRESULT hr = NOERROR;
  392. HRESULT hrT;
  393. DWORD dwCallBack = 0;
  394. WamRegMetabaseConfig MDConfig;
  395. if (szMDPath == NULL)
  396. {
  397. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  398. }
  399. // Acquire a Lock
  400. g_WamRegGlobal.AcquireAdmWriteLock();
  401. hrT = g_WamRegGlobal.W3ServiceUtil(szMDPath, APPCMD_GETSTATUS, &dwCallBack);
  402. if (dwCallBack == APPSTATUS_Running)
  403. {
  404. *pdwAppStatus = APPSTATUS_RUNNING;
  405. }
  406. else if (dwCallBack == APPSTATUS_Stopped)
  407. {
  408. *pdwAppStatus = APPSTATUS_STOPPED;
  409. }
  410. else
  411. {
  412. DWORD dwAppMode;
  413. hr = MDConfig.MDGetDWORD(szMDPath, MD_APP_ISOLATED, &dwAppMode);
  414. if (hr == MD_ERROR_DATA_NOT_FOUND)
  415. {
  416. *pdwAppStatus = APPSTATUS_NOTDEFINED;
  417. hr = NOERROR;
  418. }
  419. else if (hr == NOERROR)
  420. {
  421. *pdwAppStatus = APPSTATUS_STOPPED;
  422. hr = NOERROR;
  423. }
  424. }
  425. // Release a Lock
  426. g_WamRegGlobal.ReleaseAdmWriteLock();
  427. return hr;
  428. }
  429. /*===================================================================
  430. CWamAdmin::AppDeleteRecoverable
  431. Delete an application on a Metabase Path. If there is no application existed
  432. before, it is no-op. It leaves AppIsolated untouched, because, this value is
  433. needed in Recover operation.
  434. Parameter:
  435. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  436. fRecursive TRUE if wants to deleteRecoverable applications from all sub nodes of szMDPath,
  437. FALSE otherwise.
  438. Return: HRESULT
  439. ===================================================================*/
  440. STDMETHODIMP CWamAdmin::AppDeleteRecoverable(LPCWSTR szMDPath, BOOL fRecursive)
  441. {
  442. return PrivateDeleteApplication(szMDPath,
  443. fRecursive,
  444. TRUE, // Recoverable?
  445. FALSE); // RemoveAppPool?
  446. }
  447. /*===================================================================
  448. CWamAdmin::AppRecover
  449. Recover an application on a Metabase Path. Based on the AppIsolated value
  450. on the metabase path, this function recreates an application.
  451. Parameter:
  452. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  453. fRecursive TRUE if wants to Recover applications from all sub nodes of szMDPath,
  454. FALSE otherwise.
  455. Return: HRESULT
  456. NOERROR if succeeds
  457. ===================================================================*/
  458. STDMETHODIMP CWamAdmin::AppRecover(LPCWSTR szMDPath, BOOL fRecursive)
  459. {
  460. HRESULT hr = NOERROR;
  461. WamRegMetabaseConfig MDConfig;
  462. LPWSTR pwszFormattedPath = NULL;
  463. if (szMDPath == NULL)
  464. {
  465. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  466. }
  467. // Refer to function comment.
  468. hr = FormatMetabasePath(szMDPath, &pwszFormattedPath);
  469. if (FAILED(hr))
  470. {
  471. return hr;
  472. }
  473. //
  474. // Grab the Lock
  475. //
  476. g_WamRegGlobal.AcquireAdmWriteLock();
  477. if (fRecursive)
  478. {
  479. DWORD dwSizePrefix;
  480. WCHAR* pbBufferTemp = 0;
  481. DWORD dwBufferSizeTemp;
  482. dwSizePrefix = wcslen(pwszFormattedPath);
  483. hr = MDConfig.MDGetPropPaths(pwszFormattedPath, MD_APP_ISOLATED, &pbBufferTemp, &dwBufferSizeTemp);
  484. if (SUCCEEDED(hr) && pbBufferTemp)
  485. {
  486. WCHAR *pszString = NULL;
  487. WCHAR *pszMetabasePath = NULL;
  488. for (pszString = (LPWSTR)pbBufferTemp;
  489. *pszString != (WCHAR)'\0' && SUCCEEDED(hr);
  490. pszString += (wcslen(pszString) + 1))
  491. {
  492. hr = g_WamRegGlobal.ConstructFullPath(pwszFormattedPath,
  493. dwSizePrefix,
  494. pszString,
  495. &pszMetabasePath
  496. );
  497. if (SUCCEEDED(hr))
  498. {
  499. if (!g_WamRegGlobal.FIsW3SVCRoot(pszMetabasePath))
  500. {
  501. hr = g_WamRegGlobal.RecoverApp(pszMetabasePath, TRUE);
  502. if (FAILED(hr))
  503. {
  504. DBGPRINTF((DBG_CONTEXT, "Failed to Recover on path %S, hr = %08x\n",
  505. pszMetabasePath,
  506. hr));
  507. break;
  508. }
  509. }
  510. delete [] pszMetabasePath;
  511. pszMetabasePath = NULL;
  512. }
  513. else
  514. {
  515. DBGPRINTF((DBG_CONTEXT, "Failed to Recover, hr = %08x\n",
  516. pszString,
  517. hr));
  518. }
  519. }
  520. }
  521. else
  522. {
  523. DBGPRINTF((DBG_CONTEXT, "Recover: GetPropPaths failed hr = %08x\n", hr));
  524. }
  525. if (pbBufferTemp != NULL)
  526. {
  527. delete [] pbBufferTemp;
  528. pbBufferTemp = NULL;
  529. }
  530. }
  531. else
  532. {
  533. hr = g_WamRegGlobal.RecoverApp(pwszFormattedPath, TRUE);
  534. if (FAILED(hr))
  535. {
  536. DBGPRINTF((DBG_CONTEXT, "Failed to Recover on path %S, hr = %08x\n",
  537. szMDPath,
  538. hr));
  539. }
  540. }
  541. if (SUCCEEDED(hr))
  542. {
  543. MDConfig.SaveData();
  544. }
  545. //
  546. // Release the Lock
  547. //
  548. g_WamRegGlobal.ReleaseAdmWriteLock();
  549. if (pwszFormattedPath != szMDPath)
  550. {
  551. delete [] pwszFormattedPath;
  552. pwszFormattedPath = NULL;
  553. }
  554. return hr;
  555. }
  556. /*==================================================================
  557. CWamAdmin::AppCreate2
  558. Create an application on szMDPath. The dwAppMode indicates whether the
  559. result application is in-proc or out-proc in a default pool or out proc isolated.
  560. If the application exists with the desired mode, it will be a no op. Otherwise,
  561. registration is done.
  562. Parameter:
  563. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  564. dwAppMode
  565. Return: HRESULT
  566. ===================================================================*/
  567. STDMETHODIMP CWamAdmin::AppCreate2(LPCWSTR szMDPath, DWORD dwAppModeIn)
  568. {
  569. HRESULT hr = NOERROR;
  570. DWORD dwAppMode = 0;
  571. BOOL fCreateNewApp = FALSE;
  572. BOOL fDeleteOldApp = FALSE;
  573. WamRegMetabaseConfig MDConfig;
  574. LPWSTR pwszFormattedPath = NULL;
  575. if (szMDPath == NULL)
  576. {
  577. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  578. }
  579. //
  580. // See FormatMetabasePath comment
  581. //
  582. hr = FormatMetabasePath(szMDPath, &pwszFormattedPath);
  583. if (FAILED(hr))
  584. {
  585. return hr;
  586. }
  587. if (!g_WamRegGlobal.FAppPathAllowConfig(pwszFormattedPath))
  588. {
  589. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  590. }
  591. // Acquire a Lock
  592. g_WamRegGlobal.AcquireAdmWriteLock();
  593. hr = MDConfig.MDGetDWORD(pwszFormattedPath, MD_APP_ISOLATED, &dwAppMode);
  594. if (hr == MD_ERROR_DATA_NOT_FOUND)
  595. {
  596. fCreateNewApp = TRUE;
  597. hr = NOERROR;
  598. }
  599. else if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))
  600. {
  601. hr = MDConfig.MDCreatePath(NULL, pwszFormattedPath);
  602. fCreateNewApp = TRUE;
  603. if(FAILED(hr))
  604. {
  605. DBGPRINTF((DBG_CONTEXT, "Failed to create metabase path %S, hr = %08x",
  606. szMDPath,
  607. hr));
  608. }
  609. }
  610. else if (SUCCEEDED(hr))
  611. {
  612. //
  613. // if the input application mode is not the same as defined
  614. // in the metabase, we need to delete the old application as
  615. // defined in the metabase and create a new application as
  616. // specified by dwAppModeIn, the in parameter.
  617. //
  618. if (dwAppMode != dwAppModeIn)
  619. {
  620. fDeleteOldApp = TRUE;
  621. fCreateNewApp = TRUE;
  622. }
  623. }
  624. else
  625. {
  626. DBGPRINTF((DBG_CONTEXT, "Failed to get DWORD on metabase path %S, hr = %08x",
  627. szMDPath,
  628. hr));
  629. }
  630. if (SUCCEEDED(hr))
  631. {
  632. if (fDeleteOldApp)
  633. {
  634. DBG_ASSERT(fCreateNewApp);
  635. hr = g_WamRegGlobal.DeleteApp(pwszFormattedPath, FALSE, FALSE);
  636. if (FAILED(hr))
  637. {
  638. DBGPRINTF((DBG_CONTEXT, "Failed to delete old application on path %S, hr = 08x\n",
  639. szMDPath,
  640. hr));
  641. }
  642. }
  643. if (fCreateNewApp)
  644. {
  645. if (dwAppModeIn == eAppRunOutProcInDefaultPool)
  646. {
  647. hr = g_WamRegGlobal.CreatePooledApp(pwszFormattedPath, FALSE);
  648. }
  649. else if (dwAppModeIn == eAppRunInProc)
  650. {
  651. hr = g_WamRegGlobal.CreatePooledApp(pwszFormattedPath, TRUE);
  652. }
  653. else
  654. {
  655. hr = g_WamRegGlobal.CreateOutProcApp(pwszFormattedPath);
  656. }
  657. if (FAILED(hr))
  658. {
  659. DBGPRINTF((DBG_CONTEXT, "Failed to create new application on path %S, hr = 08x\n",
  660. szMDPath,
  661. hr));
  662. }
  663. }
  664. }
  665. // Release a Lock
  666. g_WamRegGlobal.ReleaseAdmWriteLock();
  667. //
  668. // if pwszFormattedPath is not same as szMDPath
  669. // then FormatMetabasePath() did a memory allocation.
  670. //
  671. if (pwszFormattedPath != szMDPath)
  672. {
  673. delete [] pwszFormattedPath;
  674. pwszFormattedPath = NULL;
  675. }
  676. return hr;
  677. }
  678. //===============================================================================
  679. // Wam Admin Replication implementation
  680. //
  681. //===============================================================================
  682. /*===================================================================
  683. CWamAdmin::GetSignature
  684. Get signature of application configurations. A signature in WAMREG is a checksum from
  685. all the metabase paths that define application.
  686. Parameter:
  687. Return: HRESULT
  688. NOERROR if succeeds
  689. ===================================================================*/
  690. STDMETHODIMP CWamAdmin::GetSignature
  691. (
  692. /* [in] */ DWORD dwBufferSize,
  693. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  694. /* [out */ DWORD __RPC_FAR *pdwMDRequiredBufferSize
  695. )
  696. {
  697. HRESULT hr = NOERROR;
  698. WCHAR *pbBufferTemp = NULL;
  699. DWORD dwBufferSizeTemp = 0;
  700. DWORD dwSignature = 0;
  701. DWORD dwRequiredSize = 0;
  702. WamRegMetabaseConfig MDConfig;
  703. //
  704. // Grab the Lock
  705. //
  706. g_WamRegGlobal.AcquireAdmWriteLock();
  707. hr = MDConfig.MDGetPropPaths(WamRegGlobal::g_szMDW3SVCRoot, MD_APP_ISOLATED, &pbBufferTemp, &dwBufferSizeTemp);
  708. if (SUCCEEDED(hr))
  709. {
  710. WCHAR *pszString = NULL;
  711. WCHAR *pszMetabasePath = NULL;
  712. DWORD dwSignatureofPath = 0;
  713. for (pszString = (LPWSTR)pbBufferTemp;
  714. *pszString != (WCHAR)'\0' && SUCCEEDED(hr);
  715. pszString += (wcslen(pszString) + 1))
  716. {
  717. dwRequiredSize += sizeof(DWORD);
  718. if (dwRequiredSize <= dwBufferSize)
  719. {
  720. hr = g_WamRegGlobal.ConstructFullPath(WamRegGlobal::g_szMDW3SVCRoot,
  721. WamRegGlobal::g_cchMDW3SVCRoot,
  722. pszString,
  723. &pszMetabasePath
  724. );
  725. if (SUCCEEDED(hr))
  726. {
  727. dwSignatureofPath = 0;
  728. hr = MDConfig.GetSignatureOnPath(pszMetabasePath, &dwSignatureofPath);
  729. if (SUCCEEDED(hr))
  730. {
  731. // Add Signature
  732. *(DWORD*)pbBuffer = dwSignatureofPath;
  733. pbBuffer += sizeof(DWORD);
  734. DBGPRINTF((DBG_CONTEXT, "Get Signature on path %S, signature = %08x\n",
  735. pszMetabasePath,
  736. dwSignatureofPath));
  737. }
  738. else
  739. {
  740. DBGPRINTF((DBG_CONTEXT, "Failed to get signature on path %S, hr = %08x\n",
  741. pszString,
  742. hr));
  743. DBG_ASSERT(hr);
  744. }
  745. delete [] pszMetabasePath;
  746. pszMetabasePath = NULL;
  747. }
  748. }
  749. }
  750. if (dwRequiredSize > dwBufferSize)
  751. {
  752. *pdwMDRequiredBufferSize = dwRequiredSize;
  753. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  754. }
  755. }
  756. else
  757. {
  758. DBGPRINTF((DBG_CONTEXT, "GetSignature: GetPropPaths failed hr = %08x\n", hr));
  759. }
  760. if (SUCCEEDED(hr))
  761. {
  762. *pdwMDRequiredBufferSize = dwRequiredSize;
  763. }
  764. if (pbBufferTemp != NULL)
  765. {
  766. delete [] pbBufferTemp;
  767. }
  768. //
  769. // Release the Lock
  770. //
  771. g_WamRegGlobal.ReleaseAdmWriteLock();
  772. return hr;
  773. }
  774. /*===================================================================
  775. CWamAdmin::Propagate
  776. Unused in WAMREG. NOOP.
  777. Parameter:
  778. Return: HRESULT
  779. NOERROR if succeeds
  780. ===================================================================*/
  781. STDMETHODIMP CWamAdmin::Propagate
  782. (
  783. /* [in] */ DWORD dwBufferSize,
  784. /* [size_is][in] */ unsigned char __RPC_FAR *pszBuffer
  785. )
  786. {
  787. return NOERROR;
  788. }
  789. /*===================================================================
  790. CWamAdmin::Propagate2
  791. This function is called after IIS replication, and triggers MTS to start
  792. replication pakcages, it calls IISComputerToComputer.
  793. Parameter:
  794. Return: HRESULT
  795. NOERROR if succeeds
  796. ===================================================================*/
  797. STDMETHODIMP CWamAdmin::Propagate2
  798. (
  799. /* [in] */ DWORD dwBufferSize,
  800. /* [size_is][in] */ unsigned char __RPC_FAR *pszBuffer,
  801. /* [in] */ DWORD dwSignatureMismatch
  802. )
  803. {
  804. //
  805. // IISComputerToComputer can not be called from inetinfo.exe, because IISComputerToComputer will
  806. // make cross-machine RPC call, and inetinfo is set to Local system, therefore, IISComputerToComputer
  807. // will fail at the authentication level.
  808. // move IISComputerToComputer to iissync.exe. Where iissync.exe has some user account & password.
  809. //
  810. return NOERROR;
  811. }
  812. /*===================================================================
  813. CWamAdmin::Serialize
  814. This function packs all neccessary infomation (path + WAMCLSID) for a target
  815. machine to prepare replication(DeSerialize).
  816. The only applications that we really care about are isolated applications.
  817. We need the path + WAMCLSID + APPID.
  818. CODEWORK
  819. See NT Bug 378371
  820. Replication of IIS COM+ applications has been broken for a long time
  821. but the all of the fixes I considered have some serious drawbacks.
  822. 1. Don't use comrepl to move the IIS applications. Serialize/Deserialize
  823. all the data needed to create the isolated applications and then delete
  824. and recreate them on the target. The problem here is that the packages
  825. may in fact be modified by the user and these modifications should be
  826. preserved.
  827. 2. Use comrepl as it is and replicate the IWAM_* account. This seems like
  828. a bad idea. The IWAM_ account should ideally never exist on multiple
  829. machines. Another issue is handling the password and account privileges.
  830. 3. Use a modified comrepl (or let comrepl fail and leave the package identity
  831. as "interactive user"). Then do a fixup of the activation identity.
  832. This doesn't work, because the Propogate/Propogate2 protocol is
  833. essentially useless. Changing this protocol on the next release
  834. is absolutely something that should be considered, although AppCenter
  835. probably makes it a moot point.
  836. The current implementation is option 1.
  837. Parameter:
  838. Return: HRESULT
  839. NOERROR if succeeds
  840. ===================================================================*/
  841. STDMETHODIMP CWamAdmin::Serialize
  842. (
  843. /* [in] */ DWORD dwBufferSize,
  844. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  845. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize
  846. )
  847. {
  848. HRESULT hr = NOERROR;
  849. WCHAR *pbBufferTemp = NULL;
  850. DWORD dwBufSizePath = 0;
  851. DWORD dwSizeForReturn = sizeof(DWORD);
  852. WamRegMetabaseConfig MDConfig;
  853. //
  854. // Grab the Lock
  855. //
  856. g_WamRegGlobal.AcquireAdmWriteLock();
  857. hr = MDConfig.MDGetPropPaths( WamRegGlobal::g_szMDW3SVCRoot,
  858. MD_APP_WAM_CLSID,
  859. &pbBufferTemp,
  860. &dwBufSizePath
  861. );
  862. if (SUCCEEDED(hr))
  863. {
  864. WCHAR *pszString = NULL;
  865. WCHAR *pszMetabasePath = NULL;
  866. WCHAR *pszAppName = NULL;
  867. WCHAR szWAMCLSID[uSizeCLSID];
  868. WCHAR szAppId[uSizeCLSID];
  869. DWORD dwSizeofRecord;
  870. DWORD cSizeMetabasePath = 0;
  871. DWORD cSizeAppName = 0;
  872. DWORD dwAppIsolated;
  873. for( pszString = (LPWSTR)pbBufferTemp;
  874. *pszString != (WCHAR)'\0';
  875. pszString += (wcslen(pszString) + 1))
  876. {
  877. // Clean up allocations
  878. if( pszMetabasePath != NULL )
  879. {
  880. delete [] pszMetabasePath;
  881. pszMetabasePath = NULL;
  882. }
  883. if( pszAppName != NULL )
  884. {
  885. delete [] pszAppName;
  886. pszAppName = NULL;
  887. }
  888. hr = g_WamRegGlobal.ConstructFullPath(
  889. WamRegGlobal::g_szMDW3SVCRoot,
  890. WamRegGlobal::g_cchMDW3SVCRoot,
  891. pszString,
  892. &pszMetabasePath
  893. );
  894. if( FAILED(hr) )
  895. {
  896. DBGERROR(( DBG_CONTEXT,
  897. "ConstructFullPath failed for base (%S) "
  898. "partial (%S) hr=%08x\n",
  899. WamRegGlobal::g_szMDW3SVCRoot,
  900. pszString,
  901. hr
  902. ));
  903. break;
  904. }
  905. if( g_WamRegGlobal.FIsW3SVCRoot( pszMetabasePath ) )
  906. {
  907. // Don't consider the root application
  908. continue;
  909. }
  910. hr = MDConfig.MDGetDWORD( pszMetabasePath,
  911. MD_APP_ISOLATED,
  912. &dwAppIsolated
  913. );
  914. if( FAILED(hr) )
  915. {
  916. DBGERROR(( DBG_CONTEXT,
  917. "Failed to get MD_APP_ISOLATED, hr=%08x\n",
  918. hr
  919. ));
  920. break;
  921. }
  922. if( dwAppIsolated != eAppRunOutProcIsolated )
  923. {
  924. // Don't consider non-isolated applications
  925. continue;
  926. }
  927. hr = MDConfig.MDGetIDs( pszMetabasePath,
  928. szWAMCLSID,
  929. szAppId,
  930. dwAppIsolated
  931. );
  932. if( FAILED(hr) )
  933. {
  934. DBGERROR(( DBG_CONTEXT,
  935. "Failed to get IDs for %S, hr = %08x\n",
  936. pszMetabasePath,
  937. hr
  938. ));
  939. break;
  940. }
  941. hr = MDConfig.MDGetAppName( pszMetabasePath,
  942. &pszAppName
  943. );
  944. if( FAILED(hr) )
  945. {
  946. DBGERROR(( DBG_CONTEXT,
  947. "Failed to get AppName for %S, hr = %08x\n",
  948. pszMetabasePath,
  949. hr
  950. ));
  951. break;
  952. }
  953. cSizeMetabasePath = wcslen(pszMetabasePath) + 1;
  954. cSizeAppName = wcslen(pszAppName) + 1;
  955. dwSizeofRecord = sizeof(DWORD) +
  956. ((2 * uSizeCLSID) * sizeof(WCHAR)) +
  957. (cSizeMetabasePath * sizeof(WCHAR)) +
  958. (cSizeAppName * sizeof(WCHAR));
  959. dwSizeForReturn += dwSizeofRecord;
  960. if (dwSizeForReturn <= dwBufferSize)
  961. {
  962. // Size
  963. *(DWORD *)pbBuffer = dwSizeofRecord;
  964. pbBuffer += sizeof(DWORD);
  965. // WAMCLSID
  966. memcpy( pbBuffer, szWAMCLSID, sizeof(WCHAR) * uSizeCLSID );
  967. pbBuffer += sizeof(WCHAR) * uSizeCLSID;
  968. // APPID
  969. memcpy( pbBuffer, szAppId, sizeof(WCHAR) * uSizeCLSID );
  970. pbBuffer += sizeof(WCHAR) * uSizeCLSID;
  971. // PATH
  972. memcpy( pbBuffer, pszMetabasePath, cSizeMetabasePath * sizeof(WCHAR) );
  973. pbBuffer += cSizeMetabasePath * sizeof(WCHAR);
  974. // APPNAME
  975. memcpy( pbBuffer, pszAppName, cSizeAppName * sizeof(WCHAR) );
  976. pbBuffer += cSizeAppName * sizeof(WCHAR);
  977. }
  978. }
  979. if (SUCCEEDED(hr))
  980. {
  981. if (dwSizeForReturn <= dwBufferSize)
  982. {
  983. *(DWORD*)pbBuffer = 0x0; // Ending Signature
  984. }
  985. else
  986. {
  987. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  988. }
  989. *pdwMDRequiredBufferSize = dwSizeForReturn;
  990. }
  991. // Clean up allocations
  992. if( pszMetabasePath != NULL )
  993. {
  994. delete [] pszMetabasePath;
  995. pszMetabasePath = NULL;
  996. }
  997. if( pszAppName != NULL )
  998. {
  999. delete [] pszAppName;
  1000. pszAppName = NULL;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. DBGERROR(( DBG_CONTEXT,
  1006. "Serialize: GetPropPaths failed hr = %08x\n",
  1007. hr
  1008. ));
  1009. }
  1010. //
  1011. // Release the Lock
  1012. //
  1013. g_WamRegGlobal.ReleaseAdmWriteLock();
  1014. if (pbBufferTemp)
  1015. {
  1016. delete [] pbBufferTemp;
  1017. }
  1018. return hr;
  1019. }
  1020. /*===================================================================
  1021. CWamAdmin::DeSerialize
  1022. This function unpacks all neccessary infomation (path + WAMCLSID) on a target
  1023. machine to prepare replication(DeSerialize).
  1024. The only applications that we really care about with replication are
  1025. isolated apps. This routine removes the existing out of process apps
  1026. and then recreates the applications that are sent over in pbBuffer.
  1027. CODEWORK - See comments in Serialize
  1028. Return: HRESULT
  1029. NOERROR if succeeds
  1030. ===================================================================*/
  1031. STDMETHODIMP CWamAdmin::DeSerialize
  1032. (
  1033. /* [in] */ DWORD dwBufferSize,
  1034. /* [size_is][in] */ unsigned char __RPC_FAR *pbBuffer
  1035. )
  1036. {
  1037. DWORD dwBufferSizeTemp= 0;
  1038. WCHAR* pbBufferTemp = NULL;
  1039. HRESULT hr = NOERROR;
  1040. WamRegMetabaseConfig MDConfig;
  1041. g_WamRegGlobal.AcquireAdmWriteLock();
  1042. hr = MDConfig.MDGetPropPaths( WamRegGlobal::g_szMDW3SVCRoot,
  1043. MD_APP_WAM_CLSID,
  1044. &pbBufferTemp,
  1045. &dwBufferSizeTemp
  1046. );
  1047. if (SUCCEEDED(hr))
  1048. {
  1049. //
  1050. // Remove all the existing isolated applications.
  1051. //
  1052. WCHAR * pszString = NULL;
  1053. WCHAR * pszMetabasePath = NULL;
  1054. DWORD dwAppIsolated;
  1055. for ( pszString = (LPWSTR)pbBufferTemp;
  1056. *pszString != (WCHAR)'\0';
  1057. pszString += (wcslen(pszString) + 1))
  1058. {
  1059. if( pszMetabasePath != NULL )
  1060. {
  1061. delete [] pszMetabasePath;
  1062. pszMetabasePath = NULL;
  1063. }
  1064. hr = g_WamRegGlobal.ConstructFullPath(
  1065. WamRegGlobal::g_szMDW3SVCRoot,
  1066. WamRegGlobal::g_cchMDW3SVCRoot,
  1067. pszString,
  1068. &pszMetabasePath
  1069. );
  1070. if( FAILED(hr) )
  1071. {
  1072. // This failure is fatal
  1073. DBGERROR(( DBG_CONTEXT,
  1074. "ConstructFullPath failed for base (%S) "
  1075. "partial (%S) hr=%08x\n",
  1076. WamRegGlobal::g_szMDW3SVCRoot,
  1077. pszString,
  1078. hr
  1079. ));
  1080. break;
  1081. }
  1082. hr = MDConfig.MDGetDWORD( pszMetabasePath,
  1083. MD_APP_ISOLATED,
  1084. &dwAppIsolated
  1085. );
  1086. if( FAILED(hr) )
  1087. {
  1088. DBGWARN(( DBG_CONTEXT,
  1089. "Failed to get MD_APP_ISOLATED at (%S) hr=%08x\n",
  1090. pszMetabasePath,
  1091. hr
  1092. ));
  1093. hr = NOERROR;
  1094. continue;
  1095. }
  1096. if( dwAppIsolated == eAppRunOutProcIsolated )
  1097. {
  1098. hr = g_WamRegGlobal.DeleteApp( pszMetabasePath, FALSE, FALSE );
  1099. if (FAILED(hr))
  1100. {
  1101. DBGWARN(( DBG_CONTEXT,
  1102. "Unable to delete app at %S, hr = %08x\n",
  1103. pszMetabasePath,
  1104. hr
  1105. ));
  1106. hr = NOERROR;
  1107. continue;
  1108. }
  1109. }
  1110. }
  1111. if( pszMetabasePath != NULL )
  1112. {
  1113. delete [] pszMetabasePath;
  1114. pszMetabasePath = NULL;
  1115. }
  1116. }
  1117. //
  1118. // Now go through the serialized data and create the
  1119. // necessary new applications.
  1120. //
  1121. BYTE * pbTemp = pbBuffer;
  1122. DWORD cTotalBytes = 0;
  1123. DWORD cRecBytes = 0;
  1124. WCHAR * szWAMCLSID = NULL;
  1125. WCHAR * szPath = NULL;
  1126. WCHAR * szAppId = NULL;
  1127. WCHAR * szAppName = NULL;
  1128. DBGPRINTF(( DBG_CONTEXT,
  1129. "DeSerialize: buffer size %d, \n",
  1130. dwBufferSize
  1131. ));
  1132. while( *((DWORD*)pbTemp) != 0x0 )
  1133. {
  1134. // SIZE
  1135. cRecBytes = *((DWORD*)pbTemp);
  1136. pbTemp += sizeof(DWORD);
  1137. // CLSID
  1138. szWAMCLSID = (WCHAR *)pbTemp;
  1139. pbTemp += uSizeCLSID * sizeof(WCHAR);
  1140. // APPID
  1141. szAppId = (WCHAR *)pbTemp;
  1142. pbTemp += uSizeCLSID * sizeof(WCHAR);
  1143. // PATH
  1144. szPath = (WCHAR *)pbTemp;
  1145. pbTemp += (wcslen(szPath) + 1) * sizeof(WCHAR);
  1146. // APPNAME
  1147. szAppName = (WCHAR *)pbTemp;
  1148. pbTemp += (wcslen(szAppName) + 1) * sizeof(WCHAR);
  1149. // TODO - This should really be output based on a flag
  1150. DBGPRINTF(( DBG_CONTEXT,
  1151. "Deserialize path = %S, WAMCLSID = %S.\n",
  1152. szPath,
  1153. szWAMCLSID
  1154. ));
  1155. // Should never serialize the w3svc root
  1156. DBG_ASSERT( !g_WamRegGlobal.FIsW3SVCRoot(szPath) );
  1157. hr = g_WamRegGlobal.CreateOutProcAppReplica( szPath,
  1158. szAppName,
  1159. szWAMCLSID,
  1160. szAppId
  1161. );
  1162. if( FAILED(hr) )
  1163. {
  1164. DBGERROR(( DBG_CONTEXT,
  1165. "Failed to create COM application. Path(%S) "
  1166. "Clsid(%S) AppId(%S). hr=%08x\n",
  1167. szPath,
  1168. szWAMCLSID,
  1169. szAppId,
  1170. hr
  1171. ));
  1172. // ??? Should we be continuing here ???
  1173. // Don't report an error if we are continuing
  1174. hr = NOERROR;
  1175. }
  1176. }
  1177. if (pbBufferTemp)
  1178. {
  1179. delete [] pbBufferTemp;
  1180. }
  1181. //
  1182. // Release the Lock
  1183. //
  1184. g_WamRegGlobal.ReleaseAdmWriteLock();
  1185. return hr;
  1186. }
  1187. /*===================================================================
  1188. CWamAdmin::FormatMetabasePath
  1189. This function format the input metabase path. If the metabase path has an
  1190. ending '/', this function will allocate a memory block and make a new string
  1191. without the ending '/'. This function will return a pointer to newly allocated
  1192. memory block. Otherwise, the function will return the pointer to
  1193. the input metabase path.
  1194. Parameter:
  1195. pwszMetabasePathIn input metabase path
  1196. ppwszMetabasePathOut pointer to the resulting pointer that contains the formatted
  1197. metabase path.
  1198. Return: HRESULT
  1199. NOERROR if succeeds
  1200. NOTE: if ppwszMetabasePathOut == pwszMetabasePathIn, then no memory allocation.
  1201. Otherwise, there is a memory allocation happened, and caller needs to free the
  1202. memory block passed out in ppwszMetabasePathOut.
  1203. ===================================================================*/
  1204. STDMETHODIMP CWamAdmin::FormatMetabasePath
  1205. (
  1206. /* [in] */ LPCWSTR pwszMetabasePathIn,
  1207. /* [out] */ LPWSTR *ppwszMetabasePathOut
  1208. )
  1209. {
  1210. HRESULT hr = NOERROR;
  1211. LPWSTR pResult = NULL;
  1212. DBG_ASSERT(pwszMetabasePathIn);
  1213. DBG_ASSERT(ppwszMetabasePathOut);
  1214. LONG cch = wcslen(pwszMetabasePathIn);
  1215. if (pwszMetabasePathIn[cch-1] == L'\\' ||
  1216. pwszMetabasePathIn[cch-1] == L'/')
  1217. {
  1218. //
  1219. // Need to start up with a new string, can not do it with old string.
  1220. //
  1221. pResult = new WCHAR[cch];
  1222. if (pResult != NULL)
  1223. {
  1224. wcsncpy(pResult, pwszMetabasePathIn, cch);
  1225. pResult[cch-1] = L'\0';
  1226. }
  1227. else
  1228. {
  1229. hr = HRESULT_FROM_WIN32(GetLastError());
  1230. DBGPRINTF((DBG_CONTEXT, "FormatMetabasePath, failed to allocate memory. hr = %08x\n",
  1231. hr));
  1232. }
  1233. if (pResult != NULL)
  1234. {
  1235. *ppwszMetabasePathOut = pResult;
  1236. }
  1237. }
  1238. else
  1239. {
  1240. *ppwszMetabasePathOut = (LPWSTR)pwszMetabasePathIn;
  1241. }
  1242. return hr;
  1243. }
  1244. //===============================================================================
  1245. //
  1246. // IIISApplicationAdmin implementation
  1247. //
  1248. //===============================================================================
  1249. #ifdef _IIS_6_0
  1250. /*===================================================================
  1251. DoesAppPoolExist
  1252. Determine whether the AppPool passed exists
  1253. Parameter:
  1254. szAppPoolId a AppPoolId
  1255. pfRet where to place whether or not the appPool exists
  1256. Return: HRESULT
  1257. ===================================================================*/
  1258. HRESULT
  1259. DoesAppPoolExist
  1260. (
  1261. LPCWSTR szAppPoolId,
  1262. BOOL * pfRet
  1263. )
  1264. {
  1265. DBG_ASSERT(pfRet);
  1266. WamRegMetabaseConfig MDConfig;
  1267. HRESULT hr = E_FAIL;
  1268. STACK_STRU(szPoolBuf, 64);
  1269. hr = szPoolBuf.Append(APPPOOLPATH);
  1270. if (FAILED(hr))
  1271. {
  1272. goto done;
  1273. }
  1274. hr = szPoolBuf.Append(szAppPoolId);
  1275. if (FAILED(hr))
  1276. {
  1277. goto done;
  1278. }
  1279. (*pfRet) = MDConfig.MDDoesPathExist(NULL, szPoolBuf.QueryStr());
  1280. hr = S_OK;
  1281. done:
  1282. return hr;
  1283. }
  1284. /*===================================================================
  1285. CWamAdmin::CreateApplication
  1286. Create an application on szMDPath, and add it to szAppPoolId AppPool.
  1287. Optionally create szAppPoolId
  1288. Parameter:
  1289. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  1290. dwAppMode mode to create application in
  1291. szAppPoolId AppPool to setup app in.
  1292. fCreatePool Whether or not to create the pool
  1293. Return: HRESULT
  1294. ===================================================================*/
  1295. STDMETHODIMP
  1296. CWamAdmin::CreateApplication
  1297. (
  1298. LPCWSTR szMDPath,
  1299. DWORD dwAppMode,
  1300. LPCWSTR szAppPoolId,
  1301. BOOL fCreatePool
  1302. )
  1303. {
  1304. HRESULT hr = S_OK;
  1305. WamRegMetabaseConfig MDConfig;
  1306. LPWSTR pwszFormattedPath = NULL;
  1307. if (NULL == szMDPath)
  1308. {
  1309. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1310. goto done;
  1311. }
  1312. //
  1313. // See FormatMetabasePath comment
  1314. //
  1315. hr = FormatMetabasePath(szMDPath, &pwszFormattedPath);
  1316. if (FAILED(hr))
  1317. {
  1318. goto done;
  1319. }
  1320. // BUGBUG: Do We need locking around all of this? Why is locking present in other places?
  1321. hr = AppCreate2(pwszFormattedPath, dwAppMode);
  1322. if (FAILED(hr))
  1323. {
  1324. goto done;
  1325. }
  1326. if (FALSE == fCreatePool && NULL == szAppPoolId)
  1327. {
  1328. //
  1329. // We weren't told to create an application pool
  1330. // and NULL was passed as the application pool,
  1331. // therefore do nothing wil the application pool
  1332. //
  1333. hr = S_OK;
  1334. goto done;
  1335. }
  1336. if (TRUE == fCreatePool)
  1337. {
  1338. //
  1339. // create the application pool that we were passed
  1340. //
  1341. hr = CreateApplicationPool(szAppPoolId);
  1342. if (FAILED(hr) &&
  1343. HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) != hr)
  1344. {
  1345. goto done;
  1346. }
  1347. }
  1348. else
  1349. {
  1350. //
  1351. // We weren't told to create the application pool,
  1352. // but one was passed in. Verify that it exists.
  1353. //
  1354. DBG_ASSERT(NULL != szAppPoolId);
  1355. BOOL fRet;
  1356. hr = DoesAppPoolExist(szAppPoolId, &fRet);
  1357. if (FAILED(hr))
  1358. {
  1359. goto done;
  1360. }
  1361. if (FALSE == fRet)
  1362. {
  1363. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  1364. goto done;
  1365. }
  1366. }
  1367. hr = MDConfig.MDSetStringProperty(NULL,
  1368. pwszFormattedPath,
  1369. MD_APP_APPPOOL_ID,
  1370. szAppPoolId,
  1371. IIS_MD_UT_SERVER);
  1372. if (FAILED(hr))
  1373. {
  1374. goto done;
  1375. }
  1376. hr = S_OK;
  1377. done:
  1378. //
  1379. // if pwszFormattedPath is not same as szMDPath
  1380. // then FormatMetabasePath() did a memory allocation.
  1381. //
  1382. if (pwszFormattedPath != szMDPath)
  1383. {
  1384. delete [] pwszFormattedPath;
  1385. pwszFormattedPath = NULL;
  1386. }
  1387. return hr;
  1388. }
  1389. /*===================================================================
  1390. CWamAdmin::DeleteApplication
  1391. Delete an application on a Metabase Path.
  1392. Parameter:
  1393. szMDPath a Metabase Path, in format of "/LM/W3SVC/..."
  1394. fRecursive TRUE if wants to deleteRecoverable applications from all sub nodes of szMDPath,
  1395. FALSE otherwise.
  1396. Return: HRESULT
  1397. ===================================================================*/
  1398. STDMETHODIMP
  1399. CWamAdmin::DeleteApplication
  1400. (
  1401. LPCWSTR szMDPath,
  1402. BOOL fRecursive
  1403. )
  1404. {
  1405. return PrivateDeleteApplication(szMDPath,
  1406. fRecursive,
  1407. FALSE, // Recoverable?
  1408. TRUE); // RemoveAppPool?
  1409. }
  1410. /*===================================================================
  1411. CWamAdmin::CreateApplicationPool
  1412. Delete an application on a Metabase Path. If there is no application existed
  1413. before, it is no-op. It leaves AppIsolated untouched, because, this value is
  1414. needed in Recover operation.
  1415. Parameter:
  1416. szAppPool Application Pool to create
  1417. Return: HRESULT
  1418. ===================================================================*/
  1419. STDMETHODIMP
  1420. CWamAdmin::CreateApplicationPool
  1421. (
  1422. LPCWSTR szAppPool
  1423. )
  1424. {
  1425. HRESULT hr = S_OK;
  1426. WamRegMetabaseConfig MDConfig;
  1427. STACK_STRU(szBuf, 64);
  1428. // Acquire a Lock
  1429. g_WamRegGlobal.AcquireAdmWriteLock();
  1430. if (NULL == szAppPool)
  1431. {
  1432. hr = E_INVALIDARG;
  1433. goto done;
  1434. }
  1435. // concatenate the path into a buffer
  1436. hr = szBuf.Append(APPPOOLPATH);
  1437. if (FAILED(hr))
  1438. {
  1439. goto done;
  1440. }
  1441. hr = szBuf.Append(szAppPool);
  1442. if (FAILED(hr))
  1443. {
  1444. goto done;
  1445. }
  1446. hr = MDConfig.MDCreatePath(NULL, szBuf.QueryStr());
  1447. if (FAILED(hr))
  1448. {
  1449. goto done;
  1450. }
  1451. hr = MDConfig.MDSetKeyType(NULL, szBuf.QueryStr(), L"IIsApplicationPool");
  1452. if (FAILED(hr))
  1453. {
  1454. goto done;
  1455. }
  1456. done:
  1457. // Release a Lock
  1458. g_WamRegGlobal.ReleaseAdmWriteLock();
  1459. return hr;
  1460. }
  1461. /*===================================================================
  1462. CWamAdmin::DeleteApplicationPool
  1463. Delete an application pool. First check to see if ApplicationPool is empty.
  1464. If not, return ERROR_NOT_EMPTY. Otherwise, remove apppool.
  1465. Parameter:
  1466. szAppPool Application Pool to remove
  1467. Return: HRESULT
  1468. ===================================================================*/
  1469. STDMETHODIMP
  1470. CWamAdmin::DeleteApplicationPool
  1471. (
  1472. LPCWSTR szAppPool
  1473. )
  1474. {
  1475. HRESULT hr = S_OK;
  1476. UINT cchBstr = 0;
  1477. BOOL fRet = FALSE;
  1478. BSTR bstr = NULL;
  1479. WamRegMetabaseConfig MDConfig;
  1480. // BUGBUG: need locking around this?
  1481. if (NULL == szAppPool)
  1482. {
  1483. hr = E_INVALIDARG;
  1484. goto done;
  1485. }
  1486. hr = DoesAppPoolExist(szAppPool, &fRet);
  1487. if (FAILED(hr))
  1488. {
  1489. goto done;
  1490. }
  1491. if (FALSE == fRet)
  1492. {
  1493. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  1494. goto done;
  1495. }
  1496. hr = EnumerateApplicationsInPool(szAppPool, &bstr);
  1497. if (FAILED(hr))
  1498. {
  1499. goto done;
  1500. }
  1501. cchBstr = SysStringLen(bstr);
  1502. // were there two terminating NULLs to be written into out buffer?
  1503. if (!(cchBstr >= 2 && '\0' == bstr[0] && '\0' == bstr[1]))
  1504. {
  1505. hr = HRESULT_FROM_WIN32(ERROR_NOT_EMPTY);
  1506. goto done;
  1507. }
  1508. hr = MDConfig.MDDeleteKey(NULL, APPPOOLPATH, szAppPool);
  1509. if (FAILED(hr))
  1510. {
  1511. goto done;
  1512. }
  1513. hr = S_OK;
  1514. done:
  1515. if (bstr)
  1516. {
  1517. SysFreeString(bstr);
  1518. }
  1519. return hr;
  1520. }
  1521. /*===================================================================
  1522. DoesBeginWithLMW3SVCNRoot
  1523. Determine whether the string passed in starts with
  1524. /lm/w3svc/NNNN/root
  1525. where NNNN is greater than 0.
  1526. Parameter:
  1527. pszApp an metabase application path
  1528. pdwCharsAfter [OPTIONAL] - storage for the number of characters following /root
  1529. Return: BOOL
  1530. ===================================================================*/
  1531. const WCHAR MB_W3SVC[] = L"/lm/w3svc/";
  1532. const int LEN_MB_W3SVC = (sizeof(MB_W3SVC) / sizeof(WCHAR)) - 1;
  1533. const WCHAR MB_W3SVC_1_ROOT[] = L"/LM/W3SVC/1/ROOT";
  1534. const int LEN_MB_W3SVC_1_ROOT = (sizeof(MB_W3SVC_1_ROOT) / sizeof(WCHAR)) - 1;
  1535. const WCHAR MB_ROOT[] = L"/Root";
  1536. const int LEN_MB_ROOT = (sizeof(MB_ROOT) / sizeof(WCHAR)) - 1;
  1537. BOOL
  1538. DoesBeginWithLMW3SVCNRoot
  1539. (
  1540. LPCWSTR pszApp,
  1541. DWORD * pdwCharsAfter = NULL
  1542. )
  1543. {
  1544. DBG_ASSERT(pszApp);
  1545. BOOL fRet = FALSE;
  1546. WCHAR pBuf[256] = {0};
  1547. int iSite;
  1548. // must have at least this many characters to have a chance
  1549. if (wcslen(pszApp) < LEN_MB_W3SVC_1_ROOT)
  1550. {
  1551. goto done;
  1552. }
  1553. // Applications must have \lm\w3svc\ at the front
  1554. if (0 != _wcsnicmp(MB_W3SVC, pszApp, LEN_MB_W3SVC))
  1555. {
  1556. goto done;
  1557. }
  1558. // Advance the pointer by enough characters
  1559. pszApp += LEN_MB_W3SVC;
  1560. // _wtoi returns as many characters as possible in a string before hitting a non-number or NULL
  1561. // if there is no number, the return is 0.
  1562. iSite = _wtoi(pszApp);
  1563. // Applications must then have a number that is >=1
  1564. if (0 == iSite)
  1565. {
  1566. goto done;
  1567. }
  1568. // get the count of numbers read from the string
  1569. _itow(iSite, pBuf, 10);
  1570. // advance the pointer by enough characters.
  1571. pszApp += wcslen(pBuf);
  1572. // Applications must them have "/Root"
  1573. if (0 != _wcsnicmp(pszApp, MB_ROOT, LEN_MB_ROOT))
  1574. {
  1575. goto done;
  1576. }
  1577. // if caller wants a count of characters following /Root
  1578. if (pdwCharsAfter)
  1579. {
  1580. // advance the pointer by enough characters
  1581. pszApp += LEN_MB_ROOT;
  1582. // get the remaining length
  1583. *pdwCharsAfter = wcslen(pszApp);
  1584. }
  1585. fRet = TRUE;
  1586. done:
  1587. return fRet;
  1588. }
  1589. /*===================================================================
  1590. IsRootApplication
  1591. Determine whether the string passed in is of the form:
  1592. /lm/w3svc/NNNN/root/
  1593. where NNNN is greater than 0.
  1594. And no additional characters following
  1595. Parameter:
  1596. pszApp an metabase application path
  1597. Return: BOOL
  1598. ===================================================================*/
  1599. BOOL
  1600. IsRootApplication
  1601. (
  1602. LPCWSTR pszApp
  1603. )
  1604. {
  1605. DWORD dwCharsAfter = 0;
  1606. // Root applications must begin with /lm/w3svc/nnn/root
  1607. if (!DoesBeginWithLMW3SVCNRoot(pszApp, &dwCharsAfter))
  1608. {
  1609. return FALSE;
  1610. }
  1611. // we expect at most a trailing '/' after /lm/w3svc/nnn/root.
  1612. // If there is more, this was not a root application
  1613. if(1 < dwCharsAfter)
  1614. {
  1615. return FALSE;
  1616. }
  1617. return TRUE;
  1618. }
  1619. /*===================================================================
  1620. IsApplication
  1621. Determine whether the string passed in starts with
  1622. /lm/w3svc/NNNN/root
  1623. where NNNN is greater than 0.
  1624. With any additional characters following
  1625. Parameter:
  1626. pszApp an metabase application path
  1627. Return: BOOL
  1628. ===================================================================*/
  1629. BOOL
  1630. IsApplication
  1631. (
  1632. LPCWSTR pszApp
  1633. )
  1634. {
  1635. return DoesBeginWithLMW3SVCNRoot(pszApp);
  1636. }
  1637. /*===================================================================
  1638. IsAppInAppPool
  1639. Determine whether the App is in Pool
  1640. Parameter:
  1641. pszApp an metabase application path
  1642. pszPool an applicationPool ID
  1643. Return: BOOL
  1644. ===================================================================*/
  1645. BOOL
  1646. IsAppInAppPool
  1647. (
  1648. LPCWSTR pszApp,
  1649. LPCWSTR pszPool
  1650. )
  1651. {
  1652. DBG_ASSERT(pszApp);
  1653. DBG_ASSERT(pszPool);
  1654. HRESULT hr = E_FAIL;
  1655. BOOL fRet = FALSE;
  1656. LPWSTR pBuf = NULL;
  1657. WamRegMetabaseConfig MDConfig;
  1658. hr = MDConfig.MDGetStringAttribute(pszApp, MD_APP_APPPOOL_ID, &pBuf);
  1659. if (FAILED(hr) || NULL == pBuf)
  1660. {
  1661. goto done;
  1662. }
  1663. if (0 == _wcsicmp(pBuf, pszPool))
  1664. {
  1665. fRet = TRUE;
  1666. }
  1667. done:
  1668. delete [] pBuf;
  1669. return fRet;
  1670. }
  1671. /*===================================================================
  1672. CWamAdmin::EnumerateApplicationsInPool
  1673. Determine what applications are setup to point to the given pool.
  1674. Parameter:
  1675. szPool Application Pool enumerate
  1676. pbstrBuffer Where to store the pointer to allocated memory for application paths
  1677. Return: HRESULT
  1678. S_OK if buffer filled with a MULTISZ - if empty, double NULL at beginning
  1679. ===================================================================*/
  1680. STDMETHODIMP
  1681. CWamAdmin::EnumerateApplicationsInPool
  1682. (
  1683. LPCWSTR szPool,
  1684. BSTR* pbstrBuffer
  1685. )
  1686. {
  1687. HRESULT hr = E_FAIL;
  1688. WamRegMetabaseConfig MDConfig;
  1689. MULTISZ mszApplicationsInPool;
  1690. WCHAR * pBuffer = NULL;
  1691. UINT cchMulti = 0;
  1692. DWORD dwBufferSize = 0;
  1693. if (NULL == szPool ||
  1694. NULL == pbstrBuffer
  1695. )
  1696. {
  1697. hr = E_INVALIDARG;
  1698. goto done;
  1699. }
  1700. *pbstrBuffer = NULL;
  1701. // First get all of the root applications
  1702. {
  1703. hr = MDConfig.MDGetAllSiteRoots(&pBuffer);
  1704. if (FAILED(hr))
  1705. {
  1706. goto done;
  1707. }
  1708. const WCHAR * pTestBuf = pBuffer;
  1709. while(pTestBuf && pTestBuf[0])
  1710. {
  1711. DBG_ASSERT(IsRootApplication(pTestBuf));
  1712. if ( IsAppInAppPool(pTestBuf, szPool) )
  1713. {
  1714. if (FALSE == mszApplicationsInPool.Append(pTestBuf))
  1715. {
  1716. hr = E_OUTOFMEMORY;
  1717. goto done;
  1718. }
  1719. }
  1720. // move pTestBuf beyond end of this string, including NULL terminator.
  1721. pTestBuf += wcslen(pTestBuf) + 1;
  1722. }
  1723. delete [] pBuffer;
  1724. pBuffer = NULL;
  1725. }
  1726. // now get any other applications that have APPISOLATED set
  1727. {
  1728. hr = MDConfig.MDGetPropPaths(NULL,
  1729. MD_APP_ISOLATED,
  1730. &pBuffer,
  1731. &dwBufferSize
  1732. );
  1733. if (FAILED(hr))
  1734. {
  1735. goto done;
  1736. }
  1737. {
  1738. const WCHAR * pTestBuf = pBuffer;
  1739. while (pTestBuf && pTestBuf[0])
  1740. {
  1741. // root applications have already been added
  1742. // the path needs to be an application
  1743. // and the application needs to be in the app pool
  1744. if ( !IsRootApplication(pTestBuf) &&
  1745. IsApplication(pTestBuf) &&
  1746. IsAppInAppPool(pTestBuf, szPool) )
  1747. {
  1748. if (FALSE == mszApplicationsInPool.Append(pTestBuf))
  1749. {
  1750. hr = E_OUTOFMEMORY;
  1751. goto done;
  1752. }
  1753. }
  1754. // move pTestBuf beyond end of this string, including NULL terminator.
  1755. pTestBuf += wcslen(pTestBuf) + 1;
  1756. }
  1757. }
  1758. }
  1759. // have the data in a MULTISZ - move it to the outgoing BSTR
  1760. cchMulti = mszApplicationsInPool.QueryCCH();
  1761. *pbstrBuffer = SysAllocStringLen(NULL, cchMulti);
  1762. if (NULL == *pbstrBuffer)
  1763. {
  1764. hr = E_OUTOFMEMORY;
  1765. goto done;
  1766. }
  1767. dwBufferSize = cchMulti;
  1768. mszApplicationsInPool.CopyToBuffer(*pbstrBuffer, &dwBufferSize);
  1769. hr = S_OK;
  1770. done:
  1771. delete [] pBuffer;
  1772. pBuffer = NULL;
  1773. return hr;
  1774. }
  1775. /*===================================================================
  1776. QueryW3SVCStatus
  1777. Using the ServiceControlManager, determine the current state of W3SVC
  1778. pfRunning return bool value - TRUE if running, otherwise FALSE
  1779. Return: HRESULT
  1780. S_OK if able to read status. HRESULT_FROM_WIN32 error otherwise
  1781. ===================================================================*/
  1782. HRESULT
  1783. QueryW3SVCStatus
  1784. (
  1785. BOOL * pfRunning
  1786. )
  1787. {
  1788. DBG_ASSERT(pfRunning);
  1789. *pfRunning = FALSE;
  1790. HRESULT hr = E_FAIL;
  1791. BOOL fRet = FALSE;
  1792. SC_HANDLE hSCM = 0;
  1793. SC_HANDLE hService = 0;
  1794. SERVICE_STATUS ssStatus;
  1795. ZeroMemory(&ssStatus, sizeof(ssStatus));
  1796. // first, get the service control manager
  1797. hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1798. if (NULL == hSCM)
  1799. {
  1800. hr = HRESULT_FROM_WIN32(GetLastError());
  1801. goto done;
  1802. }
  1803. // now get the w3svc service
  1804. hService = OpenService(hSCM, "W3SVC", SERVICE_QUERY_STATUS);
  1805. if (NULL == hService)
  1806. {
  1807. hr = HRESULT_FROM_WIN32(GetLastError());
  1808. goto done;
  1809. }
  1810. // now ask for the status
  1811. fRet = QueryServiceStatus(hService, &ssStatus);
  1812. if (FALSE == fRet)
  1813. {
  1814. hr = HRESULT_FROM_WIN32(GetLastError());
  1815. goto done;
  1816. }
  1817. if (SERVICE_RUNNING == ssStatus.dwCurrentState)
  1818. {
  1819. *pfRunning = TRUE;
  1820. }
  1821. hr = S_OK;
  1822. done:
  1823. if (0 != hService)
  1824. {
  1825. CloseServiceHandle(hService);
  1826. }
  1827. if (0 != hSCM)
  1828. {
  1829. CloseServiceHandle(hSCM);
  1830. }
  1831. return hr;
  1832. }
  1833. /*===================================================================
  1834. GetWASIfRunning
  1835. Get a pointer to WAS iff w3svc is already running.
  1836. ppiW3Control where to store the addref'ed pointer if it can be gotten
  1837. Return: HRESULT
  1838. S_OK if pointer retrieved
  1839. HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE) if W3SVC is not up
  1840. +other error codes
  1841. ===================================================================*/
  1842. HRESULT
  1843. GetWASIfRunning
  1844. (
  1845. IW3Control ** ppiW3Control
  1846. )
  1847. {
  1848. DBG_ASSERT(ppiW3Control);
  1849. *ppiW3Control = NULL;
  1850. HRESULT hr = E_FAIL;
  1851. BOOL fRunning = FALSE;
  1852. hr = QueryW3SVCStatus(&fRunning);
  1853. if (FAILED(hr))
  1854. {
  1855. goto done;
  1856. }
  1857. if (FALSE == fRunning)
  1858. {
  1859. hr = HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE);
  1860. goto done;
  1861. }
  1862. hr = CoCreateInstance(CLSID_W3Control,
  1863. NULL,
  1864. CLSCTX_ALL,
  1865. IID_IW3Control,
  1866. reinterpret_cast<void**>(ppiW3Control));
  1867. if (FAILED(hr))
  1868. {
  1869. goto done;
  1870. }
  1871. hr = S_OK;
  1872. done:
  1873. return hr;
  1874. }
  1875. /*===================================================================
  1876. ValidateWriteAccessToMetabaseKey
  1877. Determine whether the caller has write access to the given metabase key
  1878. pPath - path to check write access on
  1879. Return: HRESULT
  1880. S_OK if access allowed
  1881. otherwise failure
  1882. ===================================================================*/
  1883. HRESULT
  1884. ValidateWriteAccessToMetabaseKey(LPCWSTR pPath)
  1885. {
  1886. HRESULT hr = S_OK;
  1887. IMSAdminBase * pIMSAdminBase = NULL;
  1888. METADATA_HANDLE hMB = NULL;
  1889. METADATA_RECORD mdr;
  1890. DWORD dwTemp = 0x1234;
  1891. hr = CoImpersonateClient();
  1892. if (FAILED(hr))
  1893. {
  1894. goto done;
  1895. }
  1896. hr = CoCreateInstance(
  1897. CLSID_MSAdminBase, // CLSID
  1898. NULL, // controlling unknown
  1899. CLSCTX_SERVER, // desired context
  1900. IID_IMSAdminBase, // IID
  1901. ( VOID * * ) ( &pIMSAdminBase ) // returned interface
  1902. );
  1903. if (FAILED(hr))
  1904. {
  1905. goto done;
  1906. }
  1907. hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1908. pPath,
  1909. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1910. 30000, // 30 seconds max
  1911. &hMB );
  1912. if (FAILED(hr))
  1913. {
  1914. goto done;
  1915. }
  1916. MD_SET_DATA_RECORD(&mdr,
  1917. MD_ISM_ACCESS_CHECK, // same identifier UI uses for this operation
  1918. METADATA_NO_ATTRIBUTES,
  1919. IIS_MD_UT_FILE,
  1920. DWORD_METADATA,
  1921. sizeof(DWORD),
  1922. &dwTemp);
  1923. hr = pIMSAdminBase->SetData(hMB,
  1924. NULL,
  1925. &mdr
  1926. );
  1927. if (FAILED(hr))
  1928. {
  1929. goto done;
  1930. }
  1931. //
  1932. // don't leave goo hanging around
  1933. //
  1934. hr = pIMSAdminBase->DeleteData(hMB,
  1935. NULL,
  1936. MD_ISM_ACCESS_CHECK,
  1937. DWORD_METADATA
  1938. );
  1939. if (FAILED(hr))
  1940. {
  1941. goto done;
  1942. }
  1943. hr = CoRevertToSelf();
  1944. if (FAILED(hr))
  1945. {
  1946. goto done;
  1947. }
  1948. hr = S_OK;
  1949. done:
  1950. if ( hMB )
  1951. {
  1952. DBG_ASSERT( NULL != pIMSAdminBase );
  1953. DBG_REQUIRE( pIMSAdminBase->CloseKey( hMB ) == S_OK );
  1954. hMB = NULL;
  1955. }
  1956. if (pIMSAdminBase)
  1957. {
  1958. pIMSAdminBase->Release();
  1959. pIMSAdminBase = NULL;
  1960. }
  1961. return hr;
  1962. }
  1963. /*===================================================================
  1964. ValidateAccessToAppPool
  1965. Determine whether the caller has write access to the given apppool
  1966. szAppPool - AppPool to check access on
  1967. Return: HRESULT
  1968. S_OK if access allowed
  1969. otherwise failure
  1970. ===================================================================*/
  1971. HRESULT
  1972. ValidateAccessToAppPool(LPCWSTR pAppPool)
  1973. {
  1974. HRESULT hr = S_OK;
  1975. STACK_STRU( strPath, 128 );
  1976. hr = strPath.Copy(L"\\LM\\W3SVC\\AppPools\\");
  1977. if (FAILED(hr))
  1978. {
  1979. goto done;
  1980. }
  1981. hr = strPath.Append(pAppPool);
  1982. if (FAILED(hr))
  1983. {
  1984. goto done;
  1985. }
  1986. hr = ValidateWriteAccessToMetabaseKey(strPath.QueryStr());
  1987. if (FAILED(hr))
  1988. {
  1989. goto done;
  1990. }
  1991. hr = S_OK;
  1992. done:
  1993. return hr;
  1994. }
  1995. /*===================================================================
  1996. CWamAdmin::RecycleApplicationPool
  1997. Restart the given application pool
  1998. szAppPool - AppPool to restart.
  1999. Return: HRESULT
  2000. S_OK if restarted
  2001. HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE) if W3SVC is not up
  2002. +other error codes
  2003. ===================================================================*/
  2004. STDMETHODIMP
  2005. CWamAdmin::RecycleApplicationPool
  2006. (
  2007. LPCWSTR szAppPool
  2008. )
  2009. {
  2010. HRESULT hr = E_FAIL;
  2011. IW3Control* piW3Control = NULL;
  2012. if (NULL == szAppPool)
  2013. {
  2014. hr = E_INVALIDARG;
  2015. goto done;
  2016. }
  2017. hr = ValidateAccessToAppPool(szAppPool);
  2018. if (FAILED(hr))
  2019. {
  2020. goto done;
  2021. }
  2022. hr = GetWASIfRunning(&piW3Control);
  2023. if (FAILED(hr))
  2024. {
  2025. goto done;
  2026. }
  2027. hr = piW3Control->RecycleAppPool(szAppPool);
  2028. if (FAILED(hr))
  2029. {
  2030. goto done;
  2031. }
  2032. hr = S_OK;
  2033. done:
  2034. ReleaseInterface(piW3Control);
  2035. return hr;
  2036. }
  2037. /*===================================================================
  2038. CWamAdmin::GetProcessMode
  2039. Retrieve the current process mode
  2040. pdwMode - where to store the mode
  2041. Return: HRESULT
  2042. S_OK if retrieved
  2043. HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE) if W3SVC is not up
  2044. +other error codes
  2045. ===================================================================*/
  2046. STDMETHODIMP
  2047. CWamAdmin::GetProcessMode
  2048. (
  2049. DWORD * pdwMode
  2050. )
  2051. {
  2052. HRESULT hr = E_FAIL;
  2053. IW3Control* piW3Control = NULL;
  2054. if (NULL == pdwMode)
  2055. {
  2056. hr = E_INVALIDARG;
  2057. goto done;
  2058. }
  2059. hr = ValidateWriteAccessToMetabaseKey(L"\\LM\\W3SVC");
  2060. if (FAILED(hr))
  2061. {
  2062. goto done;
  2063. }
  2064. hr = GetWASIfRunning(&piW3Control);
  2065. if (FAILED(hr))
  2066. {
  2067. goto done;
  2068. }
  2069. hr = piW3Control->GetCurrentMode(pdwMode);
  2070. if (FAILED(hr))
  2071. {
  2072. goto done;
  2073. }
  2074. hr = S_OK;
  2075. done:
  2076. ReleaseInterface(piW3Control);
  2077. return hr;
  2078. }
  2079. #endif // _IIS_6_0
  2080. /*
  2081. CWamAdminFactory: Class Factory IUnknown Implementation
  2082. */
  2083. /*===================================================================
  2084. CWamAdminFactory::CWamAdminFactory
  2085. Parameter:
  2086. Return: HRESULT
  2087. NOERROR if succeeds
  2088. ===================================================================*/
  2089. CWamAdminFactory::CWamAdminFactory()
  2090. : m_cRef(1)
  2091. {
  2092. InterlockedIncrement((long *)&g_dwRefCount);
  2093. }
  2094. /*===================================================================
  2095. CWamAdminFactory::~CWamAdminFactory
  2096. Parameter:
  2097. Return: HRESULT
  2098. NOERROR if succeeds
  2099. ===================================================================*/
  2100. CWamAdminFactory::~CWamAdminFactory()
  2101. {
  2102. InterlockedDecrement((long *)&g_dwRefCount);
  2103. }
  2104. /*===================================================================
  2105. CWamAdminFactory::QueryInterface
  2106. Parameter:
  2107. Return: HRESULT
  2108. NOERROR if succeeds
  2109. ===================================================================*/
  2110. STDMETHODIMP CWamAdminFactory::QueryInterface(REFIID riid, void ** ppv)
  2111. {
  2112. if (riid==IID_IUnknown || riid == IID_IClassFactory)
  2113. {
  2114. *ppv = static_cast<IClassFactory *>(this);
  2115. AddRef();
  2116. }
  2117. else
  2118. {
  2119. *ppv = NULL;
  2120. return E_NOINTERFACE;
  2121. }
  2122. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  2123. return NOERROR;
  2124. }
  2125. /*===================================================================
  2126. CWamAdminFactory::AddRef
  2127. Parameter:
  2128. Return: HRESULT
  2129. NOERROR if succeeds
  2130. ===================================================================*/
  2131. STDMETHODIMP_(ULONG) CWamAdminFactory::AddRef( )
  2132. {
  2133. DWORD dwRefCount;
  2134. dwRefCount = InterlockedIncrement((long *)&m_cRef);
  2135. return dwRefCount;
  2136. }
  2137. /*===================================================================
  2138. CWamAdminFactory::Release
  2139. Parameter:
  2140. Return: HRESULT
  2141. NOERROR if succeeds
  2142. ===================================================================*/
  2143. STDMETHODIMP_(ULONG) CWamAdminFactory::Release( )
  2144. {
  2145. DWORD dwRefCount;
  2146. dwRefCount = InterlockedDecrement((long *)&m_cRef);
  2147. return dwRefCount;
  2148. }
  2149. /*===================================================================
  2150. CWamAdminFactory::CreateInstance
  2151. Parameter:
  2152. Return: HRESULT
  2153. NOERROR if succeeds
  2154. ===================================================================*/
  2155. STDMETHODIMP CWamAdminFactory::CreateInstance(IUnknown * pUnknownOuter, REFIID riid, void ** ppv)
  2156. {
  2157. if (pUnknownOuter != NULL)
  2158. {
  2159. return CLASS_E_NOAGGREGATION;
  2160. }
  2161. CWamAdmin *pWamAdmin = new CWamAdmin;
  2162. if (pWamAdmin == NULL)
  2163. {
  2164. return E_OUTOFMEMORY;
  2165. }
  2166. HRESULT hrReturn = pWamAdmin->QueryInterface(riid, ppv);
  2167. pWamAdmin->Release();
  2168. return hrReturn;
  2169. }
  2170. /*===================================================================
  2171. CWamAdminFactory::LockServer
  2172. Parameter:
  2173. Return: HRESULT
  2174. NOERROR if succeeds
  2175. ===================================================================*/
  2176. STDMETHODIMP CWamAdminFactory::LockServer(BOOL fLock)
  2177. {
  2178. if (fLock)
  2179. {
  2180. InterlockedIncrement((long *)&g_dwRefCount);
  2181. }
  2182. else
  2183. {
  2184. InterlockedDecrement((long *)&g_dwRefCount);
  2185. }
  2186. return NOERROR;
  2187. }
  2188. #if 0
  2189. // OBSOLETE - This fix (335422) was implemented in script but
  2190. // some of the code is general enough that it might be worth
  2191. // keeping around for a while.
  2192. STDMETHODIMP CWamAdmin::SynchWamAccountAll()
  2193. /*+
  2194. Routine Description:
  2195. Updates all out of process packages with the current IWAM_ account
  2196. values stored in the metabase.
  2197. There are a number of ways that the IWAM_ account information can get
  2198. out of sync between the metabase/sam/com+. The metabase contains code
  2199. to repair the IWAM_ and IUSR_ accounts on startup if there is a disconnect
  2200. with the SAM. If there is a disconnect with com+ calling this method will
  2201. repair it.
  2202. If the IWAM_ account does not match what is stored in the com catalog the
  2203. following error's will happen:
  2204. CoCreateInstance for WAM object returns CO_E_RUNAS_CREATEPROCESS_FAILURE
  2205. Event Log - DCOM 10004 - "Logon error"
  2206. Arguments:
  2207. None
  2208. Returns:
  2209. HRESULT
  2210. -*/
  2211. {
  2212. HRESULT hr = NOERROR;
  2213. // Get WAM user info from the metabase
  2214. WamRegMetabaseConfig mb;
  2215. // These are way too big...
  2216. WCHAR wszIWamUser[MAX_PATH];
  2217. WCHAR wszIWamPass[MAX_PATH];
  2218. hr = mb.MDGetIdentity( wszIWamUser,
  2219. sizeof(wszIWamUser),
  2220. wszIWamPass,
  2221. sizeof(wszIWamPass)
  2222. );
  2223. if( FAILED(hr) ) return hr;
  2224. // Init the com admin interface
  2225. WamRegPackageConfig comAdmin;
  2226. hr = comAdmin.CreateCatalog();
  2227. if( FAILED(hr) ) return hr;
  2228. //
  2229. // For each of the out of process applications,
  2230. // get the package and reset the metabase identity.
  2231. //
  2232. // After this failures cause a goto exit, which will release the lock
  2233. g_WamRegGlobal.AcquireAdmWriteLock();
  2234. WCHAR * wszPropPaths = NULL;
  2235. DWORD cbPropPaths = 0;
  2236. WCHAR * pwszPartialPath;
  2237. WCHAR * wszFullPath = NULL;
  2238. DWORD dwAppMode;
  2239. WCHAR wszWamClsid[uSizeCLSID];
  2240. WCHAR wszAppPackageId[uSizeCLSID];
  2241. // Reset the properties for the pooled package
  2242. hr = comAdmin.ResetPackageActivation(
  2243. g_WamRegGlobal.g_szIISOOPPoolPackageID,
  2244. wszIWamUser,
  2245. wszIWamPass
  2246. );
  2247. if( FAILED(hr) )
  2248. {
  2249. DBGPRINTF(( DBG_CONTEXT,
  2250. "comAdmin.ResetPackageActivation FAILED(%08x) on (%S)\n",
  2251. hr,
  2252. g_WamRegGlobal.g_szIISOOPPoolPackageID
  2253. ));
  2254. goto exit;
  2255. }
  2256. // Reset the properties for each isolated application
  2257. hr = mb.MDGetPropPaths( g_WamRegGlobal.g_szMDW3SVCRoot,
  2258. MD_APP_ISOLATED,
  2259. &wszPropPaths,
  2260. &cbPropPaths
  2261. );
  2262. if( FAILED(hr) )
  2263. {
  2264. DBGPRINTF(( DBG_CONTEXT,
  2265. "mb.MDGetPropPaths FAILED(%08x)\n",
  2266. hr
  2267. ));
  2268. goto exit;
  2269. }
  2270. if( SUCCEEDED(hr) )
  2271. {
  2272. for( pwszPartialPath = wszPropPaths;
  2273. *pwszPartialPath != L'\0';
  2274. pwszPartialPath += ( wcslen( pwszPartialPath ) + 1 )
  2275. )
  2276. {
  2277. if( wszFullPath )
  2278. {
  2279. delete [] wszFullPath;
  2280. wszFullPath = NULL;
  2281. }
  2282. hr = g_WamRegGlobal.ConstructFullPath(
  2283. WamRegGlobal::g_szMDW3SVCRoot,
  2284. WamRegGlobal::g_cchMDW3SVCRoot,
  2285. pwszPartialPath,
  2286. &wszFullPath
  2287. );
  2288. if( FAILED(hr) ) goto exit;
  2289. hr = mb.MDGetDWORD( wszFullPath, MD_APP_ISOLATED, &dwAppMode );
  2290. if( FAILED(hr) ) goto exit;
  2291. if( dwAppMode == eAppRunOutProcIsolated )
  2292. {
  2293. hr = mb.MDGetIDs( wszFullPath, wszWamClsid, wszAppPackageId, dwAppMode );
  2294. if( FAILED(hr) )
  2295. {
  2296. DBGPRINTF(( DBG_CONTEXT,
  2297. "mb.MDGetIDs FAILED(%08x) on (%S)\n",
  2298. hr,
  2299. wszFullPath
  2300. ));
  2301. continue;
  2302. }
  2303. hr = comAdmin.ResetPackageActivation( wszAppPackageId, wszIWamUser, wszIWamPass );
  2304. if( FAILED(hr) )
  2305. {
  2306. DBGPRINTF(( DBG_CONTEXT,
  2307. "comAdmin.ResetPackageActivation FAILED(%08x) on (%S)\n",
  2308. hr,
  2309. wszFullPath
  2310. ));
  2311. continue;
  2312. }
  2313. }
  2314. }
  2315. }
  2316. // goto exit on catastrophic failures, but if there is just
  2317. // an individual malformed application continue
  2318. exit:
  2319. g_WamRegGlobal.ReleaseAdmWriteLock();
  2320. if( FAILED(hr) )
  2321. {
  2322. DBGPRINTF(( DBG_CONTEXT,
  2323. "CWamAdmin::SynchWamAccountAll FAILED(%08x)\n",
  2324. hr
  2325. ));
  2326. }
  2327. if( wszPropPaths ) delete [] wszPropPaths;
  2328. if( wszFullPath ) delete [] wszFullPath;
  2329. return hr;
  2330. }
  2331. // OBSOLETE
  2332. #endif