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