1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Test for service process environment block 5 * PROGRAMMER: Hermes Belusca-Maito 6 */ 7 8 #include "precomp.h" 9 10 #include "svchlp.h" 11 12 13 /*** Service part of the test ***/ 14 15 static SERVICE_STATUS_HANDLE status_handle; 16 17 static void 18 report_service_status(DWORD dwCurrentState, 19 DWORD dwWin32ExitCode, 20 DWORD dwWaitHint) 21 { 22 BOOL res; 23 SERVICE_STATUS status; 24 25 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 26 status.dwCurrentState = dwCurrentState; 27 status.dwWin32ExitCode = dwWin32ExitCode; 28 status.dwWaitHint = dwWaitHint; 29 30 status.dwServiceSpecificExitCode = 0; 31 status.dwCheckPoint = 0; 32 33 if ( (dwCurrentState == SERVICE_START_PENDING) || 34 (dwCurrentState == SERVICE_STOP_PENDING) || 35 (dwCurrentState == SERVICE_STOPPED) ) 36 { 37 status.dwControlsAccepted = 0; 38 } 39 else 40 { 41 status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 42 } 43 44 #if 0 45 if ( (dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED) ) 46 status.dwCheckPoint = 0; 47 else 48 status.dwCheckPoint = dwCheckPoint++; 49 #endif 50 51 res = SetServiceStatus(status_handle, &status); 52 service_ok(res, "SetServiceStatus(%d) failed: %lu\n", dwCurrentState, GetLastError()); 53 } 54 55 static VOID WINAPI service_handler(DWORD ctrl) 56 { 57 switch(ctrl) 58 { 59 case SERVICE_CONTROL_STOP: 60 case SERVICE_CONTROL_SHUTDOWN: 61 report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 0); 62 default: 63 report_service_status(SERVICE_RUNNING, NO_ERROR, 0); 64 } 65 } 66 67 static void WINAPI 68 service_main(DWORD dwArgc, LPWSTR* lpszArgv) 69 { 70 // SERVICE_STATUS_HANDLE status_handle; 71 LPWSTR lpEnvironment, lpEnvStr; 72 DWORD dwSize; 73 74 UNREFERENCED_PARAMETER(dwArgc); 75 UNREFERENCED_PARAMETER(lpszArgv); 76 77 /* Register our service for control (lpszArgv[0] holds the service name) */ 78 status_handle = RegisterServiceCtrlHandlerW(lpszArgv[0], service_handler); 79 service_ok(status_handle != NULL, "RegisterServiceCtrlHandler failed: %lu\n", GetLastError()); 80 if (!status_handle) 81 return; 82 83 /* Report SERVICE_RUNNING status */ 84 report_service_status(SERVICE_RUNNING, NO_ERROR, 4000); 85 86 /* Display our current environment for informative purposes */ 87 lpEnvironment = GetEnvironmentStringsW(); 88 lpEnvStr = lpEnvironment; 89 while (*lpEnvStr) 90 { 91 service_trace("%S\n", lpEnvStr); 92 lpEnvStr += wcslen(lpEnvStr) + 1; 93 } 94 FreeEnvironmentStringsW(lpEnvironment); 95 96 /* Check the presence of the user-related environment variables */ 97 dwSize = GetEnvironmentVariableW(L"ALLUSERSPROFILE", NULL, 0); 98 service_ok(dwSize != 0, "ALLUSERSPROFILE envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError()); 99 dwSize = GetEnvironmentVariableW(L"USERPROFILE", NULL, 0); 100 service_ok(dwSize != 0, "USERPROFILE envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError()); 101 #if 0 // May not always exist 102 dwSize = GetEnvironmentVariableW(L"USERNAME", NULL, 0); 103 service_ok(dwSize != 0, "USERNAME envvar not found, or GetEnvironmentVariableW failed: %lu\n", GetLastError()); 104 #endif 105 106 /* Work is done */ 107 report_service_status(SERVICE_STOPPED, NO_ERROR, 0); 108 } 109 110 static BOOL start_service(PCSTR service_nameA, PCWSTR service_nameW) 111 { 112 BOOL res; 113 114 SERVICE_TABLE_ENTRYW servtbl[] = 115 { 116 { (PWSTR)service_nameW, service_main }, 117 { NULL, NULL } 118 }; 119 120 res = StartServiceCtrlDispatcherW(servtbl); 121 service_ok(res, "StartServiceCtrlDispatcherW failed: %lu\n", GetLastError()); 122 return res; 123 } 124 125 126 /*** Tester part of the test ***/ 127 128 static void 129 my_test_server(PCSTR service_nameA, 130 PCWSTR service_nameW, 131 void *param) 132 { 133 BOOL res; 134 SC_HANDLE hSC = NULL; 135 SC_HANDLE hService = NULL; 136 SERVICE_STATUS ServiceStatus; 137 138 /* Open the SCM */ 139 hSC = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); 140 if (!hSC) 141 { 142 skip("OpenSCManagerW failed with error %lu!\n", GetLastError()); 143 return; 144 } 145 146 /* First create ourselves as a service running in the default LocalSystem account */ 147 hService = register_service_exW(hSC, L"ServiceEnv", service_nameW, NULL, 148 SERVICE_ALL_ACCESS, 149 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 150 SERVICE_DEMAND_START, 151 SERVICE_ERROR_IGNORE, 152 NULL, NULL, NULL, 153 NULL, NULL); 154 if (!hService) 155 { 156 skip("CreateServiceW failed with error %lu!\n", GetLastError()); 157 goto Cleanup; 158 } 159 160 /* Start it */ 161 if (!StartServiceW(hService, 0, NULL)) 162 { 163 skip("StartServiceW failed with error %lu!\n", GetLastError()); 164 goto Cleanup; 165 } 166 167 /* Wait for the service to stop by itself */ 168 do 169 { 170 Sleep(100); 171 ZeroMemory(&ServiceStatus, sizeof(ServiceStatus)); 172 res = QueryServiceStatus(hService, &ServiceStatus); 173 } while (res && ServiceStatus.dwCurrentState != SERVICE_STOPPED); 174 ok(res, "QueryServiceStatus failed: %lu\n", GetLastError()); 175 ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState); 176 177 /* Be sure the service is really stopped */ 178 res = ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus); 179 if (!res && ServiceStatus.dwCurrentState != SERVICE_STOPPED && 180 ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING && 181 GetLastError() != ERROR_SERVICE_NOT_ACTIVE) 182 { 183 skip("ControlService failed with error %lu!\n", GetLastError()); 184 goto Cleanup; 185 } 186 187 #if 0 188 trace("Service stopped. Going to restart it...\n"); 189 190 /* Now change the service configuration to make it start under the NetworkService account */ 191 if (!ChangeServiceConfigW(hService, 192 SERVICE_NO_CHANGE, 193 SERVICE_NO_CHANGE, 194 SERVICE_NO_CHANGE, 195 NULL, NULL, NULL, NULL, 196 L"NT AUTHORITY\\NetworkService", L"", 197 NULL)) 198 { 199 skip("ChangeServiceConfigW failed with error %lu!\n", GetLastError()); 200 goto Cleanup; 201 } 202 203 /* Start it */ 204 if (!StartServiceW(hService, 0, NULL)) 205 { 206 skip("StartServiceW failed with error %lu!\n", GetLastError()); 207 goto Cleanup; 208 } 209 210 /* Wait for the service to stop by itself */ 211 do 212 { 213 Sleep(100); 214 ZeroMemory(&ServiceStatus, sizeof(ServiceStatus)); 215 res = QueryServiceStatus(hService, &ServiceStatus); 216 } while (res && ServiceStatus.dwCurrentState != SERVICE_STOPPED); 217 ok(res, "QueryServiceStatus failed: %lu\n", GetLastError()); 218 ok(ServiceStatus.dwCurrentState == SERVICE_STOPPED, "ServiceStatus.dwCurrentState = %lx\n", ServiceStatus.dwCurrentState); 219 220 /* Be sure the service is really stopped */ 221 res = ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus); 222 if (!res && ServiceStatus.dwCurrentState != SERVICE_STOPPED && 223 ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING && 224 GetLastError() != ERROR_SERVICE_NOT_ACTIVE) 225 { 226 skip("ControlService failed with error %lu!\n", GetLastError()); 227 goto Cleanup; 228 } 229 #endif 230 231 Cleanup: 232 if (hService) 233 { 234 res = DeleteService(hService); 235 ok(res, "DeleteService failed: %lu\n", GetLastError()); 236 CloseServiceHandle(hService); 237 } 238 239 if (hSC) 240 CloseServiceHandle(hSC); 241 } 242 243 START_TEST(ServiceEnv) 244 { 245 int argc; 246 char** argv; 247 248 /* Check whether this test is started as a separated service process */ 249 argc = winetest_get_mainargs(&argv); 250 if (argc >= 3) 251 { 252 service_process(start_service, argc, argv); 253 return; 254 } 255 256 /* We are started as the real test */ 257 test_runner(my_test_server, NULL); 258 // trace("Returned from test_runner\n"); 259 } 260