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(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(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_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 */ 178