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.

1640 lines
46 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1998.
  5. //
  6. // File: imprsnat.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 2-16-96 srikants Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include <imprsnat.hxx>
  20. #include <pathpars.hxx>
  21. #include <smatch.hxx>
  22. #include <regacc.hxx>
  23. #include <regevent.hxx>
  24. #include <regscp.hxx>
  25. #include <ciregkey.hxx>
  26. #include <cievtmsg.h>
  27. #include <eventlog.hxx>
  28. #include <cimbmgr.hxx>
  29. #include <lcase.hxx>
  30. #include "cicat.hxx"
  31. #include "catreg.hxx"
  32. // List of logon information, shared between catalogs to help reduce
  33. // the problem of running out of logon instances.
  34. CLogonInfoList g_LogonList;
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Member: CLogonInfoList::Empty
  38. //
  39. // Synopsis: Empties the logon list
  40. //
  41. // History: 2-19-96 srikants Created
  42. //
  43. //----------------------------------------------------------------------------
  44. void CLogonInfoList::Empty()
  45. {
  46. for ( CLogonInfo * pLogonInfo = g_LogonList.Pop();
  47. 0 != pLogonInfo;
  48. pLogonInfo = g_LogonList.Pop() )
  49. {
  50. pLogonInfo->Close();
  51. delete pLogonInfo;
  52. }
  53. } //Empty
  54. //+---------------------------------------------------------------------------
  55. //
  56. // Function: AllocAndCopy
  57. //
  58. // Synopsis: A helper function to allocate and copy the source string into
  59. // a destination string.
  60. //
  61. // Arguments: [pSrc] -
  62. // [cc] -
  63. //
  64. // Returns:
  65. //
  66. // History: 4-08-96 srikants Created
  67. //
  68. //----------------------------------------------------------------------------
  69. WCHAR * CLogonInfo::AllocAndCopy( const WCHAR * pSrc, ULONG & cc )
  70. {
  71. WCHAR * pDst = 0;
  72. if ( 0 != pSrc )
  73. {
  74. cc = wcslen( pSrc );
  75. pDst = new WCHAR [cc+1];
  76. RtlCopyMemory( pDst, pSrc, (cc+1)*sizeof(WCHAR) );
  77. }
  78. else
  79. {
  80. cc = 0;
  81. }
  82. return pDst;
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Member: CLogonInfo::Logon
  87. //
  88. // Synopsis: Logon the given user with the given password.
  89. //
  90. // Arguments: [pwszUser] - User name
  91. // [pwszDomain] - Domain name
  92. // [pwszPassword] - Password (in clear text) to use.
  93. //
  94. // Returns: Status of the operation.
  95. //
  96. // History: 4-02-96 srikants Created
  97. //
  98. //----------------------------------------------------------------------------
  99. DWORD CLogonInfo::Logon( WCHAR const * pwszUser,
  100. WCHAR const * pwszDomain,
  101. WCHAR const * pwszPassword )
  102. {
  103. Win4Assert( 0 == _pwszUser );
  104. Win4Assert( 0 == _pwszDomain );
  105. Win4Assert( 0 == _pwszPassword );
  106. _pwszUser = AllocAndCopy( pwszUser, _ccUser );
  107. _pwszDomain = AllocAndCopy( pwszDomain, _ccDomain );
  108. _pwszPassword = AllocAndCopy( pwszPassword, _ccPassword );
  109. Win4Assert( INVALID_HANDLE_VALUE == _hToken );
  110. DWORD dwError = 0;
  111. if ( !LogonUser( _pwszUser, _pwszDomain, _pwszPassword,
  112. LOGON32_LOGON_INTERACTIVE, //LOGON32_LOGON_NETWORK
  113. LOGON32_PROVIDER_DEFAULT,
  114. &_hToken
  115. ) )
  116. {
  117. dwError = GetLastError();
  118. ciDebugOut(( DEB_ERROR, "Failure to logon user (%ws) domain (%ws). Error 0x%X\n",
  119. pwszUser, pwszDomain, dwError ));
  120. _hToken = INVALID_HANDLE_VALUE;
  121. }
  122. return dwError;
  123. } //Logon
  124. //+---------------------------------------------------------------------------
  125. //
  126. // Member: CLogonInfo::~CLogonInfo
  127. //
  128. // Synopsis: Frees up memory and closes the logon token.
  129. //
  130. // History: 4-05-96 srikants Created
  131. //
  132. //----------------------------------------------------------------------------
  133. CLogonInfo::~CLogonInfo()
  134. {
  135. Win4Assert( IsSingle() ); // must not be on the list
  136. delete [] _pwszUser;
  137. delete [] _pwszDomain;
  138. delete [] _pwszPassword;
  139. if ( INVALID_HANDLE_VALUE != _hToken )
  140. CloseHandle( _hToken );
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Member: CLogonInfo::IsSameUser
  145. //
  146. // Synopsis: Tests if the given user and domain match what is stored in
  147. // this object.
  148. //
  149. // Arguments: [pwszUser] - Name of the user
  150. // [pwszDomain] - Name of the domain
  151. //
  152. // Returns: TRUE if same; FALSE o/w
  153. //
  154. // History: 4-05-96 srikants Created
  155. //
  156. //----------------------------------------------------------------------------
  157. BOOL CLogonInfo::IsSameUser( WCHAR const * pwszUser, WCHAR const * pwszDomain ) const
  158. {
  159. ULONG ccUser = pwszUser ? wcslen(pwszUser) : 0;
  160. ULONG ccDomain = pwszDomain ? wcslen(pwszDomain) : 0;
  161. if ( ccUser == _ccUser && ccDomain == _ccDomain )
  162. {
  163. if ( ccUser != 0 && _wcsicmp( pwszUser, _pwszUser ) != 0 )
  164. return FALSE;
  165. if ( ccDomain != 0 && _wcsicmp( pwszDomain, _pwszDomain) != 0 )
  166. return FALSE;
  167. return TRUE;
  168. }
  169. else
  170. return FALSE;
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Member: CLogonInfo::IsSamePassword
  175. //
  176. // Synopsis: Tests if the given password is same as the one stored in this.
  177. //
  178. // Arguments: [pwszPassword] - Password to compare.
  179. //
  180. // Returns: TRUE if passwords match; FALSE o/w
  181. //
  182. // History: 4-05-96 srikants Created
  183. //
  184. // Notes:
  185. //
  186. //----------------------------------------------------------------------------
  187. BOOL CLogonInfo::IsSamePassword( WCHAR const * pwszPassword ) const
  188. {
  189. ULONG ccPassword = pwszPassword ? wcslen(pwszPassword) : 0;
  190. if ( ccPassword == _ccPassword )
  191. {
  192. return RtlEqualMemory( pwszPassword, _pwszPassword,
  193. _ccPassword*sizeof(WCHAR) );
  194. }
  195. return FALSE;
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Function: IpAddressFromWStr
  200. //
  201. // Synopsis: Given an ip address in the form of a.b.c.d, it is converted
  202. // into a ULONG and returned
  203. //
  204. // Arguments: [pwszAddress] -
  205. //
  206. // History: 7-12-96 srikants Created
  207. //
  208. //----------------------------------------------------------------------------
  209. ULONG CPhyDirLogonInfo::IpAddressFromWStr( WCHAR const * pwszAddress )
  210. {
  211. if ( 0 == pwszAddress )
  212. return CI_DEFAULT_IP_ADDRESS;
  213. ULONG ipAddress = 0;
  214. WCHAR const * pwszStart = pwszAddress;
  215. WCHAR wszField[4];
  216. for ( unsigned cTok = 0; (cTok < 4) && pwszStart[0]; cTok++ )
  217. {
  218. WCHAR const * pwszEnd = wcschr( pwszStart, L'.' );
  219. if ( 0 == pwszEnd )
  220. pwszEnd = pwszStart + wcslen( pwszStart );
  221. ULONG cwc = (ULONG)(pwszEnd - pwszStart);
  222. if ( cwc > 3 ) // max is 255
  223. {
  224. ciDebugOut(( DEB_ERROR, "Bad IP Address %ws\n", pwszAddress ));
  225. return CI_DEFAULT_IP_ADDRESS;
  226. }
  227. RtlCopyMemory( wszField, pwszStart, cwc * sizeof(WCHAR) );
  228. wszField[cwc] = 0;
  229. ULONG lField = (ULONG) _wtol( wszField );
  230. ipAddress <<= 8; // left shift by 8 bits and or in the new ones
  231. ipAddress |= (lField & 0xFF);
  232. if ( 0 != pwszEnd[0] )
  233. pwszStart = pwszEnd+1;
  234. else pwszStart = pwszEnd;
  235. }
  236. if ( cTok == 4 && pwszStart[0] == 0 )
  237. return ipAddress;
  238. else return CI_DEFAULT_IP_ADDRESS;
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Member: CPhyDirLogonInfo::CPhyDirLogonInfo
  243. //
  244. // Synopsis: Constructor for the object that keeps logon information for a
  245. // specific physical directory
  246. //
  247. // Arguments: [pwszPhyDirName] - Name of the physical directory (remote)
  248. //
  249. // History: 4-02-96 srikants Created
  250. //
  251. //----------------------------------------------------------------------------
  252. CPhyDirLogonInfo::CPhyDirLogonInfo( CImpersonationTokenCache & cache,
  253. CImprsObjInfo const & obj,
  254. CLogonInfo * pLogonInfo )
  255. : _cache( cache ),
  256. _pwszDirName(0),
  257. _pwszVirtualRoot(0),
  258. _ccVirtual(0)
  259. {
  260. Win4Assert( 0 != obj.GetPhysicalPath() );
  261. CDoubleLink::Close();
  262. _fIsZombie = FALSE;
  263. _cRef = 0;
  264. //
  265. // Create a local copy of the physical directory, virtual root and
  266. // save the logon information.
  267. //
  268. _pwszDirName = CLogonInfo::AllocAndCopy( obj.GetPhysicalPath(), _cc );
  269. _phyScope.Init( _pwszDirName, _cc );
  270. if ( 0 != obj.GetVPath() )
  271. {
  272. _pwszVirtualRoot = CLogonInfo::AllocAndCopy( obj.GetVPath(), _ccVirtual );
  273. _virtualScope.Init( _pwszVirtualRoot, _ccVirtual );
  274. }
  275. _pLogonInfo = pLogonInfo;
  276. if ( 0 != _pLogonInfo )
  277. _pLogonInfo->Addref();
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Member: CPhyDirLogonInfo::~CPhyDirLogonInfo
  282. //
  283. // Synopsis: Free up the memory and release the logon info.
  284. //
  285. // History: 4-02-96 srikants Created
  286. //
  287. //----------------------------------------------------------------------------
  288. CPhyDirLogonInfo::~CPhyDirLogonInfo()
  289. {
  290. Win4Assert( IsSingle() ); // must not be on the list
  291. delete [] _pwszDirName;
  292. delete [] _pwszVirtualRoot;
  293. if ( 0 != _pLogonInfo )
  294. {
  295. _cache.Release( _pLogonInfo );
  296. }
  297. }
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Member: CImpersonationTokenCache::CImpersonationTokenCache
  301. //
  302. // Synopsis: Constructor of the impersonation token cache.
  303. //
  304. // History: 4-02-96 srikants Created
  305. //
  306. //----------------------------------------------------------------------------
  307. CImpersonationTokenCache::CImpersonationTokenCache(
  308. WCHAR const * pwcCatName )
  309. : _fIndexW3Roots(FALSE),
  310. _fIndexNNTPRoots(FALSE),
  311. _fIndexIMAPRoots(FALSE),
  312. _W3SvcInstance(1),
  313. _NNTPSvcInstance(1),
  314. _IMAPSvcInstance(1),
  315. _fRemoteSharesPresent(FALSE),
  316. _pwszComponentName(0)
  317. {
  318. if ( 0 != pwcCatName )
  319. wcscpy( _awcCatalogName, pwcCatName );
  320. else
  321. _awcCatalogName[0] = 0;
  322. for ( unsigned i = 0; i < CI_MAX_DRIVES;i++ )
  323. _aDriveInfo[i] = eUnknown;
  324. }
  325. //+---------------------------------------------------------------------------
  326. //
  327. // Member: CImpersonationTokenCache::~CImpersonationTokenCache
  328. //
  329. // Synopsis: Release the cached information.
  330. //
  331. // History: 4-02-96 srikants Created
  332. //
  333. //----------------------------------------------------------------------------
  334. CImpersonationTokenCache::~CImpersonationTokenCache()
  335. {
  336. // Release the physical directory list elements
  337. for ( CPhyDirLogonInfo * pDirInfo = _phyDirList.Pop(); 0 != pDirInfo;
  338. pDirInfo = _phyDirList.Pop() )
  339. {
  340. pDirInfo->Close();
  341. delete pDirInfo;
  342. }
  343. delete [] _pwszComponentName;
  344. }
  345. //+---------------------------------------------------------------------------
  346. //
  347. // Member: CImpersonationTokenCache::Find
  348. //
  349. // Synopsis: Locate impersonation information for the given path.
  350. //
  351. // Arguments: [pwszPath] - Path for which impersonation information is
  352. // needed.
  353. //
  354. // Returns: A pointer to the impersonation if lookup is successful.
  355. // NULL otherwise. The returned CPhyDirLogonInfo is AddRefed().
  356. //
  357. // History: 4-02-96 srikants Created
  358. //
  359. // It is assumed that pwszPath is all Lower case.
  360. //
  361. //----------------------------------------------------------------------------
  362. CPhyDirLogonInfo *
  363. CImpersonationTokenCache::Find( WCHAR const * pwszPath, ULONG len )
  364. {
  365. CPhyDirLogonInfo * pDirInfo = 0;
  366. // ====================================================
  367. CLock lock(_mutex);
  368. //
  369. // Try to locate the path in the list
  370. //
  371. for ( CFwdPhyDirLogonIter iter(_phyDirList); !_phyDirList.AtEnd(iter);
  372. _phyDirList.Advance(iter) )
  373. {
  374. if ( iter->IsInScope( pwszPath, len ) )
  375. {
  376. pDirInfo = iter.GetEntry();
  377. break;
  378. }
  379. }
  380. if ( pDirInfo )
  381. {
  382. pDirInfo->AddRef();
  383. }
  384. // ====================================================
  385. return pDirInfo;
  386. }
  387. //+---------------------------------------------------------------------------
  388. //
  389. // Member: CImpersonationTokenCache::Find
  390. //
  391. // Synopsis: Finds a directory logon info for the given object after skipping
  392. // over the specified matched entries.
  393. //
  394. // Arguments: [info] - Information about the VPath and PhysPath and ip
  395. // address.
  396. // [cSkip] - Number of matching entries to skip
  397. //
  398. // Returns:
  399. //
  400. // Modifies:
  401. //
  402. // History: 7-12-96 srikants Created
  403. //
  404. // Notes:
  405. //
  406. //----------------------------------------------------------------------------
  407. CPhyDirLogonInfo *
  408. CImpersonationTokenCache::Find( CImprsObjInfo & info, ULONG cSkip )
  409. {
  410. CPhyDirLogonInfo * pDirInfo = 0;
  411. ULONG cSkipped = 0;
  412. // ====================================================
  413. CLock lock(_mutex);
  414. //
  415. // Try to locate the path in the list
  416. //
  417. for ( CFwdPhyDirLogonIter iter(_phyDirList); !_phyDirList.AtEnd(iter);
  418. _phyDirList.Advance(iter) )
  419. {
  420. if ( iter->IsMatch( info ) )
  421. {
  422. if ( cSkipped == cSkip )
  423. {
  424. pDirInfo = iter.GetEntry();
  425. break;
  426. }
  427. cSkipped++;
  428. }
  429. }
  430. if ( pDirInfo )
  431. {
  432. pDirInfo->AddRef();
  433. }
  434. // ====================================================
  435. return pDirInfo;
  436. }
  437. CPhyDirLogonInfo *
  438. CImpersonationTokenCache::_FindExact( CImprsObjInfo const & info )
  439. {
  440. CPhyDirLogonInfo * pDirInfo = 0;
  441. // ====================================================
  442. CLock lock(_mutex);
  443. //
  444. // Try to locate the path in the list
  445. //
  446. for ( CFwdPhyDirLogonIter iter(_phyDirList); !_phyDirList.AtEnd(iter);
  447. _phyDirList.Advance(iter) )
  448. {
  449. if ( iter->IsSame( info ) )
  450. {
  451. pDirInfo = iter.GetEntry();
  452. break;
  453. }
  454. }
  455. if ( pDirInfo )
  456. {
  457. pDirInfo->AddRef();
  458. }
  459. // ====================================================
  460. return pDirInfo;
  461. }
  462. //+---------------------------------------------------------------------------
  463. //
  464. // Member: CImpersonationTokenCache::_LokFindLogonEntry
  465. //
  466. // Synopsis: Looks up a logon entry for the given name and domain.
  467. //
  468. // Arguments: [pwszUser] -
  469. // [pwszDomain] -
  470. //
  471. // Returns:
  472. //
  473. // History: 4-05-96 srikants Created
  474. //
  475. //----------------------------------------------------------------------------
  476. CLogonInfo *
  477. CImpersonationTokenCache::_LokFindLogonEntry( WCHAR const * pwszUser,
  478. WCHAR const * pwszDomain )
  479. {
  480. for ( CFwdLogonInfoIter iter(g_LogonList); !g_LogonList.AtEnd(iter);
  481. g_LogonList.Advance(iter) )
  482. {
  483. if ( iter->IsSameUser( pwszUser, pwszDomain ) )
  484. return iter.GetEntry();
  485. }
  486. return 0;
  487. }
  488. //+---------------------------------------------------------------------------
  489. //
  490. // Class: CParseAccount
  491. //
  492. // Purpose: A class to parse account of the form domain\username
  493. //
  494. // History: 4-05-96 srikants Created
  495. //
  496. // Notes:
  497. //
  498. //----------------------------------------------------------------------------
  499. class CParseAccount
  500. {
  501. enum { MAX_USER = UNLEN, MAX_DOMAIN = 100 };
  502. public:
  503. CParseAccount( WCHAR const * pwszAccount );
  504. WCHAR const * GetUserName() const { return _wszUser; }
  505. WCHAR const * GetDomainName() const { return _wszDomain; }
  506. WCHAR * GetUserName() { return _wszUser; }
  507. WCHAR * GetDomainName() { return _wszDomain; }
  508. private:
  509. WCHAR _wszUser[MAX_USER];
  510. WCHAR _wszDomain[MAX_DOMAIN];
  511. };
  512. //+---------------------------------------------------------------------------
  513. //
  514. // Member: CParseAccount::CParseAccount
  515. //
  516. // Synopsis: Parses a string of form domain\username into domain and
  517. // username.
  518. //
  519. // Arguments: [pwszAccount] -
  520. //
  521. // History: 4-03-96 srikants Created
  522. //
  523. //----------------------------------------------------------------------------
  524. CParseAccount::CParseAccount( WCHAR const * pwszAccount )
  525. {
  526. _wszUser[0] = _wszDomain[0] = 0;
  527. if ( pwszAccount )
  528. {
  529. int len = wcslen(pwszAccount);
  530. //
  531. // Separate the domain\user into domain and user
  532. //
  533. for ( int i = len-1; i >= 0; i-- )
  534. {
  535. if ( L'\\' == pwszAccount[i] )
  536. break;
  537. }
  538. if ( i < 0 )
  539. {
  540. //
  541. // See if there is a forward slash. Some mistaken users specify the
  542. // userid like that.
  543. //
  544. for ( i = len-1; i >= 0; i-- )
  545. {
  546. if ( L'/' == pwszAccount[i] )
  547. break;
  548. }
  549. }
  550. if ( i > 0 )
  551. {
  552. //
  553. // Copy the domain name
  554. //
  555. RtlCopyMemory( _wszDomain, pwszAccount, i * sizeof(WCHAR) );
  556. _wszDomain[i] = 0;
  557. //
  558. // Copy the user name.
  559. //
  560. RtlCopyMemory( _wszUser, pwszAccount+i+1, (len-i-1)*sizeof(WCHAR) );
  561. _wszUser[len-i-1] = 0;
  562. }
  563. else
  564. {
  565. //
  566. // No backslash was specified. The entire id is the username and
  567. // domain is NULL.
  568. //
  569. RtlCopyMemory( _wszUser, pwszAccount, len*sizeof(WCHAR) );
  570. _wszUser[len] = 0;
  571. }
  572. }
  573. } //CParseAccount
  574. //+---------------------------------------------------------------------------
  575. //
  576. // Member: CImpersonationTokenCache::_LokAddDirEntry
  577. //
  578. // Synopsis: Adds a new entry to the cache for the given account name.
  579. //
  580. // Arguments: [obj] - The impersonation object info
  581. // [pwszAccount] - Name of the account to use for logging on.
  582. //
  583. // History: 4-03-96 srikants Created
  584. //
  585. //----------------------------------------------------------------------------
  586. void CImpersonationTokenCache::_LokAddDirEntry( CImprsObjInfo const & obj,
  587. WCHAR const * pwszAccount )
  588. {
  589. //
  590. // Parse the account name into username and domain.
  591. //
  592. CParseAccount parse( pwszAccount );
  593. _fRemoteSharesPresent = TRUE;
  594. //
  595. // Look up the logon entry.
  596. //
  597. CLogonInfo * pLogonInfo = _LokFindLogonEntry( parse.GetUserName(),
  598. parse.GetDomainName() );
  599. //
  600. // Create the dir entry and add it to the list of physical directories.
  601. //
  602. CPhyDirLogonInfo * pDirInfo = new CPhyDirLogonInfo( *this,
  603. obj,
  604. pLogonInfo );
  605. _phyDirList.Queue( pDirInfo );
  606. } //_LokAddDirEntry
  607. //+---------------------------------------------------------------------------
  608. //
  609. // Member: CImpersonationTokenCache::IsNetworkDrive
  610. //
  611. // Synopsis: Given a drive, check if it is a network drive.
  612. //
  613. // Arguments: [pwszPath] - Path to check.
  614. //
  615. // Returns: TRUE if it is a network drive. FALSE o/w
  616. //
  617. // History: 4-02-96 srikants Created
  618. //
  619. //----------------------------------------------------------------------------
  620. BOOL CImpersonationTokenCache::IsNetworkDrive( WCHAR const * pwszPath )
  621. {
  622. CPathParser parser( pwszPath );
  623. if ( parser.IsUNCName() )
  624. return TRUE;
  625. if ( parser.IsDrivePath() )
  626. {
  627. WCHAR wDriveLetter = pwszPath[0];
  628. unsigned iDrive = _GetDriveIndex( wDriveLetter );
  629. // ====================================================
  630. CLock lock(_mutex);
  631. if ( eUnknown == _aDriveInfo[iDrive] )
  632. {
  633. UINT uType = GetDriveType( pwszPath );
  634. if ( DRIVE_REMOTE == uType )
  635. _aDriveInfo[iDrive] = eRemote;
  636. else
  637. _aDriveInfo[iDrive] = eLocal;
  638. }
  639. return eRemote == _aDriveInfo[iDrive];
  640. // ====================================================
  641. }
  642. else
  643. {
  644. //
  645. // If it is neither a UNC nor a drive letter, it is probably
  646. // a relative name.
  647. //
  648. return FALSE;
  649. }
  650. } //IsNetworkDrive
  651. //+---------------------------------------------------------------------------
  652. //
  653. // Member: CImpersonationTokenCache::_LokValidateOrAddDirEntry
  654. //
  655. // Synopsis: Validates the given path and account. If there is no entry for
  656. // the given path, a new one is added. If the current entry does
  657. // not match the given account info, the current one is zombified
  658. // and a new entry added.
  659. //
  660. // Arguments: [pwszPhyPath] - Physical path
  661. // [pwszAccount] - Account to use for accessing the physical path.
  662. //
  663. // History: 4-05-96 srikants Created
  664. //
  665. //----------------------------------------------------------------------------
  666. void
  667. CImpersonationTokenCache::_LokValidateOrAddDirEntry( CImprsObjInfo const & obj,
  668. WCHAR const * pwszAccount )
  669. {
  670. CPhyDirLogonInfo * pDirInfo = _FindExact( obj );
  671. if ( pDirInfo )
  672. {
  673. CParseAccount account( pwszAccount );
  674. CLogonInfo * pLogonInfo = _LokFindLogonEntry( account.GetUserName(),
  675. account.GetDomainName() );
  676. if ( pLogonInfo == pDirInfo->GetLogonInfo() )
  677. {
  678. // There is no change in logon information.
  679. Win4Assert( !pLogonInfo || !pLogonInfo->IsZombie() );
  680. Release(pDirInfo);
  681. return;
  682. }
  683. //
  684. // The logon information has changed for this directory.
  685. // So, we must zombify the current entry and create a new one.
  686. //
  687. _phyDirList.RemoveFromList( pDirInfo );
  688. pDirInfo->Close();
  689. pDirInfo->Zombify();
  690. Release( pDirInfo );
  691. pDirInfo = 0;
  692. }
  693. Win4Assert( 0 == pDirInfo );
  694. _LokAddDirEntry( obj, pwszAccount );
  695. } //_LokValidateOrAddDirEntry
  696. //+---------------------------------------------------------------------------
  697. //
  698. // Member: CImpersonationTokenCache::_LokValidateOrAddLogonEntry
  699. //
  700. // Synopsis: Validate the logon entry. If there is no logon entry for
  701. // the given account, add a new one. If the current one does not
  702. // match the given one, zombify the current one and replace it
  703. // with the new information.
  704. //
  705. // Arguments: [pwszUser] - Username of the account
  706. // [pwszDomain] - Domain of the account
  707. // [pwszPassword] - Password to use for logging this account/
  708. //
  709. // History: 4-05-96 srikants Created
  710. //
  711. //----------------------------------------------------------------------------
  712. DWORD
  713. CImpersonationTokenCache::_LokValidateOrAddLogonEntry(
  714. WCHAR const * pwszUser,
  715. WCHAR const * pwszDomain,
  716. WCHAR const * pwszPassword )
  717. {
  718. CLogonInfo * pLogonInfo = _LokFindLogonEntry( pwszUser, pwszDomain );
  719. if ( pLogonInfo )
  720. {
  721. if ( pLogonInfo->IsSamePassword( pwszPassword ) )
  722. return NO_ERROR;
  723. //
  724. // Invalidate the logon information.
  725. //
  726. g_LogonList.RemoveFromList( pLogonInfo );
  727. pLogonInfo->Close();
  728. pLogonInfo->Zombify();
  729. pLogonInfo->Addref();
  730. Release( pLogonInfo );
  731. pLogonInfo = 0;
  732. }
  733. Win4Assert( 0 == pLogonInfo );
  734. //
  735. // Create a new logon entry for the user and password.
  736. //
  737. pLogonInfo = new CLogonInfo;
  738. XPtr<CLogonInfo> xLogonInfo(pLogonInfo);
  739. DWORD status = pLogonInfo->Logon( pwszUser, pwszDomain, pwszPassword );
  740. if ( 0 == status )
  741. {
  742. xLogonInfo.Acquire();
  743. g_LogonList.Push( pLogonInfo );
  744. }
  745. return status;
  746. } //_LokValidateOrAddLogonEntry
  747. //+---------------------------------------------------------------------------
  748. //
  749. // Class: CIISCallBackImp
  750. //
  751. // Purpose: Callback to parse IIS scopes and save impersonation
  752. // information for each.
  753. //
  754. // History: 30-Oct-96 dlee created
  755. //
  756. //----------------------------------------------------------------------------
  757. class CIISCallBackImp : public CMetaDataCallBack
  758. {
  759. public:
  760. CIISCallBackImp( CImpersonationTokenCache & cache ) :
  761. _cache( cache )
  762. {
  763. }
  764. SCODE CallBack( WCHAR const * pwcVPath,
  765. WCHAR const * pwcPPath,
  766. BOOL fIsIndexed,
  767. DWORD dwAccess,
  768. WCHAR const * pwcUser,
  769. WCHAR const * pwcPassword,
  770. BOOL fIsAVRoot )
  771. {
  772. ciDebugOut(( DEB_ITRACE,
  773. "CIISCallBackImp checking c '%ws', vp '%ws', pp '%ws' i %d, u '%ws' pw '%ws', isavroot: %d\n",
  774. _cache.GetCatalog(),
  775. pwcVPath,
  776. pwcPPath,
  777. fIsIndexed,
  778. pwcUser,
  779. pwcPassword,
  780. fIsAVRoot ));
  781. // If there's a vroot scope on a remote drive, a username, and a
  782. // password, save the token info.
  783. if ( ( fIsAVRoot ) &&
  784. ( fIsIndexed ) &&
  785. ( _cache.IsNetworkDrive( pwcPPath ) ) &&
  786. ( 0 != pwcUser[0] ) )
  787. {
  788. ciDebugOut(( DEB_ITRACE, "CIISCallBackImp adding\n" ));
  789. {
  790. CParseAccount parser( pwcUser );
  791. DWORD status = _cache._LokValidateOrAddLogonEntry(
  792. parser.GetUserName(),
  793. parser.GetDomainName(),
  794. pwcPassword );
  795. if ( NO_ERROR != status )
  796. _cache._WriteLogonFailure( pwcUser, status );
  797. }
  798. {
  799. // normalize both the physical and virtual paths
  800. // to lowercase
  801. CLowcaseBuf lcasePhyDir( pwcPPath );
  802. lcasePhyDir.AppendBackSlash();
  803. // vpaths in ci always have backslashes, not slashes
  804. unsigned cwc = wcslen( pwcVPath );
  805. if ( cwc >= MAX_PATH )
  806. return S_OK;
  807. WCHAR awcVPath[ MAX_PATH ];
  808. for ( unsigned x = 0; x <= cwc; x++ )
  809. {
  810. if ( L'/' == pwcVPath[x] )
  811. awcVPath[ x ] = L'\\';
  812. else
  813. awcVPath[ x ] = pwcVPath[ x ];
  814. }
  815. CLowcaseBuf lcaseVPath( awcVPath );
  816. CImprsObjInfo info( lcasePhyDir.Get(),
  817. lcaseVPath.Get() );
  818. _cache._LokValidateOrAddDirEntry( info, pwcUser );
  819. }
  820. }
  821. return S_OK;
  822. }
  823. private:
  824. CImpersonationTokenCache & _cache;
  825. };
  826. //+---------------------------------------------------------------------------
  827. //
  828. // Member: CImpersonationTokenCache::ReInitializeIISScopes
  829. //
  830. // Synopsis: ReInitialize the token cache for iis
  831. //
  832. // History: 2-Sep-97 dlee created
  833. //
  834. //----------------------------------------------------------------------------
  835. void CImpersonationTokenCache::ReInitializeIISScopes(
  836. CIISVirtualDirectories * pW3Dirs,
  837. CIISVirtualDirectories * pNNTPDirs,
  838. CIISVirtualDirectories * pIMAPDirs )
  839. {
  840. ciDebugOut(( DEB_ITRACE, "reinit iis impersonation fast\n" ));
  841. CLock lock( _mutex );
  842. Win4Assert( 0 != _pwszComponentName );
  843. CImpersonateSystem impersonate;
  844. if ( _fIndexW3Roots )
  845. {
  846. CIISCallBackImp callBack( *this );
  847. Win4Assert( 0 != pW3Dirs );
  848. pW3Dirs->Enum( callBack );
  849. }
  850. if ( _fIndexNNTPRoots )
  851. {
  852. CIISCallBackImp callBack( *this );
  853. Win4Assert( 0 != pNNTPDirs );
  854. pNNTPDirs->Enum( callBack );
  855. }
  856. if ( _fIndexIMAPRoots )
  857. {
  858. CIISCallBackImp callBack( *this );
  859. Win4Assert( 0 != pIMAPDirs );
  860. pIMAPDirs->Enum( callBack );
  861. }
  862. ciDebugOut(( DEB_ITRACE, "reinit iis impersonation fast (done)\n" ));
  863. } //ReInitializeIISScopes
  864. //+---------------------------------------------------------------------------
  865. //
  866. // Member: CImpersonationTokenCache::ReInitializeIISScopes
  867. //
  868. // Synopsis: ReInitialize the token cache for iis
  869. //
  870. // History: 4-02-96 srikants Created
  871. // 2-12-97 dlee Reimplemented for metabase
  872. //
  873. //----------------------------------------------------------------------------
  874. void CImpersonationTokenCache::ReInitializeIISScopes()
  875. {
  876. ciDebugOut(( DEB_ITRACE, "reinit iis impersonation slow\n" ));
  877. CLock lock( _mutex );
  878. Win4Assert( 0 != _pwszComponentName );
  879. CImpersonateSystem impersonate;
  880. if ( _fIndexW3Roots )
  881. {
  882. TRY
  883. {
  884. CIISVirtualDirectories dirs( W3VRoot );
  885. {
  886. CMetaDataMgr mdMgr( FALSE, W3VRoot, _W3SvcInstance );
  887. mdMgr.EnumVPaths( dirs );
  888. }
  889. CIISCallBackImp callBack( *this );
  890. dirs.Enum( callBack );
  891. }
  892. CATCH( CException, e )
  893. {
  894. ciDebugOut(( DEB_WARN,
  895. "exception getting logon info for w3\n" ));
  896. }
  897. END_CATCH
  898. }
  899. //
  900. // If the news server is enabled, we have to read the news server
  901. // virtual roots and process them.
  902. //
  903. if ( _fIndexNNTPRoots )
  904. {
  905. TRY
  906. {
  907. CIISVirtualDirectories dirs( NNTPVRoot );
  908. {
  909. CMetaDataMgr mdMgr( FALSE, NNTPVRoot, _NNTPSvcInstance );
  910. mdMgr.EnumVPaths( dirs );
  911. }
  912. CIISCallBackImp callBack( *this );
  913. dirs.Enum( callBack );
  914. }
  915. CATCH( CException, e )
  916. {
  917. ciDebugOut(( DEB_WARN,
  918. "exception getting logon info for nntp\n" ));
  919. }
  920. END_CATCH
  921. }
  922. if ( _fIndexIMAPRoots )
  923. {
  924. TRY
  925. {
  926. CIISVirtualDirectories dirs( IMAPVRoot );
  927. {
  928. CMetaDataMgr mdMgr( FALSE, IMAPVRoot, _IMAPSvcInstance );
  929. mdMgr.EnumVPaths( dirs );
  930. }
  931. CIISCallBackImp callBack( *this );
  932. dirs.Enum( callBack );
  933. }
  934. CATCH( CException, e )
  935. {
  936. ciDebugOut(( DEB_WARN,
  937. "exception getting logon info for imap\n" ));
  938. }
  939. END_CATCH
  940. }
  941. ciDebugOut(( DEB_ITRACE, "reinit iis impersonation slow (done)\n" ));
  942. } //ReInitializeIISScopes
  943. //+---------------------------------------------------------------------------
  944. //
  945. // Class: CRegistryScopesCallBackImp
  946. //
  947. // Purpose: Callback to parse registry scopes and save impersonation
  948. // information for each.
  949. //
  950. // History: 30-Oct-96 dlee created
  951. //
  952. //----------------------------------------------------------------------------
  953. class CRegistryScopesCallBackImp : public CRegCallBack
  954. {
  955. public:
  956. CRegistryScopesCallBackImp(
  957. CImpersonationTokenCache & cache ) :
  958. _cache( cache )
  959. {
  960. }
  961. NTSTATUS CallBack( WCHAR *pValueName, ULONG uValueType,
  962. VOID *pValueData, ULONG uValueLength)
  963. {
  964. TRY
  965. {
  966. CParseRegistryScope parse( pValueName,
  967. uValueType,
  968. pValueData,
  969. uValueLength );
  970. ciDebugOut(( DEB_ITRACE,
  971. "CRegistryScopesCallBackImp checking c '%ws', s '%ws' u '%ws' pw '%ws'\n",
  972. _cache.GetCatalog(),
  973. parse.GetScope(),
  974. parse.GetUsername(),
  975. parse.GetPassword( _cache.GetCatalog() ) ));
  976. // If there's a scope on a remote drive, a username, and a
  977. // password, save the token info.
  978. if ( ( 0 != parse.GetScope() ) &&
  979. ( _cache.IsNetworkDrive( parse.GetScope() ) ) &&
  980. ( 0 != parse.GetUsername() ) &&
  981. ( 0 != parse.GetPassword( _cache.GetCatalog() ) ) )
  982. {
  983. ciDebugOut(( DEB_ITRACE, "CRegistryScopesCallBackImp adding\n" ));
  984. {
  985. CParseAccount parser( parse.GetUsername() );
  986. DWORD status = _cache._LokValidateOrAddLogonEntry(
  987. parser.GetUserName(),
  988. parser.GetDomainName(),
  989. parse.GetPassword( _cache.GetCatalog() ) );
  990. if ( NO_ERROR != status )
  991. _cache._WriteLogonFailure( parse.GetUsername(), status );
  992. }
  993. {
  994. CLowcaseBuf lcasePhyDir( parse.GetScope() );
  995. lcasePhyDir.AppendBackSlash();
  996. CImprsObjInfo info( lcasePhyDir.Get(), 0 );
  997. _cache._LokValidateOrAddDirEntry( info, parse.GetUsername() );
  998. }
  999. }
  1000. }
  1001. CATCH( CException, e )
  1002. {
  1003. ciDebugOut(( DEB_ERROR,
  1004. "CRegistryScopesCallBackImp::CallBack caught error 0x%x\n",
  1005. e.GetErrorCode() ));
  1006. }
  1007. END_CATCH;
  1008. return S_OK;
  1009. }
  1010. private:
  1011. CImpersonationTokenCache & _cache;
  1012. }; //CRegistryScopesCallBackImp
  1013. //+---------------------------------------------------------------------------
  1014. //
  1015. // Member: CImpersonationTokenCache::ReInitializeScopes
  1016. //
  1017. // Synopsis: ReInitialize the token cache for remote registry scopes
  1018. //
  1019. // History: 10-24-96 dlee Created
  1020. //
  1021. //----------------------------------------------------------------------------
  1022. void CImpersonationTokenCache::ReInitializeScopes()
  1023. {
  1024. CLock lock( _mutex );
  1025. Win4Assert( 0 != _pwszComponentName );
  1026. // if the catalog isn't named, it can't have any scopes in the registry
  1027. if ( 0 == _awcCatalogName[0] )
  1028. return;
  1029. CImpersonateSystem impersonate;
  1030. TRY
  1031. {
  1032. XArray<WCHAR> xKey;
  1033. BuildRegistryScopesKey( xKey, _awcCatalogName );
  1034. ciDebugOut(( DEB_ITRACE, "Reading scope impinfo '%ws'\n", xKey.Get() ));
  1035. CRegAccess regScopes( RTL_REGISTRY_ABSOLUTE, xKey.Get() );
  1036. CRegistryScopesCallBackImp callback( *this );
  1037. regScopes.EnumerateValues( 0, callback );
  1038. }
  1039. CATCH( CException, e )
  1040. {
  1041. ciDebugOut(( DEB_WARN,
  1042. "Exception 0x%x caught groveling ci registry for impersonation info\n",
  1043. e.GetErrorCode() ));
  1044. }
  1045. END_CATCH
  1046. } //ReInitializeScopes
  1047. //+---------------------------------------------------------------------------
  1048. //
  1049. // Member: CImpersonationTokenCache::_WriteLogonFailure
  1050. //
  1051. // Synopsis: Writes an event to the event log that a logon failure
  1052. // occurred.
  1053. //
  1054. // Arguments: [pwszUser] - Id of the user
  1055. // [dwError] - Error
  1056. //
  1057. // History: 5-24-96 srikants Created
  1058. //
  1059. // Notes:
  1060. //
  1061. //----------------------------------------------------------------------------
  1062. void CImpersonationTokenCache::_WriteLogonFailure( WCHAR const * pwszUser,
  1063. DWORD dwError )
  1064. {
  1065. TRY
  1066. {
  1067. CEventLog eventLog( NULL, wcsCiEventSource );
  1068. if ( ERROR_LOGON_TYPE_NOT_GRANTED != dwError )
  1069. {
  1070. CEventItem item( EVENTLOG_ERROR_TYPE,
  1071. CI_SERVICE_CATEGORY,
  1072. MSG_CI_REMOTE_LOGON_FAILURE,
  1073. 3 );
  1074. Win4Assert( 0 != _pwszComponentName );
  1075. item.AddArg( _pwszComponentName );
  1076. item.AddArg( pwszUser );
  1077. item.AddError( dwError );
  1078. eventLog.ReportEvent( item );
  1079. }
  1080. else
  1081. {
  1082. //
  1083. // The specified user-id has no interactive logon privilege on
  1084. // this machine.
  1085. //
  1086. CEventItem item( EVENTLOG_ERROR_TYPE,
  1087. CI_SERVICE_CATEGORY,
  1088. MSG_CI_NO_INTERACTIVE_LOGON_PRIVILEGE,
  1089. 1 );
  1090. item.AddArg( pwszUser );
  1091. eventLog.ReportEvent( item );
  1092. }
  1093. }
  1094. CATCH( CException, e )
  1095. {
  1096. ciDebugOut(( DEB_ERROR, "Exception 0x%X while writing to event log\n",
  1097. e.GetErrorCode() ));
  1098. }
  1099. END_CATCH
  1100. } //_WriteLogonFailure
  1101. //+---------------------------------------------------------------------------
  1102. //
  1103. // Method: CImpersonationTokenCache::Initialize
  1104. //
  1105. // Synopsis: Initializes the token cache.
  1106. //
  1107. // History: 4-04-96 srikants Created
  1108. // 10-22-96 dlee global => member
  1109. //
  1110. //----------------------------------------------------------------------------
  1111. void CImpersonationTokenCache::Initialize(
  1112. WCHAR const * pwszComponent,
  1113. BOOL fIndexW3Roots,
  1114. BOOL fIndexNNTPRoots,
  1115. BOOL fIndexIMAPRoots,
  1116. ULONG W3SvcInstance,
  1117. ULONG NNTPSvcInstance,
  1118. ULONG IMAPSvcInstance )
  1119. {
  1120. Win4Assert( 0 == _pwszComponentName );
  1121. unsigned len = wcslen( pwszComponent );
  1122. _pwszComponentName = new WCHAR [len+1];
  1123. RtlCopyMemory( _pwszComponentName, pwszComponent, (len+1)*sizeof(WCHAR) );
  1124. _fIndexW3Roots = fIndexW3Roots;
  1125. _fIndexNNTPRoots = fIndexNNTPRoots;
  1126. _fIndexIMAPRoots = fIndexIMAPRoots;
  1127. _W3SvcInstance = W3SvcInstance;
  1128. _NNTPSvcInstance = NNTPSvcInstance;
  1129. _IMAPSvcInstance = IMAPSvcInstance;
  1130. if ( fIndexW3Roots || fIndexNNTPRoots || fIndexIMAPRoots )
  1131. ReInitializeIISScopes();
  1132. ReInitializeScopes();
  1133. } //Initialize
  1134. //+---------------------------------------------------------------------------
  1135. //
  1136. // Member: Constructor for CImpersonateRemoteAccess
  1137. //
  1138. // History: 4-03-96 srikants Created
  1139. //
  1140. //----------------------------------------------------------------------------
  1141. CImpersonateRemoteAccess::CImpersonateRemoteAccess(
  1142. CImpersonationTokenCache * pCache ) :
  1143. _pCache( pCache ),
  1144. _pTokenInfo( 0 ),
  1145. _hTokenPrev( INVALID_HANDLE_VALUE ),
  1146. _fMustRevert( FALSE )
  1147. {
  1148. }
  1149. //+---------------------------------------------------------------------------
  1150. //
  1151. // Member: CImpersonateRemoteAccess::_ImpersonateIf
  1152. //
  1153. // Synopsis: Impersonates if necessary for the given path.
  1154. //
  1155. // Arguments: [pwszPath] - Given path.
  1156. //
  1157. // History: 4-03-96 srikants Created
  1158. //
  1159. //----------------------------------------------------------------------------
  1160. BOOL CImpersonateRemoteAccess::_ImpersonateIf( WCHAR const * pwszPath,
  1161. WCHAR const * pwszVPath,
  1162. ULONG cSkip )
  1163. {
  1164. DWORD dwError = 0;
  1165. if ( _pCache->IsNetworkDrive(pwszPath) )
  1166. {
  1167. //
  1168. // If we have already impersonated for the given share, then nothing
  1169. // to do.
  1170. //
  1171. CLowcaseBuf lcasePath( pwszPath );
  1172. lcasePath.AppendBackSlash();
  1173. //
  1174. // It has been assumed that the VPath is already in lowercase and
  1175. // the forward slashes are converted to back slashes.
  1176. //
  1177. CImprsObjInfo obj( lcasePath.Get(), pwszVPath );
  1178. if ( IsImpersonated() )
  1179. {
  1180. Win4Assert( 0 != _pTokenInfo );
  1181. if ( !_pTokenInfo->IsZombie() &&
  1182. _pTokenInfo->IsMatch(obj) )
  1183. {
  1184. ciDebugOut(( DEB_ITRACE, "Already impersonated for (%ws)\n",
  1185. lcasePath.Get() ));
  1186. return TRUE;
  1187. }
  1188. else
  1189. {
  1190. Release(); // Release the current impersonation
  1191. }
  1192. }
  1193. BOOL fSuccess = OpenThreadToken( GetCurrentThread(),
  1194. TOKEN_QUERY | TOKEN_IMPERSONATE,
  1195. TRUE, // Access check against process
  1196. &_hTokenPrev );
  1197. if ( !fSuccess )
  1198. {
  1199. dwError = GetLastError();
  1200. if ( ERROR_NO_TOKEN == dwError )
  1201. {
  1202. //
  1203. // This thread is currently not impersonating anyone.
  1204. //
  1205. }
  1206. else
  1207. {
  1208. ciDebugOut(( DEB_ERROR, "Failed to open thread token. Error %d\n",
  1209. dwError ));
  1210. THROW( CException( HRESULT_FROM_WIN32(dwError)) );
  1211. }
  1212. }
  1213. //
  1214. // Get the impersonation information for the path.
  1215. //
  1216. _pTokenInfo = _pCache->Find( obj, cSkip );
  1217. if ( 0 == _pTokenInfo )
  1218. {
  1219. ciDebugOut(( DEB_WARN, "There is no %simpersonation info for (%ws)\n",
  1220. cSkip > 0 ? "more " : "",
  1221. lcasePath.Get() ));
  1222. return FALSE;
  1223. }
  1224. if ( INVALID_HANDLE_VALUE == _pTokenInfo->GetHandle() )
  1225. return FALSE;
  1226. //
  1227. // Impersonate the specified user.
  1228. //
  1229. fSuccess = ImpersonateLoggedOnUser( _pTokenInfo->GetHandle() );
  1230. if ( !fSuccess )
  1231. {
  1232. dwError = GetLastError();
  1233. ciDebugOut(( DEB_WARN, "Error (%d) while impersonating for path (%ws)\n",
  1234. dwError, pwszPath ));
  1235. return FALSE;
  1236. }
  1237. #if CIDBG == 1
  1238. ciDebugOut(( DEB_ITRACE, "Impersonated successfully for (%ws)\n",
  1239. pwszPath ));
  1240. CLogonInfo &li = *_pTokenInfo->GetLogonInfo();
  1241. ciDebugOut(( DEB_ITRACE, " using user %ws\\%ws, password %ws\n",
  1242. li.GetDomain(), li.GetUser(), li.GetPassword() ));
  1243. #endif
  1244. _fMustRevert = TRUE;
  1245. }
  1246. return TRUE;
  1247. } //_ImpersonateIf
  1248. //+---------------------------------------------------------------------------
  1249. //
  1250. // Member: CImpersonateRemoteAccess::Release
  1251. //
  1252. // Synopsis: Releases the resources that were used for impersonation.
  1253. //
  1254. // History: 4-04-96 srikants Created
  1255. //
  1256. //----------------------------------------------------------------------------
  1257. void CImpersonateRemoteAccess::Release()
  1258. {
  1259. DWORD dwError = 0;
  1260. if ( _fMustRevert )
  1261. {
  1262. if ( INVALID_HANDLE_VALUE != _hTokenPrev )
  1263. {
  1264. BOOL fResult = ImpersonateLoggedOnUser( _hTokenPrev );
  1265. if ( !fResult )
  1266. {
  1267. dwError = GetLastError();
  1268. ciDebugOut(( DEB_WARN, "ImpersonateLoggedOnUser failed with error %d\n",
  1269. dwError ));
  1270. }
  1271. }
  1272. else
  1273. {
  1274. //
  1275. // There was no impersonation token - just revert to self.
  1276. //
  1277. BOOL fResult = RevertToSelf();
  1278. if ( !fResult )
  1279. {
  1280. dwError = GetLastError();
  1281. ciDebugOut(( DEB_ERROR, "RevertToSelf failed with error %d\n",
  1282. dwError ));
  1283. }
  1284. }
  1285. }
  1286. if ( _pTokenInfo )
  1287. _pCache->Release( _pTokenInfo );
  1288. if ( INVALID_HANDLE_VALUE != _hTokenPrev )
  1289. CloseHandle( _hTokenPrev );
  1290. _fMustRevert = FALSE;
  1291. _pTokenInfo = 0;
  1292. _hTokenPrev = INVALID_HANDLE_VALUE;
  1293. } //Release
  1294. //+---------------------------------------------------------------------------
  1295. //
  1296. // Member: PImpersonatedWorkItem::ImpersonateAndDoWork
  1297. //
  1298. // Synopsis: Calls the DoIt() virtual method after impersonating.
  1299. //
  1300. // Arguments: [access] - The remote access object to use for impersonation.
  1301. //
  1302. // History: 7-15-96 srikants Created
  1303. //
  1304. // Notes: Calls the DoIt() method until it either returns TRUE or there
  1305. // is an exception.
  1306. //
  1307. //----------------------------------------------------------------------------
  1308. void PImpersonatedWorkItem::ImpersonateAndDoWork(
  1309. CImpersonateRemoteAccess & access )
  1310. {
  1311. ULONG cSkip = 0;
  1312. if ( _fNetPath )
  1313. {
  1314. while ( TRUE )
  1315. {
  1316. BOOL fSuccess = access.ImpersonateIf( _pwszPath, cSkip, 0 );
  1317. if ( !access.IsTokenFound() )
  1318. THROW( CException( STATUS_LOGON_FAILURE ) );
  1319. if ( fSuccess && DoIt() )
  1320. break;
  1321. cSkip++;
  1322. access.Release();
  1323. }
  1324. }
  1325. else
  1326. {
  1327. if ( access.IsImpersonated() )
  1328. {
  1329. //
  1330. // Just revert back to what it was
  1331. //
  1332. access.Release();
  1333. }
  1334. DoIt();
  1335. }
  1336. } //ImpersonateAndDoWork
  1337. //+---------------------------------------------------------------------------
  1338. //
  1339. // Member: CImpersonatedGetAttr::DoIt
  1340. //
  1341. // Synopsis: Does the actual work of getting attributes.
  1342. //
  1343. // Returns: TRUE if successful; FALSE if should be retried; THROWS
  1344. // otherwise.
  1345. //
  1346. // History: 7-18-96 srikants Created
  1347. //
  1348. //----------------------------------------------------------------------------
  1349. BOOL CImpersonatedGetAttr::DoIt()
  1350. {
  1351. if ( !GetFileAttributesEx( _funnyPath.GetPath(), GetFileExInfoStandard, &_ffData ) )
  1352. {
  1353. DWORD dwError = GetLastError();
  1354. if ( IsRetryableError( (NTSTATUS) dwError ) )
  1355. {
  1356. return FALSE;
  1357. }
  1358. else
  1359. {
  1360. ciDebugOut(( DEB_ERROR, "Error 0x%X while starting scan on path (%ws)\n",
  1361. dwError, _funnyPath.GetPath() ));
  1362. THROW( CException( HRESULT_FROM_WIN32(dwError)) );
  1363. return FALSE;
  1364. }
  1365. }
  1366. else return TRUE;
  1367. } //DoIt
  1368. //+---------------------------------------------------------------------------
  1369. //
  1370. // Member: CImpersonatedGetFileAttr::DoIt
  1371. //
  1372. // Synopsis: Does the actual work of getting attributes.
  1373. //
  1374. // Returns: TRUE if successful; FALSE if should be retried; THROWS
  1375. // otherwise.
  1376. //
  1377. // History: 12-05-01 dlee Created
  1378. //
  1379. //----------------------------------------------------------------------------
  1380. BOOL CImpersonatedGetFileAttr::DoIt()
  1381. {
  1382. ULONG ulAttr = GetFileAttributes( _funnyPath.GetPath() );
  1383. if ( INVALID_FILE_ATTRIBUTES == ulAttr )
  1384. {
  1385. DWORD dwError = GetLastError();
  1386. if ( IsRetryableError( (NTSTATUS) dwError ) )
  1387. {
  1388. return FALSE;
  1389. }
  1390. ciDebugOut(( DEB_ERROR, "Error %#x while getting file attributes (%ws)\n",
  1391. dwError, _funnyPath.GetPath() ));
  1392. THROW( CException( HRESULT_FROM_WIN32(dwError)) );
  1393. }
  1394. _ulAttr = ulAttr;
  1395. return TRUE;
  1396. } //DoIt