1 /* 2 * Unit tests for service functions 3 * 4 * Copyright (c) 2007 Paul Vriens 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #define WIN32_NO_STATUS 22 #define WIN32_LEAN_AND_MEAN 23 24 #include <stdarg.h> 25 #include <stdio.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winerror.h" 30 #include "winreg.h" 31 #include "winsvc.h" 32 #include "winnls.h" 33 #include "lmcons.h" 34 #include "aclapi.h" 35 36 #include "wine/test.h" 37 38 static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */ 39 static CHAR selfname[MAX_PATH]; 40 41 static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID); 42 static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD, 43 DWORD, LPBYTE, DWORD, LPDWORD, 44 LPDWORD, LPDWORD, LPCSTR); 45 static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD, 46 DWORD, LPBYTE, DWORD, LPDWORD, 47 LPDWORD, LPDWORD, LPCWSTR); 48 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, 49 PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); 50 static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); 51 static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); 52 static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, 53 DWORD, LPDWORD); 54 static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION, 55 PSECURITY_DESCRIPTOR, DWORD, LPDWORD); 56 static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*); 57 58 static void init_function_pointers(void) 59 { 60 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); 61 62 pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A"); 63 pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA"); 64 pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW"); 65 pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo"); 66 pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A"); 67 pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W"); 68 pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx"); 69 pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity"); 70 pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW"); 71 } 72 73 static void test_open_scm(void) 74 { 75 SC_HANDLE scm_handle; 76 77 /* No access rights */ 78 SetLastError(0xdeadbeef); 79 scm_handle = OpenSCManagerA(NULL, NULL, 0); 80 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError()); 81 CloseServiceHandle(scm_handle); 82 83 /* Unknown database name */ 84 SetLastError(0xdeadbeef); 85 scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT); 86 ok(!scm_handle, "Expected failure\n"); 87 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError()); 88 CloseServiceHandle(scm_handle); /* Just in case */ 89 90 /* MSDN says only ServiceActive is allowed, or NULL */ 91 SetLastError(0xdeadbeef); 92 scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT); 93 ok(!scm_handle, "Expected failure\n"); 94 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError()); 95 CloseServiceHandle(scm_handle); /* Just in case */ 96 97 /* Remote unknown host */ 98 SetLastError(0xdeadbeef); 99 scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT); 100 todo_wine 101 { 102 ok(!scm_handle, "Expected failure\n"); 103 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */, 104 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError()); 105 } 106 CloseServiceHandle(scm_handle); /* Just in case */ 107 108 /* Proper call with an empty hostname */ 109 scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT); 110 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError()); 111 CloseServiceHandle(scm_handle); 112 113 /* Again a correct one */ 114 SetLastError(0xdeadbeef); 115 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 116 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_IO_PENDING) /* win2k */, 117 "Expected ERROR_SUCCESS, got %u\n", GetLastError()); 118 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError()); 119 CloseServiceHandle(scm_handle); 120 } 121 122 static void test_open_svc(void) 123 { 124 SC_HANDLE scm_handle, svc_handle; 125 CHAR displayname[4096]; 126 DWORD displaysize; 127 128 /* All NULL (invalid access rights) */ 129 SetLastError(0xdeadbeef); 130 svc_handle = OpenServiceA(NULL, NULL, 0); 131 ok(!svc_handle, "Expected failure\n"); 132 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 133 134 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */ 135 136 /* NULL service */ 137 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 138 SetLastError(0xdeadbeef); 139 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ); 140 ok(!svc_handle, "Expected failure\n"); 141 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ || 142 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 143 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 144 CloseServiceHandle(scm_handle); 145 146 /* Nonexistent service */ 147 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 148 SetLastError(0xdeadbeef); 149 svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ); 150 ok(!svc_handle, "Expected failure\n"); 151 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 152 CloseServiceHandle(scm_handle); 153 154 /* Proper SCM handle but different access rights */ 155 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 156 SetLastError(0xdeadbeef); 157 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_WRITE); 158 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 159 skip("Not enough rights to get a handle to the service\n"); 160 else 161 { 162 ok(svc_handle != NULL, "Expected success, got error %u\n", GetLastError()); 163 CloseServiceHandle(svc_handle); 164 } 165 166 /* Test to show we can't open a service with the displayname */ 167 168 /* Retrieve the needed size for the buffer */ 169 displaysize = 0; 170 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize); 171 /* Get the displayname */ 172 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 173 /* Try to open the service with this displayname, unless the displayname equals 174 * the servicename as that would defeat the purpose of this test. 175 */ 176 if (!lstrcmpiA(spooler, displayname)) 177 { 178 skip("displayname equals servicename\n"); 179 CloseServiceHandle(scm_handle); 180 return; 181 } 182 183 SetLastError(0xdeadbeef); 184 svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ); 185 ok(!svc_handle, "Expected failure\n"); 186 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 187 /* Just in case */ 188 CloseServiceHandle(svc_handle); 189 190 CloseServiceHandle(scm_handle); 191 } 192 193 static void test_create_delete_svc(void) 194 { 195 SC_HANDLE scm_handle, svc_handle1, svc_handle2; 196 CHAR username[UNLEN + 1], domain[MAX_PATH]; 197 DWORD user_size = UNLEN + 1; 198 CHAR account[UNLEN + 3]; 199 static const CHAR servicename [] = "Winetest"; 200 static const CHAR pathname [] = "we_dont_care.exe"; 201 static const CHAR empty [] = ""; 202 static const CHAR password [] = "secret"; 203 BOOL spooler_exists = FALSE; 204 BOOL ret; 205 CHAR display[4096]; 206 DWORD display_size = sizeof(display); 207 208 /* Get the username and turn it into an account to be used in some tests */ 209 GetUserNameA(username, &user_size); 210 /* Get the domainname to cater for that situation */ 211 if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH)) 212 sprintf(account, "%s\\%s", domain, username); 213 else 214 sprintf(account, ".\\%s", username); 215 216 /* All NULL */ 217 SetLastError(0xdeadbeef); 218 svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL); 219 ok(!svc_handle1, "Expected failure\n"); 220 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 221 222 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 223 224 /* Only a valid handle to the Service Control Manager */ 225 SetLastError(0xdeadbeef); 226 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL); 227 ok(!svc_handle1, "Expected failure\n"); 228 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ || 229 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 230 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 231 232 /* Now with a servicename */ 233 SetLastError(0xdeadbeef); 234 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL); 235 ok(!svc_handle1, "Expected failure\n"); 236 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ || 237 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 238 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 239 240 /* Or just a binary name */ 241 SetLastError(0xdeadbeef); 242 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL); 243 ok(!svc_handle1, "Expected failure\n"); 244 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ || 245 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 246 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 247 248 /* Both servicename and binary name (We only have connect rights) */ 249 SetLastError(0xdeadbeef); 250 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL); 251 ok(!svc_handle1, "Expected failure\n"); 252 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 253 254 /* They can even be empty at this stage of parameter checking */ 255 SetLastError(0xdeadbeef); 256 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL); 257 ok(!svc_handle1, "Expected failure\n"); 258 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 259 260 SetLastError(0xdeadbeef); 261 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL); 262 ok(!svc_handle1, "Expected failure\n"); 263 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 264 265 /* Open the Service Control Manager with minimal rights for creation 266 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE') 267 */ 268 CloseServiceHandle(scm_handle); 269 SetLastError(0xdeadbeef); 270 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 271 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 272 { 273 skip("Not enough rights to get a handle to the manager\n"); 274 return; 275 } 276 277 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */ 278 279 /* Empty strings for servicename and binary name are checked */ 280 SetLastError(0xdeadbeef); 281 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL); 282 ok(!svc_handle1, "Expected failure\n"); 283 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError()); 284 285 SetLastError(0xdeadbeef); 286 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL); 287 ok(!svc_handle1, "Expected failure\n"); 288 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 289 290 SetLastError(0xdeadbeef); 291 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL); 292 ok(!svc_handle1, "Expected failure\n"); 293 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError()); 294 295 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed 296 * an ERROR_INVALID_PARAMETER) 297 */ 298 SetLastError(0xdeadbeef); 299 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS, 300 SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL); 301 ok(!svc_handle1, "Expected failure\n"); 302 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 303 304 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */ 305 306 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with 307 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call) 308 */ 309 SetLastError(0xdeadbeef); 310 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS, 311 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 312 ok(!svc_handle1, "Expected failure\n"); 313 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 314 315 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */ 316 SetLastError(0xdeadbeef); 317 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS, 318 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 319 ok(!svc_handle1, "Expected failure\n"); 320 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 321 322 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used) 323 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT. 324 */ 325 SetLastError(0xdeadbeef); 326 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 327 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password); 328 ok(!svc_handle1, "Expected failure\n"); 329 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT, 330 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError()); 331 332 /* Illegal (start-type is not a mask and should only be one of the possibilities) 333 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as 334 * it's most likely not the wanted start-type) 335 */ 336 SetLastError(0xdeadbeef); 337 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS, 338 SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 339 ok(!svc_handle1, "Expected failure\n"); 340 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 341 342 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */ 343 SetLastError(0xdeadbeef); 344 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS, 345 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL); 346 ok(!svc_handle1, "Expected failure\n"); 347 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 348 349 /* Test if ServiceType can be a combined one for drivers */ 350 SetLastError(0xdeadbeef); 351 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER, 352 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL); 353 ok(!svc_handle1, "Expected failure\n"); 354 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 355 356 /* The service already exists (check first, just in case) */ 357 svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ); 358 if (svc_handle1) 359 { 360 spooler_exists = TRUE; 361 CloseServiceHandle(svc_handle1); 362 SetLastError(0xdeadbeef); 363 svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS, 364 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 365 ok(!svc_handle1, "Expected failure\n"); 366 ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError()); 367 } 368 else 369 skip("Spooler service doesn't exist\n"); 370 371 /* To find an existing displayname we check the 'Spooler' service. Although the registry 372 * doesn't show DisplayName on NT4, this call will return a displayname which is equal 373 * to the servicename and can't be used as well for a new displayname. 374 */ 375 if (spooler_exists) 376 { 377 ret = GetServiceDisplayNameA(scm_handle, spooler, display, &display_size); 378 379 if (!ret) 380 skip("Could not retrieve a displayname for the Spooler service\n"); 381 else 382 { 383 svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS, 384 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 385 ok(!svc_handle1, "Expected failure for display name '%s'\n", display); 386 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, 387 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError()); 388 } 389 } 390 else 391 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n"); 392 393 /* Windows doesn't care about the access rights for creation (which makes 394 * sense as there is no service yet) as long as there are sufficient 395 * rights to the manager. 396 */ 397 SetLastError(0xdeadbeef); 398 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 399 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 400 ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError()); 401 402 /* DeleteService however must have proper rights */ 403 SetLastError(0xdeadbeef); 404 ret = DeleteService(svc_handle1); 405 ok(!ret, "Expected failure\n"); 406 ok(GetLastError() == ERROR_ACCESS_DENIED, 407 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 408 409 /* Open the service with minimal rights for deletion. 410 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE') 411 */ 412 CloseServiceHandle(svc_handle1); 413 svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE); 414 415 /* Now that we have the proper rights, we should be able to delete */ 416 SetLastError(0xdeadbeef); 417 ret = DeleteService(svc_handle1); 418 ok(ret, "Expected success, got error %u\n", GetLastError()); 419 420 /* Service is marked for delete, but handle is still open. Try to open service again. */ 421 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ); 422 ok(svc_handle2 != NULL, "got %p, error %u\n", svc_handle2, GetLastError()); 423 CloseServiceHandle(svc_handle2); 424 425 CloseServiceHandle(svc_handle1); 426 CloseServiceHandle(scm_handle); 427 428 /* Wait a while. One of the following tests also does a CreateService for the 429 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE 430 * error if we do this too quickly. Vista seems more picky than the others. 431 */ 432 Sleep(1000); 433 434 /* And a final NULL check */ 435 SetLastError(0xdeadbeef); 436 ret = DeleteService(NULL); 437 ok(!ret, "Expected failure\n"); 438 ok(GetLastError() == ERROR_INVALID_HANDLE, 439 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 440 } 441 442 static void test_get_displayname(void) 443 { 444 SC_HANDLE scm_handle, svc_handle; 445 BOOL ret; 446 CHAR displayname[4096]; 447 WCHAR displaynameW[2048]; 448 DWORD displaysize, tempsize, tempsizeW; 449 static const CHAR deadbeef[] = "Deadbeef"; 450 static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0}; 451 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0}; 452 static const WCHAR abcW[] = {'A','B','C',0}; 453 static const CHAR servicename[] = "Winetest"; 454 static const CHAR pathname[] = "we_dont_care.exe"; 455 456 /* Having NULL for the size of the buffer will crash on W2K3 */ 457 458 SetLastError(0xdeadbeef); 459 ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize); 460 ok(!ret, "Expected failure\n"); 461 ok(GetLastError() == ERROR_INVALID_HANDLE, 462 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 463 464 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 465 466 SetLastError(0xdeadbeef); 467 ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize); 468 ok(!ret, "Expected failure\n"); 469 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ || 470 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 471 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 472 473 SetLastError(0xdeadbeef); 474 displaysize = sizeof(displayname); 475 ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize); 476 ok(!ret, "Expected failure\n"); 477 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ || 478 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 479 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 480 481 /* Test for nonexistent service */ 482 SetLastError(0xdeadbeef); 483 displaysize = -1; 484 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize); 485 ok(!ret, "Expected failure\n"); 486 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 487 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 488 489 SetLastError(0xdeadbeef); 490 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize); 491 ok(!ret, "Expected failure\n"); 492 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 493 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 494 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize); 495 496 displaysize = 15; 497 strcpy(displayname, "ABC"); 498 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize); 499 ok(!ret, "Expected failure\n"); 500 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 501 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 502 todo_wine ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize); 503 ok(displayname[0] == 0, "Service name not empty\n"); 504 505 displaysize = 15; 506 lstrcpyW( displaynameW, abcW ); 507 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize); 508 ok(!ret, "Expected failure\n"); 509 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 510 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 511 ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize); 512 ok(displaynameW[0] == 0, "Service name not empty\n"); 513 514 displaysize = 0; 515 strcpy(displayname, "ABC"); 516 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize); 517 ok(!ret, "Expected failure\n"); 518 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 519 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 520 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize); 521 ok(displayname[0] == 'A', "Service name changed\n"); 522 523 displaysize = 0; 524 lstrcpyW( displaynameW, abcW ); 525 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize); 526 ok(!ret, "Expected failure\n"); 527 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize); 528 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 529 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 530 ok(displaynameW[0] == 'A', "Service name changed\n"); 531 532 displaysize = 1; 533 strcpy(displayname, "ABC"); 534 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize); 535 ok(!ret, "Expected failure\n"); 536 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 537 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 538 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize); 539 ok(displayname[0] == 0, "Service name not empty\n"); 540 541 displaysize = 1; 542 lstrcpyW( displaynameW, abcW ); 543 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize); 544 ok(!ret, "Expected failure\n"); 545 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize); 546 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 547 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 548 ok(displaynameW[0] == 'A', "Service name changed\n"); 549 550 displaysize = 2; 551 strcpy(displayname, "ABC"); 552 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize); 553 ok(!ret, "Expected failure\n"); 554 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 555 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 556 todo_wine ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize); 557 ok(displayname[0] == 0, "Service name not empty\n"); 558 559 displaysize = 2; 560 lstrcpyW( displaynameW, abcW ); 561 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize); 562 ok(!ret, "Expected failure\n"); 563 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize); 564 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 565 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 566 ok(displaynameW[0] == 0, "Service name not empty\n"); 567 568 /* Check if 'Spooler' exists */ 569 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ); 570 if (!svc_handle) 571 { 572 skip("Spooler service doesn't exist\n"); 573 CloseServiceHandle(scm_handle); 574 return; 575 } 576 CloseServiceHandle(svc_handle); 577 578 /* Retrieve the needed size for the buffer */ 579 SetLastError(0xdeadbeef); 580 displaysize = -1; 581 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize); 582 ok(!ret, "Expected failure\n"); 583 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 584 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 585 tempsize = displaysize; 586 587 displaysize = 0; 588 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize); 589 ok(!ret, "Expected failure\n"); 590 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 591 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 592 ok(displaysize == tempsize, "Buffer size mismatch (%d vs %d)\n", tempsize, displaysize); 593 594 /* Buffer is too small */ 595 SetLastError(0xdeadbeef); 596 displaysize = (tempsize / 2); 597 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 598 ok(!ret, "Expected failure\n"); 599 ok(displaysize == tempsize, "Expected the needed buffersize\n"); 600 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 601 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 602 603 /* First try with a buffer that should be big enough to hold 604 * the ANSI string (and terminating character). This succeeds on Windows 605 * although when asked (see above 2 tests) it will return twice the needed size. 606 */ 607 SetLastError(0xdeadbeef); 608 displaysize = (tempsize / 2) + 1; 609 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 610 ok(ret, "Expected success, got error %u\n", GetLastError()); 611 ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n"); 612 613 /* Now with the original returned size */ 614 SetLastError(0xdeadbeef); 615 displaysize = tempsize; 616 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 617 ok(ret, "Expected success, got error %u\n", GetLastError()); 618 ok(displaysize == tempsize, "Expected no change for the needed buffer size\n"); 619 620 /* And with a bigger than needed buffer */ 621 SetLastError(0xdeadbeef); 622 displaysize = tempsize * 2; 623 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 624 ok(ret, "Expected success, got error %u\n", GetLastError()); 625 /* Test that shows that if the buffersize is enough, it's not changed */ 626 ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n"); 627 ok(strlen(displayname) == tempsize/2, 628 "Expected the buffer to be twice the length of the string\n") ; 629 630 /* Do the buffer(size) tests also for GetServiceDisplayNameW */ 631 SetLastError(0xdeadbeef); 632 displaysize = -1; 633 ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize); 634 ok(!ret, "Expected failure\n"); 635 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 636 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 637 638 /* Buffer is too small */ 639 SetLastError(0xdeadbeef); 640 tempsizeW = displaysize; 641 displaysize = tempsizeW / 2; 642 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); 643 ok(!ret, "Expected failure\n"); 644 ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); 645 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 646 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 647 648 /* Now with the original returned size */ 649 SetLastError(0xdeadbeef); 650 displaysize = tempsizeW; 651 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); 652 ok(!ret, "Expected failure\n"); 653 ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); 654 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 655 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 656 657 /* And with a bigger than needed buffer */ 658 SetLastError(0xdeadbeef); 659 displaysize = tempsizeW + 1; /* This caters for the null terminating character */ 660 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize); 661 ok(ret, "Expected success, got error %u\n", GetLastError()); 662 ok(displaysize == tempsizeW, "Expected the needed buffersize\n"); 663 ok(lstrlenW(displaynameW) == displaysize, 664 "Expected the buffer to be the length of the string\n") ; 665 ok(tempsize / 2 == tempsizeW, 666 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n"); 667 668 CloseServiceHandle(scm_handle); 669 670 /* Test for a service without a displayname (which is valid). This should return 671 * the servicename itself. 672 */ 673 SetLastError(0xdeadbeef); 674 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 675 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 676 { 677 skip("Not enough rights to get a handle to the manager\n"); 678 return; 679 } 680 681 SetLastError(0xdeadbeef); 682 svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE, 683 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 684 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 685 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError()); 686 if (!svc_handle) 687 { 688 CloseServiceHandle(scm_handle); 689 return; 690 } 691 692 /* Retrieve the needed size for the buffer */ 693 SetLastError(0xdeadbeef); 694 displaysize = -1; 695 ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize); 696 ok(!ret, "Expected failure\n"); 697 ok(displaysize == strlen(servicename) * 2, 698 "Expected the displaysize to be twice the size of the servicename\n"); 699 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 700 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 701 702 /* Buffer is too small */ 703 SetLastError(0xdeadbeef); 704 tempsize = displaysize; 705 displaysize = (tempsize / 2); 706 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize); 707 ok(!ret, "Expected failure\n"); 708 ok(displaysize == tempsize, "Expected the needed buffersize\n"); 709 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 710 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 711 712 /* Get the displayname */ 713 SetLastError(0xdeadbeef); 714 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize); 715 ok(ret, "Expected success, got error %u\n", GetLastError()); 716 ok(!lstrcmpiA(displayname, servicename), 717 "Expected displayname to be %s, got %s\n", servicename, displayname); 718 719 /* Delete the service */ 720 ret = DeleteService(svc_handle); 721 ok(ret, "Expected success (err=%d)\n", GetLastError()); 722 723 CloseServiceHandle(svc_handle); 724 CloseServiceHandle(scm_handle); 725 726 /* Wait a while. Just in case one of the following tests does a CreateService again */ 727 Sleep(1000); 728 } 729 730 static void test_get_servicekeyname(void) 731 { 732 SC_HANDLE scm_handle, svc_handle; 733 CHAR servicename[4096]; 734 CHAR displayname[4096]; 735 WCHAR servicenameW[4096]; 736 WCHAR displaynameW[4096]; 737 DWORD servicesize, displaysize, tempsize; 738 BOOL ret; 739 static const CHAR deadbeef[] = "Deadbeef"; 740 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0}; 741 static const WCHAR abcW[] = {'A','B','C',0}; 742 743 /* Having NULL for the size of the buffer will crash on W2K3 */ 744 745 SetLastError(0xdeadbeef); 746 ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize); 747 ok(!ret, "Expected failure\n"); 748 ok(GetLastError() == ERROR_INVALID_HANDLE, 749 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 750 751 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 752 753 servicesize = 200; 754 SetLastError(0xdeadbeef); 755 ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize); 756 ok(!ret, "Expected failure\n"); 757 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ || 758 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 759 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 760 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize); 761 762 /* Valid handle and buffer but no displayname */ 763 servicesize = 200; 764 SetLastError(0xdeadbeef); 765 ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize); 766 ok(!ret, "Expected failure\n"); 767 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ || 768 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 769 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 770 todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize); 771 772 /* Test for nonexistent displayname */ 773 SetLastError(0xdeadbeef); 774 ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize); 775 ok(!ret, "Expected failure\n"); 776 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 777 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 778 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize); 779 780 servicesize = 15; 781 strcpy(servicename, "ABC"); 782 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize); 783 ok(!ret, "Expected failure\n"); 784 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 785 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 786 todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize); 787 ok(servicename[0] == 0, "Service name not empty\n"); 788 789 servicesize = 15; 790 lstrcpyW( servicenameW, abcW ); 791 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize); 792 ok(!ret, "Expected failure\n"); 793 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 794 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 795 ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize); 796 ok(servicenameW[0] == 0, "Service name not empty\n"); 797 798 servicesize = 0; 799 strcpy(servicename, "ABC"); 800 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize); 801 ok(!ret, "Expected failure\n"); 802 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 803 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 804 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize); 805 ok(servicename[0] == 'A', "Service name changed\n"); 806 807 servicesize = 0; 808 lstrcpyW( servicenameW, abcW ); 809 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize); 810 ok(!ret, "Expected failure\n"); 811 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize); 812 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 813 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 814 ok(servicenameW[0] == 'A', "Service name changed\n"); 815 816 servicesize = 1; 817 strcpy(servicename, "ABC"); 818 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize); 819 ok(!ret, "Expected failure\n"); 820 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 821 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 822 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize); 823 ok(servicename[0] == 0, "Service name not empty\n"); 824 825 servicesize = 1; 826 lstrcpyW( servicenameW, abcW ); 827 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize); 828 ok(!ret, "Expected failure\n"); 829 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize); 830 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 831 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 832 ok(servicenameW[0] == 'A', "Service name changed\n"); 833 834 servicesize = 2; 835 strcpy(servicename, "ABC"); 836 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize); 837 ok(!ret, "Expected failure\n"); 838 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 839 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 840 todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize); 841 ok(servicename[0] == 0, "Service name not empty\n"); 842 843 servicesize = 2; 844 lstrcpyW( servicenameW, abcW ); 845 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize); 846 ok(!ret, "Expected failure\n"); 847 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize); 848 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 849 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 850 ok(servicenameW[0] == 0, "Service name not empty\n"); 851 852 /* Check if 'Spooler' exists */ 853 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ); 854 if (!svc_handle) 855 { 856 skip("Spooler service doesn't exist\n"); 857 CloseServiceHandle(scm_handle); 858 return; 859 } 860 CloseServiceHandle(svc_handle); 861 862 /* Get the displayname for the 'Spooler' service */ 863 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize); 864 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize); 865 866 /* Retrieve the needed size for the buffer */ 867 SetLastError(0xdeadbeef); 868 servicesize = 0; 869 ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize); 870 ok(!ret, "Expected failure\n"); 871 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 872 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 873 874 /* Valid call with the correct buffersize */ 875 SetLastError(0xdeadbeef); 876 tempsize = servicesize; 877 servicesize *= 2; 878 ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize); 879 ok(ret, "Expected success, got error %u\n", GetLastError()); 880 if (ret) 881 { 882 ok(strlen(servicename) == tempsize/2, 883 "Expected the buffer to be twice the length of the string\n") ; 884 ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename); 885 ok(servicesize == (tempsize * 2), 886 "Expected servicesize not to change if buffer not insufficient\n") ; 887 } 888 889 MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2); 890 SetLastError(0xdeadbeef); 891 servicesize *= 2; 892 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize); 893 ok(ret, "Expected success, got error %u\n", GetLastError()); 894 if (ret) 895 { 896 ok(strlen(servicename) == tempsize/2, 897 "Expected the buffer to be twice the length of the string\n") ; 898 ok(servicesize == lstrlenW(servicenameW), 899 "Expected servicesize not to change if buffer not insufficient\n") ; 900 } 901 902 SetLastError(0xdeadbeef); 903 servicesize = 3; 904 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize); 905 ok(!ret, "Expected failure\n"); 906 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 907 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 908 ok(servicenameW[0] == 0, "Buffer not empty\n"); 909 910 CloseServiceHandle(scm_handle); 911 } 912 913 static void test_query_svc(void) 914 { 915 SC_HANDLE scm_handle, svc_handle; 916 BOOL ret; 917 SERVICE_STATUS status; 918 SERVICE_STATUS_PROCESS *statusproc; 919 DWORD bufsize, needed; 920 921 /* All NULL or wrong */ 922 SetLastError(0xdeadbeef); 923 ret = QueryServiceStatus(NULL, NULL); 924 ok(!ret, "Expected failure\n"); 925 ok(GetLastError() == ERROR_INVALID_HANDLE, 926 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 927 928 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 929 930 /* Check if 'Spooler' exists. 931 * Open with not enough rights to query the status. 932 */ 933 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ); 934 if (!svc_handle) 935 { 936 skip("Spooler service doesn't exist\n"); 937 CloseServiceHandle(scm_handle); 938 return; 939 } 940 941 SetLastError(0xdeadbeef); 942 ret = QueryServiceStatus(svc_handle, NULL); 943 ok(!ret, "Expected failure\n"); 944 ok(GetLastError() == ERROR_INVALID_ADDRESS || 945 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 946 "Unexpected last error %d\n", GetLastError()); 947 948 SetLastError(0xdeadbeef); 949 ret = QueryServiceStatus(svc_handle, &status); 950 ok(!ret, "Expected failure\n"); 951 ok(GetLastError() == ERROR_ACCESS_DENIED, 952 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 953 954 /* Open the service with just enough rights. 955 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS') 956 */ 957 CloseServiceHandle(svc_handle); 958 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS); 959 960 SetLastError(0xdeadbeef); 961 ret = QueryServiceStatus(svc_handle, &status); 962 ok(ret, "Expected success, got error %u\n", GetLastError()); 963 964 CloseServiceHandle(svc_handle); 965 966 /* More or less the same tests for QueryServiceStatusEx */ 967 if (!pQueryServiceStatusEx) 968 { 969 win_skip( "QueryServiceStatusEx not available\n" ); 970 CloseServiceHandle(scm_handle); 971 return; 972 } 973 974 /* Open service with not enough rights to query the status */ 975 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ); 976 977 /* All NULL or wrong, this proves that info level is checked first */ 978 SetLastError(0xdeadbeef); 979 ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL); 980 ok(!ret, "Expected failure\n"); 981 ok(GetLastError() == ERROR_INVALID_LEVEL, 982 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError()); 983 984 /* Passing a NULL parameter for the needed buffer size 985 * will crash on anything but NT4. 986 */ 987 988 /* Only info level is correct. It looks like the buffer/size is checked second */ 989 SetLastError(0xdeadbeef); 990 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed); 991 /* NT4 checks the handle first */ 992 if (GetLastError() != ERROR_INVALID_HANDLE) 993 { 994 ok(!ret, "Expected failure\n"); 995 ok(needed == sizeof(SERVICE_STATUS_PROCESS), 996 "Needed buffersize is wrong : %d\n", needed); 997 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 998 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 999 } 1000 1001 /* Pass a correct buffer and buffersize but a NULL handle */ 1002 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS)); 1003 bufsize = needed; 1004 SetLastError(0xdeadbeef); 1005 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed); 1006 ok(!ret, "Expected failure\n"); 1007 ok(GetLastError() == ERROR_INVALID_HANDLE, 1008 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1009 HeapFree(GetProcessHeap(), 0, statusproc); 1010 1011 /* Correct handle and info level */ 1012 SetLastError(0xdeadbeef); 1013 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed); 1014 /* NT4 doesn't return the needed size */ 1015 if (GetLastError() != ERROR_INVALID_PARAMETER) 1016 { 1017 ok(!ret, "Expected failure\n"); 1018 ok(needed == sizeof(SERVICE_STATUS_PROCESS), 1019 "Needed buffersize is wrong : %d\n", needed); 1020 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, 1021 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 1022 } 1023 1024 /* All parameters are OK but we don't have enough rights */ 1025 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS)); 1026 bufsize = sizeof(SERVICE_STATUS_PROCESS); 1027 SetLastError(0xdeadbeef); 1028 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed); 1029 ok(!ret, "Expected failure\n"); 1030 ok(GetLastError() == ERROR_ACCESS_DENIED, 1031 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1032 HeapFree(GetProcessHeap(), 0, statusproc); 1033 1034 /* Open the service with just enough rights. */ 1035 CloseServiceHandle(svc_handle); 1036 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS); 1037 1038 /* Everything should be fine now. */ 1039 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS)); 1040 bufsize = sizeof(SERVICE_STATUS_PROCESS); 1041 SetLastError(0xdeadbeef); 1042 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed); 1043 ok(ret, "Expected success, got error %u\n", GetLastError()); 1044 if (statusproc->dwCurrentState == SERVICE_RUNNING) 1045 ok(statusproc->dwProcessId != 0, 1046 "Expect a process id for this running service\n"); 1047 else 1048 ok(statusproc->dwProcessId == 0, 1049 "Expect no process id for this stopped service\n"); 1050 1051 /* same call with null needed pointer */ 1052 SetLastError(0xdeadbeef); 1053 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL); 1054 ok(!ret, "Expected failure\n"); 1055 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ || 1056 GetLastError() == ERROR_INVALID_ADDRESS, "got %d\n", GetLastError()); 1057 1058 HeapFree(GetProcessHeap(), 0, statusproc); 1059 1060 CloseServiceHandle(svc_handle); 1061 CloseServiceHandle(scm_handle); 1062 } 1063 1064 static void test_enum_svc(void) 1065 { 1066 SC_HANDLE scm_handle; 1067 BOOL ret; 1068 DWORD bufsize, needed, returned, resume; 1069 DWORD neededW, returnedW; 1070 DWORD tempneeded, tempreturned, missing; 1071 DWORD servicecountactive, servicecountinactive; 1072 ENUM_SERVICE_STATUSA *services; 1073 ENUM_SERVICE_STATUSW *servicesW; 1074 ENUM_SERVICE_STATUS_PROCESSA *exservices; 1075 UINT i; 1076 1077 /* All NULL or wrong */ 1078 SetLastError(0xdeadbeef); 1079 ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL); 1080 ok(!ret, "Expected failure\n"); 1081 ok(GetLastError() == ERROR_INVALID_HANDLE, 1082 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1083 1084 SetLastError(0xdeadbeef); 1085 ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL); 1086 ok(!ret, "Expected failure\n"); 1087 ok(GetLastError() == ERROR_INVALID_HANDLE, 1088 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1089 1090 /* Open the service control manager with not enough rights at first */ 1091 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 1092 1093 /* Valid handle but rest is still NULL or wrong */ 1094 SetLastError(0xdeadbeef); 1095 ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL); 1096 ok(!ret, "Expected failure\n"); 1097 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1098 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1099 "Unexpected last error %d\n", GetLastError()); 1100 1101 SetLastError(0xdeadbeef); 1102 ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL); 1103 ok(!ret, "Expected failure\n"); 1104 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1105 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1106 "Unexpected last error %d\n", GetLastError()); 1107 1108 /* Don't specify the two required pointers */ 1109 returned = 0xdeadbeef; 1110 SetLastError(0xdeadbeef); 1111 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL); 1112 ok(!ret, "Expected failure\n"); 1113 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n"); 1114 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1115 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1116 "Unexpected last error %d\n", GetLastError()); 1117 1118 returned = 0xdeadbeef; 1119 SetLastError(0xdeadbeef); 1120 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL); 1121 ok(!ret, "Expected failure\n"); 1122 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n"); 1123 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1124 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1125 "Unexpected last error %d\n", GetLastError()); 1126 1127 /* Don't specify the two required pointers */ 1128 needed = 0xdeadbeef; 1129 SetLastError(0xdeadbeef); 1130 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL); 1131 ok(!ret, "Expected failure\n"); 1132 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */ 1133 "Expected no change to the needed buffer variable\n"); 1134 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1135 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1136 "Unexpected last error %d\n", GetLastError()); 1137 1138 needed = 0xdeadbeef; 1139 SetLastError(0xdeadbeef); 1140 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL); 1141 ok(!ret, "Expected failure\n"); 1142 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */ 1143 "Expected no change to the needed buffer variable\n"); 1144 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1145 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1146 "Unexpected last error %d\n", GetLastError()); 1147 1148 /* No valid servicetype and servicestate */ 1149 needed = 0xdeadbeef; 1150 returned = 0xdeadbeef; 1151 SetLastError(0xdeadbeef); 1152 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL); 1153 ok(!ret, "Expected failure\n"); 1154 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1155 "Expected needed buffer size to be set to 0, got %d\n", needed); 1156 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned); 1157 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1158 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1159 1160 needed = 0xdeadbeef; 1161 returned = 0xdeadbeef; 1162 SetLastError(0xdeadbeef); 1163 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL); 1164 ok(!ret, "Expected failure\n"); 1165 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1166 "Expected needed buffer size to be set to 0, got %d\n", needed); 1167 ok(returned == 0 || broken(returned != 0), /* nt4 */ 1168 "Expected number of services to be set to 0, got %d\n", returned); 1169 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1170 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1171 1172 /* No valid servicestate */ 1173 needed = 0xdeadbeef; 1174 returned = 0xdeadbeef; 1175 SetLastError(0xdeadbeef); 1176 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL); 1177 ok(!ret, "Expected failure\n"); 1178 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1179 "Expected needed buffer size to be set to 0, got %d\n", needed); 1180 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned); 1181 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1182 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1183 1184 needed = 0xdeadbeef; 1185 returned = 0xdeadbeef; 1186 SetLastError(0xdeadbeef); 1187 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL); 1188 ok(!ret, "Expected failure\n"); 1189 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1190 "Expected needed buffer size to be set to 0, got %d\n", needed); 1191 ok(returned == 0 || broken(returned != 0), /* nt4 */ 1192 "Expected number of services to be set to 0, got %d\n", returned); 1193 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1194 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1195 1196 /* No valid servicetype */ 1197 needed = 0xdeadbeef; 1198 returned = 0xdeadbeef; 1199 SetLastError(0xdeadbeef); 1200 ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); 1201 ok(!ret, "Expected failure\n"); 1202 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1203 "Expected needed buffer size to be set to 0, got %d\n", needed); 1204 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned); 1205 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1206 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1207 1208 needed = 0xdeadbeef; 1209 returned = 0xdeadbeef; 1210 SetLastError(0xdeadbeef); 1211 ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); 1212 ok(!ret, "Expected failure\n"); 1213 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1214 "Expected needed buffer size to be set to 0, got %d\n", needed); 1215 ok(returned == 0 || broken(returned != 0), /* nt4 */ 1216 "Expected number of services to be set to 0, got %d\n", returned); 1217 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1218 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1219 1220 /* All parameters are correct but our access rights are wrong */ 1221 needed = 0xdeadbeef; 1222 returned = 0xdeadbeef; 1223 SetLastError(0xdeadbeef); 1224 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); 1225 ok(!ret, "Expected failure\n"); 1226 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1227 "Expected needed buffer size to be set to 0, got %d\n", needed); 1228 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned); 1229 ok(GetLastError() == ERROR_ACCESS_DENIED, 1230 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1231 1232 needed = 0xdeadbeef; 1233 returned = 0xdeadbeef; 1234 SetLastError(0xdeadbeef); 1235 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); 1236 ok(!ret, "Expected failure\n"); 1237 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1238 "Expected needed buffer size to be set to 0, got %d\n", needed); 1239 ok(returned == 0 || broken(returned != 0), /* nt4 */ 1240 "Expected number of services to be set to 0, got %d\n", returned); 1241 ok(GetLastError() == ERROR_ACCESS_DENIED, 1242 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1243 1244 /* Open the service control manager with the needed rights */ 1245 CloseServiceHandle(scm_handle); 1246 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); 1247 1248 /* All parameters are correct. Request the needed buffer size */ 1249 needed = 0xdeadbeef; 1250 returned = 0xdeadbeef; 1251 SetLastError(0xdeadbeef); 1252 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL); 1253 ok(!ret, "Expected failure\n"); 1254 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); 1255 ok(returned == 0, "Expected no service returned, got %d\n", returned); 1256 ok(GetLastError() == ERROR_MORE_DATA, 1257 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1258 1259 /* Test to show we get the same needed buffer size for the W-call */ 1260 neededW = 0xdeadbeef; 1261 returnedW = 0xdeadbeef; 1262 SetLastError(0xdeadbeef); 1263 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL); 1264 ok(!ret, "Expected failure\n"); 1265 ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n"); 1266 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); 1267 ok(returnedW == 0, "Expected no service returned, got %d\n", returnedW); 1268 ok(GetLastError() == ERROR_MORE_DATA, 1269 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1270 1271 /* Store the needed bytes */ 1272 tempneeded = needed; 1273 1274 /* Allocate the correct needed bytes */ 1275 services = HeapAlloc(GetProcessHeap(), 0, needed); 1276 bufsize = needed; 1277 needed = 0xdeadbeef; 1278 returned = 0xdeadbeef; 1279 SetLastError(0xdeadbeef); 1280 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, 1281 services, bufsize, &needed, &returned, NULL); 1282 ok(ret, "Expected success, got error %u\n", GetLastError()); 1283 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); 1284 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n"); 1285 HeapFree(GetProcessHeap(), 0, services); 1286 1287 /* Store the number of returned services */ 1288 tempreturned = returned; 1289 1290 servicesW = HeapAlloc(GetProcessHeap(), 0, neededW); 1291 bufsize = neededW; 1292 neededW = 0xdeadbeef; 1293 returnedW = 0xdeadbeef; 1294 SetLastError(0xdeadbeef); 1295 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, 1296 servicesW, bufsize, &neededW, &returnedW, NULL); 1297 ok(ret, "Expected success, got error %u\n", GetLastError()); 1298 ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n"); 1299 ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n"); 1300 HeapFree(GetProcessHeap(), 0, servicesW); 1301 1302 /* Allocate less than the needed bytes and don't specify a resume handle */ 1303 services = HeapAlloc(GetProcessHeap(), 0, tempneeded); 1304 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); 1305 needed = 0xdeadbeef; 1306 returned = 0xdeadbeef; 1307 SetLastError(0xdeadbeef); 1308 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, 1309 services, bufsize, &needed, &returned, NULL); 1310 ok(!ret, "Expected failure\n"); 1311 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); 1312 ok(returned < tempreturned, "Expected fewer services to be returned\n"); 1313 ok(GetLastError() == ERROR_MORE_DATA, 1314 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1315 1316 /* Allocate less than the needed bytes, this time with a correct resume handle */ 1317 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); 1318 needed = 0xdeadbeef; 1319 returned = 0xdeadbeef; 1320 resume = 0; 1321 SetLastError(0xdeadbeef); 1322 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, 1323 services, bufsize, &needed, &returned, &resume); 1324 ok(!ret, "Expected failure\n"); 1325 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n"); 1326 ok(returned < tempreturned, "Expected fewer services to be returned\n"); 1327 todo_wine ok(resume, "Expected a resume handle\n"); 1328 ok(GetLastError() == ERROR_MORE_DATA, 1329 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1330 1331 /* Fetch the missing services but pass a bigger buffer size */ 1332 missing = tempreturned - returned; 1333 bufsize = tempneeded; 1334 needed = 0xdeadbeef; 1335 returned = 0xdeadbeef; 1336 SetLastError(0xdeadbeef); 1337 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, 1338 services, bufsize, &needed, &returned, &resume); 1339 ok(ret, "Expected success, got error %u\n", GetLastError()); 1340 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); 1341 ok(returned == missing, "Expected %u services to be returned\n", missing); 1342 ok(resume == 0, "Expected the resume handle to be 0\n"); 1343 HeapFree(GetProcessHeap(), 0, services); 1344 1345 /* See if things add up */ 1346 1347 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active 1348 * and doesn't count the others as inactive. This means that Vista could 1349 * show a total that is greater than the sum of active and inactive 1350 * drivers. 1351 * The number of active and inactive drivers is greatly influenced by the 1352 * time when tests are run, immediately after boot or later for example. 1353 * 1354 * Both reasons make calculations for drivers not so useful 1355 */ 1356 1357 /* Get the number of active win32 services */ 1358 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, 1359 &needed, &returned, NULL); 1360 services = HeapAlloc(GetProcessHeap(), 0, needed); 1361 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services, 1362 needed, &needed, &returned, NULL); 1363 HeapFree(GetProcessHeap(), 0, services); 1364 1365 servicecountactive = returned; 1366 1367 /* Get the number of inactive win32 services */ 1368 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, 1369 &needed, &returned, NULL); 1370 services = HeapAlloc(GetProcessHeap(), 0, needed); 1371 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services, 1372 needed, &needed, &returned, NULL); 1373 HeapFree(GetProcessHeap(), 0, services); 1374 1375 servicecountinactive = returned; 1376 1377 /* Get the number of win32 services */ 1378 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, 1379 &needed, &returned, NULL); 1380 services = HeapAlloc(GetProcessHeap(), 0, needed); 1381 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services, 1382 needed, &needed, &returned, NULL); 1383 HeapFree(GetProcessHeap(), 0, services); 1384 1385 /* Check if total is the same as active and inactive win32 services */ 1386 ok(returned == (servicecountactive + servicecountinactive), 1387 "Something wrong in the calculation\n"); 1388 1389 /* Get all drivers and services 1390 * 1391 * Fetch the status of the last call as failing could make the following tests crash 1392 * on Wine (we don't return anything yet). 1393 */ 1394 EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, 1395 NULL, 0, &needed, &returned, NULL); 1396 services = HeapAlloc(GetProcessHeap(), 0, needed); 1397 ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL, 1398 services, needed, &needed, &returned, NULL); 1399 1400 /* Loop through all those returned drivers and services */ 1401 for (i = 0; ret && i < returned; i++) 1402 { 1403 SERVICE_STATUS status = services[i].ServiceStatus; 1404 1405 /* lpServiceName and lpDisplayName should always be filled */ 1406 ok(services[i].lpServiceName[0], "Expected a service name\n"); 1407 ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n"); 1408 1409 /* Decrement the counters to see if the functions calls return the same 1410 * numbers as the contents of these structures. 1411 */ 1412 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS)) 1413 { 1414 if (status.dwCurrentState == SERVICE_STOPPED) 1415 servicecountinactive--; 1416 else 1417 servicecountactive--; 1418 } 1419 } 1420 HeapFree(GetProcessHeap(), 0, services); 1421 1422 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive); 1423 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive); 1424 1425 CloseServiceHandle(scm_handle); 1426 1427 /* More or less the same for EnumServicesStatusExA */ 1428 if (!pEnumServicesStatusExA) 1429 { 1430 win_skip( "EnumServicesStatusExA not available\n" ); 1431 return; 1432 } 1433 1434 /* All NULL or wrong */ 1435 SetLastError(0xdeadbeef); 1436 ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL); 1437 ok(!ret, "Expected failure\n"); 1438 ok(GetLastError() == ERROR_INVALID_LEVEL, 1439 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError()); 1440 1441 /* All NULL or wrong, just the info level is correct */ 1442 SetLastError(0xdeadbeef); 1443 ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL); 1444 ok(!ret, "Expected failure\n"); 1445 ok(GetLastError() == ERROR_INVALID_HANDLE, 1446 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1447 1448 /* Open the service control manager with not enough rights at first */ 1449 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 1450 1451 /* Valid handle and info level but rest is still NULL or wrong */ 1452 SetLastError(0xdeadbeef); 1453 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL); 1454 ok(!ret, "Expected failure\n"); 1455 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1456 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1457 "Unexpected last error %d\n", GetLastError()); 1458 1459 /* Don't specify the two required pointers */ 1460 needed = 0xdeadbeef; 1461 SetLastError(0xdeadbeef); 1462 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL); 1463 ok(!ret, "Expected failure\n"); 1464 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */ 1465 "Expected no change to the needed buffer variable\n"); 1466 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1467 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1468 "Unexpected last error %d\n", GetLastError()); 1469 1470 /* Don't specify the two required pointers */ 1471 returned = 0xdeadbeef; 1472 SetLastError(0xdeadbeef); 1473 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL); 1474 ok(!ret, "Expected failure\n"); 1475 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n"); 1476 ok(GetLastError() == ERROR_INVALID_ADDRESS || 1477 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, 1478 "Unexpected last error %d\n", GetLastError()); 1479 1480 /* No valid servicetype and servicestate */ 1481 needed = 0xdeadbeef; 1482 returned = 0xdeadbeef; 1483 SetLastError(0xdeadbeef); 1484 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL); 1485 ok(!ret, "Expected failure\n"); 1486 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1487 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1488 "Expected needed buffer size to be set to 0, got %d\n", needed); 1489 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1490 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1491 1492 /* No valid servicestate */ 1493 needed = 0xdeadbeef; 1494 returned = 0xdeadbeef; 1495 SetLastError(0xdeadbeef); 1496 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0, 1497 &needed, &returned, NULL, NULL); 1498 ok(!ret, "Expected failure\n"); 1499 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1500 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1501 "Expected needed buffer size to be set to 0, got %d\n", needed); 1502 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1503 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1504 1505 /* No valid servicetype */ 1506 needed = 0xdeadbeef; 1507 returned = 0xdeadbeef; 1508 SetLastError(0xdeadbeef); 1509 ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0, 1510 &needed, &returned, NULL, NULL); 1511 ok(!ret, "Expected failure\n"); 1512 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1513 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1514 "Expected needed buffer size to be set to 0, got %d\n", needed); 1515 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1516 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1517 1518 /* No valid servicetype and servicestate and unknown service group */ 1519 needed = 0xdeadbeef; 1520 returned = 0xdeadbeef; 1521 SetLastError(0xdeadbeef); 1522 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, 1523 &returned, NULL, "deadbeef_group"); 1524 ok(!ret, "Expected failure\n"); 1525 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1526 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1527 "Expected needed buffer size to be set to 0, got %d\n", needed); 1528 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1529 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 1530 1531 /* All parameters are correct but our access rights are wrong */ 1532 needed = 0xdeadbeef; 1533 returned = 0xdeadbeef; 1534 SetLastError(0xdeadbeef); 1535 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1536 NULL, 0, &needed, &returned, NULL, NULL); 1537 ok(!ret, "Expected failure\n"); 1538 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1539 "Expected needed buffer size to be set to 0, got %d\n", needed); 1540 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1541 ok(GetLastError() == ERROR_ACCESS_DENIED, 1542 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1543 1544 /* All parameters are correct, access rights are wrong but the 1545 * group name won't be checked yet. 1546 */ 1547 needed = 0xdeadbeef; 1548 returned = 0xdeadbeef; 1549 SetLastError(0xdeadbeef); 1550 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1551 NULL, 0, &needed, &returned, NULL, "deadbeef_group"); 1552 ok(!ret, "Expected failure\n"); 1553 ok(needed == 0 || broken(needed != 0), /* nt4 */ 1554 "Expected needed buffer size to be set to 0, got %d\n", needed); 1555 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1556 ok(GetLastError() == ERROR_ACCESS_DENIED, 1557 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); 1558 1559 /* Open the service control manager with the needed rights */ 1560 CloseServiceHandle(scm_handle); 1561 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); 1562 1563 /* All parameters are correct and the group will be checked */ 1564 needed = 0xdeadbeef; 1565 returned = 0xdeadbeef; 1566 SetLastError(0xdeadbeef); 1567 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1568 NULL, 0, &needed, &returned, NULL, "deadbeef_group"); 1569 ok(!ret, "Expected failure\n"); 1570 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned); 1571 ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed); 1572 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, 1573 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError()); 1574 1575 /* TODO: Create a test that makes sure we enumerate all services that don't 1576 * belong to a group. (specifying ""). 1577 */ 1578 1579 /* All parameters are correct. Request the needed buffer size */ 1580 needed = 0xdeadbeef; 1581 returned = 0xdeadbeef; 1582 SetLastError(0xdeadbeef); 1583 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1584 NULL, 0, &needed, &returned, NULL, NULL); 1585 ok(!ret, "Expected failure\n"); 1586 ok(returned == 0, "Expected no service returned, got %d\n", returned); 1587 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); 1588 ok(GetLastError() == ERROR_MORE_DATA, 1589 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1590 1591 /* Test to show we get the same needed buffer size for the W-call */ 1592 neededW = 0xdeadbeef; 1593 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1594 NULL, 0, &neededW, &returnedW, NULL, NULL); 1595 ok(!ret, "Expected failure\n"); 1596 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); 1597 1598 /* Store the needed bytes */ 1599 tempneeded = needed; 1600 1601 /* Allocate the correct needed bytes */ 1602 exservices = HeapAlloc(GetProcessHeap(), 0, needed); 1603 bufsize = needed; 1604 needed = 0xdeadbeef; 1605 returned = 0xdeadbeef; 1606 SetLastError(0xdeadbeef); 1607 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1608 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); 1609 ok(ret, "Expected success, got error %u\n", GetLastError()); 1610 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); 1611 ok(returned == tempreturned, "Expected the same number of service from this function\n"); 1612 HeapFree(GetProcessHeap(), 0, exservices); 1613 1614 /* Store the number of returned services */ 1615 tempreturned = returned; 1616 1617 /* Allocate less than the needed bytes and don't specify a resume handle */ 1618 exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded); 1619 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); 1620 needed = 0xdeadbeef; 1621 returned = 0xdeadbeef; 1622 SetLastError(0xdeadbeef); 1623 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1624 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL); 1625 ok(!ret, "Expected failure\n"); 1626 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); 1627 ok(returned < tempreturned, "Expected fewer services to be returned\n"); 1628 ok(GetLastError() == ERROR_MORE_DATA, 1629 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1630 1631 /* Allocate less than the needed bytes, this time with a correct resume handle */ 1632 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA); 1633 needed = 0xdeadbeef; 1634 returned = 0xdeadbeef; 1635 resume = 0; 1636 SetLastError(0xdeadbeef); 1637 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1638 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); 1639 ok(!ret, "Expected failure\n"); 1640 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n"); 1641 ok(returned < tempreturned, "Expected fewer services to be returned\n"); 1642 todo_wine ok(resume, "Expected a resume handle\n"); 1643 ok(GetLastError() == ERROR_MORE_DATA, 1644 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 1645 1646 /* Fetch that last service but pass a bigger buffer size */ 1647 missing = tempreturned - returned; 1648 bufsize = tempneeded; 1649 needed = 0xdeadbeef; 1650 returned = 0xdeadbeef; 1651 SetLastError(0xdeadbeef); 1652 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1653 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL); 1654 ok(ret, "Expected success, got error %u\n", GetLastError()); 1655 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n"); 1656 ok(returned == missing, "Expected %u services to be returned\n", missing); 1657 ok(resume == 0, "Expected the resume handle to be 0\n"); 1658 HeapFree(GetProcessHeap(), 0, exservices); 1659 1660 /* See if things add up */ 1661 1662 /* Get the number of active win32 services */ 1663 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, 1664 NULL, 0, &needed, &returned, NULL, NULL); 1665 exservices = HeapAlloc(GetProcessHeap(), 0, needed); 1666 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE, 1667 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); 1668 HeapFree(GetProcessHeap(), 0, exservices); 1669 1670 servicecountactive = returned; 1671 1672 /* Get the number of inactive win32 services */ 1673 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, 1674 NULL, 0, &needed, &returned, NULL, NULL); 1675 exservices = HeapAlloc(GetProcessHeap(), 0, needed); 1676 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE, 1677 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); 1678 HeapFree(GetProcessHeap(), 0, exservices); 1679 1680 servicecountinactive = returned; 1681 1682 /* Get the number of win32 services */ 1683 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1684 NULL, 0, &needed, &returned, NULL, NULL); 1685 exservices = HeapAlloc(GetProcessHeap(), 0, needed); 1686 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, 1687 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); 1688 HeapFree(GetProcessHeap(), 0, exservices); 1689 1690 /* Check if total is the same as active and inactive win32 services */ 1691 ok(returned == (servicecountactive + servicecountinactive), 1692 "Something wrong in the calculation\n"); 1693 1694 /* Get all drivers and services */ 1695 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, 1696 SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL); 1697 ok(!ret, "Expected failure\n"); 1698 exservices = HeapAlloc(GetProcessHeap(), 0, needed); 1699 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER, 1700 SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL); 1701 ok(ret, "Expected success %u\n", GetLastError()); 1702 1703 /* Loop through all those returned drivers and services */ 1704 for (i = 0; i < returned; i++) 1705 { 1706 SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess; 1707 1708 /* lpServiceName and lpDisplayName should always be filled */ 1709 ok(exservices[i].lpServiceName[0], "Expected a service name\n"); 1710 ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n"); 1711 1712 /* Decrement the counters to see if the functions calls return the 1713 * same numbers as the contents of these structures. 1714 * Check some process id specifics. 1715 */ 1716 if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER)) 1717 { 1718 /* We shouldn't have a process id for drivers */ 1719 ok(status.dwProcessId == 0, 1720 "This driver shouldn't have an associated process id\n"); 1721 } 1722 1723 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS)) 1724 { 1725 if (status.dwCurrentState != SERVICE_STOPPED) 1726 { 1727 /* We expect a process id for every running service */ 1728 ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n", 1729 exservices[i].lpServiceName); 1730 1731 servicecountactive--; 1732 } 1733 else 1734 { 1735 /* We shouldn't have a process id for inactive services */ 1736 ok(status.dwProcessId == 0, "Service %s state %u shouldn't have an associated process id\n", 1737 exservices[i].lpServiceName, status.dwCurrentState); 1738 1739 servicecountinactive--; 1740 } 1741 } 1742 } 1743 HeapFree(GetProcessHeap(), 0, exservices); 1744 1745 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive); 1746 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive); 1747 1748 CloseServiceHandle(scm_handle); 1749 } 1750 1751 static void test_close(void) 1752 { 1753 SC_HANDLE handle; 1754 BOOL ret; 1755 1756 /* NULL handle */ 1757 SetLastError(0xdeadbeef); 1758 ret = CloseServiceHandle(NULL); 1759 ok(!ret, "Expected failure\n"); 1760 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1761 1762 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */ 1763 1764 /* Proper call */ 1765 handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); 1766 SetLastError(0xdeadbeef); 1767 ret = CloseServiceHandle(handle); 1768 ok(ret, "Expected success got error %u\n", GetLastError()); 1769 } 1770 1771 static void test_sequence(void) 1772 { 1773 SC_HANDLE scm_handle, svc_handle; 1774 BOOL ret, is_nt4; 1775 QUERY_SERVICE_CONFIGA *config; 1776 DWORD given, needed; 1777 static const CHAR servicename [] = "Winetest"; 1778 static const CHAR displayname [] = "Winetest dummy service"; 1779 static const CHAR displayname2[] = "Winetest dummy service (2)"; 1780 static const CHAR pathname [] = "we_dont_care.exe"; 1781 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0"; 1782 static const CHAR password [] = ""; 1783 static const CHAR empty [] = ""; 1784 static const CHAR localsystem [] = "LocalSystem"; 1785 1786 SetLastError(0xdeadbeef); 1787 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 1788 1789 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 1790 { 1791 skip("Not enough rights to get a handle to the manager\n"); 1792 return; 1793 } 1794 else 1795 ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError()); 1796 1797 if (!scm_handle) return; 1798 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ); 1799 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER); 1800 CloseServiceHandle(svc_handle); 1801 1802 /* Create a dummy service */ 1803 SetLastError(0xdeadbeef); 1804 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL, 1805 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE, 1806 pathname, NULL, NULL, dependencies, NULL, password); 1807 1808 if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS)) 1809 { 1810 /* We try and open the service and do the rest of the tests. Some could 1811 * fail if the tests were changed between these runs. 1812 */ 1813 trace("Deletion probably didn't work last time\n"); 1814 SetLastError(0xdeadbeef); 1815 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL); 1816 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 1817 { 1818 skip("Not enough rights to open the service\n"); 1819 CloseServiceHandle(scm_handle); 1820 return; 1821 } 1822 ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError()); 1823 } 1824 else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 1825 { 1826 skip("Not enough rights to create the service\n"); 1827 CloseServiceHandle(scm_handle); 1828 return; 1829 } 1830 else 1831 { 1832 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError()); 1833 if ((svc_handle != NULL) && (pGetSecurityInfo != NULL)) 1834 { 1835 PSID sidOwner, sidGroup; 1836 PACL dacl, sacl; 1837 PSECURITY_DESCRIPTOR pSD; 1838 DWORD error, n1, n2; 1839 HRESULT retval; 1840 BOOL bret; 1841 1842 /* Test using GetSecurityInfo to obtain security information */ 1843 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner, 1844 &sidGroup, &dacl, &sacl, &pSD); 1845 LocalFree(pSD); 1846 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); 1847 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, 1848 NULL, NULL, NULL, &pSD); 1849 LocalFree(pSD); 1850 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); 1851 if (!is_nt4) 1852 { 1853 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, 1854 NULL, &dacl, NULL, &pSD); 1855 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval); 1856 LocalFree(pSD); 1857 SetLastError(0xdeadbeef); 1858 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, 1859 NULL, NULL, NULL, NULL); 1860 error = GetLastError(); 1861 ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval); 1862 ok(error == 0xdeadbeef, "Unexpected last error %d\n", error); 1863 } 1864 else 1865 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n"); 1866 1867 /* Test using QueryServiceObjectSecurity to obtain security information */ 1868 SetLastError(0xdeadbeef); 1869 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1); 1870 error = GetLastError(); 1871 ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret); 1872 ok(error == ERROR_INSUFFICIENT_BUFFER || 1873 broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER), 1874 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error); 1875 if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024; 1876 pSD = LocalAlloc(0, n1); 1877 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2); 1878 ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret); 1879 LocalFree(pSD); 1880 } 1881 } 1882 1883 if (!svc_handle) { 1884 CloseServiceHandle(scm_handle); 1885 return; 1886 } 1887 1888 /* TODO: 1889 * Before we do a QueryServiceConfig we should check the registry. This will make sure 1890 * that the correct keys are used. 1891 */ 1892 1893 /* Request the size for the buffer */ 1894 SetLastError(0xdeadbeef); 1895 ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed); 1896 ok(!ret, "Expected failure\n"); 1897 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 1898 1899 config = HeapAlloc(GetProcessHeap(), 0, needed); 1900 given = needed; 1901 SetLastError(0xdeadbeef); 1902 ret = QueryServiceConfigA(svc_handle, config, given, &needed); 1903 ok(ret, "Expected success, got error %u\n", GetLastError()); 1904 1905 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName && 1906 config->lpDisplayName, "Expected all string struct members to be non-NULL\n"); 1907 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS), 1908 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType); 1909 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType); 1910 ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl); 1911 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName); 1912 ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup); 1913 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId); 1914 /* TODO: Show the double 0 terminated string */ 1915 todo_wine 1916 { 1917 ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n"); 1918 } 1919 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName); 1920 ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName); 1921 1922 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2", 1923 NULL, NULL, NULL, NULL, displayname2); 1924 ok(ret, "ChangeServiceConfig failed (err=%d)\n", GetLastError()); 1925 1926 QueryServiceConfigA(svc_handle, NULL, 0, &needed); 1927 config = HeapReAlloc(GetProcessHeap(), 0, config, needed); 1928 ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n"); 1929 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName && 1930 config->lpDisplayName, "Expected all string struct members to be non-NULL\n"); 1931 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS), 1932 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType); 1933 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType); 1934 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl); 1935 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName); 1936 ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup); 1937 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId); 1938 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName); 1939 ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName); 1940 1941 SetLastError(0xdeadbeef); 1942 ret = DeleteService(svc_handle); 1943 ok(ret, "Expected success, got error %u\n", GetLastError()); 1944 CloseServiceHandle(svc_handle); 1945 1946 /* Wait a while. The following test does a CreateService again */ 1947 Sleep(1000); 1948 1949 CloseServiceHandle(scm_handle); 1950 HeapFree(GetProcessHeap(), 0, config); 1951 } 1952 1953 static void test_queryconfig2(void) 1954 { 1955 SC_HANDLE scm_handle, svc_handle; 1956 BOOL ret; 1957 DWORD expected, needed; 1958 BYTE buffer[MAX_PATH]; 1959 LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer; 1960 SERVICE_PRESHUTDOWN_INFO preshutdown_info; 1961 static const CHAR servicename [] = "Winetest"; 1962 static const CHAR displayname [] = "Winetest dummy service"; 1963 static const CHAR pathname [] = "we_dont_care.exe"; 1964 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0"; 1965 static const CHAR password [] = ""; 1966 static const CHAR description [] = "Description"; 1967 1968 if(!pQueryServiceConfig2A) 1969 { 1970 win_skip("function QueryServiceConfig2A not present\n"); 1971 return; 1972 } 1973 1974 SetLastError(0xdeadbeef); 1975 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 1976 1977 if (!scm_handle) 1978 { 1979 if(GetLastError() == ERROR_ACCESS_DENIED) 1980 skip("Not enough rights to get a handle to the manager\n"); 1981 else 1982 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError()); 1983 return; 1984 } 1985 1986 /* Create a dummy service */ 1987 SetLastError(0xdeadbeef); 1988 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL, 1989 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE, 1990 pathname, NULL, NULL, dependencies, NULL, password); 1991 1992 if (!svc_handle) 1993 { 1994 if(GetLastError() == ERROR_SERVICE_EXISTS) 1995 { 1996 /* We try and open the service and do the rest of the tests. Some could 1997 * fail if the tests were changed between these runs. 1998 */ 1999 trace("Deletion probably didn't work last time\n"); 2000 SetLastError(0xdeadbeef); 2001 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL); 2002 if (!svc_handle) 2003 { 2004 if(GetLastError() == ERROR_ACCESS_DENIED) 2005 skip("Not enough rights to open the service\n"); 2006 else 2007 ok(FALSE, "Could not open the service : %d\n", GetLastError()); 2008 CloseServiceHandle(scm_handle); 2009 return; 2010 } 2011 } 2012 if (GetLastError() == ERROR_ACCESS_DENIED) 2013 { 2014 skip("Not enough rights to create the service\n"); 2015 CloseServiceHandle(scm_handle); 2016 return; 2017 } 2018 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError()); 2019 if (!svc_handle) 2020 { 2021 CloseServiceHandle(scm_handle); 2022 return; 2023 } 2024 } 2025 SetLastError(0xdeadbeef); 2026 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed); 2027 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2028 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError()); 2029 2030 SetLastError(0xdeadbeef); 2031 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL); 2032 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2033 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError()); 2034 2035 SetLastError(0xdeadbeef); 2036 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL); 2037 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2038 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError()); 2039 2040 SetLastError(0xdeadbeef); 2041 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed); 2042 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2043 ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()), 2044 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2045 2046 SetLastError(0xdeadbeef); 2047 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL); 2048 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2049 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError()); 2050 2051 needed = 0; 2052 SetLastError(0xdeadbeef); 2053 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed); 2054 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2055 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2056 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed); 2057 2058 needed = 0; 2059 pConfig->lpDescription = (LPSTR)0xdeadbeef; 2060 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed); 2061 ok(ret, "expected QueryServiceConfig2A to succeed\n"); 2062 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed); 2063 ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription); 2064 2065 SetLastError(0xdeadbeef); 2066 needed = 0; 2067 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed); 2068 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2069 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2070 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed); 2071 2072 if(!pChangeServiceConfig2A) 2073 { 2074 win_skip("function ChangeServiceConfig2A not present\n"); 2075 goto cleanup; 2076 } 2077 2078 pConfig->lpDescription = (LPSTR) description; 2079 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer); 2080 ok(ret, "ChangeServiceConfig2A failed\n"); 2081 if (!ret) { 2082 goto cleanup; 2083 } 2084 2085 SetLastError(0xdeadbeef); 2086 needed = 0; 2087 expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */ 2088 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed); 2089 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2090 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2091 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed); 2092 2093 SetLastError(0xdeadbeef); 2094 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed); 2095 ok(!ret, "expected QueryServiceConfig2A to fail\n"); 2096 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2097 2098 SetLastError(0xdeadbeef); 2099 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed); 2100 ok(ret, "expected QueryServiceConfig2A to succeed\n"); 2101 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription), 2102 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription); 2103 2104 SetLastError(0xdeadbeef); 2105 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed); 2106 ok(ret, "expected QueryServiceConfig2A to succeed\n"); 2107 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription), 2108 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription); 2109 2110 if(!pQueryServiceConfig2W) 2111 { 2112 win_skip("function QueryServiceConfig2W not present\n"); 2113 goto cleanup; 2114 } 2115 SetLastError(0xdeadbeef); 2116 needed = 0; 2117 expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description); 2118 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed); 2119 ok(!ret, "expected QueryServiceConfig2W to fail\n"); 2120 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); 2121 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed); 2122 2123 SetLastError(0xdeadbeef); 2124 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed); 2125 ok(ret, "expected QueryServiceConfig2W to succeed\n"); 2126 2127 SetLastError(0xdeadbeef); 2128 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO, 2129 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed); 2130 if(!ret && GetLastError()==ERROR_INVALID_LEVEL) 2131 { 2132 /* Win2k3 and older */ 2133 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n"); 2134 goto cleanup; 2135 } 2136 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError()); 2137 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed); 2138 ok(preshutdown_info.dwPreshutdownTimeout == 180000, "Default PreshutdownTimeout = %d\n", 2139 preshutdown_info.dwPreshutdownTimeout); 2140 2141 SetLastError(0xdeadbeef); 2142 preshutdown_info.dwPreshutdownTimeout = -1; 2143 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO, 2144 (LPVOID)&preshutdown_info); 2145 ok(ret, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError()); 2146 2147 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO, 2148 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed); 2149 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError()); 2150 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed); 2151 ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %d\n", 2152 preshutdown_info.dwPreshutdownTimeout); 2153 2154 cleanup: 2155 DeleteService(svc_handle); 2156 2157 CloseServiceHandle(svc_handle); 2158 2159 /* Wait a while. The following test does a CreateService again */ 2160 Sleep(1000); 2161 2162 CloseServiceHandle(scm_handle); 2163 } 2164 2165 static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4) 2166 { 2167 BOOL ret; 2168 DWORD le1, le2; 2169 SERVICE_STATUS status; 2170 2171 #ifdef __REACTOS__ 2172 fprintf(stdout, "ROSTESTS-56: Hello sysreg, I am awake\n"); 2173 #endif 2174 ret = StartServiceA(svc_handle, 0, NULL); 2175 le1 = GetLastError(); 2176 ok(!ret, "%s: StartServiceA() should have failed\n", name); 2177 2178 if (pQueryServiceStatusEx) 2179 { 2180 DWORD needed; 2181 SERVICE_STATUS_PROCESS statusproc; 2182 2183 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed); 2184 ok(ret, "%s: QueryServiceStatusEx() failed le=%u\n", name, GetLastError()); 2185 ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%x\n", name, statusproc.dwCurrentState); 2186 ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %x\n", name, statusproc.dwProcessId); 2187 } 2188 2189 ret = StartServiceA(svc_handle, 0, NULL); 2190 le2 = GetLastError(); 2191 ok(!ret, "%s: StartServiceA() should have failed\n", name); 2192 ok(le2 == le1, "%s: the second try should yield the same error: %u != %u\n", name, le1, le2); 2193 2194 status.dwCurrentState = 0xdeadbeef; 2195 ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status); 2196 le2 = GetLastError(); 2197 ok(!ret, "%s: ControlService() should have failed\n", name); 2198 ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name, le2); 2199 ok(status.dwCurrentState == SERVICE_STOPPED || 2200 broken(is_nt4), /* NT4 returns a random value */ 2201 "%s: should be stopped state=%x\n", name, status.dwCurrentState); 2202 2203 return le1; 2204 } 2205 2206 struct notify_data { 2207 SERVICE_NOTIFYW notify; 2208 SC_HANDLE svc; 2209 }; 2210 2211 static void CALLBACK cb_stopped(void *user) 2212 { 2213 struct notify_data *data = user; 2214 BOOL br; 2215 2216 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS, 2217 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus); 2218 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED, 2219 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState); 2220 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED, 2221 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered); 2222 2223 br = StartServiceA(data->svc, 0, NULL); 2224 ok(br, "StartService failed: %u\n", GetLastError()); 2225 } 2226 2227 static void CALLBACK cb_running(void *user) 2228 { 2229 struct notify_data *data = user; 2230 BOOL br; 2231 SERVICE_STATUS status; 2232 2233 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS, 2234 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus); 2235 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING, 2236 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState); 2237 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING, 2238 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered); 2239 2240 br = ControlService(data->svc, SERVICE_CONTROL_STOP, &status); 2241 ok(br, "ControlService failed: %u\n", GetLastError()); 2242 } 2243 2244 static void test_servicenotify(SC_HANDLE svc) 2245 { 2246 DWORD dr; 2247 struct notify_data data; 2248 2249 if(!pNotifyServiceStatusChangeW){ 2250 win_skip("No NotifyServiceStatusChangeW\n"); 2251 return; 2252 } 2253 2254 memset(&data.notify, 0, sizeof(data.notify)); 2255 data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; 2256 data.notify.pfnNotifyCallback = &cb_stopped; 2257 data.notify.pContext = &data; 2258 data.svc = svc; 2259 2260 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify); 2261 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr); 2262 2263 dr = SleepEx(100, TRUE); 2264 ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n"); 2265 2266 data.notify.pfnNotifyCallback = &cb_running; 2267 2268 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify); 2269 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr); 2270 2271 dr = SleepEx(100, TRUE); 2272 ok(dr == WAIT_IO_COMPLETION, "APC wasn't called\n"); 2273 } 2274 2275 static void test_start_stop(void) 2276 { 2277 BOOL ret; 2278 SC_HANDLE scm_handle, svc_handle; 2279 DWORD le, is_nt4; 2280 static const char servicename[] = "Winetest"; 2281 char cmd[MAX_PATH+20]; 2282 const char* displayname; 2283 2284 SetLastError(0xdeadbeef); 2285 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 2286 if (!scm_handle) 2287 { 2288 if(GetLastError() == ERROR_ACCESS_DENIED) 2289 skip("Not enough rights to get a handle to the manager\n"); 2290 else 2291 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError()); 2292 return; 2293 } 2294 2295 /* Detect NT4 */ 2296 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ); 2297 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER); 2298 2299 /* Do some cleanup in case a previous run crashed */ 2300 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL); 2301 if (svc_handle) 2302 { 2303 DeleteService(svc_handle); 2304 CloseServiceHandle(svc_handle); 2305 } 2306 2307 /* Create a dummy disabled service */ 2308 sprintf(cmd, "\"%s\" service exit", selfname); 2309 displayname = "Winetest Disabled Service"; 2310 svc_handle = CreateServiceA(scm_handle, servicename, displayname, 2311 GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, 2312 SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL, 2313 NULL, NULL, NULL, NULL); 2314 if (!svc_handle) 2315 { 2316 if(GetLastError() == ERROR_ACCESS_DENIED) 2317 skip("Not enough rights to create the service\n"); 2318 else 2319 ok(FALSE, "Could not create the service: %d\n", GetLastError()); 2320 goto cleanup; 2321 } 2322 le = try_start_stop(svc_handle, displayname, is_nt4); 2323 ok(le == ERROR_SERVICE_DISABLED, "%d != ERROR_SERVICE_DISABLED\n", le); 2324 2325 /* Then one with a bad path */ 2326 displayname = "Winetest Bad Path"; 2327 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname); 2328 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError()); 2329 try_start_stop(svc_handle, displayname, is_nt4); 2330 2331 if (is_nt4) 2332 { 2333 /* NT4 does not detect when a service fails to start and uses an 2334 * insanely long timeout: 120s. So skip the rest of the tests. 2335 */ 2336 win_skip("Skip some service start/stop tests on NT4\n"); 2337 goto cleanup; 2338 } 2339 2340 if (!winetest_interactive) 2341 { 2342 skip("ROSTESTS-151: Skipping service start timeout tests because they take too long. This is not a bug!\n"); 2343 goto cleanup; 2344 } 2345 2346 /* Again with a process that exits right away */ 2347 displayname = "Winetest Exit Service"; 2348 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname); 2349 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError()); 2350 le = try_start_stop(svc_handle, displayname, is_nt4); 2351 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le); 2352 2353 /* create a real service and test notifications */ 2354 sprintf(cmd, "%s service serve", selfname); 2355 displayname = "Winetest Service"; 2356 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname); 2357 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError()); 2358 test_servicenotify(svc_handle); 2359 2360 cleanup: 2361 if (svc_handle) 2362 { 2363 DeleteService(svc_handle); 2364 CloseServiceHandle(svc_handle); 2365 } 2366 2367 /* Wait a while. The following test does a CreateService again */ 2368 Sleep(1000); 2369 2370 CloseServiceHandle(scm_handle); 2371 } 2372 2373 static void test_refcount(void) 2374 { 2375 SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5; 2376 static const CHAR servicename [] = "Winetest"; 2377 static const CHAR pathname [] = "we_dont_care.exe"; 2378 BOOL ret; 2379 2380 /* Get a handle to the Service Control Manager */ 2381 SetLastError(0xdeadbeef); 2382 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 2383 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED)) 2384 { 2385 skip("Not enough rights to get a handle to the manager\n"); 2386 return; 2387 } 2388 2389 /* Create a service */ 2390 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, 2391 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 2392 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 2393 ok(svc_handle1 != NULL, "Expected success, got error %u\n", GetLastError()); 2394 2395 /* Get a handle to this new service */ 2396 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ); 2397 ok(svc_handle2 != NULL, "Expected success, got error %u\n", GetLastError()); 2398 2399 /* Get another handle to this new service */ 2400 svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ); 2401 ok(svc_handle3 != NULL, "Expected success, got error %u\n", GetLastError()); 2402 2403 /* Check if we can close the handle to the Service Control Manager */ 2404 ret = CloseServiceHandle(scm_handle); 2405 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2406 2407 /* Get a new handle to the Service Control Manager */ 2408 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 2409 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError()); 2410 2411 /* Get a handle to this new service */ 2412 svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL); 2413 ok(svc_handle4 != NULL, "Expected success, got error %u\n", GetLastError()); 2414 2415 /* Delete the service */ 2416 ret = DeleteService(svc_handle4); 2417 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2418 2419 /* We cannot create the same service again as it's still marked as 'being deleted'. 2420 * The reason is that we still have 4 open handles to this service even though we 2421 * closed the handle to the Service Control Manager in between. 2422 */ 2423 SetLastError(0xdeadbeef); 2424 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, 2425 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 2426 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 2427 ok(!svc_handle5, "Expected failure\n"); 2428 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE, 2429 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError()); 2430 2431 /* Close all the handles to the service and try again */ 2432 ret = CloseServiceHandle(svc_handle4); 2433 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2434 ret = CloseServiceHandle(svc_handle3); 2435 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2436 ret = CloseServiceHandle(svc_handle2); 2437 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2438 ret = CloseServiceHandle(svc_handle1); 2439 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2440 2441 /* Wait a while. Doing a CreateService too soon will result again 2442 * in an ERROR_SERVICE_MARKED_FOR_DELETE error. 2443 */ 2444 Sleep(1000); 2445 2446 /* We succeed now as all handles are closed (tested this also with a long SLeep() */ 2447 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, 2448 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, 2449 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); 2450 ok(svc_handle5 != NULL, "Expected success, got error %u\n", GetLastError()); 2451 2452 /* Delete the service */ 2453 ret = DeleteService(svc_handle5); 2454 ok(ret, "Expected success (err=%d)\n", GetLastError()); 2455 2456 /* Wait a while. Just in case one of the following tests does a CreateService again */ 2457 Sleep(1000); 2458 2459 CloseServiceHandle(svc_handle5); 2460 CloseServiceHandle(scm_handle); 2461 } 2462 2463 static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user) 2464 { 2465 HANDLE evt = user; 2466 2467 switch(ctl){ 2468 case SERVICE_CONTROL_STOP: 2469 SetEvent(evt); 2470 break; 2471 case SERVICE_CONTROL_INTERROGATE: 2472 return NO_ERROR; 2473 } 2474 2475 return ERROR_CALL_NOT_IMPLEMENTED; 2476 } 2477 2478 static void WINAPI service_main(DWORD argc, char **argv) 2479 { 2480 SERVICE_STATUS_HANDLE st_handle; 2481 SERVICE_STATUS st; 2482 HANDLE evt = CreateEventW(0, FALSE, FALSE, 0); 2483 2484 st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt); 2485 2486 st.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 2487 st.dwServiceSpecificExitCode = 0; 2488 st.dwCurrentState = SERVICE_RUNNING; 2489 st.dwWin32ExitCode = NO_ERROR; 2490 st.dwWaitHint = 0; 2491 st.dwControlsAccepted = SERVICE_ACCEPT_STOP; 2492 st.dwCheckPoint = 0; 2493 2494 SetServiceStatus(st_handle, &st); 2495 2496 WaitForSingleObject(evt, 5000); 2497 2498 st.dwCurrentState = SERVICE_STOPPED; 2499 2500 SetServiceStatus(st_handle, &st); 2501 } 2502 2503 static void run_service(void) 2504 { 2505 char empty[] = {0}; 2506 SERVICE_TABLE_ENTRYA table[] = { 2507 {empty, &service_main }, 2508 {0, 0} 2509 }; 2510 2511 StartServiceCtrlDispatcherA(table); 2512 } 2513 2514 START_TEST(service) 2515 { 2516 SC_HANDLE scm_handle; 2517 int myARGC; 2518 char** myARGV; 2519 2520 myARGC = winetest_get_mainargs(&myARGV); 2521 GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL); 2522 if (myARGC >= 3) 2523 { 2524 if (strcmp(myARGV[2], "serve") == 0) 2525 run_service(); 2526 return; 2527 } 2528 2529 /* Bail out if we are on win98 */ 2530 SetLastError(0xdeadbeef); 2531 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL); 2532 2533 if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) 2534 { 2535 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n"); 2536 return; 2537 } 2538 CloseServiceHandle(scm_handle); 2539 2540 init_function_pointers(); 2541 2542 /* First some parameter checking */ 2543 test_open_scm(); 2544 test_open_svc(); 2545 test_create_delete_svc(); 2546 test_get_displayname(); 2547 test_get_servicekeyname(); 2548 test_query_svc(); 2549 test_enum_svc(); 2550 test_close(); 2551 /* Test the creation, querying and deletion of a service */ 2552 test_sequence(); 2553 test_queryconfig2(); 2554 test_start_stop(); 2555 /* The main reason for this test is to check if any refcounting is used 2556 * and what the rules are 2557 */ 2558 test_refcount(); 2559 } 2560