1 /* 2 * PROJECT: ReactOS Service Control Manager 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/services/rpcserver.c 5 * PURPOSE: RPC server interface for the advapi32 calls 6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl 7 * Copyright 2006-2007 Herv� Poussineau <hpoussin@reactos.org> 8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org> 9 */ 10 11 /* INCLUDES ****************************************************************/ 12 13 #include "services.h" 14 15 #include <winnls.h> 16 #include <strsafe.h> 17 18 #define NDEBUG 19 #include <debug.h> 20 21 /* GLOBALS *****************************************************************/ 22 23 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */ 24 #define SERVICE_TAG 0x63765368 /* 'hSvc' */ 25 #define INVALID_TAG 0xAABBCCDD 26 27 typedef struct _SCMGR_HANDLE 28 { 29 DWORD Tag; 30 DWORD DesiredAccess; 31 } SCMGR_HANDLE; 32 33 34 typedef struct _MANAGER_HANDLE 35 { 36 SCMGR_HANDLE Handle; 37 WCHAR DatabaseName[1]; 38 } MANAGER_HANDLE, *PMANAGER_HANDLE; 39 40 41 typedef struct _SERVICE_HANDLE 42 { 43 SCMGR_HANDLE Handle; 44 PSERVICE ServiceEntry; 45 } SERVICE_HANDLE, *PSERVICE_HANDLE; 46 47 48 #define SC_MANAGER_READ \ 49 (STANDARD_RIGHTS_READ | \ 50 SC_MANAGER_QUERY_LOCK_STATUS | \ 51 SC_MANAGER_ENUMERATE_SERVICE) 52 53 #define SC_MANAGER_WRITE \ 54 (STANDARD_RIGHTS_WRITE | \ 55 SC_MANAGER_MODIFY_BOOT_CONFIG | \ 56 SC_MANAGER_CREATE_SERVICE) 57 58 #define SC_MANAGER_EXECUTE \ 59 (STANDARD_RIGHTS_EXECUTE | \ 60 SC_MANAGER_LOCK | \ 61 SC_MANAGER_ENUMERATE_SERVICE | \ 62 SC_MANAGER_CONNECT | \ 63 SC_MANAGER_CREATE_SERVICE) 64 65 66 #define SERVICE_READ \ 67 (STANDARD_RIGHTS_READ | \ 68 SERVICE_INTERROGATE | \ 69 SERVICE_ENUMERATE_DEPENDENTS | \ 70 SERVICE_QUERY_STATUS | \ 71 SERVICE_QUERY_CONFIG) 72 73 #define SERVICE_WRITE \ 74 (STANDARD_RIGHTS_WRITE | \ 75 SERVICE_CHANGE_CONFIG) 76 77 #define SERVICE_EXECUTE \ 78 (STANDARD_RIGHTS_EXECUTE | \ 79 SERVICE_USER_DEFINED_CONTROL | \ 80 SERVICE_PAUSE_CONTINUE | \ 81 SERVICE_STOP | \ 82 SERVICE_START) 83 84 #define TAG_ARRAY_SIZE 32 85 86 /* VARIABLES ***************************************************************/ 87 88 static GENERIC_MAPPING 89 ScmManagerMapping = {SC_MANAGER_READ, 90 SC_MANAGER_WRITE, 91 SC_MANAGER_EXECUTE, 92 SC_MANAGER_ALL_ACCESS}; 93 94 static GENERIC_MAPPING 95 ScmServiceMapping = {SERVICE_READ, 96 SERVICE_WRITE, 97 SERVICE_EXECUTE, 98 SERVICE_ALL_ACCESS}; 99 100 101 /* FUNCTIONS ***************************************************************/ 102 103 VOID 104 ScmStartRpcServer(VOID) 105 { 106 RPC_STATUS Status; 107 108 DPRINT("ScmStartRpcServer() called\n"); 109 110 Status = RpcServerUseProtseqEpW(L"ncacn_np", 111 10, 112 L"\\pipe\\ntsvcs", 113 NULL); 114 if (Status != RPC_S_OK) 115 { 116 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 117 return; 118 } 119 120 Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec, 121 NULL, 122 NULL); 123 if (Status != RPC_S_OK) 124 { 125 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); 126 return; 127 } 128 129 Status = RpcServerListen(1, 20, TRUE); 130 if (Status != RPC_S_OK) 131 { 132 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); 133 return; 134 } 135 136 DPRINT("ScmStartRpcServer() done\n"); 137 } 138 139 140 static DWORD 141 ScmCreateManagerHandle(LPWSTR lpDatabaseName, 142 SC_HANDLE *Handle) 143 { 144 PMANAGER_HANDLE Ptr; 145 146 if (lpDatabaseName == NULL) 147 lpDatabaseName = SERVICES_ACTIVE_DATABASEW; 148 149 if (_wcsicmp(lpDatabaseName, SERVICES_FAILED_DATABASEW) == 0) 150 { 151 DPRINT("Database %S, does not exist\n", lpDatabaseName); 152 return ERROR_DATABASE_DOES_NOT_EXIST; 153 } 154 else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0) 155 { 156 DPRINT("Invalid Database name %S.\n", lpDatabaseName); 157 return ERROR_INVALID_NAME; 158 } 159 160 Ptr = HeapAlloc(GetProcessHeap(), 161 HEAP_ZERO_MEMORY, 162 FIELD_OFFSET(MANAGER_HANDLE, DatabaseName[wcslen(lpDatabaseName) + 1])); 163 if (Ptr == NULL) 164 return ERROR_NOT_ENOUGH_MEMORY; 165 166 Ptr->Handle.Tag = MANAGER_TAG; 167 168 wcscpy(Ptr->DatabaseName, lpDatabaseName); 169 170 *Handle = (SC_HANDLE)Ptr; 171 172 return ERROR_SUCCESS; 173 } 174 175 176 static DWORD 177 ScmCreateServiceHandle(PSERVICE lpServiceEntry, 178 SC_HANDLE *Handle) 179 { 180 PSERVICE_HANDLE Ptr; 181 182 Ptr = HeapAlloc(GetProcessHeap(), 183 HEAP_ZERO_MEMORY, 184 sizeof(SERVICE_HANDLE)); 185 if (Ptr == NULL) 186 return ERROR_NOT_ENOUGH_MEMORY; 187 188 Ptr->Handle.Tag = SERVICE_TAG; 189 190 Ptr->ServiceEntry = lpServiceEntry; 191 192 *Handle = (SC_HANDLE)Ptr; 193 194 return ERROR_SUCCESS; 195 } 196 197 198 static PMANAGER_HANDLE 199 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle) 200 { 201 PMANAGER_HANDLE pManager = NULL; 202 203 _SEH2_TRY 204 { 205 if (((PMANAGER_HANDLE)Handle)->Handle.Tag == MANAGER_TAG) 206 pManager = (PMANAGER_HANDLE)Handle; 207 } 208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 209 { 210 DPRINT1("Exception: Invalid Service Manager handle!\n"); 211 } 212 _SEH2_END; 213 214 return pManager; 215 } 216 217 218 static PSERVICE_HANDLE 219 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle) 220 { 221 PSERVICE_HANDLE pService = NULL; 222 223 _SEH2_TRY 224 { 225 if (((PSERVICE_HANDLE)Handle)->Handle.Tag == SERVICE_TAG) 226 pService = (PSERVICE_HANDLE)Handle; 227 } 228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 229 { 230 DPRINT1("Exception: Invalid Service handle!\n"); 231 } 232 _SEH2_END; 233 234 return pService; 235 } 236 237 238 static DWORD 239 ScmCheckAccess(SC_HANDLE Handle, 240 DWORD dwDesiredAccess) 241 { 242 PMANAGER_HANDLE hMgr; 243 244 hMgr = (PMANAGER_HANDLE)Handle; 245 if (hMgr->Handle.Tag == MANAGER_TAG) 246 { 247 RtlMapGenericMask(&dwDesiredAccess, 248 &ScmManagerMapping); 249 250 hMgr->Handle.DesiredAccess = dwDesiredAccess; 251 252 return ERROR_SUCCESS; 253 } 254 else if (hMgr->Handle.Tag == SERVICE_TAG) 255 { 256 RtlMapGenericMask(&dwDesiredAccess, 257 &ScmServiceMapping); 258 259 hMgr->Handle.DesiredAccess = dwDesiredAccess; 260 261 return ERROR_SUCCESS; 262 } 263 264 return ERROR_INVALID_HANDLE; 265 } 266 267 268 DWORD 269 ScmAssignNewTag(PSERVICE lpService) 270 { 271 HKEY hKey = NULL; 272 DWORD dwError; 273 DWORD dwGroupTagCount = 0; 274 PDWORD pdwGroupTags = NULL; 275 DWORD dwFreeTag = 0; 276 DWORD dwTagUsedBase = 1; 277 BOOLEAN TagUsed[TAG_ARRAY_SIZE]; 278 INT nTagOffset; 279 DWORD i; 280 DWORD cbDataSize; 281 PLIST_ENTRY ServiceEntry; 282 PSERVICE CurrentService; 283 284 ASSERT(lpService != NULL); 285 ASSERT(lpService->lpGroup != NULL); 286 287 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 288 L"System\\CurrentControlSet\\Control\\GroupOrderList", 289 0, 290 KEY_READ, 291 &hKey); 292 293 if (dwError != ERROR_SUCCESS) 294 goto findFreeTag; 295 296 /* query value length */ 297 cbDataSize = 0; 298 dwError = RegQueryValueExW(hKey, 299 lpService->lpGroup->szGroupName, 300 NULL, 301 NULL, 302 NULL, 303 &cbDataSize); 304 305 if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA) 306 goto findFreeTag; 307 308 pdwGroupTags = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDataSize); 309 if (!pdwGroupTags) 310 { 311 dwError = ERROR_NOT_ENOUGH_MEMORY; 312 goto cleanup; 313 } 314 315 dwError = RegQueryValueExW(hKey, 316 lpService->lpGroup->szGroupName, 317 NULL, 318 NULL, 319 (LPBYTE)pdwGroupTags, 320 &cbDataSize); 321 322 if (dwError != ERROR_SUCCESS) 323 goto findFreeTag; 324 325 if (cbDataSize < sizeof(pdwGroupTags[0])) 326 goto findFreeTag; 327 328 dwGroupTagCount = min(pdwGroupTags[0], cbDataSize / sizeof(pdwGroupTags[0]) - 1); 329 330 findFreeTag: 331 do 332 { 333 /* mark all tags as unused */ 334 for (i = 0; i < TAG_ARRAY_SIZE; i++) 335 TagUsed[i] = FALSE; 336 337 /* mark tags in GroupOrderList as used */ 338 for (i = 1; i <= dwGroupTagCount; i++) 339 { 340 nTagOffset = pdwGroupTags[i] - dwTagUsedBase; 341 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE) 342 TagUsed[nTagOffset] = TRUE; 343 } 344 345 /* mark tags in service list as used */ 346 ServiceEntry = lpService->ServiceListEntry.Flink; 347 while (ServiceEntry != &lpService->ServiceListEntry) 348 { 349 ASSERT(ServiceEntry != NULL); 350 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); 351 if (CurrentService->lpGroup == lpService->lpGroup) 352 { 353 nTagOffset = CurrentService->dwTag - dwTagUsedBase; 354 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE) 355 TagUsed[nTagOffset] = TRUE; 356 } 357 358 ServiceEntry = ServiceEntry->Flink; 359 } 360 361 /* find unused tag, if any */ 362 for (i = 0; i < TAG_ARRAY_SIZE; i++) 363 { 364 if (!TagUsed[i]) 365 { 366 dwFreeTag = dwTagUsedBase + i; 367 break; 368 } 369 } 370 371 dwTagUsedBase += TAG_ARRAY_SIZE; 372 } while (!dwFreeTag); 373 374 cleanup: 375 if (pdwGroupTags) 376 HeapFree(GetProcessHeap(), 0, pdwGroupTags); 377 378 if (hKey) 379 RegCloseKey(hKey); 380 381 if (dwFreeTag) 382 { 383 lpService->dwTag = dwFreeTag; 384 DPRINT("Assigning new tag %lu to service %S in group %S\n", 385 lpService->dwTag, lpService->lpServiceName, lpService->lpGroup->szGroupName); 386 dwError = ERROR_SUCCESS; 387 } 388 else 389 { 390 DPRINT1("Failed to assign new tag to service %S, error=%lu\n", 391 lpService->lpServiceName, dwError); 392 } 393 394 return dwError; 395 } 396 397 398 /* Create a path suitable for the bootloader out of the full path */ 399 DWORD 400 ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName) 401 { 402 SIZE_T ServiceNameLen, ExpandedLen; 403 DWORD BufferSize; 404 WCHAR Dest; 405 WCHAR *Expanded; 406 UNICODE_STRING NtPathName, SystemRoot, LinkTarget; 407 OBJECT_ATTRIBUTES ObjectAttributes; 408 NTSTATUS Status; 409 HANDLE SymbolicLinkHandle; 410 411 DPRINT("ScmConvertToBootPathName %S\n", CanonName); 412 413 if (!RelativeName) 414 return ERROR_INVALID_PARAMETER; 415 416 *RelativeName = NULL; 417 418 ServiceNameLen = wcslen(CanonName); 419 420 /* First check, if it's already good */ 421 if (ServiceNameLen > 12 && 422 !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12)) 423 { 424 *RelativeName = HeapAlloc(GetProcessHeap(), 425 HEAP_ZERO_MEMORY, 426 (ServiceNameLen + 1) * sizeof(WCHAR)); 427 if (*RelativeName == NULL) 428 { 429 DPRINT("Error allocating memory for boot driver name!\n"); 430 return ERROR_NOT_ENOUGH_MEMORY; 431 } 432 433 /* Copy it */ 434 wcscpy(*RelativeName, CanonName); 435 436 DPRINT("Bootdriver name %S\n", *RelativeName); 437 return ERROR_SUCCESS; 438 } 439 440 /* If it has %SystemRoot% prefix, substitute it to \System*/ 441 if (ServiceNameLen > 13 && 442 !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13)) 443 { 444 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */ 445 *RelativeName = HeapAlloc(GetProcessHeap(), 446 HEAP_ZERO_MEMORY, 447 ServiceNameLen * sizeof(WCHAR)); 448 449 if (*RelativeName == NULL) 450 { 451 DPRINT("Error allocating memory for boot driver name!\n"); 452 return ERROR_NOT_ENOUGH_MEMORY; 453 } 454 455 /* Copy it */ 456 wcscpy(*RelativeName, L"\\SystemRoot\\"); 457 wcscat(*RelativeName, CanonName + 13); 458 459 DPRINT("Bootdriver name %S\n", *RelativeName); 460 return ERROR_SUCCESS; 461 } 462 463 /* Get buffer size needed for expanding env strings */ 464 BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1); 465 466 if (BufferSize <= 1) 467 { 468 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n"); 469 return ERROR_INVALID_ENVIRONMENT; 470 } 471 472 /* Allocate memory, since the size is known now */ 473 Expanded = HeapAlloc(GetProcessHeap(), 474 HEAP_ZERO_MEMORY, 475 (BufferSize + 1) * sizeof(WCHAR)); 476 if (!Expanded) 477 { 478 DPRINT("Error allocating memory for boot driver name!\n"); 479 return ERROR_NOT_ENOUGH_MEMORY; 480 } 481 482 /* Expand it */ 483 if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) > 484 BufferSize) 485 { 486 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n"); 487 HeapFree(GetProcessHeap(), 0, Expanded); 488 return ERROR_NOT_ENOUGH_MEMORY; 489 } 490 491 /* Convert to NT-style path */ 492 if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL)) 493 { 494 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n"); 495 return ERROR_INVALID_ENVIRONMENT; 496 } 497 498 DPRINT("Converted to NT-style %wZ\n", &NtPathName); 499 500 /* No need to keep the dos-path anymore */ 501 HeapFree(GetProcessHeap(), 0, Expanded); 502 503 /* Copy it to the allocated place */ 504 Expanded = HeapAlloc(GetProcessHeap(), 505 HEAP_ZERO_MEMORY, 506 NtPathName.Length + sizeof(UNICODE_NULL)); 507 if (!Expanded) 508 { 509 DPRINT("Error allocating memory for boot driver name!\n"); 510 RtlFreeUnicodeString(&NtPathName); 511 return ERROR_NOT_ENOUGH_MEMORY; 512 } 513 514 ExpandedLen = NtPathName.Length / sizeof(WCHAR); 515 wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen); 516 Expanded[ExpandedLen] = UNICODE_NULL; 517 RtlFreeUnicodeString(&NtPathName); 518 519 if (ServiceNameLen > ExpandedLen && 520 !_wcsnicmp(Expanded, CanonName, ExpandedLen)) 521 { 522 HeapFree(GetProcessHeap(), 0, Expanded); 523 524 /* Only \SystemRoot\ is missing */ 525 *RelativeName = HeapAlloc(GetProcessHeap(), 526 HEAP_ZERO_MEMORY, 527 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR)); 528 if (*RelativeName == NULL) 529 { 530 DPRINT("Error allocating memory for boot driver name!\n"); 531 return ERROR_NOT_ENOUGH_MEMORY; 532 } 533 534 wcscpy(*RelativeName, L"\\SystemRoot\\"); 535 wcscat(*RelativeName, CanonName + ExpandedLen); 536 537 return ERROR_SUCCESS; 538 } 539 540 /* No longer need this */ 541 HeapFree(GetProcessHeap(), 0, Expanded); 542 543 /* The most complex case starts here */ 544 RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot"); 545 InitializeObjectAttributes(&ObjectAttributes, 546 &SystemRoot, 547 OBJ_CASE_INSENSITIVE, 548 NULL, 549 NULL); 550 551 /* Open this symlink */ 552 Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); 553 if (NT_SUCCESS(Status)) 554 { 555 DPRINT("Opened symbolic link object\n"); 556 557 RtlInitEmptyUnicodeString(&LinkTarget, NULL, 0); 558 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize); 559 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) 560 { 561 /* Check if required buffer size is sane */ 562 if (BufferSize > UNICODE_STRING_MAX_BYTES - sizeof(UNICODE_NULL)) 563 { 564 DPRINT("Too large buffer required\n"); 565 566 NtClose(SymbolicLinkHandle); 567 return ERROR_NOT_ENOUGH_MEMORY; 568 } 569 570 /* Alloc the string */ 571 LinkTarget.Length = (USHORT)BufferSize; 572 LinkTarget.MaximumLength = LinkTarget.Length + sizeof(UNICODE_NULL); 573 LinkTarget.Buffer = HeapAlloc(GetProcessHeap(), 574 HEAP_ZERO_MEMORY, 575 LinkTarget.MaximumLength); 576 if (!LinkTarget.Buffer) 577 { 578 DPRINT("Unable to alloc buffer\n"); 579 NtClose(SymbolicLinkHandle); 580 return ERROR_NOT_ENOUGH_MEMORY; 581 } 582 583 /* Do a real query now */ 584 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize); 585 NtClose(SymbolicLinkHandle); 586 if (NT_SUCCESS(Status)) 587 { 588 DPRINT("LinkTarget: %wZ\n", &LinkTarget); 589 590 ExpandedLen = LinkTarget.Length / sizeof(WCHAR); 591 if ((ServiceNameLen > ExpandedLen) && 592 !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen)) 593 { 594 *RelativeName = HeapAlloc(GetProcessHeap(), 595 HEAP_ZERO_MEMORY, 596 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR)); 597 598 if (*RelativeName == NULL) 599 { 600 DPRINT("Unable to alloc buffer\n"); 601 return ERROR_NOT_ENOUGH_MEMORY; 602 } 603 604 /* Copy it over, substituting the first part 605 with SystemRoot */ 606 wcscpy(*RelativeName, L"\\SystemRoot\\"); 607 wcscat(*RelativeName, CanonName+ExpandedLen+1); 608 609 /* Return success */ 610 return ERROR_SUCCESS; 611 } 612 else 613 { 614 return ERROR_INVALID_PARAMETER; 615 } 616 } 617 else 618 { 619 DPRINT("Error, Status = %08X\n", Status); 620 return ERROR_INVALID_PARAMETER; 621 } 622 } 623 else 624 { 625 DPRINT("Error, Status = %08X\n", Status); 626 NtClose(SymbolicLinkHandle); 627 return ERROR_INVALID_PARAMETER; 628 } 629 } 630 else 631 { 632 /* Failure */ 633 DPRINT("Error, Status = %08X\n", Status); 634 return ERROR_INVALID_PARAMETER; 635 } 636 } 637 638 639 DWORD 640 ScmCanonDriverImagePath(DWORD dwStartType, 641 const wchar_t *lpServiceName, 642 wchar_t **lpCanonName) 643 { 644 DWORD Result; 645 SIZE_T ServiceNameLen; 646 UNICODE_STRING NtServiceName; 647 WCHAR *RelativeName; 648 const WCHAR *SourceName = lpServiceName; 649 650 /* Calculate the length of the service's name */ 651 ServiceNameLen = wcslen(lpServiceName); 652 653 /* 12 is wcslen(L"\\SystemRoot\\") */ 654 if (ServiceNameLen > 12 && 655 !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12)) 656 { 657 /* SystemRoot prefix is already included */ 658 *lpCanonName = HeapAlloc(GetProcessHeap(), 659 HEAP_ZERO_MEMORY, 660 (ServiceNameLen + 1) * sizeof(WCHAR)); 661 662 if (*lpCanonName == NULL) 663 { 664 DPRINT("Error allocating memory for canonized service name!\n"); 665 return ERROR_NOT_ENOUGH_MEMORY; 666 } 667 668 /* If it's a boot-time driver, it must be systemroot relative */ 669 if (dwStartType == SERVICE_BOOT_START) 670 SourceName += 12; 671 672 /* Copy it */ 673 wcscpy(*lpCanonName, SourceName); 674 675 DPRINT("Canonicalized name %S\n", *lpCanonName); 676 return NO_ERROR; 677 } 678 679 /* Check if it has %SystemRoot% (len=13) */ 680 if (ServiceNameLen > 13 && 681 !_wcsnicmp(L"%SystemRoot%\\", lpServiceName, 13)) 682 { 683 /* Substitute %SystemRoot% with \\SystemRoot\\ */ 684 *lpCanonName = HeapAlloc(GetProcessHeap(), 685 HEAP_ZERO_MEMORY, 686 (ServiceNameLen + 1) * sizeof(WCHAR)); 687 688 if (*lpCanonName == NULL) 689 { 690 DPRINT("Error allocating memory for canonized service name!\n"); 691 return ERROR_NOT_ENOUGH_MEMORY; 692 } 693 694 /* If it's a boot-time driver, it must be systemroot relative */ 695 if (dwStartType == SERVICE_BOOT_START) 696 wcscpy(*lpCanonName, L"\\SystemRoot\\"); 697 698 wcscat(*lpCanonName, lpServiceName + 13); 699 700 DPRINT("Canonicalized name %S\n", *lpCanonName); 701 return NO_ERROR; 702 } 703 704 /* Check if it's a relative path name */ 705 if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':') 706 { 707 *lpCanonName = HeapAlloc(GetProcessHeap(), 708 HEAP_ZERO_MEMORY, 709 (ServiceNameLen + 1) * sizeof(WCHAR)); 710 711 if (*lpCanonName == NULL) 712 { 713 DPRINT("Error allocating memory for canonized service name!\n"); 714 return ERROR_NOT_ENOUGH_MEMORY; 715 } 716 717 /* Just copy it over without changing */ 718 wcscpy(*lpCanonName, lpServiceName); 719 720 return NO_ERROR; 721 } 722 723 /* It seems to be a DOS path, convert it */ 724 if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL)) 725 { 726 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n"); 727 return ERROR_INVALID_PARAMETER; 728 } 729 730 *lpCanonName = HeapAlloc(GetProcessHeap(), 731 HEAP_ZERO_MEMORY, 732 NtServiceName.Length + sizeof(WCHAR)); 733 734 if (*lpCanonName == NULL) 735 { 736 DPRINT("Error allocating memory for canonized service name!\n"); 737 RtlFreeUnicodeString(&NtServiceName); 738 return ERROR_NOT_ENOUGH_MEMORY; 739 } 740 741 /* Copy the string */ 742 wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR)); 743 744 /* The unicode string is not needed anymore */ 745 RtlFreeUnicodeString(&NtServiceName); 746 747 if (dwStartType != SERVICE_BOOT_START) 748 { 749 DPRINT("Canonicalized name %S\n", *lpCanonName); 750 return NO_ERROR; 751 } 752 753 /* The service is boot-started, so must be relative */ 754 Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName); 755 if (Result) 756 { 757 /* There is a problem, free name and return */ 758 HeapFree(GetProcessHeap(), 0, *lpCanonName); 759 DPRINT("Error converting named!\n"); 760 return Result; 761 } 762 763 ASSERT(RelativeName); 764 765 /* Copy that string */ 766 wcscpy(*lpCanonName, RelativeName + 12); 767 768 /* Free the allocated buffer */ 769 HeapFree(GetProcessHeap(), 0, RelativeName); 770 771 DPRINT("Canonicalized name %S\n", *lpCanonName); 772 773 /* Success */ 774 return NO_ERROR; 775 } 776 777 778 /* Internal recursive function */ 779 /* Need to search for every dependency on every service */ 780 static DWORD 781 Int_EnumDependentServicesW(HKEY hServicesKey, 782 PSERVICE lpService, 783 DWORD dwServiceState, 784 PSERVICE *lpServices, 785 LPDWORD pcbBytesNeeded, 786 LPDWORD lpServicesReturned) 787 { 788 DWORD dwError = ERROR_SUCCESS; 789 WCHAR szNameBuf[MAX_PATH]; 790 WCHAR szValueBuf[MAX_PATH]; 791 WCHAR *lpszNameBuf = szNameBuf; 792 WCHAR *lpszValueBuf = szValueBuf; 793 DWORD dwSize; 794 DWORD dwNumSubKeys; 795 DWORD dwIteration; 796 PSERVICE lpCurrentService; 797 HKEY hServiceEnumKey; 798 DWORD dwCurrentServiceState = SERVICE_ACTIVE; 799 DWORD dwDependServiceStrPtr = 0; 800 DWORD dwRequiredSize = 0; 801 802 /* Get the number of service keys */ 803 dwError = RegQueryInfoKeyW(hServicesKey, 804 NULL, 805 NULL, 806 NULL, 807 &dwNumSubKeys, 808 NULL, 809 NULL, 810 NULL, 811 NULL, 812 NULL, 813 NULL, 814 NULL); 815 if (dwError != ERROR_SUCCESS) 816 { 817 DPRINT("ERROR! Unable to get number of services keys.\n"); 818 return dwError; 819 } 820 821 /* Iterate the service keys to see if another service depends on the this service */ 822 for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++) 823 { 824 dwSize = MAX_PATH; 825 dwError = RegEnumKeyExW(hServicesKey, 826 dwIteration, 827 lpszNameBuf, 828 &dwSize, 829 NULL, 830 NULL, 831 NULL, 832 NULL); 833 if (dwError != ERROR_SUCCESS) 834 return dwError; 835 836 /* Open the Service key */ 837 dwError = RegOpenKeyExW(hServicesKey, 838 lpszNameBuf, 839 0, 840 KEY_READ, 841 &hServiceEnumKey); 842 if (dwError != ERROR_SUCCESS) 843 return dwError; 844 845 dwSize = MAX_PATH * sizeof(WCHAR); 846 847 /* Check for the DependOnService Value */ 848 dwError = RegQueryValueExW(hServiceEnumKey, 849 L"DependOnService", 850 NULL, 851 NULL, 852 (LPBYTE)lpszValueBuf, 853 &dwSize); 854 855 /* FIXME: Handle load order. */ 856 857 /* If the service found has a DependOnService value */ 858 if (dwError == ERROR_SUCCESS) 859 { 860 dwDependServiceStrPtr = 0; 861 862 /* Can be more than one Dependencies in the DependOnService string */ 863 while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0) 864 { 865 if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0) 866 { 867 /* Get the current enumed service pointer */ 868 lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf); 869 870 /* Check for valid Service */ 871 if (!lpCurrentService) 872 { 873 /* This should never happen! */ 874 DPRINT("This should not happen at this point, report to Developer\n"); 875 return ERROR_NOT_FOUND; 876 } 877 878 /* Determine state the service is in */ 879 if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED) 880 dwCurrentServiceState = SERVICE_INACTIVE; 881 882 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */ 883 if ((dwCurrentServiceState == dwServiceState) || 884 (dwServiceState == SERVICE_STATE_ALL)) 885 { 886 /* Calculate the required size */ 887 dwRequiredSize += sizeof(SERVICE_STATUS); 888 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR)); 889 dwRequiredSize += (DWORD)((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 890 891 /* Add the size for service name and display name pointers */ 892 dwRequiredSize += (2 * sizeof(PVOID)); 893 894 /* increase the BytesNeeded size */ 895 *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize; 896 897 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency 898 comes first */ 899 900 /* Recursive call to check for its dependencies */ 901 Int_EnumDependentServicesW(hServicesKey, 902 lpCurrentService, 903 dwServiceState, 904 lpServices, 905 pcbBytesNeeded, 906 lpServicesReturned); 907 908 /* If the lpServices is valid set the service pointer */ 909 if (lpServices) 910 lpServices[*lpServicesReturned] = lpCurrentService; 911 912 *lpServicesReturned = *lpServicesReturned + 1; 913 } 914 } 915 916 dwDependServiceStrPtr += (DWORD)(wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1); 917 } 918 } 919 else if (*pcbBytesNeeded) 920 { 921 dwError = ERROR_SUCCESS; 922 } 923 924 RegCloseKey(hServiceEnumKey); 925 } 926 927 return dwError; 928 } 929 930 931 /* Function 0 */ 932 DWORD 933 WINAPI 934 RCloseServiceHandle( 935 LPSC_RPC_HANDLE hSCObject) 936 { 937 PMANAGER_HANDLE hManager; 938 PSERVICE_HANDLE hService; 939 PSERVICE lpService; 940 HKEY hServicesKey; 941 DWORD dwError; 942 DWORD pcbBytesNeeded = 0; 943 DWORD dwServicesReturned = 0; 944 945 DPRINT("RCloseServiceHandle() called\n"); 946 947 DPRINT("hSCObject = %p\n", *hSCObject); 948 949 if (*hSCObject == 0) 950 return ERROR_INVALID_HANDLE; 951 952 hManager = ScmGetServiceManagerFromHandle(*hSCObject); 953 hService = ScmGetServiceFromHandle(*hSCObject); 954 955 if (hManager != NULL) 956 { 957 DPRINT("Found manager handle\n"); 958 959 /* Make sure we don't access stale memory if someone tries to use this handle again. */ 960 hManager->Handle.Tag = INVALID_TAG; 961 962 HeapFree(GetProcessHeap(), 0, hManager); 963 hManager = NULL; 964 965 *hSCObject = NULL; 966 967 DPRINT("RCloseServiceHandle() done\n"); 968 return ERROR_SUCCESS; 969 } 970 else if (hService != NULL) 971 { 972 DPRINT("Found service handle\n"); 973 974 /* Lock the service database exclusively */ 975 ScmLockDatabaseExclusive(); 976 977 /* Get the pointer to the service record */ 978 lpService = hService->ServiceEntry; 979 980 /* Make sure we don't access stale memory if someone tries to use this handle again. */ 981 hService->Handle.Tag = INVALID_TAG; 982 983 /* Free the handle */ 984 HeapFree(GetProcessHeap(), 0, hService); 985 hService = NULL; 986 987 ASSERT(lpService->dwRefCount > 0); 988 989 lpService->dwRefCount--; 990 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n", 991 lpService->dwRefCount); 992 993 if (lpService->dwRefCount == 0) 994 { 995 /* If this service has been marked for deletion */ 996 if (lpService->bDeleted && 997 lpService->Status.dwCurrentState == SERVICE_STOPPED) 998 { 999 /* Open the Services Reg key */ 1000 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1001 L"System\\CurrentControlSet\\Services", 1002 0, 1003 KEY_SET_VALUE | KEY_READ, 1004 &hServicesKey); 1005 if (dwError != ERROR_SUCCESS) 1006 { 1007 DPRINT("Failed to open services key\n"); 1008 ScmUnlockDatabase(); 1009 return dwError; 1010 } 1011 1012 /* Call the internal function with NULL, just to get bytes we need */ 1013 Int_EnumDependentServicesW(hServicesKey, 1014 lpService, 1015 SERVICE_ACTIVE, 1016 NULL, 1017 &pcbBytesNeeded, 1018 &dwServicesReturned); 1019 1020 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */ 1021 if (pcbBytesNeeded) 1022 { 1023 DPRINT("Deletion failed due to running dependencies.\n"); 1024 RegCloseKey(hServicesKey); 1025 ScmUnlockDatabase(); 1026 return ERROR_SUCCESS; 1027 } 1028 1029 /* There are no references and no running dependencies, 1030 it is now safe to delete the service */ 1031 1032 /* Delete the Service Key */ 1033 dwError = ScmDeleteRegKey(hServicesKey, 1034 lpService->lpServiceName); 1035 1036 RegCloseKey(hServicesKey); 1037 1038 if (dwError != ERROR_SUCCESS) 1039 { 1040 DPRINT("Failed to Delete the Service Registry key\n"); 1041 ScmUnlockDatabase(); 1042 return dwError; 1043 } 1044 1045 /* Delete the Service */ 1046 ScmDeleteServiceRecord(lpService); 1047 } 1048 } 1049 1050 ScmUnlockDatabase(); 1051 1052 *hSCObject = NULL; 1053 1054 DPRINT("RCloseServiceHandle() done\n"); 1055 return ERROR_SUCCESS; 1056 } 1057 1058 DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag); 1059 1060 return ERROR_INVALID_HANDLE; 1061 } 1062 1063 1064 /* Function 1 */ 1065 DWORD 1066 WINAPI 1067 RControlService( 1068 SC_RPC_HANDLE hService, 1069 DWORD dwControl, 1070 LPSERVICE_STATUS lpServiceStatus) 1071 { 1072 PSERVICE_HANDLE hSvc; 1073 PSERVICE lpService; 1074 ACCESS_MASK DesiredAccess; 1075 DWORD dwError = ERROR_SUCCESS; 1076 DWORD pcbBytesNeeded = 0; 1077 DWORD dwServicesReturned = 0; 1078 DWORD dwControlsAccepted; 1079 DWORD dwCurrentState; 1080 HKEY hServicesKey = NULL; 1081 LPCWSTR lpLogStrings[2]; 1082 WCHAR szLogBuffer[80]; 1083 UINT uID; 1084 1085 DPRINT("RControlService() called\n"); 1086 1087 if (ScmShutdown) 1088 return ERROR_SHUTDOWN_IN_PROGRESS; 1089 1090 /* Check the service handle */ 1091 hSvc = ScmGetServiceFromHandle(hService); 1092 if (hSvc == NULL) 1093 { 1094 DPRINT1("Invalid service handle!\n"); 1095 return ERROR_INVALID_HANDLE; 1096 } 1097 1098 /* Check the service entry point */ 1099 lpService = hSvc->ServiceEntry; 1100 if (lpService == NULL) 1101 { 1102 DPRINT1("lpService == NULL!\n"); 1103 return ERROR_INVALID_HANDLE; 1104 } 1105 1106 /* Check access rights */ 1107 switch (dwControl) 1108 { 1109 case SERVICE_CONTROL_STOP: 1110 DesiredAccess = SERVICE_STOP; 1111 break; 1112 1113 case SERVICE_CONTROL_PAUSE: 1114 case SERVICE_CONTROL_CONTINUE: 1115 case SERVICE_CONTROL_PARAMCHANGE: 1116 case SERVICE_CONTROL_NETBINDADD: 1117 case SERVICE_CONTROL_NETBINDREMOVE: 1118 case SERVICE_CONTROL_NETBINDENABLE: 1119 case SERVICE_CONTROL_NETBINDDISABLE: 1120 DesiredAccess = SERVICE_PAUSE_CONTINUE; 1121 break; 1122 1123 case SERVICE_CONTROL_INTERROGATE: 1124 DesiredAccess = SERVICE_INTERROGATE; 1125 break; 1126 1127 default: 1128 if (dwControl >= 128 && dwControl <= 255) 1129 DesiredAccess = SERVICE_USER_DEFINED_CONTROL; 1130 else 1131 return ERROR_INVALID_PARAMETER; 1132 break; 1133 } 1134 1135 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1136 DesiredAccess)) 1137 return ERROR_ACCESS_DENIED; 1138 1139 /* Return the current service status information */ 1140 RtlCopyMemory(lpServiceStatus, 1141 &lpService->Status, 1142 sizeof(SERVICE_STATUS)); 1143 1144 if (dwControl == SERVICE_CONTROL_STOP) 1145 { 1146 /* Check if the service has dependencies running as windows 1147 doesn't stop a service that does */ 1148 1149 /* Open the Services Reg key */ 1150 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 1151 L"System\\CurrentControlSet\\Services", 1152 0, 1153 KEY_READ, 1154 &hServicesKey); 1155 if (dwError != ERROR_SUCCESS) 1156 { 1157 DPRINT("Failed to open services key\n"); 1158 return dwError; 1159 } 1160 1161 /* Call the internal function with NULL, just to get bytes we need */ 1162 Int_EnumDependentServicesW(hServicesKey, 1163 lpService, 1164 SERVICE_ACTIVE, 1165 NULL, 1166 &pcbBytesNeeded, 1167 &dwServicesReturned); 1168 1169 RegCloseKey(hServicesKey); 1170 1171 /* If pcbBytesNeeded is not zero then there are services running that 1172 are dependent on this service */ 1173 if (pcbBytesNeeded != 0) 1174 { 1175 DPRINT("Service has running dependencies. Failed to stop service.\n"); 1176 return ERROR_DEPENDENT_SERVICES_RUNNING; 1177 } 1178 } 1179 1180 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 1181 { 1182 /* Send control code to the driver */ 1183 dwError = ScmControlDriver(lpService, 1184 dwControl, 1185 lpServiceStatus); 1186 } 1187 else 1188 { 1189 dwControlsAccepted = lpService->Status.dwControlsAccepted; 1190 dwCurrentState = lpService->Status.dwCurrentState; 1191 1192 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */ 1193 if (lpService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED) 1194 return ERROR_SERVICE_NOT_ACTIVE; 1195 1196 /* Check the current state before sending a control request */ 1197 switch (dwCurrentState) 1198 { 1199 case SERVICE_STOP_PENDING: 1200 case SERVICE_STOPPED: 1201 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; 1202 1203 case SERVICE_START_PENDING: 1204 switch (dwControl) 1205 { 1206 case SERVICE_CONTROL_STOP: 1207 break; 1208 1209 case SERVICE_CONTROL_INTERROGATE: 1210 RtlCopyMemory(lpServiceStatus, 1211 &lpService->Status, 1212 sizeof(SERVICE_STATUS)); 1213 return ERROR_SUCCESS; 1214 1215 default: 1216 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; 1217 } 1218 break; 1219 } 1220 1221 /* Check if the control code is acceptable to the service */ 1222 switch (dwControl) 1223 { 1224 case SERVICE_CONTROL_STOP: 1225 if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0) 1226 return ERROR_INVALID_SERVICE_CONTROL; 1227 break; 1228 1229 case SERVICE_CONTROL_PAUSE: 1230 case SERVICE_CONTROL_CONTINUE: 1231 if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0) 1232 return ERROR_INVALID_SERVICE_CONTROL; 1233 break; 1234 1235 case SERVICE_CONTROL_PARAMCHANGE: 1236 if ((dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE) == 0) 1237 return ERROR_INVALID_SERVICE_CONTROL; 1238 break; 1239 1240 case SERVICE_CONTROL_NETBINDADD: 1241 case SERVICE_CONTROL_NETBINDREMOVE: 1242 case SERVICE_CONTROL_NETBINDENABLE: 1243 case SERVICE_CONTROL_NETBINDDISABLE: 1244 if ((dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE) == 0) 1245 return ERROR_INVALID_SERVICE_CONTROL; 1246 break; 1247 } 1248 1249 /* Send control code to the service */ 1250 dwError = ScmControlService(lpService->lpImage->hControlPipe, 1251 lpService->lpServiceName, 1252 (SERVICE_STATUS_HANDLE)lpService, 1253 dwControl); 1254 1255 /* Return service status information */ 1256 RtlCopyMemory(lpServiceStatus, 1257 &lpService->Status, 1258 sizeof(SERVICE_STATUS)); 1259 } 1260 1261 if (dwError == ERROR_SUCCESS) 1262 { 1263 if (dwControl == SERVICE_CONTROL_STOP || 1264 dwControl == SERVICE_CONTROL_PAUSE || 1265 dwControl == SERVICE_CONTROL_CONTINUE) 1266 { 1267 /* Log a successful send control */ 1268 1269 switch (dwControl) 1270 { 1271 case SERVICE_CONTROL_STOP: 1272 uID = IDS_SERVICE_STOP; 1273 break; 1274 1275 case SERVICE_CONTROL_PAUSE: 1276 uID = IDS_SERVICE_PAUSE; 1277 break; 1278 1279 case SERVICE_CONTROL_CONTINUE: 1280 uID = IDS_SERVICE_RESUME; 1281 break; 1282 } 1283 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer)); 1284 1285 lpLogStrings[0] = lpService->lpDisplayName; 1286 lpLogStrings[1] = szLogBuffer; 1287 1288 ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS, 1289 EVENTLOG_INFORMATION_TYPE, 1290 2, 1291 lpLogStrings); 1292 } 1293 } 1294 1295 return dwError; 1296 } 1297 1298 1299 /* Function 2 */ 1300 DWORD 1301 WINAPI 1302 RDeleteService( 1303 SC_RPC_HANDLE hService) 1304 { 1305 PSERVICE_HANDLE hSvc; 1306 PSERVICE lpService; 1307 DWORD dwError; 1308 1309 DPRINT("RDeleteService() called\n"); 1310 1311 if (ScmShutdown) 1312 return ERROR_SHUTDOWN_IN_PROGRESS; 1313 1314 hSvc = ScmGetServiceFromHandle(hService); 1315 if (hSvc == NULL) 1316 { 1317 DPRINT1("Invalid service handle!\n"); 1318 return ERROR_INVALID_HANDLE; 1319 } 1320 1321 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1322 DELETE)) 1323 return ERROR_ACCESS_DENIED; 1324 1325 lpService = hSvc->ServiceEntry; 1326 if (lpService == NULL) 1327 { 1328 DPRINT("lpService == NULL!\n"); 1329 return ERROR_INVALID_HANDLE; 1330 } 1331 1332 /* Lock the service database exclusively */ 1333 ScmLockDatabaseExclusive(); 1334 1335 if (lpService->bDeleted) 1336 { 1337 DPRINT("The service has already been marked for delete!\n"); 1338 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 1339 goto Done; 1340 } 1341 1342 /* Mark service for delete */ 1343 lpService->bDeleted = TRUE; 1344 1345 dwError = ScmMarkServiceForDelete(lpService); 1346 1347 Done: 1348 /* Unlock the service database */ 1349 ScmUnlockDatabase(); 1350 1351 DPRINT("RDeleteService() done\n"); 1352 1353 return dwError; 1354 } 1355 1356 1357 /* Function 3 */ 1358 DWORD 1359 WINAPI 1360 RLockServiceDatabase( 1361 SC_RPC_HANDLE hSCManager, 1362 LPSC_RPC_LOCK lpLock) 1363 { 1364 PMANAGER_HANDLE hMgr; 1365 1366 DPRINT("RLockServiceDatabase() called\n"); 1367 1368 *lpLock = NULL; 1369 1370 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 1371 if (hMgr == NULL) 1372 { 1373 DPRINT1("Invalid service manager handle!\n"); 1374 return ERROR_INVALID_HANDLE; 1375 } 1376 1377 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 1378 SC_MANAGER_LOCK)) 1379 return ERROR_ACCESS_DENIED; 1380 1381 return ScmAcquireServiceStartLock(FALSE, lpLock); 1382 } 1383 1384 1385 /* Function 4 */ 1386 DWORD 1387 WINAPI 1388 RQueryServiceObjectSecurity( 1389 SC_RPC_HANDLE hService, 1390 SECURITY_INFORMATION dwSecurityInformation, 1391 LPBYTE lpSecurityDescriptor, 1392 DWORD cbBufSize, 1393 LPBOUNDED_DWORD_256K pcbBytesNeeded) 1394 { 1395 PSERVICE_HANDLE hSvc; 1396 PSERVICE lpService; 1397 ULONG DesiredAccess = 0; 1398 NTSTATUS Status; 1399 DWORD dwBytesNeeded; 1400 DWORD dwError; 1401 1402 DPRINT("RQueryServiceObjectSecurity() called\n"); 1403 1404 hSvc = ScmGetServiceFromHandle(hService); 1405 if (hSvc == NULL) 1406 { 1407 DPRINT1("Invalid service handle!\n"); 1408 return ERROR_INVALID_HANDLE; 1409 } 1410 1411 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION | 1412 GROUP_SECURITY_INFORMATION | 1413 OWNER_SECURITY_INFORMATION)) 1414 DesiredAccess |= READ_CONTROL; 1415 1416 if (dwSecurityInformation & SACL_SECURITY_INFORMATION) 1417 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 1418 1419 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1420 DesiredAccess)) 1421 { 1422 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 1423 return ERROR_ACCESS_DENIED; 1424 } 1425 1426 lpService = hSvc->ServiceEntry; 1427 if (lpService == NULL) 1428 { 1429 DPRINT("lpService == NULL!\n"); 1430 return ERROR_INVALID_HANDLE; 1431 } 1432 1433 /* Lock the service database */ 1434 ScmLockDatabaseShared(); 1435 1436 /* Retrieve the security descriptor */ 1437 Status = RtlQuerySecurityObject(lpService->pSecurityDescriptor, 1438 dwSecurityInformation, 1439 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor, 1440 cbBufSize, 1441 &dwBytesNeeded); 1442 1443 /* Unlock the service database */ 1444 ScmUnlockDatabase(); 1445 1446 if (NT_SUCCESS(Status)) 1447 { 1448 *pcbBytesNeeded = dwBytesNeeded; 1449 dwError = STATUS_SUCCESS; 1450 } 1451 else if (Status == STATUS_BUFFER_TOO_SMALL) 1452 { 1453 *pcbBytesNeeded = dwBytesNeeded; 1454 dwError = ERROR_INSUFFICIENT_BUFFER; 1455 } 1456 else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT) 1457 { 1458 dwError = ERROR_GEN_FAILURE; 1459 } 1460 else 1461 { 1462 dwError = RtlNtStatusToDosError(Status); 1463 } 1464 1465 return dwError; 1466 } 1467 1468 1469 /* Function 5 */ 1470 DWORD 1471 WINAPI 1472 RSetServiceObjectSecurity( 1473 SC_RPC_HANDLE hService, 1474 DWORD dwSecurityInformation, 1475 LPBYTE lpSecurityDescriptor, 1476 DWORD dwSecurityDescriptorSize) 1477 { 1478 PSERVICE_HANDLE hSvc; 1479 PSERVICE lpService; 1480 ACCESS_MASK DesiredAccess = 0; 1481 HANDLE hToken = NULL; 1482 HKEY hServiceKey = NULL; 1483 BOOL bDatabaseLocked = FALSE; 1484 NTSTATUS Status; 1485 DWORD dwError; 1486 1487 DPRINT("RSetServiceObjectSecurity() called\n"); 1488 1489 hSvc = ScmGetServiceFromHandle(hService); 1490 if (hSvc == NULL) 1491 { 1492 DPRINT1("Invalid service handle!\n"); 1493 return ERROR_INVALID_HANDLE; 1494 } 1495 1496 if (dwSecurityInformation == 0 || 1497 dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION 1498 | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)) 1499 return ERROR_INVALID_PARAMETER; 1500 1501 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)) 1502 return ERROR_INVALID_PARAMETER; 1503 1504 if (dwSecurityInformation & SACL_SECURITY_INFORMATION) 1505 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 1506 1507 if (dwSecurityInformation & DACL_SECURITY_INFORMATION) 1508 DesiredAccess |= WRITE_DAC; 1509 1510 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) 1511 DesiredAccess |= WRITE_OWNER; 1512 1513 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) && 1514 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL)) 1515 return ERROR_INVALID_PARAMETER; 1516 1517 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) && 1518 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL)) 1519 return ERROR_INVALID_PARAMETER; 1520 1521 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1522 DesiredAccess)) 1523 { 1524 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 1525 return ERROR_ACCESS_DENIED; 1526 } 1527 1528 lpService = hSvc->ServiceEntry; 1529 if (lpService == NULL) 1530 { 1531 DPRINT1("lpService == NULL!\n"); 1532 return ERROR_INVALID_HANDLE; 1533 } 1534 1535 if (lpService->bDeleted) 1536 return ERROR_SERVICE_MARKED_FOR_DELETE; 1537 1538 #if 0 1539 RpcImpersonateClient(NULL); 1540 1541 Status = NtOpenThreadToken(NtCurrentThread(), 1542 8, 1543 TRUE, 1544 &hToken); 1545 if (!NT_SUCCESS(Status)) 1546 return RtlNtStatusToDosError(Status); 1547 1548 RpcRevertToSelf(); 1549 #endif 1550 1551 /* Build the new security descriptor */ 1552 Status = RtlSetSecurityObject(dwSecurityInformation, 1553 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor, 1554 &lpService->pSecurityDescriptor, 1555 &ScmServiceMapping, 1556 hToken); 1557 if (!NT_SUCCESS(Status)) 1558 { 1559 dwError = RtlNtStatusToDosError(Status); 1560 goto Done; 1561 } 1562 1563 /* Lock the service database exclusive */ 1564 ScmLockDatabaseExclusive(); 1565 bDatabaseLocked = TRUE; 1566 1567 /* Open the service key */ 1568 dwError = ScmOpenServiceKey(lpService->lpServiceName, 1569 READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE, 1570 &hServiceKey); 1571 if (dwError != ERROR_SUCCESS) 1572 goto Done; 1573 1574 /* Store the new security descriptor */ 1575 dwError = ScmWriteSecurityDescriptor(hServiceKey, 1576 lpService->pSecurityDescriptor); 1577 1578 RegFlushKey(hServiceKey); 1579 1580 Done: 1581 if (hServiceKey != NULL) 1582 RegCloseKey(hServiceKey); 1583 1584 /* Unlock service database */ 1585 if (bDatabaseLocked == TRUE) 1586 ScmUnlockDatabase(); 1587 1588 if (hToken != NULL) 1589 NtClose(hToken); 1590 1591 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError); 1592 1593 return dwError; 1594 } 1595 1596 1597 /* Function 6 */ 1598 DWORD 1599 WINAPI 1600 RQueryServiceStatus( 1601 SC_RPC_HANDLE hService, 1602 LPSERVICE_STATUS lpServiceStatus) 1603 { 1604 PSERVICE_HANDLE hSvc; 1605 PSERVICE lpService; 1606 1607 DPRINT("RQueryServiceStatus() called\n"); 1608 1609 if (ScmShutdown) 1610 return ERROR_SHUTDOWN_IN_PROGRESS; 1611 1612 hSvc = ScmGetServiceFromHandle(hService); 1613 if (hSvc == NULL) 1614 { 1615 DPRINT1("Invalid service handle!\n"); 1616 return ERROR_INVALID_HANDLE; 1617 } 1618 1619 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1620 SERVICE_QUERY_STATUS)) 1621 { 1622 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 1623 return ERROR_ACCESS_DENIED; 1624 } 1625 1626 lpService = hSvc->ServiceEntry; 1627 if (lpService == NULL) 1628 { 1629 DPRINT("lpService == NULL!\n"); 1630 return ERROR_INVALID_HANDLE; 1631 } 1632 1633 /* Lock the service database shared */ 1634 ScmLockDatabaseShared(); 1635 1636 /* Return service status information */ 1637 RtlCopyMemory(lpServiceStatus, 1638 &lpService->Status, 1639 sizeof(SERVICE_STATUS)); 1640 1641 /* Unlock the service database */ 1642 ScmUnlockDatabase(); 1643 1644 return ERROR_SUCCESS; 1645 } 1646 1647 1648 static BOOL 1649 ScmIsValidServiceState(DWORD dwCurrentState) 1650 { 1651 switch (dwCurrentState) 1652 { 1653 case SERVICE_STOPPED: 1654 case SERVICE_START_PENDING: 1655 case SERVICE_STOP_PENDING: 1656 case SERVICE_RUNNING: 1657 case SERVICE_CONTINUE_PENDING: 1658 case SERVICE_PAUSE_PENDING: 1659 case SERVICE_PAUSED: 1660 return TRUE; 1661 1662 default: 1663 return FALSE; 1664 } 1665 } 1666 1667 1668 /* Function 7 */ 1669 DWORD 1670 WINAPI 1671 RSetServiceStatus( 1672 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 1673 LPSERVICE_STATUS lpServiceStatus) 1674 { 1675 PSERVICE lpService; 1676 DWORD dwPreviousState; 1677 DWORD dwPreviousType; 1678 LPCWSTR lpLogStrings[2]; 1679 WCHAR szLogBuffer[80]; 1680 UINT uID; 1681 1682 DPRINT("RSetServiceStatus() called\n"); 1683 DPRINT("hServiceStatus = %lu\n", hServiceStatus); 1684 DPRINT("dwServiceType = 0x%lx\n", lpServiceStatus->dwServiceType); 1685 DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState); 1686 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted); 1687 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode); 1688 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode); 1689 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint); 1690 DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint); 1691 1692 if (hServiceStatus == 0) 1693 { 1694 DPRINT("hServiceStatus == NULL!\n"); 1695 return ERROR_INVALID_HANDLE; 1696 } 1697 1698 lpService = (PSERVICE)hServiceStatus; 1699 1700 /* Check current state */ 1701 if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState)) 1702 { 1703 DPRINT("Invalid service state!\n"); 1704 return ERROR_INVALID_DATA; 1705 } 1706 1707 /* Check service type */ 1708 if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) && 1709 (lpServiceStatus->dwServiceType & SERVICE_DRIVER)) 1710 { 1711 DPRINT("Invalid service type!\n"); 1712 return ERROR_INVALID_DATA; 1713 } 1714 1715 /* Check accepted controls */ 1716 if (lpServiceStatus->dwControlsAccepted & ~0xFF) 1717 { 1718 DPRINT("Invalid controls accepted!\n"); 1719 return ERROR_INVALID_DATA; 1720 } 1721 1722 /* Set the wait hint and check point only if the service is in a pending state, 1723 otherwise they should be 0 */ 1724 if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED || 1725 lpServiceStatus->dwCurrentState == SERVICE_PAUSED || 1726 lpServiceStatus->dwCurrentState == SERVICE_RUNNING) 1727 { 1728 lpServiceStatus->dwWaitHint = 0; 1729 lpServiceStatus->dwCheckPoint = 0; 1730 } 1731 1732 /* Lock the service database exclusively */ 1733 ScmLockDatabaseExclusive(); 1734 1735 /* Save the current service state */ 1736 dwPreviousState = lpService->Status.dwCurrentState; 1737 1738 /* Save the current service type */ 1739 dwPreviousType = lpService->Status.dwServiceType; 1740 1741 /* Update the service status */ 1742 RtlCopyMemory(&lpService->Status, 1743 lpServiceStatus, 1744 sizeof(SERVICE_STATUS)); 1745 1746 /* Restore the previous service type */ 1747 lpService->Status.dwServiceType = dwPreviousType; 1748 1749 /* Dereference a stopped service */ 1750 if ((lpServiceStatus->dwServiceType & SERVICE_WIN32) && 1751 (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)) 1752 { 1753 /* Decrement the image run counter */ 1754 lpService->lpImage->dwImageRunCount--; 1755 1756 /* If we just stopped the last running service... */ 1757 if (lpService->lpImage->dwImageRunCount == 0) 1758 { 1759 /* Stop the dispatcher thread */ 1760 ScmControlService(lpService->lpImage->hControlPipe, 1761 L"", 1762 (SERVICE_STATUS_HANDLE)lpService, 1763 SERVICE_CONTROL_STOP); 1764 1765 /* Remove the service image */ 1766 ScmRemoveServiceImage(lpService->lpImage); 1767 lpService->lpImage = NULL; 1768 } 1769 } 1770 1771 /* Unlock the service database */ 1772 ScmUnlockDatabase(); 1773 1774 if ((lpServiceStatus->dwCurrentState == SERVICE_STOPPED) && 1775 (dwPreviousState != SERVICE_STOPPED) && 1776 (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS)) 1777 { 1778 /* Log a failed service stop */ 1779 StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer), 1780 L"%lu", lpServiceStatus->dwWin32ExitCode); 1781 lpLogStrings[0] = lpService->lpDisplayName; 1782 lpLogStrings[1] = szLogBuffer; 1783 1784 ScmLogEvent(EVENT_SERVICE_EXIT_FAILED, 1785 EVENTLOG_ERROR_TYPE, 1786 2, 1787 lpLogStrings); 1788 } 1789 else if (lpServiceStatus->dwCurrentState != dwPreviousState && 1790 (lpServiceStatus->dwCurrentState == SERVICE_STOPPED || 1791 lpServiceStatus->dwCurrentState == SERVICE_RUNNING || 1792 lpServiceStatus->dwCurrentState == SERVICE_PAUSED)) 1793 { 1794 /* Log a successful service status change */ 1795 switch(lpServiceStatus->dwCurrentState) 1796 { 1797 case SERVICE_STOPPED: 1798 uID = IDS_SERVICE_STOPPED; 1799 break; 1800 1801 case SERVICE_RUNNING: 1802 uID = IDS_SERVICE_RUNNING; 1803 break; 1804 1805 case SERVICE_PAUSED: 1806 uID = IDS_SERVICE_PAUSED; 1807 break; 1808 } 1809 1810 LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer)); 1811 lpLogStrings[0] = lpService->lpDisplayName; 1812 lpLogStrings[1] = szLogBuffer; 1813 1814 ScmLogEvent(EVENT_SERVICE_STATUS_SUCCESS, 1815 EVENTLOG_INFORMATION_TYPE, 1816 2, 1817 lpLogStrings); 1818 } 1819 1820 DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState); 1821 DPRINT("RSetServiceStatus() done\n"); 1822 1823 return ERROR_SUCCESS; 1824 } 1825 1826 1827 /* Function 8 */ 1828 DWORD 1829 WINAPI 1830 RUnlockServiceDatabase( 1831 LPSC_RPC_LOCK Lock) 1832 { 1833 DPRINT("RUnlockServiceDatabase(%p)\n", Lock); 1834 return ScmReleaseServiceStartLock(Lock); 1835 } 1836 1837 1838 /* Function 9 */ 1839 DWORD 1840 WINAPI 1841 RNotifyBootConfigStatus( 1842 SVCCTL_HANDLEW lpMachineName, 1843 DWORD BootAcceptable) 1844 { 1845 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName, BootAcceptable); 1846 return ERROR_SUCCESS; 1847 1848 // UNIMPLEMENTED; 1849 // return ERROR_CALL_NOT_IMPLEMENTED; 1850 } 1851 1852 1853 /* Function 10 */ 1854 DWORD 1855 WINAPI 1856 RI_ScSetServiceBitsW( 1857 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 1858 DWORD dwServiceBits, 1859 int bSetBitsOn, 1860 int bUpdateImmediately, 1861 wchar_t *lpString) 1862 { 1863 PSERVICE pService; 1864 1865 DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n", 1866 hServiceStatus, dwServiceBits, bSetBitsOn, 1867 bUpdateImmediately, lpString); 1868 1869 if (ScmShutdown) 1870 return ERROR_SHUTDOWN_IN_PROGRESS; 1871 1872 if (lpString != NULL) 1873 return ERROR_INVALID_PARAMETER; 1874 1875 if (hServiceStatus == 0) 1876 { 1877 DPRINT("hServiceStatus == NULL!\n"); 1878 return ERROR_INVALID_HANDLE; 1879 } 1880 1881 // FIXME: Validate the status handle 1882 pService = (PSERVICE)hServiceStatus; 1883 1884 if (bSetBitsOn) 1885 { 1886 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits); 1887 pService->dwServiceBits |= dwServiceBits; 1888 DPRINT("New service bits: %08lx\n", pService->dwServiceBits); 1889 } 1890 else 1891 { 1892 DPRINT("Old service bits: %08lx\n", pService->dwServiceBits); 1893 pService->dwServiceBits &= ~dwServiceBits; 1894 DPRINT("New service bits: %08lx\n", pService->dwServiceBits); 1895 } 1896 1897 return ERROR_SUCCESS; 1898 } 1899 1900 1901 /* Function 11 */ 1902 DWORD 1903 WINAPI 1904 RChangeServiceConfigW( 1905 SC_RPC_HANDLE hService, 1906 DWORD dwServiceType, 1907 DWORD dwStartType, 1908 DWORD dwErrorControl, 1909 LPWSTR lpBinaryPathName, 1910 LPWSTR lpLoadOrderGroup, 1911 LPDWORD lpdwTagId, 1912 LPBYTE lpDependencies, 1913 DWORD dwDependSize, 1914 LPWSTR lpServiceStartName, 1915 LPBYTE lpPassword, 1916 DWORD dwPwSize, 1917 LPWSTR lpDisplayName) 1918 { 1919 DWORD dwError = ERROR_SUCCESS; 1920 PSERVICE_HANDLE hSvc; 1921 PSERVICE lpService = NULL; 1922 HKEY hServiceKey = NULL; 1923 LPWSTR lpDisplayNameW = NULL; 1924 LPWSTR lpImagePathW = NULL; 1925 1926 DPRINT("RChangeServiceConfigW() called\n"); 1927 DPRINT("dwServiceType = 0x%lx\n", dwServiceType); 1928 DPRINT("dwStartType = %lu\n", dwStartType); 1929 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 1930 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 1931 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 1932 DPRINT("lpDisplayName = %S\n", lpDisplayName); 1933 1934 if (ScmShutdown) 1935 return ERROR_SHUTDOWN_IN_PROGRESS; 1936 1937 hSvc = ScmGetServiceFromHandle(hService); 1938 if (hSvc == NULL) 1939 { 1940 DPRINT1("Invalid service handle!\n"); 1941 return ERROR_INVALID_HANDLE; 1942 } 1943 1944 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1945 SERVICE_CHANGE_CONFIG)) 1946 { 1947 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 1948 return ERROR_ACCESS_DENIED; 1949 } 1950 1951 /* Check for invalid service type value */ 1952 if ((dwServiceType != SERVICE_NO_CHANGE) && 1953 (dwServiceType != SERVICE_KERNEL_DRIVER) && 1954 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) && 1955 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && 1956 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS)) 1957 return ERROR_INVALID_PARAMETER; 1958 1959 /* Check for invalid start type value */ 1960 if ((dwStartType != SERVICE_NO_CHANGE) && 1961 (dwStartType != SERVICE_BOOT_START) && 1962 (dwStartType != SERVICE_SYSTEM_START) && 1963 (dwStartType != SERVICE_AUTO_START) && 1964 (dwStartType != SERVICE_DEMAND_START) && 1965 (dwStartType != SERVICE_DISABLED)) 1966 return ERROR_INVALID_PARAMETER; 1967 1968 /* Only drivers can be boot start or system start services */ 1969 if ((dwStartType == SERVICE_BOOT_START) || 1970 (dwStartType == SERVICE_SYSTEM_START)) 1971 { 1972 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 1973 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) 1974 return ERROR_INVALID_PARAMETER; 1975 } 1976 1977 /* Check for invalid error control value */ 1978 if ((dwErrorControl != SERVICE_NO_CHANGE) && 1979 (dwErrorControl != SERVICE_ERROR_IGNORE) && 1980 (dwErrorControl != SERVICE_ERROR_NORMAL) && 1981 (dwErrorControl != SERVICE_ERROR_SEVERE) && 1982 (dwErrorControl != SERVICE_ERROR_CRITICAL)) 1983 return ERROR_INVALID_PARAMETER; 1984 1985 lpService = hSvc->ServiceEntry; 1986 if (lpService == NULL) 1987 { 1988 DPRINT("lpService == NULL!\n"); 1989 return ERROR_INVALID_HANDLE; 1990 } 1991 1992 /* Lock the service database exclusively */ 1993 ScmLockDatabaseExclusive(); 1994 1995 if (lpService->bDeleted) 1996 { 1997 DPRINT("The service has already been marked for delete!\n"); 1998 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 1999 goto done; 2000 } 2001 2002 /* Open the service key */ 2003 dwError = ScmOpenServiceKey(lpService->szServiceName, 2004 KEY_SET_VALUE, 2005 &hServiceKey); 2006 if (dwError != ERROR_SUCCESS) 2007 goto done; 2008 2009 /* Write service data to the registry */ 2010 /* Set the display name */ 2011 if (lpDisplayName != NULL && *lpDisplayName != 0) 2012 { 2013 RegSetValueExW(hServiceKey, 2014 L"DisplayName", 2015 0, 2016 REG_SZ, 2017 (LPBYTE)lpDisplayName, 2018 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR))); 2019 2020 /* Update the display name */ 2021 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 2022 HEAP_ZERO_MEMORY, 2023 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 2024 if (lpDisplayNameW == NULL) 2025 { 2026 dwError = ERROR_NOT_ENOUGH_MEMORY; 2027 goto done; 2028 } 2029 2030 wcscpy(lpDisplayNameW, lpDisplayName); 2031 if (lpService->lpDisplayName != lpService->lpServiceName) 2032 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 2033 2034 lpService->lpDisplayName = lpDisplayNameW; 2035 } 2036 2037 if (dwServiceType != SERVICE_NO_CHANGE) 2038 { 2039 /* Set the service type */ 2040 dwError = RegSetValueExW(hServiceKey, 2041 L"Type", 2042 0, 2043 REG_DWORD, 2044 (LPBYTE)&dwServiceType, 2045 sizeof(DWORD)); 2046 if (dwError != ERROR_SUCCESS) 2047 goto done; 2048 2049 lpService->Status.dwServiceType = dwServiceType; 2050 } 2051 2052 if (dwStartType != SERVICE_NO_CHANGE) 2053 { 2054 /* Set the start value */ 2055 dwError = RegSetValueExW(hServiceKey, 2056 L"Start", 2057 0, 2058 REG_DWORD, 2059 (LPBYTE)&dwStartType, 2060 sizeof(DWORD)); 2061 if (dwError != ERROR_SUCCESS) 2062 goto done; 2063 2064 lpService->dwStartType = dwStartType; 2065 } 2066 2067 if (dwErrorControl != SERVICE_NO_CHANGE) 2068 { 2069 /* Set the error control value */ 2070 dwError = RegSetValueExW(hServiceKey, 2071 L"ErrorControl", 2072 0, 2073 REG_DWORD, 2074 (LPBYTE)&dwErrorControl, 2075 sizeof(DWORD)); 2076 if (dwError != ERROR_SUCCESS) 2077 goto done; 2078 2079 lpService->dwErrorControl = dwErrorControl; 2080 } 2081 2082 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 2083 { 2084 /* Set the image path */ 2085 lpImagePathW = lpBinaryPathName; 2086 2087 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 2088 { 2089 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 2090 lpBinaryPathName, 2091 &lpImagePathW); 2092 2093 if (dwError != ERROR_SUCCESS) 2094 goto done; 2095 } 2096 2097 dwError = RegSetValueExW(hServiceKey, 2098 L"ImagePath", 2099 0, 2100 REG_EXPAND_SZ, 2101 (LPBYTE)lpImagePathW, 2102 (DWORD)((wcslen(lpImagePathW) + 1) * sizeof(WCHAR))); 2103 2104 if (lpImagePathW != lpBinaryPathName) 2105 HeapFree(GetProcessHeap(), 0, lpImagePathW); 2106 2107 if (dwError != ERROR_SUCCESS) 2108 goto done; 2109 } 2110 2111 /* Set the group name */ 2112 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2113 { 2114 dwError = RegSetValueExW(hServiceKey, 2115 L"Group", 2116 0, 2117 REG_SZ, 2118 (LPBYTE)lpLoadOrderGroup, 2119 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR))); 2120 if (dwError != ERROR_SUCCESS) 2121 goto done; 2122 2123 dwError = ScmSetServiceGroup(lpService, 2124 lpLoadOrderGroup); 2125 if (dwError != ERROR_SUCCESS) 2126 goto done; 2127 } 2128 2129 /* Set the tag */ 2130 if (lpdwTagId != NULL) 2131 { 2132 dwError = ScmAssignNewTag(lpService); 2133 if (dwError != ERROR_SUCCESS) 2134 goto done; 2135 2136 dwError = RegSetValueExW(hServiceKey, 2137 L"Tag", 2138 0, 2139 REG_DWORD, 2140 (LPBYTE)&lpService->dwTag, 2141 sizeof(DWORD)); 2142 if (dwError != ERROR_SUCCESS) 2143 goto done; 2144 2145 *lpdwTagId = lpService->dwTag; 2146 } 2147 2148 /* Write dependencies */ 2149 if (lpDependencies != NULL && *lpDependencies != 0) 2150 { 2151 dwError = ScmWriteDependencies(hServiceKey, 2152 (LPWSTR)lpDependencies, 2153 dwDependSize); 2154 if (dwError != ERROR_SUCCESS) 2155 goto done; 2156 } 2157 2158 if (lpPassword != NULL) 2159 { 2160 if (wcslen((LPWSTR)lpPassword) != 0) 2161 { 2162 /* FIXME: Decrypt the password */ 2163 2164 /* Write the password */ 2165 dwError = ScmSetServicePassword(lpService->szServiceName, 2166 (LPCWSTR)lpPassword); 2167 if (dwError != ERROR_SUCCESS) 2168 goto done; 2169 } 2170 else 2171 { 2172 /* Delete the password */ 2173 dwError = ScmSetServicePassword(lpService->szServiceName, 2174 NULL); 2175 if (dwError == ERROR_FILE_NOT_FOUND) 2176 dwError = ERROR_SUCCESS; 2177 2178 if (dwError != ERROR_SUCCESS) 2179 goto done; 2180 } 2181 } 2182 2183 done: 2184 if (hServiceKey != NULL) 2185 RegCloseKey(hServiceKey); 2186 2187 /* Unlock the service database */ 2188 ScmUnlockDatabase(); 2189 2190 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError); 2191 2192 return dwError; 2193 } 2194 2195 2196 /* Function 12 */ 2197 DWORD 2198 WINAPI 2199 RCreateServiceW( 2200 SC_RPC_HANDLE hSCManager, 2201 LPCWSTR lpServiceName, 2202 LPCWSTR lpDisplayName, 2203 DWORD dwDesiredAccess, 2204 DWORD dwServiceType, 2205 DWORD dwStartType, 2206 DWORD dwErrorControl, 2207 LPCWSTR lpBinaryPathName, 2208 LPCWSTR lpLoadOrderGroup, 2209 LPDWORD lpdwTagId, 2210 LPBYTE lpDependencies, 2211 DWORD dwDependSize, 2212 LPCWSTR lpServiceStartName, 2213 LPBYTE lpPassword, 2214 DWORD dwPwSize, 2215 LPSC_RPC_HANDLE lpServiceHandle) 2216 { 2217 PMANAGER_HANDLE hManager; 2218 DWORD dwError = ERROR_SUCCESS; 2219 PSERVICE lpService = NULL; 2220 SC_HANDLE hServiceHandle = NULL; 2221 LPWSTR lpImagePath = NULL; 2222 HKEY hServiceKey = NULL; 2223 LPWSTR lpObjectName; 2224 2225 DPRINT("RCreateServiceW() called\n"); 2226 DPRINT("lpServiceName = %S\n", lpServiceName); 2227 DPRINT("lpDisplayName = %S\n", lpDisplayName); 2228 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess); 2229 DPRINT("dwServiceType = 0x%lx\n", dwServiceType); 2230 DPRINT("dwStartType = %lu\n", dwStartType); 2231 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 2232 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 2233 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 2234 DPRINT("lpdwTagId = %p\n", lpdwTagId); 2235 2236 if (ScmShutdown) 2237 return ERROR_SHUTDOWN_IN_PROGRESS; 2238 2239 hManager = ScmGetServiceManagerFromHandle(hSCManager); 2240 if (hManager == NULL) 2241 { 2242 DPRINT1("Invalid service manager handle!\n"); 2243 return ERROR_INVALID_HANDLE; 2244 } 2245 2246 /* Check access rights */ 2247 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 2248 SC_MANAGER_CREATE_SERVICE)) 2249 { 2250 DPRINT("Insufficient access rights! 0x%lx\n", 2251 hManager->Handle.DesiredAccess); 2252 return ERROR_ACCESS_DENIED; 2253 } 2254 2255 if (wcslen(lpServiceName) == 0) 2256 { 2257 return ERROR_INVALID_NAME; 2258 } 2259 2260 if (wcslen(lpBinaryPathName) == 0) 2261 { 2262 return ERROR_INVALID_PARAMETER; 2263 } 2264 2265 /* Check for invalid service type value */ 2266 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 2267 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) && 2268 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && 2269 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS)) 2270 return ERROR_INVALID_PARAMETER; 2271 2272 /* Check for invalid start type value */ 2273 if ((dwStartType != SERVICE_BOOT_START) && 2274 (dwStartType != SERVICE_SYSTEM_START) && 2275 (dwStartType != SERVICE_AUTO_START) && 2276 (dwStartType != SERVICE_DEMAND_START) && 2277 (dwStartType != SERVICE_DISABLED)) 2278 return ERROR_INVALID_PARAMETER; 2279 2280 /* Only drivers can be boot start or system start services */ 2281 if ((dwStartType == SERVICE_BOOT_START) || 2282 (dwStartType == SERVICE_SYSTEM_START)) 2283 { 2284 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 2285 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) 2286 return ERROR_INVALID_PARAMETER; 2287 } 2288 2289 /* Check for invalid error control value */ 2290 if ((dwErrorControl != SERVICE_ERROR_IGNORE) && 2291 (dwErrorControl != SERVICE_ERROR_NORMAL) && 2292 (dwErrorControl != SERVICE_ERROR_SEVERE) && 2293 (dwErrorControl != SERVICE_ERROR_CRITICAL)) 2294 return ERROR_INVALID_PARAMETER; 2295 2296 if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) && 2297 (lpServiceStartName)) 2298 { 2299 /* We allow LocalSystem to run interactive. */ 2300 if (wcsicmp(lpServiceStartName, L"LocalSystem")) 2301 { 2302 return ERROR_INVALID_PARAMETER; 2303 } 2304 } 2305 2306 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup)) 2307 { 2308 return ERROR_INVALID_PARAMETER; 2309 } 2310 2311 /* Lock the service database exclusively */ 2312 ScmLockDatabaseExclusive(); 2313 2314 lpService = ScmGetServiceEntryByName(lpServiceName); 2315 if (lpService) 2316 { 2317 /* Unlock the service database */ 2318 ScmUnlockDatabase(); 2319 2320 /* Check if it is marked for deletion */ 2321 if (lpService->bDeleted) 2322 return ERROR_SERVICE_MARKED_FOR_DELETE; 2323 2324 /* Return Error exist */ 2325 return ERROR_SERVICE_EXISTS; 2326 } 2327 2328 if (lpDisplayName != NULL && 2329 ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL) 2330 { 2331 /* Unlock the service database */ 2332 ScmUnlockDatabase(); 2333 2334 return ERROR_DUPLICATE_SERVICE_NAME; 2335 } 2336 2337 if (dwServiceType & SERVICE_DRIVER) 2338 { 2339 dwError = ScmCanonDriverImagePath(dwStartType, 2340 lpBinaryPathName, 2341 &lpImagePath); 2342 if (dwError != ERROR_SUCCESS) 2343 goto done; 2344 } 2345 else 2346 { 2347 if (dwStartType == SERVICE_BOOT_START || 2348 dwStartType == SERVICE_SYSTEM_START) 2349 { 2350 /* Unlock the service database */ 2351 ScmUnlockDatabase(); 2352 2353 return ERROR_INVALID_PARAMETER; 2354 } 2355 } 2356 2357 /* Allocate a new service entry */ 2358 dwError = ScmCreateNewServiceRecord(lpServiceName, 2359 &lpService, 2360 dwServiceType, 2361 dwStartType); 2362 if (dwError != ERROR_SUCCESS) 2363 goto done; 2364 2365 /* Fill the new service entry */ 2366 lpService->dwErrorControl = dwErrorControl; 2367 2368 /* Fill the display name */ 2369 if (lpDisplayName != NULL && 2370 *lpDisplayName != 0 && 2371 _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0) 2372 { 2373 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 2374 HEAP_ZERO_MEMORY, 2375 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 2376 if (lpService->lpDisplayName == NULL) 2377 { 2378 dwError = ERROR_NOT_ENOUGH_MEMORY; 2379 goto done; 2380 } 2381 wcscpy(lpService->lpDisplayName, lpDisplayName); 2382 } 2383 2384 /* Assign the service to a group */ 2385 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2386 { 2387 dwError = ScmSetServiceGroup(lpService, 2388 lpLoadOrderGroup); 2389 if (dwError != ERROR_SUCCESS) 2390 goto done; 2391 } 2392 2393 /* Assign a new tag */ 2394 if (lpdwTagId != NULL) 2395 { 2396 dwError = ScmAssignNewTag(lpService); 2397 if (dwError != ERROR_SUCCESS) 2398 goto done; 2399 } 2400 2401 /* Assign the default security descriptor */ 2402 if (dwServiceType & SERVICE_WIN32) 2403 { 2404 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor); 2405 if (dwError != ERROR_SUCCESS) 2406 goto done; 2407 } 2408 2409 /* Write service data to the registry */ 2410 /* Create the service key */ 2411 dwError = ScmCreateServiceKey(lpServiceName, 2412 KEY_WRITE, 2413 &hServiceKey); 2414 if (dwError != ERROR_SUCCESS) 2415 goto done; 2416 2417 /* Set the display name */ 2418 if (lpDisplayName != NULL && *lpDisplayName != 0) 2419 { 2420 RegSetValueExW(hServiceKey, 2421 L"DisplayName", 2422 0, 2423 REG_SZ, 2424 (LPBYTE)lpDisplayName, 2425 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR))); 2426 } 2427 2428 /* Set the service type */ 2429 dwError = RegSetValueExW(hServiceKey, 2430 L"Type", 2431 0, 2432 REG_DWORD, 2433 (LPBYTE)&dwServiceType, 2434 sizeof(DWORD)); 2435 if (dwError != ERROR_SUCCESS) 2436 goto done; 2437 2438 /* Set the start value */ 2439 dwError = RegSetValueExW(hServiceKey, 2440 L"Start", 2441 0, 2442 REG_DWORD, 2443 (LPBYTE)&dwStartType, 2444 sizeof(DWORD)); 2445 if (dwError != ERROR_SUCCESS) 2446 goto done; 2447 2448 /* Set the error control value */ 2449 dwError = RegSetValueExW(hServiceKey, 2450 L"ErrorControl", 2451 0, 2452 REG_DWORD, 2453 (LPBYTE)&dwErrorControl, 2454 sizeof(DWORD)); 2455 if (dwError != ERROR_SUCCESS) 2456 goto done; 2457 2458 /* Set the image path */ 2459 if (dwServiceType & SERVICE_WIN32) 2460 { 2461 dwError = RegSetValueExW(hServiceKey, 2462 L"ImagePath", 2463 0, 2464 REG_EXPAND_SZ, 2465 (LPBYTE)lpBinaryPathName, 2466 (DWORD)((wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR))); 2467 if (dwError != ERROR_SUCCESS) 2468 goto done; 2469 } 2470 else if (dwServiceType & SERVICE_DRIVER) 2471 { 2472 dwError = RegSetValueExW(hServiceKey, 2473 L"ImagePath", 2474 0, 2475 REG_EXPAND_SZ, 2476 (LPBYTE)lpImagePath, 2477 (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR))); 2478 if (dwError != ERROR_SUCCESS) 2479 goto done; 2480 } 2481 2482 /* Set the group name */ 2483 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2484 { 2485 dwError = RegSetValueExW(hServiceKey, 2486 L"Group", 2487 0, 2488 REG_SZ, 2489 (LPBYTE)lpLoadOrderGroup, 2490 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR))); 2491 if (dwError != ERROR_SUCCESS) 2492 goto done; 2493 } 2494 2495 /* Set the service tag */ 2496 if (lpdwTagId != NULL) 2497 { 2498 dwError = RegSetValueExW(hServiceKey, 2499 L"Tag", 2500 0, 2501 REG_DWORD, 2502 (LPBYTE)&lpService->dwTag, 2503 sizeof(DWORD)); 2504 if (dwError != ERROR_SUCCESS) 2505 goto done; 2506 } 2507 2508 /* Write dependencies */ 2509 if (lpDependencies != NULL && *lpDependencies != 0) 2510 { 2511 dwError = ScmWriteDependencies(hServiceKey, 2512 (LPCWSTR)lpDependencies, 2513 dwDependSize); 2514 if (dwError != ERROR_SUCCESS) 2515 goto done; 2516 } 2517 2518 /* Start name and password are only used by Win32 services */ 2519 if (dwServiceType & SERVICE_WIN32) 2520 { 2521 /* Write service start name */ 2522 lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem"; 2523 dwError = RegSetValueExW(hServiceKey, 2524 L"ObjectName", 2525 0, 2526 REG_SZ, 2527 (LPBYTE)lpObjectName, 2528 (DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR))); 2529 if (dwError != ERROR_SUCCESS) 2530 goto done; 2531 2532 if (lpPassword != NULL && wcslen((LPWSTR)lpPassword) != 0) 2533 { 2534 /* FIXME: Decrypt the password */ 2535 2536 /* Write the password */ 2537 dwError = ScmSetServicePassword(lpServiceName, 2538 (LPCWSTR)lpPassword); 2539 if (dwError != ERROR_SUCCESS) 2540 goto done; 2541 } 2542 2543 DPRINT1("\n"); 2544 /* Write the security descriptor */ 2545 dwError = ScmWriteSecurityDescriptor(hServiceKey, 2546 lpService->pSecurityDescriptor); 2547 if (dwError != ERROR_SUCCESS) 2548 goto done; 2549 } 2550 2551 dwError = ScmCreateServiceHandle(lpService, 2552 &hServiceHandle); 2553 if (dwError != ERROR_SUCCESS) 2554 goto done; 2555 2556 dwError = ScmCheckAccess(hServiceHandle, 2557 dwDesiredAccess); 2558 if (dwError != ERROR_SUCCESS) 2559 goto done; 2560 2561 lpService->dwRefCount = 1; 2562 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount); 2563 2564 done: 2565 /* Unlock the service database */ 2566 ScmUnlockDatabase(); 2567 2568 if (hServiceKey != NULL) 2569 RegCloseKey(hServiceKey); 2570 2571 if (dwError == ERROR_SUCCESS) 2572 { 2573 DPRINT("hService %p\n", hServiceHandle); 2574 *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle; 2575 2576 if (lpdwTagId != NULL) 2577 *lpdwTagId = lpService->dwTag; 2578 } 2579 else 2580 { 2581 if (lpService != NULL && 2582 lpService->lpServiceName != NULL) 2583 { 2584 /* Release the display name buffer */ 2585 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 2586 } 2587 2588 if (hServiceHandle) 2589 { 2590 /* Remove the service handle */ 2591 HeapFree(GetProcessHeap(), 0, hServiceHandle); 2592 } 2593 2594 if (lpService != NULL) 2595 { 2596 /* FIXME: remove the service entry */ 2597 } 2598 } 2599 2600 if (lpImagePath != NULL) 2601 HeapFree(GetProcessHeap(), 0, lpImagePath); 2602 2603 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError); 2604 2605 return dwError; 2606 } 2607 2608 2609 /* Function 13 */ 2610 DWORD 2611 WINAPI 2612 REnumDependentServicesW( 2613 SC_RPC_HANDLE hService, 2614 DWORD dwServiceState, 2615 LPBYTE lpServices, 2616 DWORD cbBufSize, 2617 LPBOUNDED_DWORD_256K pcbBytesNeeded, 2618 LPBOUNDED_DWORD_256K lpServicesReturned) 2619 { 2620 DWORD dwError = ERROR_SUCCESS; 2621 DWORD dwServicesReturned = 0; 2622 DWORD dwServiceCount; 2623 HKEY hServicesKey = NULL; 2624 PSERVICE_HANDLE hSvc; 2625 PSERVICE lpService = NULL; 2626 PSERVICE *lpServicesArray = NULL; 2627 LPENUM_SERVICE_STATUSW lpServicesPtr = NULL; 2628 LPWSTR lpStr; 2629 2630 *pcbBytesNeeded = 0; 2631 *lpServicesReturned = 0; 2632 2633 DPRINT("REnumDependentServicesW() called\n"); 2634 2635 hSvc = ScmGetServiceFromHandle(hService); 2636 if (hSvc == NULL) 2637 { 2638 DPRINT1("Invalid service handle!\n"); 2639 return ERROR_INVALID_HANDLE; 2640 } 2641 2642 lpService = hSvc->ServiceEntry; 2643 2644 /* Check access rights */ 2645 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 2646 SC_MANAGER_ENUMERATE_SERVICE)) 2647 { 2648 DPRINT("Insufficient access rights! 0x%lx\n", 2649 hSvc->Handle.DesiredAccess); 2650 return ERROR_ACCESS_DENIED; 2651 } 2652 2653 /* Open the Services Reg key */ 2654 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2655 L"System\\CurrentControlSet\\Services", 2656 0, 2657 KEY_READ, 2658 &hServicesKey); 2659 if (dwError != ERROR_SUCCESS) 2660 return dwError; 2661 2662 /* First determine the bytes needed and get the number of dependent services */ 2663 dwError = Int_EnumDependentServicesW(hServicesKey, 2664 lpService, 2665 dwServiceState, 2666 NULL, 2667 pcbBytesNeeded, 2668 &dwServicesReturned); 2669 if (dwError != ERROR_SUCCESS) 2670 goto Done; 2671 2672 /* If buffer size is less than the bytes needed or pointer is null */ 2673 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 2674 { 2675 dwError = ERROR_MORE_DATA; 2676 goto Done; 2677 } 2678 2679 /* Allocate memory for array of service pointers */ 2680 lpServicesArray = HeapAlloc(GetProcessHeap(), 2681 HEAP_ZERO_MEMORY, 2682 (dwServicesReturned + 1) * sizeof(PSERVICE)); 2683 if (!lpServicesArray) 2684 { 2685 DPRINT1("Could not allocate a buffer!!\n"); 2686 dwError = ERROR_NOT_ENOUGH_MEMORY; 2687 goto Done; 2688 } 2689 2690 dwServicesReturned = 0; 2691 *pcbBytesNeeded = 0; 2692 2693 dwError = Int_EnumDependentServicesW(hServicesKey, 2694 lpService, 2695 dwServiceState, 2696 lpServicesArray, 2697 pcbBytesNeeded, 2698 &dwServicesReturned); 2699 if (dwError != ERROR_SUCCESS) 2700 { 2701 goto Done; 2702 } 2703 2704 lpServicesPtr = (LPENUM_SERVICE_STATUSW)lpServices; 2705 lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW))); 2706 2707 /* Copy EnumDepenedentService to Buffer */ 2708 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 2709 { 2710 lpService = lpServicesArray[dwServiceCount]; 2711 2712 /* Copy status info */ 2713 memcpy(&lpServicesPtr->ServiceStatus, 2714 &lpService->Status, 2715 sizeof(SERVICE_STATUS)); 2716 2717 /* Copy display name */ 2718 wcscpy(lpStr, lpService->lpDisplayName); 2719 lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 2720 lpStr += (wcslen(lpService->lpDisplayName) + 1); 2721 2722 /* Copy service name */ 2723 wcscpy(lpStr, lpService->lpServiceName); 2724 lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 2725 lpStr += (wcslen(lpService->lpServiceName) + 1); 2726 2727 lpServicesPtr++; 2728 } 2729 2730 *lpServicesReturned = dwServicesReturned; 2731 2732 Done: 2733 if (lpServicesArray != NULL) 2734 HeapFree(GetProcessHeap(), 0, lpServicesArray); 2735 2736 RegCloseKey(hServicesKey); 2737 2738 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError); 2739 2740 return dwError; 2741 } 2742 2743 2744 /* Function 14 */ 2745 DWORD 2746 WINAPI 2747 REnumServicesStatusW( 2748 SC_RPC_HANDLE hSCManager, 2749 DWORD dwServiceType, 2750 DWORD dwServiceState, 2751 LPBYTE lpBuffer, 2752 DWORD dwBufSize, 2753 LPBOUNDED_DWORD_256K pcbBytesNeeded, 2754 LPBOUNDED_DWORD_256K lpServicesReturned, 2755 LPBOUNDED_DWORD_256K lpResumeHandle) 2756 { 2757 /* Enumerate all the services, not regarding of their group */ 2758 return REnumServiceGroupW(hSCManager, 2759 dwServiceType, 2760 dwServiceState, 2761 lpBuffer, 2762 dwBufSize, 2763 pcbBytesNeeded, 2764 lpServicesReturned, 2765 lpResumeHandle, 2766 NULL); 2767 } 2768 2769 2770 /* Function 15 */ 2771 DWORD 2772 WINAPI 2773 ROpenSCManagerW( 2774 LPWSTR lpMachineName, 2775 LPWSTR lpDatabaseName, 2776 DWORD dwDesiredAccess, 2777 LPSC_RPC_HANDLE lpScHandle) 2778 { 2779 DWORD dwError; 2780 SC_HANDLE hHandle; 2781 2782 DPRINT("ROpenSCManagerW() called\n"); 2783 DPRINT("lpMachineName = %p\n", lpMachineName); 2784 DPRINT("lpMachineName: %S\n", lpMachineName); 2785 DPRINT("lpDataBaseName = %p\n", lpDatabaseName); 2786 DPRINT("lpDataBaseName: %S\n", lpDatabaseName); 2787 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 2788 2789 if (ScmShutdown) 2790 return ERROR_SHUTDOWN_IN_PROGRESS; 2791 2792 if (!lpScHandle) 2793 return ERROR_INVALID_PARAMETER; 2794 2795 dwError = ScmCreateManagerHandle(lpDatabaseName, 2796 &hHandle); 2797 if (dwError != ERROR_SUCCESS) 2798 { 2799 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError); 2800 return dwError; 2801 } 2802 2803 /* Check the desired access */ 2804 dwError = ScmCheckAccess(hHandle, 2805 dwDesiredAccess | SC_MANAGER_CONNECT); 2806 if (dwError != ERROR_SUCCESS) 2807 { 2808 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 2809 HeapFree(GetProcessHeap(), 0, hHandle); 2810 return dwError; 2811 } 2812 2813 *lpScHandle = (SC_RPC_HANDLE)hHandle; 2814 DPRINT("*hScm = %p\n", *lpScHandle); 2815 2816 DPRINT("ROpenSCManagerW() done\n"); 2817 2818 return ERROR_SUCCESS; 2819 } 2820 2821 2822 /* Function 16 */ 2823 DWORD 2824 WINAPI 2825 ROpenServiceW( 2826 SC_RPC_HANDLE hSCManager, 2827 LPWSTR lpServiceName, 2828 DWORD dwDesiredAccess, 2829 LPSC_RPC_HANDLE lpServiceHandle) 2830 { 2831 PSERVICE lpService; 2832 PMANAGER_HANDLE hManager; 2833 SC_HANDLE hHandle; 2834 DWORD dwError = ERROR_SUCCESS; 2835 2836 DPRINT("ROpenServiceW() called\n"); 2837 DPRINT("hSCManager = %p\n", hSCManager); 2838 DPRINT("lpServiceName = %p\n", lpServiceName); 2839 DPRINT("lpServiceName: %S\n", lpServiceName); 2840 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 2841 2842 if (ScmShutdown) 2843 return ERROR_SHUTDOWN_IN_PROGRESS; 2844 2845 hManager = ScmGetServiceManagerFromHandle(hSCManager); 2846 if (hManager == NULL) 2847 { 2848 DPRINT1("Invalid service manager handle!\n"); 2849 return ERROR_INVALID_HANDLE; 2850 } 2851 2852 if (!lpServiceHandle) 2853 return ERROR_INVALID_PARAMETER; 2854 2855 if (!lpServiceName) 2856 return ERROR_INVALID_ADDRESS; 2857 2858 /* Lock the service database exclusive */ 2859 ScmLockDatabaseExclusive(); 2860 2861 /* Get service database entry */ 2862 lpService = ScmGetServiceEntryByName(lpServiceName); 2863 if (lpService == NULL) 2864 { 2865 DPRINT("Could not find a service!\n"); 2866 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 2867 goto Done; 2868 } 2869 2870 /* Create a service handle */ 2871 dwError = ScmCreateServiceHandle(lpService, 2872 &hHandle); 2873 if (dwError != ERROR_SUCCESS) 2874 { 2875 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError); 2876 goto Done; 2877 } 2878 2879 /* Check the desired access */ 2880 dwError = ScmCheckAccess(hHandle, 2881 dwDesiredAccess); 2882 if (dwError != ERROR_SUCCESS) 2883 { 2884 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 2885 HeapFree(GetProcessHeap(), 0, hHandle); 2886 goto Done; 2887 } 2888 2889 lpService->dwRefCount++; 2890 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount); 2891 2892 *lpServiceHandle = (SC_RPC_HANDLE)hHandle; 2893 DPRINT("*hService = %p\n", *lpServiceHandle); 2894 2895 Done: 2896 /* Unlock the service database */ 2897 ScmUnlockDatabase(); 2898 2899 DPRINT("ROpenServiceW() done\n"); 2900 2901 return dwError; 2902 } 2903 2904 2905 /* Function 17 */ 2906 DWORD 2907 WINAPI 2908 RQueryServiceConfigW( 2909 SC_RPC_HANDLE hService, 2910 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig, 2911 DWORD cbBufSize, 2912 LPBOUNDED_DWORD_8K pcbBytesNeeded) 2913 { 2914 LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf; 2915 DWORD dwError = ERROR_SUCCESS; 2916 PSERVICE_HANDLE hSvc; 2917 PSERVICE lpService = NULL; 2918 HKEY hServiceKey = NULL; 2919 LPWSTR lpImagePath = NULL; 2920 LPWSTR lpServiceStartName = NULL; 2921 LPWSTR lpDependencies = NULL; 2922 DWORD dwDependenciesLength = 0; 2923 DWORD dwRequiredSize; 2924 WCHAR lpEmptyString[] = {0,0}; 2925 LPWSTR lpStr; 2926 2927 DPRINT("RQueryServiceConfigW() called\n"); 2928 2929 if (ScmShutdown) 2930 return ERROR_SHUTDOWN_IN_PROGRESS; 2931 2932 hSvc = ScmGetServiceFromHandle(hService); 2933 if (hSvc == NULL) 2934 { 2935 DPRINT1("Invalid service handle!\n"); 2936 return ERROR_INVALID_HANDLE; 2937 } 2938 2939 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 2940 SERVICE_QUERY_CONFIG)) 2941 { 2942 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 2943 return ERROR_ACCESS_DENIED; 2944 } 2945 2946 lpService = hSvc->ServiceEntry; 2947 if (lpService == NULL) 2948 { 2949 DPRINT("lpService == NULL!\n"); 2950 return ERROR_INVALID_HANDLE; 2951 } 2952 2953 /* Lock the service database shared */ 2954 ScmLockDatabaseShared(); 2955 2956 dwError = ScmOpenServiceKey(lpService->lpServiceName, 2957 KEY_READ, 2958 &hServiceKey); 2959 if (dwError != ERROR_SUCCESS) 2960 goto Done; 2961 2962 /* Read the image path */ 2963 dwError = ScmReadString(hServiceKey, 2964 L"ImagePath", 2965 &lpImagePath); 2966 if (dwError != ERROR_SUCCESS) 2967 goto Done; 2968 2969 /* Read the service start name */ 2970 ScmReadString(hServiceKey, 2971 L"ObjectName", 2972 &lpServiceStartName); 2973 2974 /* Read the dependencies */ 2975 ScmReadDependencies(hServiceKey, 2976 &lpDependencies, 2977 &dwDependenciesLength); 2978 2979 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW); 2980 2981 if (lpImagePath != NULL) 2982 dwRequiredSize += (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR)); 2983 else 2984 dwRequiredSize += 2 * sizeof(WCHAR); 2985 2986 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 2987 dwRequiredSize += (DWORD)((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR)); 2988 else 2989 dwRequiredSize += 2 * sizeof(WCHAR); 2990 2991 if (lpDependencies != NULL) 2992 dwRequiredSize += dwDependenciesLength * sizeof(WCHAR); 2993 else 2994 dwRequiredSize += 2 * sizeof(WCHAR); 2995 2996 if (lpServiceStartName != NULL) 2997 dwRequiredSize += (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)); 2998 else 2999 dwRequiredSize += 2 * sizeof(WCHAR); 3000 3001 if (lpService->lpDisplayName != NULL) 3002 dwRequiredSize += (DWORD)((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR)); 3003 else 3004 dwRequiredSize += 2 * sizeof(WCHAR); 3005 3006 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 3007 { 3008 dwError = ERROR_INSUFFICIENT_BUFFER; 3009 } 3010 else 3011 { 3012 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType; 3013 lpServiceConfig->dwStartType = lpService->dwStartType; 3014 lpServiceConfig->dwErrorControl = lpService->dwErrorControl; 3015 lpServiceConfig->dwTagId = lpService->dwTag; 3016 3017 lpStr = (LPWSTR)(lpServiceConfig + 1); 3018 3019 /* Append the image path */ 3020 if (lpImagePath != NULL) 3021 { 3022 wcscpy(lpStr, lpImagePath); 3023 } 3024 else 3025 { 3026 wcscpy(lpStr, lpEmptyString); 3027 } 3028 3029 lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3030 lpStr += (wcslen(lpStr) + 1); 3031 3032 /* Append the group name */ 3033 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 3034 { 3035 wcscpy(lpStr, lpService->lpGroup->lpGroupName); 3036 } 3037 else 3038 { 3039 wcscpy(lpStr, lpEmptyString); 3040 } 3041 3042 lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3043 lpStr += (wcslen(lpStr) + 1); 3044 3045 /* Append Dependencies */ 3046 if (lpDependencies != NULL) 3047 { 3048 memcpy(lpStr, 3049 lpDependencies, 3050 dwDependenciesLength * sizeof(WCHAR)); 3051 } 3052 else 3053 { 3054 wcscpy(lpStr, lpEmptyString); 3055 } 3056 3057 lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3058 if (lpDependencies != NULL) 3059 lpStr += dwDependenciesLength; 3060 else 3061 lpStr += (wcslen(lpStr) + 1); 3062 3063 /* Append the service start name */ 3064 if (lpServiceStartName != NULL) 3065 { 3066 wcscpy(lpStr, lpServiceStartName); 3067 } 3068 else 3069 { 3070 wcscpy(lpStr, lpEmptyString); 3071 } 3072 3073 lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3074 lpStr += (wcslen(lpStr) + 1); 3075 3076 /* Append the display name */ 3077 if (lpService->lpDisplayName != NULL) 3078 { 3079 wcscpy(lpStr, lpService->lpDisplayName); 3080 } 3081 else 3082 { 3083 wcscpy(lpStr, lpEmptyString); 3084 } 3085 3086 lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3087 } 3088 3089 if (pcbBytesNeeded != NULL) 3090 *pcbBytesNeeded = dwRequiredSize; 3091 3092 Done: 3093 /* Unlock the service database */ 3094 ScmUnlockDatabase(); 3095 3096 if (lpImagePath != NULL) 3097 HeapFree(GetProcessHeap(), 0, lpImagePath); 3098 3099 if (lpServiceStartName != NULL) 3100 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 3101 3102 if (lpDependencies != NULL) 3103 HeapFree(GetProcessHeap(), 0, lpDependencies); 3104 3105 if (hServiceKey != NULL) 3106 RegCloseKey(hServiceKey); 3107 3108 DPRINT("RQueryServiceConfigW() done\n"); 3109 3110 return dwError; 3111 } 3112 3113 3114 /* Function 18 */ 3115 DWORD 3116 WINAPI 3117 RQueryServiceLockStatusW( 3118 SC_RPC_HANDLE hSCManager, 3119 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, 3120 DWORD cbBufSize, 3121 LPBOUNDED_DWORD_4K pcbBytesNeeded) 3122 { 3123 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSW)lpBuf; 3124 PMANAGER_HANDLE hMgr; 3125 DWORD dwRequiredSize; 3126 3127 if (!lpLockStatus || !pcbBytesNeeded) 3128 return ERROR_INVALID_PARAMETER; 3129 3130 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 3131 if (hMgr == NULL) 3132 { 3133 DPRINT1("Invalid service manager handle!\n"); 3134 return ERROR_INVALID_HANDLE; 3135 } 3136 3137 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 3138 SC_MANAGER_QUERY_LOCK_STATUS)) 3139 { 3140 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess); 3141 return ERROR_ACCESS_DENIED; 3142 } 3143 3144 /* FIXME: we need to compute instead the real length of the owner name */ 3145 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR); 3146 *pcbBytesNeeded = dwRequiredSize; 3147 3148 if (cbBufSize < dwRequiredSize) 3149 return ERROR_INSUFFICIENT_BUFFER; 3150 3151 ScmQueryServiceLockStatusW(lpLockStatus); 3152 3153 return ERROR_SUCCESS; 3154 } 3155 3156 3157 /* Function 19 */ 3158 DWORD 3159 WINAPI 3160 RStartServiceW( 3161 SC_RPC_HANDLE hService, 3162 DWORD argc, 3163 LPSTRING_PTRSW argv) 3164 { 3165 DWORD dwError = ERROR_SUCCESS; 3166 PSERVICE_HANDLE hSvc; 3167 PSERVICE lpService = NULL; 3168 3169 #ifndef NDEBUG 3170 DWORD i; 3171 3172 DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv); 3173 DPRINT(" argc: %lu\n", argc); 3174 if (argv != NULL) 3175 { 3176 for (i = 0; i < argc; i++) 3177 { 3178 DPRINT(" argv[%lu]: %S\n", i, argv[i].StringPtr); 3179 } 3180 } 3181 #endif 3182 3183 if (ScmShutdown) 3184 return ERROR_SHUTDOWN_IN_PROGRESS; 3185 3186 hSvc = ScmGetServiceFromHandle(hService); 3187 if (hSvc == NULL) 3188 { 3189 DPRINT1("Invalid service handle!\n"); 3190 return ERROR_INVALID_HANDLE; 3191 } 3192 3193 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3194 SERVICE_START)) 3195 { 3196 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 3197 return ERROR_ACCESS_DENIED; 3198 } 3199 3200 lpService = hSvc->ServiceEntry; 3201 if (lpService == NULL) 3202 { 3203 DPRINT("lpService == NULL!\n"); 3204 return ERROR_INVALID_HANDLE; 3205 } 3206 3207 if (lpService->dwStartType == SERVICE_DISABLED) 3208 return ERROR_SERVICE_DISABLED; 3209 3210 if (lpService->bDeleted) 3211 return ERROR_SERVICE_MARKED_FOR_DELETE; 3212 3213 /* Start the service */ 3214 dwError = ScmStartService(lpService, argc, (LPWSTR*)argv); 3215 3216 return dwError; 3217 } 3218 3219 3220 /* Function 20 */ 3221 DWORD 3222 WINAPI 3223 RGetServiceDisplayNameW( 3224 SC_RPC_HANDLE hSCManager, 3225 LPCWSTR lpServiceName, 3226 LPWSTR lpDisplayName, 3227 DWORD *lpcchBuffer) 3228 { 3229 // PMANAGER_HANDLE hManager; 3230 PSERVICE lpService; 3231 DWORD dwLength; 3232 DWORD dwError; 3233 3234 DPRINT("RGetServiceDisplayNameW() called\n"); 3235 DPRINT("hSCManager = %p\n", hSCManager); 3236 DPRINT("lpServiceName: %S\n", lpServiceName); 3237 DPRINT("lpDisplayName: %p\n", lpDisplayName); 3238 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 3239 3240 // hManager = (PMANAGER_HANDLE)hSCManager; 3241 // if (hManager->Handle.Tag != MANAGER_TAG) 3242 // { 3243 // DPRINT("Invalid manager handle!\n"); 3244 // return ERROR_INVALID_HANDLE; 3245 // } 3246 3247 /* Get service database entry */ 3248 lpService = ScmGetServiceEntryByName(lpServiceName); 3249 if (lpService == NULL) 3250 { 3251 DPRINT("Could not find a service!\n"); 3252 3253 /* If the service could not be found and lpcchBuffer is less than 2, windows 3254 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 3255 if (*lpcchBuffer < 2) 3256 { 3257 *lpcchBuffer = 2; 3258 if (lpDisplayName != NULL) 3259 { 3260 *lpDisplayName = 0; 3261 } 3262 } 3263 3264 return ERROR_SERVICE_DOES_NOT_EXIST; 3265 } 3266 3267 if (!lpService->lpDisplayName) 3268 { 3269 dwLength = (DWORD)wcslen(lpService->lpServiceName); 3270 3271 if (lpDisplayName != NULL && 3272 *lpcchBuffer > dwLength) 3273 { 3274 wcscpy(lpDisplayName, lpService->lpServiceName); 3275 } 3276 } 3277 else 3278 { 3279 dwLength = (DWORD)wcslen(lpService->lpDisplayName); 3280 3281 if (lpDisplayName != NULL && 3282 *lpcchBuffer > dwLength) 3283 { 3284 wcscpy(lpDisplayName, lpService->lpDisplayName); 3285 } 3286 } 3287 3288 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 3289 3290 *lpcchBuffer = dwLength; 3291 3292 return dwError; 3293 } 3294 3295 3296 /* Function 21 */ 3297 DWORD 3298 WINAPI 3299 RGetServiceKeyNameW( 3300 SC_RPC_HANDLE hSCManager, 3301 LPCWSTR lpDisplayName, 3302 LPWSTR lpServiceName, 3303 DWORD *lpcchBuffer) 3304 { 3305 // PMANAGER_HANDLE hManager; 3306 PSERVICE lpService; 3307 DWORD dwLength; 3308 DWORD dwError; 3309 3310 DPRINT("RGetServiceKeyNameW() called\n"); 3311 DPRINT("hSCManager = %p\n", hSCManager); 3312 DPRINT("lpDisplayName: %S\n", lpDisplayName); 3313 DPRINT("lpServiceName: %p\n", lpServiceName); 3314 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 3315 3316 // hManager = (PMANAGER_HANDLE)hSCManager; 3317 // if (hManager->Handle.Tag != MANAGER_TAG) 3318 // { 3319 // DPRINT("Invalid manager handle!\n"); 3320 // return ERROR_INVALID_HANDLE; 3321 // } 3322 3323 /* Get service database entry */ 3324 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName); 3325 if (lpService == NULL) 3326 { 3327 DPRINT("Could not find a service!\n"); 3328 3329 /* If the service could not be found and lpcchBuffer is less than 2, windows 3330 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 3331 if (*lpcchBuffer < 2) 3332 { 3333 *lpcchBuffer = 2; 3334 if (lpServiceName != NULL) 3335 { 3336 *lpServiceName = 0; 3337 } 3338 } 3339 3340 return ERROR_SERVICE_DOES_NOT_EXIST; 3341 } 3342 3343 dwLength = (DWORD)wcslen(lpService->lpServiceName); 3344 3345 if (lpServiceName != NULL && 3346 *lpcchBuffer > dwLength) 3347 { 3348 wcscpy(lpServiceName, lpService->lpServiceName); 3349 *lpcchBuffer = dwLength; 3350 return ERROR_SUCCESS; 3351 } 3352 3353 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 3354 3355 *lpcchBuffer = dwLength; 3356 3357 return dwError; 3358 } 3359 3360 3361 /* Function 22 */ 3362 DWORD 3363 WINAPI 3364 RI_ScSetServiceBitsA( 3365 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 3366 DWORD dwServiceBits, 3367 int bSetBitsOn, 3368 int bUpdateImmediately, 3369 char *lpString) 3370 { 3371 if (ScmShutdown) 3372 return ERROR_SHUTDOWN_IN_PROGRESS; 3373 3374 if (lpString != NULL) 3375 return ERROR_INVALID_PARAMETER; 3376 3377 return RI_ScSetServiceBitsW(hServiceStatus, 3378 dwServiceBits, 3379 bSetBitsOn, 3380 bUpdateImmediately, 3381 NULL); 3382 } 3383 3384 3385 /* Function 23 */ 3386 DWORD 3387 WINAPI 3388 RChangeServiceConfigA( 3389 SC_RPC_HANDLE hService, 3390 DWORD dwServiceType, 3391 DWORD dwStartType, 3392 DWORD dwErrorControl, 3393 LPSTR lpBinaryPathName, 3394 LPSTR lpLoadOrderGroup, 3395 LPDWORD lpdwTagId, 3396 LPBYTE lpDependencies, 3397 DWORD dwDependSize, 3398 LPSTR lpServiceStartName, 3399 LPBYTE lpPassword, 3400 DWORD dwPwSize, 3401 LPSTR lpDisplayName) 3402 { 3403 DWORD dwError = ERROR_SUCCESS; 3404 PSERVICE_HANDLE hSvc; 3405 PSERVICE lpService = NULL; 3406 HKEY hServiceKey = NULL; 3407 LPWSTR lpDisplayNameW = NULL; 3408 LPWSTR lpBinaryPathNameW = NULL; 3409 LPWSTR lpCanonicalImagePathW = NULL; 3410 LPWSTR lpLoadOrderGroupW = NULL; 3411 LPWSTR lpDependenciesW = NULL; 3412 3413 DPRINT("RChangeServiceConfigA() called\n"); 3414 DPRINT("dwServiceType = %lu\n", dwServiceType); 3415 DPRINT("dwStartType = %lu\n", dwStartType); 3416 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 3417 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName); 3418 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup); 3419 DPRINT("lpDisplayName = %s\n", lpDisplayName); 3420 3421 if (ScmShutdown) 3422 return ERROR_SHUTDOWN_IN_PROGRESS; 3423 3424 hSvc = ScmGetServiceFromHandle(hService); 3425 if (hSvc == NULL) 3426 { 3427 DPRINT1("Invalid service handle!\n"); 3428 return ERROR_INVALID_HANDLE; 3429 } 3430 3431 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3432 SERVICE_CHANGE_CONFIG)) 3433 { 3434 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 3435 return ERROR_ACCESS_DENIED; 3436 } 3437 3438 lpService = hSvc->ServiceEntry; 3439 if (lpService == NULL) 3440 { 3441 DPRINT("lpService == NULL!\n"); 3442 return ERROR_INVALID_HANDLE; 3443 } 3444 3445 /* Lock the service database exclusively */ 3446 ScmLockDatabaseExclusive(); 3447 3448 if (lpService->bDeleted) 3449 { 3450 DPRINT("The service has already been marked for delete!\n"); 3451 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 3452 goto done; 3453 } 3454 3455 /* Open the service key */ 3456 dwError = ScmOpenServiceKey(lpService->szServiceName, 3457 KEY_SET_VALUE, 3458 &hServiceKey); 3459 if (dwError != ERROR_SUCCESS) 3460 goto done; 3461 3462 /* Write service data to the registry */ 3463 3464 if (lpDisplayName != NULL && *lpDisplayName != 0) 3465 { 3466 /* Set the display name */ 3467 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 3468 HEAP_ZERO_MEMORY, 3469 (strlen(lpDisplayName) + 1) * sizeof(WCHAR)); 3470 if (lpDisplayNameW == NULL) 3471 { 3472 dwError = ERROR_NOT_ENOUGH_MEMORY; 3473 goto done; 3474 } 3475 3476 MultiByteToWideChar(CP_ACP, 3477 0, 3478 lpDisplayName, 3479 -1, 3480 lpDisplayNameW, 3481 (int)(strlen(lpDisplayName) + 1)); 3482 3483 RegSetValueExW(hServiceKey, 3484 L"DisplayName", 3485 0, 3486 REG_SZ, 3487 (LPBYTE)lpDisplayNameW, 3488 (DWORD)((wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR))); 3489 3490 /* Update lpService->lpDisplayName */ 3491 if (lpService->lpDisplayName) 3492 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 3493 3494 lpService->lpDisplayName = lpDisplayNameW; 3495 } 3496 3497 if (dwServiceType != SERVICE_NO_CHANGE) 3498 { 3499 /* Set the service type */ 3500 dwError = RegSetValueExW(hServiceKey, 3501 L"Type", 3502 0, 3503 REG_DWORD, 3504 (LPBYTE)&dwServiceType, 3505 sizeof(DWORD)); 3506 if (dwError != ERROR_SUCCESS) 3507 goto done; 3508 3509 lpService->Status.dwServiceType = dwServiceType; 3510 } 3511 3512 if (dwStartType != SERVICE_NO_CHANGE) 3513 { 3514 /* Set the start value */ 3515 dwError = RegSetValueExW(hServiceKey, 3516 L"Start", 3517 0, 3518 REG_DWORD, 3519 (LPBYTE)&dwStartType, 3520 sizeof(DWORD)); 3521 if (dwError != ERROR_SUCCESS) 3522 goto done; 3523 3524 lpService->dwStartType = dwStartType; 3525 } 3526 3527 if (dwErrorControl != SERVICE_NO_CHANGE) 3528 { 3529 /* Set the error control value */ 3530 dwError = RegSetValueExW(hServiceKey, 3531 L"ErrorControl", 3532 0, 3533 REG_DWORD, 3534 (LPBYTE)&dwErrorControl, 3535 sizeof(DWORD)); 3536 if (dwError != ERROR_SUCCESS) 3537 goto done; 3538 3539 lpService->dwErrorControl = dwErrorControl; 3540 } 3541 3542 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 3543 { 3544 /* Set the image path */ 3545 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 3546 HEAP_ZERO_MEMORY, 3547 (strlen(lpBinaryPathName) + 1) * sizeof(WCHAR)); 3548 if (lpBinaryPathNameW == NULL) 3549 { 3550 dwError = ERROR_NOT_ENOUGH_MEMORY; 3551 goto done; 3552 } 3553 3554 MultiByteToWideChar(CP_ACP, 3555 0, 3556 lpBinaryPathName, 3557 -1, 3558 lpBinaryPathNameW, 3559 (int)(strlen(lpBinaryPathName) + 1)); 3560 3561 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 3562 { 3563 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 3564 lpBinaryPathNameW, 3565 &lpCanonicalImagePathW); 3566 3567 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3568 3569 if (dwError != ERROR_SUCCESS) 3570 goto done; 3571 3572 lpBinaryPathNameW = lpCanonicalImagePathW; 3573 } 3574 3575 dwError = RegSetValueExW(hServiceKey, 3576 L"ImagePath", 3577 0, 3578 REG_EXPAND_SZ, 3579 (LPBYTE)lpBinaryPathNameW, 3580 (DWORD)((wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR))); 3581 3582 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3583 3584 if (dwError != ERROR_SUCCESS) 3585 goto done; 3586 } 3587 3588 /* Set the group name */ 3589 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 3590 { 3591 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 3592 HEAP_ZERO_MEMORY, 3593 (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); 3594 if (lpLoadOrderGroupW == NULL) 3595 { 3596 dwError = ERROR_NOT_ENOUGH_MEMORY; 3597 goto done; 3598 } 3599 3600 MultiByteToWideChar(CP_ACP, 3601 0, 3602 lpLoadOrderGroup, 3603 -1, 3604 lpLoadOrderGroupW, 3605 (int)(strlen(lpLoadOrderGroup) + 1)); 3606 3607 dwError = RegSetValueExW(hServiceKey, 3608 L"Group", 3609 0, 3610 REG_SZ, 3611 (LPBYTE)lpLoadOrderGroupW, 3612 (DWORD)((wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR))); 3613 if (dwError != ERROR_SUCCESS) 3614 { 3615 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3616 goto done; 3617 } 3618 3619 dwError = ScmSetServiceGroup(lpService, 3620 lpLoadOrderGroupW); 3621 3622 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3623 3624 if (dwError != ERROR_SUCCESS) 3625 goto done; 3626 } 3627 3628 if (lpdwTagId != NULL) 3629 { 3630 dwError = ScmAssignNewTag(lpService); 3631 if (dwError != ERROR_SUCCESS) 3632 goto done; 3633 3634 dwError = RegSetValueExW(hServiceKey, 3635 L"Tag", 3636 0, 3637 REG_DWORD, 3638 (LPBYTE)&lpService->dwTag, 3639 sizeof(DWORD)); 3640 if (dwError != ERROR_SUCCESS) 3641 goto done; 3642 3643 *lpdwTagId = lpService->dwTag; 3644 } 3645 3646 /* Write dependencies */ 3647 if (lpDependencies != NULL && *lpDependencies != 0) 3648 { 3649 lpDependenciesW = HeapAlloc(GetProcessHeap(), 3650 HEAP_ZERO_MEMORY, 3651 (strlen((LPSTR)lpDependencies) + 1) * sizeof(WCHAR)); 3652 if (lpDependenciesW == NULL) 3653 { 3654 dwError = ERROR_NOT_ENOUGH_MEMORY; 3655 goto done; 3656 } 3657 3658 MultiByteToWideChar(CP_ACP, 3659 0, 3660 (LPSTR)lpDependencies, 3661 dwDependSize, 3662 lpDependenciesW, 3663 (int)(strlen((LPSTR)lpDependencies) + 1)); 3664 3665 dwError = ScmWriteDependencies(hServiceKey, 3666 (LPWSTR)lpDependenciesW, 3667 dwDependSize); 3668 3669 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 3670 3671 if (dwError != ERROR_SUCCESS) 3672 goto done; 3673 } 3674 3675 if (lpPassword != NULL) 3676 { 3677 if (wcslen((LPWSTR)lpPassword) != 0) 3678 { 3679 /* FIXME: Decrypt the password */ 3680 3681 /* Write the password */ 3682 dwError = ScmSetServicePassword(lpService->szServiceName, 3683 (LPCWSTR)lpPassword); 3684 if (dwError != ERROR_SUCCESS) 3685 goto done; 3686 } 3687 else 3688 { 3689 /* Delete the password */ 3690 dwError = ScmSetServicePassword(lpService->szServiceName, 3691 NULL); 3692 if (dwError == ERROR_FILE_NOT_FOUND) 3693 dwError = ERROR_SUCCESS; 3694 3695 if (dwError != ERROR_SUCCESS) 3696 goto done; 3697 } 3698 } 3699 3700 done: 3701 /* Unlock the service database */ 3702 ScmUnlockDatabase(); 3703 3704 if (hServiceKey != NULL) 3705 RegCloseKey(hServiceKey); 3706 3707 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError); 3708 3709 return dwError; 3710 } 3711 3712 3713 /* Function 24 */ 3714 DWORD 3715 WINAPI 3716 RCreateServiceA( 3717 SC_RPC_HANDLE hSCManager, 3718 LPSTR lpServiceName, 3719 LPSTR lpDisplayName, 3720 DWORD dwDesiredAccess, 3721 DWORD dwServiceType, 3722 DWORD dwStartType, 3723 DWORD dwErrorControl, 3724 LPSTR lpBinaryPathName, 3725 LPSTR lpLoadOrderGroup, 3726 LPDWORD lpdwTagId, 3727 LPBYTE lpDependencies, 3728 DWORD dwDependSize, 3729 LPSTR lpServiceStartName, 3730 LPBYTE lpPassword, 3731 DWORD dwPwSize, 3732 LPSC_RPC_HANDLE lpServiceHandle) 3733 { 3734 DWORD dwError = ERROR_SUCCESS; 3735 LPWSTR lpServiceNameW = NULL; 3736 LPWSTR lpDisplayNameW = NULL; 3737 LPWSTR lpBinaryPathNameW = NULL; 3738 LPWSTR lpLoadOrderGroupW = NULL; 3739 LPWSTR lpDependenciesW = NULL; 3740 LPWSTR lpServiceStartNameW = NULL; 3741 DWORD dwDependenciesLength = 0; 3742 SIZE_T cchLength; 3743 int len; 3744 LPCSTR lpStr; 3745 3746 if (lpServiceName) 3747 { 3748 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0); 3749 lpServiceNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3750 if (!lpServiceNameW) 3751 { 3752 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3753 goto cleanup; 3754 } 3755 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len); 3756 } 3757 3758 if (lpDisplayName) 3759 { 3760 len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0); 3761 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3762 if (!lpDisplayNameW) 3763 { 3764 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3765 goto cleanup; 3766 } 3767 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len); 3768 } 3769 3770 if (lpBinaryPathName) 3771 { 3772 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0); 3773 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3774 if (!lpBinaryPathNameW) 3775 { 3776 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3777 goto cleanup; 3778 } 3779 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len); 3780 } 3781 3782 if (lpLoadOrderGroup) 3783 { 3784 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0); 3785 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3786 if (!lpLoadOrderGroupW) 3787 { 3788 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3789 goto cleanup; 3790 } 3791 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len); 3792 } 3793 3794 if (lpDependencies) 3795 { 3796 lpStr = (LPCSTR)lpDependencies; 3797 while (*lpStr) 3798 { 3799 cchLength = strlen(lpStr) + 1; 3800 dwDependenciesLength += (DWORD)cchLength; 3801 lpStr = lpStr + cchLength; 3802 } 3803 dwDependenciesLength++; 3804 3805 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR)); 3806 if (!lpDependenciesW) 3807 { 3808 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3809 goto cleanup; 3810 } 3811 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength); 3812 } 3813 3814 if (lpServiceStartName) 3815 { 3816 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0); 3817 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3818 if (!lpServiceStartNameW) 3819 { 3820 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3821 goto cleanup; 3822 } 3823 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len); 3824 } 3825 3826 dwError = RCreateServiceW(hSCManager, 3827 lpServiceNameW, 3828 lpDisplayNameW, 3829 dwDesiredAccess, 3830 dwServiceType, 3831 dwStartType, 3832 dwErrorControl, 3833 lpBinaryPathNameW, 3834 lpLoadOrderGroupW, 3835 lpdwTagId, 3836 (LPBYTE)lpDependenciesW, 3837 dwDependenciesLength, 3838 lpServiceStartNameW, 3839 lpPassword, 3840 dwPwSize, 3841 lpServiceHandle); 3842 3843 cleanup: 3844 if (lpServiceNameW !=NULL) 3845 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 3846 3847 if (lpDisplayNameW != NULL) 3848 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 3849 3850 if (lpBinaryPathNameW != NULL) 3851 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3852 3853 if (lpLoadOrderGroupW != NULL) 3854 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3855 3856 if (lpDependenciesW != NULL) 3857 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 3858 3859 if (lpServiceStartNameW != NULL) 3860 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW); 3861 3862 return dwError; 3863 } 3864 3865 3866 /* Function 25 */ 3867 DWORD 3868 WINAPI 3869 REnumDependentServicesA( 3870 SC_RPC_HANDLE hService, 3871 DWORD dwServiceState, 3872 LPBYTE lpServices, 3873 DWORD cbBufSize, 3874 LPBOUNDED_DWORD_256K pcbBytesNeeded, 3875 LPBOUNDED_DWORD_256K lpServicesReturned) 3876 { 3877 DWORD dwError = ERROR_SUCCESS; 3878 DWORD dwServicesReturned = 0; 3879 DWORD dwServiceCount; 3880 HKEY hServicesKey = NULL; 3881 PSERVICE_HANDLE hSvc; 3882 PSERVICE lpService = NULL; 3883 PSERVICE *lpServicesArray = NULL; 3884 LPENUM_SERVICE_STATUSA lpServicesPtr = NULL; 3885 LPSTR lpStr; 3886 3887 *pcbBytesNeeded = 0; 3888 *lpServicesReturned = 0; 3889 3890 DPRINT("REnumDependentServicesA() called\n"); 3891 3892 hSvc = ScmGetServiceFromHandle(hService); 3893 if (hSvc == NULL) 3894 { 3895 DPRINT1("Invalid service handle!\n"); 3896 return ERROR_INVALID_HANDLE; 3897 } 3898 3899 lpService = hSvc->ServiceEntry; 3900 3901 /* Check access rights */ 3902 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3903 SC_MANAGER_ENUMERATE_SERVICE)) 3904 { 3905 DPRINT("Insufficient access rights! 0x%lx\n", 3906 hSvc->Handle.DesiredAccess); 3907 return ERROR_ACCESS_DENIED; 3908 } 3909 3910 /* Open the Services Reg key */ 3911 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3912 L"System\\CurrentControlSet\\Services", 3913 0, 3914 KEY_READ, 3915 &hServicesKey); 3916 3917 if (dwError != ERROR_SUCCESS) 3918 return dwError; 3919 3920 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for 3921 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded 3922 are the same for both. Verified in WINXP. */ 3923 3924 /* First determine the bytes needed and get the number of dependent services*/ 3925 dwError = Int_EnumDependentServicesW(hServicesKey, 3926 lpService, 3927 dwServiceState, 3928 NULL, 3929 pcbBytesNeeded, 3930 &dwServicesReturned); 3931 if (dwError != ERROR_SUCCESS) 3932 goto Done; 3933 3934 /* If buffer size is less than the bytes needed or pointer is null*/ 3935 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 3936 { 3937 dwError = ERROR_MORE_DATA; 3938 goto Done; 3939 } 3940 3941 /* Allocate memory for array of service pointers */ 3942 lpServicesArray = HeapAlloc(GetProcessHeap(), 3943 HEAP_ZERO_MEMORY, 3944 (dwServicesReturned + 1) * sizeof(PSERVICE)); 3945 if (!lpServicesArray) 3946 { 3947 DPRINT("Could not allocate a buffer!!\n"); 3948 dwError = ERROR_NOT_ENOUGH_MEMORY; 3949 goto Done; 3950 } 3951 3952 dwServicesReturned = 0; 3953 *pcbBytesNeeded = 0; 3954 3955 dwError = Int_EnumDependentServicesW(hServicesKey, 3956 lpService, 3957 dwServiceState, 3958 lpServicesArray, 3959 pcbBytesNeeded, 3960 &dwServicesReturned); 3961 if (dwError != ERROR_SUCCESS) 3962 { 3963 goto Done; 3964 } 3965 3966 lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices; 3967 lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA))); 3968 3969 /* Copy EnumDepenedentService to Buffer */ 3970 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 3971 { 3972 lpService = lpServicesArray[dwServiceCount]; 3973 3974 /* Copy the status info */ 3975 memcpy(&lpServicesPtr->ServiceStatus, 3976 &lpService->Status, 3977 sizeof(SERVICE_STATUS)); 3978 3979 /* Copy display name */ 3980 WideCharToMultiByte(CP_ACP, 3981 0, 3982 lpService->lpDisplayName, 3983 -1, 3984 lpStr, 3985 (int)wcslen(lpService->lpDisplayName), 3986 0, 3987 0); 3988 lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 3989 lpStr += strlen(lpStr) + 1; 3990 3991 /* Copy service name */ 3992 WideCharToMultiByte(CP_ACP, 3993 0, 3994 lpService->lpServiceName, 3995 -1, 3996 lpStr, 3997 (int)wcslen(lpService->lpServiceName), 3998 0, 3999 0); 4000 lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 4001 lpStr += strlen(lpStr) + 1; 4002 4003 lpServicesPtr++; 4004 } 4005 4006 *lpServicesReturned = dwServicesReturned; 4007 4008 Done: 4009 if (lpServicesArray) 4010 HeapFree(GetProcessHeap(), 0, lpServicesArray); 4011 4012 RegCloseKey(hServicesKey); 4013 4014 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError); 4015 4016 return dwError; 4017 } 4018 4019 4020 /* Function 26 */ 4021 DWORD 4022 WINAPI 4023 REnumServicesStatusA( 4024 SC_RPC_HANDLE hSCManager, 4025 DWORD dwServiceType, 4026 DWORD dwServiceState, 4027 LPBYTE lpBuffer, 4028 DWORD dwBufSize, 4029 LPBOUNDED_DWORD_256K pcbBytesNeeded, 4030 LPBOUNDED_DWORD_256K lpServicesReturned, 4031 LPBOUNDED_DWORD_256K lpResumeHandle) 4032 { 4033 LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL; 4034 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW; 4035 LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL; 4036 LPWSTR lpStringPtrW; 4037 LPSTR lpStringPtrA; 4038 DWORD dwError; 4039 DWORD dwServiceCount; 4040 4041 DPRINT("REnumServicesStatusA() called\n"); 4042 4043 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 4044 { 4045 return ERROR_INVALID_ADDRESS; 4046 } 4047 4048 if ((dwBufSize > 0) && (lpBuffer)) 4049 { 4050 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize); 4051 if (!lpStatusPtrW) 4052 { 4053 DPRINT("Failed to allocate buffer!\n"); 4054 return ERROR_NOT_ENOUGH_MEMORY; 4055 } 4056 } 4057 4058 dwError = REnumServicesStatusW(hSCManager, 4059 dwServiceType, 4060 dwServiceState, 4061 (LPBYTE)lpStatusPtrW, 4062 dwBufSize, 4063 pcbBytesNeeded, 4064 lpServicesReturned, 4065 lpResumeHandle); 4066 4067 /* if no services were returned then we are Done */ 4068 if (*lpServicesReturned == 0) 4069 goto Done; 4070 4071 lpStatusPtrIncrW = lpStatusPtrW; 4072 lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer; 4073 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 4074 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA)); 4075 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 4076 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW)); 4077 4078 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 4079 { 4080 /* Copy the service name */ 4081 WideCharToMultiByte(CP_ACP, 4082 0, 4083 lpStringPtrW, 4084 -1, 4085 lpStringPtrA, 4086 (int)wcslen(lpStringPtrW), 4087 0, 4088 0); 4089 4090 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 4091 lpStringPtrA += wcslen(lpStringPtrW) + 1; 4092 lpStringPtrW += wcslen(lpStringPtrW) + 1; 4093 4094 /* Copy the display name */ 4095 WideCharToMultiByte(CP_ACP, 4096 0, 4097 lpStringPtrW, 4098 -1, 4099 lpStringPtrA, 4100 (int)wcslen(lpStringPtrW), 4101 0, 4102 0); 4103 4104 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 4105 lpStringPtrA += wcslen(lpStringPtrW) + 1; 4106 lpStringPtrW += wcslen(lpStringPtrW) + 1; 4107 4108 /* Copy the status information */ 4109 memcpy(&lpStatusPtrA->ServiceStatus, 4110 &lpStatusPtrIncrW->ServiceStatus, 4111 sizeof(SERVICE_STATUS)); 4112 4113 lpStatusPtrIncrW++; 4114 lpStatusPtrA++; 4115 } 4116 4117 Done: 4118 if (lpStatusPtrW) 4119 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 4120 4121 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError); 4122 4123 return dwError; 4124 } 4125 4126 4127 /* Function 27 */ 4128 DWORD 4129 WINAPI 4130 ROpenSCManagerA( 4131 LPSTR lpMachineName, 4132 LPSTR lpDatabaseName, 4133 DWORD dwDesiredAccess, 4134 LPSC_RPC_HANDLE lpScHandle) 4135 { 4136 UNICODE_STRING MachineName; 4137 UNICODE_STRING DatabaseName; 4138 DWORD dwError; 4139 4140 DPRINT("ROpenSCManagerA() called\n"); 4141 4142 if (lpMachineName) 4143 RtlCreateUnicodeStringFromAsciiz(&MachineName, 4144 lpMachineName); 4145 4146 if (lpDatabaseName) 4147 RtlCreateUnicodeStringFromAsciiz(&DatabaseName, 4148 lpDatabaseName); 4149 4150 dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL, 4151 lpDatabaseName ? DatabaseName.Buffer : NULL, 4152 dwDesiredAccess, 4153 lpScHandle); 4154 4155 if (lpMachineName) 4156 RtlFreeUnicodeString(&MachineName); 4157 4158 if (lpDatabaseName) 4159 RtlFreeUnicodeString(&DatabaseName); 4160 4161 return dwError; 4162 } 4163 4164 4165 /* Function 28 */ 4166 DWORD 4167 WINAPI 4168 ROpenServiceA( 4169 SC_RPC_HANDLE hSCManager, 4170 LPSTR lpServiceName, 4171 DWORD dwDesiredAccess, 4172 LPSC_RPC_HANDLE lpServiceHandle) 4173 { 4174 UNICODE_STRING ServiceName; 4175 DWORD dwError; 4176 4177 DPRINT("ROpenServiceA() called\n"); 4178 4179 if (lpServiceName) 4180 RtlCreateUnicodeStringFromAsciiz(&ServiceName, 4181 lpServiceName); 4182 4183 dwError = ROpenServiceW(hSCManager, 4184 lpServiceName ? ServiceName.Buffer : NULL, 4185 dwDesiredAccess, 4186 lpServiceHandle); 4187 4188 if (lpServiceName) 4189 RtlFreeUnicodeString(&ServiceName); 4190 4191 return dwError; 4192 } 4193 4194 4195 /* Function 29 */ 4196 DWORD 4197 WINAPI 4198 RQueryServiceConfigA( 4199 SC_RPC_HANDLE hService, 4200 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig, 4201 DWORD cbBufSize, 4202 LPBOUNDED_DWORD_8K pcbBytesNeeded) 4203 { 4204 LPQUERY_SERVICE_CONFIGA lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)lpBuf; 4205 DWORD dwError = ERROR_SUCCESS; 4206 PSERVICE_HANDLE hSvc; 4207 PSERVICE lpService = NULL; 4208 HKEY hServiceKey = NULL; 4209 LPWSTR lpImagePath = NULL; 4210 LPWSTR lpServiceStartName = NULL; 4211 LPWSTR lpDependencies = NULL; 4212 DWORD dwDependenciesLength = 0; 4213 DWORD dwRequiredSize; 4214 CHAR lpEmptyString[]={0,0}; 4215 LPSTR lpStr; 4216 4217 DPRINT("RQueryServiceConfigA() called\n"); 4218 4219 if (ScmShutdown) 4220 return ERROR_SHUTDOWN_IN_PROGRESS; 4221 4222 hSvc = ScmGetServiceFromHandle(hService); 4223 if (hSvc == NULL) 4224 { 4225 DPRINT1("Invalid service handle!\n"); 4226 return ERROR_INVALID_HANDLE; 4227 } 4228 4229 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 4230 SERVICE_QUERY_CONFIG)) 4231 { 4232 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 4233 return ERROR_ACCESS_DENIED; 4234 } 4235 4236 lpService = hSvc->ServiceEntry; 4237 if (lpService == NULL) 4238 { 4239 DPRINT("lpService == NULL!\n"); 4240 return ERROR_INVALID_HANDLE; 4241 } 4242 4243 /* Lock the service database shared */ 4244 ScmLockDatabaseShared(); 4245 4246 dwError = ScmOpenServiceKey(lpService->lpServiceName, 4247 KEY_READ, 4248 &hServiceKey); 4249 if (dwError != ERROR_SUCCESS) 4250 goto Done; 4251 4252 /* Read the image path */ 4253 dwError = ScmReadString(hServiceKey, 4254 L"ImagePath", 4255 &lpImagePath); 4256 if (dwError != ERROR_SUCCESS) 4257 goto Done; 4258 4259 /* Read the service start name */ 4260 ScmReadString(hServiceKey, 4261 L"ObjectName", 4262 &lpServiceStartName); 4263 4264 /* Read the dependencies */ 4265 ScmReadDependencies(hServiceKey, 4266 &lpDependencies, 4267 &dwDependenciesLength); 4268 4269 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA); 4270 4271 if (lpImagePath != NULL) 4272 dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1); 4273 else 4274 dwRequiredSize += 2; 4275 4276 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 4277 dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1); 4278 else 4279 dwRequiredSize += 2; 4280 4281 /* Add Dependencies length */ 4282 if (lpDependencies != NULL) 4283 dwRequiredSize += dwDependenciesLength; 4284 else 4285 dwRequiredSize += 2; 4286 4287 if (lpServiceStartName != NULL) 4288 dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1); 4289 else 4290 dwRequiredSize += 2; 4291 4292 if (lpService->lpDisplayName != NULL) 4293 dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1); 4294 else 4295 dwRequiredSize += 2; 4296 4297 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 4298 { 4299 dwError = ERROR_INSUFFICIENT_BUFFER; 4300 } 4301 else 4302 { 4303 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType; 4304 lpServiceConfig->dwStartType = lpService->dwStartType; 4305 lpServiceConfig->dwErrorControl = lpService->dwErrorControl; 4306 lpServiceConfig->dwTagId = lpService->dwTag; 4307 4308 lpStr = (LPSTR)(lpServiceConfig + 1); 4309 4310 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings. 4311 Verified in WINXP */ 4312 4313 if (lpImagePath) 4314 { 4315 WideCharToMultiByte(CP_ACP, 4316 0, 4317 lpImagePath, 4318 -1, 4319 lpStr, 4320 (int)(wcslen(lpImagePath) + 1), 4321 0, 4322 0); 4323 } 4324 else 4325 { 4326 strcpy(lpStr, lpEmptyString); 4327 } 4328 4329 lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4330 lpStr += (strlen((LPSTR)lpStr) + 1); 4331 4332 if (lpService->lpGroup && lpService->lpGroup->lpGroupName) 4333 { 4334 WideCharToMultiByte(CP_ACP, 4335 0, 4336 lpService->lpGroup->lpGroupName, 4337 -1, 4338 lpStr, 4339 (int)(wcslen(lpService->lpGroup->lpGroupName) + 1), 4340 0, 4341 0); 4342 } 4343 else 4344 { 4345 strcpy(lpStr, lpEmptyString); 4346 } 4347 4348 lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4349 lpStr += (strlen(lpStr) + 1); 4350 4351 /* Append Dependencies */ 4352 if (lpDependencies) 4353 { 4354 WideCharToMultiByte(CP_ACP, 4355 0, 4356 lpDependencies, 4357 dwDependenciesLength, 4358 lpStr, 4359 dwDependenciesLength, 4360 0, 4361 0); 4362 } 4363 else 4364 { 4365 strcpy(lpStr, lpEmptyString); 4366 } 4367 4368 lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4369 if (lpDependencies) 4370 lpStr += dwDependenciesLength; 4371 else 4372 lpStr += (strlen(lpStr) + 1); 4373 4374 if (lpServiceStartName) 4375 { 4376 WideCharToMultiByte(CP_ACP, 4377 0, 4378 lpServiceStartName, 4379 -1, 4380 lpStr, 4381 (int)(wcslen(lpServiceStartName) + 1), 4382 0, 4383 0); 4384 } 4385 else 4386 { 4387 strcpy(lpStr, lpEmptyString); 4388 } 4389 4390 lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4391 lpStr += (strlen(lpStr) + 1); 4392 4393 if (lpService->lpDisplayName) 4394 { 4395 WideCharToMultiByte(CP_ACP, 4396 0, 4397 lpService->lpDisplayName, 4398 -1, 4399 lpStr, 4400 (int)(wcslen(lpService->lpDisplayName) + 1), 4401 0, 4402 0); 4403 } 4404 else 4405 { 4406 strcpy(lpStr, lpEmptyString); 4407 } 4408 4409 lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4410 } 4411 4412 if (pcbBytesNeeded != NULL) 4413 *pcbBytesNeeded = dwRequiredSize; 4414 4415 Done: 4416 /* Unlock the service database */ 4417 ScmUnlockDatabase(); 4418 4419 if (lpImagePath != NULL) 4420 HeapFree(GetProcessHeap(), 0, lpImagePath); 4421 4422 if (lpServiceStartName != NULL) 4423 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 4424 4425 if (lpDependencies != NULL) 4426 HeapFree(GetProcessHeap(), 0, lpDependencies); 4427 4428 if (hServiceKey != NULL) 4429 RegCloseKey(hServiceKey); 4430 4431 DPRINT("RQueryServiceConfigA() done\n"); 4432 4433 return dwError; 4434 } 4435 4436 4437 /* Function 30 */ 4438 DWORD 4439 WINAPI 4440 RQueryServiceLockStatusA( 4441 SC_RPC_HANDLE hSCManager, 4442 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, 4443 DWORD cbBufSize, 4444 LPBOUNDED_DWORD_4K pcbBytesNeeded) 4445 { 4446 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSA)lpBuf; 4447 PMANAGER_HANDLE hMgr; 4448 DWORD dwRequiredSize; 4449 4450 if (!lpLockStatus || !pcbBytesNeeded) 4451 return ERROR_INVALID_PARAMETER; 4452 4453 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 4454 if (hMgr == NULL) 4455 { 4456 DPRINT1("Invalid service manager handle!\n"); 4457 return ERROR_INVALID_HANDLE; 4458 } 4459 4460 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 4461 SC_MANAGER_QUERY_LOCK_STATUS)) 4462 { 4463 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess); 4464 return ERROR_ACCESS_DENIED; 4465 } 4466 4467 /* FIXME: we need to compute instead the real length of the owner name */ 4468 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(CHAR); 4469 *pcbBytesNeeded = dwRequiredSize; 4470 4471 if (cbBufSize < dwRequiredSize) 4472 return ERROR_INSUFFICIENT_BUFFER; 4473 4474 ScmQueryServiceLockStatusA(lpLockStatus); 4475 4476 return ERROR_SUCCESS; 4477 } 4478 4479 4480 /* Function 31 */ 4481 DWORD 4482 WINAPI 4483 RStartServiceA( 4484 SC_RPC_HANDLE hService, 4485 DWORD argc, 4486 LPSTRING_PTRSA argv) 4487 { 4488 DWORD dwError = ERROR_SUCCESS; 4489 PSERVICE_HANDLE hSvc; 4490 PSERVICE lpService = NULL; 4491 LPWSTR *lpVector = NULL; 4492 DWORD i; 4493 DWORD dwLength; 4494 4495 DPRINT("RStartServiceA() called\n"); 4496 4497 if (ScmShutdown) 4498 return ERROR_SHUTDOWN_IN_PROGRESS; 4499 4500 hSvc = ScmGetServiceFromHandle(hService); 4501 if (hSvc == NULL) 4502 { 4503 DPRINT1("Invalid service handle!\n"); 4504 return ERROR_INVALID_HANDLE; 4505 } 4506 4507 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 4508 SERVICE_START)) 4509 { 4510 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 4511 return ERROR_ACCESS_DENIED; 4512 } 4513 4514 lpService = hSvc->ServiceEntry; 4515 if (lpService == NULL) 4516 { 4517 DPRINT("lpService == NULL!\n"); 4518 return ERROR_INVALID_HANDLE; 4519 } 4520 4521 if (lpService->dwStartType == SERVICE_DISABLED) 4522 return ERROR_SERVICE_DISABLED; 4523 4524 if (lpService->bDeleted) 4525 return ERROR_SERVICE_MARKED_FOR_DELETE; 4526 4527 /* Build a Unicode argument vector */ 4528 if (argc > 0) 4529 { 4530 lpVector = HeapAlloc(GetProcessHeap(), 4531 HEAP_ZERO_MEMORY, 4532 argc * sizeof(LPWSTR)); 4533 if (lpVector == NULL) 4534 return ERROR_NOT_ENOUGH_MEMORY; 4535 4536 for (i = 0; i < argc; i++) 4537 { 4538 dwLength = MultiByteToWideChar(CP_ACP, 4539 0, 4540 ((LPSTR*)argv)[i], 4541 -1, 4542 NULL, 4543 0); 4544 4545 lpVector[i] = HeapAlloc(GetProcessHeap(), 4546 HEAP_ZERO_MEMORY, 4547 dwLength * sizeof(WCHAR)); 4548 if (lpVector[i] == NULL) 4549 { 4550 dwError = ERROR_NOT_ENOUGH_MEMORY; 4551 goto done; 4552 } 4553 4554 MultiByteToWideChar(CP_ACP, 4555 0, 4556 ((LPSTR*)argv)[i], 4557 -1, 4558 lpVector[i], 4559 dwLength); 4560 } 4561 } 4562 4563 /* Start the service */ 4564 dwError = ScmStartService(lpService, argc, lpVector); 4565 4566 done: 4567 /* Free the Unicode argument vector */ 4568 if (lpVector != NULL) 4569 { 4570 for (i = 0; i < argc; i++) 4571 { 4572 if (lpVector[i] != NULL) 4573 HeapFree(GetProcessHeap(), 0, lpVector[i]); 4574 } 4575 HeapFree(GetProcessHeap(), 0, lpVector); 4576 } 4577 4578 return dwError; 4579 } 4580 4581 4582 /* Function 32 */ 4583 DWORD 4584 WINAPI 4585 RGetServiceDisplayNameA( 4586 SC_RPC_HANDLE hSCManager, 4587 LPCSTR lpServiceName, 4588 LPSTR lpDisplayName, 4589 LPBOUNDED_DWORD_4K lpcchBuffer) 4590 { 4591 // PMANAGER_HANDLE hManager; 4592 PSERVICE lpService = NULL; 4593 DWORD dwLength; 4594 DWORD dwError; 4595 LPWSTR lpServiceNameW; 4596 4597 DPRINT("RGetServiceDisplayNameA() called\n"); 4598 DPRINT("hSCManager = %p\n", hSCManager); 4599 DPRINT("lpServiceName: %s\n", lpServiceName); 4600 DPRINT("lpDisplayName: %p\n", lpDisplayName); 4601 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 4602 4603 // hManager = (PMANAGER_HANDLE)hSCManager; 4604 // if (hManager->Handle.Tag != MANAGER_TAG) 4605 // { 4606 // DPRINT("Invalid manager handle!\n"); 4607 // return ERROR_INVALID_HANDLE; 4608 // } 4609 4610 if (lpServiceName != NULL) 4611 { 4612 dwLength = (DWORD)(strlen(lpServiceName) + 1); 4613 lpServiceNameW = HeapAlloc(GetProcessHeap(), 4614 HEAP_ZERO_MEMORY, 4615 dwLength * sizeof(WCHAR)); 4616 if (!lpServiceNameW) 4617 return ERROR_NOT_ENOUGH_MEMORY; 4618 4619 MultiByteToWideChar(CP_ACP, 4620 0, 4621 lpServiceName, 4622 -1, 4623 lpServiceNameW, 4624 dwLength); 4625 4626 lpService = ScmGetServiceEntryByName(lpServiceNameW); 4627 4628 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 4629 } 4630 4631 if (lpService == NULL) 4632 { 4633 DPRINT("Could not find a service!\n"); 4634 4635 /* If the service could not be found and lpcchBuffer is 0, windows 4636 puts null in lpDisplayName and puts 1 in lpcchBuffer */ 4637 if (*lpcchBuffer == 0) 4638 { 4639 *lpcchBuffer = 1; 4640 if (lpDisplayName != NULL) 4641 { 4642 *lpDisplayName = 0; 4643 } 4644 } 4645 return ERROR_SERVICE_DOES_NOT_EXIST; 4646 } 4647 4648 if (!lpService->lpDisplayName) 4649 { 4650 dwLength = (DWORD)wcslen(lpService->lpServiceName); 4651 if (lpDisplayName != NULL && 4652 *lpcchBuffer > dwLength) 4653 { 4654 WideCharToMultiByte(CP_ACP, 4655 0, 4656 lpService->lpServiceName, 4657 (int)wcslen(lpService->lpServiceName), 4658 lpDisplayName, 4659 dwLength + 1, 4660 NULL, 4661 NULL); 4662 return ERROR_SUCCESS; 4663 } 4664 } 4665 else 4666 { 4667 dwLength = (DWORD)wcslen(lpService->lpDisplayName); 4668 if (lpDisplayName != NULL && 4669 *lpcchBuffer > dwLength) 4670 { 4671 WideCharToMultiByte(CP_ACP, 4672 0, 4673 lpService->lpDisplayName, 4674 (int)wcslen(lpService->lpDisplayName), 4675 lpDisplayName, 4676 dwLength + 1, 4677 NULL, 4678 NULL); 4679 return ERROR_SUCCESS; 4680 } 4681 } 4682 4683 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 4684 4685 *lpcchBuffer = dwLength * 2; 4686 4687 return dwError; 4688 } 4689 4690 4691 /* Function 33 */ 4692 DWORD 4693 WINAPI 4694 RGetServiceKeyNameA( 4695 SC_RPC_HANDLE hSCManager, 4696 LPCSTR lpDisplayName, 4697 LPSTR lpServiceName, 4698 LPBOUNDED_DWORD_4K lpcchBuffer) 4699 { 4700 PSERVICE lpService; 4701 DWORD dwLength; 4702 DWORD dwError; 4703 LPWSTR lpDisplayNameW; 4704 4705 DPRINT("RGetServiceKeyNameA() called\n"); 4706 DPRINT("hSCManager = %p\n", hSCManager); 4707 DPRINT("lpDisplayName: %s\n", lpDisplayName); 4708 DPRINT("lpServiceName: %p\n", lpServiceName); 4709 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 4710 4711 dwLength = (DWORD)(strlen(lpDisplayName) + 1); 4712 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 4713 HEAP_ZERO_MEMORY, 4714 dwLength * sizeof(WCHAR)); 4715 if (!lpDisplayNameW) 4716 return ERROR_NOT_ENOUGH_MEMORY; 4717 4718 MultiByteToWideChar(CP_ACP, 4719 0, 4720 lpDisplayName, 4721 -1, 4722 lpDisplayNameW, 4723 dwLength); 4724 4725 lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW); 4726 4727 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 4728 4729 if (lpService == NULL) 4730 { 4731 DPRINT("Could not find the service!\n"); 4732 4733 /* If the service could not be found and lpcchBuffer is 0, 4734 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */ 4735 if (*lpcchBuffer == 0) 4736 { 4737 *lpcchBuffer = 1; 4738 if (lpServiceName != NULL) 4739 { 4740 *lpServiceName = 0; 4741 } 4742 } 4743 4744 return ERROR_SERVICE_DOES_NOT_EXIST; 4745 } 4746 4747 dwLength = (DWORD)wcslen(lpService->lpServiceName); 4748 if (lpServiceName != NULL && 4749 *lpcchBuffer > dwLength) 4750 { 4751 WideCharToMultiByte(CP_ACP, 4752 0, 4753 lpService->lpServiceName, 4754 (int)wcslen(lpService->lpServiceName), 4755 lpServiceName, 4756 dwLength + 1, 4757 NULL, 4758 NULL); 4759 return ERROR_SUCCESS; 4760 } 4761 4762 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 4763 4764 *lpcchBuffer = dwLength * 2; 4765 4766 return dwError; 4767 } 4768 4769 4770 /* Function 34 */ 4771 DWORD 4772 WINAPI 4773 RI_ScGetCurrentGroupStateW( 4774 SC_RPC_HANDLE hSCManager, 4775 LPWSTR lpLoadOrderGroup, 4776 LPDWORD lpState) 4777 { 4778 PMANAGER_HANDLE hManager; 4779 PSERVICE_GROUP pServiceGroup; 4780 DWORD dwError = ERROR_SUCCESS; 4781 4782 DPRINT("RI_ScGetCurrentGroupStateW() called\n"); 4783 4784 if (ScmShutdown) 4785 return ERROR_SHUTDOWN_IN_PROGRESS; 4786 4787 hManager = ScmGetServiceManagerFromHandle(hSCManager); 4788 if (hManager == NULL) 4789 { 4790 DPRINT1("Invalid service manager handle!\n"); 4791 return ERROR_INVALID_HANDLE; 4792 } 4793 4794 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */ 4795 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 4796 SC_MANAGER_ENUMERATE_SERVICE)) 4797 { 4798 DPRINT("Insufficient access rights! 0x%lx\n", 4799 hManager->Handle.DesiredAccess); 4800 return ERROR_ACCESS_DENIED; 4801 } 4802 4803 /* Lock the service database shared */ 4804 ScmLockDatabaseShared(); 4805 4806 /* Get the group list entry */ 4807 pServiceGroup = ScmGetServiceGroupByName(lpLoadOrderGroup); 4808 if (pServiceGroup == NULL) 4809 { 4810 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 4811 goto done; 4812 } 4813 4814 /* FIXME: Return the group state */ 4815 *lpState = 0; 4816 4817 done: 4818 /* Unlock the service database */ 4819 ScmUnlockDatabase(); 4820 4821 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError); 4822 4823 return dwError; 4824 } 4825 4826 4827 /* Function 35 */ 4828 DWORD 4829 WINAPI 4830 REnumServiceGroupW( 4831 SC_RPC_HANDLE hSCManager, 4832 DWORD dwServiceType, 4833 DWORD dwServiceState, 4834 LPBYTE lpBuffer, 4835 DWORD cbBufSize, 4836 LPBOUNDED_DWORD_256K pcbBytesNeeded, 4837 LPBOUNDED_DWORD_256K lpServicesReturned, 4838 LPBOUNDED_DWORD_256K lpResumeIndex, 4839 LPCWSTR pszGroupName) 4840 { 4841 PMANAGER_HANDLE hManager; 4842 PSERVICE lpService; 4843 DWORD dwError = ERROR_SUCCESS; 4844 PLIST_ENTRY ServiceEntry; 4845 PSERVICE CurrentService; 4846 DWORD dwState; 4847 DWORD dwRequiredSize; 4848 DWORD dwServiceCount; 4849 DWORD dwSize; 4850 DWORD dwLastResumeCount = 0; 4851 LPENUM_SERVICE_STATUSW lpStatusPtr; 4852 LPWSTR lpStringPtr; 4853 4854 DPRINT("REnumServiceGroupW() called\n"); 4855 4856 if (ScmShutdown) 4857 return ERROR_SHUTDOWN_IN_PROGRESS; 4858 4859 hManager = ScmGetServiceManagerFromHandle(hSCManager); 4860 if (hManager == NULL) 4861 { 4862 DPRINT1("Invalid service manager handle!\n"); 4863 return ERROR_INVALID_HANDLE; 4864 } 4865 4866 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 4867 { 4868 return ERROR_INVALID_ADDRESS; 4869 } 4870 4871 *pcbBytesNeeded = 0; 4872 *lpServicesReturned = 0; 4873 4874 if ((dwServiceType == 0) || 4875 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0)) 4876 { 4877 DPRINT("Not a valid Service Type!\n"); 4878 return ERROR_INVALID_PARAMETER; 4879 } 4880 4881 if ((dwServiceState == 0) || 4882 ((dwServiceState & ~SERVICE_STATE_ALL) != 0)) 4883 { 4884 DPRINT("Not a valid Service State!\n"); 4885 return ERROR_INVALID_PARAMETER; 4886 } 4887 4888 /* Check access rights */ 4889 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 4890 SC_MANAGER_ENUMERATE_SERVICE)) 4891 { 4892 DPRINT("Insufficient access rights! 0x%lx\n", 4893 hManager->Handle.DesiredAccess); 4894 return ERROR_ACCESS_DENIED; 4895 } 4896 4897 if (lpResumeIndex) 4898 dwLastResumeCount = *lpResumeIndex; 4899 4900 /* Lock the service database shared */ 4901 ScmLockDatabaseShared(); 4902 4903 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 4904 if (lpService == NULL) 4905 { 4906 dwError = ERROR_SUCCESS; 4907 goto Done; 4908 } 4909 4910 dwRequiredSize = 0; 4911 dwServiceCount = 0; 4912 4913 for (ServiceEntry = &lpService->ServiceListEntry; 4914 ServiceEntry != &ServiceListHead; 4915 ServiceEntry = ServiceEntry->Flink) 4916 { 4917 CurrentService = CONTAINING_RECORD(ServiceEntry, 4918 SERVICE, 4919 ServiceListEntry); 4920 4921 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 4922 continue; 4923 4924 dwState = SERVICE_ACTIVE; 4925 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 4926 dwState = SERVICE_INACTIVE; 4927 4928 if ((dwState & dwServiceState) == 0) 4929 continue; 4930 4931 if (pszGroupName) 4932 { 4933 if (*pszGroupName == 0) 4934 { 4935 if (CurrentService->lpGroup != NULL) 4936 continue; 4937 } 4938 else 4939 { 4940 if ((CurrentService->lpGroup == NULL) || 4941 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 4942 continue; 4943 } 4944 } 4945 4946 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 4947 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 4948 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 4949 4950 if (dwRequiredSize + dwSize > cbBufSize) 4951 { 4952 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 4953 break; 4954 } 4955 4956 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 4957 dwRequiredSize += dwSize; 4958 dwServiceCount++; 4959 dwLastResumeCount = CurrentService->dwResumeCount; 4960 } 4961 4962 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 4963 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 4964 4965 for (; 4966 ServiceEntry != &ServiceListHead; 4967 ServiceEntry = ServiceEntry->Flink) 4968 { 4969 CurrentService = CONTAINING_RECORD(ServiceEntry, 4970 SERVICE, 4971 ServiceListEntry); 4972 4973 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 4974 continue; 4975 4976 dwState = SERVICE_ACTIVE; 4977 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 4978 dwState = SERVICE_INACTIVE; 4979 4980 if ((dwState & dwServiceState) == 0) 4981 continue; 4982 4983 if (pszGroupName) 4984 { 4985 if (*pszGroupName == 0) 4986 { 4987 if (CurrentService->lpGroup != NULL) 4988 continue; 4989 } 4990 else 4991 { 4992 if ((CurrentService->lpGroup == NULL) || 4993 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 4994 continue; 4995 } 4996 } 4997 4998 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) + 4999 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 5000 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 5001 5002 dwError = ERROR_MORE_DATA; 5003 } 5004 5005 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 5006 5007 if (lpResumeIndex) 5008 *lpResumeIndex = dwLastResumeCount; 5009 5010 *lpServicesReturned = dwServiceCount; 5011 *pcbBytesNeeded = dwRequiredSize; 5012 5013 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer; 5014 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 5015 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW)); 5016 5017 dwRequiredSize = 0; 5018 for (ServiceEntry = &lpService->ServiceListEntry; 5019 ServiceEntry != &ServiceListHead; 5020 ServiceEntry = ServiceEntry->Flink) 5021 { 5022 CurrentService = CONTAINING_RECORD(ServiceEntry, 5023 SERVICE, 5024 ServiceListEntry); 5025 5026 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 5027 continue; 5028 5029 dwState = SERVICE_ACTIVE; 5030 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 5031 dwState = SERVICE_INACTIVE; 5032 5033 if ((dwState & dwServiceState) == 0) 5034 continue; 5035 5036 if (pszGroupName) 5037 { 5038 if (*pszGroupName == 0) 5039 { 5040 if (CurrentService->lpGroup != NULL) 5041 continue; 5042 } 5043 else 5044 { 5045 if ((CurrentService->lpGroup == NULL) || 5046 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 5047 continue; 5048 } 5049 } 5050 5051 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 5052 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 5053 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 5054 5055 if (dwRequiredSize + dwSize > cbBufSize) 5056 break; 5057 5058 /* Copy the service name */ 5059 wcscpy(lpStringPtr, CurrentService->lpServiceName); 5060 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 5061 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 5062 5063 /* Copy the display name */ 5064 wcscpy(lpStringPtr, CurrentService->lpDisplayName); 5065 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 5066 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 5067 5068 /* Copy the status information */ 5069 memcpy(&lpStatusPtr->ServiceStatus, 5070 &CurrentService->Status, 5071 sizeof(SERVICE_STATUS)); 5072 5073 lpStatusPtr++; 5074 dwRequiredSize += dwSize; 5075 } 5076 5077 if (dwError == ERROR_SUCCESS) 5078 { 5079 *pcbBytesNeeded = 0; 5080 if (lpResumeIndex) *lpResumeIndex = 0; 5081 } 5082 5083 Done: 5084 /* Unlock the service database */ 5085 ScmUnlockDatabase(); 5086 5087 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError); 5088 5089 return dwError; 5090 } 5091 5092 5093 /* Function 36 */ 5094 DWORD 5095 WINAPI 5096 RChangeServiceConfig2A( 5097 SC_RPC_HANDLE hService, 5098 SC_RPC_CONFIG_INFOA Info) 5099 { 5100 SC_RPC_CONFIG_INFOW InfoW; 5101 DWORD dwRet, dwLength; 5102 PVOID ptr = NULL; 5103 5104 DPRINT("RChangeServiceConfig2A() called\n"); 5105 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 5106 5107 InfoW.dwInfoLevel = Info.dwInfoLevel; 5108 5109 if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5110 { 5111 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW; 5112 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA; 5113 5114 lpServiceDescriptionA = Info.psd; 5115 5116 if (lpServiceDescriptionA && 5117 lpServiceDescriptionA->lpDescription) 5118 { 5119 dwLength = (DWORD)((strlen(lpServiceDescriptionA->lpDescription) + 1) * sizeof(WCHAR)); 5120 5121 lpServiceDescriptionW = HeapAlloc(GetProcessHeap(), 5122 HEAP_ZERO_MEMORY, 5123 dwLength + sizeof(SERVICE_DESCRIPTIONW)); 5124 if (!lpServiceDescriptionW) 5125 { 5126 return ERROR_NOT_ENOUGH_MEMORY; 5127 } 5128 5129 lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1); 5130 5131 MultiByteToWideChar(CP_ACP, 5132 0, 5133 lpServiceDescriptionA->lpDescription, 5134 -1, 5135 lpServiceDescriptionW->lpDescription, 5136 dwLength); 5137 5138 ptr = lpServiceDescriptionW; 5139 InfoW.psd = lpServiceDescriptionW; 5140 } 5141 } 5142 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5143 { 5144 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; 5145 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; 5146 DWORD dwRebootLen = 0; 5147 DWORD dwCommandLen = 0; 5148 DWORD dwActionArrayLen = 0; 5149 LPWSTR lpStr = NULL; 5150 5151 lpServiceFailureActionsA = Info.psfa; 5152 5153 if (lpServiceFailureActionsA) 5154 { 5155 /* 5156 * The following code is inspired by the 5157 * SERVICE_CONFIG_FAILURE_ACTIONS case of 5158 * the RQueryServiceConfig2W function. 5159 */ 5160 5161 /* Retrieve the needed length for the two data strings */ 5162 if (lpServiceFailureActionsA->lpRebootMsg) 5163 { 5164 dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR)); 5165 } 5166 if (lpServiceFailureActionsA->lpCommand) 5167 { 5168 dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR)); 5169 } 5170 5171 /* 5172 * Retrieve the size of the lpsaActions array if needed. 5173 * We will copy the lpsaActions array only if there is at 5174 * least one action AND that the original array is valid. 5175 */ 5176 if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions) 5177 { 5178 dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION); 5179 } 5180 5181 /* Compute the total length for the UNICODE structure, including data */ 5182 dwLength = sizeof(SERVICE_FAILURE_ACTIONSW) + 5183 dwActionArrayLen + dwRebootLen + dwCommandLen; 5184 5185 /* Allocate the structure */ 5186 lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(), 5187 HEAP_ZERO_MEMORY, 5188 dwLength); 5189 if (!lpServiceFailureActionsW) 5190 { 5191 return ERROR_NOT_ENOUGH_MEMORY; 5192 } 5193 5194 /* Copy the members */ 5195 lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; 5196 lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; 5197 5198 /* Copy the lpsaActions array if needed */ 5199 if (dwActionArrayLen > 0) 5200 { 5201 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */ 5202 lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1)); 5203 5204 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */ 5205 RtlCopyMemory(lpServiceFailureActionsW->lpsaActions, 5206 lpServiceFailureActionsA->lpsaActions, 5207 dwActionArrayLen); 5208 } 5209 else 5210 { 5211 /* No lpsaActions array */ 5212 lpServiceFailureActionsW->lpsaActions = NULL; 5213 } 5214 /* The data strings are stored just after the lpsaActions array */ 5215 lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen); 5216 5217 /* 5218 * Convert the data strings to UNICODE 5219 */ 5220 5221 lpServiceFailureActionsW->lpRebootMsg = NULL; 5222 lpServiceFailureActionsW->lpCommand = NULL; 5223 5224 if (dwRebootLen) 5225 { 5226 /* lpRebootMsg points just after the lpsaActions array */ 5227 lpServiceFailureActionsW->lpRebootMsg = lpStr; 5228 5229 MultiByteToWideChar(CP_ACP, 5230 0, 5231 lpServiceFailureActionsA->lpRebootMsg, 5232 -1, 5233 lpServiceFailureActionsW->lpRebootMsg, 5234 dwRebootLen); 5235 5236 lpStr += dwRebootLen / sizeof(WCHAR); 5237 } 5238 5239 if (dwCommandLen) 5240 { 5241 /* lpRebootMsg points just after the lpRebootMsg data string */ 5242 lpServiceFailureActionsW->lpCommand = lpStr; 5243 5244 MultiByteToWideChar(CP_ACP, 5245 0, 5246 lpServiceFailureActionsA->lpCommand, 5247 -1, 5248 lpServiceFailureActionsW->lpCommand, 5249 dwCommandLen); 5250 } 5251 5252 /* Set the pointers */ 5253 ptr = lpServiceFailureActionsW; 5254 InfoW.psfa = lpServiceFailureActionsW; 5255 } 5256 } 5257 5258 dwRet = RChangeServiceConfig2W(hService, InfoW); 5259 5260 HeapFree(GetProcessHeap(), 0, ptr); 5261 5262 return dwRet; 5263 } 5264 5265 5266 static DWORD 5267 ScmSetFailureActions(HKEY hServiceKey, 5268 LPSERVICE_FAILURE_ACTIONSW lpFailureActions) 5269 { 5270 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL; 5271 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL; 5272 DWORD dwRequiredSize = 0; 5273 DWORD dwType = 0; 5274 DWORD dwError; 5275 5276 /* There is nothing to be done if we have no failure actions */ 5277 if (lpFailureActions == NULL) 5278 return ERROR_SUCCESS; 5279 5280 /* 5281 * 1- Retrieve the original value of FailureActions. 5282 */ 5283 5284 /* Query value length */ 5285 dwError = RegQueryValueExW(hServiceKey, 5286 L"FailureActions", 5287 NULL, 5288 &dwType, 5289 NULL, 5290 &dwRequiredSize); 5291 if (dwError != ERROR_SUCCESS && 5292 dwError != ERROR_MORE_DATA && 5293 dwError != ERROR_FILE_NOT_FOUND) 5294 return dwError; 5295 5296 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize) 5297 : sizeof(SERVICE_FAILURE_ACTIONSW); 5298 5299 /* Initialize the read buffer */ 5300 lpReadBuffer = HeapAlloc(GetProcessHeap(), 5301 HEAP_ZERO_MEMORY, 5302 dwRequiredSize); 5303 if (lpReadBuffer == NULL) 5304 return ERROR_NOT_ENOUGH_MEMORY; 5305 5306 /* Now we can fill the read buffer */ 5307 if (dwError != ERROR_FILE_NOT_FOUND && 5308 dwType == REG_BINARY) 5309 { 5310 dwError = RegQueryValueExW(hServiceKey, 5311 L"FailureActions", 5312 NULL, 5313 NULL, 5314 (LPBYTE)lpReadBuffer, 5315 &dwRequiredSize); 5316 if (dwError != ERROR_SUCCESS && 5317 dwError != ERROR_FILE_NOT_FOUND) 5318 goto done; 5319 5320 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) 5321 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5322 } 5323 else 5324 { 5325 /* 5326 * The value of the error doesn't really matter, the only 5327 * important thing is that it must be != ERROR_SUCCESS. 5328 */ 5329 dwError = ERROR_INVALID_DATA; 5330 } 5331 5332 if (dwError == ERROR_SUCCESS) 5333 { 5334 lpReadBuffer->cActions = min(lpReadBuffer->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION)); 5335 lpReadBuffer->lpsaActions = (lpReadBuffer->cActions > 0 ? (LPSC_ACTION)(lpReadBuffer + 1) : NULL); 5336 } 5337 else 5338 { 5339 lpReadBuffer->dwResetPeriod = 0; 5340 lpReadBuffer->cActions = 0; 5341 lpReadBuffer->lpsaActions = NULL; 5342 } 5343 5344 lpReadBuffer->lpRebootMsg = NULL; 5345 lpReadBuffer->lpCommand = NULL; 5346 5347 /* 5348 * 2- Initialize the new value to set. 5349 */ 5350 5351 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5352 5353 if (lpFailureActions->lpsaActions == NULL) 5354 { 5355 /* 5356 * lpFailureActions->cActions is ignored. 5357 * Therefore we use the original values 5358 * of cActions and lpsaActions. 5359 */ 5360 dwRequiredSize += lpReadBuffer->cActions * sizeof(SC_ACTION); 5361 } 5362 else 5363 { 5364 /* 5365 * The reset period and array of failure actions 5366 * are deleted if lpFailureActions->cActions == 0 . 5367 */ 5368 dwRequiredSize += lpFailureActions->cActions * sizeof(SC_ACTION); 5369 } 5370 5371 lpWriteBuffer = HeapAlloc(GetProcessHeap(), 5372 HEAP_ZERO_MEMORY, 5373 dwRequiredSize); 5374 if (lpWriteBuffer == NULL) 5375 { 5376 dwError = ERROR_NOT_ENOUGH_MEMORY; 5377 goto done; 5378 } 5379 5380 /* Clean the pointers as they have no meaning when the structure is stored in the registry */ 5381 lpWriteBuffer->lpRebootMsg = NULL; 5382 lpWriteBuffer->lpCommand = NULL; 5383 lpWriteBuffer->lpsaActions = NULL; 5384 5385 /* Set the members */ 5386 if (lpFailureActions->lpsaActions == NULL) 5387 { 5388 /* 5389 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored. 5390 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions. 5391 */ 5392 lpWriteBuffer->dwResetPeriod = lpReadBuffer->dwResetPeriod; 5393 lpWriteBuffer->cActions = lpReadBuffer->cActions; 5394 5395 if (lpReadBuffer->lpsaActions != NULL) 5396 { 5397 memmove(lpWriteBuffer + 1, 5398 lpReadBuffer->lpsaActions, 5399 lpReadBuffer->cActions * sizeof(SC_ACTION)); 5400 } 5401 } 5402 else 5403 { 5404 if (lpFailureActions->cActions > 0) 5405 { 5406 lpWriteBuffer->dwResetPeriod = lpFailureActions->dwResetPeriod; 5407 lpWriteBuffer->cActions = lpFailureActions->cActions; 5408 5409 memmove(lpWriteBuffer + 1, 5410 lpFailureActions->lpsaActions, 5411 lpFailureActions->cActions * sizeof(SC_ACTION)); 5412 } 5413 else 5414 { 5415 /* The reset period and array of failure actions are deleted */ 5416 lpWriteBuffer->dwResetPeriod = 0; 5417 lpWriteBuffer->cActions = 0; 5418 } 5419 } 5420 5421 /* Save the new failure actions into the registry */ 5422 dwError = RegSetValueExW(hServiceKey, 5423 L"FailureActions", 5424 0, 5425 REG_BINARY, 5426 (LPBYTE)lpWriteBuffer, 5427 dwRequiredSize); 5428 5429 /* We modify the strings only in case of success.*/ 5430 if (dwError == ERROR_SUCCESS) 5431 { 5432 /* Modify the Reboot Message value, if specified */ 5433 if (lpFailureActions->lpRebootMsg != NULL) 5434 { 5435 /* If the Reboot Message is "" then we delete it */ 5436 if (*lpFailureActions->lpRebootMsg == 0) 5437 { 5438 DPRINT("Delete Reboot Message value\n"); 5439 RegDeleteValueW(hServiceKey, L"RebootMessage"); 5440 } 5441 else 5442 { 5443 DPRINT("Setting Reboot Message value %S\n", lpFailureActions->lpRebootMsg); 5444 RegSetValueExW(hServiceKey, 5445 L"RebootMessage", 5446 0, 5447 REG_SZ, 5448 (LPBYTE)lpFailureActions->lpRebootMsg, 5449 (DWORD)((wcslen(lpFailureActions->lpRebootMsg) + 1) * sizeof(WCHAR))); 5450 } 5451 } 5452 5453 /* Modify the Failure Command value, if specified */ 5454 if (lpFailureActions->lpCommand != NULL) 5455 { 5456 /* If the FailureCommand string is an empty string, delete the value */ 5457 if (*lpFailureActions->lpCommand == 0) 5458 { 5459 DPRINT("Delete Failure Command value\n"); 5460 RegDeleteValueW(hServiceKey, L"FailureCommand"); 5461 } 5462 else 5463 { 5464 DPRINT("Setting Failure Command value %S\n", lpFailureActions->lpCommand); 5465 RegSetValueExW(hServiceKey, 5466 L"FailureCommand", 5467 0, 5468 REG_SZ, 5469 (LPBYTE)lpFailureActions->lpCommand, 5470 (DWORD)((wcslen(lpFailureActions->lpCommand) + 1) * sizeof(WCHAR))); 5471 } 5472 } 5473 } 5474 5475 done: 5476 if (lpWriteBuffer != NULL) 5477 HeapFree(GetProcessHeap(), 0, lpWriteBuffer); 5478 5479 if (lpReadBuffer != NULL) 5480 HeapFree(GetProcessHeap(), 0, lpReadBuffer); 5481 5482 return dwError; 5483 } 5484 5485 5486 /* Function 37 */ 5487 DWORD 5488 WINAPI 5489 RChangeServiceConfig2W( 5490 SC_RPC_HANDLE hService, 5491 SC_RPC_CONFIG_INFOW Info) 5492 { 5493 DWORD dwError = ERROR_SUCCESS; 5494 PSERVICE_HANDLE hSvc; 5495 PSERVICE lpService = NULL; 5496 HKEY hServiceKey = NULL; 5497 ACCESS_MASK RequiredAccess = SERVICE_CHANGE_CONFIG; 5498 5499 DPRINT("RChangeServiceConfig2W() called\n"); 5500 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 5501 5502 if (ScmShutdown) 5503 return ERROR_SHUTDOWN_IN_PROGRESS; 5504 5505 hSvc = ScmGetServiceFromHandle(hService); 5506 if (hSvc == NULL) 5507 { 5508 DPRINT("Invalid service handle!\n"); 5509 return ERROR_INVALID_HANDLE; 5510 } 5511 5512 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5513 RequiredAccess |= SERVICE_START; 5514 5515 /* Check the access rights */ 5516 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5517 RequiredAccess)) 5518 { 5519 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5520 return ERROR_ACCESS_DENIED; 5521 } 5522 5523 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5524 { 5525 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */ 5526 5527 } 5528 5529 lpService = hSvc->ServiceEntry; 5530 if (lpService == NULL) 5531 { 5532 DPRINT("lpService == NULL!\n"); 5533 return ERROR_INVALID_HANDLE; 5534 } 5535 5536 /* Failure actions can only be set for Win32 services, not for drivers */ 5537 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5538 { 5539 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 5540 return ERROR_CANNOT_DETECT_DRIVER_FAILURE; 5541 } 5542 5543 /* Lock the service database exclusively */ 5544 ScmLockDatabaseExclusive(); 5545 5546 if (lpService->bDeleted) 5547 { 5548 DPRINT("The service has already been marked for delete!\n"); 5549 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 5550 goto done; 5551 } 5552 5553 /* Open the service key */ 5554 dwError = ScmOpenServiceKey(lpService->szServiceName, 5555 KEY_READ | KEY_SET_VALUE, 5556 &hServiceKey); 5557 if (dwError != ERROR_SUCCESS) 5558 goto done; 5559 5560 if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5561 { 5562 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd; 5563 5564 /* Modify the service description, if specified */ 5565 if (lpServiceDescription != NULL && 5566 lpServiceDescription->lpDescription != NULL) 5567 { 5568 /* If the description is "" then we delete it */ 5569 if (*lpServiceDescription->lpDescription == 0) 5570 { 5571 DPRINT("Delete service description\n"); 5572 dwError = RegDeleteValueW(hServiceKey, L"Description"); 5573 5574 if (dwError == ERROR_FILE_NOT_FOUND) 5575 dwError = ERROR_SUCCESS; 5576 } 5577 else 5578 { 5579 DPRINT("Setting service description value %S\n", lpServiceDescription->lpDescription); 5580 dwError = RegSetValueExW(hServiceKey, 5581 L"Description", 5582 0, 5583 REG_SZ, 5584 (LPBYTE)lpServiceDescription->lpDescription, 5585 (DWORD)((wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR))); 5586 } 5587 } 5588 else 5589 { 5590 dwError = ERROR_SUCCESS; 5591 } 5592 } 5593 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5594 { 5595 dwError = ScmSetFailureActions(hServiceKey, 5596 (LPSERVICE_FAILURE_ACTIONSW)Info.psfa); 5597 } 5598 5599 done: 5600 if (hServiceKey != NULL) 5601 RegCloseKey(hServiceKey); 5602 5603 /* Unlock the service database */ 5604 ScmUnlockDatabase(); 5605 5606 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError); 5607 5608 return dwError; 5609 } 5610 5611 5612 /* Function 38 */ 5613 DWORD 5614 WINAPI 5615 RQueryServiceConfig2A( 5616 SC_RPC_HANDLE hService, 5617 DWORD dwInfoLevel, 5618 LPBYTE lpBuffer, 5619 DWORD cbBufSize, 5620 LPBOUNDED_DWORD_8K pcbBytesNeeded) 5621 { 5622 DWORD dwError = ERROR_SUCCESS; 5623 PSERVICE_HANDLE hSvc; 5624 PSERVICE lpService = NULL; 5625 HKEY hServiceKey = NULL; 5626 DWORD dwRequiredSize = 0; 5627 DWORD dwType = 0; 5628 LPWSTR lpDescriptionW = NULL; 5629 LPWSTR lpRebootMessageW = NULL; 5630 LPWSTR lpFailureCommandW = NULL; 5631 5632 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n", 5633 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); 5634 5635 if (!lpBuffer) 5636 return ERROR_INVALID_ADDRESS; 5637 5638 if (ScmShutdown) 5639 return ERROR_SHUTDOWN_IN_PROGRESS; 5640 5641 hSvc = ScmGetServiceFromHandle(hService); 5642 if (hSvc == NULL) 5643 { 5644 DPRINT1("Invalid service handle!\n"); 5645 return ERROR_INVALID_HANDLE; 5646 } 5647 5648 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5649 SERVICE_QUERY_CONFIG)) 5650 { 5651 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5652 return ERROR_ACCESS_DENIED; 5653 } 5654 5655 lpService = hSvc->ServiceEntry; 5656 if (lpService == NULL) 5657 { 5658 DPRINT("lpService == NULL!\n"); 5659 return ERROR_INVALID_HANDLE; 5660 } 5661 5662 /* Lock the service database shared */ 5663 ScmLockDatabaseShared(); 5664 5665 dwError = ScmOpenServiceKey(lpService->lpServiceName, 5666 KEY_READ, 5667 &hServiceKey); 5668 if (dwError != ERROR_SUCCESS) 5669 goto done; 5670 5671 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5672 { 5673 LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer; 5674 LPSTR lpStr; 5675 5676 dwError = ScmReadString(hServiceKey, 5677 L"Description", 5678 &lpDescriptionW); 5679 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5680 goto done; 5681 5682 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA); 5683 if (dwError == ERROR_SUCCESS) 5684 *pcbBytesNeeded += (DWORD)((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR)); 5685 5686 if (cbBufSize < *pcbBytesNeeded) 5687 { 5688 dwError = ERROR_INSUFFICIENT_BUFFER; 5689 goto done; 5690 } 5691 5692 if (dwError == ERROR_SUCCESS) 5693 { 5694 lpStr = (LPSTR)(lpServiceDescription + 1); 5695 5696 WideCharToMultiByte(CP_ACP, 5697 0, 5698 lpDescriptionW, 5699 -1, 5700 lpStr, 5701 (int)wcslen(lpDescriptionW), 5702 NULL, 5703 NULL); 5704 lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 5705 } 5706 else 5707 { 5708 lpServiceDescription->lpDescription = NULL; 5709 dwError = ERROR_SUCCESS; 5710 } 5711 } 5712 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5713 { 5714 LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer; 5715 LPSTR lpStr = NULL; 5716 5717 /* Query value length */ 5718 dwError = RegQueryValueExW(hServiceKey, 5719 L"FailureActions", 5720 NULL, 5721 &dwType, 5722 NULL, 5723 &dwRequiredSize); 5724 if (dwError != ERROR_SUCCESS && 5725 dwError != ERROR_MORE_DATA && 5726 dwError != ERROR_FILE_NOT_FOUND) 5727 goto done; 5728 5729 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize) 5730 : sizeof(SERVICE_FAILURE_ACTIONSA); 5731 5732 /* Get the strings */ 5733 ScmReadString(hServiceKey, 5734 L"FailureCommand", 5735 &lpFailureCommandW); 5736 5737 ScmReadString(hServiceKey, 5738 L"RebootMessage", 5739 &lpRebootMessageW); 5740 5741 if (lpRebootMessageW) 5742 dwRequiredSize += (DWORD)((wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR)); 5743 5744 if (lpFailureCommandW) 5745 dwRequiredSize += (DWORD)((wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR)); 5746 5747 if (cbBufSize < dwRequiredSize) 5748 { 5749 *pcbBytesNeeded = dwRequiredSize; 5750 dwError = ERROR_INSUFFICIENT_BUFFER; 5751 goto done; 5752 } 5753 5754 /* Now we can fill the buffer */ 5755 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY) 5756 { 5757 dwError = RegQueryValueExW(hServiceKey, 5758 L"FailureActions", 5759 NULL, 5760 NULL, 5761 (LPBYTE)lpFailureActions, 5762 &dwRequiredSize); 5763 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5764 goto done; 5765 5766 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA)) 5767 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSA); 5768 } 5769 else 5770 { 5771 /* 5772 * The value of the error doesn't really matter, the only 5773 * important thing is that it must be != ERROR_SUCCESS . 5774 */ 5775 dwError = ERROR_INVALID_DATA; 5776 } 5777 5778 if (dwError == ERROR_SUCCESS) 5779 { 5780 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSA)) / sizeof(SC_ACTION)); 5781 5782 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */ 5783 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSA) : NULL); 5784 5785 lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); 5786 } 5787 else 5788 { 5789 lpFailureActions->dwResetPeriod = 0; 5790 lpFailureActions->cActions = 0; 5791 lpFailureActions->lpsaActions = NULL; 5792 lpStr = (LPSTR)(lpFailureActions + 1); 5793 } 5794 5795 lpFailureActions->lpRebootMsg = NULL; 5796 lpFailureActions->lpCommand = NULL; 5797 5798 if (lpRebootMessageW) 5799 { 5800 WideCharToMultiByte(CP_ACP, 5801 0, 5802 lpRebootMessageW, 5803 -1, 5804 lpStr, 5805 (int)wcslen(lpRebootMessageW), 5806 NULL, 5807 NULL); 5808 lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5809 lpStr += strlen(lpStr) + 1; 5810 } 5811 5812 if (lpFailureCommandW) 5813 { 5814 WideCharToMultiByte(CP_ACP, 5815 0, 5816 lpFailureCommandW, 5817 -1, 5818 lpStr, 5819 (int)wcslen(lpFailureCommandW), 5820 NULL, 5821 NULL); 5822 lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5823 /* lpStr += strlen(lpStr) + 1; */ 5824 } 5825 5826 dwError = ERROR_SUCCESS; 5827 } 5828 5829 done: 5830 /* Unlock the service database */ 5831 ScmUnlockDatabase(); 5832 5833 if (lpDescriptionW != NULL) 5834 HeapFree(GetProcessHeap(), 0, lpDescriptionW); 5835 5836 if (lpRebootMessageW != NULL) 5837 HeapFree(GetProcessHeap(), 0, lpRebootMessageW); 5838 5839 if (lpFailureCommandW != NULL) 5840 HeapFree(GetProcessHeap(), 0, lpFailureCommandW); 5841 5842 if (hServiceKey != NULL) 5843 RegCloseKey(hServiceKey); 5844 5845 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError); 5846 5847 return dwError; 5848 } 5849 5850 5851 /* Function 39 */ 5852 DWORD 5853 WINAPI 5854 RQueryServiceConfig2W( 5855 SC_RPC_HANDLE hService, 5856 DWORD dwInfoLevel, 5857 LPBYTE lpBuffer, 5858 DWORD cbBufSize, 5859 LPBOUNDED_DWORD_8K pcbBytesNeeded) 5860 { 5861 DWORD dwError = ERROR_SUCCESS; 5862 PSERVICE_HANDLE hSvc; 5863 PSERVICE lpService = NULL; 5864 HKEY hServiceKey = NULL; 5865 DWORD dwRequiredSize = 0; 5866 DWORD dwType = 0; 5867 LPWSTR lpDescription = NULL; 5868 LPWSTR lpRebootMessage = NULL; 5869 LPWSTR lpFailureCommand = NULL; 5870 5871 DPRINT("RQueryServiceConfig2W() called\n"); 5872 5873 if (!lpBuffer) 5874 return ERROR_INVALID_ADDRESS; 5875 5876 if (ScmShutdown) 5877 return ERROR_SHUTDOWN_IN_PROGRESS; 5878 5879 hSvc = ScmGetServiceFromHandle(hService); 5880 if (hSvc == NULL) 5881 { 5882 DPRINT1("Invalid service handle!\n"); 5883 return ERROR_INVALID_HANDLE; 5884 } 5885 5886 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5887 SERVICE_QUERY_CONFIG)) 5888 { 5889 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5890 return ERROR_ACCESS_DENIED; 5891 } 5892 5893 lpService = hSvc->ServiceEntry; 5894 if (lpService == NULL) 5895 { 5896 DPRINT("lpService == NULL!\n"); 5897 return ERROR_INVALID_HANDLE; 5898 } 5899 5900 /* Lock the service database shared */ 5901 ScmLockDatabaseShared(); 5902 5903 dwError = ScmOpenServiceKey(lpService->lpServiceName, 5904 KEY_READ, 5905 &hServiceKey); 5906 if (dwError != ERROR_SUCCESS) 5907 goto done; 5908 5909 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5910 { 5911 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer; 5912 LPWSTR lpStr; 5913 5914 dwError = ScmReadString(hServiceKey, 5915 L"Description", 5916 &lpDescription); 5917 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5918 goto done; 5919 5920 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONW); 5921 if (dwError == ERROR_SUCCESS) 5922 *pcbBytesNeeded += (DWORD)((wcslen(lpDescription) + 1) * sizeof(WCHAR)); 5923 5924 if (cbBufSize < *pcbBytesNeeded) 5925 { 5926 dwError = ERROR_INSUFFICIENT_BUFFER; 5927 goto done; 5928 } 5929 5930 if (dwError == ERROR_SUCCESS) 5931 { 5932 lpStr = (LPWSTR)(lpServiceDescription + 1); 5933 wcscpy(lpStr, lpDescription); 5934 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 5935 } 5936 else 5937 { 5938 lpServiceDescription->lpDescription = NULL; 5939 dwError = ERROR_SUCCESS; 5940 } 5941 } 5942 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5943 { 5944 LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer; 5945 LPWSTR lpStr = NULL; 5946 5947 /* Query value length */ 5948 dwError = RegQueryValueExW(hServiceKey, 5949 L"FailureActions", 5950 NULL, 5951 &dwType, 5952 NULL, 5953 &dwRequiredSize); 5954 if (dwError != ERROR_SUCCESS && 5955 dwError != ERROR_MORE_DATA && 5956 dwError != ERROR_FILE_NOT_FOUND) 5957 goto done; 5958 5959 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize) 5960 : sizeof(SERVICE_FAILURE_ACTIONSW); 5961 5962 /* Get the strings */ 5963 ScmReadString(hServiceKey, 5964 L"FailureCommand", 5965 &lpFailureCommand); 5966 5967 ScmReadString(hServiceKey, 5968 L"RebootMessage", 5969 &lpRebootMessage); 5970 5971 if (lpRebootMessage) 5972 dwRequiredSize += (DWORD)((wcslen(lpRebootMessage) + 1) * sizeof(WCHAR)); 5973 5974 if (lpFailureCommand) 5975 dwRequiredSize += (DWORD)((wcslen(lpFailureCommand) + 1) * sizeof(WCHAR)); 5976 5977 if (cbBufSize < dwRequiredSize) 5978 { 5979 *pcbBytesNeeded = dwRequiredSize; 5980 dwError = ERROR_INSUFFICIENT_BUFFER; 5981 goto done; 5982 } 5983 5984 /* Now we can fill the buffer */ 5985 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY) 5986 { 5987 dwError = RegQueryValueExW(hServiceKey, 5988 L"FailureActions", 5989 NULL, 5990 NULL, 5991 (LPBYTE)lpFailureActions, 5992 &dwRequiredSize); 5993 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5994 goto done; 5995 5996 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) 5997 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5998 } 5999 else 6000 { 6001 /* 6002 * The value of the error doesn't really matter, the only 6003 * important thing is that it must be != ERROR_SUCCESS . 6004 */ 6005 dwError = ERROR_INVALID_DATA; 6006 } 6007 6008 if (dwError == ERROR_SUCCESS) 6009 { 6010 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION)); 6011 6012 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */ 6013 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSW) : NULL); 6014 6015 lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); 6016 } 6017 else 6018 { 6019 lpFailureActions->dwResetPeriod = 0; 6020 lpFailureActions->cActions = 0; 6021 lpFailureActions->lpsaActions = NULL; 6022 lpStr = (LPWSTR)(lpFailureActions + 1); 6023 } 6024 6025 lpFailureActions->lpRebootMsg = NULL; 6026 lpFailureActions->lpCommand = NULL; 6027 6028 if (lpRebootMessage) 6029 { 6030 wcscpy(lpStr, lpRebootMessage); 6031 lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 6032 lpStr += wcslen(lpStr) + 1; 6033 } 6034 6035 if (lpFailureCommand) 6036 { 6037 wcscpy(lpStr, lpFailureCommand); 6038 lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 6039 /* lpStr += wcslen(lpStr) + 1; */ 6040 } 6041 6042 dwError = ERROR_SUCCESS; 6043 } 6044 6045 done: 6046 /* Unlock the service database */ 6047 ScmUnlockDatabase(); 6048 6049 if (lpDescription != NULL) 6050 HeapFree(GetProcessHeap(), 0, lpDescription); 6051 6052 if (lpRebootMessage != NULL) 6053 HeapFree(GetProcessHeap(), 0, lpRebootMessage); 6054 6055 if (lpFailureCommand != NULL) 6056 HeapFree(GetProcessHeap(), 0, lpFailureCommand); 6057 6058 if (hServiceKey != NULL) 6059 RegCloseKey(hServiceKey); 6060 6061 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError); 6062 6063 return dwError; 6064 } 6065 6066 6067 /* Function 40 */ 6068 DWORD 6069 WINAPI 6070 RQueryServiceStatusEx( 6071 SC_RPC_HANDLE hService, 6072 SC_STATUS_TYPE InfoLevel, 6073 LPBYTE lpBuffer, 6074 DWORD cbBufSize, 6075 LPBOUNDED_DWORD_8K pcbBytesNeeded) 6076 { 6077 LPSERVICE_STATUS_PROCESS lpStatus; 6078 PSERVICE_HANDLE hSvc; 6079 PSERVICE lpService; 6080 6081 DPRINT("RQueryServiceStatusEx() called\n"); 6082 6083 if (ScmShutdown) 6084 return ERROR_SHUTDOWN_IN_PROGRESS; 6085 6086 if (InfoLevel != SC_STATUS_PROCESS_INFO) 6087 return ERROR_INVALID_LEVEL; 6088 6089 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS); 6090 6091 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) 6092 return ERROR_INSUFFICIENT_BUFFER; 6093 6094 hSvc = ScmGetServiceFromHandle(hService); 6095 if (hSvc == NULL) 6096 { 6097 DPRINT1("Invalid service handle!\n"); 6098 return ERROR_INVALID_HANDLE; 6099 } 6100 6101 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 6102 SERVICE_QUERY_STATUS)) 6103 { 6104 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 6105 return ERROR_ACCESS_DENIED; 6106 } 6107 6108 lpService = hSvc->ServiceEntry; 6109 if (lpService == NULL) 6110 { 6111 DPRINT("lpService == NULL!\n"); 6112 return ERROR_INVALID_HANDLE; 6113 } 6114 6115 /* Lock the service database shared */ 6116 ScmLockDatabaseShared(); 6117 6118 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer; 6119 6120 /* Return service status information */ 6121 RtlCopyMemory(lpStatus, 6122 &lpService->Status, 6123 sizeof(SERVICE_STATUS)); 6124 6125 /* Copy the service process ID */ 6126 if ((lpService->Status.dwCurrentState == SERVICE_STOPPED) || (lpService->lpImage == NULL)) 6127 lpStatus->dwProcessId = 0; 6128 else 6129 lpStatus->dwProcessId = lpService->lpImage->dwProcessId; 6130 6131 lpStatus->dwServiceFlags = 0; /* FIXME */ 6132 6133 /* Unlock the service database */ 6134 ScmUnlockDatabase(); 6135 6136 return ERROR_SUCCESS; 6137 } 6138 6139 6140 /* Function 41 */ 6141 DWORD 6142 WINAPI 6143 REnumServicesStatusExA( 6144 SC_RPC_HANDLE hSCManager, 6145 SC_ENUM_TYPE InfoLevel, 6146 DWORD dwServiceType, 6147 DWORD dwServiceState, 6148 LPBYTE lpBuffer, 6149 DWORD cbBufSize, 6150 LPBOUNDED_DWORD_256K pcbBytesNeeded, 6151 LPBOUNDED_DWORD_256K lpServicesReturned, 6152 LPBOUNDED_DWORD_256K lpResumeIndex, 6153 LPCSTR pszGroupName) 6154 { 6155 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL; 6156 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW; 6157 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL; 6158 LPWSTR lpStringPtrW; 6159 LPSTR lpStringPtrA; 6160 LPWSTR pszGroupNameW = NULL; 6161 DWORD dwError; 6162 DWORD dwServiceCount; 6163 6164 DPRINT("REnumServicesStatusExA() called\n"); 6165 6166 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 6167 { 6168 return ERROR_INVALID_ADDRESS; 6169 } 6170 6171 if (pszGroupName) 6172 { 6173 pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR)); 6174 if (!pszGroupNameW) 6175 { 6176 DPRINT("Failed to allocate buffer!\n"); 6177 dwError = ERROR_NOT_ENOUGH_MEMORY; 6178 goto Done; 6179 } 6180 6181 MultiByteToWideChar(CP_ACP, 6182 0, 6183 pszGroupName, 6184 -1, 6185 pszGroupNameW, 6186 (int)(strlen(pszGroupName) + 1)); 6187 } 6188 6189 if ((cbBufSize > 0) && (lpBuffer)) 6190 { 6191 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize); 6192 if (!lpStatusPtrW) 6193 { 6194 DPRINT("Failed to allocate buffer!\n"); 6195 dwError = ERROR_NOT_ENOUGH_MEMORY; 6196 goto Done; 6197 } 6198 } 6199 6200 dwError = REnumServicesStatusExW(hSCManager, 6201 InfoLevel, 6202 dwServiceType, 6203 dwServiceState, 6204 (LPBYTE)lpStatusPtrW, 6205 cbBufSize, 6206 pcbBytesNeeded, 6207 lpServicesReturned, 6208 lpResumeIndex, 6209 pszGroupNameW); 6210 6211 /* if no services were returned then we are Done */ 6212 if (*lpServicesReturned == 0) 6213 goto Done; 6214 6215 lpStatusPtrIncrW = lpStatusPtrW; 6216 lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer; 6217 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 6218 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA)); 6219 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 6220 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 6221 6222 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 6223 { 6224 /* Copy the service name */ 6225 WideCharToMultiByte(CP_ACP, 6226 0, 6227 lpStringPtrW, 6228 -1, 6229 lpStringPtrA, 6230 (int)wcslen(lpStringPtrW), 6231 0, 6232 0); 6233 6234 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 6235 lpStringPtrA += wcslen(lpStringPtrW) + 1; 6236 lpStringPtrW += wcslen(lpStringPtrW) + 1; 6237 6238 /* Copy the display name */ 6239 WideCharToMultiByte(CP_ACP, 6240 0, 6241 lpStringPtrW, 6242 -1, 6243 lpStringPtrA, 6244 (int)wcslen(lpStringPtrW), 6245 0, 6246 0); 6247 6248 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 6249 lpStringPtrA += wcslen(lpStringPtrW) + 1; 6250 lpStringPtrW += wcslen(lpStringPtrW) + 1; 6251 6252 /* Copy the status information */ 6253 memcpy(&lpStatusPtrA->ServiceStatusProcess, 6254 &lpStatusPtrIncrW->ServiceStatusProcess, 6255 sizeof(SERVICE_STATUS)); 6256 6257 /* Copy the service process ID */ 6258 lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId; 6259 6260 lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 6261 6262 lpStatusPtrIncrW++; 6263 lpStatusPtrA++; 6264 } 6265 6266 Done: 6267 if (pszGroupNameW) 6268 HeapFree(GetProcessHeap(), 0, pszGroupNameW); 6269 6270 if (lpStatusPtrW) 6271 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 6272 6273 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError); 6274 6275 return dwError; 6276 } 6277 6278 6279 /* Function 42 */ 6280 DWORD 6281 WINAPI 6282 REnumServicesStatusExW( 6283 SC_RPC_HANDLE hSCManager, 6284 SC_ENUM_TYPE InfoLevel, 6285 DWORD dwServiceType, 6286 DWORD dwServiceState, 6287 LPBYTE lpBuffer, 6288 DWORD cbBufSize, 6289 LPBOUNDED_DWORD_256K pcbBytesNeeded, 6290 LPBOUNDED_DWORD_256K lpServicesReturned, 6291 LPBOUNDED_DWORD_256K lpResumeIndex, 6292 LPCWSTR pszGroupName) 6293 { 6294 PMANAGER_HANDLE hManager; 6295 PSERVICE lpService; 6296 DWORD dwError = ERROR_SUCCESS; 6297 PLIST_ENTRY ServiceEntry; 6298 PSERVICE CurrentService; 6299 DWORD dwState; 6300 DWORD dwRequiredSize; 6301 DWORD dwServiceCount; 6302 DWORD dwSize; 6303 DWORD dwLastResumeCount = 0; 6304 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; 6305 LPWSTR lpStringPtr; 6306 6307 DPRINT("REnumServicesStatusExW() called\n"); 6308 6309 if (ScmShutdown) 6310 return ERROR_SHUTDOWN_IN_PROGRESS; 6311 6312 if (InfoLevel != SC_ENUM_PROCESS_INFO) 6313 return ERROR_INVALID_LEVEL; 6314 6315 hManager = ScmGetServiceManagerFromHandle(hSCManager); 6316 if (hManager == NULL) 6317 { 6318 DPRINT1("Invalid service manager handle!\n"); 6319 return ERROR_INVALID_HANDLE; 6320 } 6321 6322 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 6323 { 6324 return ERROR_INVALID_ADDRESS; 6325 } 6326 6327 *pcbBytesNeeded = 0; 6328 *lpServicesReturned = 0; 6329 6330 if ((dwServiceType == 0) || 6331 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0)) 6332 { 6333 DPRINT("Not a valid Service Type!\n"); 6334 return ERROR_INVALID_PARAMETER; 6335 } 6336 6337 if ((dwServiceState == 0) || 6338 ((dwServiceState & ~SERVICE_STATE_ALL) != 0)) 6339 { 6340 DPRINT("Not a valid Service State!\n"); 6341 return ERROR_INVALID_PARAMETER; 6342 } 6343 6344 /* Check access rights */ 6345 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 6346 SC_MANAGER_ENUMERATE_SERVICE)) 6347 { 6348 DPRINT("Insufficient access rights! 0x%lx\n", 6349 hManager->Handle.DesiredAccess); 6350 return ERROR_ACCESS_DENIED; 6351 } 6352 6353 if (lpResumeIndex) 6354 dwLastResumeCount = *lpResumeIndex; 6355 6356 /* Lock the service database shared */ 6357 ScmLockDatabaseShared(); 6358 6359 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 6360 if (lpService == NULL) 6361 { 6362 dwError = ERROR_SUCCESS; 6363 goto Done; 6364 } 6365 6366 dwRequiredSize = 0; 6367 dwServiceCount = 0; 6368 6369 for (ServiceEntry = &lpService->ServiceListEntry; 6370 ServiceEntry != &ServiceListHead; 6371 ServiceEntry = ServiceEntry->Flink) 6372 { 6373 CurrentService = CONTAINING_RECORD(ServiceEntry, 6374 SERVICE, 6375 ServiceListEntry); 6376 6377 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6378 continue; 6379 6380 dwState = SERVICE_ACTIVE; 6381 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6382 dwState = SERVICE_INACTIVE; 6383 6384 if ((dwState & dwServiceState) == 0) 6385 continue; 6386 6387 if (pszGroupName) 6388 { 6389 if (*pszGroupName == 0) 6390 { 6391 if (CurrentService->lpGroup != NULL) 6392 continue; 6393 } 6394 else 6395 { 6396 if ((CurrentService->lpGroup == NULL) || 6397 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6398 continue; 6399 } 6400 } 6401 6402 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6403 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6404 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 6405 6406 if (dwRequiredSize + dwSize <= cbBufSize) 6407 { 6408 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 6409 dwRequiredSize += dwSize; 6410 dwServiceCount++; 6411 dwLastResumeCount = CurrentService->dwResumeCount; 6412 } 6413 else 6414 { 6415 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 6416 break; 6417 } 6418 6419 } 6420 6421 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 6422 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 6423 6424 for (; 6425 ServiceEntry != &ServiceListHead; 6426 ServiceEntry = ServiceEntry->Flink) 6427 { 6428 CurrentService = CONTAINING_RECORD(ServiceEntry, 6429 SERVICE, 6430 ServiceListEntry); 6431 6432 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6433 continue; 6434 6435 dwState = SERVICE_ACTIVE; 6436 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6437 dwState = SERVICE_INACTIVE; 6438 6439 if ((dwState & dwServiceState) == 0) 6440 continue; 6441 6442 if (pszGroupName) 6443 { 6444 if (*pszGroupName == 0) 6445 { 6446 if (CurrentService->lpGroup != NULL) 6447 continue; 6448 } 6449 else 6450 { 6451 if ((CurrentService->lpGroup == NULL) || 6452 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6453 continue; 6454 } 6455 } 6456 6457 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6458 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6459 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 6460 6461 dwError = ERROR_MORE_DATA; 6462 } 6463 6464 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 6465 6466 if (lpResumeIndex) 6467 *lpResumeIndex = dwLastResumeCount; 6468 6469 *lpServicesReturned = dwServiceCount; 6470 *pcbBytesNeeded = dwRequiredSize; 6471 6472 /* If there was no services that matched */ 6473 if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA)) 6474 { 6475 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 6476 goto Done; 6477 } 6478 6479 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer; 6480 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 6481 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 6482 6483 dwRequiredSize = 0; 6484 for (ServiceEntry = &lpService->ServiceListEntry; 6485 ServiceEntry != &ServiceListHead; 6486 ServiceEntry = ServiceEntry->Flink) 6487 { 6488 CurrentService = CONTAINING_RECORD(ServiceEntry, 6489 SERVICE, 6490 ServiceListEntry); 6491 6492 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6493 continue; 6494 6495 dwState = SERVICE_ACTIVE; 6496 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6497 dwState = SERVICE_INACTIVE; 6498 6499 if ((dwState & dwServiceState) == 0) 6500 continue; 6501 6502 if (pszGroupName) 6503 { 6504 if (*pszGroupName == 0) 6505 { 6506 if (CurrentService->lpGroup != NULL) 6507 continue; 6508 } 6509 else 6510 { 6511 if ((CurrentService->lpGroup == NULL) || 6512 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6513 continue; 6514 } 6515 } 6516 6517 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6518 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6519 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 6520 6521 if (dwRequiredSize + dwSize <= cbBufSize) 6522 { 6523 /* Copy the service name */ 6524 wcscpy(lpStringPtr, 6525 CurrentService->lpServiceName); 6526 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 6527 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 6528 6529 /* Copy the display name */ 6530 wcscpy(lpStringPtr, 6531 CurrentService->lpDisplayName); 6532 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 6533 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 6534 6535 /* Copy the status information */ 6536 memcpy(&lpStatusPtr->ServiceStatusProcess, 6537 &CurrentService->Status, 6538 sizeof(SERVICE_STATUS)); 6539 6540 /* Copy the service process ID */ 6541 if ((CurrentService->Status.dwCurrentState == SERVICE_STOPPED) || (CurrentService->lpImage == NULL)) 6542 lpStatusPtr->ServiceStatusProcess.dwProcessId = 0; 6543 else 6544 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->lpImage->dwProcessId; 6545 6546 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 6547 6548 lpStatusPtr++; 6549 dwRequiredSize += dwSize; 6550 } 6551 else 6552 { 6553 break; 6554 } 6555 } 6556 6557 if (dwError == 0) 6558 { 6559 *pcbBytesNeeded = 0; 6560 if (lpResumeIndex) 6561 *lpResumeIndex = 0; 6562 } 6563 6564 Done: 6565 /* Unlock the service database */ 6566 ScmUnlockDatabase(); 6567 6568 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError); 6569 6570 return dwError; 6571 } 6572 6573 6574 /* Function 43 */ 6575 DWORD 6576 WINAPI 6577 RSendTSMessage( 6578 handle_t BindingHandle) /* FIXME */ 6579 { 6580 UNIMPLEMENTED; 6581 return ERROR_CALL_NOT_IMPLEMENTED; 6582 } 6583 6584 6585 /* Function 44 */ 6586 DWORD 6587 WINAPI 6588 RCreateServiceWOW64A( 6589 handle_t BindingHandle, 6590 LPSTR lpServiceName, 6591 LPSTR lpDisplayName, 6592 DWORD dwDesiredAccess, 6593 DWORD dwServiceType, 6594 DWORD dwStartType, 6595 DWORD dwErrorControl, 6596 LPSTR lpBinaryPathName, 6597 LPSTR lpLoadOrderGroup, 6598 LPDWORD lpdwTagId, 6599 LPBYTE lpDependencies, 6600 DWORD dwDependSize, 6601 LPSTR lpServiceStartName, 6602 LPBYTE lpPassword, 6603 DWORD dwPwSize, 6604 LPSC_RPC_HANDLE lpServiceHandle) 6605 { 6606 UNIMPLEMENTED; 6607 return ERROR_CALL_NOT_IMPLEMENTED; 6608 } 6609 6610 6611 /* Function 45 */ 6612 DWORD 6613 WINAPI 6614 RCreateServiceWOW64W( 6615 handle_t BindingHandle, 6616 LPWSTR lpServiceName, 6617 LPWSTR lpDisplayName, 6618 DWORD dwDesiredAccess, 6619 DWORD dwServiceType, 6620 DWORD dwStartType, 6621 DWORD dwErrorControl, 6622 LPWSTR lpBinaryPathName, 6623 LPWSTR lpLoadOrderGroup, 6624 LPDWORD lpdwTagId, 6625 LPBYTE lpDependencies, 6626 DWORD dwDependSize, 6627 LPWSTR lpServiceStartName, 6628 LPBYTE lpPassword, 6629 DWORD dwPwSize, 6630 LPSC_RPC_HANDLE lpServiceHandle) 6631 { 6632 UNIMPLEMENTED; 6633 return ERROR_CALL_NOT_IMPLEMENTED; 6634 } 6635 6636 6637 /* Function 46 */ 6638 DWORD 6639 WINAPI 6640 RQueryServiceTagInfo( 6641 handle_t BindingHandle) /* FIXME */ 6642 { 6643 UNIMPLEMENTED; 6644 return ERROR_CALL_NOT_IMPLEMENTED; 6645 } 6646 6647 6648 /* Function 47 */ 6649 DWORD 6650 WINAPI 6651 RNotifyServiceStatusChange( 6652 SC_RPC_HANDLE hService, 6653 SC_RPC_NOTIFY_PARAMS NotifyParams, 6654 GUID *pClientProcessGuid, 6655 GUID *pSCMProcessGuid, 6656 PBOOL pfCreateRemoteQueue, 6657 LPSC_NOTIFY_RPC_HANDLE phNotify) 6658 { 6659 UNIMPLEMENTED; 6660 return ERROR_CALL_NOT_IMPLEMENTED; 6661 } 6662 6663 6664 /* Function 48 */ 6665 DWORD 6666 WINAPI 6667 RGetNotifyResults( 6668 SC_NOTIFY_RPC_HANDLE hNotify, 6669 PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams) 6670 { 6671 UNIMPLEMENTED; 6672 return ERROR_CALL_NOT_IMPLEMENTED; 6673 } 6674 6675 6676 /* Function 49 */ 6677 DWORD 6678 WINAPI 6679 RCloseNotifyHandle( 6680 LPSC_NOTIFY_RPC_HANDLE phNotify, 6681 PBOOL pfApcFired) 6682 { 6683 UNIMPLEMENTED; 6684 return ERROR_CALL_NOT_IMPLEMENTED; 6685 } 6686 6687 6688 /* Function 50 */ 6689 DWORD 6690 WINAPI 6691 RControlServiceExA( 6692 SC_RPC_HANDLE hService, 6693 DWORD dwControl, 6694 DWORD dwInfoLevel) 6695 { 6696 UNIMPLEMENTED; 6697 return ERROR_CALL_NOT_IMPLEMENTED; 6698 } 6699 6700 6701 /* Function 51 */ 6702 DWORD 6703 WINAPI 6704 RControlServiceExW( 6705 SC_RPC_HANDLE hService, 6706 DWORD dwControl, 6707 DWORD dwInfoLevel) 6708 { 6709 UNIMPLEMENTED; 6710 return ERROR_CALL_NOT_IMPLEMENTED; 6711 } 6712 6713 6714 /* Function 52 */ 6715 DWORD 6716 WINAPI 6717 RSendPnPMessage( 6718 handle_t BindingHandle) /* FIXME */ 6719 { 6720 UNIMPLEMENTED; 6721 return ERROR_CALL_NOT_IMPLEMENTED; 6722 } 6723 6724 6725 /* Function 53 */ 6726 DWORD 6727 WINAPI 6728 RValidatePnPService( 6729 handle_t BindingHandle) /* FIXME */ 6730 { 6731 UNIMPLEMENTED; 6732 return ERROR_CALL_NOT_IMPLEMENTED; 6733 } 6734 6735 6736 /* Function 54 */ 6737 DWORD 6738 WINAPI 6739 ROpenServiceStatusHandle( 6740 handle_t BindingHandle) /* FIXME */ 6741 { 6742 UNIMPLEMENTED; 6743 return ERROR_CALL_NOT_IMPLEMENTED; 6744 } 6745 6746 6747 /* Function 55 */ 6748 DWORD 6749 WINAPI 6750 RFunction55( 6751 handle_t BindingHandle) /* FIXME */ 6752 { 6753 UNIMPLEMENTED; 6754 return ERROR_CALL_NOT_IMPLEMENTED; 6755 } 6756 6757 6758 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 6759 { 6760 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 6761 } 6762 6763 6764 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 6765 { 6766 HeapFree(GetProcessHeap(), 0, ptr); 6767 } 6768 6769 6770 void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject) 6771 { 6772 /* Close the handle */ 6773 RCloseServiceHandle(&hSCObject); 6774 } 6775 6776 6777 void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock) 6778 { 6779 /* Unlock the database */ 6780 RUnlockServiceDatabase(&Lock); 6781 } 6782 6783 6784 void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify) 6785 { 6786 } 6787 6788 /* EOF */ 6789