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