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.

272 lines
8.7 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: ThemeManagerService.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // This file contains a class that implements the theme server service
  7. // specifics.
  8. //
  9. // History: 2000-11-29 vtan created
  10. // --------------------------------------------------------------------------
  11. #include "StandardHeader.h"
  12. #include "ThemeManagerService.h"
  13. #include <lpcthemes.h>
  14. #include <winsta.h>
  15. #include "Access.h"
  16. #include "StatusCode.h"
  17. const TCHAR CThemeManagerService::s_szName[] = TEXT("Themes");
  18. // --------------------------------------------------------------------------
  19. // CThemeManagerService::CThemeManagerService
  20. //
  21. // Arguments: pAPIConnection = CAPIConnection passed to base class.
  22. // pServerAPI = CServerAPI passed to base class.
  23. //
  24. // Returns: <none>
  25. //
  26. // Purpose: Constructor for CThemeManagerService.
  27. //
  28. // History: 2000-11-29 vtan created
  29. // --------------------------------------------------------------------------
  30. CThemeManagerService::CThemeManagerService (CAPIConnection *pAPIConnection, CServerAPI *pServerAPI) :
  31. CService(pAPIConnection, pServerAPI, GetName())
  32. {
  33. }
  34. // --------------------------------------------------------------------------
  35. // CThemeManagerService::~CThemeManagerService
  36. //
  37. // Arguments: <none>
  38. //
  39. // Returns: <none>
  40. //
  41. // Purpose: Destructor for CThemeManagerService.
  42. //
  43. // History: 2000-11-29 vtan created
  44. // --------------------------------------------------------------------------
  45. CThemeManagerService::~CThemeManagerService (void)
  46. {
  47. }
  48. // --------------------------------------------------------------------------
  49. // CThemeManagerService::Signal
  50. //
  51. // Arguments: <none>
  52. //
  53. // Returns: NTSTATUS
  54. //
  55. // Purpose: Used to signal that the service is coming up. Winlogon (via
  56. // msgina) is listening for this event in its own session. This
  57. // function queues a request to execute the real work done on a
  58. // worker thread to prevent blocking the main service thread. If
  59. // this is not possible then execute the signal inline.
  60. //
  61. // History: 2000-11-29 vtan created
  62. // --------------------------------------------------------------------------
  63. NTSTATUS CThemeManagerService::Signal (void)
  64. {
  65. if (QueueUserWorkItem(SignalSessionEvents, NULL, WT_EXECUTEDEFAULT) == FALSE)
  66. {
  67. (DWORD)SignalSessionEvents(NULL);
  68. }
  69. return(STATUS_SUCCESS);
  70. }
  71. // --------------------------------------------------------------------------
  72. // CThemeManagerService::GetName
  73. //
  74. // Arguments: <none>
  75. //
  76. // Returns: const TCHAR*
  77. //
  78. // Purpose: Returns the name of the service (ThemeService).
  79. //
  80. // History: 2000-11-29 vtan created
  81. // --------------------------------------------------------------------------
  82. const TCHAR* CThemeManagerService::GetName (void)
  83. {
  84. return(s_szName);
  85. }
  86. // --------------------------------------------------------------------------
  87. // CThemeManagerService::OpenStartEvent
  88. //
  89. // Arguments: <none>
  90. //
  91. // Returns: HANDLE
  92. //
  93. // Purpose: Opens or creates the theme service recovery event. This allows
  94. // a process that has registered for the event to be signaled
  95. // when the theme server is demand started. Currently only
  96. // winlogon listens for this event and is required so that it can
  97. // reestablish a server connection and re-create the session data
  98. // which holds the hooks for theming.
  99. //
  100. // History: 2000-11-29 vtan created
  101. // --------------------------------------------------------------------------
  102. HANDLE CThemeManagerService::OpenStartEvent (DWORD dwSessionID, DWORD dwDesiredAccess)
  103. {
  104. HANDLE hEvent;
  105. NTSTATUS status;
  106. UNICODE_STRING eventName;
  107. OBJECT_ATTRIBUTES objectAttributes;
  108. WCHAR szEventName[64];
  109. if (dwSessionID == 0)
  110. {
  111. wsprintfW(szEventName, L"\\BaseNamedObjects\\%s", THEMES_START_EVENT_NAME);
  112. }
  113. else
  114. {
  115. wsprintfW(szEventName, L"\\Sessions\\%d\\BaseNamedObjects\\%s", dwSessionID, THEMES_START_EVENT_NAME);
  116. }
  117. RtlInitUnicodeString(&eventName, szEventName);
  118. InitializeObjectAttributes(&objectAttributes,
  119. &eventName,
  120. 0,
  121. NULL,
  122. NULL);
  123. status = NtOpenEvent(&hEvent, dwDesiredAccess, &objectAttributes);
  124. if (!NT_SUCCESS(status))
  125. {
  126. // Build a security descriptor for the event that allows:
  127. // S-1-5-18 NT AUTHORITY\SYSTEM EVENT_ALL_ACCESS
  128. // S-1-5-32-544 <local administrators> SYNCHRONIZE | READ_CONTROL
  129. // S-1-1-0 <everyone> SYNCHRONIZE
  130. static SID_IDENTIFIER_AUTHORITY s_SecurityNTAuthority = SECURITY_NT_AUTHORITY;
  131. static SID_IDENTIFIER_AUTHORITY s_SecurityWorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  132. static const CSecurityDescriptor::ACCESS_CONTROL s_AccessControl[] =
  133. {
  134. {
  135. &s_SecurityNTAuthority,
  136. 1,
  137. SECURITY_LOCAL_SYSTEM_RID,
  138. 0, 0, 0, 0, 0, 0, 0,
  139. EVENT_ALL_ACCESS
  140. },
  141. {
  142. &s_SecurityNTAuthority,
  143. 2,
  144. SECURITY_BUILTIN_DOMAIN_RID,
  145. DOMAIN_ALIAS_RID_ADMINS,
  146. 0, 0, 0, 0, 0, 0,
  147. SYNCHRONIZE | READ_CONTROL
  148. },
  149. {
  150. &s_SecurityWorldAuthority,
  151. 1,
  152. SECURITY_WORLD_RID,
  153. 0, 0, 0, 0, 0, 0, 0,
  154. SYNCHRONIZE
  155. },
  156. };
  157. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  158. // Build a security descriptor that allows the described access above.
  159. pSecurityDescriptor = CSecurityDescriptor::Create(ARRAYSIZE(s_AccessControl), s_AccessControl);
  160. InitializeObjectAttributes(&objectAttributes,
  161. &eventName,
  162. 0,
  163. NULL,
  164. pSecurityDescriptor);
  165. status = NtCreateEvent(&hEvent,
  166. EVENT_ALL_ACCESS,
  167. &objectAttributes,
  168. NotificationEvent,
  169. FALSE);
  170. ReleaseMemory(pSecurityDescriptor);
  171. if (!NT_SUCCESS(status))
  172. {
  173. hEvent = NULL;
  174. SetLastError(CStatusCode::ErrorCodeOfStatusCode(status));
  175. }
  176. }
  177. return(hEvent);
  178. }
  179. // --------------------------------------------------------------------------
  180. // CThemeManagerService::SignalSessionEvents
  181. //
  182. // Arguments: <none>
  183. //
  184. // Returns: HANDLE
  185. //
  186. // Purpose: Opens or creates the theme service recovery event. This allows
  187. // a process that has registered for the event to be signaled
  188. // when the theme server is demand started.
  189. //
  190. // History: 2000-11-29 vtan created
  191. // --------------------------------------------------------------------------
  192. DWORD WINAPI CThemeManagerService::SignalSessionEvents (void *pParameter)
  193. {
  194. UNREFERENCED_PARAMETER(pParameter);
  195. HANDLE hEvent;
  196. HANDLE hServer;
  197. // First try and use terminal server to enumerate the sessions available.
  198. hServer = WinStationOpenServerW(reinterpret_cast<WCHAR*>(SERVERNAME_CURRENT));
  199. if (hServer != NULL)
  200. {
  201. ULONG ulEntries;
  202. PLOGONID pLogonIDs;
  203. if (WinStationEnumerate(hServer, &pLogonIDs, &ulEntries))
  204. {
  205. ULONG ul;
  206. PLOGONID pLogonID;
  207. for (ul = 0, pLogonID = pLogonIDs; ul < ulEntries; ++ul, ++pLogonID)
  208. {
  209. if ((pLogonID->State == State_Active) || (pLogonID->State == State_Connected) || (pLogonID->State == State_Disconnected))
  210. {
  211. hEvent = OpenStartEvent(pLogonID->SessionId, EVENT_MODIFY_STATE);
  212. if (hEvent != NULL)
  213. {
  214. TBOOL(SetEvent(hEvent));
  215. TBOOL(CloseHandle(hEvent));
  216. }
  217. }
  218. }
  219. (BOOLEAN)WinStationFreeMemory(pLogonIDs);
  220. }
  221. (BOOLEAN)WinStationCloseServer(hServer);
  222. }
  223. else
  224. {
  225. // If terminal services is not available then assume session 0 only.
  226. hEvent = OpenStartEvent(0, EVENT_MODIFY_STATE);
  227. if (hEvent != NULL)
  228. {
  229. TBOOL(SetEvent(hEvent));
  230. TBOOL(CloseHandle(hEvent));
  231. }
  232. }
  233. return(0);
  234. }