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

1879 lines
49 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 ( ! _pGpoData->GetRsopContext()->IsReportingModeEnabled() )
  305. {
  306. if ( _wszRedirectedPath )
  307. {
  308. hr = SetValue(
  309. RDR_ATTRIBUTE_RESULT,
  310. _wszRedirectedPath);
  311. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_RESULT, hr )
  312. }
  313. }
  314. //
  315. // In the case of a child setting with a missing parent, none of the
  316. // other information can be logged, since it cannot be inferred
  317. // from the parent (there is none)
  318. //
  319. //
  320. // Access grant type
  321. //
  322. hr = SetValue(
  323. RDR_ATTRIBUTE_GRANTTYPE,
  324. ( ! _bMissingAncestor ) ? (BOOL) (_dwFlags & REDIR_SETACLS) : FALSE);
  325. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_GRANTTYPE, hr )
  326. //
  327. // Move Type
  328. //
  329. hr = SetValue(
  330. RDR_ATTRIBUTE_MOVETYPE,
  331. ( ! _bMissingAncestor ) ? (BOOL) (_dwFlags & REDIR_MOVE_CONTENTS) : FALSE);
  332. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_MOVETYPE, hr )
  333. WCHAR* wszDefaultGroup = EVERYONE_WELLKNOWN_SID;
  334. //
  335. // Redirecting group
  336. //
  337. if ( ! _pGpoData->GetRsopContext()->IsReportingModeEnabled() )
  338. {
  339. hr = SetValue(
  340. RDR_ATTRIBUTE_REDIRECTING_GROUP,
  341. ( ! _bMissingAncestor ) ? _RedirectedSid.Buffer : wszDefaultGroup );
  342. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_REDIRECTING_GROUP, hr )
  343. }
  344. //
  345. // List of security groups
  346. //
  347. hr = SetValue(
  348. RDR_ATTRIBUTE_GROUPS,
  349. ( ! _bMissingAncestor ) ? _rgwszGroups : &wszDefaultGroup,
  350. ( ! _bMissingAncestor ) ? _cGroups : 1);
  351. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_GROUPS, hr )
  352. //
  353. // In the case of a child setting with a missing parent, we must
  354. // generate the resultant path from local state since policy has
  355. // not redirected the parent
  356. //
  357. //
  358. // List of redirected paths parallel to the security group list
  359. //
  360. if ( ! _bMissingAncestor )
  361. {
  362. hr = SetValue(
  363. RDR_ATTRIBUTE_PATHS,
  364. _rgwszRedirectedPaths,
  365. _cGroups);
  366. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_PATHS, hr )
  367. }
  368. else if ( ! _pGpoData->GetRsopContext()->IsReportingModeEnabled() )
  369. {
  370. WCHAR* wszLocalInheritedPath;
  371. wszLocalInheritedPath = NULL;
  372. //
  373. // If this folder is set to follow its ancestor but no ancestor
  374. // was specified, we can still set the resulting path by
  375. // looking at the path to which we are redirected
  376. //
  377. hr = GenerateLocalInheritedPath(
  378. &wszLocalInheritedPath);
  379. if ( SUCCEEDED( hr ) )
  380. {
  381. hr = SetValue(
  382. RDR_ATTRIBUTE_RESULT,
  383. _rgwszGroups,
  384. _cGroups);
  385. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_RESULT, hr )
  386. hr = SetValue(
  387. RDR_ATTRIBUTE_PATHS,
  388. &wszLocalInheritedPath,
  389. 1);
  390. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_PATHS, hr )
  391. }
  392. }
  393. //
  394. // Policy Removal
  395. //
  396. hr = SetValue(
  397. RDR_ATTRIBUTE_POLICYREMOVAL,
  398. (_dwFlags & REDIR_RELOCATEONREMOVE) ?
  399. RDR_ATTRIBUTE_POLICYREMOVAL_VALUE_REDIRECT :
  400. RDR_ATTRIBUTE_POLICYREMOVAL_VALUE_REMAIN);
  401. REPORT_ATTRIBUTE_SET_STATUS( RDR_ATTRIBUTE_POLICYREMOVAL, hr )
  402. return S_OK;
  403. }
  404. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  405. //
  406. // Function: CRedirectionPolicy::GetGroupInformation
  407. //
  408. // Purpose: Gets gorup information from the redirection ini
  409. // file data concerning the list of security groups and
  410. // the redirected folder for each group
  411. //
  412. // Params: wszGroupRedirectionData -- this data was retrieved
  413. // from an ini file and contains group and folder lists
  414. //
  415. // Return value: S_OK if successful, error otherwise
  416. //
  417. // Notes:
  418. //
  419. //------------------------------------------------------------
  420. HRESULT CRedirectionPolicy::GetGroupInformation(
  421. WCHAR* wszGroupRedirectionData)
  422. {
  423. HRESULT hr;
  424. //
  425. // First, parse the file in order to count the groups. No
  426. // memory allocation is done when counting, so this should
  427. // always succeed
  428. //
  429. hr = ParseGroupInformation(
  430. wszGroupRedirectionData,
  431. &_cGroups);
  432. ASSERT(S_OK == hr);
  433. //
  434. // Allocate space for references to each group and folder
  435. // based on the count returned above
  436. //
  437. _rgwszGroups = new WCHAR* [_cGroups];
  438. _rgwszRedirectedPaths = new WCHAR* [_cGroups];
  439. if (!_rgwszGroups || !_rgwszRedirectedPaths)
  440. {
  441. return E_OUTOFMEMORY;
  442. }
  443. //
  444. // Initialize newly allocated references
  445. //
  446. RtlZeroMemory(_rgwszGroups, sizeof(*_rgwszGroups) * _cGroups);
  447. RtlZeroMemory(_rgwszRedirectedPaths, sizeof(*_rgwszRedirectedPaths) * _cGroups);
  448. //
  449. // Now perform the actual copy of parsed information. Note that this
  450. // will allocate space for strings for each folder and group and
  451. // set our vectors of references to refer to those strings. An out of
  452. // memory error could occur here, so we return any error we get
  453. //
  454. hr = ParseGroupInformation(
  455. wszGroupRedirectionData,
  456. &_cGroups,
  457. _rgwszGroups,
  458. _rgwszRedirectedPaths);
  459. return hr;
  460. }
  461. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  462. //
  463. // Function: CRedirectionPolicy::ParseGroupInformation
  464. //
  465. // Purpose: parses the redirection ini file data to retrieve
  466. // the list of security groups and the redirected folder for
  467. // each group
  468. //
  469. // Params:
  470. // wszGroupRedirectionData -- this data was retrieved
  471. // from an ini file and contains group and folder lists. IMPORTANT : This data
  472. // is distructive in the sence that the data is changed by this function.
  473. // pCount -- in, out param indicating # of groups / paths to retrieve.
  474. // on output, only has meaning if the folder and group arrays
  475. // are not specified -- in this case, it contains the count
  476. // of groups / paths so you can determine how many exist
  477. // before allocation.
  478. // rgwszGroups -- on input, contains an array of pointers
  479. // to c-strings. If NULL, only a count of groups / paths
  480. // is performed and there is no output.
  481. // On output, an allocation is made and data is copied
  482. // for each group. Each entry in the array
  483. // will be set to point to the appropriate allocated
  484. // string
  485. // rgwszPaths -- similar to above, except for target paths
  486. //
  487. // Return value: S_OK if successful, error otherwise
  488. //
  489. // Notes: IMPORTANT: rgwszGroups and rgwszPaths are parallel
  490. // arrays and should be accessed as such.
  491. // In the case of partial allocations below due to out of memory,
  492. // allocated memory is cleared by the destructor.
  493. // The basic algorithm for the parsing is taken from another location
  494. // in this extension -- if that changes, so must this.
  495. //
  496. // Current data format:
  497. //
  498. // <group-sid1>=<redirected-filesyspath1><String terminator \0>
  499. // <group-sid2>=<redirected-filesyspath2><String terminator \0>
  500. // <group-sid3>=<redirected-filesyspath3><String terminator \0><String terminator \0>
  501. // ...
  502. //
  503. //------------------------------------------------------------
  504. HRESULT CRedirectionPolicy::ParseGroupInformation(
  505. WCHAR* wszGroupRedirectionData,
  506. LONG* pCount,
  507. WCHAR** rgwszGroups,
  508. WCHAR** rgwszPaths)
  509. {
  510. WCHAR* wszCurrent;
  511. DWORD cchCurrent;
  512. DWORD cGroups;
  513. HRESULT hr;
  514. //
  515. // Init locals
  516. //
  517. cGroups = 0;
  518. hr = S_OK;
  519. //
  520. // First, find out how many paths there are, and separate
  521. // the path entry into its constituents
  522. //
  523. wszCurrent = wszGroupRedirectionData;
  524. if (wszCurrent)
  525. {
  526. //
  527. // Move through the data
  528. //
  529. for (wszCurrent;
  530. *wszCurrent;
  531. wszCurrent += cchCurrent)
  532. {
  533. WCHAR* wszPath;
  534. //
  535. // Find out the length of the current entry
  536. //
  537. cchCurrent = lstrlen(wszCurrent) + 1;
  538. //
  539. // Get the path so we can validate it
  540. //
  541. wszPath = wcschr(wszCurrent, L'=');
  542. //
  543. // If no path is specified, this is an invalid entry
  544. //
  545. if (!wszPath)
  546. {
  547. continue;
  548. }
  549. //
  550. // Terminate the pathname, but only if we're doing copying
  551. //
  552. if (rgwszGroups)
  553. {
  554. *wszPath = L'\0';
  555. }
  556. //
  557. // Advance to the path past the delimiter
  558. //
  559. wszPath++;
  560. //
  561. // A blank path -- skip this
  562. //
  563. if (!*wszPath)
  564. {
  565. continue;
  566. }
  567. //
  568. // If the group array is specified, we need to copy the
  569. // group and folder information, not just count groups / paths
  570. //
  571. if (rgwszGroups)
  572. {
  573. DWORD Status;
  574. //
  575. // Copy this group
  576. //
  577. rgwszGroups[cGroups] = StringDuplicate(wszCurrent);
  578. if ( ! rgwszGroups[cGroups] )
  579. {
  580. hr = E_OUTOFMEMORY;
  581. break;
  582. }
  583. //
  584. // Copy this path
  585. //
  586. Status = GetExpandedPath(
  587. _pGpoData,
  588. wszPath,
  589. _iFolderIndex,
  590. _bHasAncestor,
  591. &(rgwszPaths[cGroups]));
  592. //
  593. // In planning mode, we may get an empty string for a
  594. // path if an environment variable cannot be generated,
  595. // so we check for that case here and simulate the error
  596. //
  597. if ( _pGpoData->GetRsopContext()->IsPlanningModeEnabled() &&
  598. ( ERROR_SUCCESS == Status ) )
  599. {
  600. if ( ! *(rgwszPaths[cGroups]) )
  601. {
  602. gpEvents->Report(
  603. EVENT_FDEPLOY_FOLDER_EXPAND_FAIL,
  604. 2,
  605. _wszDisplayName,
  606. StatusToString ( ERROR_ENVVAR_NOT_FOUND )
  607. );
  608. _pGpoData->SimulatePlanningError( ERROR_ENVVAR_NOT_FOUND );
  609. }
  610. }
  611. if ( ERROR_SUCCESS != Status )
  612. {
  613. hr = HRESULT_FROM_WIN32( Status );
  614. break;
  615. }
  616. }
  617. cGroups++;
  618. }
  619. }
  620. //
  621. // Record the number of groups counted
  622. //
  623. *pCount = cGroups;
  624. return hr;
  625. }
  626. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  627. //
  628. // Function: CRedirectionPolicy::GenerateInheritedPath
  629. //
  630. // Purpose: Return the name of the path that results from
  631. // treating this folder as a subfolder of a specific path
  632. //
  633. // Params:
  634. // pwszAncestorPath -- in parameter indicating parent folder in
  635. // in which this folder should be placed
  636. //
  637. // ppwszInheritedPath -- out parameter for resulting path
  638. //
  639. // Return value: S_OK if successful, error otherwise
  640. //
  641. //------------------------------------------------------------
  642. HRESULT CRedirectionPolicy::GenerateInheritedPath(
  643. WCHAR* pwszAncestorPath,
  644. WCHAR** ppwszInheritedPath)
  645. {
  646. HRESULT hr;
  647. DWORD cchParent;
  648. DWORD cchRelative;
  649. size_t sizeInheritedPath;
  650. hr = E_OUTOFMEMORY;
  651. //
  652. // Construct the folder path by adding the relative path of this
  653. // child to its ancestor's path
  654. //
  655. //
  656. // First, determine the length of the path of this folder
  657. // relative to its ancestor's path -- this is just the
  658. // localized name of the folder
  659. //
  660. cchRelative = lstrlen( _wszLocalizedName );
  661. cchParent = lstrlen( pwszAncestorPath );
  662. sizeInheritedPath = cchParent + 1 + cchRelative + 1;
  663. *ppwszInheritedPath = new WCHAR[sizeInheritedPath];
  664. if ( *ppwszInheritedPath )
  665. {
  666. //
  667. // Now, copy the ancestor's path
  668. //
  669. (void) StringCchCopy( *ppwszInheritedPath, sizeInheritedPath, pwszAncestorPath );
  670. //
  671. // Add on the path separator if one does not already exist at the end of the ancestor path
  672. //
  673. if ( ( cchParent != 0 ) &&
  674. ( L'\\' != pwszAncestorPath[ cchParent - 1] ) )
  675. {
  676. (void) StringCchCat( *ppwszInheritedPath, sizeInheritedPath, L"\\" );
  677. }
  678. //
  679. // Now append this child's relative path to its ancestor
  680. //
  681. (void) StringCchCat( *ppwszInheritedPath, sizeInheritedPath, _wszLocalizedName );
  682. hr = S_OK;
  683. }
  684. return hr;
  685. }
  686. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  687. //
  688. // Function: CRedirectionPolicy::GenerateInheritedPath
  689. //
  690. // Purpose: Return the name of the path that results from
  691. // treating this folder as a subfolder of the path
  692. // to which this folder's parent is redirected
  693. //
  694. // Params:
  695. //
  696. // ppwszInheritedPath -- out parameter for resulting path
  697. //
  698. // Return value: S_OK if successful, error otherwise
  699. //
  700. //------------------------------------------------------------
  701. HRESULT CRedirectionPolicy::GenerateLocalInheritedPath(
  702. WCHAR** ppwszInheritedPath )
  703. {
  704. HRESULT hr;
  705. int iAncestor;
  706. CRedirectInfo* pAncestorInfo;
  707. WCHAR wszFolderKey [ TARGETPATHLIMIT ];
  708. WCHAR wszInheritedFolder [ TARGETPATHLIMIT ];
  709. hr = S_OK;
  710. iAncestor = GetAncestorIndex();
  711. pAncestorInfo = & ( gPolicyResultant[ iAncestor ] );
  712. hr = StringCchCopy( wszFolderKey, TARGETPATHLIMIT, pAncestorInfo->m_szFolderRelativePath );
  713. if ( FAILED(hr) )
  714. {
  715. return hr;
  716. }
  717. hr = StringCchCat( wszFolderKey, TARGETPATHLIMIT, L"\\" );
  718. if ( FAILED(hr) )
  719. {
  720. return hr;
  721. }
  722. if ( _pGpoData->GetRsopContext()->IsDiagnosticModeEnabled() )
  723. {
  724. DWORD Status;
  725. Status = _pGpoData->GetLocalFilePath(
  726. wszFolderKey,
  727. wszInheritedFolder);
  728. hr = HRESULT_FROM_WIN32( Status );
  729. }
  730. else
  731. {
  732. hr = StringCchCopy( wszInheritedFolder, TARGETPATHLIMIT, L"%USERPROFILE%\\" );
  733. if ( FAILED(hr) )
  734. {
  735. return hr;
  736. }
  737. hr = StringCchCat( wszInheritedFolder, TARGETPATHLIMIT, wszFolderKey );
  738. if ( FAILED(hr) )
  739. {
  740. return hr;
  741. }
  742. }
  743. if ( SUCCEEDED( hr ) )
  744. {
  745. hr = GenerateInheritedPath(
  746. wszInheritedFolder,
  747. ppwszInheritedPath);
  748. }
  749. return hr;
  750. }
  751. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  752. //
  753. // Function: CRedirectionPolicy::CopyInheritedData
  754. //
  755. // Purpose: Copies data that should be inherited from an ancestor
  756. // to the object
  757. //
  758. // Params:
  759. // pAncestralPolicy -- pointer to CRedirectionPolicy representing
  760. // the policy for the ancestor folder
  761. //
  762. // Return value: S_OK if successful, error otherwise.
  763. //
  764. // Notes:
  765. //
  766. // If a folder is set to inherit from its parent, the
  767. // following attributes must be copied from the parent:
  768. //
  769. // - Security Groups
  770. // - Redirection target paths
  771. // - The number of groups / paths
  772. // - Flags
  773. //
  774. // This method copies those attributes from an ancestor
  775. // to this object
  776. //
  777. //------------------------------------------------------------
  778. HRESULT CRedirectionPolicy::CopyInheritedData( CRedirectionPolicy* pAncestralPolicy )
  779. {
  780. LONG iGroup;
  781. LONG cGroups;
  782. HRESULT hr;
  783. //
  784. // If we have no ancestor, then the only ancestral information
  785. // we can copy is the redirected path
  786. //
  787. if ( ! pAncestralPolicy )
  788. {
  789. _bMissingAncestor = TRUE;
  790. hr = GenerateLocalInheritedPath(
  791. &_wszRedirectedPath);
  792. return hr;
  793. }
  794. //
  795. // Copy the redirecting group information first -- it
  796. // will only be there if the user would have gotten
  797. // this folder, so do not try to copy it if it is not there
  798. //
  799. if ( pAncestralPolicy->_RedirectedSid.Buffer )
  800. {
  801. BOOLEAN fAllocatedString;
  802. fAllocatedString = RtlCreateUnicodeString(
  803. &_RedirectedSid,
  804. pAncestralPolicy->_RedirectedSid.Buffer);
  805. if ( !fAllocatedString )
  806. {
  807. return E_OUTOFMEMORY;
  808. }
  809. RtlCopyUnicodeString(
  810. &_RedirectedSid,
  811. &(pAncestralPolicy->_RedirectedSid));
  812. hr = GenerateInheritedPath(
  813. pAncestralPolicy->_wszRedirectedPath,
  814. &_wszRedirectedPath);
  815. if ( FAILED(hr) )
  816. {
  817. return hr;
  818. }
  819. }
  820. //
  821. // Find out how many groups / paths there are
  822. //
  823. cGroups = pAncestralPolicy->_cGroups;
  824. iGroup = 0;
  825. _rgwszGroups = NULL;
  826. _rgwszRedirectedPaths = NULL;
  827. //
  828. // Allocate space for the security groups
  829. //
  830. _rgwszGroups = new WCHAR* [ cGroups ];
  831. hr = E_OUTOFMEMORY;
  832. if ( _rgwszGroups )
  833. {
  834. //
  835. // Now allocate space for the target paths
  836. //
  837. _rgwszRedirectedPaths = new WCHAR* [ cGroups ];
  838. if ( _rgwszRedirectedPaths )
  839. {
  840. hr = S_OK;
  841. //
  842. // Now allocate copies of each security group and
  843. // redirected target path
  844. //
  845. for ( iGroup = 0; iGroup < cGroups; iGroup ++ )
  846. {
  847. DWORD cchParent;
  848. //
  849. // Construct the folder path by adding the relative path of this
  850. // child to its ancestor's path
  851. //
  852. //
  853. // First, copy the ancestor's path
  854. //
  855. hr = GenerateInheritedPath(
  856. pAncestralPolicy->_rgwszRedirectedPaths[ iGroup ],
  857. &( _rgwszRedirectedPaths[ iGroup ] )
  858. );
  859. if ( FAILED( hr ) )
  860. {
  861. break;
  862. }
  863. //
  864. // Security group is much simpler -- just copy it
  865. //
  866. _rgwszGroups[ iGroup ] = StringDuplicate(
  867. pAncestralPolicy->_rgwszGroups[ iGroup ]);
  868. if ( ! _rgwszGroups[ iGroup ] )
  869. {
  870. // Clean up at least this iteration
  871. delete [] _rgwszRedirectedPaths[ iGroup ];
  872. hr = E_OUTOFMEMORY;
  873. break;
  874. }
  875. }
  876. }
  877. }
  878. //
  879. // Copy the flags
  880. //
  881. _dwFlags = pAncestralPolicy->_dwFlags;
  882. //
  883. // If we're successful, set the # of groups. We only set this on
  884. // success so that we don't write out an incomplete set
  885. //
  886. if ( SUCCEEDED( hr ) )
  887. {
  888. _cGroups = cGroups;
  889. }
  890. // Otherwise we must clean up any memory we used ...
  891. else
  892. {
  893. LONG iCleanupGroup;
  894. for ( iCleanupGroup = 0; iCleanupGroup < iGroup; iCleanupGroup++ )
  895. {
  896. delete [] _rgwszGroups[ iCleanupGroup ];
  897. delete [] _rgwszRedirectedPaths[ iCleanupGroup ];
  898. }
  899. delete [] _rgwszGroups;
  900. _rgwszGroups = NULL;
  901. delete [] _rgwszRedirectedPaths;
  902. _rgwszRedirectedPaths = NULL;
  903. _cGroups = 0;
  904. }
  905. return hr;
  906. }
  907. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  908. //
  909. // Function: CRedirectionPolicy::GetFolderIndex
  910. //
  911. // Purpose: Retrieves a numeric index representing the folder
  912. // (startup, mydocs, etc)
  913. //
  914. // Params: none
  915. //
  916. // Return value: index of the folder redirected by this policy
  917. //
  918. // Notes:
  919. //
  920. //------------------------------------------------------------
  921. int CRedirectionPolicy::GetFolderIndex()
  922. {
  923. return _iFolderIndex;
  924. }
  925. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  926. //
  927. // Function: CRedirectionPolicy::GetAncestorIndex
  928. //
  929. // Purpose: Retrieves a numeric index representing the ancestor
  930. // of this folder
  931. //
  932. // Params: none
  933. //
  934. // Return value: index of the ancestor of the folder redirected
  935. // by this policy
  936. //
  937. // Notes:
  938. //
  939. //------------------------------------------------------------
  940. int CRedirectionPolicy::GetAncestorIndex()
  941. {
  942. return _iAncestorIndex;
  943. }
  944. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  945. //
  946. // Function: CRedirectionPolicy::HasAncestor
  947. //
  948. // Purpose: Indicates whether or not the folder redirected by
  949. // this policy has an ancestor folder
  950. //
  951. // Params: none
  952. //
  953. // Return value: TRUE if the folder redirected by this policy
  954. // has an ancestor, FALSE if not
  955. //
  956. // Notes:
  957. //
  958. //------------------------------------------------------------
  959. BOOL CRedirectionPolicy::HasAncestor()
  960. {
  961. return _bHasAncestor;
  962. }
  963. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  964. //
  965. // Function: CRedirectionPolicy::HasInheritedData
  966. //
  967. // Purpose: Indicates whether or not the folder redirected by
  968. // this policy should inherit data from its ancestor
  969. //
  970. // Params: none
  971. //
  972. // Return value: TRUE if the folder redirected by this policy
  973. // should inherit data from an ancestor, FALSE if not
  974. //
  975. // Notes:
  976. //
  977. //------------------------------------------------------------
  978. BOOL CRedirectionPolicy::HasInheritedData()
  979. {
  980. //
  981. // If the policy lists no groups / target paths, then
  982. // it must obtain them from a parent
  983. //
  984. return 0 == _cGroups;
  985. }
  986. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  987. //
  988. // Function: CRedirectionPolicy::NormalizePrecedence
  989. //
  990. // Purpose: Normalize precedence according the scale passed in
  991. //
  992. // Params:
  993. // lScale - indicates what value should be considered the
  994. // highest priority, and then priority is reversed based on this --
  995. // e.g. if 5 is the scale, an object with precedence 5
  996. // will become precedence 1 (the most important) when this
  997. // function is called. The object with precedence 1
  998. // will have value 5, the least significant, and intervening
  999. // values will behave accordingly
  1000. //
  1001. // Return value: none
  1002. //
  1003. // Notes:
  1004. //
  1005. //------------------------------------------------------------
  1006. void CRedirectionPolicy::NormalizePrecedence( LONG Scale )
  1007. {
  1008. //
  1009. // Reverse the precedence -- switch it from highest values
  1010. // are most important to the reverse
  1011. //
  1012. _Precedence = Scale - _Precedence + 1;
  1013. }
  1014. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1015. //
  1016. // Function: CRedirectionPolicy::IsRedirected()
  1017. //
  1018. // Purpose: Normalize precedence according the scale passed in
  1019. //
  1020. // Params:
  1021. // none
  1022. //
  1023. // Return value: TRUE if the folder is currently
  1024. // successfully redirected, FALSE if not
  1025. //
  1026. // Notes:
  1027. //
  1028. //------------------------------------------------------------
  1029. BOOL CRedirectionPolicy::IsRedirected()
  1030. {
  1031. DWORD Status;
  1032. //
  1033. // Check the global state to see if this folder
  1034. // has been successfully redirected
  1035. //
  1036. Status = gPolicyResultant[ _iFolderIndex ].m_StatusRedir;
  1037. return ERROR_SUCCESS == Status;
  1038. }
  1039. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1040. //
  1041. // Function: CPrecedenceState::CPrecedenceState
  1042. //
  1043. // Purpose: Constructor for CPrecedenceState class
  1044. //
  1045. // Params: none
  1046. //
  1047. // Return value: none
  1048. //
  1049. // Notes:
  1050. //
  1051. //------------------------------------------------------------
  1052. CPrecedenceState::CPrecedenceState()
  1053. {
  1054. RtlZeroMemory(_rgFolderPrecedence, sizeof(_rgFolderPrecedence));
  1055. }
  1056. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1057. //
  1058. // Function: CPrecedenceState::UpdateFolderPrecedence
  1059. //
  1060. // Purpose: Changes the precedence of the winning folder specified by
  1061. // the index
  1062. //
  1063. // Params:
  1064. // iFolder -- index of folder whose precedence we are updating
  1065. //
  1066. // Return value: returns the new precedence of the folder
  1067. //
  1068. // Notes:
  1069. //
  1070. //------------------------------------------------------------
  1071. LONG CPrecedenceState::UpdateFolderPrecedence( int iFolder )
  1072. {
  1073. //
  1074. // Increase the precedence of the winning folder
  1075. //
  1076. return ++ ( _rgFolderPrecedence[ iFolder ] );
  1077. }
  1078. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1079. //
  1080. // Function: CPrecedenceState::GetFolderPrecedence
  1081. //
  1082. // Purpose: Retrieves the precedence of the folder specified by
  1083. // the index
  1084. //
  1085. // Params:
  1086. // iFolder -- index of folder whose precedence we are
  1087. // retrieving
  1088. //
  1089. // Return value: returns the current precedence of the folder
  1090. //
  1091. // Notes:
  1092. //
  1093. //------------------------------------------------------------
  1094. LONG CPrecedenceState::GetFolderPrecedence( int iFolder )
  1095. {
  1096. return _rgFolderPrecedence[ iFolder ];
  1097. }
  1098. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1099. //
  1100. // Function: CRedirectionLog::AddRedirectionPolicies
  1101. //
  1102. // Purpose: Appends candidate policies to the list of
  1103. // redirection candidates
  1104. //
  1105. // Params:
  1106. // pGpoData -- pointer to information concerning the gpo
  1107. // from which the redirection candidate came
  1108. // pRedirectionInfo -- pointer to array candidate policies
  1109. // (one for each folder that can be redirected) to
  1110. // append to the list
  1111. //
  1112. // Return value: S_OK if successful, error otherwise
  1113. //
  1114. // Notes:
  1115. // IMPORTANT: this method is designed to be called
  1116. // multiple times and aggregate state across calls. The
  1117. // order in which calls occur is important -- each gpo
  1118. // passed in must be greater than the gpo passed
  1119. // in the previous call. Or put another way, this
  1120. // method should be called in order of least precedent gpo
  1121. // to most. This is necessary in order for the precedence
  1122. // calculations to be correct
  1123. //
  1124. //------------------------------------------------------------
  1125. HRESULT CRedirectionLog::AddRedirectionPolicies(
  1126. CFileDB* pGpoData,
  1127. CRedirectInfo* pRedirectionInfo)
  1128. {
  1129. DWORD iRedirect;
  1130. ASSERT( _pRsopContext->IsRsopEnabled() );
  1131. //
  1132. // For each folder that could be redirected, we'll check to see
  1133. // if it gets redirected, and add it to the list if so
  1134. //
  1135. for (iRedirect = 0 ; iRedirect < EndRedirectable; iRedirect++)
  1136. {
  1137. LONG Precedence;
  1138. CRedirectionPolicy* pNewRedirection;
  1139. //
  1140. // Check to see if this is redirected
  1141. //
  1142. if ( pRedirectionInfo[ iRedirect ].HasPolicy() )
  1143. {
  1144. HRESULT hr;
  1145. //
  1146. // We do not support the Programs and Startup folders --
  1147. // we used to and the core code continues to include
  1148. // them in its data structures. We should ignore these folders
  1149. // if we see them
  1150. //
  1151. if ( ( Programs == pRedirectionInfo[ iRedirect ].GetFolderID() ) ||
  1152. ( Startup == pRedirectionInfo[ iRedirect ].GetFolderID() ) )
  1153. {
  1154. continue;
  1155. }
  1156. //
  1157. // Update the folder's precedence since we found a candidate
  1158. //
  1159. Precedence = _PrecedenceState.UpdateFolderPrecedence( iRedirect );
  1160. //
  1161. // Create an abstraction of the redirection candidate policy
  1162. //
  1163. pNewRedirection = new CRedirectionPolicy(
  1164. pGpoData,
  1165. &(pRedirectionInfo[iRedirect]),
  1166. Precedence,
  1167. &hr);
  1168. if ( ! pNewRedirection )
  1169. {
  1170. hr = E_OUTOFMEMORY;
  1171. }
  1172. if ( FAILED(hr) )
  1173. {
  1174. _pRsopContext->DisableRsop( hr );
  1175. return hr;
  1176. }
  1177. //
  1178. // Add it to the list of redirections
  1179. //
  1180. *_ppNextRedirection = pNewRedirection;
  1181. _ppNextRedirection = &(pNewRedirection->_pNext);
  1182. }
  1183. }
  1184. return S_OK;
  1185. }
  1186. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1187. //
  1188. // Function: CRedirectionLog::NormalizePrecedence
  1189. //
  1190. // Purpose: Normalize a redirection's precedence according
  1191. // to its relationship with redirections from other gpo's
  1192. //
  1193. // Params:
  1194. // pRedirectionPolicy -- redirection policy candidate to
  1195. // be normalized
  1196. //
  1197. // Return value: none
  1198. //
  1199. // Notes:
  1200. //
  1201. //------------------------------------------------------------
  1202. void CRedirectionLog::NormalizePrecedence( CRedirectionPolicy* pRedirectionPolicy )
  1203. {
  1204. int iFolder;
  1205. //
  1206. // Find the folder index for the redirected candidate
  1207. //
  1208. iFolder = pRedirectionPolicy->GetFolderIndex();
  1209. //
  1210. // Now use the winning precedence as the scale to normalize
  1211. // this candidate
  1212. //
  1213. pRedirectionPolicy->NormalizePrecedence(
  1214. _PrecedenceState.GetFolderPrecedence( iFolder ) );
  1215. }
  1216. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1217. //
  1218. // Function: CRedirectionLog::WriteRsopLog
  1219. //
  1220. // Purpose: Creates an rsop log of all the redirection information
  1221. // for the current user
  1222. //
  1223. // Params: none
  1224. //
  1225. // Return value: S_OK if successful, error otherwise
  1226. //
  1227. // Notes:
  1228. //
  1229. //------------------------------------------------------------
  1230. HRESULT CRedirectionLog::WriteRsopLog()
  1231. {
  1232. CRedirectionPolicy* pCurrent;
  1233. if ( ! _pRsopContext->IsRsopEnabled() )
  1234. {
  1235. return S_OK;
  1236. }
  1237. //
  1238. // Clear any existing log before writing out redirection results
  1239. //
  1240. ClearRsopLog();
  1241. //
  1242. // Iterate through the list of redirection candidates
  1243. //
  1244. for (pCurrent = _pRedirectionList;
  1245. pCurrent;
  1246. pCurrent = (CRedirectionPolicy*) pCurrent->_pNext)
  1247. {
  1248. //
  1249. // Normalize the precedence of this candidate with
  1250. // respect to other redirections
  1251. //
  1252. NormalizePrecedence( pCurrent );
  1253. //
  1254. // Add in any ancestral policy data
  1255. //
  1256. (void) AddAncestralPolicy( pCurrent );
  1257. //
  1258. // Write the record to the database
  1259. //
  1260. if ( pCurrent->IsRedirected() )
  1261. {
  1262. WriteNewRecord(pCurrent);
  1263. }
  1264. }
  1265. return S_OK;
  1266. }
  1267. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1268. //
  1269. // Function: CRedirectionLog::GetAncestor
  1270. //
  1271. // Purpose: returns the candidate redirection that is redirecting
  1272. // the folder that is the ancestor of the specified redirection
  1273. // candidate
  1274. //
  1275. // Params: pRedirectionPolicy -- redirection whose candidate
  1276. // redirection ancestor we wish to retrieve
  1277. //
  1278. // Return value: reference to redirection policy candidate
  1279. //
  1280. // Notes:
  1281. //
  1282. //------------------------------------------------------------
  1283. CRedirectionPolicy* CRedirectionLog::GetAncestor(
  1284. CRedirectionPolicy* pRedirectionPolicy )
  1285. {
  1286. int iFolder;
  1287. CRedirectionPolicy* pAncestor;
  1288. CRedirectionPolicy* pCurrent;
  1289. pAncestor = NULL;
  1290. //
  1291. // First, determine which folder is the ancestor of the
  1292. // specified redirection
  1293. //
  1294. iFolder = pRedirectionPolicy->GetAncestorIndex();
  1295. //
  1296. // Iterate trhough the list -- it is sorted, with
  1297. // the highest gpo last, and ancestors always
  1298. // appear before children -- we want to find the
  1299. // highest ancestor
  1300. //
  1301. for (pCurrent = _pRedirectionList;
  1302. pCurrent;
  1303. pCurrent = (CRedirectionPolicy*) pCurrent->_pNext)
  1304. {
  1305. //
  1306. // Remember the last ancestor we've seen
  1307. //
  1308. if ( iFolder == pCurrent->GetFolderIndex() )
  1309. {
  1310. pAncestor = pCurrent;
  1311. }
  1312. }
  1313. //
  1314. // Now return the ancestor that is currently highest
  1315. // without violating the gpo precedence of the child setting
  1316. //
  1317. return pAncestor;
  1318. }
  1319. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1320. //
  1321. // Function: CRedirectionLog::AddAncestralPolicy
  1322. //
  1323. // Purpose: causes a redirection candidate to inherit settings
  1324. // from an ancestor folder (if it has one) if inheritance
  1325. // is specified in the policy
  1326. //
  1327. // Params: pRedirectionPolicy -- redirection to which we want
  1328. // to which we want to add ancestor's policy settings
  1329. //
  1330. // Return value: S_OK if successful, error otherwise
  1331. //
  1332. // Notes:
  1333. //
  1334. //------------------------------------------------------------
  1335. HRESULT CRedirectionLog::AddAncestralPolicy( CRedirectionPolicy* pRedirectionPolicy)
  1336. {
  1337. HRESULT hr;
  1338. CRedirectionPolicy* pAncestorPolicy;
  1339. //
  1340. // See if this redirection has inherited data
  1341. //
  1342. if ( ! pRedirectionPolicy->HasInheritedData() )
  1343. {
  1344. return S_OK;
  1345. }
  1346. //
  1347. // If this policy doesn't have an ancestor, then we're done
  1348. //
  1349. if ( ! pRedirectionPolicy->HasAncestor() )
  1350. {
  1351. return S_OK;
  1352. }
  1353. //
  1354. // This policy has an ancestor -- retrieve it
  1355. //
  1356. pAncestorPolicy = GetAncestor( pRedirectionPolicy );
  1357. //
  1358. // Inherit settings from the ancestor
  1359. //
  1360. hr = pRedirectionPolicy->CopyInheritedData( pAncestorPolicy );
  1361. return hr;
  1362. }
  1363. HRESULT CRedirectionLog::AddPreservedPolicy( WCHAR* wszFolderName )
  1364. {
  1365. DWORD cchLen;
  1366. WCHAR* wszNewQuery;
  1367. HRESULT hr = S_OK;
  1368. if ( ! _pRsopContext->IsRsopEnabled() )
  1369. {
  1370. return S_OK;
  1371. }
  1372. cchLen = lstrlen( wszFolderName );
  1373. cchLen += sizeof( WQL_INSTANCE ) / sizeof( WCHAR ) +
  1374. sizeof( WQL_AND ) / sizeof( WCHAR );
  1375. if ( _wszDeletionQuery )
  1376. {
  1377. cchLen += lstrlen( _wszDeletionQuery );
  1378. }
  1379. wszNewQuery = new WCHAR [ cchLen ];
  1380. if ( ! wszNewQuery )
  1381. {
  1382. return E_OUTOFMEMORY;
  1383. }
  1384. if ( _wszDeletionQuery )
  1385. {
  1386. (void) StringCchCopy( wszNewQuery, cchLen, _wszDeletionQuery );
  1387. (void) StringCchCat( wszNewQuery, cchLen, WQL_AND );
  1388. }
  1389. else
  1390. {
  1391. *wszNewQuery = L'\0';
  1392. }
  1393. hr = StringCchPrintf( wszNewQuery + lstrlen( wszNewQuery ),
  1394. cchLen - lstrlen( wszNewQuery ),
  1395. WQL_INSTANCE,
  1396. wszFolderName );
  1397. if ( SUCCEEDED(hr) )
  1398. {
  1399. delete [] _wszDeletionQuery;
  1400. _wszDeletionQuery = wszNewQuery;
  1401. }
  1402. else
  1403. {
  1404. delete [] wszNewQuery;
  1405. }
  1406. return hr;
  1407. }
  1408. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1409. //
  1410. // Function: CRedirectionLog::CRedirectionLog
  1411. //
  1412. // Purpose: constructor for class CRedirectionLog
  1413. //
  1414. // Params: none
  1415. //
  1416. // Return value: none
  1417. //
  1418. // Notes:
  1419. //
  1420. //------------------------------------------------------------
  1421. CRedirectionLog::CRedirectionLog() :
  1422. _pRedirectionList(NULL),
  1423. _ppNextRedirection(&_pRedirectionList),
  1424. _wszDeletionQuery( NULL ),
  1425. _SimulatedStatus( ERROR_SUCCESS )
  1426. {}
  1427. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1428. //
  1429. // Function: CRedirectionLog::~CRedirectionLog
  1430. //
  1431. // Purpose: destructor for class CRedirectionLog.
  1432. //
  1433. // Params: none
  1434. //
  1435. // Return value: none
  1436. //
  1437. // Notes:
  1438. //
  1439. //------------------------------------------------------------
  1440. CRedirectionLog::~CRedirectionLog()
  1441. {
  1442. CRedirectionPolicy* pCurrent;
  1443. CRedirectionPolicy* pNext;
  1444. for (pCurrent = _pRedirectionList;
  1445. pCurrent;
  1446. pCurrent = pNext)
  1447. {
  1448. pNext = (CRedirectionPolicy*) pCurrent->_pNext;
  1449. delete pCurrent;
  1450. }
  1451. delete [] _wszDeletionQuery;
  1452. }
  1453. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1454. //
  1455. // Function: CRedirectionLog::InitRsop
  1456. //
  1457. // Purpose: Initializes rsop logging
  1458. //
  1459. // Params: pRsopContext -- logging contxt
  1460. // bForceRsop -- TRUE if we should bind to a namespace
  1461. // in the absence of an existing namespace in this context
  1462. //
  1463. //
  1464. // Return value: none
  1465. //
  1466. // Notes:
  1467. //
  1468. // Success of initialization is stored internally -- rsop
  1469. // is disabled if there's a failure
  1470. //
  1471. //------------------------------------------------------------
  1472. void CRedirectionLog::InitRsop( CRsopContext* pRsopContext, BOOL bForceRsop )
  1473. {
  1474. HRESULT hr;
  1475. //
  1476. // If the caller needs us to bind to a saved namespace because
  1477. // the gp engine did not pass one in and we need to log new data,
  1478. // do so.
  1479. //
  1480. if ( bForceRsop )
  1481. {
  1482. (void) pRsopContext->InitializeSavedNameSpace();
  1483. }
  1484. //
  1485. // Initialize Rsop logging
  1486. //
  1487. hr = InitLog( pRsopContext, RSOP_REDIRECTED_FOLDER );
  1488. if (FAILED(hr))
  1489. {
  1490. pRsopContext->DisableRsop( hr );
  1491. return;
  1492. }
  1493. }
  1494. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1495. //
  1496. // Function: CRedirectionLog::ClearRsopLog
  1497. //
  1498. // Purpose: Clears the namespace of records
  1499. //
  1500. // Params: none
  1501. //
  1502. // Return value: none
  1503. //
  1504. // Notes:
  1505. //
  1506. //------------------------------------------------------------
  1507. void CRedirectionLog::ClearRsopLog()
  1508. {
  1509. HRESULT hr;
  1510. //
  1511. // Nothing to do if logging is not enabled
  1512. //
  1513. if (! _pRsopContext->IsRsopEnabled() )
  1514. {
  1515. return;
  1516. }
  1517. //
  1518. // Attempt to clear the log
  1519. //
  1520. hr = ClearLog( _wszDeletionQuery );
  1521. //
  1522. // If we cannot clear it, disable logging
  1523. //
  1524. if (FAILED(hr))
  1525. {
  1526. _pRsopContext->DisableRsop( hr );
  1527. }
  1528. }
  1529. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1530. //
  1531. // Function: CRedirectionLog::SimluatePlanningError
  1532. //
  1533. // Purpose: During planning mode, we may be able to detect
  1534. // a situation that would result in an error
  1535. // if policy application were attempted on a real client --
  1536. // this function simulates a specific Win32 error
  1537. //
  1538. // Params: Status
  1539. //
  1540. // Return value: none
  1541. //
  1542. // Notes:
  1543. //
  1544. //------------------------------------------------------------
  1545. void CRedirectionLog::SimulatePlanningError( DWORD Status )
  1546. {
  1547. if ( ERROR_SUCCESS == _SimulatedStatus )
  1548. {
  1549. _SimulatedStatus = Status;
  1550. }
  1551. }
  1552. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1553. //
  1554. // Function: CRedirectionLog::GetPlanningSimulatedErrorIfNecessary
  1555. //
  1556. // Purpose: During planning mode, we may be able to detect
  1557. // a situation that would result in an error
  1558. // if policy application were attempted on a real client --
  1559. // this function retrieves such a simulated error, but
  1560. // only if it does not "override" the Status code
  1561. // passed in
  1562. //
  1563. // Params: Status
  1564. //
  1565. // Return value: The error status with the highest precedence
  1566. //
  1567. // Notes:
  1568. //
  1569. //------------------------------------------------------------
  1570. DWORD CRedirectionLog::GetPlanningSimulatedErrorIfNecessary( DWORD Status )
  1571. {
  1572. DWORD PreferredStatus;
  1573. PreferredStatus = Status;
  1574. if ( ERROR_SUCCESS == Status )
  1575. {
  1576. PreferredStatus = _SimulatedStatus;
  1577. }
  1578. return PreferredStatus;
  1579. }
  1580. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1581. //
  1582. // Function: StringDuplicate
  1583. //
  1584. // Purpose: Simple duplication of a c-string
  1585. //
  1586. // Params: wszOriginal -- string to be duplicated
  1587. //
  1588. // Return value: reference to allocated duplicate string if
  1589. // successful, NULL on failure
  1590. //
  1591. // Notes: returned string should be freed by caller with
  1592. // vector delete
  1593. //
  1594. //------------------------------------------------------------
  1595. WCHAR* StringDuplicate(WCHAR* wszOriginal)
  1596. {
  1597. WCHAR* wszNew;
  1598. DWORD cchSize;
  1599. ASSERT(wszOriginal);
  1600. //
  1601. // Determine original size
  1602. //
  1603. cchSize = lstrlen(wszOriginal) + 1;
  1604. //
  1605. // Allocate the space for the duplicate
  1606. //
  1607. wszNew = new WCHAR[ cchSize ];
  1608. //
  1609. // Duplicate to the new allocation if
  1610. // the allocation was successful
  1611. //
  1612. if (wszNew)
  1613. {
  1614. (void) StringCchCopy(wszNew, cchSize, wszOriginal);
  1615. }
  1616. return wszNew;
  1617. }