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

614 lines
21 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1999.
  5. //
  6. // File: catreg.cxx
  7. //
  8. // Contents: Catalog registry helper classes
  9. //
  10. // History: 13-Dec-1996 dlee split from cicat.cxx
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <lm.h>
  16. #include <ciregkey.hxx>
  17. #include <regacc.hxx>
  18. #include <pathpars.hxx>
  19. #include <regscp.hxx>
  20. #include <cimbmgr.hxx>
  21. #include <lcase.hxx>
  22. #include "cicat.hxx"
  23. #include "cinulcat.hxx"
  24. #include "catreg.hxx"
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Member: CIISVirtualDirectories::CallBack, public
  28. //
  29. // Synopsis: Adds a virtual directory to the list
  30. //
  31. // Arguments: [pwcIISVPath] -- Virtual Root
  32. // [pwcIISPPath] -- Physical path of vroot
  33. // [fIsIndexed] -- TRUE if vroot should be indexed
  34. // [dwAccess] -- IIS access permissions
  35. // [pwcUser] -- Username for logons if pwcPRoot is a UNC
  36. // [pwcPassword] -- Password for logons if pwcPRoot is a UNC
  37. // [fIsAVRoot] -- TRUE if a vroot, FALSE if a vpath
  38. //
  39. // History: 2-Sep-97 dlee Created
  40. //
  41. //--------------------------------------------------------------------------
  42. SCODE CIISVirtualDirectories::CallBack(
  43. WCHAR const * pwcIISVPath,
  44. WCHAR const * pwcIISPPath,
  45. BOOL fIsIndexed,
  46. DWORD dwAccess,
  47. WCHAR const * pwcUser,
  48. WCHAR const * pwcPassword,
  49. BOOL fIsAVRoot )
  50. {
  51. ciDebugOut(( DEB_ITRACE, "CII::CB '%ws' '%ws', %d, %#x, %d\n",
  52. pwcIISVPath,
  53. pwcIISPPath,
  54. fIsIndexed,
  55. dwAccess,
  56. fIsAVRoot ));
  57. BOOL fReadable = ( 0 != ( dwAccess & MD_ACCESS_READ ) );
  58. //
  59. // Treat unreadable paths the same as nonindexed paths
  60. //
  61. if ( !fReadable )
  62. {
  63. fIsIndexed = FALSE;
  64. fReadable = TRUE;
  65. }
  66. //
  67. // Ignore vdirs that are indexed -- they are indexed by the vroot
  68. // under which they fall.
  69. //
  70. if ( !fIsAVRoot && fIsIndexed )
  71. return STATUS_SUCCESS;
  72. CLowcaseBuf lcPPath( pwcIISPPath );
  73. WCHAR * pwcPRoot = lcPPath.GetWriteable();
  74. unsigned cwcPRoot = lcPPath.Length();
  75. BOOL fValidPRoot = FALSE;
  76. if (cwcPRoot >= 3 &&
  77. pwcPRoot[1] == L':' &&
  78. pwcPRoot[2] == L'\\')
  79. {
  80. fValidPRoot = TRUE;
  81. }
  82. else if ( cwcPRoot == 2 &&
  83. pwcPRoot[1] == L':' )
  84. {
  85. // Treat this as the root of the drive. Append a backslash.
  86. pwcPRoot[2] = L'\\';
  87. cwcPRoot++;
  88. pwcPRoot[cwcPRoot] = 0;
  89. fValidPRoot = TRUE;
  90. }
  91. else if ( CiCat::IsUNCName( pwcPRoot ) )
  92. {
  93. fValidPRoot = TRUE;
  94. }
  95. //
  96. // This is probably obsolete in the metabase world:
  97. // Flip slashes. Believe it or not, Gibraltar allows physical paths to
  98. // have slashes in place of backslashes.
  99. //
  100. lcPPath.ForwardToBackSlash();
  101. //
  102. // Remove the trailing backslash if it exists
  103. //
  104. if ( cwcPRoot > 3 && L'\\' == pwcPRoot[ cwcPRoot - 1 ] )
  105. {
  106. cwcPRoot--;
  107. pwcPRoot[ cwcPRoot ] = 0;
  108. }
  109. //
  110. // Remember the root if it's valid
  111. //
  112. if ( fValidPRoot )
  113. {
  114. CLowcaseBuf lcVPath( pwcIISVPath );
  115. lcVPath.ForwardToBackSlash();
  116. WCHAR * pwcVRoot = lcVPath.GetWriteable();
  117. unsigned cwcVRoot = lcVPath.Length();
  118. XPtr<CIISVirtualDirectory> xvdir( new CIISVirtualDirectory( pwcVRoot,
  119. pwcPRoot,
  120. fIsIndexed,
  121. dwAccess,
  122. pwcUser,
  123. pwcPassword,
  124. fIsAVRoot ) );
  125. _aDirectories.Add( xvdir.GetPointer(), _aDirectories.Count() );
  126. _htDirectories.Add( xvdir.GetPointer() );
  127. xvdir.Acquire();
  128. }
  129. return S_OK;
  130. } //CallBack
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Member: CIISVirtualDirectories::Lookup, public
  134. //
  135. // Synopsis: Looks for a virtual directory exact match in the list
  136. //
  137. // Arguments: [pwcVPath] -- Virtual path
  138. // [cwcVPath] -- # characters in pwcVPath
  139. // [pwcPPath] -- Physical path
  140. // [cwcPPath] -- # characters in pwcPPath
  141. //
  142. // Returns: TRUE if a match was found.
  143. //
  144. // History: 2-Sep-97 dlee Created
  145. //
  146. //--------------------------------------------------------------------------
  147. BOOL CIISVirtualDirectories::Lookup(
  148. WCHAR const * pwcVPath,
  149. unsigned cwcVPath,
  150. WCHAR const * pwcPPath,
  151. unsigned cwcPPath )
  152. {
  153. CIISVirtualDirectory * pDir = _htDirectories.Lookup( pwcVPath );
  154. if ( 0 != pDir )
  155. {
  156. //
  157. // Physical paths don't have a terminating backslash. They
  158. // are stripped by the callback unless it's a drive root like x:\
  159. // OR for input pwcVPath a unc root like \\machine\share\
  160. //
  161. if ( ( cwcPPath > 3 ) &&
  162. ( L'\\' == pwcPPath[ cwcPPath - 1 ] ) )
  163. cwcPPath--;
  164. Win4Assert( 3 == cwcPPath ||
  165. L'\\' != pwcPPath[ cwcPPath - 1 ] );
  166. Win4Assert( 3 == pDir->PPathLen() ||
  167. L'\\' != pDir->PPath()[ pDir->PPathLen() - 1 ] );
  168. if ( cwcPPath == pDir->PPathLen() &&
  169. RtlEqualMemory( pwcPPath, pDir->PPath(), cwcPPath * sizeof WCHAR ) )
  170. return TRUE;
  171. }
  172. return FALSE;
  173. } //Lookup
  174. //+-------------------------------------------------------------------------
  175. //
  176. // Member: CIISVirtualDirectories::Enum, public
  177. //
  178. // Synopsis: Adds directories in the list to the catalog
  179. //
  180. // Arguments: [cicat] -- The catalog into which vdirs are added
  181. //
  182. // History: 2-Sep-97 dlee Created
  183. //
  184. //--------------------------------------------------------------------------
  185. void CIISVirtualDirectories::Enum( CiCat & cicat )
  186. {
  187. for ( unsigned i = 0; i < _aDirectories.Count(); i++ )
  188. {
  189. CIISVirtualDirectory & vdir = * _aDirectories[i];
  190. ciDebugOut(( DEB_WARN,
  191. "adding %s %s %ws %s '%ws', proot '%ws'\n",
  192. ( MD_ACCESS_READ & vdir.Access() ) ? "readable" : "unreadable",
  193. vdir.IsIndexed() ? "indexed" : "non-indexed",
  194. GetVRootService( _eType ),
  195. vdir.IsAVRoot() ? "vroot" : "vpath",
  196. vdir.VPath(),
  197. vdir.PPath() ));
  198. cicat.AddVirtualScope( vdir.VPath(),
  199. vdir.PPath(),
  200. TRUE,
  201. _eType,
  202. vdir.IsAVRoot(),
  203. vdir.IsIndexed() );
  204. }
  205. } //Enum
  206. //+-------------------------------------------------------------------------
  207. //
  208. // Member: CIISVirtualDirectories::Enum, public
  209. //
  210. // Synopsis: Enumerates the directory list into the callback
  211. //
  212. // Arguments: [callback] -- The callback for each directory
  213. //
  214. // History: 2-Sep-97 dlee Created
  215. //
  216. //--------------------------------------------------------------------------
  217. void CIISVirtualDirectories::Enum( CMetaDataCallBack & callback )
  218. {
  219. for ( unsigned i = 0; i < _aDirectories.Count(); i++ )
  220. {
  221. CIISVirtualDirectory & vdir = * _aDirectories[i];
  222. callback.CallBack( vdir.VPath(),
  223. vdir.PPath(),
  224. vdir.IsIndexed(),
  225. vdir.Access(),
  226. vdir.User(),
  227. vdir.Password(),
  228. vdir.IsAVRoot() );
  229. }
  230. } //Enum
  231. //+-------------------------------------------------------------------------
  232. //
  233. // Member: CIISVirtualDirectory::CIISVirtualDirectory, public
  234. //
  235. // Synopsis: Constructs a vdir object
  236. //
  237. // Arguments: [pwcVPath] -- The virtual path
  238. // [pwcPPath] -- The physical path
  239. // [fIsIndexed] -- TRUE if indexed
  240. // [dwAccess] -- access mask
  241. // [pwcUser] -- The domain\username
  242. // [pwcPassword] -- The password for logons
  243. // [fIsAVRoot] -- TRUE if a root, FALSE if a directory
  244. // [fIsIndexed] -- TRUE if indexed, FALSE otherwise
  245. //
  246. // History: 2-Sep-97 dlee Created
  247. //
  248. //--------------------------------------------------------------------------
  249. CIISVirtualDirectory::CIISVirtualDirectory(
  250. WCHAR const * pwcVPath,
  251. WCHAR const * pwcPPath,
  252. BOOL fIsIndexed,
  253. DWORD dwAccess,
  254. WCHAR const * pwcUser,
  255. WCHAR const * pwcPassword,
  256. BOOL fIsAVRoot ) :
  257. _fIsIndexed( fIsIndexed ),
  258. _dwAccess( dwAccess ),
  259. _fIsAVRoot( fIsAVRoot ),
  260. _pNext( 0 )
  261. {
  262. _cwcVPath = wcslen( pwcVPath );
  263. XArray<WCHAR> xVPath( _cwcVPath + 1 );
  264. RtlCopyMemory( xVPath.GetPointer(), pwcVPath, xVPath.SizeOf() );
  265. _xVPath.Set( xVPath.Acquire() );
  266. _cwcPPath = wcslen( pwcPPath );
  267. XArray<WCHAR> xPPath( _cwcPPath + 1 );
  268. RtlCopyMemory( xPPath.GetPointer(), pwcPPath, xPPath.SizeOf() );
  269. _xPPath.Set( xPPath.Acquire() );
  270. unsigned cwcUser = 1 + wcslen( pwcUser );
  271. XArray<WCHAR> xUser( cwcUser );
  272. RtlCopyMemory( xUser.GetPointer(), pwcUser, xUser.SizeOf() );
  273. _xUser.Set( xUser.Acquire() );
  274. unsigned cwcPassword = 1 + wcslen( pwcPassword );
  275. XArray<WCHAR> xPassword( cwcPassword );
  276. RtlCopyMemory( xPassword.GetPointer(), pwcPassword, xPassword.SizeOf() );
  277. _xPassword.Set( xPassword.Acquire() );
  278. } //CIISVirtualDirectory
  279. //+-------------------------------------------------------------------------
  280. //
  281. // Member: CRegistryScopesCallBackRemoveAlias::CRegistryScopesCallBackRemoveAlias, public
  282. //
  283. // Synopsis: Constructor
  284. //
  285. // Arguments: [Cat] -- Catalog
  286. // [dlNetApi32] -- Dynamically loaded NetApi32 (for performance)
  287. // [fRemoveAll] -- TRUE if *all* aliases should be deleted.
  288. //
  289. // History: 13-Jun-1998 KyleP Created
  290. //
  291. //--------------------------------------------------------------------------
  292. CRegistryScopesCallBackRemoveAlias::CRegistryScopesCallBackRemoveAlias( CiCat & Cat,
  293. CDynLoadNetApi32 & dlNetApi32,
  294. BOOL fRemoveAll )
  295. : _cicat( Cat ),
  296. _dlNetApi32( dlNetApi32 ),
  297. _fScopeRemoved( FALSE ),
  298. _fRemoveAll( fRemoveAll )
  299. {
  300. _ccCompName = sizeof(_wcsCompName)/sizeof(WCHAR);
  301. if ( !GetComputerName( &_wcsCompName[0], &_ccCompName ) )
  302. {
  303. ciDebugOut(( DEB_ERROR, "Error %u from GetComputerName\n", GetLastError() ));
  304. THROW( CException() );
  305. }
  306. } //CRegistryScopesCallBackRemoveAlias
  307. //+-------------------------------------------------------------------------
  308. //
  309. // Member: CRegistryScopesCallBackRemoveAlias::Callback
  310. //
  311. // Synopsis: Registry callback routine. Removes unneeded fixups.
  312. //
  313. // Arguments: [pValueName] -- Scope
  314. // [uValueType] -- REG_SZ
  315. // [pValueData] -- Fixup, flags, etc.
  316. // [uValueLength] -- Length
  317. //
  318. // History: 13-Jun-1998 KyleP Created
  319. //
  320. //--------------------------------------------------------------------------
  321. NTSTATUS CRegistryScopesCallBackRemoveAlias::CallBack( WCHAR *pValueName,
  322. ULONG uValueType,
  323. VOID *pValueData,
  324. ULONG uValueLength )
  325. {
  326. CParseRegistryScope parse( pValueName,
  327. uValueType,
  328. pValueData,
  329. uValueLength );
  330. if ( parse.IsShadowAlias() )
  331. {
  332. //
  333. // Does it still exist?
  334. //
  335. BYTE * pbShareInfo;
  336. DWORD dwError = _dlNetApi32.NetShareGetInfo( _wcsCompName, // Server
  337. (WCHAR *)parse.GetFixup() + _ccCompName + 3, // Share (un-const, ugh)
  338. 2, // Level 2
  339. &pbShareInfo ); // Result
  340. if ( _fRemoveAll || NO_ERROR != dwError )
  341. {
  342. //
  343. // Note that removing a share based on a bogus error code (out-of-memory, etc.)
  344. // is not too bad an error. The fixup will be readded later.
  345. //
  346. ciDebugOut(( DEB_ITRACE, "Removing alias %ws\n", parse.GetFixup() ));
  347. _cicat.GetScopeFixup()->Remove( parse.GetScope(), parse.GetFixup() );
  348. _cicat.DeleteIfShadowAlias( parse.GetScope(), parse.GetFixup() );
  349. //
  350. // Set flag. I'm not sure if we are guaranteed to examine everything after
  351. // a change has been made. We're modifying the scope we're iterating over.
  352. //
  353. _fScopeRemoved = TRUE;
  354. }
  355. else
  356. _dlNetApi32.NetApiBufferFree( pbShareInfo );
  357. }
  358. return STATUS_SUCCESS;
  359. } //CallBack
  360. //+-------------------------------------------------------------------------
  361. //
  362. // Member: CRegistryScopesCallBackAdd::Callback
  363. //
  364. // Synopsis: Registry callback routine. Adds scopes.
  365. //
  366. // Arguments: [pValueName] -- Scope
  367. // [uValueType] -- REG_SZ
  368. // [pValueData] -- Fixup, flags, etc.
  369. // [uValueLength] -- Length
  370. //
  371. // History: 13-Jun-1998 KyleP Moved to .cxx file
  372. //
  373. //--------------------------------------------------------------------------
  374. NTSTATUS CRegistryScopesCallBackAdd::CallBack( WCHAR *pValueName,
  375. ULONG uValueType,
  376. VOID *pValueData,
  377. ULONG uValueLength )
  378. {
  379. // if the value isn't a string, ignore it.
  380. if ( REG_SZ == uValueType )
  381. {
  382. ciDebugOut(( DEB_ITRACE, "callbackadd '%ws', '%ws'\n",
  383. pValueName, pValueData ));
  384. CParseRegistryScope parse( pValueName,
  385. uValueType,
  386. pValueData,
  387. uValueLength );
  388. if ( parse.IsShadowAlias() )
  389. _cicat.GetScopeFixup()->Add( parse.GetScope(), parse.GetFixup() );
  390. else if ( parse.IsPhysical() )
  391. {
  392. // update the list of ignored scopes; either add or remove path
  393. BOOL fChange = _cicat._scopesIgnored.Update( parse.GetScope(),
  394. parse.IsIndexed() );
  395. // Either add the scope or make sure it isn't in the list of
  396. // scopes being indexed.
  397. // If the scope is supposed to be indexed, only do a scan if
  398. // the state of indexing went from off to on.
  399. //
  400. // Only remove the scope if it used to be indexed, and now
  401. // its not or if this is startup.
  402. if ( parse.IsIndexed() )
  403. _cicat.ScanOrAddScope( parse.GetScope(),
  404. TRUE,
  405. UPD_INCREM,
  406. TRUE,
  407. fChange );
  408. else if ( fChange )
  409. _cicat.RemoveScopeFromCI( parse.GetScope(), TRUE );
  410. }
  411. if ( parse.IsPhysical() ||
  412. parse.IsVirtualPlaceholder() ||
  413. parse.IsShadowAlias() )
  414. {
  415. // add the fixup as well -- it may have changed
  416. if ( 0 != parse.GetFixup() )
  417. {
  418. ciDebugOut(( DEB_ITRACE,
  419. "callbackAdd '%ws', fixup as '%ws'\n",
  420. pValueName, parse.GetFixup() ));
  421. _cicat._scopeFixup.Add( parse.GetScope(), parse.GetFixup() );
  422. }
  423. }
  424. }
  425. return S_OK;
  426. } //CallBack
  427. //+-------------------------------------------------------------------------
  428. //
  429. // Member: CRegistryScopesCallBackFillUsnArray::Callback
  430. //
  431. // Synopsis: Registry callback routine. Popular the Usn volume array.
  432. //
  433. // Arguments: [pValueName] -- Scope
  434. // [uValueType] -- REG_SZ
  435. // [pValueData] -- Fixup, flags, etc.
  436. // [uValueLength] -- Length
  437. //
  438. // History: 23-Jun-1998 KitmanH created
  439. //
  440. //--------------------------------------------------------------------------
  441. NTSTATUS CRegistryScopesCallBackFillUsnArray::CallBack( WCHAR *pValueName,
  442. ULONG uValueType,
  443. VOID *pValueData,
  444. ULONG uValueLength )
  445. {
  446. // if the value isn't a string, ignore it.
  447. if ( REG_SZ == uValueType )
  448. {
  449. ciDebugOut(( DEB_ITRACE, "CallBackFillUsnArray '%ws', '%ws'\n",
  450. pValueName, pValueData ));
  451. WCHAR wcsPath[MAX_PATH+1];
  452. ULONG scopeLen = wcslen( pValueName );
  453. RtlCopyMemory( wcsPath, pValueName, (scopeLen+1) * sizeof(WCHAR) );
  454. TerminateWithBackSlash( wcsPath, scopeLen );
  455. CLowcaseBuf lcase( wcsPath );
  456. _cicat.VolumeSupportsUsns( lcase.Get()[0] );
  457. }
  458. return S_OK;
  459. } //CallBack
  460. //+-------------------------------------------------------------------------
  461. //
  462. // Member: CRegistryScopesCallBackToDismount::Callback
  463. //
  464. // Synopsis: Registry callback routine. Check if the catlog contains a
  465. // scope that resides on a volume to be dismounted.
  466. //
  467. // Arguments: [pValueName] -- Scope
  468. // [uValueType] -- REG_SZ
  469. // [pValueData] -- Fixup, flags, etc.
  470. // [uValueLength] -- Length
  471. //
  472. // History: 21-Jul-1998 KitmanH created
  473. //
  474. //--------------------------------------------------------------------------
  475. NTSTATUS CRegistryScopesCallBackToDismount::CallBack( WCHAR *pValueName,
  476. ULONG uValueType,
  477. VOID *pValueData,
  478. ULONG uValueLength )
  479. {
  480. // if the value isn't a string, ignore it.
  481. if ( REG_SZ == uValueType )
  482. {
  483. ciDebugOut(( DEB_ITRACE, "CallBackToDismount: scope '%ws' for volume %wc\n",
  484. pValueName, _wcVol ));
  485. if ( toupper(pValueName[0]) == toupper(_wcVol) )
  486. {
  487. _fWasFound = TRUE;
  488. ciDebugOut(( DEB_ITRACE, "CRegistryScopesCallBackToDismount: FOUND\n" ));
  489. }
  490. }
  491. return S_OK;
  492. } //CallBack
  493. //+-------------------------------------------------------------------------
  494. //
  495. // Member: CRegistryScopesCallBackAddDrvNotif::Callback
  496. //
  497. // Synopsis: Registry callback routine. Register the scopes for drive
  498. // notification
  499. //
  500. // Arguments: [pValueName] -- Scope
  501. // [uValueType] -- REG_SZ
  502. // [pValueData] -- Fixup, flags, etc.
  503. // [uValueLength] -- Length
  504. //
  505. // History: 19-Aug-1998 KitmanH created
  506. //
  507. //--------------------------------------------------------------------------
  508. NTSTATUS CRegistryScopesCallBackAddDrvNotif::CallBack( WCHAR *pValueName,
  509. ULONG uValueType,
  510. VOID *pValueData,
  511. ULONG uValueLength )
  512. {
  513. // if the value isn't a string, ignore it.
  514. if ( REG_SZ == uValueType )
  515. {
  516. ciDebugOut(( DEB_ITRACE, "CallBackAddDrvNotif for scope '%ws'\n", pValueName ));
  517. if ( L'\\' != pValueName[0] )
  518. _pNotifArray->AddDriveNotification( pValueName[0] );
  519. }
  520. return S_OK;
  521. } //CallBack