xref: /reactos/base/services/shsvcs/thmserver.c (revision 1734f297)
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(VOID);
32 
33 /* FUNCTIONS *****************************************************************/
34 
35 static
36 HANDLE
37 GetThemeServiceProcessHandle(VOID)
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(hThemeServiceWaitObject);
80 
81     ThemeWatchForStart();
82     ThemeHooksRemove();
83 }
84 
85 static
86 VOID
87 CALLBACK
88 ThemeServiceDiedCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
89 {
90     /* The theme service died and we don't know if it could set its events properly */
91     ResetEvent(hStartEvent);
92     ResetEvent(hStopEvent);
93 
94     CloseHandle(hServiceProcess);
95     UnregisterWait(hThemeStopWaitObject);
96     ThemeWatchForStart();
97     ThemeHooksRemove();
98 }
99 
100 static
101 VOID
102 CALLBACK
103 ThemeStartCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
104 {
105     hServiceProcess = GetThemeServiceProcessHandle();
106 
107     RegisterWaitForSingleObject(&hThemeStopWaitObject, hStopEvent, ThemeStopCallback, NULL, INFINITE, WT_EXECUTEONLYONCE);
108     RegisterWaitForSingleObject(&hThemeServiceWaitObject, hServiceProcess, ThemeServiceDiedCallback, NULL, INFINITE, WT_EXECUTEONLYONCE);
109 
110     ThemeHooksInstall();
111 }
112 
113 BOOL
114 WINAPI
115 ThemeWatchForStart(VOID)
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_EXECUTEONLYONCE);
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 */
178