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.

1707 lines
57 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: ThemeManagerAPIRequest.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // This file contains a class that implements the work for the theme server.
  7. //
  8. // History: 2000-10-10 vtan created
  9. // 2000-11-29 vtan moved to separate file
  10. // --------------------------------------------------------------------------
  11. #include "StandardHeader.h"
  12. #include "ThemeManagerAPIRequest.h"
  13. #include "ThemeManagerService.h"
  14. #include <LPCThemes.h>
  15. #include <uxthemep.h>
  16. #include <UxThemeServer.h>
  17. #include "RegistryResources.h"
  18. #include "SingleThreadedExecution.h"
  19. #include "StatusCode.h"
  20. #include "TokenInformation.h"
  21. #define STRSAFE_LIB
  22. #include <strsafe.h>
  23. // --------------------------------------------------------------------------
  24. // Static member variables.
  25. //
  26. // History: 2000-11-09 vtan created
  27. // --------------------------------------------------------------------------
  28. CDynamicCountedObjectArray* CThemeManagerAPIRequest::s_pSessionData = NULL;
  29. CCriticalSection* CThemeManagerAPIRequest::s_pLock = NULL;
  30. DWORD CThemeManagerAPIRequest::s_dwServerChangeNumber = 0;
  31. const TCHAR CThemeManagerAPIRequest::s_szServerChangeNumberValue[] = TEXT("ServerChangeNumber");
  32. #ifdef DEBUG
  33. #define PROCESSLOADERWAIT DISPATCHSYNC_TIMEOUT * 10
  34. #else
  35. #define PROCESSLOADERWAIT DISPATCHSYNC_TIMEOUT
  36. #endif DEBUG
  37. // --------------------------------------------------------------------------
  38. // Forward decls
  39. //
  40. // History: 2002-02-26 scotthan created
  41. // --------------------------------------------------------------------------
  42. inline NTSTATUS _CheckTokenPrivilege( HANDLE hToken, DWORD dwPrivilege )
  43. {
  44. CTokenInformation tokenInformation(hToken);
  45. return tokenInformation.UserHasPrivilege(dwPrivilege) ?
  46. STATUS_SUCCESS : STATUS_ACCESS_DENIED;
  47. }
  48. // --------------------------------------------------------------------------
  49. // CThemeManagerAPIRequest::CThemeManagerAPIRequest
  50. //
  51. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  52. // pAPIConnection = CAPIConnection for access change.
  53. //
  54. // Returns: <none>
  55. //
  56. // Purpose: Constructor for the CThemeManagerAPIRequest class. It just passes the
  57. // control to the super class.
  58. //
  59. // History: 2000-10-10 vtan created
  60. // --------------------------------------------------------------------------
  61. CThemeManagerAPIRequest::CThemeManagerAPIRequest (CAPIDispatcher* pAPIDispatcher) :
  62. CAPIRequest(pAPIDispatcher),
  63. _hToken(NULL),
  64. _pSessionData(NULL)
  65. {
  66. }
  67. // --------------------------------------------------------------------------
  68. // CThemeManagerAPIRequest::CThemeManagerAPIRequest
  69. //
  70. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  71. // pAPIConnection = CAPIConnection for access change.
  72. // portMessage = CPortMessage to copy construct.
  73. //
  74. // Returns: <none>
  75. //
  76. // Purpose: Constructor for the CThemeManagerAPIRequest class. It just
  77. // passes the control to the super class.
  78. //
  79. // History: 2000-10-10 vtan created
  80. // --------------------------------------------------------------------------
  81. CThemeManagerAPIRequest::CThemeManagerAPIRequest (
  82. CAPIDispatcher* pAPIDispatcher, const CPortMessage& portMessage)
  83. : CAPIRequest(pAPIDispatcher, portMessage),
  84. _hToken(NULL),
  85. _pSessionData(NULL)
  86. {
  87. }
  88. // --------------------------------------------------------------------------
  89. // CThemeManagerAPIRequest::~CThemeManagerAPIRequest
  90. //
  91. // Arguments: <none>
  92. //
  93. // Returns: <none>
  94. //
  95. // Purpose: Destructor for the CThemeManagerAPIRequest class.
  96. //
  97. // History: 2000-10-10 vtan created
  98. // --------------------------------------------------------------------------
  99. CThemeManagerAPIRequest::~CThemeManagerAPIRequest (void)
  100. {
  101. ASSERTMSG(_hToken == NULL, "Impersonation token not released in CThemeManagerAPIRequest::~CThemeManagerAPIRequest");
  102. }
  103. // --------------------------------------------------------------------------
  104. // CThemeManagerAPIRequest::Execute
  105. //
  106. // Arguments: pAPIDispatchSync - allows request execution access to various
  107. // service notifications and events
  108. //
  109. // Returns: NTSTATUS
  110. //
  111. // Purpose: Execute implementation for theme manager API requests. This
  112. // function dispatches requests based on the API request number.
  113. //
  114. // History: 2000-10-10 vtan created
  115. // 2002-03-11 scotthan add API_THEMES_PROCESSLOADTHEME,
  116. // API_THEMES_PROCESSASSIGNSECTION handlers
  117. // 2002-03-24 scotthan add DispatchSync arg
  118. // --------------------------------------------------------------------------
  119. NTSTATUS CThemeManagerAPIRequest::Execute (CAPIDispatchSync* pAPIDispatchSync)
  120. {
  121. NTSTATUS status;
  122. unsigned long ulAPINumber;
  123. ulAPINumber = reinterpret_cast<API_THEMES*>(&_data)->apiGeneric.ulAPINumber & API_GENERIC_NUMBER_MASK;
  124. // First try and get the client session data. If this fails then
  125. // there's no object to execute the request on. Fail it.
  126. // Exception to this is API_THEMES_SESSIONCREATE which creates one.
  127. // Note: GetClientSessionData will store the session data in the
  128. // _pSessionData member variable. While doing so it will increase
  129. // reference count on this so that it doesn't get pulled from the
  130. // array while the API request is being executed. The reference is
  131. // released at the end of this function.
  132. status = GetClientSessionData();
  133. if (NT_SUCCESS(status) || (ulAPINumber == API_THEMES_SESSIONCREATE))
  134. {
  135. switch (ulAPINumber)
  136. {
  137. case API_THEMES_THEMEHOOKSON:
  138. status = Execute_ThemeHooksOn();
  139. break;
  140. case API_THEMES_THEMEHOOKSOFF:
  141. status = Execute_ThemeHooksOff();
  142. break;
  143. case API_THEMES_GETSTATUSFLAGS:
  144. status = Execute_GetStatusFlags();
  145. break;
  146. case API_THEMES_GETCURRENTCHANGENUMBER:
  147. status = Execute_GetCurrentChangeNumber();
  148. break;
  149. case API_THEMES_GETNEWCHANGENUMBER:
  150. status = Execute_GetNewChangeNumber();
  151. break;
  152. case API_THEMES_SETGLOBALTHEME:
  153. status = Execute_SetGlobalTheme();
  154. break;
  155. case API_THEMES_MARKSECTION:
  156. status = Execute_MarkSection();
  157. break;
  158. case API_THEMES_GETGLOBALTHEME:
  159. status = Execute_GetGlobalTheme();
  160. break;
  161. case API_THEMES_CHECKTHEMESIGNATURE:
  162. status = Execute_CheckThemeSignature();
  163. break;
  164. case API_THEMES_LOADTHEME:
  165. status = Execute_LoadTheme();
  166. break;
  167. case API_THEMES_PROCESSLOADTHEME:
  168. status = Execute_ProcessLoadTheme(pAPIDispatchSync);
  169. break;
  170. case API_THEMES_PROCESSASSIGNSECTION:
  171. status = Execute_ProcessAssignSection();
  172. break;
  173. case API_THEMES_USERLOGON:
  174. status = Execute_UserLogon();
  175. break;
  176. case API_THEMES_USERLOGOFF:
  177. status = Execute_UserLogoff();
  178. break;
  179. case API_THEMES_SESSIONCREATE:
  180. status = Execute_SessionCreate();
  181. break;
  182. case API_THEMES_SESSIONDESTROY:
  183. status = Execute_SessionDestroy();
  184. break;
  185. case API_THEMES_PING:
  186. status = Execute_Ping();
  187. break;
  188. default:
  189. DISPLAYMSG("Unknown API request in CThemeManagerAPIRequest::Execute");
  190. status = STATUS_NOT_IMPLEMENTED;
  191. break;
  192. }
  193. }
  194. // If the execution function needed to impersonate the client then
  195. // revert here and release the token used.
  196. if (_hToken != NULL)
  197. {
  198. if (RevertToSelf() == FALSE)
  199. {
  200. status = CStatusCode::StatusCodeOfLastError();
  201. }
  202. ReleaseHandle(_hToken);
  203. }
  204. // Release the _pSessionData object now. NULL it out to prevent
  205. // accidentally using it after being released.
  206. if (_pSessionData != NULL)
  207. {
  208. _pSessionData->Release();
  209. _pSessionData = NULL;
  210. }
  211. // Return to caller.
  212. TSTATUS(status);
  213. return(status);
  214. }
  215. // --------------------------------------------------------------------------
  216. // CThemeManagerAPIRequest::SessionDestroy
  217. //
  218. // Arguments: dwSessionID = Session ID to destroy.
  219. //
  220. // Returns: NTSTATUS
  221. //
  222. // Purpose: External entry point for session client (winlogon) watcher.
  223. // When winlogon dies we clean up the session information for
  224. // that session and release resources.
  225. //
  226. // History: 2000-12-09 vtan created
  227. // --------------------------------------------------------------------------
  228. NTSTATUS CThemeManagerAPIRequest::SessionDestroy (DWORD dwSessionID)
  229. {
  230. NTSTATUS status;
  231. int iIndex;
  232. CSingleThreadedExecution lock(*s_pLock);
  233. iIndex = FindIndexSessionData(dwSessionID);
  234. if (iIndex >= 0)
  235. {
  236. status = s_pSessionData->Remove(iIndex);
  237. }
  238. else
  239. {
  240. status = STATUS_SUCCESS;
  241. }
  242. return(status);
  243. }
  244. // --------------------------------------------------------------------------
  245. // CThemeManagerAPIRequest::InitializeServerChangeNumber
  246. //
  247. // Arguments: <none>
  248. //
  249. // Returns: NTSTATUS
  250. //
  251. // Purpose: Initializes the static server change number. Every time the
  252. // service starts up this number is incremented. If the number
  253. // isn't present then 0 is used.
  254. //
  255. // History: 2000-12-09 vtan created
  256. // 2000-12-09 vtan split from StaticInitialize
  257. // --------------------------------------------------------------------------
  258. NTSTATUS CThemeManagerAPIRequest::InitializeServerChangeNumber (void)
  259. {
  260. LONG lErrorCodeOpen, lErrorCodeRead;
  261. DWORD dwServerChangeNumber;
  262. CRegKey regKey;
  263. dwServerChangeNumber = s_dwServerChangeNumber;
  264. // Initialize the static member variable now in case of failure.
  265. // We ignore failures because at GUI setup the key does NOT exist
  266. // because the server dll hasn't been regsvr'd yet. After GUI setup
  267. // this gets regsvr'd and the key exists and we are happy campers.
  268. lErrorCodeOpen = regKey.Open(HKEY_LOCAL_MACHINE,
  269. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"),
  270. KEY_QUERY_VALUE | KEY_SET_VALUE);
  271. if (ERROR_SUCCESS == lErrorCodeOpen)
  272. {
  273. lErrorCodeRead = regKey.GetDWORD(s_szServerChangeNumberValue, dwServerChangeNumber);
  274. }
  275. else
  276. {
  277. lErrorCodeRead = ERROR_FILE_NOT_FOUND;
  278. }
  279. dwServerChangeNumber = static_cast<WORD>(dwServerChangeNumber + 1);
  280. if ((ERROR_SUCCESS == lErrorCodeOpen) && (ERROR_SUCCESS == lErrorCodeRead))
  281. {
  282. TW32(regKey.SetDWORD(s_szServerChangeNumberValue, dwServerChangeNumber));
  283. }
  284. s_dwServerChangeNumber = dwServerChangeNumber;
  285. return(STATUS_SUCCESS);
  286. }
  287. // --------------------------------------------------------------------------
  288. // CThemeManagerAPIRequest::StaticInitialize
  289. //
  290. // Arguments: <none>
  291. //
  292. // Returns: NTSTATUS
  293. //
  294. // Purpose: Static initializer for the class.
  295. //
  296. // History: 2000-10-10 vtan created
  297. // --------------------------------------------------------------------------
  298. NTSTATUS CThemeManagerAPIRequest::StaticInitialize (void)
  299. {
  300. NTSTATUS status;
  301. status = STATUS_SUCCESS;
  302. if (s_pLock == NULL)
  303. {
  304. s_pLock = new CCriticalSection;
  305. if (s_pLock != NULL)
  306. {
  307. status = s_pLock->Status();
  308. if (!NT_SUCCESS(status))
  309. {
  310. delete s_pLock;
  311. s_pLock = NULL;
  312. }
  313. }
  314. else
  315. {
  316. status = STATUS_NO_MEMORY;
  317. }
  318. }
  319. return(status);
  320. }
  321. // --------------------------------------------------------------------------
  322. // CThemeManagerAPIRequest::StaticTerminate
  323. //
  324. // Arguments: <none>
  325. //
  326. // Returns: NTSTATUS
  327. //
  328. // Purpose: Static destructor for the class.
  329. //
  330. // History: 2000-10-10 vtan created
  331. // --------------------------------------------------------------------------
  332. NTSTATUS CThemeManagerAPIRequest::StaticTerminate (void)
  333. {
  334. if (s_pLock != NULL)
  335. {
  336. delete s_pLock;
  337. s_pLock = NULL;
  338. }
  339. return(STATUS_SUCCESS);
  340. }
  341. // --------------------------------------------------------------------------
  342. // CThemeManagerAPIRequest::ArrayInitialize
  343. //
  344. // Arguments: <none>
  345. //
  346. // Returns: NTSTATUS
  347. //
  348. // Purpose: Initializes (allocates) the session array.
  349. //
  350. // History: 2001-01-05 vtan created
  351. // --------------------------------------------------------------------------
  352. NTSTATUS CThemeManagerAPIRequest::ArrayInitialize (void)
  353. {
  354. NTSTATUS status;
  355. CSingleThreadedExecution lock(*s_pLock);
  356. status = STATUS_SUCCESS;
  357. if (s_pSessionData == NULL)
  358. {
  359. s_pSessionData = new CDynamicCountedObjectArray;
  360. if (s_pSessionData == NULL)
  361. {
  362. status = STATUS_NO_MEMORY;
  363. }
  364. }
  365. return(status);
  366. }
  367. // --------------------------------------------------------------------------
  368. // CThemeManagerAPIRequest::ArrayTerminate
  369. //
  370. // Arguments: <none>
  371. //
  372. // Returns: NTSTATUS
  373. //
  374. // Purpose: Releases all objects in the session array (removes the waits)
  375. // and releases the session array object.
  376. //
  377. // History: 2001-01-05 vtan created
  378. // --------------------------------------------------------------------------
  379. NTSTATUS CThemeManagerAPIRequest::ArrayTerminate (void)
  380. {
  381. CSingleThreadedExecution lock(*s_pLock);
  382. if (s_pSessionData != NULL)
  383. {
  384. int i, iLimit;
  385. iLimit = s_pSessionData->GetCount();
  386. for (i = iLimit - 1; i >= 0; --i)
  387. {
  388. TSTATUS(static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(i))->Cleanup());
  389. TSTATUS(s_pSessionData->Remove(i));
  390. }
  391. delete s_pSessionData;
  392. s_pSessionData = NULL;
  393. }
  394. return(STATUS_SUCCESS);
  395. }
  396. // --------------------------------------------------------------------------
  397. // CThemeManagerAPIRequest::ImpersonateClientIfRequired
  398. //
  399. // Arguments: <none>
  400. //
  401. // Returns: NTSTATUS
  402. //
  403. // Purpose: Impersonates the client if the client is NOT the SYSTEM.
  404. // There's usually no point impersonating the system unless the
  405. // token is actually a filtered token.
  406. //
  407. // History: 2000-10-19 vtan created
  408. // --------------------------------------------------------------------------
  409. NTSTATUS CThemeManagerAPIRequest::ImpersonateClientIfRequired (void)
  410. {
  411. NTSTATUS status;
  412. status = OpenClientToken(_hToken);
  413. if (NT_SUCCESS(status))
  414. {
  415. CTokenInformation tokenInformation(_hToken);
  416. if (tokenInformation.IsUserTheSystem())
  417. {
  418. ReleaseHandle(_hToken);
  419. status = STATUS_SUCCESS;
  420. }
  421. else if (ImpersonateLoggedOnUser(_hToken) != FALSE)
  422. {
  423. status = STATUS_SUCCESS;
  424. }
  425. else
  426. {
  427. status = CStatusCode::StatusCodeOfLastError();
  428. }
  429. }
  430. return(status);
  431. }
  432. // --------------------------------------------------------------------------
  433. // CThemeManagerAPIRequest::ClientHasTcbPrivilege
  434. //
  435. // Arguments: <none>
  436. //
  437. // Returns: NTSTATUS
  438. //
  439. // Purpose: Returns whether the client has the SE_TCB_PRIVILEGE as a
  440. // status code.
  441. //
  442. // History: 2000-11-09 vtan created
  443. // --------------------------------------------------------------------------
  444. NTSTATUS CThemeManagerAPIRequest::ClientHasTcbPrivilege (void)
  445. {
  446. NTSTATUS status;
  447. HANDLE hTokenClient;
  448. if (OpenProcessToken(_pAPIDispatcher->GetClientProcess(),
  449. TOKEN_QUERY,
  450. &hTokenClient) != FALSE)
  451. {
  452. status = _CheckTokenPrivilege(hTokenClient, SE_TCB_PRIVILEGE);
  453. TBOOL(CloseHandle(hTokenClient));
  454. }
  455. else
  456. {
  457. status = CStatusCode::StatusCodeOfLastError();
  458. }
  459. return(status);
  460. }
  461. // --------------------------------------------------------------------------
  462. // CThemeManagerAPIRequest::FindIndexSessionData
  463. //
  464. // Arguments: dwSessionID = Session ID to find.
  465. //
  466. // Returns: int
  467. //
  468. // Purpose: Iterates the session data array looking for the sessions that
  469. // matches the given session.
  470. //
  471. // History: 2000-11-30 vtan created
  472. // --------------------------------------------------------------------------
  473. int CThemeManagerAPIRequest::FindIndexSessionData (DWORD dwSessionID)
  474. {
  475. int iIndex;
  476. iIndex = -1;
  477. if ((s_pLock != NULL) && (s_pSessionData != NULL))
  478. {
  479. int i, iLimit;
  480. ASSERTMSG(s_pLock->IsOwned(), "s_pLock must be acquired in CThemeManagerAPIRequest::FindIndexSessionData");
  481. iLimit = s_pSessionData->GetCount();
  482. for (i = 0; (iIndex < 0) && (i < iLimit); ++i)
  483. {
  484. CThemeManagerSessionData *pSessionData;
  485. pSessionData = static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(i));
  486. if ((pSessionData != NULL) && (pSessionData->EqualSessionID(dwSessionID)))
  487. {
  488. iIndex = i;
  489. }
  490. }
  491. }
  492. return(iIndex);
  493. }
  494. // --------------------------------------------------------------------------
  495. // CThemeManagerAPIRequest::GetClientSessionData
  496. //
  497. // Arguments: <none>
  498. //
  499. // Returns: NTSTATUS
  500. //
  501. // Purpose: Retrieves the session data associated with the client's
  502. // session ID. This abstracts the information from uxtheme's
  503. // loader code and just passes it an object it knows how to deal
  504. // with.
  505. //
  506. // History: 2000-11-09 vtan created
  507. // --------------------------------------------------------------------------
  508. NTSTATUS CThemeManagerAPIRequest::GetClientSessionData (void)
  509. {
  510. NTSTATUS status;
  511. int iIndex;
  512. CSingleThreadedExecution lock(*s_pLock);
  513. status = STATUS_UNSUCCESSFUL;
  514. iIndex = FindIndexSessionData(_pAPIDispatcher->GetClientSessionID());
  515. if (iIndex >= 0)
  516. {
  517. _pSessionData = static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(iIndex));
  518. if (_pSessionData != NULL)
  519. {
  520. _pSessionData->AddRef();
  521. status = STATUS_SUCCESS;
  522. }
  523. }
  524. else
  525. {
  526. _pSessionData = NULL;
  527. }
  528. return(status);
  529. }
  530. // --------------------------------------------------------------------------
  531. // CThemeManagerAPIRequest::Execute_ThemeHooksOn
  532. //
  533. // Arguments: <none>
  534. //
  535. // Returns: NTSTATUS
  536. //
  537. // Purpose: Handles API_THEMES_THEMEHOOKSON.
  538. //
  539. // History: 2000-10-10 vtan created
  540. // --------------------------------------------------------------------------
  541. NTSTATUS CThemeManagerAPIRequest::Execute_ThemeHooksOn (void)
  542. {
  543. NTSTATUS status;
  544. status = ImpersonateClientIfRequired();
  545. if (NT_SUCCESS(status))
  546. {
  547. API_THEMES_THEMEHOOKSON_OUT *pAPIOut;
  548. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiThemeHooksOn.out;
  549. pAPIOut->hr = ThemeHooksOn(_pSessionData->GetData());
  550. }
  551. SetDataLength(sizeof(API_THEMES));
  552. return(status);
  553. }
  554. // --------------------------------------------------------------------------
  555. // CThemeManagerAPIRequest::Execute_ThemeHooksOff
  556. //
  557. // Arguments: <none>
  558. //
  559. // Returns: NTSTATUS
  560. //
  561. // Purpose: Handles API_THEMES_THEMEHOOKSOFF.
  562. //
  563. // History: 2000-10-10 vtan created
  564. // --------------------------------------------------------------------------
  565. NTSTATUS CThemeManagerAPIRequest::Execute_ThemeHooksOff (void)
  566. {
  567. NTSTATUS status;
  568. status = ImpersonateClientIfRequired();
  569. if (NT_SUCCESS(status))
  570. {
  571. API_THEMES_THEMEHOOKSOFF_OUT *pAPIOut;
  572. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiThemeHooksOff.out;
  573. pAPIOut->hr = ThemeHooksOff(_pSessionData->GetData());
  574. }
  575. SetDataLength(sizeof(API_THEMES));
  576. return(status);
  577. }
  578. // --------------------------------------------------------------------------
  579. // CThemeManagerAPIRequest::Execute_GetStatusFlags
  580. //
  581. // Arguments: <none>
  582. //
  583. // Returns: NTSTATUS
  584. //
  585. // Purpose: Handles API_THEMES_GETSTATUSFLAGS.
  586. //
  587. // History: 2000-10-10 vtan created
  588. // --------------------------------------------------------------------------
  589. NTSTATUS CThemeManagerAPIRequest::Execute_GetStatusFlags (void)
  590. {
  591. NTSTATUS status;
  592. status = ImpersonateClientIfRequired();
  593. if (NT_SUCCESS(status))
  594. {
  595. DWORD dwFlags;
  596. API_THEMES_GETSTATUSFLAGS_OUT *pAPIOut;
  597. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetStatusFlags.out;
  598. dwFlags = QTS_AVAILABLE;
  599. if (AreThemeHooksActive(_pSessionData->GetData()))
  600. {
  601. dwFlags |= QTS_RUNNING;
  602. }
  603. pAPIOut->dwFlags = dwFlags;
  604. }
  605. SetDataLength(sizeof(API_THEMES));
  606. return(status);
  607. }
  608. // --------------------------------------------------------------------------
  609. // CThemeManagerAPIRequest::Execute_GetCurrentChangeNumber
  610. //
  611. // Arguments: <none>
  612. //
  613. // Returns: NTSTATUS
  614. //
  615. // Purpose: Handles API_THEMES_GETCURRENTCHANGENUMBER.
  616. //
  617. // History: 2000-10-10 vtan created
  618. // --------------------------------------------------------------------------
  619. NTSTATUS CThemeManagerAPIRequest::Execute_GetCurrentChangeNumber (void)
  620. {
  621. NTSTATUS status;
  622. status = ImpersonateClientIfRequired();
  623. if (NT_SUCCESS(status))
  624. {
  625. API_THEMES_GETCURRENTCHANGENUMBER_OUT *pAPIOut;
  626. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetCurrentChangeNumber.out;
  627. pAPIOut->iChangeNumber = GetCurrentChangeNumber(_pSessionData->GetData());
  628. }
  629. SetDataLength(sizeof(API_THEMES));
  630. return(status);
  631. }
  632. // --------------------------------------------------------------------------
  633. // CThemeManagerAPIRequest::Execute_GetNewChangeNumber
  634. //
  635. // Arguments: <none>
  636. //
  637. // Returns: NTSTATUS
  638. //
  639. // Purpose: Handles API_THEMES_GETNEWCHANGENUMBER.
  640. //
  641. // History: 2000-10-10 vtan created
  642. // --------------------------------------------------------------------------
  643. NTSTATUS CThemeManagerAPIRequest::Execute_GetNewChangeNumber (void)
  644. {
  645. NTSTATUS status;
  646. status = ImpersonateClientIfRequired();
  647. if (NT_SUCCESS(status))
  648. {
  649. API_THEMES_GETNEWCHANGENUMBER_OUT *pAPIOut;
  650. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetNewChangeNumber.out;
  651. pAPIOut->iChangeNumber = GetNewChangeNumber(_pSessionData->GetData());
  652. }
  653. SetDataLength(sizeof(API_THEMES));
  654. return(status);
  655. }
  656. // --------------------------------------------------------------------------
  657. // CThemeManagerAPIRequest::Execute_SetGlobalTheme
  658. //
  659. // Arguments: <none>
  660. //
  661. // Returns: NTSTATUS
  662. //
  663. // Purpose: Handles API_THEMES_SETGLOBALTHEME.
  664. //
  665. // History: 2000-10-10 vtan created
  666. // --------------------------------------------------------------------------
  667. NTSTATUS CThemeManagerAPIRequest::Execute_SetGlobalTheme (void)
  668. {
  669. NTSTATUS status;
  670. // Note: we must not impersonate the user here, since we need write access to the section
  671. HANDLE hSection;
  672. API_THEMES_SETGLOBALTHEME_IN *pAPIIn;
  673. API_THEMES_SETGLOBALTHEME_OUT *pAPIOut;
  674. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSetGlobalTheme.in;
  675. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSetGlobalTheme.out;
  676. if (pAPIIn->hSection != NULL)
  677. {
  678. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  679. pAPIIn->hSection,
  680. GetCurrentProcess(),
  681. &hSection,
  682. FILE_MAP_ALL_ACCESS,
  683. FALSE,
  684. 0) != FALSE)
  685. {
  686. status = STATUS_SUCCESS;
  687. }
  688. else
  689. {
  690. status = CStatusCode::StatusCodeOfLastError();
  691. }
  692. }
  693. else
  694. {
  695. hSection = NULL;
  696. status = STATUS_SUCCESS;
  697. }
  698. if (NT_SUCCESS(status))
  699. {
  700. pAPIOut->hr = SetGlobalTheme(_pSessionData->GetData(), hSection);
  701. if (hSection != NULL)
  702. {
  703. TBOOL(CloseHandle(hSection));
  704. }
  705. }
  706. else
  707. {
  708. pAPIOut->hr = HRESULT_FROM_NT(status);
  709. }
  710. SetDataLength(sizeof(API_THEMES));
  711. return(STATUS_SUCCESS);
  712. }
  713. // --------------------------------------------------------------------------
  714. // CThemeManagerAPIRequest::Execute_MarkSection
  715. //
  716. // Arguments: <none>
  717. //
  718. // Returns: NTSTATUS
  719. //
  720. // Purpose: Handles API_THEMES_MARKSECTION.
  721. //
  722. // History: 2001-05-08 lmouton created
  723. // --------------------------------------------------------------------------
  724. NTSTATUS CThemeManagerAPIRequest::Execute_MarkSection (void)
  725. {
  726. NTSTATUS status;
  727. // Note: we must not impersonate the user here, since we need write access to the section
  728. HANDLE hSection;
  729. DWORD dwAdd;
  730. DWORD dwRemove;
  731. API_THEMES_MARKSECTION_IN *pAPIIn;
  732. API_THEMES_MARKSECTION_OUT *pAPIOut;
  733. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiMarkSection.in;
  734. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiMarkSection.out;
  735. dwAdd = pAPIIn->dwAdd;
  736. dwRemove = pAPIIn->dwRemove;
  737. if (pAPIIn->hSection != NULL)
  738. {
  739. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  740. pAPIIn->hSection,
  741. GetCurrentProcess(),
  742. &hSection,
  743. FILE_MAP_ALL_ACCESS,
  744. FALSE,
  745. 0) != FALSE)
  746. {
  747. status = STATUS_SUCCESS;
  748. }
  749. else
  750. {
  751. status = CStatusCode::StatusCodeOfLastError();
  752. DISPLAYMSG("Execute_MarkSection: Can't get a write handle");
  753. }
  754. }
  755. else
  756. {
  757. hSection = NULL;
  758. status = STATUS_SUCCESS;
  759. }
  760. if (NT_SUCCESS(status))
  761. {
  762. if (hSection != NULL)
  763. {
  764. MarkSection(hSection, dwAdd, dwRemove);
  765. TBOOL(CloseHandle(hSection));
  766. }
  767. }
  768. SetDataLength(sizeof(API_THEMES));
  769. return(STATUS_SUCCESS);
  770. }
  771. // --------------------------------------------------------------------------
  772. // CThemeManagerAPIRequest::Execute_GetGlobalTheme
  773. //
  774. // Arguments: <none>
  775. //
  776. // Returns: NTSTATUS
  777. //
  778. // Purpose: Handles API_THEMES_GETGLOBALTHEME.
  779. //
  780. // History: 2000-10-10 vtan created
  781. // --------------------------------------------------------------------------
  782. NTSTATUS CThemeManagerAPIRequest::Execute_GetGlobalTheme (void)
  783. {
  784. NTSTATUS status;
  785. status = ImpersonateClientIfRequired();
  786. if (NT_SUCCESS(status))
  787. {
  788. HRESULT hr;
  789. HANDLE hSection;
  790. API_THEMES_GETGLOBALTHEME_OUT *pAPIOut;
  791. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetGlobalTheme.out;
  792. hr = GetGlobalTheme(_pSessionData->GetData(), &hSection);
  793. if (SUCCEEDED(hr) && (hSection != NULL))
  794. {
  795. if (DuplicateHandle(GetCurrentProcess(),
  796. hSection,
  797. _pAPIDispatcher->GetClientProcess(),
  798. &pAPIOut->hSection,
  799. FILE_MAP_READ,
  800. FALSE,
  801. 0) != FALSE)
  802. {
  803. hr = S_OK;
  804. }
  805. else
  806. {
  807. DWORD dwErrorCode;
  808. dwErrorCode = GetLastError();
  809. hr = HRESULT_FROM_WIN32(dwErrorCode);
  810. }
  811. TBOOL(CloseHandle(hSection));
  812. }
  813. pAPIOut->hr = hr;
  814. }
  815. SetDataLength(sizeof(API_THEMES));
  816. return(status);
  817. }
  818. // --------------------------------------------------------------------------
  819. // LOADTHEME_STRINGS + supporting functions
  820. //
  821. // Purpose: Manages and validates LoadTheme string parameters
  822. //
  823. // History: 2002-02-26 scotthan created
  824. // --------------------------------------------------------------------------
  825. typedef struct
  826. {
  827. LPWSTR pszFilename;
  828. LPWSTR pszColor;
  829. LPWSTR pszSize;
  830. } LOADTHEME_STRINGS;
  831. #define MAX_THEME_STRING MAX_PATH
  832. // --------------------------------------------------------------------------
  833. void _FreeThemeStrings( IN LOADTHEME_STRINGS* plts )
  834. {
  835. if( plts )
  836. {
  837. _FreeMappedClientString(plts->pszFilename);
  838. _FreeMappedClientString(plts->pszColor);
  839. _FreeMappedClientString(plts->pszSize);
  840. delete plts;
  841. }
  842. }
  843. // --------------------------------------------------------------------------
  844. NTSTATUS _AllocAndMapThemeStrings(
  845. IN HANDLE hProcessClient,
  846. IN LPCWSTR pszFilenameIn,
  847. IN UINT cchFilenameIn,
  848. IN LPCWSTR pszColorIn,
  849. IN UINT cchColorIn,
  850. IN LPCWSTR pszSizeIn,
  851. IN UINT cchSizeIn,
  852. OUT LOADTHEME_STRINGS** pplts )
  853. {
  854. NTSTATUS status;
  855. ASSERTMSG(pplts != NULL, "_AllocAndMapThemeStrings: NULL outbound parameter, LOADTHEME_STRINGS**.");
  856. ASSERTMSG(hProcessClient != NULL, "_AllocAndMapThemeStrings: NULL process handle.");
  857. // note: cchFileNameIn, cchColorIn, cchSizeIn are char counts that include the NULL terminus.
  858. if( pszFilenameIn && pszColorIn && pszSizeIn &&
  859. cchFilenameIn > 0 && cchColorIn > 0 && cchSizeIn > 0 &&
  860. cchFilenameIn <= MAX_THEME_STRING && cchColorIn <= MAX_THEME_STRING && cchSizeIn <= MAX_THEME_STRING )
  861. {
  862. *pplts = NULL;
  863. LOADTHEME_STRINGS *plts = new LOADTHEME_STRINGS;
  864. if( plts != NULL )
  865. {
  866. ZeroMemory(plts, sizeof(*plts));
  867. status = _AllocAndMapClientString(hProcessClient, pszFilenameIn, cchFilenameIn, MAX_THEME_STRING, &plts->pszFilename);
  868. if( NT_SUCCESS(status) )
  869. {
  870. status = _AllocAndMapClientString(hProcessClient, pszColorIn, cchColorIn, MAX_THEME_STRING, &plts->pszColor);
  871. if( NT_SUCCESS(status) )
  872. {
  873. status = _AllocAndMapClientString(hProcessClient, pszSizeIn, cchSizeIn, MAX_THEME_STRING, &plts->pszSize);
  874. if( NT_SUCCESS(status) )
  875. {
  876. *pplts = plts;
  877. }
  878. }
  879. }
  880. if( !NT_SUCCESS(status) )
  881. {
  882. _FreeThemeStrings(plts);
  883. }
  884. }
  885. else
  886. {
  887. status = STATUS_NO_MEMORY;
  888. }
  889. }
  890. else
  891. {
  892. status = STATUS_INVALID_PARAMETER;
  893. }
  894. return status;
  895. }
  896. // --------------------------------------------------------------------------
  897. // CThemeManagerAPIRequest::Execute_CheckThemeSignature
  898. //
  899. // Arguments: <none>
  900. //
  901. // Returns: NTSTATUS
  902. //
  903. // Purpose: Handles API_THEMES_CHECKTHEMESIGNATURE.
  904. //
  905. // History: 2000-10-10 vtan created
  906. // --------------------------------------------------------------------------
  907. NTSTATUS CThemeManagerAPIRequest::Execute_CheckThemeSignature (void)
  908. {
  909. NTSTATUS status;
  910. status = ImpersonateClientIfRequired();
  911. if (NT_SUCCESS(status))
  912. {
  913. API_THEMES_CHECKTHEMESIGNATURE_IN *pAPIIn;
  914. API_THEMES_CHECKTHEMESIGNATURE_OUT *pAPIOut;
  915. LPWSTR pszThemeFileName;
  916. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiCheckThemeSignature.in;
  917. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiCheckThemeSignature.out;
  918. status = _AllocAndMapClientString(_pAPIDispatcher->GetClientProcess(),
  919. pAPIIn->pszName,
  920. pAPIIn->cchName,
  921. MAX_PATH,
  922. &pszThemeFileName);
  923. if( NT_SUCCESS(status) )
  924. {
  925. pAPIOut->hr = CheckThemeSignature(pszThemeFileName);
  926. status = STATUS_SUCCESS;
  927. _FreeMappedClientString(pszThemeFileName);
  928. }
  929. }
  930. SetDataLength(sizeof(API_THEMES));
  931. return(status);
  932. }
  933. // --------------------------------------------------------------------------
  934. // CThemeManagerAPIRequest::Execute_LoadTheme
  935. //
  936. // Arguments: <none>
  937. //
  938. // Returns: NTSTATUS
  939. //
  940. // Purpose: Handles API_THEMES_LOADTHEME.
  941. //
  942. // History: 2000-10-10 vtan created
  943. // --------------------------------------------------------------------------
  944. NTSTATUS CThemeManagerAPIRequest::Execute_LoadTheme (void)
  945. {
  946. NTSTATUS status;
  947. BOOL fTcb = NT_SUCCESS(ClientHasTcbPrivilege());
  948. status = ImpersonateClientIfRequired();
  949. if (NT_SUCCESS(status))
  950. {
  951. HANDLE hProcessClient;
  952. API_THEMES_LOADTHEME_IN *pAPIIn;
  953. API_THEMES_LOADTHEME_OUT *pAPIOut;
  954. LOADTHEME_STRINGS* plts;
  955. hProcessClient = _pAPIDispatcher->GetClientProcess();
  956. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiLoadTheme.in;
  957. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiLoadTheme.out;
  958. status = _AllocAndMapThemeStrings( hProcessClient, pAPIIn->pszName, pAPIIn->cchName,
  959. pAPIIn->pszColor, pAPIIn->cchColor,
  960. pAPIIn->pszSize, pAPIIn->cchSize,
  961. &plts );
  962. if( NT_SUCCESS(status) )
  963. {
  964. HANDLE hSectionIn, hSectionOut;
  965. if (DuplicateHandle(hProcessClient,
  966. pAPIIn->hSection,
  967. GetCurrentProcess(),
  968. &hSectionIn,
  969. FILE_MAP_ALL_ACCESS,
  970. FALSE,
  971. 0) != FALSE)
  972. {
  973. status = STATUS_SUCCESS;
  974. // Only clients with TCB privilege can load a global theme section.
  975. // We don't want stock object ownership here; let the client clean them up on failure.
  976. DWORD dwLoadFlags = fTcb ? LTF_GLOBALPRIVILEGEDCLIENT : 0;
  977. // Warning: this function will revert to self in order to create the section in system context.
  978. // Impersonate the user again after it if needed
  979. pAPIOut->hr = LoadTheme(_pSessionData->GetData(), hSectionIn, &hSectionOut,
  980. plts->pszFilename, plts->pszColor, plts->pszSize, dwLoadFlags);
  981. if (SUCCEEDED(pAPIOut->hr))
  982. {
  983. // Still running in the system context here
  984. if (DuplicateHandle(GetCurrentProcess(),
  985. hSectionOut,
  986. hProcessClient,
  987. &pAPIOut->hSection,
  988. FILE_MAP_READ,
  989. FALSE,
  990. 0) == FALSE)
  991. {
  992. status = CStatusCode::StatusCodeOfLastError();
  993. }
  994. TBOOL(CloseHandle(hSectionOut));
  995. }
  996. TBOOL(CloseHandle(hSectionIn));
  997. }
  998. else
  999. {
  1000. status = CStatusCode::StatusCodeOfLastError();
  1001. }
  1002. _FreeThemeStrings(plts);
  1003. }
  1004. }
  1005. SetDataLength(sizeof(API_THEMES));
  1006. return(status);
  1007. }
  1008. // --------------------------------------------------------------------------
  1009. // CThemeManagerAPIRequest::Execute_ProcessLoadTheme
  1010. //
  1011. // Arguments: <none>
  1012. //
  1013. // Returns: NTSTATUS
  1014. //
  1015. // Purpose: Handles API_THEMES_PROCESSLOADTHEME.
  1016. //
  1017. // History: 2002-02-26 scotthan created
  1018. // --------------------------------------------------------------------------
  1019. NTSTATUS CThemeManagerAPIRequest::Execute_ProcessLoadTheme(
  1020. CAPIDispatchSync* pAPIDispatchSync)
  1021. {
  1022. NTSTATUS status;
  1023. CLoaderProcess *pLoader = NULL;
  1024. API_THEMES_PROCESSLOADTHEME_IN *pAPIIn;
  1025. API_THEMES_PROCESSLOADTHEME_OUT *pAPIOut;
  1026. HANDLE hProcessClient;
  1027. HANDLE hLoaderProcess = NULL;
  1028. s_pLock->Acquire();
  1029. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiProcessLoadTheme.in;
  1030. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiProcessLoadTheme.out;
  1031. hProcessClient = _pAPIDispatcher->GetClientProcess();
  1032. if( !CAPIDispatchSync::IsServiceStopping(pAPIDispatchSync) )
  1033. {
  1034. status = _pSessionData->GetLoaderProcess(&pLoader);
  1035. if( NT_SUCCESS(status) )
  1036. {
  1037. status =
  1038. // do we already have a loader?
  1039. status = pLoader->IsAlive() ? STATUS_ACCESS_DENIED : STATUS_SUCCESS;
  1040. if( NT_SUCCESS(status) )
  1041. {
  1042. status = ImpersonateClientIfRequired();
  1043. if (NT_SUCCESS(status))
  1044. {
  1045. LOADTHEME_STRINGS* plts;
  1046. if( NT_SUCCESS(status) )
  1047. {
  1048. status = _AllocAndMapThemeStrings( hProcessClient,
  1049. pAPIIn->pszName, pAPIIn->cchName,
  1050. pAPIIn->pszColor, pAPIIn->cchColor,
  1051. pAPIIn->pszSize, pAPIIn->cchSize,
  1052. &plts );
  1053. if( NT_SUCCESS(status) )
  1054. {
  1055. HANDLE hTokenClient;
  1056. if( OpenProcessToken(hProcessClient,
  1057. TOKEN_ASSIGN_PRIMARY| TOKEN_DUPLICATE | TOKEN_QUERY,
  1058. &hTokenClient) )
  1059. {
  1060. // SECURITY: Launch process with client credentials to load the theme.
  1061. status = pLoader->Create(_pSessionData->GetData(), hTokenClient, NULL,
  1062. plts->pszFilename, plts->pszColor, plts->pszSize,
  1063. &hLoaderProcess);
  1064. CloseHandle(hTokenClient);
  1065. }
  1066. else
  1067. {
  1068. status = CStatusCode::StatusCodeOfLastError();
  1069. }
  1070. _FreeThemeStrings(plts);
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. }
  1077. else // !CThemeManagerService::'()
  1078. {
  1079. status = STATUS_PORT_DISCONNECTED;
  1080. }
  1081. s_pLock->Release();
  1082. pAPIOut->hSection = NULL;
  1083. pAPIOut->hr = E_FAIL;
  1084. // If we launched a loader process, block until its finished
  1085. if( NT_SUCCESS(status) )
  1086. {
  1087. ASSERTMSG(hLoaderProcess != NULL, "CThemeManagerAPIRequest::Execute_ProcessLoadTheme - NULL loader process.");
  1088. HANDLE hStopEvent = CAPIDispatchSync::GetServiceStoppingEvent(pAPIDispatchSync);
  1089. ASSERTMSG(hStopEvent != NULL, "CThemeManagerAPIRequest::Execute_ProcessLoadTheme - NULL Stop event");
  1090. HANDLE rgHandles[2];
  1091. rgHandles[0] = hLoaderProcess;
  1092. rgHandles[1] = hStopEvent;
  1093. // paranoia: assign default status in case we fall out
  1094. status = STATUS_REQUEST_ABORTED;
  1095. DWORD dwWait = WaitForMultipleObjects(ARRAYSIZE(rgHandles), rgHandles, FALSE, PROCESSLOADERWAIT);
  1096. switch(dwWait)
  1097. {
  1098. case WAIT_OBJECT_0: // hLoaderProcess
  1099. status = STATUS_SUCCESS;
  1100. break;
  1101. case WAIT_OBJECT_0+1: // hStopEvent
  1102. status = STATUS_PORT_DISCONNECTED;
  1103. break;
  1104. case WAIT_TIMEOUT:
  1105. status = STATUS_TIMEOUT;
  1106. DISPLAYMSG("Execute_ProcessLoadTheme - Timed out waiting for loader process.");
  1107. break;
  1108. }
  1109. // default the LPC return code to current status code
  1110. pAPIOut->hr = HRESULT_FROM_NT(status);
  1111. // By the time the process is finished, we'll have a theme memory section
  1112. // stored in the loader process object, transacted via API_THEMES_PROCESSASSIGNSECTION.
  1113. // Let's fetch it and hand it back to our caller.
  1114. s_pLock->Acquire();
  1115. NTSTATUS statusLoader = _pSessionData->GetLoaderProcess(&pLoader);
  1116. if( NT_SUCCESS(statusLoader) )
  1117. {
  1118. HANDLE hSectionOut = pLoader->GetSectionHandle(TRUE);
  1119. // did we unblock from the loader?
  1120. if( NT_SUCCESS(status) )
  1121. {
  1122. pAPIOut->hr = pLoader->GetHResult();
  1123. #ifdef DEBUG
  1124. if( SUCCEEDED(pAPIOut->hr) )
  1125. {
  1126. ASSERTMSG(hSectionOut != NULL, "CThemeManagerAPIRequest::Execute_ProcessLoadTheme - Success means valid section handle!");
  1127. }
  1128. #endif DEBUG
  1129. if( hSectionOut )
  1130. {
  1131. BOOL fDuped = DuplicateHandle(GetCurrentProcess(),
  1132. hSectionOut,
  1133. hProcessClient,
  1134. &pAPIOut->hSection,
  1135. FILE_MAP_READ,
  1136. FALSE,
  1137. 0);
  1138. // Still running in the system context here
  1139. if( !fDuped )
  1140. {
  1141. // couldn't duplicate handle. This means we'll never clean stock objects.
  1142. ASSERTMSG(fDuped, "Failed to duplicate theme handle; leaking visual style stock objects");
  1143. status = CStatusCode::StatusCodeOfLastError();
  1144. pAPIOut->hr = HRESULT_FROM_NT(status);
  1145. }
  1146. }
  1147. }
  1148. else
  1149. {
  1150. ASSERTMSG(pAPIOut->hr == HRESULT_FROM_NT(status),
  1151. "CThemeManagerAPIRequest::Execute_ProcessLoadTheme - failing to preserve proper status errror code.");
  1152. if( hSectionOut )
  1153. {
  1154. THR(ServiceClearStockObjects(_pSessionData->GetData(), hSectionOut));
  1155. pAPIOut->hSection = NULL;
  1156. }
  1157. }
  1158. if( hSectionOut )
  1159. {
  1160. CloseHandle(hSectionOut);
  1161. }
  1162. // prepare the loader object for the next request.
  1163. pLoader->Clear(_pSessionData->GetData(), TRUE);
  1164. }
  1165. else // NT_SUCCESS(_pSessionData->GetLoaderProcess).
  1166. {
  1167. status = statusLoader;
  1168. pAPIOut->hr = HRESULT_FROM_NT(status);
  1169. }
  1170. s_pLock->Release();
  1171. }
  1172. else
  1173. {
  1174. pAPIOut->hr = HRESULT_FROM_NT(status);
  1175. }
  1176. SetDataLength(sizeof(API_THEMES));
  1177. return(status);
  1178. }
  1179. // --------------------------------------------------------------------------
  1180. // CThemeManagerAPIRequest::Execute_ProcessAssignSection
  1181. //
  1182. // Arguments: <none>
  1183. //
  1184. // Returns: NTSTATUS
  1185. //
  1186. // Purpose: Handles API_THEMES_PROCESSASSIGNSECTION.
  1187. //
  1188. // History: 2002-02-26 scotthan created
  1189. // --------------------------------------------------------------------------
  1190. NTSTATUS CThemeManagerAPIRequest::Execute_ProcessAssignSection (void)
  1191. {
  1192. // Note: The following must be true for this part of the
  1193. // Load/ApplySecureTheme sequence to be truly secure:
  1194. //
  1195. // 1. There is a theme service worker thread handling API_THEMES_PROCESSLOADTHEME
  1196. // now. That handler launched a secure session loader process,
  1197. // 2. The API_THEMES_PROCESSLOADTHEME handler's thread is waiting for
  1198. // secure session loader process to terminate.
  1199. // 3. The only process that should be sending the API_THEMES_PROCESSASSIGNSECTION request
  1200. // is the same secure session loader process.
  1201. // _data is a hippo-union; store off in params to init out params
  1202. API_THEMES_PROCESSASSIGNSECTION_IN *pAPIIn;
  1203. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiProcessAssignSection.in;
  1204. HRESULT hrClient = pAPIIn->hrLoad;
  1205. HANDLE hClientSection = pAPIIn->hSection;
  1206. // init out params
  1207. API_THEMES_PROCESSASSIGNSECTION_OUT *pAPIOut;
  1208. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiProcessAssignSection.out;
  1209. pAPIOut->hr = E_FAIL;
  1210. // all of this takes place under the session data lock.
  1211. s_pLock->Acquire();
  1212. CLoaderProcess* pLoader = NULL;
  1213. NTSTATUS status = _pSessionData->GetLoaderProcess(&pLoader);
  1214. if( NT_SUCCESS(status) )
  1215. {
  1216. HANDLE hProcessClient = _pAPIDispatcher->GetClientProcess();
  1217. if( pLoader->IsProcessLoader(hProcessClient) )
  1218. {
  1219. // manage errors as nt status codes until the very end.
  1220. status = hrClient & ~FACILITY_NT_BIT;
  1221. // any work to do?
  1222. if( NT_SUCCESS(status) )
  1223. {
  1224. status = ImpersonateClientIfRequired();
  1225. if( NT_SUCCESS(status) )
  1226. {
  1227. HANDLE hSectionReadWrite = NULL;
  1228. // Map the incoming read-write section handle to
  1229. // theme service's address space
  1230. if (DuplicateHandle(hProcessClient,
  1231. hClientSection,
  1232. GetCurrentProcess(),
  1233. &hSectionReadWrite,
  1234. FILE_MAP_ALL_ACCESS,
  1235. FALSE,
  1236. 0) != FALSE)
  1237. {
  1238. // Copy the incoming read-write section to a read-only section, update the theme change count
  1239. // Warning: this function will revert to self in order to create the
  1240. // section in the system context. Impersonate the user again after it if needed
  1241. HANDLE hSectionReadOnly = NULL;
  1242. status = pLoader->ValidateAndCopySection(_pSessionData->GetData(),
  1243. hSectionReadWrite,
  1244. &hSectionReadOnly);
  1245. // no longer don't need our dupe of the incoming, read-write section.
  1246. CloseHandle(hSectionReadWrite);
  1247. }
  1248. else // DuplicateHandle
  1249. {
  1250. status = CStatusCode::StatusCodeOfLastError();
  1251. pLoader->SetHResult(HRESULT_FROM_NT(status));
  1252. }
  1253. }
  1254. else // NT_SUCCESS(ImpersonateClientIfRequired)
  1255. {
  1256. status = CStatusCode::StatusCodeOfLastError();
  1257. pLoader->SetHResult(HRESULT_FROM_NT(status));
  1258. }
  1259. }
  1260. else // SUCCEEDED(hrClient)
  1261. {
  1262. pLoader->SetHResult(HRESULT_FROM_NT(status));
  1263. DISPLAYMSG("CThemeManagerAPIRequest::Execute_ProcessAssignSection: client failed section creation");
  1264. }
  1265. }
  1266. else // CLoaderProcess::IsProcessLoader
  1267. {
  1268. status = E_ACCESSDENIED;
  1269. DISPLAYMSG("CThemeManagerAPIRequest::Execute_ProcessAssignSection::IsProcessLoader failed");
  1270. }
  1271. }
  1272. pAPIOut->hr = HRESULT_FROM_NT(status);
  1273. s_pLock->Release();
  1274. SetDataLength(sizeof(API_THEMES));
  1275. return(status);
  1276. }
  1277. // --------------------------------------------------------------------------
  1278. // CThemeManagerAPIRequest::Execute_UserLogon
  1279. //
  1280. // Arguments: <none>
  1281. //
  1282. // Returns: NTSTATUS
  1283. //
  1284. // Purpose: Handles API_THEMES_USERLOGON. To call this API you must have
  1285. // the SE_TCB_PRIVILEGE in your token.
  1286. //
  1287. // History: 2000-10-12 vtan created
  1288. // --------------------------------------------------------------------------
  1289. NTSTATUS CThemeManagerAPIRequest::Execute_UserLogon (void)
  1290. {
  1291. NTSTATUS status;
  1292. status = ClientHasTcbPrivilege();
  1293. if (NT_SUCCESS(status))
  1294. {
  1295. HANDLE hToken;
  1296. API_THEMES_USERLOGON_IN *pAPIIn;
  1297. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiUserLogon.in;
  1298. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  1299. pAPIIn->hToken,
  1300. GetCurrentProcess(),
  1301. &hToken,
  1302. 0,
  1303. FALSE,
  1304. DUPLICATE_SAME_ACCESS) != FALSE)
  1305. {
  1306. status = _pSessionData->UserLogon(hToken);
  1307. TBOOL(CloseHandle(hToken));
  1308. }
  1309. else
  1310. {
  1311. status = CStatusCode::StatusCodeOfLastError();
  1312. }
  1313. }
  1314. SetDataLength(sizeof(API_THEMES));
  1315. return(status);
  1316. }
  1317. // --------------------------------------------------------------------------
  1318. // CThemeManagerAPIRequest::Execute_UserLogoff
  1319. //
  1320. // Arguments: <none>
  1321. //
  1322. // Returns: NTSTATUS
  1323. //
  1324. // Purpose: Handles API_THEMES_USERLOGOFF. To call this API you must have
  1325. // the SE_TCB_PRIVILEGE in your token.
  1326. //
  1327. // History: 2000-10-12 vtan created
  1328. // --------------------------------------------------------------------------
  1329. NTSTATUS CThemeManagerAPIRequest::Execute_UserLogoff (void)
  1330. {
  1331. NTSTATUS status;
  1332. status = ClientHasTcbPrivilege();
  1333. if (NT_SUCCESS(status))
  1334. {
  1335. status = _pSessionData->UserLogoff();
  1336. }
  1337. SetDataLength(sizeof(API_THEMES));
  1338. return(status);
  1339. }
  1340. // --------------------------------------------------------------------------
  1341. // CThemeManagerAPIRequest::Execute_SessionCreate
  1342. //
  1343. // Arguments: <none>
  1344. //
  1345. // Returns: NTSTATUS
  1346. //
  1347. // Purpose: Handles API_THEMES_SESSIONCREATE. To call this API you must
  1348. // have the SE_TCB_PRIVILEGE in your token.
  1349. //
  1350. // History: 2000-11-09 vtan created
  1351. // --------------------------------------------------------------------------
  1352. NTSTATUS CThemeManagerAPIRequest::Execute_SessionCreate (void)
  1353. {
  1354. NTSTATUS status;
  1355. status = ClientHasTcbPrivilege();
  1356. if (NT_SUCCESS(status))
  1357. {
  1358. HANDLE hProcessClient;
  1359. CThemeManagerSessionData *pSessionData;
  1360. ASSERTMSG(_pSessionData == NULL, "Session data already exists in CThemeManagerAPIRequest::Execute_SessionCreate");
  1361. if (DuplicateHandle(GetCurrentProcess(),
  1362. _pAPIDispatcher->GetClientProcess(),
  1363. GetCurrentProcess(),
  1364. &hProcessClient,
  1365. PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE,
  1366. FALSE,
  1367. 0) != FALSE)
  1368. {
  1369. DWORD dwSessionID;
  1370. dwSessionID = _pAPIDispatcher->GetClientSessionID();
  1371. pSessionData = new CThemeManagerSessionData(dwSessionID);
  1372. if (pSessionData != NULL)
  1373. {
  1374. API_THEMES_SESSIONCREATE_IN *pAPIIn;
  1375. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSessionCreate.in;
  1376. status = pSessionData->Allocate(hProcessClient,
  1377. s_dwServerChangeNumber,
  1378. pAPIIn->pfnRegister,
  1379. pAPIIn->pfnUnregister,
  1380. pAPIIn->pfnClearStockObjects,
  1381. pAPIIn->dwStackSizeReserve,
  1382. pAPIIn->dwStackSizeCommit);
  1383. if (NT_SUCCESS(status))
  1384. {
  1385. int iIndex;
  1386. CSingleThreadedExecution lock(*s_pLock);
  1387. // Find the session data in the static array. If found
  1388. // then remove the entry (don't allow duplicates).
  1389. iIndex = FindIndexSessionData(dwSessionID);
  1390. if (iIndex >= 0)
  1391. {
  1392. status = s_pSessionData->Remove(iIndex);
  1393. }
  1394. // If the static array has been destroyed (the service has been
  1395. // stopped) then don't do anything - this is not an error.
  1396. if (NT_SUCCESS(status) && (s_pSessionData != NULL))
  1397. {
  1398. status = s_pSessionData->Add(pSessionData);
  1399. }
  1400. }
  1401. pSessionData->Release();
  1402. }
  1403. else
  1404. {
  1405. status = STATUS_NO_MEMORY;
  1406. }
  1407. TBOOL(CloseHandle(hProcessClient));
  1408. }
  1409. else
  1410. {
  1411. status = CStatusCode::StatusCodeOfLastError();
  1412. }
  1413. }
  1414. SetDataLength(sizeof(API_THEMES));
  1415. return(status);
  1416. }
  1417. // --------------------------------------------------------------------------
  1418. // CThemeManagerAPIRequest::Execute_SessionDestroy
  1419. //
  1420. // Arguments: <none>
  1421. //
  1422. // Returns: NTSTATUS
  1423. //
  1424. // Purpose: Handles API_THEMES_SESSIONDESTROY. To call this API you must
  1425. // have the SE_TCB_PRIVILEGE in your token.
  1426. //
  1427. // History: 2000-11-09 vtan created
  1428. // --------------------------------------------------------------------------
  1429. NTSTATUS CThemeManagerAPIRequest::Execute_SessionDestroy (void)
  1430. {
  1431. NTSTATUS status;
  1432. status = ClientHasTcbPrivilege();
  1433. if (NT_SUCCESS(status))
  1434. {
  1435. int iIndex;
  1436. CSingleThreadedExecution lock(*s_pLock);
  1437. iIndex = FindIndexSessionData(_pAPIDispatcher->GetClientSessionID());
  1438. if (iIndex >= 0)
  1439. {
  1440. status = s_pSessionData->Remove(iIndex);
  1441. }
  1442. else
  1443. {
  1444. status = STATUS_SUCCESS;
  1445. }
  1446. }
  1447. SetDataLength(sizeof(API_THEMES));
  1448. return(status);
  1449. }
  1450. // --------------------------------------------------------------------------
  1451. // CThemeManagerAPIRequest::Execute_Ping
  1452. //
  1453. // Arguments: <none>
  1454. //
  1455. // Returns: NTSTATUS
  1456. //
  1457. // Purpose: Handles API_THEMES_PING. Tell the client we're alive.
  1458. //
  1459. // History: 2000-11-30 vtan created
  1460. // --------------------------------------------------------------------------
  1461. NTSTATUS CThemeManagerAPIRequest::Execute_Ping (void)
  1462. {
  1463. SetDataLength(sizeof(API_THEMES));
  1464. return(STATUS_SUCCESS);
  1465. }