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.

811 lines
26 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: ThemeManagerSessionData.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // This file contains a class that implements information the encapsulates a
  7. // client TS session for the theme server.
  8. //
  9. // History: 2000-10-10 vtan created
  10. // 2000-11-29 vtan moved to separate file
  11. // --------------------------------------------------------------------------
  12. #include "StandardHeader.h"
  13. #include "ThemeManagerSessionData.h"
  14. #define STRSAFE_LIB
  15. #include <strsafe.h>
  16. #include <uxthemep.h>
  17. #include <UxThemeServer.h>
  18. #include "SingleThreadedExecution.h"
  19. #include "StatusCode.h"
  20. #include "ThemeManagerAPIRequest.h"
  21. #include "TokenInformation.h"
  22. // --------------------------------------------------------------------------
  23. // CThemeManagerSessionData::s_pAPIConnection
  24. //
  25. // Purpose: Static member variables.
  26. //
  27. // History: 2000-12-02 vtan created
  28. // --------------------------------------------------------------------------
  29. CAPIConnection* CThemeManagerSessionData::s_pAPIConnection = NULL;
  30. // --------------------------------------------------------------------------
  31. // CThemeManagerSessionData::CThemeManagerSessionData
  32. //
  33. // Arguments: pAPIConnection = CAPIConnection for port access control.
  34. // dwSessionID = Session ID.
  35. //
  36. // Returns: <none>
  37. //
  38. // Purpose: Constructor for CThemeManagerSessionData.
  39. //
  40. // History: 2000-11-17 vtan created
  41. // --------------------------------------------------------------------------
  42. CThemeManagerSessionData::CThemeManagerSessionData (DWORD dwSessionID) :
  43. _dwSessionID(dwSessionID),
  44. _pvThemeLoaderData(NULL),
  45. _hToken(NULL),
  46. _hProcessClient(NULL),
  47. _pLoader(NULL),
  48. _hWait(NULL)
  49. {
  50. }
  51. // --------------------------------------------------------------------------
  52. // CThemeManagerSessionData::~CThemeManagerSessionData
  53. //
  54. // Arguments: <none>
  55. //
  56. // Returns: <none>
  57. //
  58. // Purpose: Destructor for CThemeManagerSessionData.
  59. //
  60. // History: 2000-11-17 vtan created
  61. // --------------------------------------------------------------------------
  62. CThemeManagerSessionData::~CThemeManagerSessionData (void)
  63. {
  64. ASSERTMSG(_hWait == NULL, "Wait not executed or removed in CThemeManagerSessionData::~CThemeManagerSessionData");
  65. ASSERTMSG(_hProcessClient == NULL, "_hProcessClient not closed in CThemeManagerSessionData::~CThemeManagerSessionData");
  66. // if this session's theme loader process is still alive, clear and delete it.
  67. if( _pLoader )
  68. {
  69. _pLoader->Clear(_pvThemeLoaderData, TRUE);
  70. delete _pLoader;
  71. _pLoader = NULL;
  72. }
  73. TSTATUS(UserLogoff());
  74. if (_pvThemeLoaderData != NULL)
  75. {
  76. SessionFree(_pvThemeLoaderData);
  77. _pvThemeLoaderData = NULL;
  78. }
  79. }
  80. // --------------------------------------------------------------------------
  81. // CThemeManagerSessionData::GetData
  82. //
  83. // Arguments: <none>
  84. //
  85. // Returns: void*
  86. //
  87. // Purpose: Returns the internal data blob allocated by SessionCreate.
  88. //
  89. // History: 2000-11-17 vtan created
  90. // --------------------------------------------------------------------------
  91. void* CThemeManagerSessionData::GetData (void) const
  92. {
  93. return(_pvThemeLoaderData);
  94. }
  95. // --------------------------------------------------------------------------
  96. // CThemeManagerSessionData::EqualSessionID
  97. //
  98. // Arguments: dwSessionID
  99. //
  100. // Returns: bool
  101. //
  102. // Purpose: Returns whether the given session ID matches this session
  103. // data.
  104. //
  105. // History: 2000-11-30 vtan created
  106. // --------------------------------------------------------------------------
  107. bool CThemeManagerSessionData::EqualSessionID (DWORD dwSessionID) const
  108. {
  109. return(dwSessionID == _dwSessionID);
  110. }
  111. // --------------------------------------------------------------------------
  112. // CThemeManagerSessionData::Allocate
  113. //
  114. // Arguments: hProcessClient = Handle to the client process.
  115. //
  116. // Returns: NTSTATUS
  117. //
  118. // Purpose: Allocates a data blob via SessionCreate which also keeps a
  119. // handle to the client process that initiated the session. This
  120. // is always winlogon in the client session ID.
  121. //
  122. // History: 2000-11-17 vtan created
  123. // --------------------------------------------------------------------------
  124. NTSTATUS CThemeManagerSessionData::Allocate (HANDLE hProcessClient, DWORD dwServerChangeNumber, void *pfnRegister, void *pfnUnregister, void *pfnClearStockObjects, DWORD dwStackSizeReserve, DWORD dwStackSizeCommit)
  125. {
  126. NTSTATUS status;
  127. if (DuplicateHandle(GetCurrentProcess(),
  128. hProcessClient,
  129. GetCurrentProcess(),
  130. &_hProcessClient,
  131. SYNCHRONIZE,
  132. FALSE,
  133. 0) != FALSE)
  134. {
  135. ASSERTMSG(_hWait == NULL, "_hWait already exists in CThemeManagerSessionData::Allocate");
  136. AddRef();
  137. if (RegisterWaitForSingleObject(&_hWait,
  138. _hProcessClient,
  139. CB_SessionTermination,
  140. this,
  141. INFINITE,
  142. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE) != FALSE)
  143. {
  144. _pvThemeLoaderData = SessionAllocate(hProcessClient, dwServerChangeNumber, pfnRegister, pfnUnregister, pfnClearStockObjects, dwStackSizeReserve, dwStackSizeCommit);
  145. if (_pvThemeLoaderData != NULL)
  146. {
  147. status = STATUS_SUCCESS;
  148. }
  149. else
  150. {
  151. status = STATUS_NO_MEMORY;
  152. }
  153. }
  154. else
  155. {
  156. status = CStatusCode::StatusCodeOfLastError();
  157. }
  158. if (!NT_SUCCESS(status))
  159. {
  160. HANDLE hWait;
  161. // In the case of failure grab the _hWait and try to unregister it.
  162. // If the unregister fails then the callback is already executing
  163. // and there's little we can to stop it. This means that the winlogon
  164. // for the client session died between the time we entered this function
  165. // and registered the wait and now. If the unregister worked then then
  166. // callback hasn't executed so just release the resources.
  167. hWait = InterlockedExchangePointer(&_hWait, NULL);
  168. if (hWait != NULL)
  169. {
  170. if (UnregisterWait(hWait) != FALSE)
  171. {
  172. Release();
  173. }
  174. ReleaseHandle(_hProcessClient);
  175. if (_pvThemeLoaderData != NULL)
  176. {
  177. SessionFree(_pvThemeLoaderData);
  178. _pvThemeLoaderData = NULL;
  179. }
  180. }
  181. }
  182. }
  183. else
  184. {
  185. status = CStatusCode::StatusCodeOfLastError();
  186. }
  187. return(status);
  188. }
  189. // --------------------------------------------------------------------------
  190. // CThemeManagerSessionData::Cleanup
  191. //
  192. // Arguments: <none>
  193. //
  194. // Returns: NTSTATUS
  195. //
  196. // Purpose: Used to unregister the wait on the client process. This is
  197. // necessary to prevent the callback from occurring after the
  198. // service has been shut down which will cause access to a static
  199. // member variable that is NULL'd out.
  200. //
  201. // History: 2001-01-05 vtan created
  202. // --------------------------------------------------------------------------
  203. NTSTATUS CThemeManagerSessionData::Cleanup (void)
  204. {
  205. HANDLE hWait;
  206. hWait = InterlockedExchangePointer(&_hWait, NULL);
  207. if (hWait != NULL)
  208. {
  209. if (UnregisterWait(hWait) != FALSE)
  210. {
  211. Release();
  212. }
  213. ReleaseHandle(_hProcessClient);
  214. }
  215. return(STATUS_SUCCESS);
  216. }
  217. // --------------------------------------------------------------------------
  218. // CThemeManagerSessionData::UserLogon
  219. //
  220. // Arguments: hToken = Handle to the token of the user logging on.
  221. //
  222. // Returns: NTSTATUS
  223. //
  224. // Purpose: Saves a copy of the token for use at log off. Allows access
  225. // to the theme port to the logon SID of the token.
  226. //
  227. // History: 2000-11-17 vtan created
  228. // --------------------------------------------------------------------------
  229. NTSTATUS CThemeManagerSessionData::UserLogon (HANDLE hToken)
  230. {
  231. NTSTATUS status;
  232. if (_hToken == NULL)
  233. {
  234. if (DuplicateHandle(GetCurrentProcess(),
  235. hToken,
  236. GetCurrentProcess(),
  237. &_hToken,
  238. 0,
  239. FALSE,
  240. DUPLICATE_SAME_ACCESS) != FALSE)
  241. {
  242. PSID pSIDLogon;
  243. CTokenInformation token(hToken);
  244. pSIDLogon = token.GetLogonSID();
  245. if (pSIDLogon != NULL)
  246. {
  247. if (s_pAPIConnection != NULL)
  248. {
  249. status = s_pAPIConnection->AddAccess(pSIDLogon, PORT_CONNECT);
  250. }
  251. else
  252. {
  253. status = STATUS_SUCCESS;
  254. }
  255. }
  256. else
  257. {
  258. status = STATUS_INVALID_PARAMETER;
  259. }
  260. }
  261. else
  262. {
  263. status = CStatusCode::StatusCodeOfLastError();
  264. }
  265. }
  266. else
  267. {
  268. status = STATUS_SUCCESS;
  269. }
  270. return(status);
  271. }
  272. // --------------------------------------------------------------------------
  273. // CThemeManagerSessionData::UserLogoff
  274. //
  275. // Arguments: <none>
  276. //
  277. // Returns: NTSTATUS
  278. //
  279. // Purpose: Remove access to the theme port for the user being logged off.
  280. //
  281. // History: 2000-11-17 vtan created
  282. // --------------------------------------------------------------------------
  283. NTSTATUS CThemeManagerSessionData::UserLogoff (void)
  284. {
  285. NTSTATUS status;
  286. if (_hToken != NULL)
  287. {
  288. PSID pSIDLogon;
  289. CTokenInformation token(_hToken);
  290. pSIDLogon = token.GetLogonSID();
  291. if (pSIDLogon != NULL)
  292. {
  293. if (s_pAPIConnection != NULL)
  294. {
  295. status = s_pAPIConnection->RemoveAccess(pSIDLogon);
  296. }
  297. else
  298. {
  299. status = STATUS_SUCCESS;
  300. }
  301. }
  302. else
  303. {
  304. status = STATUS_INVALID_PARAMETER;
  305. }
  306. ReleaseHandle(_hToken);
  307. }
  308. else
  309. {
  310. status = STATUS_SUCCESS;
  311. }
  312. return(status);
  313. }
  314. // --------------------------------------------------------------------------
  315. // CThemeManagerSessionData::SetAPIConnection
  316. //
  317. // Arguments: <none>
  318. //
  319. // Returns: <none>
  320. //
  321. // Purpose: Sets the static CAPIConnection for port access changes.
  322. //
  323. // History: 2000-12-02 vtan created
  324. // --------------------------------------------------------------------------
  325. void CThemeManagerSessionData::SetAPIConnection (CAPIConnection *pAPIConnection)
  326. {
  327. pAPIConnection->AddRef();
  328. s_pAPIConnection = pAPIConnection;
  329. }
  330. // --------------------------------------------------------------------------
  331. // CThemeManagerSessionData::ReleaseAPIConnection
  332. //
  333. // Arguments: <none>
  334. //
  335. // Returns: <none>
  336. //
  337. // Purpose: Releases the static CAPIConnection for port access changes.
  338. //
  339. // History: 2000-12-02 vtan created
  340. // --------------------------------------------------------------------------
  341. void CThemeManagerSessionData::ReleaseAPIConnection (void)
  342. {
  343. s_pAPIConnection->Release();
  344. s_pAPIConnection = NULL;
  345. }
  346. // --------------------------------------------------------------------------
  347. // CThemeManagerSessionData::GetLoaderProcess
  348. //
  349. // Arguments: (none)
  350. //
  351. // Returns: (n/a)
  352. //
  353. // Purpose: STATUS_SUCCESS if it worked, otherwise an error status code K
  354. //
  355. // History: 2002-02-26 scotthan created
  356. // --------------------------------------------------------------------------
  357. NTSTATUS CThemeManagerSessionData::GetLoaderProcess( OUT CLoaderProcess** ppLoader )
  358. {
  359. ASSERTBREAKMSG(ppLoader != NULL, "CThemeManagerSessionData::GetLoaderProcess - invalid output address.");
  360. *ppLoader = NULL;
  361. if( (NULL == _pLoader) && (NULL == (_pLoader = new CLoaderProcess)) )
  362. {
  363. return STATUS_NO_MEMORY;
  364. }
  365. *ppLoader = _pLoader;
  366. return STATUS_SUCCESS;
  367. }
  368. // --------------------------------------------------------------------------
  369. // CThemeManagerSessionData::SessionTermination
  370. //
  371. // Arguments: <none>
  372. //
  373. // Returns: <none>
  374. //
  375. // Purpose: Callback on winlogon process termination for a given session.
  376. // We clean up the session specific data blob when this happens.
  377. // This allows the process handles on winlogon to be released.
  378. // If this isn't done then a zombie lives and the session is
  379. // never reclaimed.
  380. //
  381. // History: 2000-12-09 vtan created
  382. // --------------------------------------------------------------------------
  383. void CThemeManagerSessionData::SessionTermination (void)
  384. {
  385. HANDLE hWait;
  386. hWait = InterlockedExchangePointer(&_hWait, NULL);
  387. if (hWait != NULL)
  388. {
  389. (BOOL)UnregisterWait(hWait);
  390. ReleaseHandle(_hProcessClient);
  391. }
  392. CThemeManagerAPIRequest::SessionDestroy(_dwSessionID);
  393. Release();
  394. }
  395. // --------------------------------------------------------------------------
  396. // CThemeManagerSessionData::CB_SessionTermination
  397. //
  398. // Arguments: pParameter = This object.
  399. // TimerOrWaitFired = Not used.
  400. //
  401. // Returns: <none>
  402. //
  403. // Purpose: Callback stub to member function.
  404. //
  405. // History: 2000-12-09 vtan created
  406. // --------------------------------------------------------------------------
  407. void CALLBACK CThemeManagerSessionData::CB_SessionTermination (void *pParameter, BOOLEAN TimerOrWaitFired)
  408. {
  409. UNREFERENCED_PARAMETER(TimerOrWaitFired);
  410. static_cast<CThemeManagerSessionData*>(pParameter)->SessionTermination();
  411. }
  412. // --------------------------------------------------------------------------
  413. // CLoaderProcess::CLoaderProcess
  414. //
  415. // Arguments: n/a
  416. //
  417. // Returns: <none>
  418. //
  419. // Purpose: CLoaderProcess constructor
  420. //
  421. // History: 2002-03-06 scotthan created
  422. // --------------------------------------------------------------------------
  423. CLoaderProcess::CLoaderProcess()
  424. : _pszFile(NULL),
  425. _pszColor(NULL),
  426. _pszSize(NULL),
  427. _hSection(NULL),
  428. _hr(0)
  429. {
  430. ZeroMemory(&_process_info, sizeof(_process_info));
  431. }
  432. // --------------------------------------------------------------------------
  433. // CLoaderProcess::~CLoaderProcess
  434. //
  435. // Arguments: n/a
  436. //
  437. // Returns: <none>
  438. //
  439. // Purpose: CLoaderProcess destructor
  440. //
  441. // History: 2002-03-06 scotthan created
  442. // --------------------------------------------------------------------------
  443. CLoaderProcess::~CLoaderProcess()
  444. {
  445. Clear(NULL, TRUE);
  446. }
  447. // --------------------------------------------------------------------------
  448. // CLoaderProcess::IsProcessLoader
  449. //
  450. // Arguments: hProcess - Handle of process to test.
  451. //
  452. // Returns: BOOL
  453. //
  454. // Purpose: Determines whether the process identified by hProcess is
  455. // matches the process spawned by CLoaderProcess::Create()
  456. //
  457. // Note: THIS MUST BE CALLED FROM THE PROCESS OWNER"S SECURITY CONTEXT.
  458. //
  459. // History: 2002-03-06 scotthan created
  460. // --------------------------------------------------------------------------
  461. BOOL CLoaderProcess::IsProcessLoader( IN HANDLE hProcess )
  462. {
  463. if( _process_info.hProcess && _process_info.dwProcessId )
  464. {
  465. PROCESS_BASIC_INFORMATION bi;
  466. ULONG cbOut;
  467. if( NT_SUCCESS(NtQueryInformationProcess(hProcess,
  468. ProcessBasicInformation,
  469. &bi, sizeof(bi), &cbOut)) )
  470. {
  471. if( bi.UniqueProcessId == _process_info.dwProcessId
  472. || bi.InheritedFromUniqueProcessId == _process_info.dwProcessId
  473. )
  474. {
  475. return TRUE;
  476. }
  477. }
  478. }
  479. return FALSE;
  480. }
  481. // --------------------------------------------------------------------------
  482. // CLoaderProcess::Create
  483. //
  484. // Arguments: pvSessionData - Session instance data (CThemeManagerSessionData::GetData()).
  485. // hTokenClient - token handle of LPC client. This is needed to
  486. // ensure the process loader is created on the correct desktop if
  487. // pszDesktop is NULL.
  488. // pszDesktop - optional; desktop on which to create the loader.
  489. // (Note: the client token handle will establish the correct session.)
  490. // pszFile - valid msstyles source file spec.
  491. // pszColor - valid color variant name.
  492. // pszSize - valid size variant name.
  493. // phLoader - optional address to receive loader process handle.
  494. //
  495. // Returns: STATUS_SUCCESS if it worked, otherwise an NT status error code.
  496. //
  497. // Purpose: Spawns a loader process.
  498. //
  499. // History: 2002-03-06 scotthan created
  500. // --------------------------------------------------------------------------
  501. NTSTATUS CLoaderProcess::Create(
  502. IN PVOID pvSessionData,
  503. IN HANDLE hTokenClient,
  504. IN OPTIONAL LPWSTR pszDesktop,
  505. IN LPCWSTR pszFile,
  506. IN LPCWSTR pszColor,
  507. IN LPCWSTR pszSize,
  508. OUT OPTIONAL HANDLE* phLoader )
  509. {
  510. ASSERTMSG( 0 == _process_info.dwProcessId, "CLoaderProcess::Create - synchronization error: loader process already exists");
  511. ASSERTMSG( (pszFile && *pszFile), "CLoaderProcess::Create - invalid source file spec.");
  512. ASSERTMSG( (pszColor && *pszColor), "CLoaderProcess::Create - invalid color variant name.");
  513. ASSERTMSG( (pszSize && *pszSize), "CLoaderProcess::Create - invalid size variant name.");
  514. NTSTATUS status = STATUS_SUCCESS;
  515. const LPCWSTR _pszFmt = L"rundll32.exe uxtheme.dll,#64 %s?%s?%s";
  516. const LPWSTR _pszDesktopDefault = L"WinSta0\\Default";
  517. LPWSTR pszRunDll = NULL;
  518. if( phLoader )
  519. {
  520. *phLoader = NULL;
  521. }
  522. // clear out existing state
  523. Clear(pvSessionData, TRUE);
  524. // Establish desktop
  525. // Note: the client token handle will establish the correct session.
  526. if( NULL == pszDesktop )
  527. {
  528. pszDesktop = _pszDesktopDefault;
  529. }
  530. // Allocate strings
  531. ULONG cchFile = lstrlen(pszFile);
  532. ULONG cchColor = lstrlen(pszColor);
  533. ULONG cchSize = lstrlen(pszSize);
  534. ULONG cchRunDll = lstrlen(_pszFmt) + cchFile + cchColor + cchSize;
  535. _pszFile = new WCHAR[cchFile + 1];
  536. _pszColor = new WCHAR[cchColor + 1];
  537. _pszSize = new WCHAR[cchSize + 1];
  538. pszRunDll = new WCHAR[cchRunDll + 1];
  539. if( (_pszFile && _pszColor && _pszSize && pszRunDll) )
  540. {
  541. STARTUPINFO si;
  542. ZeroMemory(&si, sizeof(si));
  543. si.cb = sizeof(si);
  544. si.dwFlags = STARTF_FORCEOFFFEEDBACK;
  545. si.lpDesktop = pszDesktop;
  546. StringCchPrintfW( pszRunDll, cchRunDll + 1, _pszFmt,
  547. pszFile, pszColor, pszSize );
  548. if( CreateProcessAsUser(hTokenClient,
  549. NULL,
  550. pszRunDll,
  551. NULL,
  552. NULL,
  553. FALSE,
  554. 0,
  555. NULL,
  556. NULL,
  557. &si,
  558. &_process_info) )
  559. {
  560. // make copies of the inbound parameters
  561. StringCchCopyW(_pszFile, cchFile + 1, pszFile);
  562. StringCchCopyW(_pszColor, cchColor + 1, pszColor);
  563. StringCchCopyW(_pszSize, cchSize + 1, pszSize);
  564. _hr = STATUS_ABANDONED; // initialize the return with something appropriate if the process never comes back
  565. #ifdef DEBUG
  566. DWORD dwCurrentProcessID = GetCurrentProcessId();
  567. UNREFERENCED_PARAMETER(dwCurrentProcessID);
  568. PROCESS_BASIC_INFORMATION bi;
  569. ULONG cbOut;
  570. if( NT_SUCCESS(NtQueryInformationProcess(_process_info.hProcess,
  571. ProcessBasicInformation,
  572. &bi, sizeof(bi), &cbOut)) )
  573. {
  574. }
  575. #endif DEBUG
  576. if( phLoader )
  577. {
  578. *phLoader = _process_info.hProcess;
  579. }
  580. }
  581. else
  582. {
  583. status = CStatusCode::StatusCodeOfLastError();
  584. }
  585. }
  586. else
  587. {
  588. Clear(pvSessionData, FALSE);
  589. status = STATUS_NO_MEMORY;
  590. }
  591. delete [] pszRunDll;
  592. _hr = HRESULT_FROM_NT(status);
  593. return status;
  594. }
  595. // --------------------------------------------------------------------------
  596. // CLoaderProcess::ValidateAndCopySection
  597. //
  598. // Arguments: pvSessionData = Session cookie returned from CThemeManagerSessionData->GetData().
  599. // hProcessClient = Optional, process handle of LPC client, used to validate
  600. // the client is the loader process. If NULL is supplied, the client
  601. // will not be validated.
  602. // hSectionIn = Read-write section handle from loader, mapped to local memory space.
  603. // *phSectionOut = Read-only section handle, mapped to local memory space.
  604. //
  605. // Returns: STATUS_SUCCESS if it worked, otherwise an NT status error code.
  606. //
  607. // Purpose: Validates section handle received from loader process, and creates a read-only copy.
  608. // Note: IsProcessLoader should already have been verified.
  609. //
  610. // History: 2002-03-06 scotthan created
  611. // --------------------------------------------------------------------------
  612. NTSTATUS CLoaderProcess::ValidateAndCopySection(
  613. IN PVOID pvSessionData,
  614. IN HANDLE hSectionIn,
  615. OUT HANDLE *phSectionOut )
  616. {
  617. NTSTATUS status = STATUS_SUCCESS;
  618. *phSectionOut = NULL;
  619. ASSERTMSG(_process_info.hProcess != NULL, "CLoaderProcess::ValidateAndCopySection - possible synchronization error; no loader process is active!");
  620. ASSERTMSG(NULL == _hSection, "CLoaderProcess::ValidateAndCopySection - possible synchronization error; section already assigned!");
  621. // The loader process is privileged to load global themes, and we want to
  622. // transfer ownership of the stock objects to the output section so that the
  623. // API_THEMES_PROCESSLOADTHEME client does not attempt to free them on failure.
  624. _hr = LoadTheme(pvSessionData, hSectionIn, &_hSection, _pszFile, _pszColor, _pszSize,
  625. LTF_GLOBALPRIVILEGEDCLIENT | LTF_TRANSFERSTOCKOBJOWNERSHIP);
  626. status = _hr &= ~FACILITY_NT_BIT;
  627. if( NT_SUCCESS(status) )
  628. {
  629. *phSectionOut = _hSection;
  630. }
  631. return status;
  632. }
  633. // --------------------------------------------------------------------------
  634. // CLoaderProcess::SetSectionHandle
  635. //
  636. // Arguments: hSection - section handle
  637. //
  638. // Returns: STATUS_SUCCESS if it worked, otherwise an NT status error code.
  639. //
  640. // Purpose: Spawns a loader process.
  641. //
  642. // History: 2002-03-06 scotthan created
  643. // --------------------------------------------------------------------------
  644. NTSTATUS CLoaderProcess::SetSectionHandle(
  645. IN HANDLE hSection )
  646. {
  647. ASSERTMSG(_hSection == NULL, "CLoaderProcess::SetSectionHandle - synchronization error; reassigning section handle");
  648. _hSection = hSection;
  649. return STATUS_SUCCESS;
  650. }
  651. // --------------------------------------------------------------------------
  652. // CLoaderProcess::GetSectionHandle
  653. //
  654. // Arguments: fTakeOwnership - TRUE if caller wishes to manage the section
  655. // (including closing the handle and/or clearing stock objects).
  656. //
  657. // Returns: STATUS_SUCCESS if it worked, otherwise an NT status error code.
  658. //
  659. // Purpose: Spawns a loader process.
  660. //
  661. // History: 2002-03-06 scotthan created
  662. // --------------------------------------------------------------------------
  663. HANDLE CLoaderProcess::GetSectionHandle( BOOL fTakeOwnership )
  664. {
  665. HANDLE hSection = _hSection;
  666. if( fTakeOwnership )
  667. {
  668. _hSection = NULL;
  669. }
  670. return hSection;
  671. }
  672. // --------------------------------------------------------------------------
  673. // CLoaderProcess::Clear
  674. //
  675. // Arguments: fClearHResult - TRUE to clear the HRESULT as well as the
  676. // other loader process data.
  677. //
  678. // pvSessionData - Session instance data (CThemeManagerSessionData::GetData()).
  679. //
  680. // Returns: n/a
  681. //
  682. // Purpose: Cleans up loader process state info.
  683. //
  684. // History: 2002-03-06 scotthan created
  685. // --------------------------------------------------------------------------
  686. void CLoaderProcess::Clear(
  687. IN PVOID OPTIONAL pvSessionData,
  688. IN BOOL OPTIONAL fClearHResult)
  689. {
  690. if( _process_info.hThread != NULL )
  691. {
  692. CloseHandle(_process_info.hThread);
  693. }
  694. if( _process_info.hProcess != NULL )
  695. {
  696. CloseHandle(_process_info.hProcess);
  697. }
  698. ZeroMemory(&_process_info, sizeof(_process_info));
  699. delete [] _pszFile;
  700. _pszFile = NULL;
  701. delete [] _pszColor;
  702. _pszColor = NULL;
  703. delete [] _pszSize;
  704. _pszSize = NULL;
  705. if( _hSection )
  706. {
  707. ASSERTMSG(pvSessionData != NULL, "CLoaderProcess::Clear - Exiting service without clearing stock objects from loader process block")
  708. if( pvSessionData )
  709. {
  710. THR(ServiceClearStockObjects(pvSessionData, _hSection));
  711. }
  712. CloseHandle(_hSection);
  713. _hSection = NULL;
  714. }
  715. if( fClearHResult )
  716. {
  717. _hr = 0;
  718. }
  719. }