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 UNIMPLEMENTED; 1864 return ERROR_CALL_NOT_IMPLEMENTED; 1865 } 1866 1867 1868 /* Function 11 */ 1869 DWORD 1870 WINAPI 1871 RChangeServiceConfigW( 1872 SC_RPC_HANDLE hService, 1873 DWORD dwServiceType, 1874 DWORD dwStartType, 1875 DWORD dwErrorControl, 1876 LPWSTR lpBinaryPathName, 1877 LPWSTR lpLoadOrderGroup, 1878 LPDWORD lpdwTagId, 1879 LPBYTE lpDependencies, 1880 DWORD dwDependSize, 1881 LPWSTR lpServiceStartName, 1882 LPBYTE lpPassword, 1883 DWORD dwPwSize, 1884 LPWSTR lpDisplayName) 1885 { 1886 DWORD dwError = ERROR_SUCCESS; 1887 PSERVICE_HANDLE hSvc; 1888 PSERVICE lpService = NULL; 1889 HKEY hServiceKey = NULL; 1890 LPWSTR lpDisplayNameW = NULL; 1891 LPWSTR lpImagePathW = NULL; 1892 1893 DPRINT("RChangeServiceConfigW() called\n"); 1894 DPRINT("dwServiceType = 0x%lx\n", dwServiceType); 1895 DPRINT("dwStartType = %lu\n", dwStartType); 1896 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 1897 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 1898 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 1899 DPRINT("lpDisplayName = %S\n", lpDisplayName); 1900 1901 if (ScmShutdown) 1902 return ERROR_SHUTDOWN_IN_PROGRESS; 1903 1904 hSvc = ScmGetServiceFromHandle(hService); 1905 if (hSvc == NULL) 1906 { 1907 DPRINT1("Invalid service handle!\n"); 1908 return ERROR_INVALID_HANDLE; 1909 } 1910 1911 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 1912 SERVICE_CHANGE_CONFIG)) 1913 { 1914 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 1915 return ERROR_ACCESS_DENIED; 1916 } 1917 1918 /* Check for invalid service type value */ 1919 if ((dwServiceType != SERVICE_NO_CHANGE) && 1920 (dwServiceType != SERVICE_KERNEL_DRIVER) && 1921 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) && 1922 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && 1923 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS)) 1924 return ERROR_INVALID_PARAMETER; 1925 1926 /* Check for invalid start type value */ 1927 if ((dwStartType != SERVICE_NO_CHANGE) && 1928 (dwStartType != SERVICE_BOOT_START) && 1929 (dwStartType != SERVICE_SYSTEM_START) && 1930 (dwStartType != SERVICE_AUTO_START) && 1931 (dwStartType != SERVICE_DEMAND_START) && 1932 (dwStartType != SERVICE_DISABLED)) 1933 return ERROR_INVALID_PARAMETER; 1934 1935 /* Only drivers can be boot start or system start services */ 1936 if ((dwStartType == SERVICE_BOOT_START) || 1937 (dwStartType == SERVICE_SYSTEM_START)) 1938 { 1939 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 1940 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) 1941 return ERROR_INVALID_PARAMETER; 1942 } 1943 1944 /* Check for invalid error control value */ 1945 if ((dwErrorControl != SERVICE_NO_CHANGE) && 1946 (dwErrorControl != SERVICE_ERROR_IGNORE) && 1947 (dwErrorControl != SERVICE_ERROR_NORMAL) && 1948 (dwErrorControl != SERVICE_ERROR_SEVERE) && 1949 (dwErrorControl != SERVICE_ERROR_CRITICAL)) 1950 return ERROR_INVALID_PARAMETER; 1951 1952 lpService = hSvc->ServiceEntry; 1953 if (lpService == NULL) 1954 { 1955 DPRINT("lpService == NULL!\n"); 1956 return ERROR_INVALID_HANDLE; 1957 } 1958 1959 /* Lock the service database exclusively */ 1960 ScmLockDatabaseExclusive(); 1961 1962 if (lpService->bDeleted) 1963 { 1964 DPRINT("The service has already been marked for delete!\n"); 1965 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 1966 goto done; 1967 } 1968 1969 /* Open the service key */ 1970 dwError = ScmOpenServiceKey(lpService->szServiceName, 1971 KEY_SET_VALUE, 1972 &hServiceKey); 1973 if (dwError != ERROR_SUCCESS) 1974 goto done; 1975 1976 /* Write service data to the registry */ 1977 /* Set the display name */ 1978 if (lpDisplayName != NULL && *lpDisplayName != 0) 1979 { 1980 RegSetValueExW(hServiceKey, 1981 L"DisplayName", 1982 0, 1983 REG_SZ, 1984 (LPBYTE)lpDisplayName, 1985 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR))); 1986 1987 /* Update the display name */ 1988 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 1989 HEAP_ZERO_MEMORY, 1990 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 1991 if (lpDisplayNameW == NULL) 1992 { 1993 dwError = ERROR_NOT_ENOUGH_MEMORY; 1994 goto done; 1995 } 1996 1997 wcscpy(lpDisplayNameW, lpDisplayName); 1998 if (lpService->lpDisplayName != lpService->lpServiceName) 1999 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 2000 2001 lpService->lpDisplayName = lpDisplayNameW; 2002 } 2003 2004 if (dwServiceType != SERVICE_NO_CHANGE) 2005 { 2006 /* Set the service type */ 2007 dwError = RegSetValueExW(hServiceKey, 2008 L"Type", 2009 0, 2010 REG_DWORD, 2011 (LPBYTE)&dwServiceType, 2012 sizeof(DWORD)); 2013 if (dwError != ERROR_SUCCESS) 2014 goto done; 2015 2016 lpService->Status.dwServiceType = dwServiceType; 2017 } 2018 2019 if (dwStartType != SERVICE_NO_CHANGE) 2020 { 2021 /* Set the start value */ 2022 dwError = RegSetValueExW(hServiceKey, 2023 L"Start", 2024 0, 2025 REG_DWORD, 2026 (LPBYTE)&dwStartType, 2027 sizeof(DWORD)); 2028 if (dwError != ERROR_SUCCESS) 2029 goto done; 2030 2031 lpService->dwStartType = dwStartType; 2032 } 2033 2034 if (dwErrorControl != SERVICE_NO_CHANGE) 2035 { 2036 /* Set the error control value */ 2037 dwError = RegSetValueExW(hServiceKey, 2038 L"ErrorControl", 2039 0, 2040 REG_DWORD, 2041 (LPBYTE)&dwErrorControl, 2042 sizeof(DWORD)); 2043 if (dwError != ERROR_SUCCESS) 2044 goto done; 2045 2046 lpService->dwErrorControl = dwErrorControl; 2047 } 2048 2049 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 2050 { 2051 /* Set the image path */ 2052 lpImagePathW = lpBinaryPathName; 2053 2054 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 2055 { 2056 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 2057 lpBinaryPathName, 2058 &lpImagePathW); 2059 2060 if (dwError != ERROR_SUCCESS) 2061 goto done; 2062 } 2063 2064 dwError = RegSetValueExW(hServiceKey, 2065 L"ImagePath", 2066 0, 2067 REG_EXPAND_SZ, 2068 (LPBYTE)lpImagePathW, 2069 (DWORD)((wcslen(lpImagePathW) + 1) * sizeof(WCHAR))); 2070 2071 if (lpImagePathW != lpBinaryPathName) 2072 HeapFree(GetProcessHeap(), 0, lpImagePathW); 2073 2074 if (dwError != ERROR_SUCCESS) 2075 goto done; 2076 } 2077 2078 /* Set the group name */ 2079 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2080 { 2081 dwError = RegSetValueExW(hServiceKey, 2082 L"Group", 2083 0, 2084 REG_SZ, 2085 (LPBYTE)lpLoadOrderGroup, 2086 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR))); 2087 if (dwError != ERROR_SUCCESS) 2088 goto done; 2089 2090 dwError = ScmSetServiceGroup(lpService, 2091 lpLoadOrderGroup); 2092 if (dwError != ERROR_SUCCESS) 2093 goto done; 2094 } 2095 2096 /* Set the tag */ 2097 if (lpdwTagId != NULL) 2098 { 2099 dwError = ScmAssignNewTag(lpService); 2100 if (dwError != ERROR_SUCCESS) 2101 goto done; 2102 2103 dwError = RegSetValueExW(hServiceKey, 2104 L"Tag", 2105 0, 2106 REG_DWORD, 2107 (LPBYTE)&lpService->dwTag, 2108 sizeof(DWORD)); 2109 if (dwError != ERROR_SUCCESS) 2110 goto done; 2111 2112 *lpdwTagId = lpService->dwTag; 2113 } 2114 2115 /* Write dependencies */ 2116 if (lpDependencies != NULL && *lpDependencies != 0) 2117 { 2118 dwError = ScmWriteDependencies(hServiceKey, 2119 (LPWSTR)lpDependencies, 2120 dwDependSize); 2121 if (dwError != ERROR_SUCCESS) 2122 goto done; 2123 } 2124 2125 if (lpPassword != NULL) 2126 { 2127 if (wcslen((LPWSTR)lpPassword) != 0) 2128 { 2129 /* FIXME: Decrypt the password */ 2130 2131 /* Write the password */ 2132 dwError = ScmSetServicePassword(lpService->szServiceName, 2133 (LPCWSTR)lpPassword); 2134 if (dwError != ERROR_SUCCESS) 2135 goto done; 2136 } 2137 else 2138 { 2139 /* Delete the password */ 2140 dwError = ScmSetServicePassword(lpService->szServiceName, 2141 NULL); 2142 if (dwError == ERROR_FILE_NOT_FOUND) 2143 dwError = ERROR_SUCCESS; 2144 2145 if (dwError != ERROR_SUCCESS) 2146 goto done; 2147 } 2148 } 2149 2150 done: 2151 if (hServiceKey != NULL) 2152 RegCloseKey(hServiceKey); 2153 2154 /* Unlock the service database */ 2155 ScmUnlockDatabase(); 2156 2157 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError); 2158 2159 return dwError; 2160 } 2161 2162 2163 /* Function 12 */ 2164 DWORD 2165 WINAPI 2166 RCreateServiceW( 2167 SC_RPC_HANDLE hSCManager, 2168 LPCWSTR lpServiceName, 2169 LPCWSTR lpDisplayName, 2170 DWORD dwDesiredAccess, 2171 DWORD dwServiceType, 2172 DWORD dwStartType, 2173 DWORD dwErrorControl, 2174 LPCWSTR lpBinaryPathName, 2175 LPCWSTR lpLoadOrderGroup, 2176 LPDWORD lpdwTagId, 2177 LPBYTE lpDependencies, 2178 DWORD dwDependSize, 2179 LPCWSTR lpServiceStartName, 2180 LPBYTE lpPassword, 2181 DWORD dwPwSize, 2182 LPSC_RPC_HANDLE lpServiceHandle) 2183 { 2184 PMANAGER_HANDLE hManager; 2185 DWORD dwError = ERROR_SUCCESS; 2186 PSERVICE lpService = NULL; 2187 SC_HANDLE hServiceHandle = NULL; 2188 LPWSTR lpImagePath = NULL; 2189 HKEY hServiceKey = NULL; 2190 LPWSTR lpObjectName; 2191 2192 DPRINT("RCreateServiceW() called\n"); 2193 DPRINT("lpServiceName = %S\n", lpServiceName); 2194 DPRINT("lpDisplayName = %S\n", lpDisplayName); 2195 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess); 2196 DPRINT("dwServiceType = 0x%lx\n", dwServiceType); 2197 DPRINT("dwStartType = %lu\n", dwStartType); 2198 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 2199 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 2200 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 2201 DPRINT("lpdwTagId = %p\n", lpdwTagId); 2202 2203 if (ScmShutdown) 2204 return ERROR_SHUTDOWN_IN_PROGRESS; 2205 2206 hManager = ScmGetServiceManagerFromHandle(hSCManager); 2207 if (hManager == NULL) 2208 { 2209 DPRINT1("Invalid service manager handle!\n"); 2210 return ERROR_INVALID_HANDLE; 2211 } 2212 2213 /* Check access rights */ 2214 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 2215 SC_MANAGER_CREATE_SERVICE)) 2216 { 2217 DPRINT("Insufficient access rights! 0x%lx\n", 2218 hManager->Handle.DesiredAccess); 2219 return ERROR_ACCESS_DENIED; 2220 } 2221 2222 if (wcslen(lpServiceName) == 0) 2223 { 2224 return ERROR_INVALID_NAME; 2225 } 2226 2227 if (wcslen(lpBinaryPathName) == 0) 2228 { 2229 return ERROR_INVALID_PARAMETER; 2230 } 2231 2232 /* Check for invalid service type value */ 2233 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 2234 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) && 2235 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && 2236 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS)) 2237 return ERROR_INVALID_PARAMETER; 2238 2239 /* Check for invalid start type value */ 2240 if ((dwStartType != SERVICE_BOOT_START) && 2241 (dwStartType != SERVICE_SYSTEM_START) && 2242 (dwStartType != SERVICE_AUTO_START) && 2243 (dwStartType != SERVICE_DEMAND_START) && 2244 (dwStartType != SERVICE_DISABLED)) 2245 return ERROR_INVALID_PARAMETER; 2246 2247 /* Only drivers can be boot start or system start services */ 2248 if ((dwStartType == SERVICE_BOOT_START) || 2249 (dwStartType == SERVICE_SYSTEM_START)) 2250 { 2251 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 2252 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) 2253 return ERROR_INVALID_PARAMETER; 2254 } 2255 2256 /* Check for invalid error control value */ 2257 if ((dwErrorControl != SERVICE_ERROR_IGNORE) && 2258 (dwErrorControl != SERVICE_ERROR_NORMAL) && 2259 (dwErrorControl != SERVICE_ERROR_SEVERE) && 2260 (dwErrorControl != SERVICE_ERROR_CRITICAL)) 2261 return ERROR_INVALID_PARAMETER; 2262 2263 if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) && 2264 (lpServiceStartName)) 2265 { 2266 /* We allow LocalSystem to run interactive. */ 2267 if (wcsicmp(lpServiceStartName, L"LocalSystem")) 2268 { 2269 return ERROR_INVALID_PARAMETER; 2270 } 2271 } 2272 2273 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup)) 2274 { 2275 return ERROR_INVALID_PARAMETER; 2276 } 2277 2278 /* Lock the service database exclusively */ 2279 ScmLockDatabaseExclusive(); 2280 2281 lpService = ScmGetServiceEntryByName(lpServiceName); 2282 if (lpService) 2283 { 2284 /* Unlock the service database */ 2285 ScmUnlockDatabase(); 2286 2287 /* Check if it is marked for deletion */ 2288 if (lpService->bDeleted) 2289 return ERROR_SERVICE_MARKED_FOR_DELETE; 2290 2291 /* Return Error exist */ 2292 return ERROR_SERVICE_EXISTS; 2293 } 2294 2295 if (lpDisplayName != NULL && 2296 ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL) 2297 { 2298 /* Unlock the service database */ 2299 ScmUnlockDatabase(); 2300 2301 return ERROR_DUPLICATE_SERVICE_NAME; 2302 } 2303 2304 if (dwServiceType & SERVICE_DRIVER) 2305 { 2306 dwError = ScmCanonDriverImagePath(dwStartType, 2307 lpBinaryPathName, 2308 &lpImagePath); 2309 if (dwError != ERROR_SUCCESS) 2310 goto done; 2311 } 2312 else 2313 { 2314 if (dwStartType == SERVICE_BOOT_START || 2315 dwStartType == SERVICE_SYSTEM_START) 2316 { 2317 /* Unlock the service database */ 2318 ScmUnlockDatabase(); 2319 2320 return ERROR_INVALID_PARAMETER; 2321 } 2322 } 2323 2324 /* Allocate a new service entry */ 2325 dwError = ScmCreateNewServiceRecord(lpServiceName, 2326 &lpService, 2327 dwServiceType, 2328 dwStartType); 2329 if (dwError != ERROR_SUCCESS) 2330 goto done; 2331 2332 /* Fill the new service entry */ 2333 lpService->dwErrorControl = dwErrorControl; 2334 2335 /* Fill the display name */ 2336 if (lpDisplayName != NULL && 2337 *lpDisplayName != 0 && 2338 _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0) 2339 { 2340 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 2341 HEAP_ZERO_MEMORY, 2342 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 2343 if (lpService->lpDisplayName == NULL) 2344 { 2345 dwError = ERROR_NOT_ENOUGH_MEMORY; 2346 goto done; 2347 } 2348 wcscpy(lpService->lpDisplayName, lpDisplayName); 2349 } 2350 2351 /* Assign the service to a group */ 2352 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2353 { 2354 dwError = ScmSetServiceGroup(lpService, 2355 lpLoadOrderGroup); 2356 if (dwError != ERROR_SUCCESS) 2357 goto done; 2358 } 2359 2360 /* Assign a new tag */ 2361 if (lpdwTagId != NULL) 2362 { 2363 dwError = ScmAssignNewTag(lpService); 2364 if (dwError != ERROR_SUCCESS) 2365 goto done; 2366 } 2367 2368 /* Assign the default security descriptor */ 2369 if (dwServiceType & SERVICE_WIN32) 2370 { 2371 dwError = ScmCreateDefaultServiceSD(&lpService->pSecurityDescriptor); 2372 if (dwError != ERROR_SUCCESS) 2373 goto done; 2374 } 2375 2376 /* Write service data to the registry */ 2377 /* Create the service key */ 2378 dwError = ScmCreateServiceKey(lpServiceName, 2379 KEY_WRITE, 2380 &hServiceKey); 2381 if (dwError != ERROR_SUCCESS) 2382 goto done; 2383 2384 /* Set the display name */ 2385 if (lpDisplayName != NULL && *lpDisplayName != 0) 2386 { 2387 RegSetValueExW(hServiceKey, 2388 L"DisplayName", 2389 0, 2390 REG_SZ, 2391 (LPBYTE)lpDisplayName, 2392 (DWORD)((wcslen(lpDisplayName) + 1) * sizeof(WCHAR))); 2393 } 2394 2395 /* Set the service type */ 2396 dwError = RegSetValueExW(hServiceKey, 2397 L"Type", 2398 0, 2399 REG_DWORD, 2400 (LPBYTE)&dwServiceType, 2401 sizeof(DWORD)); 2402 if (dwError != ERROR_SUCCESS) 2403 goto done; 2404 2405 /* Set the start value */ 2406 dwError = RegSetValueExW(hServiceKey, 2407 L"Start", 2408 0, 2409 REG_DWORD, 2410 (LPBYTE)&dwStartType, 2411 sizeof(DWORD)); 2412 if (dwError != ERROR_SUCCESS) 2413 goto done; 2414 2415 /* Set the error control value */ 2416 dwError = RegSetValueExW(hServiceKey, 2417 L"ErrorControl", 2418 0, 2419 REG_DWORD, 2420 (LPBYTE)&dwErrorControl, 2421 sizeof(DWORD)); 2422 if (dwError != ERROR_SUCCESS) 2423 goto done; 2424 2425 /* Set the image path */ 2426 if (dwServiceType & SERVICE_WIN32) 2427 { 2428 dwError = RegSetValueExW(hServiceKey, 2429 L"ImagePath", 2430 0, 2431 REG_EXPAND_SZ, 2432 (LPBYTE)lpBinaryPathName, 2433 (DWORD)((wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR))); 2434 if (dwError != ERROR_SUCCESS) 2435 goto done; 2436 } 2437 else if (dwServiceType & SERVICE_DRIVER) 2438 { 2439 dwError = RegSetValueExW(hServiceKey, 2440 L"ImagePath", 2441 0, 2442 REG_EXPAND_SZ, 2443 (LPBYTE)lpImagePath, 2444 (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR))); 2445 if (dwError != ERROR_SUCCESS) 2446 goto done; 2447 } 2448 2449 /* Set the group name */ 2450 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 2451 { 2452 dwError = RegSetValueExW(hServiceKey, 2453 L"Group", 2454 0, 2455 REG_SZ, 2456 (LPBYTE)lpLoadOrderGroup, 2457 (DWORD)((wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR))); 2458 if (dwError != ERROR_SUCCESS) 2459 goto done; 2460 } 2461 2462 /* Set the service tag */ 2463 if (lpdwTagId != NULL) 2464 { 2465 dwError = RegSetValueExW(hServiceKey, 2466 L"Tag", 2467 0, 2468 REG_DWORD, 2469 (LPBYTE)&lpService->dwTag, 2470 sizeof(DWORD)); 2471 if (dwError != ERROR_SUCCESS) 2472 goto done; 2473 } 2474 2475 /* Write dependencies */ 2476 if (lpDependencies != NULL && *lpDependencies != 0) 2477 { 2478 dwError = ScmWriteDependencies(hServiceKey, 2479 (LPCWSTR)lpDependencies, 2480 dwDependSize); 2481 if (dwError != ERROR_SUCCESS) 2482 goto done; 2483 } 2484 2485 /* Start name and password are only used by Win32 services */ 2486 if (dwServiceType & SERVICE_WIN32) 2487 { 2488 /* Write service start name */ 2489 lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem"; 2490 dwError = RegSetValueExW(hServiceKey, 2491 L"ObjectName", 2492 0, 2493 REG_SZ, 2494 (LPBYTE)lpObjectName, 2495 (DWORD)((wcslen(lpObjectName) + 1) * sizeof(WCHAR))); 2496 if (dwError != ERROR_SUCCESS) 2497 goto done; 2498 2499 if (lpPassword != NULL && wcslen((LPWSTR)lpPassword) != 0) 2500 { 2501 /* FIXME: Decrypt the password */ 2502 2503 /* Write the password */ 2504 dwError = ScmSetServicePassword(lpServiceName, 2505 (LPCWSTR)lpPassword); 2506 if (dwError != ERROR_SUCCESS) 2507 goto done; 2508 } 2509 2510 DPRINT1("\n"); 2511 /* Write the security descriptor */ 2512 dwError = ScmWriteSecurityDescriptor(hServiceKey, 2513 lpService->pSecurityDescriptor); 2514 if (dwError != ERROR_SUCCESS) 2515 goto done; 2516 } 2517 2518 dwError = ScmCreateServiceHandle(lpService, 2519 &hServiceHandle); 2520 if (dwError != ERROR_SUCCESS) 2521 goto done; 2522 2523 dwError = ScmCheckAccess(hServiceHandle, 2524 dwDesiredAccess); 2525 if (dwError != ERROR_SUCCESS) 2526 goto done; 2527 2528 lpService->dwRefCount = 1; 2529 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount); 2530 2531 done: 2532 /* Unlock the service database */ 2533 ScmUnlockDatabase(); 2534 2535 if (hServiceKey != NULL) 2536 RegCloseKey(hServiceKey); 2537 2538 if (dwError == ERROR_SUCCESS) 2539 { 2540 DPRINT("hService %p\n", hServiceHandle); 2541 *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle; 2542 2543 if (lpdwTagId != NULL) 2544 *lpdwTagId = lpService->dwTag; 2545 } 2546 else 2547 { 2548 if (lpService != NULL && 2549 lpService->lpServiceName != NULL) 2550 { 2551 /* Release the display name buffer */ 2552 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 2553 } 2554 2555 if (hServiceHandle) 2556 { 2557 /* Remove the service handle */ 2558 HeapFree(GetProcessHeap(), 0, hServiceHandle); 2559 } 2560 2561 if (lpService != NULL) 2562 { 2563 /* FIXME: remove the service entry */ 2564 } 2565 } 2566 2567 if (lpImagePath != NULL) 2568 HeapFree(GetProcessHeap(), 0, lpImagePath); 2569 2570 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError); 2571 2572 return dwError; 2573 } 2574 2575 2576 /* Function 13 */ 2577 DWORD 2578 WINAPI 2579 REnumDependentServicesW( 2580 SC_RPC_HANDLE hService, 2581 DWORD dwServiceState, 2582 LPBYTE lpServices, 2583 DWORD cbBufSize, 2584 LPBOUNDED_DWORD_256K pcbBytesNeeded, 2585 LPBOUNDED_DWORD_256K lpServicesReturned) 2586 { 2587 DWORD dwError = ERROR_SUCCESS; 2588 DWORD dwServicesReturned = 0; 2589 DWORD dwServiceCount; 2590 HKEY hServicesKey = NULL; 2591 PSERVICE_HANDLE hSvc; 2592 PSERVICE lpService = NULL; 2593 PSERVICE *lpServicesArray = NULL; 2594 LPENUM_SERVICE_STATUSW lpServicesPtr = NULL; 2595 LPWSTR lpStr; 2596 2597 *pcbBytesNeeded = 0; 2598 *lpServicesReturned = 0; 2599 2600 DPRINT("REnumDependentServicesW() called\n"); 2601 2602 hSvc = ScmGetServiceFromHandle(hService); 2603 if (hSvc == NULL) 2604 { 2605 DPRINT1("Invalid service handle!\n"); 2606 return ERROR_INVALID_HANDLE; 2607 } 2608 2609 lpService = hSvc->ServiceEntry; 2610 2611 /* Check access rights */ 2612 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 2613 SC_MANAGER_ENUMERATE_SERVICE)) 2614 { 2615 DPRINT("Insufficient access rights! 0x%lx\n", 2616 hSvc->Handle.DesiredAccess); 2617 return ERROR_ACCESS_DENIED; 2618 } 2619 2620 /* Open the Services Reg key */ 2621 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 2622 L"System\\CurrentControlSet\\Services", 2623 0, 2624 KEY_READ, 2625 &hServicesKey); 2626 if (dwError != ERROR_SUCCESS) 2627 return dwError; 2628 2629 /* First determine the bytes needed and get the number of dependent services */ 2630 dwError = Int_EnumDependentServicesW(hServicesKey, 2631 lpService, 2632 dwServiceState, 2633 NULL, 2634 pcbBytesNeeded, 2635 &dwServicesReturned); 2636 if (dwError != ERROR_SUCCESS) 2637 goto Done; 2638 2639 /* If buffer size is less than the bytes needed or pointer is null */ 2640 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 2641 { 2642 dwError = ERROR_MORE_DATA; 2643 goto Done; 2644 } 2645 2646 /* Allocate memory for array of service pointers */ 2647 lpServicesArray = HeapAlloc(GetProcessHeap(), 2648 HEAP_ZERO_MEMORY, 2649 (dwServicesReturned + 1) * sizeof(PSERVICE)); 2650 if (!lpServicesArray) 2651 { 2652 DPRINT1("Could not allocate a buffer!!\n"); 2653 dwError = ERROR_NOT_ENOUGH_MEMORY; 2654 goto Done; 2655 } 2656 2657 dwServicesReturned = 0; 2658 *pcbBytesNeeded = 0; 2659 2660 dwError = Int_EnumDependentServicesW(hServicesKey, 2661 lpService, 2662 dwServiceState, 2663 lpServicesArray, 2664 pcbBytesNeeded, 2665 &dwServicesReturned); 2666 if (dwError != ERROR_SUCCESS) 2667 { 2668 goto Done; 2669 } 2670 2671 lpServicesPtr = (LPENUM_SERVICE_STATUSW)lpServices; 2672 lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW))); 2673 2674 /* Copy EnumDepenedentService to Buffer */ 2675 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 2676 { 2677 lpService = lpServicesArray[dwServiceCount]; 2678 2679 /* Copy status info */ 2680 memcpy(&lpServicesPtr->ServiceStatus, 2681 &lpService->Status, 2682 sizeof(SERVICE_STATUS)); 2683 2684 /* Copy display name */ 2685 wcscpy(lpStr, lpService->lpDisplayName); 2686 lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 2687 lpStr += (wcslen(lpService->lpDisplayName) + 1); 2688 2689 /* Copy service name */ 2690 wcscpy(lpStr, lpService->lpServiceName); 2691 lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 2692 lpStr += (wcslen(lpService->lpServiceName) + 1); 2693 2694 lpServicesPtr++; 2695 } 2696 2697 *lpServicesReturned = dwServicesReturned; 2698 2699 Done: 2700 if (lpServicesArray != NULL) 2701 HeapFree(GetProcessHeap(), 0, lpServicesArray); 2702 2703 RegCloseKey(hServicesKey); 2704 2705 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError); 2706 2707 return dwError; 2708 } 2709 2710 2711 /* Function 14 */ 2712 DWORD 2713 WINAPI 2714 REnumServicesStatusW( 2715 SC_RPC_HANDLE hSCManager, 2716 DWORD dwServiceType, 2717 DWORD dwServiceState, 2718 LPBYTE lpBuffer, 2719 DWORD dwBufSize, 2720 LPBOUNDED_DWORD_256K pcbBytesNeeded, 2721 LPBOUNDED_DWORD_256K lpServicesReturned, 2722 LPBOUNDED_DWORD_256K lpResumeHandle) 2723 { 2724 /* Enumerate all the services, not regarding of their group */ 2725 return REnumServiceGroupW(hSCManager, 2726 dwServiceType, 2727 dwServiceState, 2728 lpBuffer, 2729 dwBufSize, 2730 pcbBytesNeeded, 2731 lpServicesReturned, 2732 lpResumeHandle, 2733 NULL); 2734 } 2735 2736 2737 /* Function 15 */ 2738 DWORD 2739 WINAPI 2740 ROpenSCManagerW( 2741 LPWSTR lpMachineName, 2742 LPWSTR lpDatabaseName, 2743 DWORD dwDesiredAccess, 2744 LPSC_RPC_HANDLE lpScHandle) 2745 { 2746 DWORD dwError; 2747 SC_HANDLE hHandle; 2748 2749 DPRINT("ROpenSCManagerW() called\n"); 2750 DPRINT("lpMachineName = %p\n", lpMachineName); 2751 DPRINT("lpMachineName: %S\n", lpMachineName); 2752 DPRINT("lpDataBaseName = %p\n", lpDatabaseName); 2753 DPRINT("lpDataBaseName: %S\n", lpDatabaseName); 2754 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 2755 2756 if (ScmShutdown) 2757 return ERROR_SHUTDOWN_IN_PROGRESS; 2758 2759 if (!lpScHandle) 2760 return ERROR_INVALID_PARAMETER; 2761 2762 dwError = ScmCreateManagerHandle(lpDatabaseName, 2763 &hHandle); 2764 if (dwError != ERROR_SUCCESS) 2765 { 2766 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError); 2767 return dwError; 2768 } 2769 2770 /* Check the desired access */ 2771 dwError = ScmCheckAccess(hHandle, 2772 dwDesiredAccess | SC_MANAGER_CONNECT); 2773 if (dwError != ERROR_SUCCESS) 2774 { 2775 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 2776 HeapFree(GetProcessHeap(), 0, hHandle); 2777 return dwError; 2778 } 2779 2780 *lpScHandle = (SC_RPC_HANDLE)hHandle; 2781 DPRINT("*hScm = %p\n", *lpScHandle); 2782 2783 DPRINT("ROpenSCManagerW() done\n"); 2784 2785 return ERROR_SUCCESS; 2786 } 2787 2788 2789 /* Function 16 */ 2790 DWORD 2791 WINAPI 2792 ROpenServiceW( 2793 SC_RPC_HANDLE hSCManager, 2794 LPWSTR lpServiceName, 2795 DWORD dwDesiredAccess, 2796 LPSC_RPC_HANDLE lpServiceHandle) 2797 { 2798 PSERVICE lpService; 2799 PMANAGER_HANDLE hManager; 2800 SC_HANDLE hHandle; 2801 DWORD dwError = ERROR_SUCCESS; 2802 2803 DPRINT("ROpenServiceW() called\n"); 2804 DPRINT("hSCManager = %p\n", hSCManager); 2805 DPRINT("lpServiceName = %p\n", lpServiceName); 2806 DPRINT("lpServiceName: %S\n", lpServiceName); 2807 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 2808 2809 if (ScmShutdown) 2810 return ERROR_SHUTDOWN_IN_PROGRESS; 2811 2812 hManager = ScmGetServiceManagerFromHandle(hSCManager); 2813 if (hManager == NULL) 2814 { 2815 DPRINT1("Invalid service manager handle!\n"); 2816 return ERROR_INVALID_HANDLE; 2817 } 2818 2819 if (!lpServiceHandle) 2820 return ERROR_INVALID_PARAMETER; 2821 2822 if (!lpServiceName) 2823 return ERROR_INVALID_ADDRESS; 2824 2825 /* Lock the service database exclusive */ 2826 ScmLockDatabaseExclusive(); 2827 2828 /* Get service database entry */ 2829 lpService = ScmGetServiceEntryByName(lpServiceName); 2830 if (lpService == NULL) 2831 { 2832 DPRINT("Could not find a service!\n"); 2833 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 2834 goto Done; 2835 } 2836 2837 /* Create a service handle */ 2838 dwError = ScmCreateServiceHandle(lpService, 2839 &hHandle); 2840 if (dwError != ERROR_SUCCESS) 2841 { 2842 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError); 2843 goto Done; 2844 } 2845 2846 /* Check the desired access */ 2847 dwError = ScmCheckAccess(hHandle, 2848 dwDesiredAccess); 2849 if (dwError != ERROR_SUCCESS) 2850 { 2851 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 2852 HeapFree(GetProcessHeap(), 0, hHandle); 2853 goto Done; 2854 } 2855 2856 lpService->dwRefCount++; 2857 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount); 2858 2859 *lpServiceHandle = (SC_RPC_HANDLE)hHandle; 2860 DPRINT("*hService = %p\n", *lpServiceHandle); 2861 2862 Done: 2863 /* Unlock the service database */ 2864 ScmUnlockDatabase(); 2865 2866 DPRINT("ROpenServiceW() done\n"); 2867 2868 return dwError; 2869 } 2870 2871 2872 /* Function 17 */ 2873 DWORD 2874 WINAPI 2875 RQueryServiceConfigW( 2876 SC_RPC_HANDLE hService, 2877 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig, 2878 DWORD cbBufSize, 2879 LPBOUNDED_DWORD_8K pcbBytesNeeded) 2880 { 2881 LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf; 2882 DWORD dwError = ERROR_SUCCESS; 2883 PSERVICE_HANDLE hSvc; 2884 PSERVICE lpService = NULL; 2885 HKEY hServiceKey = NULL; 2886 LPWSTR lpImagePath = NULL; 2887 LPWSTR lpServiceStartName = NULL; 2888 LPWSTR lpDependencies = NULL; 2889 DWORD dwDependenciesLength = 0; 2890 DWORD dwRequiredSize; 2891 WCHAR lpEmptyString[] = {0,0}; 2892 LPWSTR lpStr; 2893 2894 DPRINT("RQueryServiceConfigW() called\n"); 2895 2896 if (ScmShutdown) 2897 return ERROR_SHUTDOWN_IN_PROGRESS; 2898 2899 hSvc = ScmGetServiceFromHandle(hService); 2900 if (hSvc == NULL) 2901 { 2902 DPRINT1("Invalid service handle!\n"); 2903 return ERROR_INVALID_HANDLE; 2904 } 2905 2906 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 2907 SERVICE_QUERY_CONFIG)) 2908 { 2909 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 2910 return ERROR_ACCESS_DENIED; 2911 } 2912 2913 lpService = hSvc->ServiceEntry; 2914 if (lpService == NULL) 2915 { 2916 DPRINT("lpService == NULL!\n"); 2917 return ERROR_INVALID_HANDLE; 2918 } 2919 2920 /* Lock the service database shared */ 2921 ScmLockDatabaseShared(); 2922 2923 dwError = ScmOpenServiceKey(lpService->lpServiceName, 2924 KEY_READ, 2925 &hServiceKey); 2926 if (dwError != ERROR_SUCCESS) 2927 goto Done; 2928 2929 /* Read the image path */ 2930 dwError = ScmReadString(hServiceKey, 2931 L"ImagePath", 2932 &lpImagePath); 2933 if (dwError != ERROR_SUCCESS) 2934 goto Done; 2935 2936 /* Read the service start name */ 2937 ScmReadString(hServiceKey, 2938 L"ObjectName", 2939 &lpServiceStartName); 2940 2941 /* Read the dependencies */ 2942 ScmReadDependencies(hServiceKey, 2943 &lpDependencies, 2944 &dwDependenciesLength); 2945 2946 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW); 2947 2948 if (lpImagePath != NULL) 2949 dwRequiredSize += (DWORD)((wcslen(lpImagePath) + 1) * sizeof(WCHAR)); 2950 else 2951 dwRequiredSize += 2 * sizeof(WCHAR); 2952 2953 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 2954 dwRequiredSize += (DWORD)((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR)); 2955 else 2956 dwRequiredSize += 2 * sizeof(WCHAR); 2957 2958 if (lpDependencies != NULL) 2959 dwRequiredSize += dwDependenciesLength * sizeof(WCHAR); 2960 else 2961 dwRequiredSize += 2 * sizeof(WCHAR); 2962 2963 if (lpServiceStartName != NULL) 2964 dwRequiredSize += (DWORD)((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)); 2965 else 2966 dwRequiredSize += 2 * sizeof(WCHAR); 2967 2968 if (lpService->lpDisplayName != NULL) 2969 dwRequiredSize += (DWORD)((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR)); 2970 else 2971 dwRequiredSize += 2 * sizeof(WCHAR); 2972 2973 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 2974 { 2975 dwError = ERROR_INSUFFICIENT_BUFFER; 2976 } 2977 else 2978 { 2979 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType; 2980 lpServiceConfig->dwStartType = lpService->dwStartType; 2981 lpServiceConfig->dwErrorControl = lpService->dwErrorControl; 2982 lpServiceConfig->dwTagId = lpService->dwTag; 2983 2984 lpStr = (LPWSTR)(lpServiceConfig + 1); 2985 2986 /* Append the image path */ 2987 if (lpImagePath != NULL) 2988 { 2989 wcscpy(lpStr, lpImagePath); 2990 } 2991 else 2992 { 2993 wcscpy(lpStr, lpEmptyString); 2994 } 2995 2996 lpServiceConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 2997 lpStr += (wcslen(lpStr) + 1); 2998 2999 /* Append the group name */ 3000 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 3001 { 3002 wcscpy(lpStr, lpService->lpGroup->lpGroupName); 3003 } 3004 else 3005 { 3006 wcscpy(lpStr, lpEmptyString); 3007 } 3008 3009 lpServiceConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3010 lpStr += (wcslen(lpStr) + 1); 3011 3012 /* Append Dependencies */ 3013 if (lpDependencies != NULL) 3014 { 3015 memcpy(lpStr, 3016 lpDependencies, 3017 dwDependenciesLength * sizeof(WCHAR)); 3018 } 3019 else 3020 { 3021 wcscpy(lpStr, lpEmptyString); 3022 } 3023 3024 lpServiceConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3025 if (lpDependencies != NULL) 3026 lpStr += dwDependenciesLength; 3027 else 3028 lpStr += (wcslen(lpStr) + 1); 3029 3030 /* Append the service start name */ 3031 if (lpServiceStartName != NULL) 3032 { 3033 wcscpy(lpStr, lpServiceStartName); 3034 } 3035 else 3036 { 3037 wcscpy(lpStr, lpEmptyString); 3038 } 3039 3040 lpServiceConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3041 lpStr += (wcslen(lpStr) + 1); 3042 3043 /* Append the display name */ 3044 if (lpService->lpDisplayName != NULL) 3045 { 3046 wcscpy(lpStr, lpService->lpDisplayName); 3047 } 3048 else 3049 { 3050 wcscpy(lpStr, lpEmptyString); 3051 } 3052 3053 lpServiceConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 3054 } 3055 3056 if (pcbBytesNeeded != NULL) 3057 *pcbBytesNeeded = dwRequiredSize; 3058 3059 Done: 3060 /* Unlock the service database */ 3061 ScmUnlockDatabase(); 3062 3063 if (lpImagePath != NULL) 3064 HeapFree(GetProcessHeap(), 0, lpImagePath); 3065 3066 if (lpServiceStartName != NULL) 3067 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 3068 3069 if (lpDependencies != NULL) 3070 HeapFree(GetProcessHeap(), 0, lpDependencies); 3071 3072 if (hServiceKey != NULL) 3073 RegCloseKey(hServiceKey); 3074 3075 DPRINT("RQueryServiceConfigW() done\n"); 3076 3077 return dwError; 3078 } 3079 3080 3081 /* Function 18 */ 3082 DWORD 3083 WINAPI 3084 RQueryServiceLockStatusW( 3085 SC_RPC_HANDLE hSCManager, 3086 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, 3087 DWORD cbBufSize, 3088 LPBOUNDED_DWORD_4K pcbBytesNeeded) 3089 { 3090 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSW)lpBuf; 3091 PMANAGER_HANDLE hMgr; 3092 DWORD dwRequiredSize; 3093 3094 if (!lpLockStatus || !pcbBytesNeeded) 3095 return ERROR_INVALID_PARAMETER; 3096 3097 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 3098 if (hMgr == NULL) 3099 { 3100 DPRINT1("Invalid service manager handle!\n"); 3101 return ERROR_INVALID_HANDLE; 3102 } 3103 3104 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 3105 SC_MANAGER_QUERY_LOCK_STATUS)) 3106 { 3107 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess); 3108 return ERROR_ACCESS_DENIED; 3109 } 3110 3111 /* FIXME: we need to compute instead the real length of the owner name */ 3112 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR); 3113 *pcbBytesNeeded = dwRequiredSize; 3114 3115 if (cbBufSize < dwRequiredSize) 3116 return ERROR_INSUFFICIENT_BUFFER; 3117 3118 ScmQueryServiceLockStatusW(lpLockStatus); 3119 3120 return ERROR_SUCCESS; 3121 } 3122 3123 3124 /* Function 19 */ 3125 DWORD 3126 WINAPI 3127 RStartServiceW( 3128 SC_RPC_HANDLE hService, 3129 DWORD argc, 3130 LPSTRING_PTRSW argv) 3131 { 3132 DWORD dwError = ERROR_SUCCESS; 3133 PSERVICE_HANDLE hSvc; 3134 PSERVICE lpService = NULL; 3135 3136 #ifndef NDEBUG 3137 DWORD i; 3138 3139 DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv); 3140 DPRINT(" argc: %lu\n", argc); 3141 if (argv != NULL) 3142 { 3143 for (i = 0; i < argc; i++) 3144 { 3145 DPRINT(" argv[%lu]: %S\n", i, argv[i].StringPtr); 3146 } 3147 } 3148 #endif 3149 3150 if (ScmShutdown) 3151 return ERROR_SHUTDOWN_IN_PROGRESS; 3152 3153 hSvc = ScmGetServiceFromHandle(hService); 3154 if (hSvc == NULL) 3155 { 3156 DPRINT1("Invalid service handle!\n"); 3157 return ERROR_INVALID_HANDLE; 3158 } 3159 3160 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3161 SERVICE_START)) 3162 { 3163 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 3164 return ERROR_ACCESS_DENIED; 3165 } 3166 3167 lpService = hSvc->ServiceEntry; 3168 if (lpService == NULL) 3169 { 3170 DPRINT("lpService == NULL!\n"); 3171 return ERROR_INVALID_HANDLE; 3172 } 3173 3174 if (lpService->dwStartType == SERVICE_DISABLED) 3175 return ERROR_SERVICE_DISABLED; 3176 3177 if (lpService->bDeleted) 3178 return ERROR_SERVICE_MARKED_FOR_DELETE; 3179 3180 /* Start the service */ 3181 dwError = ScmStartService(lpService, argc, (LPWSTR*)argv); 3182 3183 return dwError; 3184 } 3185 3186 3187 /* Function 20 */ 3188 DWORD 3189 WINAPI 3190 RGetServiceDisplayNameW( 3191 SC_RPC_HANDLE hSCManager, 3192 LPCWSTR lpServiceName, 3193 LPWSTR lpDisplayName, 3194 DWORD *lpcchBuffer) 3195 { 3196 // PMANAGER_HANDLE hManager; 3197 PSERVICE lpService; 3198 DWORD dwLength; 3199 DWORD dwError; 3200 3201 DPRINT("RGetServiceDisplayNameW() called\n"); 3202 DPRINT("hSCManager = %p\n", hSCManager); 3203 DPRINT("lpServiceName: %S\n", lpServiceName); 3204 DPRINT("lpDisplayName: %p\n", lpDisplayName); 3205 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 3206 3207 // hManager = (PMANAGER_HANDLE)hSCManager; 3208 // if (hManager->Handle.Tag != MANAGER_TAG) 3209 // { 3210 // DPRINT("Invalid manager handle!\n"); 3211 // return ERROR_INVALID_HANDLE; 3212 // } 3213 3214 /* Get service database entry */ 3215 lpService = ScmGetServiceEntryByName(lpServiceName); 3216 if (lpService == NULL) 3217 { 3218 DPRINT("Could not find a service!\n"); 3219 3220 /* If the service could not be found and lpcchBuffer is less than 2, windows 3221 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 3222 if (*lpcchBuffer < 2) 3223 { 3224 *lpcchBuffer = 2; 3225 if (lpDisplayName != NULL) 3226 { 3227 *lpDisplayName = 0; 3228 } 3229 } 3230 3231 return ERROR_SERVICE_DOES_NOT_EXIST; 3232 } 3233 3234 if (!lpService->lpDisplayName) 3235 { 3236 dwLength = (DWORD)wcslen(lpService->lpServiceName); 3237 3238 if (lpDisplayName != NULL && 3239 *lpcchBuffer > dwLength) 3240 { 3241 wcscpy(lpDisplayName, lpService->lpServiceName); 3242 } 3243 } 3244 else 3245 { 3246 dwLength = (DWORD)wcslen(lpService->lpDisplayName); 3247 3248 if (lpDisplayName != NULL && 3249 *lpcchBuffer > dwLength) 3250 { 3251 wcscpy(lpDisplayName, lpService->lpDisplayName); 3252 } 3253 } 3254 3255 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 3256 3257 *lpcchBuffer = dwLength; 3258 3259 return dwError; 3260 } 3261 3262 3263 /* Function 21 */ 3264 DWORD 3265 WINAPI 3266 RGetServiceKeyNameW( 3267 SC_RPC_HANDLE hSCManager, 3268 LPCWSTR lpDisplayName, 3269 LPWSTR lpServiceName, 3270 DWORD *lpcchBuffer) 3271 { 3272 // PMANAGER_HANDLE hManager; 3273 PSERVICE lpService; 3274 DWORD dwLength; 3275 DWORD dwError; 3276 3277 DPRINT("RGetServiceKeyNameW() called\n"); 3278 DPRINT("hSCManager = %p\n", hSCManager); 3279 DPRINT("lpDisplayName: %S\n", lpDisplayName); 3280 DPRINT("lpServiceName: %p\n", lpServiceName); 3281 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 3282 3283 // hManager = (PMANAGER_HANDLE)hSCManager; 3284 // if (hManager->Handle.Tag != MANAGER_TAG) 3285 // { 3286 // DPRINT("Invalid manager handle!\n"); 3287 // return ERROR_INVALID_HANDLE; 3288 // } 3289 3290 /* Get service database entry */ 3291 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName); 3292 if (lpService == NULL) 3293 { 3294 DPRINT("Could not find a service!\n"); 3295 3296 /* If the service could not be found and lpcchBuffer is less than 2, windows 3297 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 3298 if (*lpcchBuffer < 2) 3299 { 3300 *lpcchBuffer = 2; 3301 if (lpServiceName != NULL) 3302 { 3303 *lpServiceName = 0; 3304 } 3305 } 3306 3307 return ERROR_SERVICE_DOES_NOT_EXIST; 3308 } 3309 3310 dwLength = (DWORD)wcslen(lpService->lpServiceName); 3311 3312 if (lpServiceName != NULL && 3313 *lpcchBuffer > dwLength) 3314 { 3315 wcscpy(lpServiceName, lpService->lpServiceName); 3316 *lpcchBuffer = dwLength; 3317 return ERROR_SUCCESS; 3318 } 3319 3320 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 3321 3322 *lpcchBuffer = dwLength; 3323 3324 return dwError; 3325 } 3326 3327 3328 /* Function 22 */ 3329 DWORD 3330 WINAPI 3331 RI_ScSetServiceBitsA( 3332 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 3333 DWORD dwServiceBits, 3334 int bSetBitsOn, 3335 int bUpdateImmediately, 3336 char *lpString) 3337 { 3338 UNIMPLEMENTED; 3339 return ERROR_CALL_NOT_IMPLEMENTED; 3340 } 3341 3342 3343 /* Function 23 */ 3344 DWORD 3345 WINAPI 3346 RChangeServiceConfigA( 3347 SC_RPC_HANDLE hService, 3348 DWORD dwServiceType, 3349 DWORD dwStartType, 3350 DWORD dwErrorControl, 3351 LPSTR lpBinaryPathName, 3352 LPSTR lpLoadOrderGroup, 3353 LPDWORD lpdwTagId, 3354 LPBYTE lpDependencies, 3355 DWORD dwDependSize, 3356 LPSTR lpServiceStartName, 3357 LPBYTE lpPassword, 3358 DWORD dwPwSize, 3359 LPSTR lpDisplayName) 3360 { 3361 DWORD dwError = ERROR_SUCCESS; 3362 PSERVICE_HANDLE hSvc; 3363 PSERVICE lpService = NULL; 3364 HKEY hServiceKey = NULL; 3365 LPWSTR lpDisplayNameW = NULL; 3366 LPWSTR lpBinaryPathNameW = NULL; 3367 LPWSTR lpCanonicalImagePathW = NULL; 3368 LPWSTR lpLoadOrderGroupW = NULL; 3369 LPWSTR lpDependenciesW = NULL; 3370 3371 DPRINT("RChangeServiceConfigA() called\n"); 3372 DPRINT("dwServiceType = %lu\n", dwServiceType); 3373 DPRINT("dwStartType = %lu\n", dwStartType); 3374 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 3375 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName); 3376 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup); 3377 DPRINT("lpDisplayName = %s\n", lpDisplayName); 3378 3379 if (ScmShutdown) 3380 return ERROR_SHUTDOWN_IN_PROGRESS; 3381 3382 hSvc = ScmGetServiceFromHandle(hService); 3383 if (hSvc == NULL) 3384 { 3385 DPRINT1("Invalid service handle!\n"); 3386 return ERROR_INVALID_HANDLE; 3387 } 3388 3389 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3390 SERVICE_CHANGE_CONFIG)) 3391 { 3392 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 3393 return ERROR_ACCESS_DENIED; 3394 } 3395 3396 lpService = hSvc->ServiceEntry; 3397 if (lpService == NULL) 3398 { 3399 DPRINT("lpService == NULL!\n"); 3400 return ERROR_INVALID_HANDLE; 3401 } 3402 3403 /* Lock the service database exclusively */ 3404 ScmLockDatabaseExclusive(); 3405 3406 if (lpService->bDeleted) 3407 { 3408 DPRINT("The service has already been marked for delete!\n"); 3409 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 3410 goto done; 3411 } 3412 3413 /* Open the service key */ 3414 dwError = ScmOpenServiceKey(lpService->szServiceName, 3415 KEY_SET_VALUE, 3416 &hServiceKey); 3417 if (dwError != ERROR_SUCCESS) 3418 goto done; 3419 3420 /* Write service data to the registry */ 3421 3422 if (lpDisplayName != NULL && *lpDisplayName != 0) 3423 { 3424 /* Set the display name */ 3425 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 3426 HEAP_ZERO_MEMORY, 3427 (strlen(lpDisplayName) + 1) * sizeof(WCHAR)); 3428 if (lpDisplayNameW == NULL) 3429 { 3430 dwError = ERROR_NOT_ENOUGH_MEMORY; 3431 goto done; 3432 } 3433 3434 MultiByteToWideChar(CP_ACP, 3435 0, 3436 lpDisplayName, 3437 -1, 3438 lpDisplayNameW, 3439 (int)(strlen(lpDisplayName) + 1)); 3440 3441 RegSetValueExW(hServiceKey, 3442 L"DisplayName", 3443 0, 3444 REG_SZ, 3445 (LPBYTE)lpDisplayNameW, 3446 (DWORD)((wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR))); 3447 3448 /* Update lpService->lpDisplayName */ 3449 if (lpService->lpDisplayName) 3450 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 3451 3452 lpService->lpDisplayName = lpDisplayNameW; 3453 } 3454 3455 if (dwServiceType != SERVICE_NO_CHANGE) 3456 { 3457 /* Set the service type */ 3458 dwError = RegSetValueExW(hServiceKey, 3459 L"Type", 3460 0, 3461 REG_DWORD, 3462 (LPBYTE)&dwServiceType, 3463 sizeof(DWORD)); 3464 if (dwError != ERROR_SUCCESS) 3465 goto done; 3466 3467 lpService->Status.dwServiceType = dwServiceType; 3468 } 3469 3470 if (dwStartType != SERVICE_NO_CHANGE) 3471 { 3472 /* Set the start value */ 3473 dwError = RegSetValueExW(hServiceKey, 3474 L"Start", 3475 0, 3476 REG_DWORD, 3477 (LPBYTE)&dwStartType, 3478 sizeof(DWORD)); 3479 if (dwError != ERROR_SUCCESS) 3480 goto done; 3481 3482 lpService->dwStartType = dwStartType; 3483 } 3484 3485 if (dwErrorControl != SERVICE_NO_CHANGE) 3486 { 3487 /* Set the error control value */ 3488 dwError = RegSetValueExW(hServiceKey, 3489 L"ErrorControl", 3490 0, 3491 REG_DWORD, 3492 (LPBYTE)&dwErrorControl, 3493 sizeof(DWORD)); 3494 if (dwError != ERROR_SUCCESS) 3495 goto done; 3496 3497 lpService->dwErrorControl = dwErrorControl; 3498 } 3499 3500 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 3501 { 3502 /* Set the image path */ 3503 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 3504 HEAP_ZERO_MEMORY, 3505 (strlen(lpBinaryPathName) + 1) * sizeof(WCHAR)); 3506 if (lpBinaryPathNameW == NULL) 3507 { 3508 dwError = ERROR_NOT_ENOUGH_MEMORY; 3509 goto done; 3510 } 3511 3512 MultiByteToWideChar(CP_ACP, 3513 0, 3514 lpBinaryPathName, 3515 -1, 3516 lpBinaryPathNameW, 3517 (int)(strlen(lpBinaryPathName) + 1)); 3518 3519 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 3520 { 3521 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 3522 lpBinaryPathNameW, 3523 &lpCanonicalImagePathW); 3524 3525 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3526 3527 if (dwError != ERROR_SUCCESS) 3528 goto done; 3529 3530 lpBinaryPathNameW = lpCanonicalImagePathW; 3531 } 3532 3533 dwError = RegSetValueExW(hServiceKey, 3534 L"ImagePath", 3535 0, 3536 REG_EXPAND_SZ, 3537 (LPBYTE)lpBinaryPathNameW, 3538 (DWORD)((wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR))); 3539 3540 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3541 3542 if (dwError != ERROR_SUCCESS) 3543 goto done; 3544 } 3545 3546 /* Set the group name */ 3547 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 3548 { 3549 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 3550 HEAP_ZERO_MEMORY, 3551 (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); 3552 if (lpLoadOrderGroupW == NULL) 3553 { 3554 dwError = ERROR_NOT_ENOUGH_MEMORY; 3555 goto done; 3556 } 3557 3558 MultiByteToWideChar(CP_ACP, 3559 0, 3560 lpLoadOrderGroup, 3561 -1, 3562 lpLoadOrderGroupW, 3563 (int)(strlen(lpLoadOrderGroup) + 1)); 3564 3565 dwError = RegSetValueExW(hServiceKey, 3566 L"Group", 3567 0, 3568 REG_SZ, 3569 (LPBYTE)lpLoadOrderGroupW, 3570 (DWORD)((wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR))); 3571 if (dwError != ERROR_SUCCESS) 3572 { 3573 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3574 goto done; 3575 } 3576 3577 dwError = ScmSetServiceGroup(lpService, 3578 lpLoadOrderGroupW); 3579 3580 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3581 3582 if (dwError != ERROR_SUCCESS) 3583 goto done; 3584 } 3585 3586 if (lpdwTagId != NULL) 3587 { 3588 dwError = ScmAssignNewTag(lpService); 3589 if (dwError != ERROR_SUCCESS) 3590 goto done; 3591 3592 dwError = RegSetValueExW(hServiceKey, 3593 L"Tag", 3594 0, 3595 REG_DWORD, 3596 (LPBYTE)&lpService->dwTag, 3597 sizeof(DWORD)); 3598 if (dwError != ERROR_SUCCESS) 3599 goto done; 3600 3601 *lpdwTagId = lpService->dwTag; 3602 } 3603 3604 /* Write dependencies */ 3605 if (lpDependencies != NULL && *lpDependencies != 0) 3606 { 3607 lpDependenciesW = HeapAlloc(GetProcessHeap(), 3608 HEAP_ZERO_MEMORY, 3609 (strlen((LPSTR)lpDependencies) + 1) * sizeof(WCHAR)); 3610 if (lpDependenciesW == NULL) 3611 { 3612 dwError = ERROR_NOT_ENOUGH_MEMORY; 3613 goto done; 3614 } 3615 3616 MultiByteToWideChar(CP_ACP, 3617 0, 3618 (LPSTR)lpDependencies, 3619 dwDependSize, 3620 lpDependenciesW, 3621 (int)(strlen((LPSTR)lpDependencies) + 1)); 3622 3623 dwError = ScmWriteDependencies(hServiceKey, 3624 (LPWSTR)lpDependenciesW, 3625 dwDependSize); 3626 3627 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 3628 3629 if (dwError != ERROR_SUCCESS) 3630 goto done; 3631 } 3632 3633 if (lpPassword != NULL) 3634 { 3635 if (wcslen((LPWSTR)lpPassword) != 0) 3636 { 3637 /* FIXME: Decrypt the password */ 3638 3639 /* Write the password */ 3640 dwError = ScmSetServicePassword(lpService->szServiceName, 3641 (LPCWSTR)lpPassword); 3642 if (dwError != ERROR_SUCCESS) 3643 goto done; 3644 } 3645 else 3646 { 3647 /* Delete the password */ 3648 dwError = ScmSetServicePassword(lpService->szServiceName, 3649 NULL); 3650 if (dwError == ERROR_FILE_NOT_FOUND) 3651 dwError = ERROR_SUCCESS; 3652 3653 if (dwError != ERROR_SUCCESS) 3654 goto done; 3655 } 3656 } 3657 3658 done: 3659 /* Unlock the service database */ 3660 ScmUnlockDatabase(); 3661 3662 if (hServiceKey != NULL) 3663 RegCloseKey(hServiceKey); 3664 3665 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError); 3666 3667 return dwError; 3668 } 3669 3670 3671 /* Function 24 */ 3672 DWORD 3673 WINAPI 3674 RCreateServiceA( 3675 SC_RPC_HANDLE hSCManager, 3676 LPSTR lpServiceName, 3677 LPSTR lpDisplayName, 3678 DWORD dwDesiredAccess, 3679 DWORD dwServiceType, 3680 DWORD dwStartType, 3681 DWORD dwErrorControl, 3682 LPSTR lpBinaryPathName, 3683 LPSTR lpLoadOrderGroup, 3684 LPDWORD lpdwTagId, 3685 LPBYTE lpDependencies, 3686 DWORD dwDependSize, 3687 LPSTR lpServiceStartName, 3688 LPBYTE lpPassword, 3689 DWORD dwPwSize, 3690 LPSC_RPC_HANDLE lpServiceHandle) 3691 { 3692 DWORD dwError = ERROR_SUCCESS; 3693 LPWSTR lpServiceNameW = NULL; 3694 LPWSTR lpDisplayNameW = NULL; 3695 LPWSTR lpBinaryPathNameW = NULL; 3696 LPWSTR lpLoadOrderGroupW = NULL; 3697 LPWSTR lpDependenciesW = NULL; 3698 LPWSTR lpServiceStartNameW = NULL; 3699 DWORD dwDependenciesLength = 0; 3700 SIZE_T cchLength; 3701 int len; 3702 LPCSTR lpStr; 3703 3704 if (lpServiceName) 3705 { 3706 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0); 3707 lpServiceNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3708 if (!lpServiceNameW) 3709 { 3710 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3711 goto cleanup; 3712 } 3713 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len); 3714 } 3715 3716 if (lpDisplayName) 3717 { 3718 len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0); 3719 lpDisplayNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3720 if (!lpDisplayNameW) 3721 { 3722 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3723 goto cleanup; 3724 } 3725 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len); 3726 } 3727 3728 if (lpBinaryPathName) 3729 { 3730 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0); 3731 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3732 if (!lpBinaryPathNameW) 3733 { 3734 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3735 goto cleanup; 3736 } 3737 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len); 3738 } 3739 3740 if (lpLoadOrderGroup) 3741 { 3742 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0); 3743 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3744 if (!lpLoadOrderGroupW) 3745 { 3746 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3747 goto cleanup; 3748 } 3749 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len); 3750 } 3751 3752 if (lpDependencies) 3753 { 3754 lpStr = (LPCSTR)lpDependencies; 3755 while (*lpStr) 3756 { 3757 cchLength = strlen(lpStr) + 1; 3758 dwDependenciesLength += (DWORD)cchLength; 3759 lpStr = lpStr + cchLength; 3760 } 3761 dwDependenciesLength++; 3762 3763 lpDependenciesW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDependenciesLength * sizeof(WCHAR)); 3764 if (!lpDependenciesW) 3765 { 3766 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3767 goto cleanup; 3768 } 3769 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength); 3770 } 3771 3772 if (lpServiceStartName) 3773 { 3774 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0); 3775 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); 3776 if (!lpServiceStartNameW) 3777 { 3778 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3779 goto cleanup; 3780 } 3781 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len); 3782 } 3783 3784 dwError = RCreateServiceW(hSCManager, 3785 lpServiceNameW, 3786 lpDisplayNameW, 3787 dwDesiredAccess, 3788 dwServiceType, 3789 dwStartType, 3790 dwErrorControl, 3791 lpBinaryPathNameW, 3792 lpLoadOrderGroupW, 3793 lpdwTagId, 3794 (LPBYTE)lpDependenciesW, 3795 dwDependenciesLength, 3796 lpServiceStartNameW, 3797 lpPassword, 3798 dwPwSize, 3799 lpServiceHandle); 3800 3801 cleanup: 3802 if (lpServiceNameW !=NULL) 3803 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 3804 3805 if (lpDisplayNameW != NULL) 3806 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 3807 3808 if (lpBinaryPathNameW != NULL) 3809 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 3810 3811 if (lpLoadOrderGroupW != NULL) 3812 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 3813 3814 if (lpDependenciesW != NULL) 3815 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 3816 3817 if (lpServiceStartNameW != NULL) 3818 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW); 3819 3820 return dwError; 3821 } 3822 3823 3824 /* Function 25 */ 3825 DWORD 3826 WINAPI 3827 REnumDependentServicesA( 3828 SC_RPC_HANDLE hService, 3829 DWORD dwServiceState, 3830 LPBYTE lpServices, 3831 DWORD cbBufSize, 3832 LPBOUNDED_DWORD_256K pcbBytesNeeded, 3833 LPBOUNDED_DWORD_256K lpServicesReturned) 3834 { 3835 DWORD dwError = ERROR_SUCCESS; 3836 DWORD dwServicesReturned = 0; 3837 DWORD dwServiceCount; 3838 HKEY hServicesKey = NULL; 3839 PSERVICE_HANDLE hSvc; 3840 PSERVICE lpService = NULL; 3841 PSERVICE *lpServicesArray = NULL; 3842 LPENUM_SERVICE_STATUSA lpServicesPtr = NULL; 3843 LPSTR lpStr; 3844 3845 *pcbBytesNeeded = 0; 3846 *lpServicesReturned = 0; 3847 3848 DPRINT("REnumDependentServicesA() called\n"); 3849 3850 hSvc = ScmGetServiceFromHandle(hService); 3851 if (hSvc == NULL) 3852 { 3853 DPRINT1("Invalid service handle!\n"); 3854 return ERROR_INVALID_HANDLE; 3855 } 3856 3857 lpService = hSvc->ServiceEntry; 3858 3859 /* Check access rights */ 3860 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 3861 SC_MANAGER_ENUMERATE_SERVICE)) 3862 { 3863 DPRINT("Insufficient access rights! 0x%lx\n", 3864 hSvc->Handle.DesiredAccess); 3865 return ERROR_ACCESS_DENIED; 3866 } 3867 3868 /* Open the Services Reg key */ 3869 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 3870 L"System\\CurrentControlSet\\Services", 3871 0, 3872 KEY_READ, 3873 &hServicesKey); 3874 3875 if (dwError != ERROR_SUCCESS) 3876 return dwError; 3877 3878 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for 3879 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded 3880 are the same for both. Verified in WINXP. */ 3881 3882 /* First determine the bytes needed and get the number of dependent services*/ 3883 dwError = Int_EnumDependentServicesW(hServicesKey, 3884 lpService, 3885 dwServiceState, 3886 NULL, 3887 pcbBytesNeeded, 3888 &dwServicesReturned); 3889 if (dwError != ERROR_SUCCESS) 3890 goto Done; 3891 3892 /* If buffer size is less than the bytes needed or pointer is null*/ 3893 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 3894 { 3895 dwError = ERROR_MORE_DATA; 3896 goto Done; 3897 } 3898 3899 /* Allocate memory for array of service pointers */ 3900 lpServicesArray = HeapAlloc(GetProcessHeap(), 3901 HEAP_ZERO_MEMORY, 3902 (dwServicesReturned + 1) * sizeof(PSERVICE)); 3903 if (!lpServicesArray) 3904 { 3905 DPRINT("Could not allocate a buffer!!\n"); 3906 dwError = ERROR_NOT_ENOUGH_MEMORY; 3907 goto Done; 3908 } 3909 3910 dwServicesReturned = 0; 3911 *pcbBytesNeeded = 0; 3912 3913 dwError = Int_EnumDependentServicesW(hServicesKey, 3914 lpService, 3915 dwServiceState, 3916 lpServicesArray, 3917 pcbBytesNeeded, 3918 &dwServicesReturned); 3919 if (dwError != ERROR_SUCCESS) 3920 { 3921 goto Done; 3922 } 3923 3924 lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices; 3925 lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA))); 3926 3927 /* Copy EnumDepenedentService to Buffer */ 3928 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 3929 { 3930 lpService = lpServicesArray[dwServiceCount]; 3931 3932 /* Copy the status info */ 3933 memcpy(&lpServicesPtr->ServiceStatus, 3934 &lpService->Status, 3935 sizeof(SERVICE_STATUS)); 3936 3937 /* Copy display name */ 3938 WideCharToMultiByte(CP_ACP, 3939 0, 3940 lpService->lpDisplayName, 3941 -1, 3942 lpStr, 3943 (int)wcslen(lpService->lpDisplayName), 3944 0, 3945 0); 3946 lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 3947 lpStr += strlen(lpStr) + 1; 3948 3949 /* Copy service name */ 3950 WideCharToMultiByte(CP_ACP, 3951 0, 3952 lpService->lpServiceName, 3953 -1, 3954 lpStr, 3955 (int)wcslen(lpService->lpServiceName), 3956 0, 3957 0); 3958 lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 3959 lpStr += strlen(lpStr) + 1; 3960 3961 lpServicesPtr++; 3962 } 3963 3964 *lpServicesReturned = dwServicesReturned; 3965 3966 Done: 3967 if (lpServicesArray) 3968 HeapFree(GetProcessHeap(), 0, lpServicesArray); 3969 3970 RegCloseKey(hServicesKey); 3971 3972 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError); 3973 3974 return dwError; 3975 } 3976 3977 3978 /* Function 26 */ 3979 DWORD 3980 WINAPI 3981 REnumServicesStatusA( 3982 SC_RPC_HANDLE hSCManager, 3983 DWORD dwServiceType, 3984 DWORD dwServiceState, 3985 LPBYTE lpBuffer, 3986 DWORD dwBufSize, 3987 LPBOUNDED_DWORD_256K pcbBytesNeeded, 3988 LPBOUNDED_DWORD_256K lpServicesReturned, 3989 LPBOUNDED_DWORD_256K lpResumeHandle) 3990 { 3991 LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL; 3992 LPENUM_SERVICE_STATUSW lpStatusPtrIncrW; 3993 LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL; 3994 LPWSTR lpStringPtrW; 3995 LPSTR lpStringPtrA; 3996 DWORD dwError; 3997 DWORD dwServiceCount; 3998 3999 DPRINT("REnumServicesStatusA() called\n"); 4000 4001 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 4002 { 4003 return ERROR_INVALID_ADDRESS; 4004 } 4005 4006 if ((dwBufSize > 0) && (lpBuffer)) 4007 { 4008 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize); 4009 if (!lpStatusPtrW) 4010 { 4011 DPRINT("Failed to allocate buffer!\n"); 4012 return ERROR_NOT_ENOUGH_MEMORY; 4013 } 4014 } 4015 4016 dwError = REnumServicesStatusW(hSCManager, 4017 dwServiceType, 4018 dwServiceState, 4019 (LPBYTE)lpStatusPtrW, 4020 dwBufSize, 4021 pcbBytesNeeded, 4022 lpServicesReturned, 4023 lpResumeHandle); 4024 4025 /* if no services were returned then we are Done */ 4026 if (*lpServicesReturned == 0) 4027 goto Done; 4028 4029 lpStatusPtrIncrW = lpStatusPtrW; 4030 lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer; 4031 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 4032 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA)); 4033 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 4034 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW)); 4035 4036 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 4037 { 4038 /* Copy the service name */ 4039 WideCharToMultiByte(CP_ACP, 4040 0, 4041 lpStringPtrW, 4042 -1, 4043 lpStringPtrA, 4044 (int)wcslen(lpStringPtrW), 4045 0, 4046 0); 4047 4048 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 4049 lpStringPtrA += wcslen(lpStringPtrW) + 1; 4050 lpStringPtrW += wcslen(lpStringPtrW) + 1; 4051 4052 /* Copy the display name */ 4053 WideCharToMultiByte(CP_ACP, 4054 0, 4055 lpStringPtrW, 4056 -1, 4057 lpStringPtrA, 4058 (int)wcslen(lpStringPtrW), 4059 0, 4060 0); 4061 4062 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 4063 lpStringPtrA += wcslen(lpStringPtrW) + 1; 4064 lpStringPtrW += wcslen(lpStringPtrW) + 1; 4065 4066 /* Copy the status information */ 4067 memcpy(&lpStatusPtrA->ServiceStatus, 4068 &lpStatusPtrIncrW->ServiceStatus, 4069 sizeof(SERVICE_STATUS)); 4070 4071 lpStatusPtrIncrW++; 4072 lpStatusPtrA++; 4073 } 4074 4075 Done: 4076 if (lpStatusPtrW) 4077 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 4078 4079 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError); 4080 4081 return dwError; 4082 } 4083 4084 4085 /* Function 27 */ 4086 DWORD 4087 WINAPI 4088 ROpenSCManagerA( 4089 LPSTR lpMachineName, 4090 LPSTR lpDatabaseName, 4091 DWORD dwDesiredAccess, 4092 LPSC_RPC_HANDLE lpScHandle) 4093 { 4094 UNICODE_STRING MachineName; 4095 UNICODE_STRING DatabaseName; 4096 DWORD dwError; 4097 4098 DPRINT("ROpenSCManagerA() called\n"); 4099 4100 if (lpMachineName) 4101 RtlCreateUnicodeStringFromAsciiz(&MachineName, 4102 lpMachineName); 4103 4104 if (lpDatabaseName) 4105 RtlCreateUnicodeStringFromAsciiz(&DatabaseName, 4106 lpDatabaseName); 4107 4108 dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL, 4109 lpDatabaseName ? DatabaseName.Buffer : NULL, 4110 dwDesiredAccess, 4111 lpScHandle); 4112 4113 if (lpMachineName) 4114 RtlFreeUnicodeString(&MachineName); 4115 4116 if (lpDatabaseName) 4117 RtlFreeUnicodeString(&DatabaseName); 4118 4119 return dwError; 4120 } 4121 4122 4123 /* Function 28 */ 4124 DWORD 4125 WINAPI 4126 ROpenServiceA( 4127 SC_RPC_HANDLE hSCManager, 4128 LPSTR lpServiceName, 4129 DWORD dwDesiredAccess, 4130 LPSC_RPC_HANDLE lpServiceHandle) 4131 { 4132 UNICODE_STRING ServiceName; 4133 DWORD dwError; 4134 4135 DPRINT("ROpenServiceA() called\n"); 4136 4137 if (lpServiceName) 4138 RtlCreateUnicodeStringFromAsciiz(&ServiceName, 4139 lpServiceName); 4140 4141 dwError = ROpenServiceW(hSCManager, 4142 lpServiceName ? ServiceName.Buffer : NULL, 4143 dwDesiredAccess, 4144 lpServiceHandle); 4145 4146 if (lpServiceName) 4147 RtlFreeUnicodeString(&ServiceName); 4148 4149 return dwError; 4150 } 4151 4152 4153 /* Function 29 */ 4154 DWORD 4155 WINAPI 4156 RQueryServiceConfigA( 4157 SC_RPC_HANDLE hService, 4158 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig, 4159 DWORD cbBufSize, 4160 LPBOUNDED_DWORD_8K pcbBytesNeeded) 4161 { 4162 LPQUERY_SERVICE_CONFIGA lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)lpBuf; 4163 DWORD dwError = ERROR_SUCCESS; 4164 PSERVICE_HANDLE hSvc; 4165 PSERVICE lpService = NULL; 4166 HKEY hServiceKey = NULL; 4167 LPWSTR lpImagePath = NULL; 4168 LPWSTR lpServiceStartName = NULL; 4169 LPWSTR lpDependencies = NULL; 4170 DWORD dwDependenciesLength = 0; 4171 DWORD dwRequiredSize; 4172 CHAR lpEmptyString[]={0,0}; 4173 LPSTR lpStr; 4174 4175 DPRINT("RQueryServiceConfigA() called\n"); 4176 4177 if (ScmShutdown) 4178 return ERROR_SHUTDOWN_IN_PROGRESS; 4179 4180 hSvc = ScmGetServiceFromHandle(hService); 4181 if (hSvc == NULL) 4182 { 4183 DPRINT1("Invalid service handle!\n"); 4184 return ERROR_INVALID_HANDLE; 4185 } 4186 4187 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 4188 SERVICE_QUERY_CONFIG)) 4189 { 4190 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 4191 return ERROR_ACCESS_DENIED; 4192 } 4193 4194 lpService = hSvc->ServiceEntry; 4195 if (lpService == NULL) 4196 { 4197 DPRINT("lpService == NULL!\n"); 4198 return ERROR_INVALID_HANDLE; 4199 } 4200 4201 /* Lock the service database shared */ 4202 ScmLockDatabaseShared(); 4203 4204 dwError = ScmOpenServiceKey(lpService->lpServiceName, 4205 KEY_READ, 4206 &hServiceKey); 4207 if (dwError != ERROR_SUCCESS) 4208 goto Done; 4209 4210 /* Read the image path */ 4211 dwError = ScmReadString(hServiceKey, 4212 L"ImagePath", 4213 &lpImagePath); 4214 if (dwError != ERROR_SUCCESS) 4215 goto Done; 4216 4217 /* Read the service start name */ 4218 ScmReadString(hServiceKey, 4219 L"ObjectName", 4220 &lpServiceStartName); 4221 4222 /* Read the dependencies */ 4223 ScmReadDependencies(hServiceKey, 4224 &lpDependencies, 4225 &dwDependenciesLength); 4226 4227 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGA); 4228 4229 if (lpImagePath != NULL) 4230 dwRequiredSize += (DWORD)(wcslen(lpImagePath) + 1); 4231 else 4232 dwRequiredSize += 2; 4233 4234 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 4235 dwRequiredSize += (DWORD)(wcslen(lpService->lpGroup->lpGroupName) + 1); 4236 else 4237 dwRequiredSize += 2; 4238 4239 /* Add Dependencies length */ 4240 if (lpDependencies != NULL) 4241 dwRequiredSize += dwDependenciesLength; 4242 else 4243 dwRequiredSize += 2; 4244 4245 if (lpServiceStartName != NULL) 4246 dwRequiredSize += (DWORD)(wcslen(lpServiceStartName) + 1); 4247 else 4248 dwRequiredSize += 2; 4249 4250 if (lpService->lpDisplayName != NULL) 4251 dwRequiredSize += (DWORD)(wcslen(lpService->lpDisplayName) + 1); 4252 else 4253 dwRequiredSize += 2; 4254 4255 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 4256 { 4257 dwError = ERROR_INSUFFICIENT_BUFFER; 4258 } 4259 else 4260 { 4261 lpServiceConfig->dwServiceType = lpService->Status.dwServiceType; 4262 lpServiceConfig->dwStartType = lpService->dwStartType; 4263 lpServiceConfig->dwErrorControl = lpService->dwErrorControl; 4264 lpServiceConfig->dwTagId = lpService->dwTag; 4265 4266 lpStr = (LPSTR)(lpServiceConfig + 1); 4267 4268 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings. 4269 Verified in WINXP */ 4270 4271 if (lpImagePath) 4272 { 4273 WideCharToMultiByte(CP_ACP, 4274 0, 4275 lpImagePath, 4276 -1, 4277 lpStr, 4278 (int)(wcslen(lpImagePath) + 1), 4279 0, 4280 0); 4281 } 4282 else 4283 { 4284 strcpy(lpStr, lpEmptyString); 4285 } 4286 4287 lpServiceConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4288 lpStr += (strlen((LPSTR)lpStr) + 1); 4289 4290 if (lpService->lpGroup && lpService->lpGroup->lpGroupName) 4291 { 4292 WideCharToMultiByte(CP_ACP, 4293 0, 4294 lpService->lpGroup->lpGroupName, 4295 -1, 4296 lpStr, 4297 (int)(wcslen(lpService->lpGroup->lpGroupName) + 1), 4298 0, 4299 0); 4300 } 4301 else 4302 { 4303 strcpy(lpStr, lpEmptyString); 4304 } 4305 4306 lpServiceConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4307 lpStr += (strlen(lpStr) + 1); 4308 4309 /* Append Dependencies */ 4310 if (lpDependencies) 4311 { 4312 WideCharToMultiByte(CP_ACP, 4313 0, 4314 lpDependencies, 4315 dwDependenciesLength, 4316 lpStr, 4317 dwDependenciesLength, 4318 0, 4319 0); 4320 } 4321 else 4322 { 4323 strcpy(lpStr, lpEmptyString); 4324 } 4325 4326 lpServiceConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4327 if (lpDependencies) 4328 lpStr += dwDependenciesLength; 4329 else 4330 lpStr += (strlen(lpStr) + 1); 4331 4332 if (lpServiceStartName) 4333 { 4334 WideCharToMultiByte(CP_ACP, 4335 0, 4336 lpServiceStartName, 4337 -1, 4338 lpStr, 4339 (int)(wcslen(lpServiceStartName) + 1), 4340 0, 4341 0); 4342 } 4343 else 4344 { 4345 strcpy(lpStr, lpEmptyString); 4346 } 4347 4348 lpServiceConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4349 lpStr += (strlen(lpStr) + 1); 4350 4351 if (lpService->lpDisplayName) 4352 { 4353 WideCharToMultiByte(CP_ACP, 4354 0, 4355 lpService->lpDisplayName, 4356 -1, 4357 lpStr, 4358 (int)(wcslen(lpService->lpDisplayName) + 1), 4359 0, 4360 0); 4361 } 4362 else 4363 { 4364 strcpy(lpStr, lpEmptyString); 4365 } 4366 4367 lpServiceConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceConfig); 4368 } 4369 4370 if (pcbBytesNeeded != NULL) 4371 *pcbBytesNeeded = dwRequiredSize; 4372 4373 Done: 4374 /* Unlock the service database */ 4375 ScmUnlockDatabase(); 4376 4377 if (lpImagePath != NULL) 4378 HeapFree(GetProcessHeap(), 0, lpImagePath); 4379 4380 if (lpServiceStartName != NULL) 4381 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 4382 4383 if (lpDependencies != NULL) 4384 HeapFree(GetProcessHeap(), 0, lpDependencies); 4385 4386 if (hServiceKey != NULL) 4387 RegCloseKey(hServiceKey); 4388 4389 DPRINT("RQueryServiceConfigA() done\n"); 4390 4391 return dwError; 4392 } 4393 4394 4395 /* Function 30 */ 4396 DWORD 4397 WINAPI 4398 RQueryServiceLockStatusA( 4399 SC_RPC_HANDLE hSCManager, 4400 LPBYTE lpBuf, // LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, 4401 DWORD cbBufSize, 4402 LPBOUNDED_DWORD_4K pcbBytesNeeded) 4403 { 4404 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus = (LPQUERY_SERVICE_LOCK_STATUSA)lpBuf; 4405 PMANAGER_HANDLE hMgr; 4406 DWORD dwRequiredSize; 4407 4408 if (!lpLockStatus || !pcbBytesNeeded) 4409 return ERROR_INVALID_PARAMETER; 4410 4411 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 4412 if (hMgr == NULL) 4413 { 4414 DPRINT1("Invalid service manager handle!\n"); 4415 return ERROR_INVALID_HANDLE; 4416 } 4417 4418 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 4419 SC_MANAGER_QUERY_LOCK_STATUS)) 4420 { 4421 DPRINT("Insufficient access rights! 0x%lx\n", hMgr->Handle.DesiredAccess); 4422 return ERROR_ACCESS_DENIED; 4423 } 4424 4425 /* FIXME: we need to compute instead the real length of the owner name */ 4426 dwRequiredSize = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(CHAR); 4427 *pcbBytesNeeded = dwRequiredSize; 4428 4429 if (cbBufSize < dwRequiredSize) 4430 return ERROR_INSUFFICIENT_BUFFER; 4431 4432 ScmQueryServiceLockStatusA(lpLockStatus); 4433 4434 return ERROR_SUCCESS; 4435 } 4436 4437 4438 /* Function 31 */ 4439 DWORD 4440 WINAPI 4441 RStartServiceA( 4442 SC_RPC_HANDLE hService, 4443 DWORD argc, 4444 LPSTRING_PTRSA argv) 4445 { 4446 DWORD dwError = ERROR_SUCCESS; 4447 PSERVICE_HANDLE hSvc; 4448 PSERVICE lpService = NULL; 4449 LPWSTR *lpVector = NULL; 4450 DWORD i; 4451 DWORD dwLength; 4452 4453 DPRINT("RStartServiceA() called\n"); 4454 4455 if (ScmShutdown) 4456 return ERROR_SHUTDOWN_IN_PROGRESS; 4457 4458 hSvc = ScmGetServiceFromHandle(hService); 4459 if (hSvc == NULL) 4460 { 4461 DPRINT1("Invalid service handle!\n"); 4462 return ERROR_INVALID_HANDLE; 4463 } 4464 4465 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 4466 SERVICE_START)) 4467 { 4468 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 4469 return ERROR_ACCESS_DENIED; 4470 } 4471 4472 lpService = hSvc->ServiceEntry; 4473 if (lpService == NULL) 4474 { 4475 DPRINT("lpService == NULL!\n"); 4476 return ERROR_INVALID_HANDLE; 4477 } 4478 4479 if (lpService->dwStartType == SERVICE_DISABLED) 4480 return ERROR_SERVICE_DISABLED; 4481 4482 if (lpService->bDeleted) 4483 return ERROR_SERVICE_MARKED_FOR_DELETE; 4484 4485 /* Build a Unicode argument vector */ 4486 if (argc > 0) 4487 { 4488 lpVector = HeapAlloc(GetProcessHeap(), 4489 HEAP_ZERO_MEMORY, 4490 argc * sizeof(LPWSTR)); 4491 if (lpVector == NULL) 4492 return ERROR_NOT_ENOUGH_MEMORY; 4493 4494 for (i = 0; i < argc; i++) 4495 { 4496 dwLength = MultiByteToWideChar(CP_ACP, 4497 0, 4498 ((LPSTR*)argv)[i], 4499 -1, 4500 NULL, 4501 0); 4502 4503 lpVector[i] = HeapAlloc(GetProcessHeap(), 4504 HEAP_ZERO_MEMORY, 4505 dwLength * sizeof(WCHAR)); 4506 if (lpVector[i] == NULL) 4507 { 4508 dwError = ERROR_NOT_ENOUGH_MEMORY; 4509 goto done; 4510 } 4511 4512 MultiByteToWideChar(CP_ACP, 4513 0, 4514 ((LPSTR*)argv)[i], 4515 -1, 4516 lpVector[i], 4517 dwLength); 4518 } 4519 } 4520 4521 /* Start the service */ 4522 dwError = ScmStartService(lpService, argc, lpVector); 4523 4524 done: 4525 /* Free the Unicode argument vector */ 4526 if (lpVector != NULL) 4527 { 4528 for (i = 0; i < argc; i++) 4529 { 4530 if (lpVector[i] != NULL) 4531 HeapFree(GetProcessHeap(), 0, lpVector[i]); 4532 } 4533 HeapFree(GetProcessHeap(), 0, lpVector); 4534 } 4535 4536 return dwError; 4537 } 4538 4539 4540 /* Function 32 */ 4541 DWORD 4542 WINAPI 4543 RGetServiceDisplayNameA( 4544 SC_RPC_HANDLE hSCManager, 4545 LPCSTR lpServiceName, 4546 LPSTR lpDisplayName, 4547 LPBOUNDED_DWORD_4K lpcchBuffer) 4548 { 4549 // PMANAGER_HANDLE hManager; 4550 PSERVICE lpService = NULL; 4551 DWORD dwLength; 4552 DWORD dwError; 4553 LPWSTR lpServiceNameW; 4554 4555 DPRINT("RGetServiceDisplayNameA() called\n"); 4556 DPRINT("hSCManager = %p\n", hSCManager); 4557 DPRINT("lpServiceName: %s\n", lpServiceName); 4558 DPRINT("lpDisplayName: %p\n", lpDisplayName); 4559 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 4560 4561 // hManager = (PMANAGER_HANDLE)hSCManager; 4562 // if (hManager->Handle.Tag != MANAGER_TAG) 4563 // { 4564 // DPRINT("Invalid manager handle!\n"); 4565 // return ERROR_INVALID_HANDLE; 4566 // } 4567 4568 if (lpServiceName != NULL) 4569 { 4570 dwLength = (DWORD)(strlen(lpServiceName) + 1); 4571 lpServiceNameW = HeapAlloc(GetProcessHeap(), 4572 HEAP_ZERO_MEMORY, 4573 dwLength * sizeof(WCHAR)); 4574 if (!lpServiceNameW) 4575 return ERROR_NOT_ENOUGH_MEMORY; 4576 4577 MultiByteToWideChar(CP_ACP, 4578 0, 4579 lpServiceName, 4580 -1, 4581 lpServiceNameW, 4582 dwLength); 4583 4584 lpService = ScmGetServiceEntryByName(lpServiceNameW); 4585 4586 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 4587 } 4588 4589 if (lpService == NULL) 4590 { 4591 DPRINT("Could not find a service!\n"); 4592 4593 /* If the service could not be found and lpcchBuffer is 0, windows 4594 puts null in lpDisplayName and puts 1 in lpcchBuffer */ 4595 if (*lpcchBuffer == 0) 4596 { 4597 *lpcchBuffer = 1; 4598 if (lpDisplayName != NULL) 4599 { 4600 *lpDisplayName = 0; 4601 } 4602 } 4603 return ERROR_SERVICE_DOES_NOT_EXIST; 4604 } 4605 4606 if (!lpService->lpDisplayName) 4607 { 4608 dwLength = (DWORD)wcslen(lpService->lpServiceName); 4609 if (lpDisplayName != NULL && 4610 *lpcchBuffer > dwLength) 4611 { 4612 WideCharToMultiByte(CP_ACP, 4613 0, 4614 lpService->lpServiceName, 4615 (int)wcslen(lpService->lpServiceName), 4616 lpDisplayName, 4617 dwLength + 1, 4618 NULL, 4619 NULL); 4620 return ERROR_SUCCESS; 4621 } 4622 } 4623 else 4624 { 4625 dwLength = (DWORD)wcslen(lpService->lpDisplayName); 4626 if (lpDisplayName != NULL && 4627 *lpcchBuffer > dwLength) 4628 { 4629 WideCharToMultiByte(CP_ACP, 4630 0, 4631 lpService->lpDisplayName, 4632 (int)wcslen(lpService->lpDisplayName), 4633 lpDisplayName, 4634 dwLength + 1, 4635 NULL, 4636 NULL); 4637 return ERROR_SUCCESS; 4638 } 4639 } 4640 4641 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 4642 4643 *lpcchBuffer = dwLength * 2; 4644 4645 return dwError; 4646 } 4647 4648 4649 /* Function 33 */ 4650 DWORD 4651 WINAPI 4652 RGetServiceKeyNameA( 4653 SC_RPC_HANDLE hSCManager, 4654 LPCSTR lpDisplayName, 4655 LPSTR lpServiceName, 4656 LPBOUNDED_DWORD_4K lpcchBuffer) 4657 { 4658 PSERVICE lpService; 4659 DWORD dwLength; 4660 DWORD dwError; 4661 LPWSTR lpDisplayNameW; 4662 4663 DPRINT("RGetServiceKeyNameA() called\n"); 4664 DPRINT("hSCManager = %p\n", hSCManager); 4665 DPRINT("lpDisplayName: %s\n", lpDisplayName); 4666 DPRINT("lpServiceName: %p\n", lpServiceName); 4667 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 4668 4669 dwLength = (DWORD)(strlen(lpDisplayName) + 1); 4670 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 4671 HEAP_ZERO_MEMORY, 4672 dwLength * sizeof(WCHAR)); 4673 if (!lpDisplayNameW) 4674 return ERROR_NOT_ENOUGH_MEMORY; 4675 4676 MultiByteToWideChar(CP_ACP, 4677 0, 4678 lpDisplayName, 4679 -1, 4680 lpDisplayNameW, 4681 dwLength); 4682 4683 lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW); 4684 4685 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 4686 4687 if (lpService == NULL) 4688 { 4689 DPRINT("Could not find the service!\n"); 4690 4691 /* If the service could not be found and lpcchBuffer is 0, 4692 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */ 4693 if (*lpcchBuffer == 0) 4694 { 4695 *lpcchBuffer = 1; 4696 if (lpServiceName != NULL) 4697 { 4698 *lpServiceName = 0; 4699 } 4700 } 4701 4702 return ERROR_SERVICE_DOES_NOT_EXIST; 4703 } 4704 4705 dwLength = (DWORD)wcslen(lpService->lpServiceName); 4706 if (lpServiceName != NULL && 4707 *lpcchBuffer > dwLength) 4708 { 4709 WideCharToMultiByte(CP_ACP, 4710 0, 4711 lpService->lpServiceName, 4712 (int)wcslen(lpService->lpServiceName), 4713 lpServiceName, 4714 dwLength + 1, 4715 NULL, 4716 NULL); 4717 return ERROR_SUCCESS; 4718 } 4719 4720 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 4721 4722 *lpcchBuffer = dwLength * 2; 4723 4724 return dwError; 4725 } 4726 4727 4728 /* Function 34 */ 4729 DWORD 4730 WINAPI 4731 RI_ScGetCurrentGroupStateW( 4732 SC_RPC_HANDLE hSCManager, 4733 LPWSTR lpLoadOrderGroup, 4734 LPDWORD lpState) 4735 { 4736 PMANAGER_HANDLE hManager; 4737 PSERVICE_GROUP pServiceGroup; 4738 DWORD dwError = ERROR_SUCCESS; 4739 4740 DPRINT("RI_ScGetCurrentGroupStateW() called\n"); 4741 4742 if (ScmShutdown) 4743 return ERROR_SHUTDOWN_IN_PROGRESS; 4744 4745 hManager = ScmGetServiceManagerFromHandle(hSCManager); 4746 if (hManager == NULL) 4747 { 4748 DPRINT1("Invalid service manager handle!\n"); 4749 return ERROR_INVALID_HANDLE; 4750 } 4751 4752 /* Check for SC_MANAGER_ENUMERATE_SERVICE access right */ 4753 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 4754 SC_MANAGER_ENUMERATE_SERVICE)) 4755 { 4756 DPRINT("Insufficient access rights! 0x%lx\n", 4757 hManager->Handle.DesiredAccess); 4758 return ERROR_ACCESS_DENIED; 4759 } 4760 4761 /* Lock the service database shared */ 4762 ScmLockDatabaseShared(); 4763 4764 /* Get the group list entry */ 4765 pServiceGroup = ScmGetServiceGroupByName(lpLoadOrderGroup); 4766 if (pServiceGroup == NULL) 4767 { 4768 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 4769 goto done; 4770 } 4771 4772 /* FIXME: Return the group state */ 4773 *lpState = 0; 4774 4775 done: 4776 /* Unlock the service database */ 4777 ScmUnlockDatabase(); 4778 4779 DPRINT("RI_ScGetCurrentGroupStateW() done (Error %lu)\n", dwError); 4780 4781 return dwError; 4782 } 4783 4784 4785 /* Function 35 */ 4786 DWORD 4787 WINAPI 4788 REnumServiceGroupW( 4789 SC_RPC_HANDLE hSCManager, 4790 DWORD dwServiceType, 4791 DWORD dwServiceState, 4792 LPBYTE lpBuffer, 4793 DWORD cbBufSize, 4794 LPBOUNDED_DWORD_256K pcbBytesNeeded, 4795 LPBOUNDED_DWORD_256K lpServicesReturned, 4796 LPBOUNDED_DWORD_256K lpResumeIndex, 4797 LPCWSTR pszGroupName) 4798 { 4799 PMANAGER_HANDLE hManager; 4800 PSERVICE lpService; 4801 DWORD dwError = ERROR_SUCCESS; 4802 PLIST_ENTRY ServiceEntry; 4803 PSERVICE CurrentService; 4804 DWORD dwState; 4805 DWORD dwRequiredSize; 4806 DWORD dwServiceCount; 4807 DWORD dwSize; 4808 DWORD dwLastResumeCount = 0; 4809 LPENUM_SERVICE_STATUSW lpStatusPtr; 4810 LPWSTR lpStringPtr; 4811 4812 DPRINT("REnumServiceGroupW() called\n"); 4813 4814 if (ScmShutdown) 4815 return ERROR_SHUTDOWN_IN_PROGRESS; 4816 4817 hManager = ScmGetServiceManagerFromHandle(hSCManager); 4818 if (hManager == NULL) 4819 { 4820 DPRINT1("Invalid service manager handle!\n"); 4821 return ERROR_INVALID_HANDLE; 4822 } 4823 4824 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 4825 { 4826 return ERROR_INVALID_ADDRESS; 4827 } 4828 4829 *pcbBytesNeeded = 0; 4830 *lpServicesReturned = 0; 4831 4832 if ((dwServiceType == 0) || 4833 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0)) 4834 { 4835 DPRINT("Not a valid Service Type!\n"); 4836 return ERROR_INVALID_PARAMETER; 4837 } 4838 4839 if ((dwServiceState == 0) || 4840 ((dwServiceState & ~SERVICE_STATE_ALL) != 0)) 4841 { 4842 DPRINT("Not a valid Service State!\n"); 4843 return ERROR_INVALID_PARAMETER; 4844 } 4845 4846 /* Check access rights */ 4847 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 4848 SC_MANAGER_ENUMERATE_SERVICE)) 4849 { 4850 DPRINT("Insufficient access rights! 0x%lx\n", 4851 hManager->Handle.DesiredAccess); 4852 return ERROR_ACCESS_DENIED; 4853 } 4854 4855 if (lpResumeIndex) 4856 dwLastResumeCount = *lpResumeIndex; 4857 4858 /* Lock the service database shared */ 4859 ScmLockDatabaseShared(); 4860 4861 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 4862 if (lpService == NULL) 4863 { 4864 dwError = ERROR_SUCCESS; 4865 goto Done; 4866 } 4867 4868 dwRequiredSize = 0; 4869 dwServiceCount = 0; 4870 4871 for (ServiceEntry = &lpService->ServiceListEntry; 4872 ServiceEntry != &ServiceListHead; 4873 ServiceEntry = ServiceEntry->Flink) 4874 { 4875 CurrentService = CONTAINING_RECORD(ServiceEntry, 4876 SERVICE, 4877 ServiceListEntry); 4878 4879 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 4880 continue; 4881 4882 dwState = SERVICE_ACTIVE; 4883 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 4884 dwState = SERVICE_INACTIVE; 4885 4886 if ((dwState & dwServiceState) == 0) 4887 continue; 4888 4889 if (pszGroupName) 4890 { 4891 if (*pszGroupName == 0) 4892 { 4893 if (CurrentService->lpGroup != NULL) 4894 continue; 4895 } 4896 else 4897 { 4898 if ((CurrentService->lpGroup == NULL) || 4899 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 4900 continue; 4901 } 4902 } 4903 4904 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 4905 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 4906 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 4907 4908 if (dwRequiredSize + dwSize > cbBufSize) 4909 { 4910 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 4911 break; 4912 } 4913 4914 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 4915 dwRequiredSize += dwSize; 4916 dwServiceCount++; 4917 dwLastResumeCount = CurrentService->dwResumeCount; 4918 } 4919 4920 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 4921 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 4922 4923 for (; 4924 ServiceEntry != &ServiceListHead; 4925 ServiceEntry = ServiceEntry->Flink) 4926 { 4927 CurrentService = CONTAINING_RECORD(ServiceEntry, 4928 SERVICE, 4929 ServiceListEntry); 4930 4931 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 4932 continue; 4933 4934 dwState = SERVICE_ACTIVE; 4935 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 4936 dwState = SERVICE_INACTIVE; 4937 4938 if ((dwState & dwServiceState) == 0) 4939 continue; 4940 4941 if (pszGroupName) 4942 { 4943 if (*pszGroupName == 0) 4944 { 4945 if (CurrentService->lpGroup != NULL) 4946 continue; 4947 } 4948 else 4949 { 4950 if ((CurrentService->lpGroup == NULL) || 4951 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 4952 continue; 4953 } 4954 } 4955 4956 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) + 4957 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 4958 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 4959 4960 dwError = ERROR_MORE_DATA; 4961 } 4962 4963 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 4964 4965 if (lpResumeIndex) 4966 *lpResumeIndex = dwLastResumeCount; 4967 4968 *lpServicesReturned = dwServiceCount; 4969 *pcbBytesNeeded = dwRequiredSize; 4970 4971 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer; 4972 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 4973 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW)); 4974 4975 dwRequiredSize = 0; 4976 for (ServiceEntry = &lpService->ServiceListEntry; 4977 ServiceEntry != &ServiceListHead; 4978 ServiceEntry = ServiceEntry->Flink) 4979 { 4980 CurrentService = CONTAINING_RECORD(ServiceEntry, 4981 SERVICE, 4982 ServiceListEntry); 4983 4984 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 4985 continue; 4986 4987 dwState = SERVICE_ACTIVE; 4988 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 4989 dwState = SERVICE_INACTIVE; 4990 4991 if ((dwState & dwServiceState) == 0) 4992 continue; 4993 4994 if (pszGroupName) 4995 { 4996 if (*pszGroupName == 0) 4997 { 4998 if (CurrentService->lpGroup != NULL) 4999 continue; 5000 } 5001 else 5002 { 5003 if ((CurrentService->lpGroup == NULL) || 5004 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 5005 continue; 5006 } 5007 } 5008 5009 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 5010 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 5011 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 5012 5013 if (dwRequiredSize + dwSize > cbBufSize) 5014 break; 5015 5016 /* Copy the service name */ 5017 wcscpy(lpStringPtr, CurrentService->lpServiceName); 5018 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 5019 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 5020 5021 /* Copy the display name */ 5022 wcscpy(lpStringPtr, CurrentService->lpDisplayName); 5023 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 5024 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 5025 5026 /* Copy the status information */ 5027 memcpy(&lpStatusPtr->ServiceStatus, 5028 &CurrentService->Status, 5029 sizeof(SERVICE_STATUS)); 5030 5031 lpStatusPtr++; 5032 dwRequiredSize += dwSize; 5033 } 5034 5035 if (dwError == ERROR_SUCCESS) 5036 { 5037 *pcbBytesNeeded = 0; 5038 if (lpResumeIndex) *lpResumeIndex = 0; 5039 } 5040 5041 Done: 5042 /* Unlock the service database */ 5043 ScmUnlockDatabase(); 5044 5045 DPRINT("REnumServiceGroupW() done (Error %lu)\n", dwError); 5046 5047 return dwError; 5048 } 5049 5050 5051 /* Function 36 */ 5052 DWORD 5053 WINAPI 5054 RChangeServiceConfig2A( 5055 SC_RPC_HANDLE hService, 5056 SC_RPC_CONFIG_INFOA Info) 5057 { 5058 SC_RPC_CONFIG_INFOW InfoW; 5059 DWORD dwRet, dwLength; 5060 PVOID ptr = NULL; 5061 5062 DPRINT("RChangeServiceConfig2A() called\n"); 5063 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 5064 5065 InfoW.dwInfoLevel = Info.dwInfoLevel; 5066 5067 if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5068 { 5069 LPSERVICE_DESCRIPTIONW lpServiceDescriptionW; 5070 LPSERVICE_DESCRIPTIONA lpServiceDescriptionA; 5071 5072 lpServiceDescriptionA = Info.psd; 5073 5074 if (lpServiceDescriptionA && 5075 lpServiceDescriptionA->lpDescription) 5076 { 5077 dwLength = (DWORD)((strlen(lpServiceDescriptionA->lpDescription) + 1) * sizeof(WCHAR)); 5078 5079 lpServiceDescriptionW = HeapAlloc(GetProcessHeap(), 5080 HEAP_ZERO_MEMORY, 5081 dwLength + sizeof(SERVICE_DESCRIPTIONW)); 5082 if (!lpServiceDescriptionW) 5083 { 5084 return ERROR_NOT_ENOUGH_MEMORY; 5085 } 5086 5087 lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1); 5088 5089 MultiByteToWideChar(CP_ACP, 5090 0, 5091 lpServiceDescriptionA->lpDescription, 5092 -1, 5093 lpServiceDescriptionW->lpDescription, 5094 dwLength); 5095 5096 ptr = lpServiceDescriptionW; 5097 InfoW.psd = lpServiceDescriptionW; 5098 } 5099 } 5100 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5101 { 5102 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; 5103 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; 5104 DWORD dwRebootLen = 0; 5105 DWORD dwCommandLen = 0; 5106 DWORD dwActionArrayLen = 0; 5107 LPWSTR lpStr = NULL; 5108 5109 lpServiceFailureActionsA = Info.psfa; 5110 5111 if (lpServiceFailureActionsA) 5112 { 5113 /* 5114 * The following code is inspired by the 5115 * SERVICE_CONFIG_FAILURE_ACTIONS case of 5116 * the RQueryServiceConfig2W function. 5117 */ 5118 5119 /* Retrieve the needed length for the two data strings */ 5120 if (lpServiceFailureActionsA->lpRebootMsg) 5121 { 5122 dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR)); 5123 } 5124 if (lpServiceFailureActionsA->lpCommand) 5125 { 5126 dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR)); 5127 } 5128 5129 /* 5130 * Retrieve the size of the lpsaActions array if needed. 5131 * We will copy the lpsaActions array only if there is at 5132 * least one action AND that the original array is valid. 5133 */ 5134 if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions) 5135 { 5136 dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION); 5137 } 5138 5139 /* Compute the total length for the UNICODE structure, including data */ 5140 dwLength = sizeof(SERVICE_FAILURE_ACTIONSW) + 5141 dwActionArrayLen + dwRebootLen + dwCommandLen; 5142 5143 /* Allocate the structure */ 5144 lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(), 5145 HEAP_ZERO_MEMORY, 5146 dwLength); 5147 if (!lpServiceFailureActionsW) 5148 { 5149 return ERROR_NOT_ENOUGH_MEMORY; 5150 } 5151 5152 /* Copy the members */ 5153 lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; 5154 lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; 5155 5156 /* Copy the lpsaActions array if needed */ 5157 if (dwActionArrayLen > 0) 5158 { 5159 /* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */ 5160 lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1)); 5161 5162 /* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */ 5163 RtlCopyMemory(lpServiceFailureActionsW->lpsaActions, 5164 lpServiceFailureActionsA->lpsaActions, 5165 dwActionArrayLen); 5166 } 5167 else 5168 { 5169 /* No lpsaActions array */ 5170 lpServiceFailureActionsW->lpsaActions = NULL; 5171 } 5172 /* The data strings are stored just after the lpsaActions array */ 5173 lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen); 5174 5175 /* 5176 * Convert the data strings to UNICODE 5177 */ 5178 5179 lpServiceFailureActionsW->lpRebootMsg = NULL; 5180 lpServiceFailureActionsW->lpCommand = NULL; 5181 5182 if (dwRebootLen) 5183 { 5184 /* lpRebootMsg points just after the lpsaActions array */ 5185 lpServiceFailureActionsW->lpRebootMsg = lpStr; 5186 5187 MultiByteToWideChar(CP_ACP, 5188 0, 5189 lpServiceFailureActionsA->lpRebootMsg, 5190 -1, 5191 lpServiceFailureActionsW->lpRebootMsg, 5192 dwRebootLen); 5193 5194 lpStr += dwRebootLen / sizeof(WCHAR); 5195 } 5196 5197 if (dwCommandLen) 5198 { 5199 /* lpRebootMsg points just after the lpRebootMsg data string */ 5200 lpServiceFailureActionsW->lpCommand = lpStr; 5201 5202 MultiByteToWideChar(CP_ACP, 5203 0, 5204 lpServiceFailureActionsA->lpCommand, 5205 -1, 5206 lpServiceFailureActionsW->lpCommand, 5207 dwCommandLen); 5208 } 5209 5210 /* Set the pointers */ 5211 ptr = lpServiceFailureActionsW; 5212 InfoW.psfa = lpServiceFailureActionsW; 5213 } 5214 } 5215 5216 dwRet = RChangeServiceConfig2W(hService, InfoW); 5217 5218 HeapFree(GetProcessHeap(), 0, ptr); 5219 5220 return dwRet; 5221 } 5222 5223 5224 static DWORD 5225 ScmSetFailureActions(HKEY hServiceKey, 5226 LPSERVICE_FAILURE_ACTIONSW lpFailureActions) 5227 { 5228 LPSERVICE_FAILURE_ACTIONSW lpReadBuffer = NULL; 5229 LPSERVICE_FAILURE_ACTIONSW lpWriteBuffer = NULL; 5230 DWORD dwRequiredSize = 0; 5231 DWORD dwType = 0; 5232 DWORD dwError; 5233 5234 /* There is nothing to be done if we have no failure actions */ 5235 if (lpFailureActions == NULL) 5236 return ERROR_SUCCESS; 5237 5238 /* 5239 * 1- Retrieve the original value of FailureActions. 5240 */ 5241 5242 /* Query value length */ 5243 dwError = RegQueryValueExW(hServiceKey, 5244 L"FailureActions", 5245 NULL, 5246 &dwType, 5247 NULL, 5248 &dwRequiredSize); 5249 if (dwError != ERROR_SUCCESS && 5250 dwError != ERROR_MORE_DATA && 5251 dwError != ERROR_FILE_NOT_FOUND) 5252 return dwError; 5253 5254 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize) 5255 : sizeof(SERVICE_FAILURE_ACTIONSW); 5256 5257 /* Initialize the read buffer */ 5258 lpReadBuffer = HeapAlloc(GetProcessHeap(), 5259 HEAP_ZERO_MEMORY, 5260 dwRequiredSize); 5261 if (lpReadBuffer == NULL) 5262 return ERROR_NOT_ENOUGH_MEMORY; 5263 5264 /* Now we can fill the read buffer */ 5265 if (dwError != ERROR_FILE_NOT_FOUND && 5266 dwType == REG_BINARY) 5267 { 5268 dwError = RegQueryValueExW(hServiceKey, 5269 L"FailureActions", 5270 NULL, 5271 NULL, 5272 (LPBYTE)lpReadBuffer, 5273 &dwRequiredSize); 5274 if (dwError != ERROR_SUCCESS && 5275 dwError != ERROR_FILE_NOT_FOUND) 5276 goto done; 5277 5278 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) 5279 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5280 } 5281 else 5282 { 5283 /* 5284 * The value of the error doesn't really matter, the only 5285 * important thing is that it must be != ERROR_SUCCESS. 5286 */ 5287 dwError = ERROR_INVALID_DATA; 5288 } 5289 5290 if (dwError == ERROR_SUCCESS) 5291 { 5292 lpReadBuffer->cActions = min(lpReadBuffer->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION)); 5293 lpReadBuffer->lpsaActions = (lpReadBuffer->cActions > 0 ? (LPSC_ACTION)(lpReadBuffer + 1) : NULL); 5294 } 5295 else 5296 { 5297 lpReadBuffer->dwResetPeriod = 0; 5298 lpReadBuffer->cActions = 0; 5299 lpReadBuffer->lpsaActions = NULL; 5300 } 5301 5302 lpReadBuffer->lpRebootMsg = NULL; 5303 lpReadBuffer->lpCommand = NULL; 5304 5305 /* 5306 * 2- Initialize the new value to set. 5307 */ 5308 5309 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5310 5311 if (lpFailureActions->lpsaActions == NULL) 5312 { 5313 /* 5314 * lpFailureActions->cActions is ignored. 5315 * Therefore we use the original values 5316 * of cActions and lpsaActions. 5317 */ 5318 dwRequiredSize += lpReadBuffer->cActions * sizeof(SC_ACTION); 5319 } 5320 else 5321 { 5322 /* 5323 * The reset period and array of failure actions 5324 * are deleted if lpFailureActions->cActions == 0 . 5325 */ 5326 dwRequiredSize += lpFailureActions->cActions * sizeof(SC_ACTION); 5327 } 5328 5329 lpWriteBuffer = HeapAlloc(GetProcessHeap(), 5330 HEAP_ZERO_MEMORY, 5331 dwRequiredSize); 5332 if (lpWriteBuffer == NULL) 5333 { 5334 dwError = ERROR_NOT_ENOUGH_MEMORY; 5335 goto done; 5336 } 5337 5338 /* Clean the pointers as they have no meaning when the structure is stored in the registry */ 5339 lpWriteBuffer->lpRebootMsg = NULL; 5340 lpWriteBuffer->lpCommand = NULL; 5341 lpWriteBuffer->lpsaActions = NULL; 5342 5343 /* Set the members */ 5344 if (lpFailureActions->lpsaActions == NULL) 5345 { 5346 /* 5347 * lpFailureActions->dwResetPeriod and lpFailureActions->cActions are ignored. 5348 * Therefore we use the original values of dwResetPeriod, cActions and lpsaActions. 5349 */ 5350 lpWriteBuffer->dwResetPeriod = lpReadBuffer->dwResetPeriod; 5351 lpWriteBuffer->cActions = lpReadBuffer->cActions; 5352 5353 if (lpReadBuffer->lpsaActions != NULL) 5354 { 5355 memmove(lpWriteBuffer + 1, 5356 lpReadBuffer->lpsaActions, 5357 lpReadBuffer->cActions * sizeof(SC_ACTION)); 5358 } 5359 } 5360 else 5361 { 5362 if (lpFailureActions->cActions > 0) 5363 { 5364 lpWriteBuffer->dwResetPeriod = lpFailureActions->dwResetPeriod; 5365 lpWriteBuffer->cActions = lpFailureActions->cActions; 5366 5367 memmove(lpWriteBuffer + 1, 5368 lpFailureActions->lpsaActions, 5369 lpFailureActions->cActions * sizeof(SC_ACTION)); 5370 } 5371 else 5372 { 5373 /* The reset period and array of failure actions are deleted */ 5374 lpWriteBuffer->dwResetPeriod = 0; 5375 lpWriteBuffer->cActions = 0; 5376 } 5377 } 5378 5379 /* Save the new failure actions into the registry */ 5380 dwError = RegSetValueExW(hServiceKey, 5381 L"FailureActions", 5382 0, 5383 REG_BINARY, 5384 (LPBYTE)lpWriteBuffer, 5385 dwRequiredSize); 5386 5387 /* We modify the strings only in case of success.*/ 5388 if (dwError == ERROR_SUCCESS) 5389 { 5390 /* Modify the Reboot Message value, if specified */ 5391 if (lpFailureActions->lpRebootMsg != NULL) 5392 { 5393 /* If the Reboot Message is "" then we delete it */ 5394 if (*lpFailureActions->lpRebootMsg == 0) 5395 { 5396 DPRINT("Delete Reboot Message value\n"); 5397 RegDeleteValueW(hServiceKey, L"RebootMessage"); 5398 } 5399 else 5400 { 5401 DPRINT("Setting Reboot Message value %S\n", lpFailureActions->lpRebootMsg); 5402 RegSetValueExW(hServiceKey, 5403 L"RebootMessage", 5404 0, 5405 REG_SZ, 5406 (LPBYTE)lpFailureActions->lpRebootMsg, 5407 (DWORD)((wcslen(lpFailureActions->lpRebootMsg) + 1) * sizeof(WCHAR))); 5408 } 5409 } 5410 5411 /* Modify the Failure Command value, if specified */ 5412 if (lpFailureActions->lpCommand != NULL) 5413 { 5414 /* If the FailureCommand string is an empty string, delete the value */ 5415 if (*lpFailureActions->lpCommand == 0) 5416 { 5417 DPRINT("Delete Failure Command value\n"); 5418 RegDeleteValueW(hServiceKey, L"FailureCommand"); 5419 } 5420 else 5421 { 5422 DPRINT("Setting Failure Command value %S\n", lpFailureActions->lpCommand); 5423 RegSetValueExW(hServiceKey, 5424 L"FailureCommand", 5425 0, 5426 REG_SZ, 5427 (LPBYTE)lpFailureActions->lpCommand, 5428 (DWORD)((wcslen(lpFailureActions->lpCommand) + 1) * sizeof(WCHAR))); 5429 } 5430 } 5431 } 5432 5433 done: 5434 if (lpWriteBuffer != NULL) 5435 HeapFree(GetProcessHeap(), 0, lpWriteBuffer); 5436 5437 if (lpReadBuffer != NULL) 5438 HeapFree(GetProcessHeap(), 0, lpReadBuffer); 5439 5440 return dwError; 5441 } 5442 5443 5444 /* Function 37 */ 5445 DWORD 5446 WINAPI 5447 RChangeServiceConfig2W( 5448 SC_RPC_HANDLE hService, 5449 SC_RPC_CONFIG_INFOW Info) 5450 { 5451 DWORD dwError = ERROR_SUCCESS; 5452 PSERVICE_HANDLE hSvc; 5453 PSERVICE lpService = NULL; 5454 HKEY hServiceKey = NULL; 5455 ACCESS_MASK RequiredAccess = SERVICE_CHANGE_CONFIG; 5456 5457 DPRINT("RChangeServiceConfig2W() called\n"); 5458 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 5459 5460 if (ScmShutdown) 5461 return ERROR_SHUTDOWN_IN_PROGRESS; 5462 5463 hSvc = ScmGetServiceFromHandle(hService); 5464 if (hSvc == NULL) 5465 { 5466 DPRINT("Invalid service handle!\n"); 5467 return ERROR_INVALID_HANDLE; 5468 } 5469 5470 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5471 RequiredAccess |= SERVICE_START; 5472 5473 /* Check the access rights */ 5474 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5475 RequiredAccess)) 5476 { 5477 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5478 return ERROR_ACCESS_DENIED; 5479 } 5480 5481 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5482 { 5483 /* FIXME: Check if the caller has the SE_SHUTDOWN_NAME privilege */ 5484 5485 } 5486 5487 lpService = hSvc->ServiceEntry; 5488 if (lpService == NULL) 5489 { 5490 DPRINT("lpService == NULL!\n"); 5491 return ERROR_INVALID_HANDLE; 5492 } 5493 5494 /* Failure actions can only be set for Win32 services, not for drivers */ 5495 if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5496 { 5497 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 5498 return ERROR_CANNOT_DETECT_DRIVER_FAILURE; 5499 } 5500 5501 /* Lock the service database exclusively */ 5502 ScmLockDatabaseExclusive(); 5503 5504 if (lpService->bDeleted) 5505 { 5506 DPRINT("The service has already been marked for delete!\n"); 5507 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 5508 goto done; 5509 } 5510 5511 /* Open the service key */ 5512 dwError = ScmOpenServiceKey(lpService->szServiceName, 5513 KEY_READ | KEY_SET_VALUE, 5514 &hServiceKey); 5515 if (dwError != ERROR_SUCCESS) 5516 goto done; 5517 5518 if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5519 { 5520 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd; 5521 5522 /* Modify the service description, if specified */ 5523 if (lpServiceDescription != NULL && 5524 lpServiceDescription->lpDescription != NULL) 5525 { 5526 /* If the description is "" then we delete it */ 5527 if (*lpServiceDescription->lpDescription == 0) 5528 { 5529 DPRINT("Delete service description\n"); 5530 dwError = RegDeleteValueW(hServiceKey, L"Description"); 5531 5532 if (dwError == ERROR_FILE_NOT_FOUND) 5533 dwError = ERROR_SUCCESS; 5534 } 5535 else 5536 { 5537 DPRINT("Setting service description value %S\n", lpServiceDescription->lpDescription); 5538 dwError = RegSetValueExW(hServiceKey, 5539 L"Description", 5540 0, 5541 REG_SZ, 5542 (LPBYTE)lpServiceDescription->lpDescription, 5543 (DWORD)((wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR))); 5544 } 5545 } 5546 else 5547 { 5548 dwError = ERROR_SUCCESS; 5549 } 5550 } 5551 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5552 { 5553 dwError = ScmSetFailureActions(hServiceKey, 5554 (LPSERVICE_FAILURE_ACTIONSW)Info.psfa); 5555 } 5556 5557 done: 5558 if (hServiceKey != NULL) 5559 RegCloseKey(hServiceKey); 5560 5561 /* Unlock the service database */ 5562 ScmUnlockDatabase(); 5563 5564 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError); 5565 5566 return dwError; 5567 } 5568 5569 5570 /* Function 38 */ 5571 DWORD 5572 WINAPI 5573 RQueryServiceConfig2A( 5574 SC_RPC_HANDLE hService, 5575 DWORD dwInfoLevel, 5576 LPBYTE lpBuffer, 5577 DWORD cbBufSize, 5578 LPBOUNDED_DWORD_8K pcbBytesNeeded) 5579 { 5580 DWORD dwError = ERROR_SUCCESS; 5581 PSERVICE_HANDLE hSvc; 5582 PSERVICE lpService = NULL; 5583 HKEY hServiceKey = NULL; 5584 DWORD dwRequiredSize = 0; 5585 DWORD dwType = 0; 5586 LPWSTR lpDescriptionW = NULL; 5587 LPWSTR lpRebootMessageW = NULL; 5588 LPWSTR lpFailureCommandW = NULL; 5589 5590 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n", 5591 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); 5592 5593 if (!lpBuffer) 5594 return ERROR_INVALID_ADDRESS; 5595 5596 if (ScmShutdown) 5597 return ERROR_SHUTDOWN_IN_PROGRESS; 5598 5599 hSvc = ScmGetServiceFromHandle(hService); 5600 if (hSvc == NULL) 5601 { 5602 DPRINT1("Invalid service handle!\n"); 5603 return ERROR_INVALID_HANDLE; 5604 } 5605 5606 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5607 SERVICE_QUERY_CONFIG)) 5608 { 5609 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5610 return ERROR_ACCESS_DENIED; 5611 } 5612 5613 lpService = hSvc->ServiceEntry; 5614 if (lpService == NULL) 5615 { 5616 DPRINT("lpService == NULL!\n"); 5617 return ERROR_INVALID_HANDLE; 5618 } 5619 5620 /* Lock the service database shared */ 5621 ScmLockDatabaseShared(); 5622 5623 dwError = ScmOpenServiceKey(lpService->lpServiceName, 5624 KEY_READ, 5625 &hServiceKey); 5626 if (dwError != ERROR_SUCCESS) 5627 goto done; 5628 5629 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5630 { 5631 LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer; 5632 LPSTR lpStr; 5633 5634 dwError = ScmReadString(hServiceKey, 5635 L"Description", 5636 &lpDescriptionW); 5637 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5638 goto done; 5639 5640 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA); 5641 if (dwError == ERROR_SUCCESS) 5642 *pcbBytesNeeded += (DWORD)((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR)); 5643 5644 if (cbBufSize < *pcbBytesNeeded) 5645 { 5646 dwError = ERROR_INSUFFICIENT_BUFFER; 5647 goto done; 5648 } 5649 5650 if (dwError == ERROR_SUCCESS) 5651 { 5652 lpStr = (LPSTR)(lpServiceDescription + 1); 5653 5654 WideCharToMultiByte(CP_ACP, 5655 0, 5656 lpDescriptionW, 5657 -1, 5658 lpStr, 5659 (int)wcslen(lpDescriptionW), 5660 NULL, 5661 NULL); 5662 lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 5663 } 5664 else 5665 { 5666 lpServiceDescription->lpDescription = NULL; 5667 dwError = ERROR_SUCCESS; 5668 } 5669 } 5670 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5671 { 5672 LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer; 5673 LPSTR lpStr = NULL; 5674 5675 /* Query value length */ 5676 dwError = RegQueryValueExW(hServiceKey, 5677 L"FailureActions", 5678 NULL, 5679 &dwType, 5680 NULL, 5681 &dwRequiredSize); 5682 if (dwError != ERROR_SUCCESS && 5683 dwError != ERROR_MORE_DATA && 5684 dwError != ERROR_FILE_NOT_FOUND) 5685 goto done; 5686 5687 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize) 5688 : sizeof(SERVICE_FAILURE_ACTIONSA); 5689 5690 /* Get the strings */ 5691 ScmReadString(hServiceKey, 5692 L"FailureCommand", 5693 &lpFailureCommandW); 5694 5695 ScmReadString(hServiceKey, 5696 L"RebootMessage", 5697 &lpRebootMessageW); 5698 5699 if (lpRebootMessageW) 5700 dwRequiredSize += (DWORD)((wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR)); 5701 5702 if (lpFailureCommandW) 5703 dwRequiredSize += (DWORD)((wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR)); 5704 5705 if (cbBufSize < dwRequiredSize) 5706 { 5707 *pcbBytesNeeded = dwRequiredSize; 5708 dwError = ERROR_INSUFFICIENT_BUFFER; 5709 goto done; 5710 } 5711 5712 /* Now we can fill the buffer */ 5713 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY) 5714 { 5715 dwError = RegQueryValueExW(hServiceKey, 5716 L"FailureActions", 5717 NULL, 5718 NULL, 5719 (LPBYTE)lpFailureActions, 5720 &dwRequiredSize); 5721 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5722 goto done; 5723 5724 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA)) 5725 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSA); 5726 } 5727 else 5728 { 5729 /* 5730 * The value of the error doesn't really matter, the only 5731 * important thing is that it must be != ERROR_SUCCESS . 5732 */ 5733 dwError = ERROR_INVALID_DATA; 5734 } 5735 5736 if (dwError == ERROR_SUCCESS) 5737 { 5738 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSA)) / sizeof(SC_ACTION)); 5739 5740 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */ 5741 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSA) : NULL); 5742 5743 lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); 5744 } 5745 else 5746 { 5747 lpFailureActions->dwResetPeriod = 0; 5748 lpFailureActions->cActions = 0; 5749 lpFailureActions->lpsaActions = NULL; 5750 lpStr = (LPSTR)(lpFailureActions + 1); 5751 } 5752 5753 lpFailureActions->lpRebootMsg = NULL; 5754 lpFailureActions->lpCommand = NULL; 5755 5756 if (lpRebootMessageW) 5757 { 5758 WideCharToMultiByte(CP_ACP, 5759 0, 5760 lpRebootMessageW, 5761 -1, 5762 lpStr, 5763 (int)wcslen(lpRebootMessageW), 5764 NULL, 5765 NULL); 5766 lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5767 lpStr += strlen(lpStr) + 1; 5768 } 5769 5770 if (lpFailureCommandW) 5771 { 5772 WideCharToMultiByte(CP_ACP, 5773 0, 5774 lpFailureCommandW, 5775 -1, 5776 lpStr, 5777 (int)wcslen(lpFailureCommandW), 5778 NULL, 5779 NULL); 5780 lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5781 /* lpStr += strlen(lpStr) + 1; */ 5782 } 5783 5784 dwError = ERROR_SUCCESS; 5785 } 5786 5787 done: 5788 /* Unlock the service database */ 5789 ScmUnlockDatabase(); 5790 5791 if (lpDescriptionW != NULL) 5792 HeapFree(GetProcessHeap(), 0, lpDescriptionW); 5793 5794 if (lpRebootMessageW != NULL) 5795 HeapFree(GetProcessHeap(), 0, lpRebootMessageW); 5796 5797 if (lpFailureCommandW != NULL) 5798 HeapFree(GetProcessHeap(), 0, lpFailureCommandW); 5799 5800 if (hServiceKey != NULL) 5801 RegCloseKey(hServiceKey); 5802 5803 DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError); 5804 5805 return dwError; 5806 } 5807 5808 5809 /* Function 39 */ 5810 DWORD 5811 WINAPI 5812 RQueryServiceConfig2W( 5813 SC_RPC_HANDLE hService, 5814 DWORD dwInfoLevel, 5815 LPBYTE lpBuffer, 5816 DWORD cbBufSize, 5817 LPBOUNDED_DWORD_8K pcbBytesNeeded) 5818 { 5819 DWORD dwError = ERROR_SUCCESS; 5820 PSERVICE_HANDLE hSvc; 5821 PSERVICE lpService = NULL; 5822 HKEY hServiceKey = NULL; 5823 DWORD dwRequiredSize = 0; 5824 DWORD dwType = 0; 5825 LPWSTR lpDescription = NULL; 5826 LPWSTR lpRebootMessage = NULL; 5827 LPWSTR lpFailureCommand = NULL; 5828 5829 DPRINT("RQueryServiceConfig2W() called\n"); 5830 5831 if (!lpBuffer) 5832 return ERROR_INVALID_ADDRESS; 5833 5834 if (ScmShutdown) 5835 return ERROR_SHUTDOWN_IN_PROGRESS; 5836 5837 hSvc = ScmGetServiceFromHandle(hService); 5838 if (hSvc == NULL) 5839 { 5840 DPRINT1("Invalid service handle!\n"); 5841 return ERROR_INVALID_HANDLE; 5842 } 5843 5844 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 5845 SERVICE_QUERY_CONFIG)) 5846 { 5847 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 5848 return ERROR_ACCESS_DENIED; 5849 } 5850 5851 lpService = hSvc->ServiceEntry; 5852 if (lpService == NULL) 5853 { 5854 DPRINT("lpService == NULL!\n"); 5855 return ERROR_INVALID_HANDLE; 5856 } 5857 5858 /* Lock the service database shared */ 5859 ScmLockDatabaseShared(); 5860 5861 dwError = ScmOpenServiceKey(lpService->lpServiceName, 5862 KEY_READ, 5863 &hServiceKey); 5864 if (dwError != ERROR_SUCCESS) 5865 goto done; 5866 5867 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 5868 { 5869 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer; 5870 LPWSTR lpStr; 5871 5872 dwError = ScmReadString(hServiceKey, 5873 L"Description", 5874 &lpDescription); 5875 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5876 goto done; 5877 5878 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONW); 5879 if (dwError == ERROR_SUCCESS) 5880 *pcbBytesNeeded += (DWORD)((wcslen(lpDescription) + 1) * sizeof(WCHAR)); 5881 5882 if (cbBufSize < *pcbBytesNeeded) 5883 { 5884 dwError = ERROR_INSUFFICIENT_BUFFER; 5885 goto done; 5886 } 5887 5888 if (dwError == ERROR_SUCCESS) 5889 { 5890 lpStr = (LPWSTR)(lpServiceDescription + 1); 5891 wcscpy(lpStr, lpDescription); 5892 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 5893 } 5894 else 5895 { 5896 lpServiceDescription->lpDescription = NULL; 5897 dwError = ERROR_SUCCESS; 5898 } 5899 } 5900 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 5901 { 5902 LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer; 5903 LPWSTR lpStr = NULL; 5904 5905 /* Query value length */ 5906 dwError = RegQueryValueExW(hServiceKey, 5907 L"FailureActions", 5908 NULL, 5909 &dwType, 5910 NULL, 5911 &dwRequiredSize); 5912 if (dwError != ERROR_SUCCESS && 5913 dwError != ERROR_MORE_DATA && 5914 dwError != ERROR_FILE_NOT_FOUND) 5915 goto done; 5916 5917 dwRequiredSize = (dwType == REG_BINARY) ? max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize) 5918 : sizeof(SERVICE_FAILURE_ACTIONSW); 5919 5920 /* Get the strings */ 5921 ScmReadString(hServiceKey, 5922 L"FailureCommand", 5923 &lpFailureCommand); 5924 5925 ScmReadString(hServiceKey, 5926 L"RebootMessage", 5927 &lpRebootMessage); 5928 5929 if (lpRebootMessage) 5930 dwRequiredSize += (DWORD)((wcslen(lpRebootMessage) + 1) * sizeof(WCHAR)); 5931 5932 if (lpFailureCommand) 5933 dwRequiredSize += (DWORD)((wcslen(lpFailureCommand) + 1) * sizeof(WCHAR)); 5934 5935 if (cbBufSize < dwRequiredSize) 5936 { 5937 *pcbBytesNeeded = dwRequiredSize; 5938 dwError = ERROR_INSUFFICIENT_BUFFER; 5939 goto done; 5940 } 5941 5942 /* Now we can fill the buffer */ 5943 if (dwError != ERROR_FILE_NOT_FOUND && dwType == REG_BINARY) 5944 { 5945 dwError = RegQueryValueExW(hServiceKey, 5946 L"FailureActions", 5947 NULL, 5948 NULL, 5949 (LPBYTE)lpFailureActions, 5950 &dwRequiredSize); 5951 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 5952 goto done; 5953 5954 if (dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) 5955 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 5956 } 5957 else 5958 { 5959 /* 5960 * The value of the error doesn't really matter, the only 5961 * important thing is that it must be != ERROR_SUCCESS . 5962 */ 5963 dwError = ERROR_INVALID_DATA; 5964 } 5965 5966 if (dwError == ERROR_SUCCESS) 5967 { 5968 lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - sizeof(SERVICE_FAILURE_ACTIONSW)) / sizeof(SC_ACTION)); 5969 5970 /* Here lpFailureActions->lpsaActions contains an offset. The conversion is done by the caller. */ 5971 lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(ULONG_PTR)sizeof(SERVICE_FAILURE_ACTIONSW) : NULL); 5972 5973 lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION)); 5974 } 5975 else 5976 { 5977 lpFailureActions->dwResetPeriod = 0; 5978 lpFailureActions->cActions = 0; 5979 lpFailureActions->lpsaActions = NULL; 5980 lpStr = (LPWSTR)(lpFailureActions + 1); 5981 } 5982 5983 lpFailureActions->lpRebootMsg = NULL; 5984 lpFailureActions->lpCommand = NULL; 5985 5986 if (lpRebootMessage) 5987 { 5988 wcscpy(lpStr, lpRebootMessage); 5989 lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5990 lpStr += wcslen(lpStr) + 1; 5991 } 5992 5993 if (lpFailureCommand) 5994 { 5995 wcscpy(lpStr, lpFailureCommand); 5996 lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions); 5997 /* lpStr += wcslen(lpStr) + 1; */ 5998 } 5999 6000 dwError = ERROR_SUCCESS; 6001 } 6002 6003 done: 6004 /* Unlock the service database */ 6005 ScmUnlockDatabase(); 6006 6007 if (lpDescription != NULL) 6008 HeapFree(GetProcessHeap(), 0, lpDescription); 6009 6010 if (lpRebootMessage != NULL) 6011 HeapFree(GetProcessHeap(), 0, lpRebootMessage); 6012 6013 if (lpFailureCommand != NULL) 6014 HeapFree(GetProcessHeap(), 0, lpFailureCommand); 6015 6016 if (hServiceKey != NULL) 6017 RegCloseKey(hServiceKey); 6018 6019 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError); 6020 6021 return dwError; 6022 } 6023 6024 6025 /* Function 40 */ 6026 DWORD 6027 WINAPI 6028 RQueryServiceStatusEx( 6029 SC_RPC_HANDLE hService, 6030 SC_STATUS_TYPE InfoLevel, 6031 LPBYTE lpBuffer, 6032 DWORD cbBufSize, 6033 LPBOUNDED_DWORD_8K pcbBytesNeeded) 6034 { 6035 LPSERVICE_STATUS_PROCESS lpStatus; 6036 PSERVICE_HANDLE hSvc; 6037 PSERVICE lpService; 6038 6039 DPRINT("RQueryServiceStatusEx() called\n"); 6040 6041 if (ScmShutdown) 6042 return ERROR_SHUTDOWN_IN_PROGRESS; 6043 6044 if (InfoLevel != SC_STATUS_PROCESS_INFO) 6045 return ERROR_INVALID_LEVEL; 6046 6047 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS); 6048 6049 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) 6050 return ERROR_INSUFFICIENT_BUFFER; 6051 6052 hSvc = ScmGetServiceFromHandle(hService); 6053 if (hSvc == NULL) 6054 { 6055 DPRINT1("Invalid service handle!\n"); 6056 return ERROR_INVALID_HANDLE; 6057 } 6058 6059 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 6060 SERVICE_QUERY_STATUS)) 6061 { 6062 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 6063 return ERROR_ACCESS_DENIED; 6064 } 6065 6066 lpService = hSvc->ServiceEntry; 6067 if (lpService == NULL) 6068 { 6069 DPRINT("lpService == NULL!\n"); 6070 return ERROR_INVALID_HANDLE; 6071 } 6072 6073 /* Lock the service database shared */ 6074 ScmLockDatabaseShared(); 6075 6076 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer; 6077 6078 /* Return service status information */ 6079 RtlCopyMemory(lpStatus, 6080 &lpService->Status, 6081 sizeof(SERVICE_STATUS)); 6082 6083 /* Copy the service process ID */ 6084 if ((lpService->Status.dwCurrentState == SERVICE_STOPPED) || (lpService->lpImage == NULL)) 6085 lpStatus->dwProcessId = 0; 6086 else 6087 lpStatus->dwProcessId = lpService->lpImage->dwProcessId; 6088 6089 lpStatus->dwServiceFlags = 0; /* FIXME */ 6090 6091 /* Unlock the service database */ 6092 ScmUnlockDatabase(); 6093 6094 return ERROR_SUCCESS; 6095 } 6096 6097 6098 /* Function 41 */ 6099 DWORD 6100 WINAPI 6101 REnumServicesStatusExA( 6102 SC_RPC_HANDLE hSCManager, 6103 SC_ENUM_TYPE InfoLevel, 6104 DWORD dwServiceType, 6105 DWORD dwServiceState, 6106 LPBYTE lpBuffer, 6107 DWORD cbBufSize, 6108 LPBOUNDED_DWORD_256K pcbBytesNeeded, 6109 LPBOUNDED_DWORD_256K lpServicesReturned, 6110 LPBOUNDED_DWORD_256K lpResumeIndex, 6111 LPCSTR pszGroupName) 6112 { 6113 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL; 6114 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrIncrW; 6115 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL; 6116 LPWSTR lpStringPtrW; 6117 LPSTR lpStringPtrA; 6118 LPWSTR pszGroupNameW = NULL; 6119 DWORD dwError; 6120 DWORD dwServiceCount; 6121 6122 DPRINT("REnumServicesStatusExA() called\n"); 6123 6124 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 6125 { 6126 return ERROR_INVALID_ADDRESS; 6127 } 6128 6129 if (pszGroupName) 6130 { 6131 pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR)); 6132 if (!pszGroupNameW) 6133 { 6134 DPRINT("Failed to allocate buffer!\n"); 6135 dwError = ERROR_NOT_ENOUGH_MEMORY; 6136 goto Done; 6137 } 6138 6139 MultiByteToWideChar(CP_ACP, 6140 0, 6141 pszGroupName, 6142 -1, 6143 pszGroupNameW, 6144 (int)(strlen(pszGroupName) + 1)); 6145 } 6146 6147 if ((cbBufSize > 0) && (lpBuffer)) 6148 { 6149 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize); 6150 if (!lpStatusPtrW) 6151 { 6152 DPRINT("Failed to allocate buffer!\n"); 6153 dwError = ERROR_NOT_ENOUGH_MEMORY; 6154 goto Done; 6155 } 6156 } 6157 6158 dwError = REnumServicesStatusExW(hSCManager, 6159 InfoLevel, 6160 dwServiceType, 6161 dwServiceState, 6162 (LPBYTE)lpStatusPtrW, 6163 cbBufSize, 6164 pcbBytesNeeded, 6165 lpServicesReturned, 6166 lpResumeIndex, 6167 pszGroupNameW); 6168 6169 /* if no services were returned then we are Done */ 6170 if (*lpServicesReturned == 0) 6171 goto Done; 6172 6173 lpStatusPtrIncrW = lpStatusPtrW; 6174 lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer; 6175 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 6176 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA)); 6177 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 6178 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 6179 6180 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 6181 { 6182 /* Copy the service name */ 6183 WideCharToMultiByte(CP_ACP, 6184 0, 6185 lpStringPtrW, 6186 -1, 6187 lpStringPtrA, 6188 (int)wcslen(lpStringPtrW), 6189 0, 6190 0); 6191 6192 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 6193 lpStringPtrA += wcslen(lpStringPtrW) + 1; 6194 lpStringPtrW += wcslen(lpStringPtrW) + 1; 6195 6196 /* Copy the display name */ 6197 WideCharToMultiByte(CP_ACP, 6198 0, 6199 lpStringPtrW, 6200 -1, 6201 lpStringPtrA, 6202 (int)wcslen(lpStringPtrW), 6203 0, 6204 0); 6205 6206 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 6207 lpStringPtrA += wcslen(lpStringPtrW) + 1; 6208 lpStringPtrW += wcslen(lpStringPtrW) + 1; 6209 6210 /* Copy the status information */ 6211 memcpy(&lpStatusPtrA->ServiceStatusProcess, 6212 &lpStatusPtrIncrW->ServiceStatusProcess, 6213 sizeof(SERVICE_STATUS)); 6214 6215 /* Copy the service process ID */ 6216 lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrIncrW->ServiceStatusProcess.dwProcessId; 6217 6218 lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 6219 6220 lpStatusPtrIncrW++; 6221 lpStatusPtrA++; 6222 } 6223 6224 Done: 6225 if (pszGroupNameW) 6226 HeapFree(GetProcessHeap(), 0, pszGroupNameW); 6227 6228 if (lpStatusPtrW) 6229 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 6230 6231 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError); 6232 6233 return dwError; 6234 } 6235 6236 6237 /* Function 42 */ 6238 DWORD 6239 WINAPI 6240 REnumServicesStatusExW( 6241 SC_RPC_HANDLE hSCManager, 6242 SC_ENUM_TYPE InfoLevel, 6243 DWORD dwServiceType, 6244 DWORD dwServiceState, 6245 LPBYTE lpBuffer, 6246 DWORD cbBufSize, 6247 LPBOUNDED_DWORD_256K pcbBytesNeeded, 6248 LPBOUNDED_DWORD_256K lpServicesReturned, 6249 LPBOUNDED_DWORD_256K lpResumeIndex, 6250 LPCWSTR pszGroupName) 6251 { 6252 PMANAGER_HANDLE hManager; 6253 PSERVICE lpService; 6254 DWORD dwError = ERROR_SUCCESS; 6255 PLIST_ENTRY ServiceEntry; 6256 PSERVICE CurrentService; 6257 DWORD dwState; 6258 DWORD dwRequiredSize; 6259 DWORD dwServiceCount; 6260 DWORD dwSize; 6261 DWORD dwLastResumeCount = 0; 6262 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; 6263 LPWSTR lpStringPtr; 6264 6265 DPRINT("REnumServicesStatusExW() called\n"); 6266 6267 if (ScmShutdown) 6268 return ERROR_SHUTDOWN_IN_PROGRESS; 6269 6270 if (InfoLevel != SC_ENUM_PROCESS_INFO) 6271 return ERROR_INVALID_LEVEL; 6272 6273 hManager = ScmGetServiceManagerFromHandle(hSCManager); 6274 if (hManager == NULL) 6275 { 6276 DPRINT1("Invalid service manager handle!\n"); 6277 return ERROR_INVALID_HANDLE; 6278 } 6279 6280 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 6281 { 6282 return ERROR_INVALID_ADDRESS; 6283 } 6284 6285 *pcbBytesNeeded = 0; 6286 *lpServicesReturned = 0; 6287 6288 if ((dwServiceType == 0) || 6289 ((dwServiceType & ~SERVICE_TYPE_ALL) != 0)) 6290 { 6291 DPRINT("Not a valid Service Type!\n"); 6292 return ERROR_INVALID_PARAMETER; 6293 } 6294 6295 if ((dwServiceState == 0) || 6296 ((dwServiceState & ~SERVICE_STATE_ALL) != 0)) 6297 { 6298 DPRINT("Not a valid Service State!\n"); 6299 return ERROR_INVALID_PARAMETER; 6300 } 6301 6302 /* Check access rights */ 6303 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 6304 SC_MANAGER_ENUMERATE_SERVICE)) 6305 { 6306 DPRINT("Insufficient access rights! 0x%lx\n", 6307 hManager->Handle.DesiredAccess); 6308 return ERROR_ACCESS_DENIED; 6309 } 6310 6311 if (lpResumeIndex) 6312 dwLastResumeCount = *lpResumeIndex; 6313 6314 /* Lock the service database shared */ 6315 ScmLockDatabaseShared(); 6316 6317 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 6318 if (lpService == NULL) 6319 { 6320 dwError = ERROR_SUCCESS; 6321 goto Done; 6322 } 6323 6324 dwRequiredSize = 0; 6325 dwServiceCount = 0; 6326 6327 for (ServiceEntry = &lpService->ServiceListEntry; 6328 ServiceEntry != &ServiceListHead; 6329 ServiceEntry = ServiceEntry->Flink) 6330 { 6331 CurrentService = CONTAINING_RECORD(ServiceEntry, 6332 SERVICE, 6333 ServiceListEntry); 6334 6335 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6336 continue; 6337 6338 dwState = SERVICE_ACTIVE; 6339 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6340 dwState = SERVICE_INACTIVE; 6341 6342 if ((dwState & dwServiceState) == 0) 6343 continue; 6344 6345 if (pszGroupName) 6346 { 6347 if (*pszGroupName == 0) 6348 { 6349 if (CurrentService->lpGroup != NULL) 6350 continue; 6351 } 6352 else 6353 { 6354 if ((CurrentService->lpGroup == NULL) || 6355 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6356 continue; 6357 } 6358 } 6359 6360 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6361 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6362 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 6363 6364 if (dwRequiredSize + dwSize <= cbBufSize) 6365 { 6366 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 6367 dwRequiredSize += dwSize; 6368 dwServiceCount++; 6369 dwLastResumeCount = CurrentService->dwResumeCount; 6370 } 6371 else 6372 { 6373 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 6374 break; 6375 } 6376 6377 } 6378 6379 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 6380 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 6381 6382 for (; 6383 ServiceEntry != &ServiceListHead; 6384 ServiceEntry = ServiceEntry->Flink) 6385 { 6386 CurrentService = CONTAINING_RECORD(ServiceEntry, 6387 SERVICE, 6388 ServiceListEntry); 6389 6390 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6391 continue; 6392 6393 dwState = SERVICE_ACTIVE; 6394 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6395 dwState = SERVICE_INACTIVE; 6396 6397 if ((dwState & dwServiceState) == 0) 6398 continue; 6399 6400 if (pszGroupName) 6401 { 6402 if (*pszGroupName == 0) 6403 { 6404 if (CurrentService->lpGroup != NULL) 6405 continue; 6406 } 6407 else 6408 { 6409 if ((CurrentService->lpGroup == NULL) || 6410 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6411 continue; 6412 } 6413 } 6414 6415 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6416 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6417 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 6418 6419 dwError = ERROR_MORE_DATA; 6420 } 6421 6422 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 6423 6424 if (lpResumeIndex) 6425 *lpResumeIndex = dwLastResumeCount; 6426 6427 *lpServicesReturned = dwServiceCount; 6428 *pcbBytesNeeded = dwRequiredSize; 6429 6430 /* If there was no services that matched */ 6431 if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA)) 6432 { 6433 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 6434 goto Done; 6435 } 6436 6437 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer; 6438 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 6439 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 6440 6441 dwRequiredSize = 0; 6442 for (ServiceEntry = &lpService->ServiceListEntry; 6443 ServiceEntry != &ServiceListHead; 6444 ServiceEntry = ServiceEntry->Flink) 6445 { 6446 CurrentService = CONTAINING_RECORD(ServiceEntry, 6447 SERVICE, 6448 ServiceListEntry); 6449 6450 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 6451 continue; 6452 6453 dwState = SERVICE_ACTIVE; 6454 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 6455 dwState = SERVICE_INACTIVE; 6456 6457 if ((dwState & dwServiceState) == 0) 6458 continue; 6459 6460 if (pszGroupName) 6461 { 6462 if (*pszGroupName == 0) 6463 { 6464 if (CurrentService->lpGroup != NULL) 6465 continue; 6466 } 6467 else 6468 { 6469 if ((CurrentService->lpGroup == NULL) || 6470 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName) != 0) 6471 continue; 6472 } 6473 } 6474 6475 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 6476 (DWORD)((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 6477 (DWORD)((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 6478 6479 if (dwRequiredSize + dwSize <= cbBufSize) 6480 { 6481 /* Copy the service name */ 6482 wcscpy(lpStringPtr, 6483 CurrentService->lpServiceName); 6484 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 6485 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 6486 6487 /* Copy the display name */ 6488 wcscpy(lpStringPtr, 6489 CurrentService->lpDisplayName); 6490 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 6491 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 6492 6493 /* Copy the status information */ 6494 memcpy(&lpStatusPtr->ServiceStatusProcess, 6495 &CurrentService->Status, 6496 sizeof(SERVICE_STATUS)); 6497 6498 /* Copy the service process ID */ 6499 if ((CurrentService->Status.dwCurrentState == SERVICE_STOPPED) || (CurrentService->lpImage == NULL)) 6500 lpStatusPtr->ServiceStatusProcess.dwProcessId = 0; 6501 else 6502 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->lpImage->dwProcessId; 6503 6504 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 6505 6506 lpStatusPtr++; 6507 dwRequiredSize += dwSize; 6508 } 6509 else 6510 { 6511 break; 6512 } 6513 } 6514 6515 if (dwError == 0) 6516 { 6517 *pcbBytesNeeded = 0; 6518 if (lpResumeIndex) 6519 *lpResumeIndex = 0; 6520 } 6521 6522 Done: 6523 /* Unlock the service database */ 6524 ScmUnlockDatabase(); 6525 6526 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError); 6527 6528 return dwError; 6529 } 6530 6531 6532 /* Function 43 */ 6533 DWORD 6534 WINAPI 6535 RSendTSMessage( 6536 handle_t BindingHandle) /* FIXME */ 6537 { 6538 UNIMPLEMENTED; 6539 return ERROR_CALL_NOT_IMPLEMENTED; 6540 } 6541 6542 6543 /* Function 44 */ 6544 DWORD 6545 WINAPI 6546 RCreateServiceWOW64A( 6547 handle_t BindingHandle, 6548 LPSTR lpServiceName, 6549 LPSTR lpDisplayName, 6550 DWORD dwDesiredAccess, 6551 DWORD dwServiceType, 6552 DWORD dwStartType, 6553 DWORD dwErrorControl, 6554 LPSTR lpBinaryPathName, 6555 LPSTR lpLoadOrderGroup, 6556 LPDWORD lpdwTagId, 6557 LPBYTE lpDependencies, 6558 DWORD dwDependSize, 6559 LPSTR lpServiceStartName, 6560 LPBYTE lpPassword, 6561 DWORD dwPwSize, 6562 LPSC_RPC_HANDLE lpServiceHandle) 6563 { 6564 UNIMPLEMENTED; 6565 return ERROR_CALL_NOT_IMPLEMENTED; 6566 } 6567 6568 6569 /* Function 45 */ 6570 DWORD 6571 WINAPI 6572 RCreateServiceWOW64W( 6573 handle_t BindingHandle, 6574 LPWSTR lpServiceName, 6575 LPWSTR lpDisplayName, 6576 DWORD dwDesiredAccess, 6577 DWORD dwServiceType, 6578 DWORD dwStartType, 6579 DWORD dwErrorControl, 6580 LPWSTR lpBinaryPathName, 6581 LPWSTR lpLoadOrderGroup, 6582 LPDWORD lpdwTagId, 6583 LPBYTE lpDependencies, 6584 DWORD dwDependSize, 6585 LPWSTR lpServiceStartName, 6586 LPBYTE lpPassword, 6587 DWORD dwPwSize, 6588 LPSC_RPC_HANDLE lpServiceHandle) 6589 { 6590 UNIMPLEMENTED; 6591 return ERROR_CALL_NOT_IMPLEMENTED; 6592 } 6593 6594 6595 /* Function 46 */ 6596 DWORD 6597 WINAPI 6598 RQueryServiceTagInfo( 6599 handle_t BindingHandle) /* FIXME */ 6600 { 6601 UNIMPLEMENTED; 6602 return ERROR_CALL_NOT_IMPLEMENTED; 6603 } 6604 6605 6606 /* Function 47 */ 6607 DWORD 6608 WINAPI 6609 RNotifyServiceStatusChange( 6610 SC_RPC_HANDLE hService, 6611 SC_RPC_NOTIFY_PARAMS NotifyParams, 6612 GUID *pClientProcessGuid, 6613 GUID *pSCMProcessGuid, 6614 PBOOL pfCreateRemoteQueue, 6615 LPSC_NOTIFY_RPC_HANDLE phNotify) 6616 { 6617 UNIMPLEMENTED; 6618 return ERROR_CALL_NOT_IMPLEMENTED; 6619 } 6620 6621 6622 /* Function 48 */ 6623 DWORD 6624 WINAPI 6625 RGetNotifyResults( 6626 SC_NOTIFY_RPC_HANDLE hNotify, 6627 PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams) 6628 { 6629 UNIMPLEMENTED; 6630 return ERROR_CALL_NOT_IMPLEMENTED; 6631 } 6632 6633 6634 /* Function 49 */ 6635 DWORD 6636 WINAPI 6637 RCloseNotifyHandle( 6638 LPSC_NOTIFY_RPC_HANDLE phNotify, 6639 PBOOL pfApcFired) 6640 { 6641 UNIMPLEMENTED; 6642 return ERROR_CALL_NOT_IMPLEMENTED; 6643 } 6644 6645 6646 /* Function 50 */ 6647 DWORD 6648 WINAPI 6649 RControlServiceExA( 6650 SC_RPC_HANDLE hService, 6651 DWORD dwControl, 6652 DWORD dwInfoLevel) 6653 { 6654 UNIMPLEMENTED; 6655 return ERROR_CALL_NOT_IMPLEMENTED; 6656 } 6657 6658 6659 /* Function 51 */ 6660 DWORD 6661 WINAPI 6662 RControlServiceExW( 6663 SC_RPC_HANDLE hService, 6664 DWORD dwControl, 6665 DWORD dwInfoLevel) 6666 { 6667 UNIMPLEMENTED; 6668 return ERROR_CALL_NOT_IMPLEMENTED; 6669 } 6670 6671 6672 /* Function 52 */ 6673 DWORD 6674 WINAPI 6675 RSendPnPMessage( 6676 handle_t BindingHandle) /* FIXME */ 6677 { 6678 UNIMPLEMENTED; 6679 return ERROR_CALL_NOT_IMPLEMENTED; 6680 } 6681 6682 6683 /* Function 53 */ 6684 DWORD 6685 WINAPI 6686 RValidatePnPService( 6687 handle_t BindingHandle) /* FIXME */ 6688 { 6689 UNIMPLEMENTED; 6690 return ERROR_CALL_NOT_IMPLEMENTED; 6691 } 6692 6693 6694 /* Function 54 */ 6695 DWORD 6696 WINAPI 6697 ROpenServiceStatusHandle( 6698 handle_t BindingHandle) /* FIXME */ 6699 { 6700 UNIMPLEMENTED; 6701 return ERROR_CALL_NOT_IMPLEMENTED; 6702 } 6703 6704 6705 /* Function 55 */ 6706 DWORD 6707 WINAPI 6708 RFunction55( 6709 handle_t BindingHandle) /* FIXME */ 6710 { 6711 UNIMPLEMENTED; 6712 return ERROR_CALL_NOT_IMPLEMENTED; 6713 } 6714 6715 6716 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 6717 { 6718 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 6719 } 6720 6721 6722 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 6723 { 6724 HeapFree(GetProcessHeap(), 0, ptr); 6725 } 6726 6727 6728 void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject) 6729 { 6730 /* Close the handle */ 6731 RCloseServiceHandle(&hSCObject); 6732 } 6733 6734 6735 void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock) 6736 { 6737 /* Unlock the database */ 6738 RUnlockServiceDatabase(&Lock); 6739 } 6740 6741 6742 void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify) 6743 { 6744 } 6745 6746 /* EOF */ 6747