Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1348 lines
41 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 <LPCThemes.h>
  14. #include <uxthemep.h>
  15. #include <UxThemeServer.h>
  16. #include "RegistryResources.h"
  17. #include "SingleThreadedExecution.h"
  18. #include "StatusCode.h"
  19. #include "TokenInformation.h"
  20. // --------------------------------------------------------------------------
  21. // CThemeManagerAPIRequest::s_pSessionData
  22. //
  23. // Purpose: Static member variables.
  24. //
  25. // History: 2000-11-09 vtan created
  26. // --------------------------------------------------------------------------
  27. CDynamicCountedObjectArray* CThemeManagerAPIRequest::s_pSessionData = NULL;
  28. CCriticalSection* CThemeManagerAPIRequest::s_pLock = NULL;
  29. DWORD CThemeManagerAPIRequest::s_dwServerChangeNumber = 0;
  30. const TCHAR CThemeManagerAPIRequest::s_szServerChangeNumberValue[] = TEXT("ServerChangeNumber");
  31. // --------------------------------------------------------------------------
  32. // CThemeManagerAPIRequest::CThemeManagerAPIRequest
  33. //
  34. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  35. // pAPIConnection = CAPIConnection for access change.
  36. //
  37. // Returns: <none>
  38. //
  39. // Purpose: Constructor for the CThemeManagerAPIRequest class. It just passes the
  40. // control to the super class.
  41. //
  42. // History: 2000-10-10 vtan created
  43. // --------------------------------------------------------------------------
  44. CThemeManagerAPIRequest::CThemeManagerAPIRequest (CAPIDispatcher* pAPIDispatcher) :
  45. CAPIRequest(pAPIDispatcher),
  46. _hToken(NULL),
  47. _pSessionData(NULL)
  48. {
  49. }
  50. // --------------------------------------------------------------------------
  51. // CThemeManagerAPIRequest::CThemeManagerAPIRequest
  52. //
  53. // Arguments: pAPIDispatcher = CAPIDispatcher that calls this object.
  54. // pAPIConnection = CAPIConnection for access change.
  55. // portMessage = CPortMessage to copy construct.
  56. //
  57. // Returns: <none>
  58. //
  59. // Purpose: Constructor for the CThemeManagerAPIRequest class. It just
  60. // passes the control to the super class.
  61. //
  62. // History: 2000-10-10 vtan created
  63. // --------------------------------------------------------------------------
  64. CThemeManagerAPIRequest::CThemeManagerAPIRequest (CAPIDispatcher* pAPIDispatcher, const CPortMessage& portMessage) :
  65. CAPIRequest(pAPIDispatcher, portMessage),
  66. _hToken(NULL),
  67. _pSessionData(NULL)
  68. {
  69. }
  70. // --------------------------------------------------------------------------
  71. // CThemeManagerAPIRequest::~CThemeManagerAPIRequest
  72. //
  73. // Arguments: <none>
  74. //
  75. // Returns: <none>
  76. //
  77. // Purpose: Destructor for the CThemeManagerAPIRequest class.
  78. //
  79. // History: 2000-10-10 vtan created
  80. // --------------------------------------------------------------------------
  81. CThemeManagerAPIRequest::~CThemeManagerAPIRequest (void)
  82. {
  83. ASSERTMSG(_hToken == NULL, "Impersonation token not released in CThemeManagerAPIRequest::~CThemeManagerAPIRequest");
  84. }
  85. // --------------------------------------------------------------------------
  86. // CThemeManagerAPIRequest::Execute
  87. //
  88. // Arguments: <none>
  89. //
  90. // Returns: NTSTATUS
  91. //
  92. // Purpose: Execute implementation for theme manager API requests. This
  93. // function dispatches requests based on the API request number.
  94. //
  95. // History: 2000-10-10 vtan created
  96. // --------------------------------------------------------------------------
  97. NTSTATUS CThemeManagerAPIRequest::Execute (void)
  98. {
  99. NTSTATUS status;
  100. unsigned long ulAPINumber;
  101. ulAPINumber = reinterpret_cast<API_THEMES*>(&_data)->apiGeneric.ulAPINumber & API_GENERIC_NUMBER_MASK;
  102. // First try and get the client session data. If this fails then
  103. // there's no object to execute the request on. Fail it.
  104. // Exception to this is API_THEMES_SESSIONCREATE which creates one.
  105. // Note: GetClientSessionData will store the session data in the
  106. // _pSessionData member variable. While doing so it will increase
  107. // reference count on this so that it doesn't get pulled from the
  108. // array while the API request is being executed. The reference is
  109. // released at the end of this function.
  110. status = GetClientSessionData();
  111. if (NT_SUCCESS(status) || (ulAPINumber == API_THEMES_SESSIONCREATE))
  112. {
  113. switch (ulAPINumber)
  114. {
  115. case API_THEMES_THEMEHOOKSON:
  116. status = Execute_ThemeHooksOn();
  117. break;
  118. case API_THEMES_THEMEHOOKSOFF:
  119. status = Execute_ThemeHooksOff();
  120. break;
  121. case API_THEMES_GETSTATUSFLAGS:
  122. status = Execute_GetStatusFlags();
  123. break;
  124. case API_THEMES_GETCURRENTCHANGENUMBER:
  125. status = Execute_GetCurrentChangeNumber();
  126. break;
  127. case API_THEMES_GETNEWCHANGENUMBER:
  128. status = Execute_GetNewChangeNumber();
  129. break;
  130. case API_THEMES_SETGLOBALTHEME:
  131. status = Execute_SetGlobalTheme();
  132. break;
  133. case API_THEMES_MARKSECTION:
  134. status = Execute_MarkSection();
  135. break;
  136. case API_THEMES_GETGLOBALTHEME:
  137. status = Execute_GetGlobalTheme();
  138. break;
  139. case API_THEMES_CHECKTHEMESIGNATURE:
  140. status = Execute_CheckThemeSignature();
  141. break;
  142. case API_THEMES_LOADTHEME:
  143. status = Execute_LoadTheme();
  144. break;
  145. case API_THEMES_USERLOGON:
  146. status = Execute_UserLogon();
  147. break;
  148. case API_THEMES_USERLOGOFF:
  149. status = Execute_UserLogoff();
  150. break;
  151. case API_THEMES_SESSIONCREATE:
  152. status = Execute_SessionCreate();
  153. break;
  154. case API_THEMES_SESSIONDESTROY:
  155. status = Execute_SessionDestroy();
  156. break;
  157. case API_THEMES_PING:
  158. status = Execute_Ping();
  159. break;
  160. default:
  161. DISPLAYMSG("Unknown API request in CThemeManagerAPIRequest::Execute");
  162. status = STATUS_NOT_IMPLEMENTED;
  163. break;
  164. }
  165. }
  166. // If the execution function needed to impersonate the client then
  167. // revert here and release the token used.
  168. if (_hToken != NULL)
  169. {
  170. TBOOL(RevertToSelf());
  171. ReleaseHandle(_hToken);
  172. }
  173. // Release the _pSessionData object now. NULL it out to prevent
  174. // accidentally using it after being released.
  175. if (_pSessionData != NULL)
  176. {
  177. _pSessionData->Release();
  178. _pSessionData = NULL;
  179. }
  180. // Return to caller.
  181. TSTATUS(status);
  182. return(status);
  183. }
  184. // --------------------------------------------------------------------------
  185. // CThemeManagerAPIRequest::SessionDestroy
  186. //
  187. // Arguments: dwSessionID = Session ID to destroy.
  188. //
  189. // Returns: NTSTATUS
  190. //
  191. // Purpose: External entry point for session client (winlogon) watcher.
  192. // When winlogon dies we clean up the session information for
  193. // that session and release resources.
  194. //
  195. // History: 2000-12-09 vtan created
  196. // --------------------------------------------------------------------------
  197. NTSTATUS CThemeManagerAPIRequest::SessionDestroy (DWORD dwSessionID)
  198. {
  199. NTSTATUS status;
  200. int iIndex;
  201. CSingleThreadedExecution lock(*s_pLock);
  202. iIndex = FindIndexSessionData(dwSessionID);
  203. if (iIndex >= 0)
  204. {
  205. status = s_pSessionData->Remove(iIndex);
  206. }
  207. else
  208. {
  209. status = STATUS_SUCCESS;
  210. }
  211. return(status);
  212. }
  213. // --------------------------------------------------------------------------
  214. // CThemeManagerAPIRequest::InitializeServerChangeNumber
  215. //
  216. // Arguments: <none>
  217. //
  218. // Returns: NTSTATUS
  219. //
  220. // Purpose: Initializes the static server change number. Every time the
  221. // service starts up this number is incremented. If the number
  222. // isn't present then 0 is used.
  223. //
  224. // History: 2000-12-09 vtan created
  225. // 2000-12-09 vtan split from StaticInitialize
  226. // --------------------------------------------------------------------------
  227. NTSTATUS CThemeManagerAPIRequest::InitializeServerChangeNumber (void)
  228. {
  229. LONG lErrorCodeOpen, lErrorCodeRead;
  230. DWORD dwServerChangeNumber;
  231. CRegKey regKey;
  232. dwServerChangeNumber = s_dwServerChangeNumber;
  233. // Initialize the static member variable now in case of failure.
  234. // We ignore failures because at GUI setup the key does NOT exist
  235. // because the server dll hasn't been regsvr'd yet. After GUI setup
  236. // this gets regsvr'd and the key exists and we are happy campers.
  237. lErrorCodeOpen = regKey.Open(HKEY_LOCAL_MACHINE,
  238. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"),
  239. KEY_QUERY_VALUE | KEY_SET_VALUE);
  240. if (ERROR_SUCCESS == lErrorCodeOpen)
  241. {
  242. lErrorCodeRead = regKey.GetDWORD(s_szServerChangeNumberValue, dwServerChangeNumber);
  243. }
  244. else
  245. {
  246. lErrorCodeRead = ERROR_FILE_NOT_FOUND;
  247. }
  248. dwServerChangeNumber = static_cast<WORD>(dwServerChangeNumber + 1);
  249. if ((ERROR_SUCCESS == lErrorCodeOpen) && (ERROR_SUCCESS == lErrorCodeRead))
  250. {
  251. TW32(regKey.SetDWORD(s_szServerChangeNumberValue, dwServerChangeNumber));
  252. }
  253. s_dwServerChangeNumber = dwServerChangeNumber;
  254. return(STATUS_SUCCESS);
  255. }
  256. // --------------------------------------------------------------------------
  257. // CThemeManagerAPIRequest::StaticInitialize
  258. //
  259. // Arguments: <none>
  260. //
  261. // Returns: NTSTATUS
  262. //
  263. // Purpose: Static initializer for the class.
  264. //
  265. // History: 2000-10-10 vtan created
  266. // --------------------------------------------------------------------------
  267. NTSTATUS CThemeManagerAPIRequest::StaticInitialize (void)
  268. {
  269. NTSTATUS status;
  270. status = STATUS_SUCCESS;
  271. if (s_pLock == NULL)
  272. {
  273. s_pLock = new CCriticalSection;
  274. if (s_pLock != NULL)
  275. {
  276. status = s_pLock->Status();
  277. if (!NT_SUCCESS(status))
  278. {
  279. delete s_pLock;
  280. s_pLock = NULL;
  281. }
  282. }
  283. else
  284. {
  285. status = STATUS_NO_MEMORY;
  286. }
  287. }
  288. return(status);
  289. }
  290. // --------------------------------------------------------------------------
  291. // CThemeManagerAPIRequest::StaticTerminate
  292. //
  293. // Arguments: <none>
  294. //
  295. // Returns: NTSTATUS
  296. //
  297. // Purpose: Static destructor for the class.
  298. //
  299. // History: 2000-10-10 vtan created
  300. // --------------------------------------------------------------------------
  301. NTSTATUS CThemeManagerAPIRequest::StaticTerminate (void)
  302. {
  303. if (s_pLock != NULL)
  304. {
  305. delete s_pLock;
  306. s_pLock = NULL;
  307. }
  308. return(STATUS_SUCCESS);
  309. }
  310. // --------------------------------------------------------------------------
  311. // CThemeManagerAPIRequest::ArrayInitialize
  312. //
  313. // Arguments: <none>
  314. //
  315. // Returns: NTSTATUS
  316. //
  317. // Purpose: Initializes (allocates) the session array.
  318. //
  319. // History: 2001-01-05 vtan created
  320. // --------------------------------------------------------------------------
  321. NTSTATUS CThemeManagerAPIRequest::ArrayInitialize (void)
  322. {
  323. NTSTATUS status;
  324. CSingleThreadedExecution lock(*s_pLock);
  325. status = STATUS_SUCCESS;
  326. if (s_pSessionData == NULL)
  327. {
  328. s_pSessionData = new CDynamicCountedObjectArray;
  329. if (s_pSessionData == NULL)
  330. {
  331. status = STATUS_NO_MEMORY;
  332. }
  333. }
  334. return(status);
  335. }
  336. // --------------------------------------------------------------------------
  337. // CThemeManagerAPIRequest::ArrayTerminate
  338. //
  339. // Arguments: <none>
  340. //
  341. // Returns: NTSTATUS
  342. //
  343. // Purpose: Releases all objects in the session array (removes the waits)
  344. // and releases the session array object.
  345. //
  346. // History: 2001-01-05 vtan created
  347. // --------------------------------------------------------------------------
  348. NTSTATUS CThemeManagerAPIRequest::ArrayTerminate (void)
  349. {
  350. CSingleThreadedExecution lock(*s_pLock);
  351. if (s_pSessionData != NULL)
  352. {
  353. int i, iLimit;
  354. iLimit = s_pSessionData->GetCount();
  355. for (i = iLimit - 1; i >= 0; --i)
  356. {
  357. TSTATUS(static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(i))->Cleanup());
  358. TSTATUS(s_pSessionData->Remove(i));
  359. }
  360. delete s_pSessionData;
  361. s_pSessionData = NULL;
  362. }
  363. return(STATUS_SUCCESS);
  364. }
  365. // --------------------------------------------------------------------------
  366. // CThemeManagerAPIRequest::ImpersonateClientIfRequired
  367. //
  368. // Arguments: <none>
  369. //
  370. // Returns: NTSTATUS
  371. //
  372. // Purpose: Impersonates the client if the client is NOT the SYSTEM.
  373. // There's usually no point impersonating the system unless the
  374. // token is actually a filtered token.
  375. //
  376. // History: 2000-10-19 vtan created
  377. // --------------------------------------------------------------------------
  378. NTSTATUS CThemeManagerAPIRequest::ImpersonateClientIfRequired (void)
  379. {
  380. NTSTATUS status;
  381. status = OpenClientToken(_hToken);
  382. if (NT_SUCCESS(status))
  383. {
  384. CTokenInformation tokenInformation(_hToken);
  385. if (tokenInformation.IsUserTheSystem())
  386. {
  387. ReleaseHandle(_hToken);
  388. status = STATUS_SUCCESS;
  389. }
  390. else if (ImpersonateLoggedOnUser(_hToken) != FALSE)
  391. {
  392. status = STATUS_SUCCESS;
  393. }
  394. else
  395. {
  396. status = CStatusCode::StatusCodeOfLastError();
  397. }
  398. }
  399. return(status);
  400. }
  401. // --------------------------------------------------------------------------
  402. // CThemeManagerAPIRequest::ClientHasTcbPrivilege
  403. //
  404. // Arguments: <none>
  405. //
  406. // Returns: NTSTATUS
  407. //
  408. // Purpose: Returns whether the client has the SE_TCB_PRIVILEGE as a
  409. // status code.
  410. //
  411. // History: 2000-11-09 vtan created
  412. // --------------------------------------------------------------------------
  413. NTSTATUS CThemeManagerAPIRequest::ClientHasTcbPrivilege (void)
  414. {
  415. NTSTATUS status;
  416. HANDLE hTokenClient;
  417. if (OpenProcessToken(_pAPIDispatcher->GetClientProcess(),
  418. TOKEN_QUERY,
  419. &hTokenClient) != FALSE)
  420. {
  421. CTokenInformation tokenInformation(hTokenClient);
  422. if (tokenInformation.UserHasPrivilege(SE_TCB_PRIVILEGE))
  423. {
  424. status = STATUS_SUCCESS;
  425. }
  426. else
  427. {
  428. status = STATUS_ACCESS_DENIED;
  429. }
  430. TBOOL(CloseHandle(hTokenClient));
  431. }
  432. else
  433. {
  434. status = CStatusCode::StatusCodeOfLastError();
  435. }
  436. return(status);
  437. }
  438. // --------------------------------------------------------------------------
  439. // CThemeManagerAPIRequest::FindIndexSessionData
  440. //
  441. // Arguments: dwSessionID = Session ID to find.
  442. //
  443. // Returns: int
  444. //
  445. // Purpose: Iterates the session data array looking for the sessions that
  446. // matches the given session.
  447. //
  448. // History: 2000-11-30 vtan created
  449. // --------------------------------------------------------------------------
  450. int CThemeManagerAPIRequest::FindIndexSessionData (DWORD dwSessionID)
  451. {
  452. int iIndex;
  453. iIndex = -1;
  454. if ((s_pLock != NULL) && (s_pSessionData != NULL))
  455. {
  456. int i, iLimit;
  457. ASSERTMSG(s_pLock->IsOwned(), "s_pLock must be acquired in CThemeManagerAPIRequest::FindIndexSessionData");
  458. iLimit = s_pSessionData->GetCount();
  459. for (i = 0; (iIndex < 0) && (i < iLimit); ++i)
  460. {
  461. CThemeManagerSessionData *pSessionData;
  462. pSessionData = static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(i));
  463. if ((pSessionData != NULL) && (pSessionData->EqualSessionID(dwSessionID)))
  464. {
  465. iIndex = i;
  466. }
  467. }
  468. }
  469. return(iIndex);
  470. }
  471. // --------------------------------------------------------------------------
  472. // CThemeManagerAPIRequest::GetClientSessionData
  473. //
  474. // Arguments: <none>
  475. //
  476. // Returns: NTSTATUS
  477. //
  478. // Purpose: Retrieves the session data associated with the client's
  479. // session ID. This abstracts the information from uxtheme's
  480. // loader code and just passes it an object it knows how to deal
  481. // with.
  482. //
  483. // History: 2000-11-09 vtan created
  484. // --------------------------------------------------------------------------
  485. NTSTATUS CThemeManagerAPIRequest::GetClientSessionData (void)
  486. {
  487. NTSTATUS status;
  488. int iIndex;
  489. CSingleThreadedExecution lock(*s_pLock);
  490. status = STATUS_UNSUCCESSFUL;
  491. iIndex = FindIndexSessionData(_pAPIDispatcher->GetClientSessionID());
  492. if (iIndex >= 0)
  493. {
  494. _pSessionData = static_cast<CThemeManagerSessionData*>(s_pSessionData->Get(iIndex));
  495. if (_pSessionData != NULL)
  496. {
  497. _pSessionData->AddRef();
  498. status = STATUS_SUCCESS;
  499. }
  500. }
  501. else
  502. {
  503. _pSessionData = NULL;
  504. }
  505. return(status);
  506. }
  507. // --------------------------------------------------------------------------
  508. // CThemeManagerAPIRequest::Execute_ThemeHooksOn
  509. //
  510. // Arguments: <none>
  511. //
  512. // Returns: NTSTATUS
  513. //
  514. // Purpose: Handles API_THEMES_THEMEHOOKSON.
  515. //
  516. // History: 2000-10-10 vtan created
  517. // --------------------------------------------------------------------------
  518. NTSTATUS CThemeManagerAPIRequest::Execute_ThemeHooksOn (void)
  519. {
  520. NTSTATUS status;
  521. status = ImpersonateClientIfRequired();
  522. if (NT_SUCCESS(status))
  523. {
  524. API_THEMES_THEMEHOOKSON_OUT *pAPIOut;
  525. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiThemeHooksOn.out;
  526. pAPIOut->hr = ThemeHooksOn(_pSessionData->GetData());
  527. }
  528. SetDataLength(sizeof(API_THEMES));
  529. return(status);
  530. }
  531. // --------------------------------------------------------------------------
  532. // CThemeManagerAPIRequest::Execute_ThemeHooksOff
  533. //
  534. // Arguments: <none>
  535. //
  536. // Returns: NTSTATUS
  537. //
  538. // Purpose: Handles API_THEMES_THEMEHOOKSOFF.
  539. //
  540. // History: 2000-10-10 vtan created
  541. // --------------------------------------------------------------------------
  542. NTSTATUS CThemeManagerAPIRequest::Execute_ThemeHooksOff (void)
  543. {
  544. NTSTATUS status;
  545. status = ImpersonateClientIfRequired();
  546. if (NT_SUCCESS(status))
  547. {
  548. API_THEMES_THEMEHOOKSOFF_OUT *pAPIOut;
  549. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiThemeHooksOff.out;
  550. pAPIOut->hr = ThemeHooksOff(_pSessionData->GetData());
  551. }
  552. SetDataLength(sizeof(API_THEMES));
  553. return(status);
  554. }
  555. // --------------------------------------------------------------------------
  556. // CThemeManagerAPIRequest::Execute_GetStatusFlags
  557. //
  558. // Arguments: <none>
  559. //
  560. // Returns: NTSTATUS
  561. //
  562. // Purpose: Handles API_THEMES_GETSTATUSFLAGS.
  563. //
  564. // History: 2000-10-10 vtan created
  565. // --------------------------------------------------------------------------
  566. NTSTATUS CThemeManagerAPIRequest::Execute_GetStatusFlags (void)
  567. {
  568. NTSTATUS status;
  569. status = ImpersonateClientIfRequired();
  570. if (NT_SUCCESS(status))
  571. {
  572. DWORD dwFlags;
  573. API_THEMES_GETSTATUSFLAGS_OUT *pAPIOut;
  574. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetStatusFlags.out;
  575. dwFlags = QTS_AVAILABLE;
  576. if (AreThemeHooksActive(_pSessionData->GetData()))
  577. {
  578. dwFlags |= QTS_RUNNING;
  579. }
  580. pAPIOut->dwFlags = dwFlags;
  581. }
  582. SetDataLength(sizeof(API_THEMES));
  583. return(status);
  584. }
  585. // --------------------------------------------------------------------------
  586. // CThemeManagerAPIRequest::Execute_GetCurrentChangeNumber
  587. //
  588. // Arguments: <none>
  589. //
  590. // Returns: NTSTATUS
  591. //
  592. // Purpose: Handles API_THEMES_GETCURRENTCHANGENUMBER.
  593. //
  594. // History: 2000-10-10 vtan created
  595. // --------------------------------------------------------------------------
  596. NTSTATUS CThemeManagerAPIRequest::Execute_GetCurrentChangeNumber (void)
  597. {
  598. NTSTATUS status;
  599. status = ImpersonateClientIfRequired();
  600. if (NT_SUCCESS(status))
  601. {
  602. API_THEMES_GETCURRENTCHANGENUMBER_OUT *pAPIOut;
  603. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetCurrentChangeNumber.out;
  604. pAPIOut->iChangeNumber = GetCurrentChangeNumber(_pSessionData->GetData());
  605. }
  606. SetDataLength(sizeof(API_THEMES));
  607. return(status);
  608. }
  609. // --------------------------------------------------------------------------
  610. // CThemeManagerAPIRequest::Execute_GetNewChangeNumber
  611. //
  612. // Arguments: <none>
  613. //
  614. // Returns: NTSTATUS
  615. //
  616. // Purpose: Handles API_THEMES_GETNEWCHANGENUMBER.
  617. //
  618. // History: 2000-10-10 vtan created
  619. // --------------------------------------------------------------------------
  620. NTSTATUS CThemeManagerAPIRequest::Execute_GetNewChangeNumber (void)
  621. {
  622. NTSTATUS status;
  623. status = ImpersonateClientIfRequired();
  624. if (NT_SUCCESS(status))
  625. {
  626. API_THEMES_GETNEWCHANGENUMBER_OUT *pAPIOut;
  627. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetNewChangeNumber.out;
  628. pAPIOut->iChangeNumber = GetNewChangeNumber(_pSessionData->GetData());
  629. }
  630. SetDataLength(sizeof(API_THEMES));
  631. return(status);
  632. }
  633. // --------------------------------------------------------------------------
  634. // CThemeManagerAPIRequest::Execute_SetGlobalTheme
  635. //
  636. // Arguments: <none>
  637. //
  638. // Returns: NTSTATUS
  639. //
  640. // Purpose: Handles API_THEMES_SETGLOBALTHEME.
  641. //
  642. // History: 2000-10-10 vtan created
  643. // --------------------------------------------------------------------------
  644. NTSTATUS CThemeManagerAPIRequest::Execute_SetGlobalTheme (void)
  645. {
  646. NTSTATUS status;
  647. // Note: we must not impersonate the user here, since we need write access to the section
  648. HANDLE hSection;
  649. API_THEMES_SETGLOBALTHEME_IN *pAPIIn;
  650. API_THEMES_SETGLOBALTHEME_OUT *pAPIOut;
  651. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSetGlobalTheme.in;
  652. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSetGlobalTheme.out;
  653. if (pAPIIn->hSection != NULL)
  654. {
  655. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  656. pAPIIn->hSection,
  657. GetCurrentProcess(),
  658. &hSection,
  659. FILE_MAP_ALL_ACCESS,
  660. FALSE,
  661. 0) != FALSE)
  662. {
  663. status = STATUS_SUCCESS;
  664. }
  665. else
  666. {
  667. status = CStatusCode::StatusCodeOfLastError();
  668. }
  669. }
  670. else
  671. {
  672. hSection = NULL;
  673. status = STATUS_SUCCESS;
  674. }
  675. if (NT_SUCCESS(status))
  676. {
  677. pAPIOut->hr = SetGlobalTheme(_pSessionData->GetData(), hSection);
  678. if (hSection != NULL)
  679. {
  680. TBOOL(CloseHandle(hSection));
  681. }
  682. }
  683. else
  684. {
  685. pAPIOut->hr = HRESULT_FROM_NT(status);
  686. }
  687. SetDataLength(sizeof(API_THEMES));
  688. return(STATUS_SUCCESS);
  689. }
  690. // --------------------------------------------------------------------------
  691. // CThemeManagerAPIRequest::Execute_MarkSection
  692. //
  693. // Arguments: <none>
  694. //
  695. // Returns: NTSTATUS
  696. //
  697. // Purpose: Handles API_THEMES_MARKSECTION.
  698. //
  699. // History: 2001-05-08 lmouton created
  700. // --------------------------------------------------------------------------
  701. NTSTATUS CThemeManagerAPIRequest::Execute_MarkSection (void)
  702. {
  703. NTSTATUS status;
  704. // Note: we must not impersonate the user here, since we need write access to the section
  705. HANDLE hSection;
  706. DWORD dwAdd;
  707. DWORD dwRemove;
  708. API_THEMES_MARKSECTION_IN *pAPIIn;
  709. API_THEMES_MARKSECTION_OUT *pAPIOut;
  710. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiMarkSection.in;
  711. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiMarkSection.out;
  712. dwAdd = pAPIIn->dwAdd;
  713. dwRemove = pAPIIn->dwRemove;
  714. if (pAPIIn->hSection != NULL)
  715. {
  716. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  717. pAPIIn->hSection,
  718. GetCurrentProcess(),
  719. &hSection,
  720. FILE_MAP_ALL_ACCESS,
  721. FALSE,
  722. 0) != FALSE)
  723. {
  724. status = STATUS_SUCCESS;
  725. }
  726. else
  727. {
  728. status = CStatusCode::StatusCodeOfLastError();
  729. DISPLAYMSG("Execute_MarkSection: Can't get a write handle");
  730. }
  731. }
  732. else
  733. {
  734. hSection = NULL;
  735. status = STATUS_SUCCESS;
  736. }
  737. if (NT_SUCCESS(status))
  738. {
  739. if (hSection != NULL)
  740. {
  741. MarkSection(hSection, dwAdd, dwRemove);
  742. TBOOL(CloseHandle(hSection));
  743. }
  744. }
  745. SetDataLength(sizeof(API_THEMES));
  746. return(STATUS_SUCCESS);
  747. }
  748. // --------------------------------------------------------------------------
  749. // CThemeManagerAPIRequest::Execute_GetGlobalTheme
  750. //
  751. // Arguments: <none>
  752. //
  753. // Returns: NTSTATUS
  754. //
  755. // Purpose: Handles API_THEMES_GETGLOBALTHEME.
  756. //
  757. // History: 2000-10-10 vtan created
  758. // --------------------------------------------------------------------------
  759. NTSTATUS CThemeManagerAPIRequest::Execute_GetGlobalTheme (void)
  760. {
  761. NTSTATUS status;
  762. status = ImpersonateClientIfRequired();
  763. if (NT_SUCCESS(status))
  764. {
  765. HRESULT hr;
  766. HANDLE hSection;
  767. API_THEMES_GETGLOBALTHEME_OUT *pAPIOut;
  768. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiGetGlobalTheme.out;
  769. hr = GetGlobalTheme(_pSessionData->GetData(), &hSection);
  770. if (SUCCEEDED(hr) && (hSection != NULL))
  771. {
  772. if (DuplicateHandle(GetCurrentProcess(),
  773. hSection,
  774. _pAPIDispatcher->GetClientProcess(),
  775. &pAPIOut->hSection,
  776. FILE_MAP_READ,
  777. FALSE,
  778. 0) != FALSE)
  779. {
  780. hr = S_OK;
  781. }
  782. else
  783. {
  784. DWORD dwErrorCode;
  785. dwErrorCode = GetLastError();
  786. hr = HRESULT_FROM_WIN32(dwErrorCode);
  787. }
  788. TBOOL(CloseHandle(hSection));
  789. }
  790. pAPIOut->hr = hr;
  791. }
  792. SetDataLength(sizeof(API_THEMES));
  793. return(status);
  794. }
  795. // --------------------------------------------------------------------------
  796. // LOADTHEME_STRINGS + supporting functions
  797. //
  798. // Purpose: Manages and validates LoadTheme string parameters
  799. //
  800. // History: 2002-02-26 scotthan created
  801. // --------------------------------------------------------------------------
  802. typedef struct
  803. {
  804. LPWSTR pszFilename;
  805. LPWSTR pszColor;
  806. LPWSTR pszSize;
  807. } LOADTHEME_STRINGS;
  808. #define MAX_THEME_STRING MAX_PATH
  809. // --------------------------------------------------------------------------
  810. void _FreeThemeStrings( IN LOADTHEME_STRINGS* plts )
  811. {
  812. if( plts )
  813. {
  814. _FreeMappedClientString(plts->pszFilename);
  815. _FreeMappedClientString(plts->pszColor);
  816. _FreeMappedClientString(plts->pszSize);
  817. delete plts;
  818. }
  819. }
  820. // --------------------------------------------------------------------------
  821. NTSTATUS _AllocAndMapThemeStrings(
  822. IN HANDLE hProcessClient,
  823. IN LPCWSTR pszFilenameIn,
  824. IN UINT cchFilenameIn,
  825. IN LPCWSTR pszColorIn,
  826. IN UINT cchColorIn,
  827. IN LPCWSTR pszSizeIn,
  828. IN UINT cchSizeIn,
  829. OUT LOADTHEME_STRINGS** pplts )
  830. {
  831. NTSTATUS status;
  832. ASSERTMSG(pplts != NULL, "_AllocAndMapThemeStrings: NULL outbound parameter, LOADTHEME_STRINGS**.");
  833. ASSERTMSG(hProcessClient != NULL, "_AllocAndMapThemeStrings: NULL process handle.");
  834. // note: cchFileNameIn, cchColorIn, cchSizeIn are char counts that include the NULL terminus.
  835. if( pszFilenameIn && pszColorIn && pszSizeIn &&
  836. cchFilenameIn > 0 && cchColorIn > 0 && cchSizeIn > 0 &&
  837. cchFilenameIn <= MAX_THEME_STRING && cchColorIn <= MAX_THEME_STRING && cchSizeIn <= MAX_THEME_STRING )
  838. {
  839. *pplts = NULL;
  840. LOADTHEME_STRINGS *plts = new LOADTHEME_STRINGS;
  841. if( plts != NULL )
  842. {
  843. ZeroMemory(plts, sizeof(*plts));
  844. status = _AllocAndMapClientString(hProcessClient, pszFilenameIn, cchFilenameIn, MAX_THEME_STRING, &plts->pszFilename);
  845. if( NT_SUCCESS(status) )
  846. {
  847. status = _AllocAndMapClientString(hProcessClient, pszColorIn, cchColorIn, MAX_THEME_STRING, &plts->pszColor);
  848. if( NT_SUCCESS(status) )
  849. {
  850. status = _AllocAndMapClientString(hProcessClient, pszSizeIn, cchSizeIn, MAX_THEME_STRING, &plts->pszSize);
  851. if( NT_SUCCESS(status) )
  852. {
  853. *pplts = plts;
  854. }
  855. }
  856. }
  857. if( !NT_SUCCESS(status) )
  858. {
  859. _FreeThemeStrings(plts);
  860. }
  861. }
  862. else
  863. {
  864. status = STATUS_NO_MEMORY;
  865. }
  866. }
  867. else
  868. {
  869. status = STATUS_INVALID_PARAMETER;
  870. }
  871. return status;
  872. }
  873. // --------------------------------------------------------------------------
  874. // CThemeManagerAPIRequest::Execute_CheckThemeSignature
  875. //
  876. // Arguments: <none>
  877. //
  878. // Returns: NTSTATUS
  879. //
  880. // Purpose: Handles API_THEMES_CHECKTHEMESIGNATURE.
  881. //
  882. // History: 2000-10-10 vtan created
  883. // --------------------------------------------------------------------------
  884. NTSTATUS CThemeManagerAPIRequest::Execute_CheckThemeSignature (void)
  885. {
  886. NTSTATUS status;
  887. status = ImpersonateClientIfRequired();
  888. if (NT_SUCCESS(status))
  889. {
  890. API_THEMES_CHECKTHEMESIGNATURE_IN *pAPIIn;
  891. API_THEMES_CHECKTHEMESIGNATURE_OUT *pAPIOut;
  892. LPWSTR pszThemeFileName;
  893. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiCheckThemeSignature.in;
  894. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiCheckThemeSignature.out;
  895. status = _AllocAndMapClientString(_pAPIDispatcher->GetClientProcess(),
  896. pAPIIn->pszName,
  897. pAPIIn->cchName,
  898. MAX_PATH,
  899. &pszThemeFileName);
  900. if( NT_SUCCESS(status) )
  901. {
  902. pAPIOut->hr = CheckThemeSignature(pszThemeFileName);
  903. status = STATUS_SUCCESS;
  904. _FreeMappedClientString(pszThemeFileName);
  905. }
  906. }
  907. SetDataLength(sizeof(API_THEMES));
  908. return(status);
  909. }
  910. // --------------------------------------------------------------------------
  911. // CThemeManagerAPIRequest::Execute_LoadTheme
  912. //
  913. // Arguments: <none>
  914. //
  915. // Returns: NTSTATUS
  916. //
  917. // Purpose: Handles API_THEMES_LOADTHEME.
  918. //
  919. // History: 2000-10-10 vtan created
  920. // --------------------------------------------------------------------------
  921. NTSTATUS CThemeManagerAPIRequest::Execute_LoadTheme (void)
  922. {
  923. NTSTATUS status;
  924. status = ImpersonateClientIfRequired();
  925. if (NT_SUCCESS(status))
  926. {
  927. HANDLE hProcessClient;
  928. API_THEMES_LOADTHEME_IN *pAPIIn;
  929. API_THEMES_LOADTHEME_OUT *pAPIOut;
  930. LOADTHEME_STRINGS* plts;
  931. hProcessClient = _pAPIDispatcher->GetClientProcess();
  932. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiLoadTheme.in;
  933. pAPIOut = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiLoadTheme.out;
  934. status = _AllocAndMapThemeStrings( hProcessClient, pAPIIn->pszName, pAPIIn->cchName,
  935. pAPIIn->pszColor, pAPIIn->cchColor,
  936. pAPIIn->pszSize, pAPIIn->cchSize,
  937. &plts );
  938. if( NT_SUCCESS(status) )
  939. {
  940. HANDLE hSectionIn, hSectionOut;
  941. if (DuplicateHandle(hProcessClient,
  942. pAPIIn->hSection,
  943. GetCurrentProcess(),
  944. &hSectionIn,
  945. FILE_MAP_ALL_ACCESS,
  946. FALSE,
  947. 0) != FALSE)
  948. {
  949. status = STATUS_SUCCESS;
  950. // Warning: this function will revert to self in order to create the section in system context.
  951. // Impersonate the user again after it if needed
  952. pAPIOut->hr = LoadTheme(_pSessionData->GetData(), hSectionIn, &hSectionOut,
  953. plts->pszFilename, plts->pszColor, plts->pszSize);
  954. if (SUCCEEDED(pAPIOut->hr))
  955. {
  956. // Still running in the system context here
  957. if (DuplicateHandle(GetCurrentProcess(),
  958. hSectionOut,
  959. hProcessClient,
  960. &pAPIOut->hSection,
  961. FILE_MAP_READ,
  962. FALSE,
  963. 0) == FALSE)
  964. {
  965. status = CStatusCode::StatusCodeOfLastError();
  966. }
  967. TBOOL(CloseHandle(hSectionOut));
  968. }
  969. TBOOL(CloseHandle(hSectionIn));
  970. }
  971. else
  972. {
  973. status = CStatusCode::StatusCodeOfLastError();
  974. }
  975. _FreeThemeStrings(plts);
  976. }
  977. }
  978. SetDataLength(sizeof(API_THEMES));
  979. return(status);
  980. }
  981. // --------------------------------------------------------------------------
  982. // CThemeManagerAPIRequest::Execute_UserLogon
  983. //
  984. // Arguments: <none>
  985. //
  986. // Returns: NTSTATUS
  987. //
  988. // Purpose: Handles API_THEMES_USERLOGON. To call this API you must have
  989. // the SE_TCB_PRIVILEGE in your token.
  990. //
  991. // History: 2000-10-12 vtan created
  992. // --------------------------------------------------------------------------
  993. NTSTATUS CThemeManagerAPIRequest::Execute_UserLogon (void)
  994. {
  995. NTSTATUS status;
  996. status = ClientHasTcbPrivilege();
  997. if (NT_SUCCESS(status))
  998. {
  999. HANDLE hToken;
  1000. API_THEMES_USERLOGON_IN *pAPIIn;
  1001. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiUserLogon.in;
  1002. if (DuplicateHandle(_pAPIDispatcher->GetClientProcess(),
  1003. pAPIIn->hToken,
  1004. GetCurrentProcess(),
  1005. &hToken,
  1006. 0,
  1007. FALSE,
  1008. DUPLICATE_SAME_ACCESS) != FALSE)
  1009. {
  1010. status = _pSessionData->UserLogon(hToken);
  1011. TBOOL(CloseHandle(hToken));
  1012. }
  1013. else
  1014. {
  1015. status = CStatusCode::StatusCodeOfLastError();
  1016. }
  1017. }
  1018. SetDataLength(sizeof(API_THEMES));
  1019. return(status);
  1020. }
  1021. // --------------------------------------------------------------------------
  1022. // CThemeManagerAPIRequest::Execute_UserLogoff
  1023. //
  1024. // Arguments: <none>
  1025. //
  1026. // Returns: NTSTATUS
  1027. //
  1028. // Purpose: Handles API_THEMES_USERLOGOFF. To call this API you must have
  1029. // the SE_TCB_PRIVILEGE in your token.
  1030. //
  1031. // History: 2000-10-12 vtan created
  1032. // --------------------------------------------------------------------------
  1033. NTSTATUS CThemeManagerAPIRequest::Execute_UserLogoff (void)
  1034. {
  1035. NTSTATUS status;
  1036. status = ClientHasTcbPrivilege();
  1037. if (NT_SUCCESS(status))
  1038. {
  1039. status = _pSessionData->UserLogoff();
  1040. }
  1041. SetDataLength(sizeof(API_THEMES));
  1042. return(status);
  1043. }
  1044. // --------------------------------------------------------------------------
  1045. // CThemeManagerAPIRequest::Execute_SessionCreate
  1046. //
  1047. // Arguments: <none>
  1048. //
  1049. // Returns: NTSTATUS
  1050. //
  1051. // Purpose: Handles API_THEMES_SESSIONCREATE. To call this API you must
  1052. // have the SE_TCB_PRIVILEGE in your token.
  1053. //
  1054. // History: 2000-11-09 vtan created
  1055. // --------------------------------------------------------------------------
  1056. NTSTATUS CThemeManagerAPIRequest::Execute_SessionCreate (void)
  1057. {
  1058. NTSTATUS status;
  1059. status = ClientHasTcbPrivilege();
  1060. if (NT_SUCCESS(status))
  1061. {
  1062. HANDLE hProcessClient;
  1063. CThemeManagerSessionData *pSessionData;
  1064. ASSERTMSG(_pSessionData == NULL, "Session data already exists in CThemeManagerAPIRequest::Execute_SessionCreate");
  1065. if (DuplicateHandle(GetCurrentProcess(),
  1066. _pAPIDispatcher->GetClientProcess(),
  1067. GetCurrentProcess(),
  1068. &hProcessClient,
  1069. PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE,
  1070. FALSE,
  1071. 0) != FALSE)
  1072. {
  1073. DWORD dwSessionID;
  1074. dwSessionID = _pAPIDispatcher->GetClientSessionID();
  1075. pSessionData = new CThemeManagerSessionData(dwSessionID);
  1076. if (pSessionData != NULL)
  1077. {
  1078. API_THEMES_SESSIONCREATE_IN *pAPIIn;
  1079. pAPIIn = &reinterpret_cast<API_THEMES*>(&_data)->apiSpecific.apiSessionCreate.in;
  1080. status = pSessionData->Allocate(hProcessClient,
  1081. s_dwServerChangeNumber,
  1082. pAPIIn->pfnRegister,
  1083. pAPIIn->pfnUnregister,
  1084. pAPIIn->pfnClearStockObjects,
  1085. pAPIIn->dwStackSizeReserve,
  1086. pAPIIn->dwStackSizeCommit);
  1087. if (NT_SUCCESS(status))
  1088. {
  1089. int iIndex;
  1090. CSingleThreadedExecution lock(*s_pLock);
  1091. // Find the session data in the static array. If found
  1092. // then remove the entry (don't allow duplicates).
  1093. iIndex = FindIndexSessionData(dwSessionID);
  1094. if (iIndex >= 0)
  1095. {
  1096. status = s_pSessionData->Remove(iIndex);
  1097. }
  1098. // If the static array has been destroyed (the service has been
  1099. // stopped) then don't do anything - this is not an error.
  1100. if (NT_SUCCESS(status) && (s_pSessionData != NULL))
  1101. {
  1102. status = s_pSessionData->Add(pSessionData);
  1103. }
  1104. }
  1105. pSessionData->Release();
  1106. }
  1107. else
  1108. {
  1109. status = STATUS_NO_MEMORY;
  1110. }
  1111. TBOOL(CloseHandle(hProcessClient));
  1112. }
  1113. else
  1114. {
  1115. status = CStatusCode::StatusCodeOfLastError();
  1116. }
  1117. }
  1118. SetDataLength(sizeof(API_THEMES));
  1119. return(status);
  1120. }
  1121. // --------------------------------------------------------------------------
  1122. // CThemeManagerAPIRequest::Execute_SessionDestroy
  1123. //
  1124. // Arguments: <none>
  1125. //
  1126. // Returns: NTSTATUS
  1127. //
  1128. // Purpose: Handles API_THEMES_SESSIONDESTROY. To call this API you must
  1129. // have the SE_TCB_PRIVILEGE in your token.
  1130. //
  1131. // History: 2000-11-09 vtan created
  1132. // --------------------------------------------------------------------------
  1133. NTSTATUS CThemeManagerAPIRequest::Execute_SessionDestroy (void)
  1134. {
  1135. NTSTATUS status;
  1136. status = ClientHasTcbPrivilege();
  1137. if (NT_SUCCESS(status))
  1138. {
  1139. int iIndex;
  1140. CSingleThreadedExecution lock(*s_pLock);
  1141. iIndex = FindIndexSessionData(_pAPIDispatcher->GetClientSessionID());
  1142. if (iIndex >= 0)
  1143. {
  1144. status = s_pSessionData->Remove(iIndex);
  1145. }
  1146. else
  1147. {
  1148. status = STATUS_SUCCESS;
  1149. }
  1150. }
  1151. SetDataLength(sizeof(API_THEMES));
  1152. return(status);
  1153. }
  1154. // --------------------------------------------------------------------------
  1155. // CThemeManagerAPIRequest::Execute_Ping
  1156. //
  1157. // Arguments: <none>
  1158. //
  1159. // Returns: NTSTATUS
  1160. //
  1161. // Purpose: Handles API_THEMES_PING. Tell the client we're alive.
  1162. //
  1163. // History: 2000-11-30 vtan created
  1164. // --------------------------------------------------------------------------
  1165. NTSTATUS CThemeManagerAPIRequest::Execute_Ping (void)
  1166. {
  1167. SetDataLength(sizeof(API_THEMES));
  1168. return(STATUS_SUCCESS);
  1169. }