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.

1714 lines
42 KiB

  1. //*************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation 1999 - 2000
  4. // All rights reserved
  5. //
  6. // log.cxx
  7. //
  8. // Contains definitions for classes related to rsop logging
  9. // for the folder redirection client-side extension
  10. //
  11. // Created: 8-01-1999 adamed
  12. //
  13. //*************************************************************
  14. #include "fdeploy.hxx"
  15. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  16. //
  17. // Function: CRedirectionPolicy::CRedirectionPolicy
  18. //
  19. // Purpose: Constructor for CRedirectionPlicy
  20. //
  21. // Params:
  22. // pGpoData -- structure containing information
  23. // from the gpo
  24. // pRdirect -- structure containing redireciton information
  25. // Precedence -- the precedence this redirection candidate
  26. // should have. Lower values are least signifcant, higher
  27. // values have higher precedence.
  28. //
  29. // Return value: none
  30. //
  31. // Notes: This constructor allocates memory and performs
  32. // other complex operations -- if it fails,
  33. // this fact is tracked internally and operations on the
  34. // object will fail as well with the error code
  35. //
  36. //------------------------------------------------------------
  37. CRedirectionPolicy::CRedirectionPolicy(
  38. CFileDB* pGpoData,
  39. CRedirectInfo* pRedirect,
  40. LONG Precedence,
  41. HRESULT* phr) :
  42. _rgwszGroups(NULL),
  43. _rgwszRedirectedPaths(NULL),
  44. _cGroups(0),
  45. _Precedence(Precedence),
  46. _dwFlags(pRedirect->m_dwFlags),
  47. _wszDisplayName(NULL),
  48. _wszLocalizedName(NULL),
  49. _wszGPODSPath(NULL),
  50. _wszSOMId(NULL),
  51. _pNext(NULL),
  52. _iFolderIndex(pRedirect->m_rID),
  53. _iAncestorIndex(0),
  54. _bHasAncestor(FALSE),
  55. _pGpoData( pGpoData ),
  56. _bMissingAncestor( FALSE ),
  57. _wszRedirectedPath( NULL )
  58. {
  59. RtlInitUnicodeString( &_RedirectedSid, NULL );
  60. //
  61. // If this folder has a parent folder, remember that fact,
  62. // and record the id of the parent folder
  63. //
  64. if (pRedirect->m_pParent)
  65. {
  66. _iAncestorIndex = pRedirect->m_pParent->m_rID;
  67. _bHasAncestor = TRUE;
  68. }
  69. //
  70. // Retrieve security group / redirected folder information
  71. //
  72. _hrInit = GetGroupInformation(pRedirect->m_szGroupRedirectionData);
  73. if (FAILED(_hrInit))
  74. {
  75. *phr = _hrInit;
  76. return;
  77. }
  78. //
  79. // Copy the gpo's ds path for use as a gpo id -- we want only the part
  80. // of the path after the link prefix and user or computer container
  81. //
  82. WCHAR* wszGPOPrefixEnd;
  83. wszGPOPrefixEnd = wcschr( StripLinkPrefix( pGpoData->_pwszGPODSPath ), L',' );
  84. //
  85. // At this point, we are one charcter in front of the gpo container --
  86. // copy everything after this position
  87. //
  88. if ( wszGPOPrefixEnd )
  89. {
  90. _wszGPODSPath = StringDuplicate( wszGPOPrefixEnd + 1 );
  91. }
  92. if ( ! _wszGPODSPath )
  93. {
  94. goto exit_on_memory_allocation_failure;
  95. }
  96. //
  97. // Copy the scope of management path and use it as an id,
  98. // copying only the path after the ds prefix
  99. //
  100. _wszSOMId = StringDuplicate( StripLinkPrefix(pGpoData->_pwszGPOSOMPath) );
  101. if ( ! _wszSOMId )
  102. {
  103. goto exit_on_memory_allocation_failure;
  104. }
  105. //
  106. // Copy the friendly name of the redirected folder
  107. //
  108. _wszDisplayName = StringDuplicate(pRedirect->m_szDisplayName);
  109. if ( ! _wszDisplayName )
  110. {
  111. goto exit_on_memory_allocation_failure;
  112. }
  113. //
  114. // Copy the localized file system name of the folder
  115. //
  116. _wszLocalizedName = StringDuplicate(pRedirect->m_szLocDisplayName);
  117. if ( ! _wszLocalizedName )
  118. {
  119. goto exit_on_memory_allocation_failure;
  120. }
  121. //
  122. // Copy the redirected sid in string format -- the sid
  123. // will not be present if this folder inherits from the parent,
  124. // so do not copy it in that case -- this will be dealt with later
  125. // when the final parent is known.
  126. //
  127. if ( pRedirect->m_pSid )
  128. {
  129. NTSTATUS Status;
  130. //
  131. // Copy the path to which this folder is redirected
  132. //
  133. _wszRedirectedPath = StringDuplicate( _rgwszRedirectedPaths[ pRedirect->m_iRedirectingGroup ] );
  134. if ( ! _wszRedirectedPath )
  135. {
  136. goto exit_on_memory_allocation_failure;
  137. }
  138. Status = RtlConvertSidToUnicodeString(
  139. &_RedirectedSid,
  140. pRedirect->m_pSid,
  141. TRUE);
  142. if (STATUS_SUCCESS != Status)
  143. {
  144. LONG Error;
  145. Error = RtlNtStatusToDosError(Status);
  146. _hrInit = HRESULT_FROM_WIN32(Error);
  147. }
  148. else
  149. {
  150. _hrInit = S_OK;
  151. }
  152. }
  153. *phr = _hrInit;
  154. return;
  155. exit_on_memory_allocation_failure:
  156. //
  157. // Set our internal state to error so that methods
  158. // know that our internal state is bad and will fail
  159. // safely
  160. //
  161. _hrInit = E_OUTOFMEMORY;
  162. *phr = _hrInit;
  163. }
  164. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  165. //
  166. // Function: CRedirectionPolicy::~CRedirectionPolicy
  167. //
  168. // Purpose: Destructor for CRedirectionPolicy. Frees resources
  169. // allocated by this object
  170. //
  171. // Params: none
  172. //
  173. // Return value: none
  174. //
  175. // Notes:
  176. //
  177. //------------------------------------------------------------
  178. CRedirectionPolicy::~CRedirectionPolicy()
  179. {
  180. LONG iGroup;
  181. //
  182. // Iterate through the groups / paths strings
  183. // and destroy each one
  184. //
  185. for (iGroup = 0; iGroup < _cGroups; iGroup++)
  186. {
  187. delete [] _rgwszGroups[iGroup];
  188. delete [] _rgwszRedirectedPaths[iGroup];
  189. }
  190. //
  191. // Free all the other allocated strings
  192. //
  193. delete [] _rgwszGroups;
  194. delete [] _rgwszRedirectedPaths;
  195. delete [] _wszGPODSPath;
  196. delete [] _wszSOMId;
  197. delete [] _wszDisplayName;
  198. delete [] _wszLocalizedName;
  199. delete [] _wszRedirectedPath;
  200. RtlFreeUnicodeString(&_RedirectedSid);
  201. }
  202. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  203. //
  204. // Function: CRedirectionPolicy::Write
  205. //
  206. // Purpose: implementation of pure virtual Write method required
  207. // by all policy records. It writes policy information
  208. // for the redirection candidate to the log in the database
  209. //
  210. // Params: none
  211. //
  212. // Return value: S_OK if successful, error otherwise
  213. //
  214. // Notes:
  215. //
  216. //------------------------------------------------------------
  217. HRESULT CRedirectionPolicy::Write()
  218. {
  219. HRESULT hr;
  220. //
  221. // Set the unique id
  222. //
  223. hr = SetValue(
  224. RSOP_ATTRIBUTE_ID,
  225. _wszDisplayName);
  226. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_ID, hr )
  227. //
  228. // If we cannot make a unique id, we must exit because this is a key
  229. //
  230. if (FAILED(hr))
  231. {
  232. DebugMsg((DM_VERBOSE, IDS_RSOP_ATTEMPT_WRITE, _wszDisplayName));
  233. return hr;
  234. }
  235. //
  236. // Set the precedence for the setting -- this is also a key
  237. // so we must exit if we cannot set this
  238. //
  239. hr = SetValue(
  240. RSOP_ATTRIBUTE_PRECEDENCE,
  241. _Precedence);
  242. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_PRECEDENCE, hr )
  243. if (FAILED(hr))
  244. {
  245. return hr;
  246. }
  247. //
  248. // Set the time stamp on the record
  249. //
  250. {
  251. SYSTEMTIME CurrentTime;
  252. //
  253. // This does not fail
  254. //
  255. GetSystemTime( &CurrentTime );
  256. hr = SetValue(
  257. RSOP_ATTRIBUTE_CREATIONTIME,
  258. &CurrentTime);
  259. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_CREATIONTIME, hr );
  260. }
  261. //
  262. // Set the installationtype -- basic or advanced in the UI
  263. //
  264. {
  265. LONG InstallationType;
  266. if ( _dwFlags & REDIR_SCALEABLE )
  267. {
  268. InstallationType = RDR_ATTRIBUTE_INSTALLATIONTYPE_VALUE_MAX;
  269. }
  270. else
  271. {
  272. InstallationType = RDR_ATTRIBUTE_INSTALLATIONTYPE_VALUE_BASIC;
  273. }
  274. hr = SetValue(
  275. RDR_ATTRIBUTE_INSTALLATIONTYPE,
  276. InstallationType);
  277. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_INSTALLATIONTYPE, hr )
  278. }
  279. //
  280. // Set unique id for the gpo
  281. //
  282. hr = SetValue(
  283. RSOP_ATTRIBUTE_GPOID,
  284. _wszGPODSPath);
  285. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_GPOID, hr )
  286. //
  287. // Set the friendly name of the redirected folder
  288. //
  289. hr = SetValue(
  290. RSOP_ATTRIBUTE_NAME,
  291. _wszDisplayName);
  292. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_NAME, hr )
  293. //
  294. // Set the scope of management that caused this
  295. // policy to be applied
  296. //
  297. hr = SetValue(
  298. RSOP_ATTRIBUTE_SOMID,
  299. _wszSOMId);
  300. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_SOMID, hr )
  301. //
  302. // The path to which the folder would be redirected
  303. //
  304. if ( _wszRedirectedPath )
  305. {
  306. hr = SetValue(
  307. RDR_ATTRIBUTE_RESULT,
  308. _wszRedirectedPath);
  309. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_RESULT, hr )
  310. }
  311. //
  312. // In the case of a child setting with a missing parent, none of the
  313. // other information can be logged, since it cannot be inferred
  314. // from the parent (there is none)
  315. //
  316. if ( ! _bMissingAncestor )
  317. {
  318. //
  319. // List of security groups
  320. //
  321. hr = SetValue(
  322. RDR_ATTRIBUTE_GROUPS,
  323. _rgwszGroups,
  324. _cGroups);
  325. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_GROUPS, hr )
  326. //
  327. // List of redirected paths parallel to the security group list
  328. //
  329. hr = SetValue(
  330. RDR_ATTRIBUTE_PATHS,
  331. _rgwszRedirectedPaths,
  332. _cGroups);
  333. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_PATHS, hr )
  334. //
  335. // Access grant type
  336. //
  337. hr = SetValue(
  338. RDR_ATTRIBUTE_GRANTTYPE,
  339. (BOOL) (_dwFlags & REDIR_SETACLS));
  340. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_GRANTTYPE, hr )
  341. //
  342. // Move Type
  343. //
  344. hr = SetValue(
  345. RDR_ATTRIBUTE_MOVETYPE,
  346. (BOOL) (_dwFlags & REDIR_MOVE_CONTENTS));
  347. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_MOVETYPE, hr )
  348. //
  349. // Redirecting group
  350. //
  351. hr = SetValue(
  352. RDR_ATTRIBUTE_REDIRECTING_GROUP,
  353. _RedirectedSid.Buffer);
  354. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_REDIRECTING_GROUP, hr )
  355. }
  356. else
  357. {
  358. WCHAR* wszLocalInheritedPath;
  359. wszLocalInheritedPath = NULL;
  360. //
  361. // If this folder is set to follow its ancestor but no ancestor
  362. // was specified, we can still set the resulting path by
  363. // looking at the path to which we are redirected
  364. //
  365. hr = GenerateLocalInheritedPath(
  366. &wszLocalInheritedPath);
  367. if ( SUCCEEDED( hr ) )
  368. {
  369. hr = SetValue(
  370. RDR_ATTRIBUTE_RESULT,
  371. _rgwszGroups,
  372. _cGroups);
  373. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_RESULT, hr )
  374. }
  375. }
  376. //
  377. // Policy Removal
  378. //
  379. hr = SetValue(
  380. RDR_ATTRIBUTE_POLICYREMOVAL,
  381. (_dwFlags & REDIR_RELOCATEONREMOVE) ?
  382. RDR_ATTRIBUTE_POLICYREMOVAL_VALUE_REDIRECT :
  383. RDR_ATTRIBUTE_POLICYREMOVAL_VALUE_REMAIN);
  384. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_POLICYREMOVAL, hr )
  385. return S_OK;
  386. }
  387. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  388. //
  389. // Function: CRedirectionPolicy::GetGroupInformation
  390. //
  391. // Purpose: Gets gorup information from the redirection ini
  392. // file data concerning the list of security groups and
  393. // the redirected folder for each group
  394. //
  395. // Params: wszGroupRedirectionData -- this data was retrieved
  396. // from an ini file and contains group and folder lists
  397. //
  398. // Return value: S_OK if successful, error otherwise
  399. //
  400. // Notes:
  401. //
  402. //------------------------------------------------------------
  403. HRESULT CRedirectionPolicy::GetGroupInformation(
  404. WCHAR* wszGroupRedirectionData)
  405. {
  406. HRESULT hr;
  407. //
  408. // First, parse the file in order to count the groups. No
  409. // memory allocation is done when counting, so this should
  410. // always succeed
  411. //
  412. hr = ParseGroupInformation(
  413. wszGroupRedirectionData,
  414. &_cGroups);
  415. ASSERT(S_OK == hr);
  416. //
  417. // Allocate space for references to each group and folder
  418. // based on the count returned above
  419. //
  420. _rgwszGroups = new WCHAR* [_cGroups];
  421. _rgwszRedirectedPaths = new WCHAR* [_cGroups];
  422. if (!_rgwszGroups || !_rgwszRedirectedPaths)
  423. {
  424. return E_OUTOFMEMORY;
  425. }
  426. //
  427. // Initialize newly allocated references
  428. //
  429. RtlZeroMemory(_rgwszGroups, sizeof(*_rgwszGroups) * _cGroups);
  430. RtlZeroMemory(_rgwszRedirectedPaths, sizeof(*_rgwszRedirectedPaths) * _cGroups);
  431. //
  432. // Now perform the actual copy of parsed information. Note that this
  433. // will allocate space for strings for each folder and group and
  434. // set our vectors of references to refer to those strings. An out of
  435. // memory error could occur here, so we return any error we get
  436. //
  437. hr = ParseGroupInformation(
  438. wszGroupRedirectionData,
  439. &_cGroups,
  440. _rgwszGroups,
  441. _rgwszRedirectedPaths);
  442. return hr;
  443. }
  444. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  445. //
  446. // Function: CRedirectionPolicy::ParseGroupInformation
  447. //
  448. // Purpose: parses the redirection ini file data to retrieve
  449. // the list of security groups and the redirected folder for
  450. // each group
  451. //
  452. // Params:
  453. // wszGroupRedirectionData -- this data was retrieved
  454. // from an ini file and contains group and folder lists
  455. // pCount -- in, out param indicating # of groups / paths to retrieve.
  456. // on output, only has meaning if the folder and group arrays
  457. // are not specified -- in this case, it contains the count
  458. // of groups / paths so you can determine how many exist
  459. // before allocation.
  460. // rgwszGroups -- on input, contains an array of pointers
  461. // to c-strings. If NULL, only a count of groups / paths
  462. // is performed and there is no output.
  463. // On output, an allocation is made and data is copied
  464. // for each group. Each entry in the array
  465. // will be set to point to the appropriate allocated
  466. // string
  467. // rgwszPaths -- similar to above, except for target paths
  468. //
  469. // Return value: S_OK if successful, error otherwise
  470. //
  471. // Notes: IMPORTANT: rgwszGroups and rgwszPaths are parallel
  472. // arrays and should be accessed as such.
  473. // In the case of partial allocations below due to out of memory,
  474. // allocated memory is cleared by the destructor.
  475. // The basic algorithm for the parsing is taken from another location
  476. // in this extension -- if that changes, so must this.
  477. //
  478. // Current data format:
  479. //
  480. // <group-sid1>=<redirected-filesyspath1>
  481. // <group-sid2>=<redirected-filesyspath2>
  482. // <group-sid3>=<redirected-filesyspath3>
  483. // ...
  484. //
  485. //------------------------------------------------------------
  486. HRESULT CRedirectionPolicy::ParseGroupInformation(
  487. WCHAR* wszGroupRedirectionData,
  488. LONG* pCount,
  489. WCHAR** rgwszGroups,
  490. WCHAR** rgwszPaths)
  491. {
  492. WCHAR* wszCurrent;
  493. DWORD cchCurrent;
  494. DWORD cGroups;
  495. HRESULT hr;
  496. //
  497. // Init locals
  498. //
  499. cGroups = 0;
  500. hr = S_OK;
  501. //
  502. // First, find out how many paths there are, and separate
  503. // the path entry into its constituents
  504. //
  505. wszCurrent = wszGroupRedirectionData;
  506. if (wszCurrent)
  507. {
  508. //
  509. // Move through the data
  510. //
  511. for (wszCurrent;
  512. *wszCurrent;
  513. wszCurrent += cchCurrent)
  514. {
  515. WCHAR* wszPath;
  516. //
  517. // Find out the length of the current entry
  518. //
  519. cchCurrent = lstrlen(wszCurrent) + 1;
  520. //
  521. // Get the path so we can validate it
  522. //
  523. wszPath = wcschr(wszCurrent, L'=');
  524. //
  525. // If no path is specified, this is an invalid entry
  526. //
  527. if (!wszPath)
  528. {
  529. continue;
  530. }
  531. //
  532. // Terminate the pathname, but only if we're doing copying
  533. //
  534. if (rgwszGroups)
  535. {
  536. *wszPath = L'\0';
  537. }
  538. //
  539. // Advance to the path past the delimiter
  540. //
  541. wszPath++;
  542. //
  543. // A blank path -- skip this
  544. //
  545. if (!*wszPath)
  546. {
  547. continue;
  548. }
  549. //
  550. // If the group array is specified, we need to copy the
  551. // group and folder information, not just count groups / paths
  552. //
  553. if (rgwszGroups)
  554. {
  555. DWORD Status;
  556. //
  557. // Copy this group
  558. //
  559. rgwszGroups[cGroups] = StringDuplicate(wszCurrent);
  560. if ( ! rgwszGroups[cGroups] )
  561. {
  562. hr = E_OUTOFMEMORY;
  563. break;
  564. }
  565. //
  566. // Copy this path
  567. //
  568. Status = GetExpandedPath(
  569. _pGpoData,
  570. wszPath,
  571. _iFolderIndex,
  572. _bHasAncestor,
  573. &(rgwszPaths[cGroups]));
  574. if ( ERROR_SUCCESS != Status )
  575. {
  576. hr = HRESULT_FROM_WIN32( Status );
  577. break;
  578. }
  579. }
  580. cGroups++;
  581. }
  582. }
  583. //
  584. // Record the number of groups counted
  585. //
  586. *pCount = cGroups;
  587. return hr;
  588. }
  589. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  590. //
  591. // Function: CRedirectionPolicy::GenerateInheritedPath
  592. //
  593. // Purpose: Return the name of the path that results from
  594. // treating this folder as a subfolder of a specific path
  595. //
  596. // Params:
  597. // pwszAncestorPath -- in parameter indicating parent folder in
  598. // in which this folder should be placed
  599. //
  600. // ppwszInheritedPath -- out parameter for resulting path
  601. //
  602. // Return value: S_OK if successful, error otherwise
  603. //
  604. //------------------------------------------------------------
  605. HRESULT CRedirectionPolicy::GenerateInheritedPath(
  606. WCHAR* pwszAncestorPath,
  607. WCHAR** ppwszInheritedPath)
  608. {
  609. HRESULT hr;
  610. DWORD cchParent;
  611. DWORD cchRelative;
  612. hr = E_OUTOFMEMORY;
  613. //
  614. // Construct the folder path by adding the relative path of this
  615. // child to its ancestor's path
  616. //
  617. //
  618. // First, determine the length of the path of this folder
  619. // relative to its ancestor's path -- this is just the
  620. // localized name of the folder
  621. //
  622. cchRelative = lstrlen( _wszLocalizedName );
  623. cchParent = lstrlen( pwszAncestorPath );
  624. *ppwszInheritedPath = new WCHAR[ cchParent + 1 + cchRelative + 1 ];
  625. if ( *ppwszInheritedPath )
  626. {
  627. //
  628. // Now, copy the ancestor's path
  629. //
  630. lstrcpy( *ppwszInheritedPath, pwszAncestorPath );
  631. //
  632. // Add on the path separator if one does not already exist at the end of the ancestor path
  633. //
  634. if ( ( cchParent != 0 ) &&
  635. ( L'\\' != pwszAncestorPath[ cchParent - 1] ) )
  636. {
  637. lstrcat( *ppwszInheritedPath, L"\\" );
  638. }
  639. //
  640. // Now append this child's relative path to its ancestor
  641. //
  642. lstrcat( *ppwszInheritedPath, _wszLocalizedName );
  643. hr = S_OK;
  644. }
  645. return hr;
  646. }
  647. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  648. //
  649. // Function: CRedirectionPolicy::GenerateInheritedPath
  650. //
  651. // Purpose: Return the name of the path that results from
  652. // treating this folder as a subfolder of the path
  653. // to which this folder's parent is redirected
  654. //
  655. // Params:
  656. //
  657. // ppwszInheritedPath -- out parameter for resulting path
  658. //
  659. // Return value: S_OK if successful, error otherwise
  660. //
  661. //------------------------------------------------------------
  662. HRESULT CRedirectionPolicy::GenerateLocalInheritedPath(
  663. WCHAR** ppwszInheritedPath )
  664. {
  665. HRESULT hr;
  666. int iAncestor;
  667. CRedirectInfo* pAncestorInfo;
  668. WCHAR wszFolderKey [ TARGETPATHLIMIT ];
  669. WCHAR wszInheritedFolder [ TARGETPATHLIMIT ];
  670. hr = S_OK;
  671. iAncestor = GetAncestorIndex();
  672. pAncestorInfo = & ( gPolicyResultant[ iAncestor ] );
  673. lstrcpy( wszFolderKey, pAncestorInfo->m_szFolderRelativePath );
  674. lstrcat( wszFolderKey, L"\\" );
  675. if ( _pGpoData->GetRsopContext()->IsDiagnosticModeEnabled() )
  676. {
  677. DWORD Status;
  678. Status = _pGpoData->GetLocalFilePath(
  679. wszFolderKey,
  680. wszInheritedFolder);
  681. hr = HRESULT_FROM_WIN32( Status );
  682. }
  683. else
  684. {
  685. lstrcpy( wszInheritedFolder, L"%USERPROFILE%\\" );
  686. lstrcat( wszInheritedFolder, wszFolderKey );
  687. }
  688. if ( SUCCEEDED( hr ) )
  689. {
  690. hr = GenerateInheritedPath(
  691. wszInheritedFolder,
  692. ppwszInheritedPath);
  693. }
  694. return hr;
  695. }
  696. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  697. //
  698. // Function: CRedirectionPolicy::CopyInheritedData
  699. //
  700. // Purpose: Copies data that should be inherited from an ancestor
  701. // to the object
  702. //
  703. // Params:
  704. // pAncestralPolicy -- pointer to CRedirectionPolicy representing
  705. // the policy for the ancestor folder
  706. //
  707. // Return value: S_OK if successful, error otherwise.
  708. //
  709. // Notes:
  710. //
  711. // If a folder is set to inherit from its parent, the
  712. // following attributes must be copied from the parent:
  713. //
  714. // - Security Groups
  715. // - Redirection target paths
  716. // - The number of groups / paths
  717. // - Flags
  718. //
  719. // This method copies those attributes from an ancestor
  720. // to this object
  721. //
  722. //------------------------------------------------------------
  723. HRESULT CRedirectionPolicy::CopyInheritedData( CRedirectionPolicy* pAncestralPolicy )
  724. {
  725. LONG iGroup;
  726. LONG cGroups;
  727. HRESULT hr;
  728. //
  729. // If we have no ancestor, then the only ancestral information
  730. // we can copy is the redirected path
  731. //
  732. if ( ! pAncestralPolicy )
  733. {
  734. _bMissingAncestor = TRUE;
  735. hr = GenerateLocalInheritedPath(
  736. &_wszRedirectedPath);
  737. return hr;
  738. }
  739. //
  740. // Copy the redirecting group information first -- it
  741. // will only be there if the user would have gotten
  742. // this folder, so do not try to copy it if it is not there
  743. //
  744. if ( pAncestralPolicy->_RedirectedSid.Buffer )
  745. {
  746. BOOLEAN fAllocatedString;
  747. fAllocatedString = RtlCreateUnicodeString(
  748. &_RedirectedSid,
  749. pAncestralPolicy->_RedirectedSid.Buffer);
  750. if ( !fAllocatedString )
  751. {
  752. return E_OUTOFMEMORY;
  753. }
  754. RtlCopyUnicodeString(
  755. &_RedirectedSid,
  756. &(pAncestralPolicy->_RedirectedSid));
  757. hr = GenerateInheritedPath(
  758. pAncestralPolicy->_wszRedirectedPath,
  759. &_wszRedirectedPath);
  760. if ( FAILED(hr) )
  761. {
  762. return hr;
  763. }
  764. }
  765. //
  766. // Find out how many groups / paths there are
  767. //
  768. cGroups = pAncestralPolicy->_cGroups;
  769. //
  770. // Allocate space for the security groups
  771. //
  772. _rgwszGroups = new WCHAR* [ cGroups ];
  773. hr = E_OUTOFMEMORY;
  774. if ( _rgwszGroups )
  775. {
  776. //
  777. // Now allocate space for the target paths
  778. //
  779. _rgwszRedirectedPaths = new WCHAR* [ cGroups ];
  780. if ( _rgwszRedirectedPaths )
  781. {
  782. hr = S_OK;
  783. //
  784. // Now allocate copies of each security group and
  785. // redirected target path
  786. //
  787. for ( iGroup = 0; iGroup < cGroups; iGroup ++ )
  788. {
  789. DWORD cchParent;
  790. //
  791. // Construct the folder path by adding the relative path of this
  792. // child to its ancestor's path
  793. //
  794. //
  795. // First, copy the ancestor's path
  796. //
  797. hr = GenerateInheritedPath(
  798. pAncestralPolicy->_rgwszRedirectedPaths[ iGroup ],
  799. &( _rgwszRedirectedPaths[ iGroup ] )
  800. );
  801. if ( FAILED( hr ) )
  802. {
  803. break;
  804. }
  805. //
  806. // Security group is much simpler -- just copy it
  807. //
  808. _rgwszGroups[ iGroup ] = StringDuplicate(
  809. pAncestralPolicy->_rgwszGroups[ iGroup ]);
  810. if ( ! _rgwszGroups[ iGroup ] )
  811. {
  812. hr = E_OUTOFMEMORY;
  813. break;
  814. }
  815. }
  816. }
  817. }
  818. //
  819. // Copy the flags
  820. //
  821. _dwFlags = pAncestralPolicy->_dwFlags;
  822. //
  823. // If we're successful, set the # of groups. We only set this on
  824. // success so that we don't write out an incomplete set
  825. //
  826. if ( SUCCEEDED( hr ) )
  827. {
  828. _cGroups = cGroups;
  829. }
  830. return hr;
  831. }
  832. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  833. //
  834. // Function: CRedirectionPolicy::GetFolderIndex
  835. //
  836. // Purpose: Retrieves a numeric index representing the folder
  837. // (startup, mydocs, etc)
  838. //
  839. // Params: none
  840. //
  841. // Return value: index of the folder redirected by this policy
  842. //
  843. // Notes:
  844. //
  845. //------------------------------------------------------------
  846. int CRedirectionPolicy::GetFolderIndex()
  847. {
  848. return _iFolderIndex;
  849. }
  850. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  851. //
  852. // Function: CRedirectionPolicy::GetAncestorIndex
  853. //
  854. // Purpose: Retrieves a numeric index representing the ancestor
  855. // of this folder
  856. //
  857. // Params: none
  858. //
  859. // Return value: index of the ancestor of the folder redirected
  860. // by this policy
  861. //
  862. // Notes:
  863. //
  864. //------------------------------------------------------------
  865. int CRedirectionPolicy::GetAncestorIndex()
  866. {
  867. return _iAncestorIndex;
  868. }
  869. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  870. //
  871. // Function: CRedirectionPolicy::HasAncestor
  872. //
  873. // Purpose: Indicates whether or not the folder redirected by
  874. // this policy has an ancestor folder
  875. //
  876. // Params: none
  877. //
  878. // Return value: TRUE if the folder redirected by this policy
  879. // has an ancestor, FALSE if not
  880. //
  881. // Notes:
  882. //
  883. //------------------------------------------------------------
  884. BOOL CRedirectionPolicy::HasAncestor()
  885. {
  886. return _bHasAncestor;
  887. }
  888. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  889. //
  890. // Function: CRedirectionPolicy::HasInheritedData
  891. //
  892. // Purpose: Indicates whether or not the folder redirected by
  893. // this policy should inherit data from its ancestor
  894. //
  895. // Params: none
  896. //
  897. // Return value: TRUE if the folder redirected by this policy
  898. // shoud inherit data from an ancestor, FALSE if not
  899. //
  900. // Notes:
  901. //
  902. //------------------------------------------------------------
  903. BOOL CRedirectionPolicy::HasInheritedData()
  904. {
  905. //
  906. // If the policy lists no groups / targat paths,
  907. //
  908. //
  909. return 0 != _cGroups;
  910. }
  911. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  912. //
  913. // Function: CRedirectionPolicy::NormalizePrecedence
  914. //
  915. // Purpose: Normalize precedence according the scale passed in
  916. //
  917. // Params:
  918. // lScale - indicates what value should be considered the
  919. // highest priority, and then priority is reversed based on this --
  920. // e.g. if 5 is the scale, an object with precedence 5
  921. // will become precedence 1 (the most important) when this
  922. // function is called. The object with precedence 1
  923. // will have value 5, the least significant, and intervening
  924. // values will behave accordingly
  925. //
  926. // Return value: none
  927. //
  928. // Notes:
  929. //
  930. //------------------------------------------------------------
  931. void CRedirectionPolicy::NormalizePrecedence( LONG Scale )
  932. {
  933. //
  934. // Reverse the precedence -- switch it from highest values
  935. // are most important to the reverse
  936. //
  937. _Precedence = Scale - _Precedence + 1;
  938. }
  939. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  940. //
  941. // Function: CRedirectionPolicy::IsRedirected()
  942. //
  943. // Purpose: Normalize precedence according the scale passed in
  944. //
  945. // Params:
  946. // none
  947. //
  948. // Return value: TRUE if the folder is currently
  949. // successfully redirected, FALSE if not
  950. //
  951. // Notes:
  952. //
  953. //------------------------------------------------------------
  954. BOOL CRedirectionPolicy::IsRedirected()
  955. {
  956. DWORD Status;
  957. //
  958. // Check the global state to see if this folder
  959. // has been successfully redirected
  960. //
  961. Status = gPolicyResultant[ _iFolderIndex ].m_StatusRedir;
  962. return ERROR_SUCCESS == Status;
  963. }
  964. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  965. //
  966. // Function: CPrecedenceState::CPrecedenceState
  967. //
  968. // Purpose: Constructor for CPrecedenceState class
  969. //
  970. // Params: none
  971. //
  972. // Return value: none
  973. //
  974. // Notes:
  975. //
  976. //------------------------------------------------------------
  977. CPrecedenceState::CPrecedenceState()
  978. {
  979. RtlZeroMemory(_rgFolderPrecedence, sizeof(_rgFolderPrecedence));
  980. }
  981. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  982. //
  983. // Function: CPrecedenceState::UpdateFolderPrecedence
  984. //
  985. // Purpose: Changes the precedence of the winning folder specified by
  986. // the index
  987. //
  988. // Params:
  989. // iFolder -- index of folder whose precedence we are updating
  990. //
  991. // Return value: returns the new precedence of the folder
  992. //
  993. // Notes:
  994. //
  995. //------------------------------------------------------------
  996. LONG CPrecedenceState::UpdateFolderPrecedence( int iFolder )
  997. {
  998. //
  999. // Increase the precedence of the winning folder
  1000. //
  1001. return ++ ( _rgFolderPrecedence[ iFolder ] );
  1002. }
  1003. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1004. //
  1005. // Function: CPrecedenceState::GetFolderPrecedence
  1006. //
  1007. // Purpose: Retrieves the precedence of the folder specified by
  1008. // the index
  1009. //
  1010. // Params:
  1011. // iFolder -- index of folder whose precedence we are
  1012. // retrieving
  1013. //
  1014. // Return value: returns the current precedence of the folder
  1015. //
  1016. // Notes:
  1017. //
  1018. //------------------------------------------------------------
  1019. LONG CPrecedenceState::GetFolderPrecedence( int iFolder )
  1020. {
  1021. return _rgFolderPrecedence[ iFolder ];
  1022. }
  1023. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1024. //
  1025. // Function: CRedirectionLog::AddRedirectionPolicies
  1026. //
  1027. // Purpose: Appends candidate policies to the list of
  1028. // redirection candidates
  1029. //
  1030. // Params:
  1031. // pGpoData -- pointer to information concerning the gpo
  1032. // from which the redirection candidate came
  1033. // pRedirectionInfo -- pointer to array candidate policies
  1034. // (one for each folder that can be redirected) to
  1035. // append to the list
  1036. //
  1037. // Return value: S_OK if successful, error otherwise
  1038. //
  1039. // Notes:
  1040. // IMPORTANT: this method is designed to be called
  1041. // multiple times and aggregate state across calls. The
  1042. // order in which calls occur is important -- each gpo
  1043. // passed in must be greater than the gpo passed
  1044. // in the previous call. Or put another way, this
  1045. // method should be called in order of least precedent gpo
  1046. // to most. This is necessary in order for the precedence
  1047. // calculations to be correct
  1048. //
  1049. //------------------------------------------------------------
  1050. HRESULT CRedirectionLog::AddRedirectionPolicies(
  1051. CFileDB* pGpoData,
  1052. CRedirectInfo* pRedirectionInfo)
  1053. {
  1054. DWORD iRedirect;
  1055. ASSERT( _pRsopContext->IsRsopEnabled() );
  1056. //
  1057. // For each folder that could be redirected, we'll check to see
  1058. // if it gets redirected, and add it to the list if so
  1059. //
  1060. for (iRedirect = 0 ; iRedirect < EndRedirectable; iRedirect++)
  1061. {
  1062. LONG Precedence;
  1063. CRedirectionPolicy* pNewRedirection;
  1064. //
  1065. // Check to see if this is redirected
  1066. //
  1067. if ( pRedirectionInfo[ iRedirect ].HasPolicy() )
  1068. {
  1069. HRESULT hr;
  1070. //
  1071. // Update the folder's precedence since we found a candidate
  1072. //
  1073. Precedence = _PrecedenceState.UpdateFolderPrecedence( iRedirect );
  1074. //
  1075. // Create an abstraction of the redirection candidate policy
  1076. //
  1077. pNewRedirection = new CRedirectionPolicy(
  1078. pGpoData,
  1079. &(pRedirectionInfo[iRedirect]),
  1080. Precedence,
  1081. &hr);
  1082. if ( ! pNewRedirection )
  1083. {
  1084. hr = E_OUTOFMEMORY;
  1085. }
  1086. if ( FAILED(hr) )
  1087. {
  1088. _pRsopContext->DisableRsop( hr );
  1089. return hr;
  1090. }
  1091. //
  1092. // Add it to the list of redirections
  1093. //
  1094. *_ppNextRedirection = pNewRedirection;
  1095. _ppNextRedirection = &(pNewRedirection->_pNext);
  1096. }
  1097. }
  1098. return S_OK;
  1099. }
  1100. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1101. //
  1102. // Function: CRedirectionLog::NormalizePrecedence
  1103. //
  1104. // Purpose: Normalize a redirection's precedence according
  1105. // to its relationship with redirections from other gpo's
  1106. //
  1107. // Params:
  1108. // pRedirectionPolicy -- redirection policy candidate to
  1109. // be normalized
  1110. //
  1111. // Return value: none
  1112. //
  1113. // Notes:
  1114. //
  1115. //------------------------------------------------------------
  1116. void CRedirectionLog::NormalizePrecedence( CRedirectionPolicy* pRedirectionPolicy )
  1117. {
  1118. int iFolder;
  1119. //
  1120. // Find the folder index for the redirected candidate
  1121. //
  1122. iFolder = pRedirectionPolicy->GetFolderIndex();
  1123. //
  1124. // Now use the winning precedence as the scale to normalize
  1125. // this candidate
  1126. //
  1127. pRedirectionPolicy->NormalizePrecedence(
  1128. _PrecedenceState.GetFolderPrecedence( iFolder ) );
  1129. }
  1130. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1131. //
  1132. // Function: CRedirectionLog::WriteRsopLog
  1133. //
  1134. // Purpose: Creates an rsop log of all the redirection information
  1135. // for the current user
  1136. //
  1137. // Params: none
  1138. //
  1139. // Return value: S_OK if successful, error otherwise
  1140. //
  1141. // Notes:
  1142. //
  1143. //------------------------------------------------------------
  1144. HRESULT CRedirectionLog::WriteRsopLog()
  1145. {
  1146. CRedirectionPolicy* pCurrent;
  1147. if ( ! _pRsopContext->IsRsopEnabled() )
  1148. {
  1149. return S_OK;
  1150. }
  1151. //
  1152. // Clear any existing log before writing out redirection results
  1153. //
  1154. ClearRsopLog();
  1155. //
  1156. // Iterate trhough the list of redirection candidates
  1157. //
  1158. for (pCurrent = _pRedirectionList;
  1159. pCurrent;
  1160. pCurrent = (CRedirectionPolicy*) pCurrent->_pNext)
  1161. {
  1162. //
  1163. // Normalize the precedence of this candidate with
  1164. // respect to other redirections
  1165. //
  1166. NormalizePrecedence( pCurrent );
  1167. //
  1168. // Add in any ancestral policy data
  1169. //
  1170. (void) AddAncestralPolicy( pCurrent );
  1171. //
  1172. // Write the record to the database
  1173. //
  1174. if ( pCurrent->IsRedirected() )
  1175. {
  1176. WriteNewRecord(pCurrent);
  1177. }
  1178. }
  1179. return S_OK;
  1180. }
  1181. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1182. //
  1183. // Function: CRedirectionLog::GetAncestor
  1184. //
  1185. // Purpose: returns the candidate redirection that is redirecting
  1186. // the folder that is the ancestor of the specified redirection
  1187. // candidate
  1188. //
  1189. // Params: pRedirectionPolicy -- redirection whose candidate
  1190. // redirection ancestor we wish to retrieve
  1191. //
  1192. // Return value: reference to redirection policy candidate
  1193. //
  1194. // Notes:
  1195. //
  1196. //------------------------------------------------------------
  1197. CRedirectionPolicy* CRedirectionLog::GetAncestor(
  1198. CRedirectionPolicy* pRedirectionPolicy )
  1199. {
  1200. int iFolder;
  1201. CRedirectionPolicy* pAncestor;
  1202. CRedirectionPolicy* pCurrent;
  1203. pAncestor = NULL;
  1204. //
  1205. // First, determine which folder is the ancestor of the
  1206. // specified redirection
  1207. //
  1208. iFolder = pRedirectionPolicy->GetAncestorIndex();
  1209. //
  1210. // Iterate trhough the list -- it is sorted, with
  1211. // the highest gpo last, and ancestors always
  1212. // appear before children -- we want to find the
  1213. // highest ancestor
  1214. //
  1215. for (pCurrent = _pRedirectionList;
  1216. pCurrent;
  1217. pCurrent = (CRedirectionPolicy*) pCurrent->_pNext)
  1218. {
  1219. //
  1220. // Remember the last ancestor we've seen
  1221. //
  1222. if ( iFolder == pCurrent->GetFolderIndex() )
  1223. {
  1224. pAncestor = pCurrent;
  1225. }
  1226. }
  1227. //
  1228. // Now return the ancestor that is currently highest
  1229. // without violating the gpo precedence of the child setting
  1230. //
  1231. return pAncestor;
  1232. }
  1233. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1234. //
  1235. // Function: CRedirectionLog::AddAncestralPolicy
  1236. //
  1237. // Purpose: causes a redirection candidate to inherit settings
  1238. // from an ancestor folder (if it has one) if inheritance
  1239. // is specified in the policy
  1240. //
  1241. // Params: pRedirectionPolicy -- redirection to which we want
  1242. // to which we want to add ancestor's policy settings
  1243. //
  1244. // Return value: S_OK if successful, error otherwise
  1245. //
  1246. // Notes:
  1247. //
  1248. //------------------------------------------------------------
  1249. HRESULT CRedirectionLog::AddAncestralPolicy( CRedirectionPolicy* pRedirectionPolicy)
  1250. {
  1251. HRESULT hr;
  1252. CRedirectionPolicy* pAncestorPolicy;
  1253. //
  1254. // See if this redirection has inherited data
  1255. //
  1256. if ( pRedirectionPolicy->HasInheritedData() )
  1257. {
  1258. return S_OK;
  1259. }
  1260. //
  1261. // If this policy doesn't have an ancestor, then we're done
  1262. //
  1263. if ( ! pRedirectionPolicy->HasAncestor() )
  1264. {
  1265. return S_OK;
  1266. }
  1267. //
  1268. // This policy has an ancestor -- retrieve it
  1269. //
  1270. pAncestorPolicy = GetAncestor( pRedirectionPolicy );
  1271. //
  1272. // Inherit settings from the ancestor
  1273. //
  1274. hr = pRedirectionPolicy->CopyInheritedData( pAncestorPolicy );
  1275. return hr;
  1276. }
  1277. HRESULT CRedirectionLog::AddPreservedPolicy( WCHAR* wszFolderName )
  1278. {
  1279. DWORD cchLen;
  1280. WCHAR* wszNewQuery;
  1281. if ( ! _pRsopContext->IsRsopEnabled() )
  1282. {
  1283. return S_OK;
  1284. }
  1285. cchLen = lstrlen( wszFolderName );
  1286. cchLen += sizeof( WQL_INSTANCE ) / sizeof( WCHAR ) +
  1287. sizeof( WQL_AND ) / sizeof( WCHAR );
  1288. if ( _wszDeletionQuery )
  1289. {
  1290. cchLen += lstrlen( _wszDeletionQuery );
  1291. }
  1292. wszNewQuery = new WCHAR [ cchLen ];
  1293. if ( ! wszNewQuery )
  1294. {
  1295. return E_OUTOFMEMORY;
  1296. }
  1297. if ( _wszDeletionQuery )
  1298. {
  1299. lstrcpy( wszNewQuery, _wszDeletionQuery );
  1300. lstrcat( wszNewQuery, WQL_AND );
  1301. }
  1302. else
  1303. {
  1304. *wszNewQuery = L'\0';
  1305. }
  1306. wsprintf( wszNewQuery + lstrlen( wszNewQuery ),
  1307. WQL_INSTANCE,
  1308. wszFolderName );
  1309. delete [] _wszDeletionQuery;
  1310. _wszDeletionQuery = wszNewQuery;
  1311. return S_OK;
  1312. }
  1313. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1314. //
  1315. // Function: CRedirectionLog::CRedirectionLog
  1316. //
  1317. // Purpose: constructor for class CRedirectionLog
  1318. //
  1319. // Params: none
  1320. //
  1321. // Return value: none
  1322. //
  1323. // Notes:
  1324. //
  1325. //------------------------------------------------------------
  1326. CRedirectionLog::CRedirectionLog() :
  1327. _pRedirectionList(NULL),
  1328. _ppNextRedirection(&_pRedirectionList),
  1329. _wszDeletionQuery( NULL )
  1330. {}
  1331. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1332. //
  1333. // Function: CRedirectionLog::~CRedirectionLog
  1334. //
  1335. // Purpose: destructor for class CRedirectionLog.
  1336. //
  1337. // Params: none
  1338. //
  1339. // Return value: none
  1340. //
  1341. // Notes:
  1342. //
  1343. //------------------------------------------------------------
  1344. CRedirectionLog::~CRedirectionLog()
  1345. {
  1346. CRedirectionPolicy* pCurrent;
  1347. CRedirectionPolicy* pNext;
  1348. for (pCurrent = _pRedirectionList;
  1349. pCurrent;
  1350. pCurrent = pNext)
  1351. {
  1352. pNext = (CRedirectionPolicy*) pCurrent->_pNext;
  1353. delete pCurrent;
  1354. }
  1355. delete [] _wszDeletionQuery;
  1356. }
  1357. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1358. //
  1359. // Function: CRedirectionLog::InitRsop
  1360. //
  1361. // Purpose: Initializes rsop logging
  1362. //
  1363. // Params: pRsopContext -- logging contxt
  1364. // bForceRsop -- TRUE if we should bind to a namespace
  1365. // in the absence of an existing namespace in this context
  1366. //
  1367. //
  1368. // Return value: none
  1369. //
  1370. // Notes:
  1371. //
  1372. // Success of initialization is stored internally -- rsop
  1373. // is disabled if there's a failure
  1374. //
  1375. //------------------------------------------------------------
  1376. void CRedirectionLog::InitRsop( CRsopContext* pRsopContext, BOOL bForceRsop )
  1377. {
  1378. HRESULT hr;
  1379. //
  1380. // If the caller needs us to bind to a saved namespace because
  1381. // the gp engine did not pass one in and we need to log new data,
  1382. // do so.
  1383. //
  1384. if ( bForceRsop )
  1385. {
  1386. (void) pRsopContext->InitializeSavedNameSpace();
  1387. }
  1388. //
  1389. // Initialize Rsop logging
  1390. //
  1391. hr = InitLog( pRsopContext, RSOP_REDIRECTED_FOLDER );
  1392. if (FAILED(hr))
  1393. {
  1394. pRsopContext->DisableRsop( hr );
  1395. return;
  1396. }
  1397. }
  1398. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1399. //
  1400. // Function: CRedirectionLog::ClearRsopLog
  1401. //
  1402. // Purpose: Clears the namespace of records
  1403. //
  1404. // Params: none
  1405. //
  1406. // Return value: none
  1407. //
  1408. // Notes:
  1409. //
  1410. //------------------------------------------------------------
  1411. void CRedirectionLog::ClearRsopLog()
  1412. {
  1413. HRESULT hr;
  1414. //
  1415. // Nothing to do if logging is not enabled
  1416. //
  1417. if (! _pRsopContext->IsRsopEnabled() )
  1418. {
  1419. return;
  1420. }
  1421. //
  1422. // Attempt to clear the log
  1423. //
  1424. hr = ClearLog( _wszDeletionQuery );
  1425. //
  1426. // If we cannot clear it, disable logging
  1427. //
  1428. if (FAILED(hr))
  1429. {
  1430. _pRsopContext->DisableRsop( hr );
  1431. }
  1432. }
  1433. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1434. //
  1435. // Function: StringDuplicate
  1436. //
  1437. // Purpose: Simple duplication of a c-string
  1438. //
  1439. // Params: wszOriginal -- string to be duplicated
  1440. //
  1441. // Return value: reference to allocated duplicate string if
  1442. // successful, NULL on failure
  1443. //
  1444. // Notes: returned string should be freed by caller with
  1445. // vector delete
  1446. //
  1447. //------------------------------------------------------------
  1448. WCHAR* StringDuplicate(WCHAR* wszOriginal)
  1449. {
  1450. WCHAR* wszNew;
  1451. DWORD cchSize;
  1452. ASSERT(wszOriginal);
  1453. //
  1454. // Determine original size
  1455. //
  1456. cchSize = lstrlen(wszOriginal) + 1;
  1457. //
  1458. // Allocate the space for the duplicate
  1459. //
  1460. wszNew = new WCHAR[ cchSize ];
  1461. //
  1462. // Duplicate to the new allocation if
  1463. // the allocation was successful
  1464. //
  1465. if (wszNew)
  1466. {
  1467. lstrcpy(wszNew, wszOriginal);
  1468. }
  1469. return wszNew;
  1470. }