Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / base / services / shsvcs / thmserver.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: base/services/thmsvc/thmserver.c
5 * PURPOSE: Themes server
6 * PROGRAMMER: Giannis Adamopoulos
7 */
8
9 /*
10 * NOTE:
11 * ThemeWaitForServiceReady and ThemeWatchForStart are called from msgina
12 * so all the functions in this file run in the context of winlogon
13 */
14
15 /* INCLUDES *****************************************************************/
16
17 #include <windows.h>
18 #include <uxtheme.h>
19 #include <uxundoc.h>
20 #include <wine/debug.h>
21
22 WINE_DEFAULT_DEBUG_CHANNEL(shsvcs);
23
24 /* GLOBALS ******************************************************************/
25
26 static WCHAR ServiceName[] = L"Themes";
27
28 HANDLE hThemeStartWaitObject, hThemeStopWaitObject, hThemeServiceWaitObject;
29 HANDLE hStartEvent, hStopEvent, hServiceProcess;
30
31 BOOL WINAPI ThemeWatchForStart();
32
33 /* FUNCTIONS *****************************************************************/
34
35 static
36 HANDLE
37 GetThemeServiceProcessHandle()
38 {
39 SC_HANDLE scm, service;
40 SERVICE_STATUS_PROCESS status;
41 DWORD dummy;
42 HANDLE ret;
43
44 if (!(scm = OpenSCManagerW( NULL, NULL, 0 )))
45 {
46 ERR( "failed to open service manager\n" );
47 return NULL;
48 }
49 if (!(service = OpenServiceW( scm, ServiceName, SERVICE_QUERY_STATUS )))
50 {
51 ERR( "failed to open themes service\n" );
52 CloseServiceHandle( scm );
53 return NULL;
54 }
55
56 if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
57 (BYTE *)&status, sizeof(status), &dummy ))
58 {
59 ERR("QueryServiceStatusEx failed\n");
60 CloseServiceHandle( service );
61 CloseServiceHandle( scm );
62 return NULL;
63 }
64
65 ret = OpenProcess(SYNCHRONIZE, FALSE, status.dwProcessId);
66
67 CloseServiceHandle( service );
68 CloseServiceHandle( scm );
69
70 return ret;
71 }
72
73 static
74 VOID
75 CALLBACK
76 ThemeStopCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
77 {
78 CloseHandle(hServiceProcess);
79 UnregisterWait(hThemeStopWaitObject);
80 UnregisterWait(hThemeServiceWaitObject);
81
82 ThemeWatchForStart();
83 ThemeHooksRemove();
84 }
85
86 static
87 VOID
88 CALLBACK
89 ThemeServiceDiedCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
90 {
91 /* The theme service died and we don't know if it could set its events properly */
92 ResetEvent(hStartEvent);
93 ResetEvent(hStopEvent);
94
95 ThemeStopCallback(lpParameter, TimerOrWaitFired);
96 }
97
98 static
99 VOID
100 CALLBACK
101 ThemeStartCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
102 {
103 UnregisterWait(hThemeStartWaitObject);
104
105 hServiceProcess = GetThemeServiceProcessHandle();
106
107 RegisterWaitForSingleObject(&hThemeStopWaitObject, hStopEvent, ThemeStopCallback, NULL, INFINITE, WT_EXECUTEDEFAULT);
108 RegisterWaitForSingleObject(&hThemeServiceWaitObject, hServiceProcess, ThemeServiceDiedCallback, NULL, INFINITE, WT_EXECUTEDEFAULT);
109
110 ThemeHooksInstall();
111 }
112
113 BOOL
114 WINAPI
115 ThemeWatchForStart()
116 {
117 hStartEvent = CreateEventW(NULL, TRUE, FALSE, L"Global\\ThemeStartEvent");
118 hStopEvent = CreateEventW(NULL, TRUE, FALSE, L"Global\\ThemeStopEvent");
119
120 RegisterWaitForSingleObject(&hThemeStartWaitObject, hStartEvent, ThemeStartCallback, NULL, INFINITE, WT_EXECUTEDEFAULT);
121
122 return TRUE;
123 }
124
125 DWORD
126 WINAPI
127 ThemeWaitForServiceReady(DWORD dwTimeout)
128 {
129 SC_HANDLE scm, service;
130 SERVICE_STATUS_PROCESS status;
131 BOOL ret = FALSE;
132 DWORD start_time = GetTickCount();
133
134 TRACE("\n");
135
136 if (!(scm = OpenSCManagerW( NULL, NULL, 0 )))
137 {
138 ERR( "failed to open service manager\n" );
139 return FALSE;
140 }
141 if (!(service = OpenServiceW( scm, ServiceName, SERVICE_QUERY_STATUS )))
142 {
143 ERR( "failed to open themes service\n" );
144 CloseServiceHandle( scm );
145 return FALSE;
146 }
147
148 while(TRUE)
149 {
150 DWORD dummy;
151
152 if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
153 (BYTE *)&status, sizeof(status), &dummy ))
154 break;
155 if (status.dwCurrentState == SERVICE_RUNNING)
156 {
157 ret = TRUE;
158 break;
159 }
160 if (status.dwCurrentState != SERVICE_START_PENDING)
161 {
162 break;
163 }
164
165 if (GetTickCount() - start_time > dwTimeout)
166 {
167 break;
168 }
169 Sleep( 100 );
170 };
171
172 CloseServiceHandle( service );
173 CloseServiceHandle( scm );
174 return ret;
175 }
176
177 /* EOF */