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.

733 lines
15 KiB

  1. //*************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation 1999 - 2000
  4. // All rights reserved
  5. //
  6. // context.cxx
  7. //
  8. //*************************************************************
  9. #include "rsop.hxx"
  10. #include <strsafe.h>
  11. CRsopContext::CRsopContext(
  12. PRSOP_TARGET pRsopTarget,
  13. BOOL bReportingMode,
  14. WCHAR* wszExtensionGuid
  15. ) :
  16. _pWbemServices( pRsopTarget->pWbemServices ),
  17. _wszNameSpace( NULL ),
  18. _pRsopTarget( pRsopTarget ),
  19. _bEnabled( TRUE ),
  20. _dwMode( bReportingMode ? MODE_REPORTING : MODE_PLANNING ),
  21. _phrLoggingStatus ( NULL ),
  22. _hPolicyAccess( NULL ),
  23. _wszExtensionGuid( wszExtensionGuid ),
  24. _hkRsop( NULL )
  25. {
  26. _pWbemServices->AddRef();
  27. }
  28. CRsopContext::CRsopContext(
  29. IWbemServices* pWbemServices,
  30. HRESULT* phrLoggingStatus,
  31. WCHAR* wszExtensionGuid
  32. ) :
  33. _pWbemServices( pWbemServices ),
  34. _wszNameSpace( NULL ),
  35. _pRsopTarget( NULL ),
  36. _bEnabled( pWbemServices != NULL ),
  37. _dwMode( MODE_DIAGNOSTIC ),
  38. _phrLoggingStatus ( phrLoggingStatus ),
  39. _hPolicyAccess( NULL ),
  40. _wszExtensionGuid( wszExtensionGuid ),
  41. _hkRsop( NULL )
  42. {
  43. if ( _bEnabled )
  44. {
  45. _pWbemServices->AddRef();
  46. }
  47. }
  48. CRsopContext::CRsopContext(
  49. WCHAR* wszExtensionGuid
  50. ) :
  51. _pWbemServices( NULL ),
  52. _wszNameSpace( NULL ),
  53. _pRsopTarget( NULL ),
  54. _bEnabled( FALSE ),
  55. _dwMode( MODE_DIAGNOSTIC ),
  56. _phrLoggingStatus ( NULL ),
  57. _hPolicyAccess( NULL ),
  58. _wszExtensionGuid( wszExtensionGuid ),
  59. _hkRsop( NULL )
  60. {}
  61. CRsopContext::~CRsopContext()
  62. {
  63. ASSERT( ! _hPolicyAccess );
  64. //
  65. // Set the final logging status
  66. //
  67. if ( _bEnabled && _phrLoggingStatus )
  68. {
  69. *_phrLoggingStatus = S_OK;
  70. }
  71. if ( _pWbemServices )
  72. {
  73. _pWbemServices->Release();
  74. }
  75. delete [] _wszNameSpace;
  76. if ( _hkRsop )
  77. {
  78. RegCloseKey( _hkRsop );
  79. }
  80. }
  81. BOOL CRsopContext::IsRsopEnabled()
  82. {
  83. return _bEnabled;
  84. }
  85. BOOL CRsopContext::IsPlanningModeEnabled()
  86. {
  87. return ( _dwMode == MODE_PLANNING ) || ( _dwMode == MODE_REPORTING );
  88. }
  89. BOOL CRsopContext::IsDiagnosticModeEnabled()
  90. {
  91. return _dwMode == MODE_DIAGNOSTIC;
  92. }
  93. BOOL CRsopContext::IsReportingModeEnabled()
  94. {
  95. return ( _dwMode == MODE_REPORTING );
  96. }
  97. HRESULT CRsopContext::GetRsopStatus()
  98. {
  99. HRESULT hr;
  100. hr = S_OK;
  101. if ( _phrLoggingStatus )
  102. {
  103. hr = *_phrLoggingStatus;
  104. }
  105. return hr;
  106. }
  107. void CRsopContext::SetNameSpace ( WCHAR* wszNameSpace )
  108. {
  109. _wszNameSpace = wszNameSpace;
  110. if ( _wszNameSpace )
  111. {
  112. EnableRsop();
  113. }
  114. }
  115. void CRsopContext::EnableRsop()
  116. {
  117. _bEnabled = (NULL != _pWbemServices) ||
  118. ( NULL != _wszNameSpace );
  119. }
  120. void CRsopContext::DisableRsop( HRESULT hrReason )
  121. {
  122. if ( _bEnabled && _phrLoggingStatus )
  123. {
  124. *_phrLoggingStatus = hrReason;
  125. }
  126. _bEnabled = FALSE;
  127. }
  128. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  129. //
  130. // Function: CRsopContext::Bind
  131. //
  132. // Purpose: Bind to a policy database and return an interface
  133. // for the user or machine namespace
  134. //
  135. // Params:
  136. //
  137. //
  138. // Return value: S_OK if successful, S_FALSE if already init'd,
  139. // other facility error if, the function fails.
  140. //
  141. // Notes:
  142. //
  143. //------------------------------------------------------------
  144. HRESULT CRsopContext::Bind( IWbemServices** ppWbemServices )
  145. {
  146. HRESULT hr;
  147. ASSERT ( _bEnabled );
  148. hr = S_OK;
  149. //
  150. // Only bind to the database if we don't already have an interface
  151. //
  152. if ( ! _pWbemServices )
  153. {
  154. //
  155. // If we don't have one, we'll have to bind
  156. // using the namespace path
  157. //
  158. hr = _PolicyDatabase.Bind(
  159. _wszNameSpace,
  160. &_pWbemServices);
  161. }
  162. //
  163. // If we already have an interface, return that
  164. //
  165. if ( _pWbemServices )
  166. {
  167. *ppWbemServices = _pWbemServices;
  168. hr = S_FALSE;
  169. }
  170. if ( FAILED(hr) )
  171. {
  172. DisableRsop( hr );
  173. }
  174. return hr;
  175. }
  176. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  177. //
  178. // Function: CRsopContext::GetNameSpace
  179. //
  180. // Purpose: Gets the namespace to which this context is bound
  181. //
  182. // Params: ppwszNameSpace -- out parameter that will point
  183. // to the address of a string that has the namespace --
  184. // this memory should be freed by the caller
  185. //
  186. // Return S_OK if success, error otherwise
  187. //
  188. // Notes:
  189. //
  190. //------------------------------------------------------------
  191. HRESULT CRsopContext::GetNameSpace( WCHAR** ppwszNameSpace )
  192. {
  193. LPWSTR wszNamespaceEnd;
  194. LPWSTR wszNameSpace;
  195. CVariant var;
  196. IWbemClassObject* pWbemClassObject;
  197. XBStr xbstrPath( L"__PATH" );
  198. XBStr xbstrClass( RSOP_POLICY_SETTING );
  199. if ( ! xbstrPath || ! xbstrClass )
  200. {
  201. return E_OUTOFMEMORY;
  202. }
  203. HRESULT hr;
  204. pWbemClassObject = NULL;
  205. //
  206. // Get the class
  207. //
  208. hr = _pWbemServices->GetObject(
  209. xbstrClass,
  210. 0L,
  211. NULL,
  212. &pWbemClassObject,
  213. NULL );
  214. if ( SUCCEEDED( hr ) )
  215. {
  216. //
  217. // Read the path property of the class from the class object
  218. //
  219. hr = pWbemClassObject->Get(
  220. xbstrPath,
  221. 0L,
  222. (VARIANT*) &var,
  223. NULL,
  224. NULL);
  225. pWbemClassObject->Release();
  226. }
  227. //
  228. // Now parse the path to obtain the parent namespace of
  229. // the class, which is the namespace in which the
  230. // IWbemServices pointer resides
  231. //
  232. //
  233. // Find the end of the class name so we can null-terminate it
  234. //
  235. if ( SUCCEEDED( hr ) )
  236. {
  237. //
  238. // Look for the delimiter that terminates the class name
  239. //
  240. wszNamespaceEnd = wcschr( ((VARIANT*) &var)->bstrVal, L':' );
  241. //
  242. // If we found the delimiter, terminate the string there
  243. //
  244. if ( wszNamespaceEnd )
  245. {
  246. *wszNamespaceEnd = L'\0';
  247. }
  248. //
  249. // Allocate space for the namespace string
  250. //
  251. DWORD dwNSLength = wcslen( ((VARIANT*) &var)->bstrVal ) + 1;
  252. wszNameSpace = new WCHAR [ dwNSLength ];
  253. //
  254. // If we got space for the namespace, copy it
  255. //
  256. if ( wszNameSpace )
  257. {
  258. hr = StringCchCopy( wszNameSpace, dwNSLength, ((VARIANT*) &var)->bstrVal );
  259. ASSERT( SUCCEEDED(hr) );
  260. *ppwszNameSpace = wszNameSpace;
  261. }
  262. else
  263. {
  264. hr = E_OUTOFMEMORY;
  265. }
  266. }
  267. return hr;
  268. }
  269. HRESULT
  270. CRsopContext::MoveContextState( CRsopContext* pRsopContext )
  271. {
  272. _pWbemServices = pRsopContext->_pWbemServices;
  273. if ( _pWbemServices )
  274. {
  275. _pWbemServices->AddRef();
  276. }
  277. _bEnabled = pRsopContext->_bEnabled;
  278. _dwMode = pRsopContext->_dwMode;
  279. _phrLoggingStatus = pRsopContext->_phrLoggingStatus;
  280. pRsopContext->_phrLoggingStatus = NULL;
  281. delete [] _wszNameSpace;
  282. _wszNameSpace = pRsopContext->_wszNameSpace;
  283. pRsopContext->_wszNameSpace = NULL;
  284. _pRsopTarget = pRsopContext->_pRsopTarget;
  285. _wszExtensionGuid = pRsopContext->_wszExtensionGuid;
  286. _hkRsop = pRsopContext->_hkRsop;
  287. pRsopContext->_hkRsop = NULL;
  288. return S_OK;
  289. }
  290. HRESULT
  291. CRsopContext::GetExclusiveLoggingAccess( BOOL bMachine )
  292. {
  293. HRESULT hr;
  294. hr = S_OK;
  295. ASSERT( ! _hPolicyAccess );
  296. //
  297. // We require exclusive access in diagnostic mode only --
  298. // in planning mode, we have implicit exclusive access
  299. //
  300. if ( IsRsopEnabled() && IsDiagnosticModeEnabled() )
  301. {
  302. _hPolicyAccess = EnterCriticalPolicySection( bMachine );
  303. //
  304. // On failure, disable logging
  305. //
  306. if ( ! _hPolicyAccess )
  307. {
  308. LONG Status;
  309. Status = GetLastError();
  310. hr = HRESULT_FROM_WIN32( Status );
  311. if ( SUCCEEDED( hr ) )
  312. {
  313. hr = E_FAIL;
  314. }
  315. DisableRsop( hr );
  316. }
  317. }
  318. return hr;
  319. }
  320. void
  321. CRsopContext::ReleaseExclusiveLoggingAccess()
  322. {
  323. if ( _hPolicyAccess )
  324. {
  325. LeaveCriticalPolicySection( _hPolicyAccess );
  326. _hPolicyAccess = NULL;
  327. }
  328. }
  329. LONG
  330. CRsopContext::GetRsopNamespaceKeyPath(
  331. PSID pUserSid,
  332. WCHAR** ppwszDiagnostic )
  333. {
  334. LONG Status;
  335. UNICODE_STRING SidString;
  336. WCHAR* wszUserSubkey;
  337. HRESULT hr = S_OK;
  338. *ppwszDiagnostic = NULL;
  339. RtlInitUnicodeString( &SidString, NULL );
  340. wszUserSubkey = NULL;
  341. Status = ERROR_SUCCESS;
  342. //
  343. // First, get the subkey
  344. //
  345. if ( pUserSid )
  346. {
  347. NTSTATUS NtStatus;
  348. NtStatus = RtlConvertSidToUnicodeString(
  349. &SidString,
  350. pUserSid,
  351. TRUE);
  352. if ( NT_SUCCESS( NtStatus ) )
  353. {
  354. wszUserSubkey = SidString.Buffer;
  355. }
  356. else
  357. {
  358. Status = RtlNtStatusToDosError( NtStatus );
  359. }
  360. }
  361. else
  362. {
  363. wszUserSubkey = MACHINESUBKEY;
  364. }
  365. //
  366. // If we have obtained the full subkey, we can now
  367. // generate the path for it
  368. //
  369. if ( ERROR_SUCCESS == Status )
  370. {
  371. DWORD cchLen;
  372. //
  373. // Space for the user sid string + the pathsep
  374. //
  375. cchLen = lstrlen ( wszUserSubkey ) + 1;
  376. //
  377. // Space for the gp extension state parent + extension list key (includes both pathseps and null terminator) +
  378. // + the cse subkey
  379. //
  380. cchLen += ( sizeof( GPSTATEKEY ) + sizeof( EXTENSIONLISTKEY ) ) / sizeof( *wszUserSubkey ) +
  381. lstrlen( _wszExtensionGuid ) + 1;
  382. *ppwszDiagnostic = new WCHAR[ cchLen ];
  383. if ( *ppwszDiagnostic )
  384. {
  385. hr = StringCchCopy( *ppwszDiagnostic, cchLen, GPSTATEKEY L"\\" );
  386. ASSERT(SUCCEEDED(hr));
  387. hr = StringCchCat( *ppwszDiagnostic, cchLen, wszUserSubkey );
  388. ASSERT(SUCCEEDED(hr));
  389. hr = StringCchCat( *ppwszDiagnostic, cchLen, EXTENSIONLISTKEY );
  390. ASSERT(SUCCEEDED(hr));
  391. hr = StringCchCat( *ppwszDiagnostic, cchLen, _wszExtensionGuid );
  392. ASSERT(SUCCEEDED(hr));
  393. }
  394. else
  395. {
  396. Status = ERROR_OUTOFMEMORY;
  397. }
  398. }
  399. //
  400. // Free allocated resources
  401. //
  402. if ( SidString.Buffer )
  403. {
  404. RtlFreeUnicodeString( &SidString );
  405. }
  406. return Status;
  407. }
  408. void
  409. CRsopContext::InitializeContext( PSID pUserSid )
  410. {
  411. LONG Status;
  412. WCHAR* wszNameSpace;
  413. WCHAR* wszNameSpaceKeyPath;
  414. //
  415. // In planning mode, all initialization is
  416. // already done, there is nothing to do here
  417. //
  418. if ( IsPlanningModeEnabled() )
  419. {
  420. return;
  421. }
  422. //
  423. // Return successfully if we already have our key.
  424. //
  425. if ( _hkRsop )
  426. return;
  427. Status = ERROR_SUCCESS;
  428. //
  429. // First, we need to get the rsop subkey -- we must ensure that it exists
  430. //
  431. Status = GetRsopNamespaceKeyPath(
  432. pUserSid,
  433. &wszNameSpaceKeyPath);
  434. if ( ERROR_SUCCESS == Status )
  435. {
  436. //
  437. // We create a key under the user's per machine policy
  438. // subtree. This key must be persistent so that extensions
  439. // that process policy outside of the policy engine context
  440. // or in no changes when the policy engine does not pass
  441. // a namepsace to the extension can know whether RSoP is enabled
  442. // or not and where to log the data
  443. //
  444. Status = RegCreateKeyEx(
  445. HKEY_LOCAL_MACHINE,
  446. wszNameSpaceKeyPath,
  447. 0,
  448. NULL,
  449. REG_OPTION_NON_VOLATILE,
  450. KEY_READ | KEY_WRITE,
  451. NULL,
  452. &_hkRsop,
  453. NULL );
  454. delete [] wszNameSpaceKeyPath;
  455. }
  456. if ( ERROR_SUCCESS != Status )
  457. {
  458. HRESULT hr;
  459. hr = HRESULT_FROM_WIN32( Status );
  460. DisableRsop( hr );
  461. }
  462. }
  463. void
  464. CRsopContext::InitializeSavedNameSpace()
  465. {
  466. LONG Status;
  467. if ( ! _hkRsop )
  468. {
  469. return;
  470. }
  471. //
  472. // In planning mode, all initialization is
  473. // already done, there is nothing to do here
  474. //
  475. if ( IsPlanningModeEnabled() )
  476. {
  477. return;
  478. }
  479. Status = ERROR_SUCCESS;
  480. //
  481. // If we already have a namespace, there is no need to use the saved
  482. // namespace, so we can leave since we've ensured the existence of the namespace key
  483. //
  484. if ( HasNameSpace() )
  485. {
  486. return;
  487. }
  488. //
  489. // The rsop namespace for this user is stored in the registry --
  490. // we query this below
  491. //
  492. DWORD Size;
  493. Size = 0;
  494. Status = RegQueryValueEx(
  495. _hkRsop,
  496. RSOPNAMESPACE,
  497. NULL,
  498. NULL,
  499. NULL,
  500. &Size);
  501. if ( ERROR_SUCCESS == Status )
  502. {
  503. WCHAR* wszNameSpace;
  504. wszNameSpace = (WCHAR*) new BYTE [ Size ];
  505. if ( ! wszNameSpace )
  506. {
  507. Status = ERROR_OUTOFMEMORY;
  508. goto CRsopContext__InitializeSavedNameSpace__Exit;
  509. }
  510. Status = RegQueryValueEx(
  511. _hkRsop,
  512. RSOPNAMESPACE,
  513. NULL,
  514. NULL,
  515. (LPBYTE) wszNameSpace,
  516. &Size);
  517. if ( ERROR_SUCCESS != Status )
  518. {
  519. delete [] wszNameSpace;
  520. wszNameSpace = NULL;
  521. }
  522. else
  523. {
  524. SetNameSpace( wszNameSpace );
  525. }
  526. }
  527. CRsopContext__InitializeSavedNameSpace__Exit:
  528. if ( ERROR_SUCCESS != Status )
  529. {
  530. HRESULT hr;
  531. hr = HRESULT_FROM_WIN32( Status );
  532. DisableRsop( hr );
  533. }
  534. }
  535. void
  536. CRsopContext::SaveNameSpace()
  537. {
  538. WCHAR* wszNameSpace;
  539. HRESULT hr;
  540. if ( ! IsRsopEnabled() )
  541. {
  542. return;
  543. }
  544. if ( IsPlanningModeEnabled() )
  545. {
  546. return;
  547. }
  548. wszNameSpace = NULL;
  549. //
  550. // Retrieve the rsop namespace -- note that the retrieved
  551. // string should be freed
  552. //
  553. hr = GetNameSpace( &wszNameSpace );
  554. if ( SUCCEEDED( hr ) )
  555. {
  556. #if DBG
  557. DWORD
  558. DebugStatus =
  559. #endif // DBG
  560. RegSetValueEx( _hkRsop,
  561. RSOPNAMESPACE,
  562. 0,
  563. REG_SZ,
  564. (LPBYTE) wszNameSpace,
  565. (lstrlen( wszNameSpace ) + 1) * sizeof(WCHAR) );
  566. }
  567. delete [] wszNameSpace;
  568. }
  569. void
  570. CRsopContext::DeleteSavedNameSpace()
  571. {
  572. if ( IsPlanningModeEnabled() )
  573. {
  574. return;
  575. }
  576. #if DBG
  577. DWORD
  578. DebugStatus =
  579. #endif // DBG
  580. RegDeleteValue( _hkRsop,
  581. RSOPNAMESPACE );
  582. }