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.

1838 lines
54 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2000.
  5. //
  6. // File: cimbmgr.cxx
  7. //
  8. // Contents: Content Index Meta Base Manager
  9. //
  10. // Classes: CMetaDataMgr
  11. //
  12. // History: 07-Feb-1997 dlee Created
  13. // 24-Apr-1997 dlee Converted to new Unicode interface
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include <cimbmgr.hxx>
  19. #define MYDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  20. EXTERN_C const GUID name \
  21. = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  22. MYDEFINE_GUID(CLSID_MSAdminBase_W, 0xa9e69610, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
  23. MYDEFINE_GUID(IID_IMSAdminBase_W, 0x70b51430, 0xb6ca, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
  24. MYDEFINE_GUID(CLSID_MSAdminBaseExe_W, 0xa9e69611, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
  25. MYDEFINE_GUID(IID_IMSAdminBaseSink_W, 0xa9e69612, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Member: CMetaDataMgr::CMetaDataMgr, public
  29. //
  30. // Synopsis: Creates an object for talking to the IIS metabase.
  31. //
  32. // Arguments: [fTopLevel] - TRUE for the top level, FALSE for a
  33. // vserver instance
  34. // [dwInstance] - instance # of the server
  35. // [eType] - type of vroot provider -- W3, NNTP, or IMAP
  36. // [pwcMachine] - the machine to open, L"." for local machine
  37. //
  38. // History: 07-Feb-1997 dlee Created
  39. //
  40. //--------------------------------------------------------------------------
  41. CMetaDataMgr::CMetaDataMgr(
  42. BOOL fTopLevel,
  43. CiVRootTypeEnum eType,
  44. DWORD dwInstance,
  45. WCHAR const * pwcMachine ) :
  46. _fNotifyEnabled( FALSE ),
  47. _fTopLevel( fTopLevel )
  48. {
  49. // -1 is a valid instance number, so this is a bogus assert, but it'll
  50. // never be hit unless something else is broken or someone hacked the
  51. // registry.
  52. #if CIDBG == 1
  53. if ( fTopLevel )
  54. Win4Assert( 0xffffffff == dwInstance );
  55. else
  56. Win4Assert( 0xffffffff != dwInstance );
  57. #endif // CIDBG == 1
  58. if ( fTopLevel )
  59. swprintf( _awcInstance, L"/lm/%ws", GetVRootService( eType ) );
  60. else
  61. swprintf( _awcInstance,
  62. L"/lm/%ws/%d",
  63. GetVRootService( eType ),
  64. dwInstance );
  65. IMSAdminBase * pcAdmCom;
  66. if ( !_wcsicmp( pwcMachine, L"." ) )
  67. {
  68. SCODE sc = CoCreateInstance( GETAdminBaseCLSID(TRUE),
  69. NULL,
  70. CLSCTX_ALL,
  71. IID_IMSAdminBase,
  72. (void **) &pcAdmCom );
  73. if ( FAILED(sc) )
  74. {
  75. ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CoCreateInstance: %x\n", sc ));
  76. THROW( CException(sc) );
  77. }
  78. }
  79. else
  80. {
  81. COSERVERINFO info;
  82. RtlZeroMemory( &info, sizeof info );
  83. info.pwszName = (WCHAR *) pwcMachine;
  84. XInterface<IClassFactory> xFactory;
  85. SCODE sc = CoGetClassObject( GETAdminBaseCLSID(TRUE),
  86. CLSCTX_SERVER,
  87. &info,
  88. IID_IClassFactory,
  89. xFactory.GetQIPointer() );
  90. if ( FAILED(sc) )
  91. {
  92. ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CoGetClassObject: %x\n", sc ));
  93. THROW( CException(sc) );
  94. }
  95. sc = xFactory->CreateInstance( 0, IID_IMSAdminBase, (void**) &pcAdmCom );
  96. if ( FAILED(sc) )
  97. {
  98. ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CreateInstance: %x\n", sc ));
  99. THROW( CException(sc) );
  100. }
  101. }
  102. _xAdminBase.Set( pcAdmCom );
  103. } //CMetaDataMgr
  104. //+-------------------------------------------------------------------------
  105. //
  106. // Member: CMetaDataMgr::~CMetaDataMgr, public
  107. //
  108. // Synopsis: Destroys an object for talking to the IIS metabase
  109. //
  110. // History: 07-Feb-1997 dlee Created
  111. //
  112. //--------------------------------------------------------------------------
  113. CMetaDataMgr::~CMetaDataMgr()
  114. {
  115. if ( !_xAdminBase.IsNull() )
  116. {
  117. // just in case we are still connected
  118. DisableVPathNotify();
  119. }
  120. } //~CMetaDataMgr
  121. //+-------------------------------------------------------------------------
  122. //
  123. // Member: CMetaDataMgr::IsIISAdminUp, public/static
  124. //
  125. // Synopsis: Returns TRUE if iisadmin svc is up
  126. //
  127. // Arguments: [fIISAdminInstalled] - returns TRUE if it's installed,
  128. // FALSE otherwise
  129. //
  130. // History: 07-Feb-1997 dlee Created
  131. //
  132. //--------------------------------------------------------------------------
  133. BOOL CMetaDataMgr::IsIISAdminUp(
  134. BOOL & fIISAdminInstalled )
  135. {
  136. fIISAdminInstalled = TRUE;
  137. BOOL fIsUp = TRUE;
  138. TRY
  139. {
  140. // The constructor will throw if the iisadmin svc is unavailable.
  141. CMetaDataMgr( TRUE, W3VRoot );
  142. }
  143. CATCH( CException, e )
  144. {
  145. fIsUp = FALSE;
  146. if ( REGDB_E_CLASSNOTREG == e.GetErrorCode() )
  147. fIISAdminInstalled = FALSE;
  148. }
  149. END_CATCH
  150. return fIsUp;
  151. } //IsIISAdminUp
  152. //+-------------------------------------------------------------------------
  153. //
  154. // Member: CMetaDataMgr::EnumVPaths, public
  155. //
  156. // Synopsis: Enumerates vpaths by calling the callback
  157. //
  158. // Arguments: [callBack] - called for each vpath
  159. //
  160. // History: 07-Feb-1997 dlee Created
  161. //
  162. //--------------------------------------------------------------------------
  163. void CMetaDataMgr::EnumVPaths(
  164. CMetaDataCallBack & callBack )
  165. {
  166. Win4Assert( !_fTopLevel );
  167. CMetaDataHandle mdRoot( _xAdminBase, _awcInstance );
  168. CVRootStack vrootStack;
  169. Enum( vrootStack, callBack, mdRoot, L"" );
  170. } //EnumVPaths
  171. //+-------------------------------------------------------------------------
  172. //
  173. // Member: CMetaDataMgr::AddVRoot, public
  174. //
  175. // Synopsis: Adds a VRoot to the metabase
  176. //
  177. // Arguments: [pwcVRoot] - name of the vroot, e.g.: /here
  178. // [pwcPRoot] - physical path of the vroot, e.g.: x:\here
  179. // [dwAccess] - access rights to the vroot
  180. //
  181. // History: 07-Feb-1997 dlee Created
  182. //
  183. //--------------------------------------------------------------------------
  184. void CMetaDataMgr::AddVRoot(
  185. WCHAR const * pwcVRoot,
  186. WCHAR const * pwcPRoot,
  187. DWORD dwAccess )
  188. {
  189. Win4Assert( !_fTopLevel );
  190. // blow it away if it currently exists
  191. RemoveVRoot( pwcVRoot );
  192. {
  193. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
  194. if ( cwc >= METADATA_MAX_NAME_LEN )
  195. THROW( CException( E_INVALIDARG ) );
  196. WCHAR awc[ METADATA_MAX_NAME_LEN ];
  197. wcscpy( awc, _awcInstance );
  198. wcscat( awc, L"/Root" );
  199. CMetaDataHandle mdRoot( _xAdminBase, awc, TRUE );
  200. _xAdminBase->AddKey( mdRoot.Get(), pwcVRoot );
  201. }
  202. WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
  203. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
  204. if ( cwc >= METADATA_MAX_NAME_LEN )
  205. THROW( CException( E_INVALIDARG ) );
  206. wcscpy( awcVRootPath, _awcInstance );
  207. wcscat( awcVRootPath, L"/Root" );
  208. wcscat( awcVRootPath, pwcVRoot );
  209. CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, TRUE );
  210. {
  211. METADATA_RECORD mdr;
  212. RtlZeroMemory( &mdr, sizeof mdr );
  213. mdr.dwMDIdentifier = MD_VR_PATH;
  214. mdr.dwMDAttributes = METADATA_INHERIT;
  215. mdr.dwMDUserType = IIS_MD_UT_FILE;
  216. mdr.dwMDDataType = STRING_METADATA;
  217. mdr.pbMDData = (BYTE *) pwcPRoot;
  218. mdr.dwMDDataLen = sizeof WCHAR * ( 1 + wcslen( pwcPRoot ) );
  219. DWORD cbRequired = 0;
  220. SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
  221. L"",
  222. &mdr );
  223. if ( FAILED( sc ) )
  224. {
  225. ciDebugOut(( DEB_WARN, "SetData PRoot failed: 0x%x\n", sc ));
  226. THROW( CException( sc ) );
  227. }
  228. }
  229. {
  230. // must set a null username to enforce metadata consistency
  231. METADATA_RECORD mdr;
  232. RtlZeroMemory( &mdr, sizeof mdr );
  233. mdr.dwMDIdentifier = MD_VR_USERNAME;
  234. mdr.dwMDAttributes = METADATA_INHERIT;
  235. mdr.dwMDUserType = IIS_MD_UT_SERVER;
  236. mdr.dwMDDataType = STRING_METADATA;
  237. mdr.pbMDData = (BYTE *) L"";
  238. mdr.dwMDDataLen = sizeof WCHAR;
  239. DWORD cbRequired = 0;
  240. SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
  241. L"",
  242. &mdr );
  243. if ( FAILED( sc ) )
  244. {
  245. ciDebugOut(( DEB_WARN, "SetData user failed: 0x%x\n", sc ));
  246. THROW( CException( sc ) );
  247. }
  248. }
  249. {
  250. METADATA_RECORD mdr;
  251. RtlZeroMemory( &mdr, sizeof mdr );
  252. mdr.dwMDIdentifier = MD_ACCESS_PERM;
  253. mdr.dwMDAttributes = METADATA_INHERIT;
  254. mdr.dwMDUserType = IIS_MD_UT_FILE;
  255. mdr.dwMDDataType = DWORD_METADATA;
  256. mdr.pbMDData = (BYTE *) &dwAccess;
  257. mdr.dwMDDataLen = sizeof dwAccess;
  258. DWORD cbRequired = 0;
  259. SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
  260. L"",
  261. &mdr );
  262. if ( FAILED( sc ) )
  263. {
  264. ciDebugOut(( DEB_WARN, "SetData accessperm failed: 0x%x\n", sc ));
  265. THROW( CException( sc ) );
  266. }
  267. }
  268. } //AddVRoot
  269. //+-------------------------------------------------------------------------
  270. //
  271. // Member: CMetaDataMgr::Flush, public
  272. //
  273. // Synopsis: Flushes the metabase, since it's not robust.
  274. //
  275. // History: 4-Dec-1998 dlee Created
  276. //
  277. //--------------------------------------------------------------------------
  278. void CMetaDataMgr::Flush()
  279. {
  280. SCODE sc = _xAdminBase->SaveData();
  281. if ( FAILED( sc ) )
  282. {
  283. ciDebugOut(( DEB_WARN, "CMetaDataMgr::Flush failed: %#x\n", sc ));
  284. THROW( CException( sc ) );
  285. }
  286. } //Flush
  287. //+-------------------------------------------------------------------------
  288. //
  289. // Member: CMetaDataMgr::RemoveVRoot, public
  290. //
  291. // Synopsis: Removes a VRoot from the metabase
  292. //
  293. // Arguments: [pwcVRoot] - name of the vroot. e.g.: /scripts
  294. //
  295. // Notes: Doesn't throw on failure to remove the root.
  296. //
  297. // History: 07-Feb-1997 dlee Created
  298. //
  299. //--------------------------------------------------------------------------
  300. SCODE CMetaDataMgr::RemoveVRoot(
  301. WCHAR const * pwcVRoot )
  302. {
  303. Win4Assert( !_fTopLevel );
  304. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
  305. if ( cwc >= METADATA_MAX_NAME_LEN )
  306. THROW( CException( E_INVALIDARG ) );
  307. WCHAR awcRoot[ METADATA_MAX_NAME_LEN ];
  308. wcscpy( awcRoot, _awcInstance );
  309. wcscat( awcRoot, L"/Root" );
  310. CMetaDataHandle mdRoot( _xAdminBase, awcRoot, TRUE );
  311. // don't throw on error deleting vroot -- the root may not exist
  312. return _xAdminBase->DeleteKey( mdRoot.Get(), pwcVRoot );
  313. } //RemoveVRoot
  314. //+-------------------------------------------------------------------------
  315. //
  316. // Member: CMetaDataMgr::WriteRootValue, private
  317. //
  318. // Synopsis: Retrieves data for the key and identifier
  319. //
  320. // Arguments: [mdRoot] - Metabase key where data reside
  321. // [mdr] - Scratch pad for the record. On output, can be
  322. // used to write the data, since all the
  323. // fields are initialized properly.
  324. // [xData] - Where data is written
  325. // [dwIdentifier] - The metabase id
  326. //
  327. // History: 24-Feb-1998 dlee Created
  328. //
  329. //--------------------------------------------------------------------------
  330. void CMetaDataMgr::ReadRootValue(
  331. CMetaDataHandle & mdRoot,
  332. METADATA_RECORD & mdr,
  333. XGrowable<WCHAR> & xData,
  334. DWORD dwIdentifier )
  335. {
  336. RtlZeroMemory( &mdr, sizeof mdr );
  337. mdr.dwMDIdentifier = dwIdentifier;
  338. // script maps, etc. can be enormous due to bugs in ISV apps
  339. do
  340. {
  341. mdr.pbMDData = (BYTE *) xData.Get();
  342. mdr.dwMDDataLen = xData.SizeOf();
  343. DWORD cbRequired = 0;
  344. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  345. L"",
  346. &mdr,
  347. &cbRequired );
  348. if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == sc )
  349. {
  350. xData.SetSizeInBytes( cbRequired );
  351. continue;
  352. }
  353. else if ( FAILED( sc ) )
  354. {
  355. ciDebugOut(( DEB_WARN, "GetData root value failed: 0x%x\n", sc ));
  356. THROW( CException( sc ) );
  357. }
  358. break;
  359. } while ( TRUE );
  360. } //ReadRootValue
  361. //+-------------------------------------------------------------------------
  362. //
  363. // Member: CMetaDataMgr::WriteRootValue, private
  364. //
  365. // Synopsis: Writes data to the key
  366. //
  367. // Arguments: [mdRoot] - Metabase key where data resides
  368. // [mdr] - Metadata record suitable for writing data
  369. // [pwcData] - Multi-sz string with data
  370. // [cwcData] - Total length including all terminating nulls
  371. //
  372. // History: 24-Feb-1998 dlee Created
  373. //
  374. //--------------------------------------------------------------------------
  375. void CMetaDataMgr::WriteRootValue(
  376. CMetaDataHandle & mdRoot,
  377. METADATA_RECORD & mdr,
  378. WCHAR const * pwcData,
  379. unsigned cwcData )
  380. {
  381. // note: the other fields in mdr were initialized properly by a call
  382. // to ReadRootValue.
  383. mdr.dwMDDataLen = sizeof WCHAR * cwcData;
  384. mdr.pbMDData = (BYTE *) pwcData;
  385. SCODE sc = _xAdminBase->SetData( mdRoot.Get(),
  386. L"",
  387. &mdr );
  388. if ( FAILED( sc ) )
  389. {
  390. ciDebugOut(( DEB_WARN, "SetData root value failed: 0x%x\n", sc ));
  391. THROW( CException( sc ) );
  392. }
  393. } //WriteRootValue
  394. //+-------------------------------------------------------------------------
  395. //
  396. // Member: CMetaDataMgr::AddScriptMap, public
  397. //
  398. // Synopsis: Adds a script map to the metabase
  399. //
  400. // Arguments: [pwcMap] - script map of the form:
  401. // L".idq,d:\\winnt\\system32\\idq.dll,0"
  402. //
  403. // History: 07-Feb-1997 dlee Created
  404. //
  405. //--------------------------------------------------------------------------
  406. void CMetaDataMgr::AddScriptMap(
  407. WCHAR const * pwcMap )
  408. {
  409. // remove the existing script map if it exists. have to get the
  410. // extension first.
  411. if ( wcslen( pwcMap ) > MAX_PATH )
  412. THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
  413. WCHAR awcExt[ MAX_PATH ];
  414. wcscpy( awcExt, pwcMap );
  415. WCHAR *pwc = wcschr( awcExt, L',' );
  416. if ( !pwc )
  417. THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
  418. *pwc = 0;
  419. RemoveScriptMap( awcExt );
  420. CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
  421. XGrowable<WCHAR> xMaps;
  422. METADATA_RECORD mdr;
  423. ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
  424. // add the new script map to the existing ones
  425. XGrowable<WCHAR> xTemp;
  426. xTemp.SetSize( xMaps.Count() + wcslen( pwcMap ) + 1 );
  427. WCHAR *pwcTemp = xTemp.Get();
  428. wcscpy( pwcTemp, pwcMap );
  429. pwcTemp += ( 1 + wcslen( pwcTemp ) );
  430. WCHAR * pwcOldMaps = xMaps.Get();
  431. while ( 0 != *pwcOldMaps )
  432. {
  433. wcscpy( pwcTemp, pwcOldMaps );
  434. int x = 1 + wcslen( pwcOldMaps );
  435. pwcTemp += x;
  436. pwcOldMaps += x;
  437. }
  438. *pwcTemp++ = 0;
  439. // write the new set of script maps
  440. WriteRootValue( mdRoot, mdr, xTemp.Get(), (UINT)( pwcTemp - xTemp.Get() ) );
  441. } //AddScriptMap
  442. //+-------------------------------------------------------------------------
  443. //
  444. // Member: CMetaDataMgr::RemoveScriptMap, public
  445. //
  446. // Synopsis: Removes a script map from the metabase
  447. //
  448. // Arguments: [pwcExt] - extension of map to remove: L".idq"
  449. //
  450. // History: 07-Feb-1997 dlee Created
  451. //
  452. //--------------------------------------------------------------------------
  453. void CMetaDataMgr::RemoveScriptMap(
  454. WCHAR const * pwcExt )
  455. {
  456. // retrieve the existing script maps
  457. CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
  458. XGrowable<WCHAR> xMaps;
  459. METADATA_RECORD mdr;
  460. ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
  461. // awcMaps is a multi-sz string
  462. XGrowable<WCHAR> xNew( xMaps.Count() );
  463. WCHAR *pwcNew = xNew.Get();
  464. pwcNew[0] = 0;
  465. int cwcExt = wcslen( pwcExt );
  466. BOOL fFound = FALSE;
  467. // re-add all mappings other than pwcExt
  468. WCHAR const *pwcCur = xMaps.Get();
  469. while ( 0 != *pwcCur )
  470. {
  471. if ( _wcsnicmp( pwcCur, pwcExt, cwcExt ) ||
  472. L',' != pwcCur[cwcExt] )
  473. {
  474. wcscpy( pwcNew, pwcCur );
  475. pwcNew += ( 1 + wcslen( pwcNew ) );
  476. }
  477. else
  478. {
  479. fFound = TRUE;
  480. }
  481. int cwc = wcslen( pwcCur );
  482. pwcCur += ( cwc + 1 );
  483. }
  484. // If the script map wasn't found, don't do the write
  485. if ( !fFound )
  486. return;
  487. *pwcNew++ = 0;
  488. // got the string, now pound it in the metabase
  489. WriteRootValue( mdRoot, mdr, xNew.Get(), (UINT)(pwcNew - xNew.Get()) );
  490. } //RemoveScriptMap
  491. //+-------------------------------------------------------------------------
  492. //
  493. // Member: CMetaDataMgr::ExtensionHasScriptMap, public
  494. //
  495. // Synopsis: Finds a script map in the metabase
  496. //
  497. // Arguments: [pwcExt] - extension of map to lookup: L".idq"
  498. //
  499. // Returns: TRUE if the extension has a script map association
  500. // FALSE otherwise
  501. //
  502. // History: 10-Jul-1997 dlee Created
  503. //
  504. //--------------------------------------------------------------------------
  505. BOOL CMetaDataMgr::ExtensionHasScriptMap(
  506. WCHAR const * pwcExt )
  507. {
  508. CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", FALSE );
  509. XGrowable<WCHAR> xMaps;
  510. METADATA_RECORD mdr;
  511. ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
  512. // xMaps is a multi-sz string, look for pwcExt
  513. int cwcExt = wcslen( pwcExt );
  514. WCHAR *pwcCur = xMaps.Get();
  515. while ( 0 != *pwcCur )
  516. {
  517. if ( !_wcsnicmp( pwcCur, pwcExt, cwcExt ) &&
  518. L',' == pwcCur[cwcExt] )
  519. return TRUE;
  520. int cwc = wcslen( pwcCur );
  521. pwcCur += ( cwc + 1 );
  522. }
  523. return FALSE;
  524. } //ExtensionHasScriptMap
  525. //+-------------------------------------------------------------------------
  526. //
  527. // Member: CMetaDataMgr::ExtensionHasTargetScriptMap, public
  528. //
  529. // Synopsis: Sees if a scriptmap is pointing at a given dll
  530. //
  531. // Arguments: [pwcExt] - extension of map to lookup: L".idq"
  532. // [pwcDll] - DLL to check, e.g. L"idq.dll"
  533. //
  534. // Returns: TRUE if the extension has a script map association
  535. // FALSE otherwise
  536. //
  537. // History: 10-Jul-1997 dlee Created
  538. //
  539. // Note: scriptmaps look like ".idq,c:\\windows\\system32\\idq.dll,3,GET,HEAD,POST"
  540. //
  541. //--------------------------------------------------------------------------
  542. BOOL CMetaDataMgr::ExtensionHasTargetScriptMap(
  543. WCHAR const * pwcExt,
  544. WCHAR const * pwcDll )
  545. {
  546. CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", FALSE );
  547. XGrowable<WCHAR> xMaps;
  548. METADATA_RECORD mdr;
  549. ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
  550. // xMaps is a multi-sz string, look for pwcExt
  551. int cwcExt = wcslen( pwcExt );
  552. WCHAR *pwcCur = xMaps.Get();
  553. int cwcDll = wcslen( pwcDll );
  554. while ( 0 != *pwcCur )
  555. {
  556. if ( !_wcsnicmp( pwcCur, pwcExt, cwcExt ) &&
  557. L',' == pwcCur[cwcExt] )
  558. {
  559. // Skip to the end of the full path and check the dll name
  560. WCHAR const * pwcSlash = wcsrchr( pwcCur, L'\\' );
  561. if ( 0 != pwcSlash )
  562. {
  563. if ( !_wcsnicmp( pwcSlash + 1, pwcDll, cwcDll ) )
  564. return TRUE;
  565. }
  566. }
  567. int cwc = wcslen( pwcCur );
  568. pwcCur += ( cwc + 1 );
  569. }
  570. return FALSE;
  571. } //ExtensionHasTargetScriptMap
  572. //+-------------------------------------------------------------------------
  573. //
  574. // Member: CMetaDataMgr::AddInProcessApp, public
  575. //
  576. // Synopsis: Adds an app to the list of in-process apps
  577. //
  578. // Arguments: [pwcApp] - App in the form "d:\\winnt\\system32\\idq.dll"
  579. //
  580. // History: 09-Dec-1998 dlee Created
  581. //
  582. //--------------------------------------------------------------------------
  583. void CMetaDataMgr::AddInProcessIsapiApp( WCHAR const * pwcApp )
  584. {
  585. //
  586. // Read the existing multi-sz value
  587. //
  588. CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
  589. XGrowable<WCHAR> xApps;
  590. METADATA_RECORD mdr;
  591. ReadRootValue( mdRoot, mdr, xApps, MD_IN_PROCESS_ISAPI_APPS );
  592. WCHAR *pwcCur = xApps.Get();
  593. //
  594. // Look for an existing entry so a duplicate isn't added
  595. //
  596. while ( 0 != *pwcCur )
  597. {
  598. //
  599. // If it's already there, leave it alone
  600. //
  601. if ( !_wcsicmp( pwcCur, pwcApp ) )
  602. return;
  603. int cwc = wcslen( pwcCur );
  604. pwcCur += ( cwc + 1 );
  605. }
  606. unsigned cwcOld = 1 + (unsigned) ( pwcCur - xApps.Get() );
  607. //
  608. // It wasn't found, so add it
  609. //
  610. unsigned cwc = wcslen( pwcApp ) + 1;
  611. XGrowable<WCHAR> xNew( cwcOld + cwc );
  612. RtlCopyMemory( xNew.Get(), pwcApp, cwc * sizeof WCHAR );
  613. RtlCopyMemory( xNew.Get() + cwc, xApps.Get(), cwcOld * sizeof WCHAR );
  614. WriteRootValue( mdRoot, mdr, xNew.Get(), cwcOld + cwc );
  615. } //AddInProcessIsapiApp
  616. //+-------------------------------------------------------------------------
  617. //
  618. // Member: CMetaDataMgr::EnableVPathNotify, public
  619. //
  620. // Synopsis: Enables notification of vpaths
  621. //
  622. // Arguments: [pCallBack] - called on a change to any vpaths
  623. //
  624. // History: 07-Feb-1997 dlee Created
  625. //
  626. //--------------------------------------------------------------------------
  627. void CMetaDataMgr::EnableVPathNotify(
  628. CMetaDataVPathChangeCallBack *pCallBack )
  629. {
  630. Win4Assert( !_fTopLevel );
  631. Win4Assert( !_fNotifyEnabled );
  632. if ( _fNotifyEnabled )
  633. THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
  634. ciDebugOut(( DEB_WARN,
  635. "enabling vpath notifications on '%ws'\n",
  636. _awcInstance ));
  637. Win4Assert( _xSink.IsNull() );
  638. //
  639. // NOTE: This new will be reported as a leak if iisamin dies or fails
  640. // to call Release() on the sink the right number of times.
  641. //
  642. XInterface<CMetaDataComSink> xSink( new CMetaDataComSink() );
  643. xSink->SetCallBack( pCallBack );
  644. xSink->SetInstance( _awcInstance );
  645. XInterface< IConnectionPointContainer > xCPC;
  646. SCODE sc = _xAdminBase->QueryInterface( IID_IConnectionPointContainer,
  647. xCPC.GetQIPointer() );
  648. if ( FAILED( sc ) )
  649. {
  650. ciDebugOut(( DEB_WARN, "could not get cpc: 0x%x\n", sc ));
  651. THROW( CException( sc ) );
  652. }
  653. XInterface< IConnectionPoint> xCP;
  654. sc = xCPC->FindConnectionPoint( IID_IMSAdminBaseSink, xCP.GetPPointer() );
  655. if ( FAILED( sc ) )
  656. {
  657. ciDebugOut(( DEB_WARN, "could not get cp: 0x%x\n", sc ));
  658. THROW( CException( sc ) );
  659. }
  660. //
  661. // Tell COM to impersonate at IMPERSONATE level instead of the default
  662. // IDENTITY level. This is to work-around a change made in IIS in
  663. // Windows 2000 SP1.
  664. //
  665. sc = CoSetProxyBlanket( xCP.GetPointer(),
  666. RPC_C_AUTHN_WINNT, // use NT default security
  667. RPC_C_AUTHZ_NONE, // use NT default authentication
  668. NULL, // must be null if default
  669. RPC_C_AUTHN_LEVEL_CALL, // call
  670. RPC_C_IMP_LEVEL_IMPERSONATE,
  671. NULL, // use process token
  672. EOAC_STATIC_CLOAKING );
  673. if ( FAILED( sc ) )
  674. {
  675. ciDebugOut(( DEB_WARN, "could not set proxy blanket: %#x\n", sc ));
  676. THROW( CException( sc ) );
  677. }
  678. sc = xCP->Advise( xSink.GetPointer(), &_dwCookie);
  679. if ( FAILED( sc ) )
  680. {
  681. ciDebugOut(( DEB_WARN, "could not advise cp: 0x%x\n", sc ));
  682. THROW( CException( sc ) );
  683. }
  684. _xCP.Set( xCP.Acquire() );
  685. _xSink.Set( xSink.Acquire() );
  686. _fNotifyEnabled = TRUE;
  687. } //EnableVPathNotify
  688. //+-------------------------------------------------------------------------
  689. //
  690. // Member: CMetaDataMgr::DisableVPathNotify, public
  691. //
  692. // Synopsis: Disables notification on VPaths
  693. //
  694. // History: 07-Feb-1997 dlee Created
  695. //
  696. //--------------------------------------------------------------------------
  697. void CMetaDataMgr::DisableVPathNotify()
  698. {
  699. if ( _fNotifyEnabled )
  700. {
  701. SCODE sc = _xCP->Unadvise( _dwCookie );
  702. ciDebugOut(( DEB_ITRACE, "result of unadvise: 0x%x\n", sc ));
  703. _fNotifyEnabled = FALSE;
  704. //
  705. // Note: The sink may still have a refcount after the free if
  706. // iisadmin has a bug or their process died. We can't just
  707. // delete it here because CoUninitialize() will realize
  708. // iisadmin messed up and try to help by calling Release()
  709. // for iisadmin.
  710. //
  711. _xSink.Free();
  712. _xCP.Free();
  713. }
  714. } //DisableVPathNotify
  715. //+-------------------------------------------------------------------------
  716. //
  717. // Member: CMetaDataMgr::ReportVPath, private
  718. //
  719. // Synopsis: Helper method for reporting a vpath via callback
  720. //
  721. // Arguments: [vrootStack] - stack of vroots for depth-first search
  722. // [mdRoot] - handle to the root of the enumeration
  723. // [callBack] - callback to call for vpath
  724. // [pwcRelative] - relative path in metabase
  725. //
  726. // Returns: TRUE if the vpath is a vroot and was pushed on vrootStack
  727. //
  728. // History: 07-Feb-1997 dlee Created
  729. //
  730. //--------------------------------------------------------------------------
  731. BOOL CMetaDataMgr::ReportVPath(
  732. CVRootStack & vrootStack,
  733. CMetaDataCallBack & callBack,
  734. CMetaDataHandle & mdRoot,
  735. WCHAR const * pwcRelative )
  736. {
  737. Win4Assert( !_fTopLevel );
  738. // read the path, username, access permissions, and password
  739. WCHAR awcPPath[ METADATA_MAX_NAME_LEN ];
  740. awcPPath[0] = 0;
  741. WCHAR awcUser[ METADATA_MAX_NAME_LEN ];
  742. awcUser[0] = 0;
  743. DWORD dwAccess = 0;
  744. WCHAR awcPassword[ METADATA_MAX_NAME_LEN ];
  745. awcPassword[0] = 0;
  746. BOOL fIsIndexed = TRUE;
  747. BOOL fVRoot = TRUE;
  748. // Get the metabase access permission mask
  749. {
  750. METADATA_RECORD mdr;
  751. RtlZeroMemory( &mdr, sizeof mdr );
  752. mdr.dwMDIdentifier = MD_ACCESS_PERM;
  753. mdr.dwMDAttributes = METADATA_INHERIT;
  754. mdr.pbMDData = (BYTE *) &dwAccess;
  755. mdr.dwMDDataLen = sizeof dwAccess;
  756. DWORD cbRequired = 0;
  757. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  758. pwcRelative,
  759. &mdr,
  760. &cbRequired );
  761. if ( ( FAILED( sc ) ) &&
  762. ( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
  763. {
  764. ciDebugOut(( DEB_WARN, "GetData awccessperm failed: 0x%x\n", sc ));
  765. THROW( CException( sc ) );
  766. }
  767. }
  768. // Get the physical path if one exists
  769. {
  770. METADATA_RECORD mdr;
  771. RtlZeroMemory( &mdr, sizeof mdr );
  772. mdr.dwMDIdentifier = MD_VR_PATH;
  773. mdr.pbMDData = (BYTE *) awcPPath;
  774. mdr.dwMDDataLen = sizeof awcPPath;
  775. DWORD cbRequired = 0;
  776. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  777. pwcRelative,
  778. &mdr,
  779. &cbRequired );
  780. if ( ( FAILED( sc ) ) &&
  781. ( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
  782. {
  783. ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
  784. THROW( CException( sc ) );
  785. }
  786. }
  787. //
  788. // Only look for a username/access/password if there is a physical path,
  789. // since it can only be a virtual root if it has a physical path.
  790. //
  791. if ( 0 != awcPPath[0] )
  792. {
  793. // Trim any trailing backslash from the physical path
  794. unsigned cwcPRoot = wcslen( awcPPath );
  795. Win4Assert( 0 != cwcPRoot );
  796. if ( L'\\' == awcPPath[ cwcPRoot - 1 ] )
  797. awcPPath[ cwcPRoot - 1 ] = 0;
  798. {
  799. METADATA_RECORD mdr;
  800. RtlZeroMemory( &mdr, sizeof mdr );
  801. mdr.dwMDIdentifier = MD_VR_USERNAME;
  802. mdr.pbMDData = (BYTE *) awcUser;
  803. mdr.dwMDDataLen = sizeof awcUser;
  804. DWORD cbRequired = 0;
  805. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  806. pwcRelative,
  807. &mdr,
  808. &cbRequired );
  809. if ( ( FAILED( sc ) ) &&
  810. ( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
  811. {
  812. ciDebugOut(( DEB_WARN, "GetData user failed: 0x%x\n", sc ));
  813. THROW( CException( sc ) );
  814. }
  815. }
  816. {
  817. METADATA_RECORD mdr;
  818. RtlZeroMemory( &mdr, sizeof mdr );
  819. mdr.dwMDIdentifier = MD_VR_PASSWORD;
  820. mdr.pbMDData = (BYTE *) awcPassword;
  821. mdr.dwMDDataLen = sizeof awcPassword;
  822. DWORD cbRequired = 0;
  823. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  824. pwcRelative,
  825. &mdr,
  826. &cbRequired );
  827. if ( ( FAILED( sc ) ) &&
  828. ( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
  829. {
  830. ciDebugOut(( DEB_WARN, "GetData password failed: 0x%x\n", sc ));
  831. THROW( CException( sc ) );
  832. }
  833. }
  834. }
  835. {
  836. METADATA_RECORD mdr;
  837. RtlZeroMemory( &mdr, sizeof mdr );
  838. mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
  839. mdr.dwMDAttributes = METADATA_INHERIT;
  840. mdr.pbMDData = (BYTE *) &fIsIndexed;
  841. mdr.dwMDDataLen = sizeof fIsIndexed;
  842. DWORD cbRequired = 0;
  843. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  844. pwcRelative,
  845. &mdr,
  846. &cbRequired );
  847. if ( MD_ERROR_DATA_NOT_FOUND == sc )
  848. {
  849. fIsIndexed = FALSE;
  850. }
  851. else if ( FAILED( sc ) )
  852. {
  853. ciDebugOut(( DEB_WARN, "GetData isindexed failed: 0x%x\n", sc ));
  854. THROW( CException( sc ) );
  855. }
  856. }
  857. WCHAR awcVPath[METADATA_MAX_NAME_LEN];
  858. wcscpy( awcVPath, pwcRelative );
  859. WCHAR *pwcVPath = awcVPath;
  860. // Important: The metabase names root "/Root" the rest of the world
  861. // names root "/".
  862. if ( !_wcsicmp( awcVPath, L"/Root" ) )
  863. awcVPath[1] = 0;
  864. else if ( !_wcsnicmp( awcVPath, L"/Root", 5 ) )
  865. {
  866. Win4Assert( L'/' == awcVPath[5] );
  867. pwcVPath = awcVPath + 5;
  868. }
  869. if ( 0 == awcPPath[0] )
  870. {
  871. // if there isn't a physical path, it isn't a virtual root.
  872. fVRoot = FALSE;
  873. if ( vrootStack.IsEmpty() )
  874. {
  875. awcPPath[0] = 0;
  876. }
  877. else
  878. {
  879. // generate a physical path based on the virtual path and
  880. // the most recent vroot parent on the stack
  881. ciDebugOut(( DEB_ITRACE,
  882. "making vpath from vroot '%ws' proot '%ws' vpath '%ws'\n",
  883. vrootStack.PeekTopVRoot(),
  884. vrootStack.PeekTopPRoot(),
  885. pwcVPath ));
  886. wcscpy( awcPPath, vrootStack.PeekTopPRoot() );
  887. unsigned cwcVRoot = wcslen( vrootStack.PeekTopVRoot() );
  888. unsigned cwcPRoot = wcslen( vrootStack.PeekTopPRoot() );
  889. // The metabase can contain trailing backslashes in physical paths
  890. if ( L'\\' == awcPPath[ cwcPRoot - 1 ] )
  891. cwcPRoot--;
  892. wcscpy( awcPPath + cwcPRoot,
  893. pwcVPath + ( ( 1 == cwcVRoot ) ? 0 : cwcVRoot ) );
  894. for ( WCHAR *pwc = awcPPath + cwcPRoot;
  895. 0 != *pwc;
  896. pwc++ )
  897. {
  898. if ( L'/' == *pwc )
  899. *pwc = L'\\';
  900. }
  901. ciDebugOut(( DEB_ITRACE, "resulting ppath: '%ws'\n", awcPPath ));
  902. }
  903. }
  904. // now we can finally call the callback
  905. if ( 0 != awcPPath[0] )
  906. callBack.CallBack( pwcVPath,
  907. awcPPath,
  908. fIsIndexed,
  909. dwAccess,
  910. awcUser,
  911. awcPassword,
  912. fVRoot );
  913. if ( fVRoot )
  914. vrootStack.Push( pwcVPath, awcPPath, dwAccess );
  915. return fVRoot;
  916. } //ReportVPath
  917. //+-------------------------------------------------------------------------
  918. //
  919. // Member: CMetaDataMgr::EnumVServers, public
  920. //
  921. // Synopsis: Enumerates virtual servers by calling the callback
  922. //
  923. // Arguments: [callBack] - called for each vroot
  924. //
  925. // History: 07-Feb-1997 dlee Created
  926. //
  927. //--------------------------------------------------------------------------
  928. void CMetaDataMgr::EnumVServers( CMetaDataVirtualServerCallBack & callBack )
  929. {
  930. Win4Assert( _fTopLevel );
  931. CMetaDataHandle mdRoot( _xAdminBase, _awcInstance );
  932. Enum( callBack, mdRoot, L"" );
  933. } //EnumVRoots
  934. //+-------------------------------------------------------------------------
  935. //
  936. // Member: CMetaDataMgr::ReportVirtualServer, private
  937. //
  938. // Synopsis: Helper method for reporting a virtual server via callback
  939. //
  940. // Arguments: [callBack] - callback to call for virtual server
  941. // [pwcRelative] - relative path in metabase
  942. //
  943. // History: 07-Feb-1997 dlee Created
  944. //
  945. //--------------------------------------------------------------------------
  946. void CMetaDataMgr::ReportVirtualServer(
  947. CMetaDataVirtualServerCallBack & callBack,
  948. CMetaDataHandle & mdRoot,
  949. WCHAR const * pwcRelative )
  950. {
  951. Win4Assert( _fTopLevel );
  952. // read the comment
  953. WCHAR awcComment[ METADATA_MAX_NAME_LEN ];
  954. awcComment[0] = 0;
  955. {
  956. METADATA_RECORD mdr;
  957. RtlZeroMemory( &mdr, sizeof mdr );
  958. mdr.dwMDIdentifier = MD_SERVER_COMMENT;
  959. mdr.pbMDData = (BYTE *) awcComment;
  960. mdr.dwMDDataLen = sizeof awcComment;
  961. DWORD cbRequired = 0;
  962. SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
  963. pwcRelative,
  964. &mdr,
  965. &cbRequired );
  966. if ( ( FAILED( sc ) ) &&
  967. ( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
  968. {
  969. ciDebugOut(( DEB_WARN, "GetData virtual server failed: 0x%x\n", sc ));
  970. THROW( CException( sc ) );
  971. }
  972. }
  973. //
  974. // Convert ID to integer
  975. //
  976. DWORD iInstance = wcstoul( pwcRelative, 0, 10 );
  977. // now we can finally call the callback
  978. callBack.CallBack( iInstance, awcComment );
  979. } //ReportVirtualServer
  980. //+-------------------------------------------------------------------------
  981. //
  982. // Member: CMetaDataMgr::Enum, private
  983. //
  984. // Synopsis: Helper method for enumerating vpaths
  985. //
  986. // Arguments: [vrootStack] - stack of vroots for depth-first search
  987. // [callBack] - callback to call when a vpath is found
  988. // [mdRoot] - root of the enumeration
  989. // [pwcRelative] - relative location in enumeration
  990. //
  991. // History: 07-Feb-1997 dlee Created
  992. //
  993. //--------------------------------------------------------------------------
  994. void CMetaDataMgr::Enum(
  995. CVRootStack & vrootStack,
  996. CMetaDataCallBack & callBack,
  997. CMetaDataHandle & mdRoot,
  998. WCHAR const * pwcRelative )
  999. {
  1000. // enumerate looking for vpaths
  1001. int c = wcslen( pwcRelative );
  1002. WCHAR awcNewRelPath[ METADATA_MAX_NAME_LEN ];
  1003. RtlCopyMemory( awcNewRelPath, pwcRelative, (c + 1) * sizeof WCHAR );
  1004. if ( 0 == c ||
  1005. L'/' != pwcRelative[c-1] )
  1006. {
  1007. wcscpy( awcNewRelPath + c, L"/" );
  1008. c++;
  1009. }
  1010. for ( int i = 0; ; i++ )
  1011. {
  1012. WCHAR NameBuf[METADATA_MAX_NAME_LEN];
  1013. SCODE sc =_xAdminBase->EnumKeys( mdRoot.Get(),
  1014. pwcRelative,
  1015. NameBuf,
  1016. i );
  1017. if ( RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS) == sc )
  1018. break;
  1019. if ( FAILED( sc ) )
  1020. {
  1021. ciDebugOut(( DEB_WARN, "EnumKeys error 0x%x\n", sc ));
  1022. THROW( CException( sc ) );
  1023. }
  1024. Win4Assert( 0 != NameBuf[0] );
  1025. Win4Assert( ( c + wcslen( NameBuf ) ) < METADATA_MAX_NAME_LEN );
  1026. wcscpy( awcNewRelPath + c, NameBuf );
  1027. BOOL fVRoot = ReportVPath( vrootStack,
  1028. callBack,
  1029. mdRoot,
  1030. awcNewRelPath );
  1031. Enum( vrootStack, callBack, mdRoot, awcNewRelPath );
  1032. if ( fVRoot )
  1033. vrootStack.Pop();
  1034. }
  1035. } //Enum
  1036. //+-------------------------------------------------------------------------
  1037. //
  1038. // Member: CMetaDataMgr::Enum, private
  1039. //
  1040. // Synopsis: Helper method for enumerating virtual servers
  1041. //
  1042. // Arguments: [callBack] - callback to call when a vserver is found
  1043. // [mdRoot] - root of the enumeration
  1044. // [pwcRelative] - relative location in enumeration
  1045. //
  1046. // History: 07-Feb-1997 dlee Created
  1047. //
  1048. //--------------------------------------------------------------------------
  1049. void CMetaDataMgr::Enum(
  1050. CMetaDataVirtualServerCallBack & callBack,
  1051. CMetaDataHandle & mdRoot,
  1052. WCHAR const * pwcRelative )
  1053. {
  1054. // enumerate looking for virtual servers
  1055. for ( int i = 0; ; i++ )
  1056. {
  1057. WCHAR NameBuf[METADATA_MAX_NAME_LEN];
  1058. SCODE sc =_xAdminBase->EnumKeys( mdRoot.Get(),
  1059. pwcRelative,
  1060. NameBuf,
  1061. i );
  1062. if ( RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS) == sc )
  1063. break;
  1064. if ( FAILED( sc ) )
  1065. {
  1066. ciDebugOut(( DEB_WARN, "EnumKeys error 0x%x\n", sc ));
  1067. THROW( CException( sc ) );
  1068. }
  1069. ciDebugOut(( DEB_WARN, "Key: %ws\n", NameBuf ));
  1070. //
  1071. // Ignore things that don't look like virtual servers.
  1072. //
  1073. if ( !isdigit( NameBuf[0] ) )
  1074. continue;
  1075. //
  1076. // Assume we just got a virtual server.
  1077. //
  1078. ReportVirtualServer( callBack, mdRoot, NameBuf );
  1079. }
  1080. } //Enum
  1081. //+-------------------------------------------------------------------------
  1082. //
  1083. // Member: CMetaDataMgr::GetVRoot, public
  1084. //
  1085. // Synopsis: Returns the physical root corresponding to a virtual root
  1086. //
  1087. // Arguments: [pwcVRoot] - VRoot to lookup
  1088. // [pwcPRoot] - where pwcVRoot's physical root is returned
  1089. //
  1090. // History: 07-Feb-1997 dlee Created
  1091. //
  1092. //--------------------------------------------------------------------------
  1093. void CMetaDataMgr::GetVRoot(
  1094. WCHAR const * pwcVRoot,
  1095. WCHAR * pwcPRoot )
  1096. {
  1097. Win4Assert( !_fTopLevel );
  1098. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
  1099. if ( cwc >= METADATA_MAX_NAME_LEN )
  1100. THROW( CException( E_INVALIDARG ) );
  1101. WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
  1102. wcscpy( awcVRootPath, _awcInstance );
  1103. wcscat( awcVRootPath, L"/Root" );
  1104. wcscat( awcVRootPath, pwcVRoot );
  1105. CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, FALSE );
  1106. *pwcPRoot = 0;
  1107. {
  1108. METADATA_RECORD mdr;
  1109. RtlZeroMemory( &mdr, sizeof mdr );
  1110. mdr.dwMDIdentifier = MD_VR_PATH;
  1111. mdr.pbMDData = (BYTE *) pwcPRoot;
  1112. mdr.dwMDDataLen = METADATA_MAX_NAME_LEN * sizeof WCHAR;
  1113. DWORD cbRequired = 0;
  1114. SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
  1115. L"",
  1116. &mdr,
  1117. &cbRequired );
  1118. if ( FAILED( sc ) )
  1119. {
  1120. ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
  1121. THROW( CException( sc ) );
  1122. }
  1123. }
  1124. } //GetVRoot
  1125. //+-------------------------------------------------------------------------
  1126. //
  1127. // Member: CMetaDataMgr::GetVRootPW, public
  1128. //
  1129. // Synopsis: Returns the physical root corresponding to a virtual root
  1130. //
  1131. // Arguments: [pwcVRoot] - VRoot to lookup
  1132. // [pwcPRoot] - where pwcVRoot's physical root is returned
  1133. //
  1134. // History: 07-Feb-1997 dlee Created
  1135. //
  1136. //--------------------------------------------------------------------------
  1137. void CMetaDataMgr::GetVRootPW(
  1138. WCHAR const * pwcVRoot,
  1139. WCHAR * pwcPW )
  1140. {
  1141. Win4Assert( !_fTopLevel );
  1142. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
  1143. if ( cwc >= METADATA_MAX_NAME_LEN )
  1144. THROW( CException( E_INVALIDARG ) );
  1145. WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
  1146. wcscpy( awcVRootPath, _awcInstance );
  1147. wcscat( awcVRootPath, L"/Root" );
  1148. wcscat( awcVRootPath, pwcVRoot );
  1149. CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, FALSE );
  1150. *pwcPW = 0;
  1151. {
  1152. METADATA_RECORD mdr;
  1153. RtlZeroMemory( &mdr, sizeof mdr );
  1154. mdr.dwMDIdentifier = MD_VR_PASSWORD;
  1155. mdr.pbMDData = (BYTE *) pwcPW;
  1156. mdr.dwMDDataLen = METADATA_MAX_NAME_LEN * sizeof WCHAR;
  1157. DWORD cbRequired = 0;
  1158. SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
  1159. L"",
  1160. &mdr,
  1161. &cbRequired );
  1162. //char ac[ 1000 ];
  1163. //sprintf( ac, "result: 0x%x, cbResult: 0x%x, string: '%ws', char 1: 0x%x\n",
  1164. // sc, mdr.dwMDDataLen, pwcPW, (ULONG) *pwcPW );
  1165. //DbgPrint( ac );
  1166. if ( FAILED( sc ) )
  1167. {
  1168. ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
  1169. THROW( CException( sc ) );
  1170. }
  1171. }
  1172. } //GetVRootPW
  1173. //+-------------------------------------------------------------------------
  1174. //
  1175. // Member: CMetaDataMgr::SetIsIndexed, public
  1176. //
  1177. // Synopsis: Sets the indexed state of a virtual path
  1178. //
  1179. // Arguments: [pwcPath] - Virtual path (optionally a vroot) to set
  1180. // [fIsIndexed] - if TRUE, path is indexed, if FALSE it isn't
  1181. //
  1182. // History: 19-Mar-1997 dlee Created
  1183. //
  1184. //--------------------------------------------------------------------------
  1185. void CMetaDataMgr::SetIsIndexed(
  1186. WCHAR const * pwcVPath,
  1187. BOOL fIsIndexed )
  1188. {
  1189. // Add the key if it doesn't exist yet
  1190. {
  1191. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
  1192. if ( cwc >= METADATA_MAX_NAME_LEN )
  1193. THROW( CException( E_INVALIDARG ) );
  1194. WCHAR awc[ METADATA_MAX_NAME_LEN ];
  1195. wcscpy( awc, _awcInstance );
  1196. wcscat( awc, L"/Root" );
  1197. CMetaDataHandle mdRoot( _xAdminBase, awc, TRUE );
  1198. _xAdminBase->AddKey( mdRoot.Get(), pwcVPath );
  1199. }
  1200. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
  1201. if ( cwc >= METADATA_MAX_NAME_LEN )
  1202. THROW( CException( E_INVALIDARG ) );
  1203. WCHAR awcCompleteVPath[ METADATA_MAX_NAME_LEN ];
  1204. wcscpy( awcCompleteVPath, _awcInstance );
  1205. wcscat( awcCompleteVPath, L"/Root" );
  1206. wcscat( awcCompleteVPath, pwcVPath );
  1207. CMetaDataHandle mdVRoot( _xAdminBase, awcCompleteVPath, TRUE );
  1208. {
  1209. METADATA_RECORD mdr;
  1210. RtlZeroMemory( &mdr, sizeof mdr );
  1211. mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
  1212. mdr.dwMDAttributes = METADATA_INHERIT;
  1213. mdr.dwMDUserType = IIS_MD_UT_FILE;
  1214. mdr.dwMDDataType = DWORD_METADATA;
  1215. mdr.pbMDData = (BYTE *) &fIsIndexed;
  1216. mdr.dwMDDataLen = sizeof fIsIndexed;
  1217. DWORD cbRequired = 0;
  1218. SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
  1219. L"",
  1220. &mdr );
  1221. if ( FAILED( sc ) )
  1222. {
  1223. ciDebugOut(( DEB_WARN, "SetData isindexed failed: 0x%x\n", sc ));
  1224. THROW( CException( sc ) );
  1225. }
  1226. }
  1227. } //SetIsIndexed
  1228. //+-------------------------------------------------------------------------
  1229. //
  1230. // Member: CMetaDataMgr::IsIndexed, public
  1231. //
  1232. // Synopsis: Checks the path to return the state of the IsIndexed flag.
  1233. // The default for no value is TRUE. No checking is made to
  1234. // if a parent directory is indexed or not.
  1235. //
  1236. // Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
  1237. //
  1238. // History: 19-Mar-1997 dlee Created
  1239. //
  1240. //--------------------------------------------------------------------------
  1241. BOOL CMetaDataMgr::IsIndexed(
  1242. WCHAR const * pwcVPath )
  1243. {
  1244. BOOL fIsIndexed = TRUE;
  1245. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
  1246. if ( cwc >= METADATA_MAX_NAME_LEN )
  1247. THROW( CException( E_INVALIDARG ) );
  1248. WCHAR awcCompletePath[ METADATA_MAX_NAME_LEN ];
  1249. wcscpy( awcCompletePath, _awcInstance );
  1250. wcscat( awcCompletePath, L"/Root" );
  1251. wcscat( awcCompletePath, pwcVPath );
  1252. TRY
  1253. {
  1254. CMetaDataHandle mdVRoot( _xAdminBase, awcCompletePath, FALSE );
  1255. {
  1256. METADATA_RECORD mdr;
  1257. RtlZeroMemory( &mdr, sizeof mdr );
  1258. mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
  1259. mdr.dwMDAttributes = METADATA_INHERIT;
  1260. mdr.pbMDData = (BYTE *) &fIsIndexed;
  1261. mdr.dwMDDataLen = sizeof fIsIndexed;
  1262. DWORD cbRequired = 0;
  1263. SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
  1264. L"",
  1265. &mdr,
  1266. &cbRequired );
  1267. if ( MD_ERROR_DATA_NOT_FOUND == sc )
  1268. {
  1269. fIsIndexed = FALSE;
  1270. }
  1271. else if ( FAILED( sc ) )
  1272. {
  1273. ciDebugOut(( DEB_WARN, "GetData isindexed failed: 0x%x\n", sc ));
  1274. THROW( CException( sc ) );
  1275. }
  1276. }
  1277. }
  1278. CATCH( CException, e )
  1279. {
  1280. // ignore -- assume IsIndexed
  1281. }
  1282. END_CATCH;
  1283. return fIsIndexed;
  1284. } //IsIndexed
  1285. //+-------------------------------------------------------------------------
  1286. //
  1287. // Member: CMetaDataMgr::GetVPathFlags, public
  1288. //
  1289. // Synopsis: Returns flag settings on a virtual path
  1290. //
  1291. // Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
  1292. // [mdID] - MD_x constant for the data
  1293. // [ulDefault] - Default if no value is in the metabase
  1294. //
  1295. // History: 18-Aug-1997 dlee Created
  1296. //
  1297. //--------------------------------------------------------------------------
  1298. ULONG CMetaDataMgr::GetVPathFlags(
  1299. WCHAR const * pwcVPath,
  1300. ULONG mdID,
  1301. ULONG ulDefault )
  1302. {
  1303. unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
  1304. if ( cwc >= METADATA_MAX_NAME_LEN )
  1305. THROW( CException( E_INVALIDARG ) );
  1306. WCHAR awcCompletePath[ METADATA_MAX_NAME_LEN ];
  1307. wcscpy( awcCompletePath, _awcInstance );
  1308. wcscat( awcCompletePath, L"/Root" );
  1309. wcscat( awcCompletePath, pwcVPath );
  1310. DWORD dwFlags = ulDefault;
  1311. // Keep removing path components on the right of the path until
  1312. // either out of path or the metabase recognizes the path.
  1313. METADATA_HANDLE h;
  1314. do
  1315. {
  1316. SCODE sc = _xAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  1317. awcCompletePath,
  1318. METADATA_PERMISSION_READ,
  1319. cmsCIMetabaseTimeout,
  1320. &h );
  1321. if ( S_OK == sc )
  1322. {
  1323. break;
  1324. }
  1325. else if ( HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == sc )
  1326. {
  1327. WCHAR * pwc = wcsrchr( awcCompletePath, L'/' );
  1328. if ( 0 == pwc )
  1329. THROW( CException( sc ) );
  1330. *pwc = 0;
  1331. }
  1332. else
  1333. THROW( CException( sc ) );
  1334. } while ( TRUE );
  1335. CMetaDataHandle mdVRoot( _xAdminBase, h );
  1336. {
  1337. METADATA_RECORD mdr;
  1338. RtlZeroMemory( &mdr, sizeof mdr );
  1339. mdr.dwMDIdentifier = mdID;
  1340. mdr.dwMDAttributes = METADATA_INHERIT;
  1341. mdr.pbMDData = (BYTE *) &dwFlags;
  1342. mdr.dwMDDataLen = sizeof dwFlags;
  1343. DWORD cbRequired = 0;
  1344. SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
  1345. L"",
  1346. &mdr,
  1347. &cbRequired );
  1348. if ( MD_ERROR_DATA_NOT_FOUND == sc )
  1349. {
  1350. // no value specified for this flag; use default
  1351. dwFlags = ulDefault;
  1352. }
  1353. else if ( FAILED( sc ) )
  1354. {
  1355. ciDebugOut(( DEB_WARN, "GetData mdid %d failed: 0x%x on '%ws'\n",
  1356. mdID, sc, awcCompletePath ));
  1357. THROW( CException( sc ) );
  1358. }
  1359. }
  1360. return dwFlags;
  1361. } //GetVPathFlags
  1362. //+-------------------------------------------------------------------------
  1363. //
  1364. // Member: CMetaDataMgr::GetVPathAccess, public
  1365. //
  1366. // Synopsis: Returns access permission settings on a virtual path
  1367. //
  1368. // Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
  1369. //
  1370. // History: 18-Aug-1997 dlee Created
  1371. //
  1372. //--------------------------------------------------------------------------
  1373. ULONG CMetaDataMgr::GetVPathAccess(
  1374. WCHAR const * pwcVPath )
  1375. {
  1376. // note: the default of 0 is from IIS' metabase guru
  1377. return GetVPathFlags( pwcVPath, MD_ACCESS_PERM, 0 );
  1378. } //GetVPathAccess
  1379. //+-------------------------------------------------------------------------
  1380. //
  1381. // Member: CMetaDataMgr::GetVPathSSLAccess, public
  1382. //
  1383. // Synopsis: Returns SSL access permission settings on a virtual path
  1384. //
  1385. // Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
  1386. //
  1387. // History: 18-Aug-1997 dlee Created
  1388. //
  1389. //--------------------------------------------------------------------------
  1390. ULONG CMetaDataMgr::GetVPathSSLAccess(
  1391. WCHAR const * pwcVPath )
  1392. {
  1393. // note: the default of 0 is from IIS' metabase guru
  1394. return GetVPathFlags( pwcVPath, MD_SSL_ACCESS_PERM, 0 );
  1395. } //GetVPathSSLAccess
  1396. //+-------------------------------------------------------------------------
  1397. //
  1398. // Member: CMetaDataMgr::GetVPathAuthorization, public
  1399. //
  1400. // Synopsis: Returns authorization on a virtual path
  1401. //
  1402. // Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
  1403. //
  1404. // History: 18-Aug-1997 dlee Created
  1405. //
  1406. //--------------------------------------------------------------------------
  1407. ULONG CMetaDataMgr::GetVPathAuthorization(
  1408. WCHAR const * pwcVPath )
  1409. {
  1410. // note: the default of MD_AUTH_ANONYMOUS is from IIS' metabase guru
  1411. return GetVPathFlags( pwcVPath, MD_AUTHORIZATION, MD_AUTH_ANONYMOUS );
  1412. } //GetVPathAuthorization
  1413. //+-------------------------------------------------------------------------
  1414. //
  1415. // Member: CMetaDataComSink::SinkNotify, public
  1416. //
  1417. // Synopsis: Called for any metadata change
  1418. //
  1419. // Arguments: [cChanges] - # of changes in pcoChangeList
  1420. // [pcoChangeList] - list of changes
  1421. //
  1422. // History: 07-Feb-1997 dlee Created
  1423. //
  1424. //--------------------------------------------------------------------------
  1425. SCODE STDMETHODCALLTYPE CMetaDataComSink::SinkNotify(
  1426. DWORD cChanges,
  1427. MD_CHANGE_OBJECT pcoChangeList[] )
  1428. {
  1429. // This is called by an RPC worker thread -- assimilate it
  1430. TRANSLATE_EXCEPTIONS;
  1431. TRY
  1432. {
  1433. int cwcInstance = wcslen( _awcInstance );
  1434. BOOL fInterestingChange = FALSE;
  1435. ciDebugOut(( DEB_WARN, "iis sinknotify '%ws', cchanges: %d\n",
  1436. _awcInstance, cChanges ));
  1437. for ( DWORD i = 0; !fInterestingChange && i < cChanges; i++ )
  1438. {
  1439. MD_CHANGE_OBJECT & co = pcoChangeList[i];
  1440. // we only care about notifications to our instance
  1441. if ( _wcsnicmp( co.pszMDPath, _awcInstance, cwcInstance ) != 0 ||
  1442. ( L'/' != co.pszMDPath[cwcInstance] &&
  1443. L'\0' != co.pszMDPath[cwcInstance] ) )
  1444. continue;
  1445. // Ignore adds of vroots -- we'll get a set_data for its
  1446. // parameters and trigger on that.
  1447. if ( ( MD_CHANGE_TYPE_DELETE_OBJECT & co.dwMDChangeType ) ||
  1448. ( MD_CHANGE_TYPE_RENAME_OBJECT & co.dwMDChangeType ) )
  1449. {
  1450. // guess that the deletion was a vroot
  1451. fInterestingChange = TRUE;
  1452. }
  1453. else if ( ( MD_CHANGE_TYPE_SET_DATA & co.dwMDChangeType ) ||
  1454. ( MD_CHANGE_TYPE_DELETE_DATA & co.dwMDChangeType ) )
  1455. {
  1456. for ( DWORD x = 0; x < co.dwMDNumDataIDs; x++ )
  1457. {
  1458. DWORD id = co.pdwMDDataIDs[x];
  1459. if ( MD_VR_PATH == id ||
  1460. MD_VR_USERNAME == id ||
  1461. MD_VR_PASSWORD == id ||
  1462. MD_ACCESS_PERM == id ||
  1463. MD_IS_CONTENT_INDEXED == id )
  1464. {
  1465. fInterestingChange = TRUE;
  1466. break;
  1467. }
  1468. }
  1469. }
  1470. }
  1471. if ( fInterestingChange && ( 0 != _pCallBack ) )
  1472. _pCallBack->CallBack( FALSE );
  1473. }
  1474. CATCH (CException, e)
  1475. {
  1476. ciDebugOut(( DEB_WARN,
  1477. "SinkNotify caught 0x%x\n",
  1478. e.GetErrorCode() ));
  1479. }
  1480. END_CATCH
  1481. UNTRANSLATE_EXCEPTIONS;
  1482. return S_OK;
  1483. } //SinkNotify
  1484. //+-------------------------------------------------------------------------
  1485. //
  1486. // Member: CMetaDataComSink::ShutdownNotify, public
  1487. //
  1488. // Synopsis: Called when iisadmin is going down cleanly
  1489. //
  1490. // History: 07-Feb-1997 dlee Created
  1491. //
  1492. //--------------------------------------------------------------------------
  1493. SCODE STDMETHODCALLTYPE CMetaDataComSink::ShutdownNotify()
  1494. {
  1495. // This is called by an RPC worker thread -- assimilate it
  1496. TRANSLATE_EXCEPTIONS;
  1497. TRY
  1498. {
  1499. ciDebugOut(( DEB_WARN, "iis shutdownnotify '%ws'\n", _awcInstance ));
  1500. // in case we get more random notifications, ignore them
  1501. CMetaDataVPathChangeCallBack * pCallBack = _pCallBack;
  1502. _pCallBack = 0;
  1503. pCallBack->CallBack( TRUE );
  1504. }
  1505. CATCH (CException, e)
  1506. {
  1507. ciDebugOut(( DEB_WARN,
  1508. "ShutdownNotify caught 0x%x\n",
  1509. e.GetErrorCode() ));
  1510. }
  1511. END_CATCH
  1512. UNTRANSLATE_EXCEPTIONS;
  1513. return S_OK;
  1514. } //ShutdownNotify