1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: lib/advapi32/service/scm.c 5 * PURPOSE: Service control manager functions 6 * PROGRAMMER: Emanuele Aliberti 7 * Eric Kohl 8 * UPDATE HISTORY: 9 * 19990413 EA created 10 * 19990515 EA 11 */ 12 13 /* INCLUDES ******************************************************************/ 14 15 #include <advapi32.h> 16 WINE_DEFAULT_DEBUG_CHANNEL(advapi); 17 18 19 /* FUNCTIONS *****************************************************************/ 20 21 handle_t __RPC_USER 22 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName) 23 { 24 handle_t hBinding = NULL; 25 UCHAR *pszStringBinding; 26 RPC_STATUS status; 27 28 TRACE("SVCCTL_HANDLEA_bind() called\n"); 29 30 status = RpcStringBindingComposeA(NULL, 31 (UCHAR *)"ncacn_np", 32 (UCHAR *)szMachineName, 33 (UCHAR *)"\\pipe\\ntsvcs", 34 NULL, 35 (UCHAR **)&pszStringBinding); 36 if (status != RPC_S_OK) 37 { 38 ERR("RpcStringBindingCompose returned 0x%x\n", status); 39 return NULL; 40 } 41 42 /* Set the binding handle that will be used to bind to the server. */ 43 status = RpcBindingFromStringBindingA(pszStringBinding, 44 &hBinding); 45 if (status != RPC_S_OK) 46 { 47 ERR("RpcBindingFromStringBinding returned 0x%x\n", status); 48 } 49 50 status = RpcStringFreeA(&pszStringBinding); 51 if (status != RPC_S_OK) 52 { 53 ERR("RpcStringFree returned 0x%x\n", status); 54 } 55 56 return hBinding; 57 } 58 59 60 void __RPC_USER 61 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName, 62 handle_t hBinding) 63 { 64 RPC_STATUS status; 65 66 TRACE("SVCCTL_HANDLEA_unbind() called\n"); 67 68 status = RpcBindingFree(&hBinding); 69 if (status != RPC_S_OK) 70 { 71 ERR("RpcBindingFree returned 0x%x\n", status); 72 } 73 } 74 75 76 handle_t __RPC_USER 77 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName) 78 { 79 handle_t hBinding = NULL; 80 LPWSTR pszStringBinding; 81 RPC_STATUS status; 82 83 TRACE("SVCCTL_HANDLEW_bind() called\n"); 84 85 status = RpcStringBindingComposeW(NULL, 86 L"ncacn_np", 87 szMachineName, 88 L"\\pipe\\ntsvcs", 89 NULL, 90 &pszStringBinding); 91 if (status != RPC_S_OK) 92 { 93 ERR("RpcStringBindingCompose returned 0x%x\n", status); 94 return NULL; 95 } 96 97 /* Set the binding handle that will be used to bind to the server. */ 98 status = RpcBindingFromStringBindingW(pszStringBinding, 99 &hBinding); 100 if (status != RPC_S_OK) 101 { 102 ERR("RpcBindingFromStringBinding returned 0x%x\n", status); 103 } 104 105 status = RpcStringFreeW(&pszStringBinding); 106 if (status != RPC_S_OK) 107 { 108 ERR("RpcStringFree returned 0x%x\n", status); 109 } 110 111 return hBinding; 112 } 113 114 115 void __RPC_USER 116 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName, 117 handle_t hBinding) 118 { 119 RPC_STATUS status; 120 121 TRACE("SVCCTL_HANDLEW_unbind() called\n"); 122 123 status = RpcBindingFree(&hBinding); 124 if (status != RPC_S_OK) 125 { 126 ERR("RpcBindingFree returned 0x%x\n", status); 127 } 128 } 129 130 131 DWORD 132 ScmRpcStatusToWinError(RPC_STATUS Status) 133 { 134 switch (Status) 135 { 136 case STATUS_ACCESS_VIOLATION: 137 case RPC_S_INVALID_BINDING: 138 case RPC_X_SS_IN_NULL_CONTEXT: 139 return ERROR_INVALID_HANDLE; 140 141 case RPC_X_ENUM_VALUE_OUT_OF_RANGE: 142 case RPC_X_BYTE_COUNT_TOO_SMALL: 143 return ERROR_INVALID_PARAMETER; 144 145 case RPC_X_NULL_REF_POINTER: 146 return ERROR_INVALID_ADDRESS; 147 148 default: 149 return (DWORD)Status; 150 } 151 } 152 153 154 /********************************************************************** 155 * ChangeServiceConfig2A 156 * 157 * @implemented 158 */ 159 BOOL WINAPI 160 ChangeServiceConfig2A(SC_HANDLE hService, 161 DWORD dwInfoLevel, 162 LPVOID lpInfo) 163 { 164 SC_RPC_CONFIG_INFOA Info; 165 DWORD dwError; 166 167 TRACE("ChangeServiceConfig2A() called\n"); 168 169 if (lpInfo == NULL) return TRUE; 170 171 /* Fill relevant field of the Info structure */ 172 Info.dwInfoLevel = dwInfoLevel; 173 switch (dwInfoLevel) 174 { 175 case SERVICE_CONFIG_DESCRIPTION: 176 Info.psd = lpInfo; 177 break; 178 179 case SERVICE_CONFIG_FAILURE_ACTIONS: 180 Info.psfa = lpInfo; 181 break; 182 183 default: 184 WARN("Unknown info level 0x%lx\n", dwInfoLevel); 185 SetLastError(ERROR_INVALID_PARAMETER); 186 return FALSE; 187 } 188 189 RpcTryExcept 190 { 191 dwError = RChangeServiceConfig2A((SC_RPC_HANDLE)hService, 192 Info); 193 } 194 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 195 { 196 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 197 } 198 RpcEndExcept; 199 200 if (dwError != ERROR_SUCCESS) 201 { 202 TRACE("RChangeServiceConfig2A() failed (Error %lu)\n", dwError); 203 SetLastError(dwError); 204 return FALSE; 205 } 206 207 return TRUE; 208 } 209 210 211 /********************************************************************** 212 * ChangeServiceConfig2W 213 * 214 * @implemented 215 */ 216 BOOL WINAPI 217 ChangeServiceConfig2W(SC_HANDLE hService, 218 DWORD dwInfoLevel, 219 LPVOID lpInfo) 220 { 221 SC_RPC_CONFIG_INFOW Info; 222 DWORD dwError; 223 224 TRACE("ChangeServiceConfig2W() called\n"); 225 226 if (lpInfo == NULL) return TRUE; 227 228 /* Fill relevant field of the Info structure */ 229 Info.dwInfoLevel = dwInfoLevel; 230 switch (dwInfoLevel) 231 { 232 case SERVICE_CONFIG_DESCRIPTION: 233 Info.psd = lpInfo; 234 break; 235 236 case SERVICE_CONFIG_FAILURE_ACTIONS: 237 Info.psfa = lpInfo; 238 break; 239 240 default: 241 WARN("Unknown info level 0x%lx\n", dwInfoLevel); 242 SetLastError(ERROR_INVALID_PARAMETER); 243 return FALSE; 244 } 245 246 RpcTryExcept 247 { 248 dwError = RChangeServiceConfig2W((SC_RPC_HANDLE)hService, 249 Info); 250 } 251 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 252 { 253 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 254 } 255 RpcEndExcept; 256 257 if (dwError != ERROR_SUCCESS) 258 { 259 TRACE("RChangeServiceConfig2W() failed (Error %lu)\n", dwError); 260 SetLastError(dwError); 261 return FALSE; 262 } 263 264 return TRUE; 265 } 266 267 268 /********************************************************************** 269 * ChangeServiceConfigA 270 * 271 * @implemented 272 */ 273 BOOL WINAPI 274 ChangeServiceConfigA(SC_HANDLE hService, 275 DWORD dwServiceType, 276 DWORD dwStartType, 277 DWORD dwErrorControl, 278 LPCSTR lpBinaryPathName, 279 LPCSTR lpLoadOrderGroup, 280 LPDWORD lpdwTagId, 281 LPCSTR lpDependencies, 282 LPCSTR lpServiceStartName, 283 LPCSTR lpPassword, 284 LPCSTR lpDisplayName) 285 { 286 DWORD dwError; 287 DWORD dwDependenciesLength = 0; 288 SIZE_T cchLength; 289 LPCSTR lpStr; 290 DWORD dwPasswordLength = 0; 291 LPWSTR lpPasswordW = NULL; 292 LPBYTE lpEncryptedPassword = NULL; 293 294 TRACE("ChangeServiceConfigA() called\n"); 295 296 /* Calculate the Dependencies length*/ 297 if (lpDependencies != NULL) 298 { 299 lpStr = lpDependencies; 300 while (*lpStr) 301 { 302 cchLength = strlen(lpStr) + 1; 303 dwDependenciesLength += (DWORD)cchLength; 304 lpStr = lpStr + cchLength; 305 } 306 dwDependenciesLength++; 307 } 308 309 if (lpPassword != NULL) 310 { 311 /* Convert the password to unicode */ 312 lpPasswordW = HeapAlloc(GetProcessHeap(), 313 HEAP_ZERO_MEMORY, 314 (strlen(lpPassword) + 1) * sizeof(WCHAR)); 315 if (lpPasswordW == NULL) 316 { 317 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 318 return FALSE; 319 } 320 321 MultiByteToWideChar(CP_ACP, 322 0, 323 lpPassword, 324 -1, 325 lpPasswordW, 326 (int)(strlen(lpPassword) + 1)); 327 328 /* FIXME: Encrypt the password */ 329 lpEncryptedPassword = (LPBYTE)lpPasswordW; 330 dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR); 331 } 332 333 RpcTryExcept 334 { 335 /* Call to services.exe using RPC */ 336 dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService, 337 dwServiceType, 338 dwStartType, 339 dwErrorControl, 340 (LPSTR)lpBinaryPathName, 341 (LPSTR)lpLoadOrderGroup, 342 lpdwTagId, 343 (LPBYTE)lpDependencies, 344 dwDependenciesLength, 345 (LPSTR)lpServiceStartName, 346 lpEncryptedPassword, 347 dwPasswordLength, 348 (LPSTR)lpDisplayName); 349 } 350 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 351 { 352 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 353 } 354 RpcEndExcept; 355 356 if (lpPasswordW != NULL) 357 HeapFree(GetProcessHeap(), 0, lpPasswordW); 358 359 if (dwError != ERROR_SUCCESS) 360 { 361 TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError); 362 SetLastError(dwError); 363 return FALSE; 364 } 365 366 return TRUE; 367 } 368 369 370 /********************************************************************** 371 * ChangeServiceConfigW 372 * 373 * @implemented 374 */ 375 BOOL WINAPI 376 ChangeServiceConfigW(SC_HANDLE hService, 377 DWORD dwServiceType, 378 DWORD dwStartType, 379 DWORD dwErrorControl, 380 LPCWSTR lpBinaryPathName, 381 LPCWSTR lpLoadOrderGroup, 382 LPDWORD lpdwTagId, 383 LPCWSTR lpDependencies, 384 LPCWSTR lpServiceStartName, 385 LPCWSTR lpPassword, 386 LPCWSTR lpDisplayName) 387 { 388 DWORD dwError; 389 DWORD dwDependenciesLength = 0; 390 SIZE_T cchLength; 391 LPCWSTR lpStr; 392 DWORD dwPasswordLength = 0; 393 LPBYTE lpEncryptedPassword = NULL; 394 395 TRACE("ChangeServiceConfigW() called\n"); 396 397 /* Calculate the Dependencies length*/ 398 if (lpDependencies != NULL) 399 { 400 lpStr = lpDependencies; 401 while (*lpStr) 402 { 403 cchLength = wcslen(lpStr) + 1; 404 dwDependenciesLength += (DWORD)cchLength; 405 lpStr = lpStr + cchLength; 406 } 407 dwDependenciesLength++; 408 dwDependenciesLength *= sizeof(WCHAR); 409 } 410 411 if (lpPassword != NULL) 412 { 413 /* FIXME: Encrypt the password */ 414 lpEncryptedPassword = (LPBYTE)lpPassword; 415 dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR); 416 } 417 418 RpcTryExcept 419 { 420 /* Call to services.exe using RPC */ 421 dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService, 422 dwServiceType, 423 dwStartType, 424 dwErrorControl, 425 (LPWSTR)lpBinaryPathName, 426 (LPWSTR)lpLoadOrderGroup, 427 lpdwTagId, 428 (LPBYTE)lpDependencies, 429 dwDependenciesLength, 430 (LPWSTR)lpServiceStartName, 431 lpEncryptedPassword, 432 dwPasswordLength, 433 (LPWSTR)lpDisplayName); 434 } 435 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 436 { 437 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 438 } 439 RpcEndExcept; 440 441 if (dwError != ERROR_SUCCESS) 442 { 443 TRACE("RChangeServiceConfigW() failed (Error %lu)\n", dwError); 444 SetLastError(dwError); 445 return FALSE; 446 } 447 448 return TRUE; 449 } 450 451 452 /********************************************************************** 453 * CloseServiceHandle 454 * 455 * @implemented 456 */ 457 BOOL WINAPI 458 CloseServiceHandle(SC_HANDLE hSCObject) 459 { 460 DWORD dwError; 461 462 TRACE("CloseServiceHandle() called\n"); 463 464 if (!hSCObject) 465 { 466 SetLastError(ERROR_INVALID_HANDLE); 467 return FALSE; 468 } 469 470 RpcTryExcept 471 { 472 /* Call to services.exe using RPC */ 473 dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject); 474 } 475 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 476 { 477 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 478 } 479 RpcEndExcept; 480 481 if (dwError) 482 { 483 TRACE("RCloseServiceHandle() failed (Error %lu)\n", dwError); 484 SetLastError(dwError); 485 return FALSE; 486 } 487 488 TRACE("CloseServiceHandle() done\n"); 489 490 return TRUE; 491 } 492 493 494 /********************************************************************** 495 * ControlService 496 * 497 * @implemented 498 */ 499 BOOL WINAPI 500 ControlService(SC_HANDLE hService, 501 DWORD dwControl, 502 LPSERVICE_STATUS lpServiceStatus) 503 { 504 DWORD dwError; 505 506 TRACE("ControlService(%x, %x, %p)\n", 507 hService, dwControl, lpServiceStatus); 508 509 RpcTryExcept 510 { 511 /* Call to services.exe using RPC */ 512 dwError = RControlService((SC_RPC_HANDLE)hService, 513 dwControl, 514 lpServiceStatus); 515 } 516 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 517 { 518 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 519 } 520 RpcEndExcept; 521 522 if (dwError != ERROR_SUCCESS) 523 { 524 TRACE("RControlService() failed (Error %lu)\n", dwError); 525 SetLastError(dwError); 526 return FALSE; 527 } 528 529 TRACE("ControlService() done\n"); 530 531 return TRUE; 532 } 533 534 535 /********************************************************************** 536 * ControlServiceEx 537 * 538 * @unimplemented 539 */ 540 BOOL WINAPI 541 ControlServiceEx(IN SC_HANDLE hService, 542 IN DWORD dwControl, 543 IN DWORD dwInfoLevel, 544 IN OUT PVOID pControlParams) 545 { 546 FIXME("ControlServiceEx(0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n", 547 hService, dwControl, dwInfoLevel, pControlParams); 548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 549 return FALSE; 550 } 551 552 553 /********************************************************************** 554 * CreateServiceA 555 * 556 * @implemented 557 */ 558 SC_HANDLE WINAPI 559 CreateServiceA(SC_HANDLE hSCManager, 560 LPCSTR lpServiceName, 561 LPCSTR lpDisplayName, 562 DWORD dwDesiredAccess, 563 DWORD dwServiceType, 564 DWORD dwStartType, 565 DWORD dwErrorControl, 566 LPCSTR lpBinaryPathName, 567 LPCSTR lpLoadOrderGroup, 568 LPDWORD lpdwTagId, 569 LPCSTR lpDependencies, 570 LPCSTR lpServiceStartName, 571 LPCSTR lpPassword) 572 { 573 SC_HANDLE hService = NULL; 574 DWORD dwDependenciesLength = 0; 575 DWORD dwError; 576 SIZE_T cchLength; 577 LPCSTR lpStr; 578 DWORD dwPasswordLength = 0; 579 LPWSTR lpPasswordW = NULL; 580 LPBYTE lpEncryptedPassword = NULL; 581 582 TRACE("CreateServiceA() called\n"); 583 TRACE("%p %s %s\n", hSCManager, 584 lpServiceName, lpDisplayName); 585 586 if (!hSCManager) 587 { 588 SetLastError(ERROR_INVALID_HANDLE); 589 return NULL; 590 } 591 592 /* Calculate the Dependencies length */ 593 if (lpDependencies != NULL) 594 { 595 lpStr = lpDependencies; 596 while (*lpStr) 597 { 598 cchLength = strlen(lpStr) + 1; 599 dwDependenciesLength += (DWORD)cchLength; 600 lpStr = lpStr + cchLength; 601 } 602 dwDependenciesLength++; 603 } 604 605 if (lpPassword != NULL) 606 { 607 /* Convert the password to unicode */ 608 lpPasswordW = HeapAlloc(GetProcessHeap(), 609 HEAP_ZERO_MEMORY, 610 (strlen(lpPassword) + 1) * sizeof(WCHAR)); 611 if (lpPasswordW == NULL) 612 { 613 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 614 return FALSE; 615 } 616 617 MultiByteToWideChar(CP_ACP, 618 0, 619 lpPassword, 620 -1, 621 lpPasswordW, 622 (int)(strlen(lpPassword) + 1)); 623 624 /* FIXME: Encrypt the password */ 625 lpEncryptedPassword = (LPBYTE)lpPasswordW; 626 dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR); 627 } 628 629 RpcTryExcept 630 { 631 /* Call to services.exe using RPC */ 632 dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager, 633 (LPSTR)lpServiceName, 634 (LPSTR)lpDisplayName, 635 dwDesiredAccess, 636 dwServiceType, 637 dwStartType, 638 dwErrorControl, 639 (LPSTR)lpBinaryPathName, 640 (LPSTR)lpLoadOrderGroup, 641 lpdwTagId, 642 (LPBYTE)lpDependencies, 643 dwDependenciesLength, 644 (LPSTR)lpServiceStartName, 645 lpEncryptedPassword, 646 dwPasswordLength, 647 (SC_RPC_HANDLE *)&hService); 648 } 649 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 650 { 651 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 652 } 653 RpcEndExcept; 654 655 if (lpPasswordW != NULL) 656 HeapFree(GetProcessHeap(), 0, lpPasswordW); 657 658 SetLastError(dwError); 659 if (dwError != ERROR_SUCCESS) 660 { 661 TRACE("RCreateServiceA() failed (Error %lu)\n", dwError); 662 return NULL; 663 } 664 665 return hService; 666 } 667 668 669 /********************************************************************** 670 * CreateServiceW 671 * 672 * @implemented 673 */ 674 SC_HANDLE WINAPI 675 CreateServiceW(SC_HANDLE hSCManager, 676 LPCWSTR lpServiceName, 677 LPCWSTR lpDisplayName, 678 DWORD dwDesiredAccess, 679 DWORD dwServiceType, 680 DWORD dwStartType, 681 DWORD dwErrorControl, 682 LPCWSTR lpBinaryPathName, 683 LPCWSTR lpLoadOrderGroup, 684 LPDWORD lpdwTagId, 685 LPCWSTR lpDependencies, 686 LPCWSTR lpServiceStartName, 687 LPCWSTR lpPassword) 688 { 689 SC_HANDLE hService = NULL; 690 DWORD dwDependenciesLength = 0; 691 DWORD dwError; 692 SIZE_T cchLength; 693 LPCWSTR lpStr; 694 DWORD dwPasswordLength = 0; 695 LPBYTE lpEncryptedPassword = NULL; 696 697 TRACE("CreateServiceW() called\n"); 698 TRACE("%p %S %S\n", hSCManager, 699 lpServiceName, lpDisplayName); 700 701 if (!hSCManager) 702 { 703 SetLastError(ERROR_INVALID_HANDLE); 704 return NULL; 705 } 706 707 /* Calculate the Dependencies length */ 708 if (lpDependencies != NULL) 709 { 710 lpStr = lpDependencies; 711 while (*lpStr) 712 { 713 cchLength = wcslen(lpStr) + 1; 714 dwDependenciesLength += (DWORD)cchLength; 715 lpStr = lpStr + cchLength; 716 } 717 dwDependenciesLength++; 718 dwDependenciesLength *= sizeof(WCHAR); 719 } 720 721 if (lpPassword != NULL) 722 { 723 /* FIXME: Encrypt the password */ 724 lpEncryptedPassword = (LPBYTE)lpPassword; 725 dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR); 726 } 727 728 RpcTryExcept 729 { 730 /* Call to services.exe using RPC */ 731 dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager, 732 lpServiceName, 733 lpDisplayName, 734 dwDesiredAccess, 735 dwServiceType, 736 dwStartType, 737 dwErrorControl, 738 lpBinaryPathName, 739 lpLoadOrderGroup, 740 lpdwTagId, 741 (LPBYTE)lpDependencies, 742 dwDependenciesLength, 743 lpServiceStartName, 744 lpEncryptedPassword, 745 dwPasswordLength, 746 (SC_RPC_HANDLE *)&hService); 747 } 748 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 749 { 750 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 751 } 752 RpcEndExcept; 753 754 SetLastError(dwError); 755 if (dwError != ERROR_SUCCESS) 756 { 757 TRACE("RCreateServiceW() failed (Error %lu)\n", dwError); 758 return NULL; 759 } 760 761 return hService; 762 } 763 764 765 /********************************************************************** 766 * DeleteService 767 * 768 * @implemented 769 */ 770 BOOL WINAPI 771 DeleteService(SC_HANDLE hService) 772 { 773 DWORD dwError; 774 775 TRACE("DeleteService(%x)\n", hService); 776 777 RpcTryExcept 778 { 779 /* Call to services.exe using RPC */ 780 dwError = RDeleteService((SC_RPC_HANDLE)hService); 781 } 782 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 783 { 784 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 785 } 786 RpcEndExcept; 787 788 if (dwError != ERROR_SUCCESS) 789 { 790 TRACE("RDeleteService() failed (Error %lu)\n", dwError); 791 SetLastError(dwError); 792 return FALSE; 793 } 794 795 return TRUE; 796 } 797 798 799 /********************************************************************** 800 * EnumDependentServicesA 801 * 802 * @implemented 803 */ 804 BOOL WINAPI 805 EnumDependentServicesA(SC_HANDLE hService, 806 DWORD dwServiceState, 807 LPENUM_SERVICE_STATUSA lpServices, 808 DWORD cbBufSize, 809 LPDWORD pcbBytesNeeded, 810 LPDWORD lpServicesReturned) 811 { 812 ENUM_SERVICE_STATUSA ServiceStatus; 813 LPENUM_SERVICE_STATUSA lpStatusPtr; 814 DWORD dwBufferSize; 815 DWORD dwError; 816 DWORD dwCount; 817 818 TRACE("EnumDependentServicesA() called\n"); 819 820 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA)) 821 { 822 lpStatusPtr = &ServiceStatus; 823 dwBufferSize = sizeof(ENUM_SERVICE_STATUSA); 824 } 825 else 826 { 827 lpStatusPtr = lpServices; 828 dwBufferSize = cbBufSize; 829 } 830 831 RpcTryExcept 832 { 833 dwError = REnumDependentServicesA((SC_RPC_HANDLE)hService, 834 dwServiceState, 835 (LPBYTE)lpStatusPtr, 836 dwBufferSize, 837 pcbBytesNeeded, 838 lpServicesReturned); 839 } 840 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 841 { 842 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 843 } 844 RpcEndExcept; 845 846 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 847 { 848 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 849 { 850 if (lpStatusPtr->lpServiceName) 851 lpStatusPtr->lpServiceName = 852 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 853 854 if (lpStatusPtr->lpDisplayName) 855 lpStatusPtr->lpDisplayName = 856 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 857 858 lpStatusPtr++; 859 } 860 } 861 862 if (dwError != ERROR_SUCCESS) 863 { 864 TRACE("REnumDependentServicesA() failed (Error %lu)\n", dwError); 865 SetLastError(dwError); 866 return FALSE; 867 } 868 869 TRACE("EnumDependentServicesA() done\n"); 870 871 return TRUE; 872 } 873 874 875 /********************************************************************** 876 * EnumDependentServicesW 877 * 878 * @implemented 879 */ 880 BOOL WINAPI 881 EnumDependentServicesW(SC_HANDLE hService, 882 DWORD dwServiceState, 883 LPENUM_SERVICE_STATUSW lpServices, 884 DWORD cbBufSize, 885 LPDWORD pcbBytesNeeded, 886 LPDWORD lpServicesReturned) 887 { 888 ENUM_SERVICE_STATUSW ServiceStatus; 889 LPENUM_SERVICE_STATUSW lpStatusPtr; 890 DWORD dwBufferSize; 891 DWORD dwError; 892 DWORD dwCount; 893 894 TRACE("EnumDependentServicesW() called\n"); 895 896 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW)) 897 { 898 lpStatusPtr = &ServiceStatus; 899 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW); 900 } 901 else 902 { 903 lpStatusPtr = lpServices; 904 dwBufferSize = cbBufSize; 905 } 906 907 RpcTryExcept 908 { 909 dwError = REnumDependentServicesW((SC_RPC_HANDLE)hService, 910 dwServiceState, 911 (LPBYTE)lpStatusPtr, 912 dwBufferSize, 913 pcbBytesNeeded, 914 lpServicesReturned); 915 } 916 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 917 { 918 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 919 } 920 RpcEndExcept; 921 922 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 923 { 924 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 925 { 926 if (lpStatusPtr->lpServiceName) 927 lpStatusPtr->lpServiceName = 928 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 929 930 if (lpStatusPtr->lpDisplayName) 931 lpStatusPtr->lpDisplayName = 932 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 933 934 lpStatusPtr++; 935 } 936 } 937 938 if (dwError != ERROR_SUCCESS) 939 { 940 TRACE("REnumDependentServicesW() failed (Error %lu)\n", dwError); 941 SetLastError(dwError); 942 return FALSE; 943 } 944 945 TRACE("EnumDependentServicesW() done\n"); 946 947 return TRUE; 948 } 949 950 951 /********************************************************************** 952 * EnumServiceGroupW 953 * 954 * @implemented 955 */ 956 BOOL WINAPI 957 EnumServiceGroupW(SC_HANDLE hSCManager, 958 DWORD dwServiceType, 959 DWORD dwServiceState, 960 LPENUM_SERVICE_STATUSW lpServices, 961 DWORD cbBufSize, 962 LPDWORD pcbBytesNeeded, 963 LPDWORD lpServicesReturned, 964 LPDWORD lpResumeHandle, 965 LPCWSTR lpGroup) 966 { 967 ENUM_SERVICE_STATUSW ServiceStatus; 968 LPENUM_SERVICE_STATUSW lpStatusPtr; 969 DWORD dwBufferSize; 970 DWORD dwError; 971 DWORD dwCount; 972 973 TRACE("EnumServiceGroupW() called\n"); 974 975 if (!hSCManager) 976 { 977 SetLastError(ERROR_INVALID_HANDLE); 978 return FALSE; 979 } 980 981 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 982 { 983 SetLastError(ERROR_INVALID_ADDRESS); 984 return FALSE; 985 } 986 987 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW)) 988 { 989 lpStatusPtr = &ServiceStatus; 990 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW); 991 } 992 else 993 { 994 lpStatusPtr = lpServices; 995 dwBufferSize = cbBufSize; 996 } 997 998 RpcTryExcept 999 { 1000 if (lpGroup == NULL) 1001 { 1002 dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager, 1003 dwServiceType, 1004 dwServiceState, 1005 (LPBYTE)lpStatusPtr, 1006 dwBufferSize, 1007 pcbBytesNeeded, 1008 lpServicesReturned, 1009 lpResumeHandle); 1010 } 1011 else 1012 { 1013 dwError = REnumServiceGroupW((SC_RPC_HANDLE)hSCManager, 1014 dwServiceType, 1015 dwServiceState, 1016 (LPBYTE)lpStatusPtr, 1017 dwBufferSize, 1018 pcbBytesNeeded, 1019 lpServicesReturned, 1020 lpResumeHandle, 1021 lpGroup); 1022 } 1023 } 1024 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1025 { 1026 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1027 } 1028 RpcEndExcept; 1029 1030 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 1031 { 1032 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 1033 { 1034 if (lpStatusPtr->lpServiceName) 1035 lpStatusPtr->lpServiceName = 1036 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 1037 1038 if (lpStatusPtr->lpDisplayName) 1039 lpStatusPtr->lpDisplayName = 1040 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 1041 1042 lpStatusPtr++; 1043 } 1044 } 1045 1046 if (dwError != ERROR_SUCCESS) 1047 { 1048 TRACE("REnumServiceGroupW() failed (Error %lu)\n", dwError); 1049 SetLastError(dwError); 1050 return FALSE; 1051 } 1052 1053 TRACE("EnumServiceGroupW() done\n"); 1054 1055 return TRUE; 1056 } 1057 1058 1059 /********************************************************************** 1060 * EnumServicesStatusA 1061 * 1062 * @implemented 1063 */ 1064 BOOL WINAPI 1065 EnumServicesStatusA(SC_HANDLE hSCManager, 1066 DWORD dwServiceType, 1067 DWORD dwServiceState, 1068 LPENUM_SERVICE_STATUSA lpServices, 1069 DWORD cbBufSize, 1070 LPDWORD pcbBytesNeeded, 1071 LPDWORD lpServicesReturned, 1072 LPDWORD lpResumeHandle) 1073 { 1074 ENUM_SERVICE_STATUSA ServiceStatus; 1075 LPENUM_SERVICE_STATUSA lpStatusPtr; 1076 DWORD dwBufferSize; 1077 DWORD dwError; 1078 DWORD dwCount; 1079 1080 TRACE("EnumServicesStatusA() called\n"); 1081 1082 if (!hSCManager) 1083 { 1084 SetLastError(ERROR_INVALID_HANDLE); 1085 return FALSE; 1086 } 1087 1088 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 1089 { 1090 SetLastError(ERROR_INVALID_ADDRESS); 1091 return FALSE; 1092 } 1093 1094 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA)) 1095 { 1096 lpStatusPtr = &ServiceStatus; 1097 dwBufferSize = sizeof(ENUM_SERVICE_STATUSA); 1098 } 1099 else 1100 { 1101 lpStatusPtr = lpServices; 1102 dwBufferSize = cbBufSize; 1103 } 1104 1105 RpcTryExcept 1106 { 1107 dwError = REnumServicesStatusA((SC_RPC_HANDLE)hSCManager, 1108 dwServiceType, 1109 dwServiceState, 1110 (LPBYTE)lpStatusPtr, 1111 dwBufferSize, 1112 pcbBytesNeeded, 1113 lpServicesReturned, 1114 lpResumeHandle); 1115 } 1116 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1117 { 1118 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1119 } 1120 RpcEndExcept; 1121 1122 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 1123 { 1124 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 1125 { 1126 if (lpStatusPtr->lpServiceName) 1127 lpStatusPtr->lpServiceName = 1128 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 1129 1130 if (lpStatusPtr->lpDisplayName) 1131 lpStatusPtr->lpDisplayName = 1132 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 1133 1134 lpStatusPtr++; 1135 } 1136 } 1137 1138 if (dwError != ERROR_SUCCESS) 1139 { 1140 TRACE("REnumServicesStatusA() failed (Error %lu)\n", dwError); 1141 SetLastError(dwError); 1142 return FALSE; 1143 } 1144 1145 TRACE("EnumServicesStatusA() done\n"); 1146 1147 return TRUE; 1148 } 1149 1150 1151 /********************************************************************** 1152 * EnumServicesStatusW 1153 * 1154 * @implemented 1155 */ 1156 BOOL WINAPI 1157 EnumServicesStatusW(SC_HANDLE hSCManager, 1158 DWORD dwServiceType, 1159 DWORD dwServiceState, 1160 LPENUM_SERVICE_STATUSW lpServices, 1161 DWORD cbBufSize, 1162 LPDWORD pcbBytesNeeded, 1163 LPDWORD lpServicesReturned, 1164 LPDWORD lpResumeHandle) 1165 { 1166 ENUM_SERVICE_STATUSW ServiceStatus; 1167 LPENUM_SERVICE_STATUSW lpStatusPtr; 1168 DWORD dwBufferSize; 1169 DWORD dwError; 1170 DWORD dwCount; 1171 1172 TRACE("EnumServicesStatusW() called\n"); 1173 1174 if (!hSCManager) 1175 { 1176 SetLastError(ERROR_INVALID_HANDLE); 1177 return FALSE; 1178 } 1179 1180 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 1181 { 1182 SetLastError(ERROR_INVALID_ADDRESS); 1183 return FALSE; 1184 } 1185 1186 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW)) 1187 { 1188 lpStatusPtr = &ServiceStatus; 1189 dwBufferSize = sizeof(ENUM_SERVICE_STATUSW); 1190 } 1191 else 1192 { 1193 lpStatusPtr = lpServices; 1194 dwBufferSize = cbBufSize; 1195 } 1196 1197 RpcTryExcept 1198 { 1199 dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager, 1200 dwServiceType, 1201 dwServiceState, 1202 (LPBYTE)lpStatusPtr, 1203 dwBufferSize, 1204 pcbBytesNeeded, 1205 lpServicesReturned, 1206 lpResumeHandle); 1207 } 1208 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1209 { 1210 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1211 } 1212 RpcEndExcept; 1213 1214 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 1215 { 1216 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 1217 { 1218 if (lpStatusPtr->lpServiceName) 1219 lpStatusPtr->lpServiceName = 1220 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 1221 1222 if (lpStatusPtr->lpDisplayName) 1223 lpStatusPtr->lpDisplayName = 1224 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 1225 1226 lpStatusPtr++; 1227 } 1228 } 1229 1230 if (dwError != ERROR_SUCCESS) 1231 { 1232 TRACE("REnumServicesStatusW() failed (Error %lu)\n", dwError); 1233 SetLastError(dwError); 1234 return FALSE; 1235 } 1236 1237 TRACE("EnumServicesStatusW() done\n"); 1238 1239 return TRUE; 1240 } 1241 1242 1243 /********************************************************************** 1244 * EnumServicesStatusExA 1245 * 1246 * @implemented 1247 */ 1248 BOOL WINAPI 1249 EnumServicesStatusExA(SC_HANDLE hSCManager, 1250 SC_ENUM_TYPE InfoLevel, 1251 DWORD dwServiceType, 1252 DWORD dwServiceState, 1253 LPBYTE lpServices, 1254 DWORD cbBufSize, 1255 LPDWORD pcbBytesNeeded, 1256 LPDWORD lpServicesReturned, 1257 LPDWORD lpResumeHandle, 1258 LPCSTR pszGroupName) 1259 { 1260 ENUM_SERVICE_STATUS_PROCESSA ServiceStatus; 1261 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr; 1262 DWORD dwBufferSize; 1263 DWORD dwError; 1264 DWORD dwCount; 1265 1266 TRACE("EnumServicesStatusExA() called\n"); 1267 1268 if (InfoLevel != SC_ENUM_PROCESS_INFO) 1269 { 1270 SetLastError(ERROR_INVALID_LEVEL); 1271 return FALSE; 1272 } 1273 1274 if (!hSCManager) 1275 { 1276 SetLastError(ERROR_INVALID_HANDLE); 1277 return FALSE; 1278 } 1279 1280 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 1281 { 1282 SetLastError(ERROR_INVALID_ADDRESS); 1283 return FALSE; 1284 } 1285 1286 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA)) 1287 { 1288 lpStatusPtr = &ServiceStatus; 1289 dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA); 1290 } 1291 else 1292 { 1293 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices; 1294 dwBufferSize = cbBufSize; 1295 } 1296 1297 RpcTryExcept 1298 { 1299 dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager, 1300 InfoLevel, 1301 dwServiceType, 1302 dwServiceState, 1303 (LPBYTE)lpStatusPtr, 1304 dwBufferSize, 1305 pcbBytesNeeded, 1306 lpServicesReturned, 1307 lpResumeHandle, 1308 (LPSTR)pszGroupName); 1309 } 1310 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1311 { 1312 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1313 } 1314 RpcEndExcept; 1315 1316 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 1317 { 1318 if (InfoLevel == SC_ENUM_PROCESS_INFO) 1319 { 1320 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 1321 { 1322 if (lpStatusPtr->lpServiceName) 1323 lpStatusPtr->lpServiceName = 1324 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 1325 1326 if (lpStatusPtr->lpDisplayName) 1327 lpStatusPtr->lpDisplayName = 1328 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 1329 1330 lpStatusPtr++; 1331 } 1332 } 1333 } 1334 1335 if (dwError != ERROR_SUCCESS) 1336 { 1337 TRACE("REnumServicesStatusExA() failed (Error %lu)\n", dwError); 1338 SetLastError(dwError); 1339 return FALSE; 1340 } 1341 1342 TRACE("EnumServicesStatusExA() done\n"); 1343 1344 return TRUE; 1345 } 1346 1347 1348 /********************************************************************** 1349 * EnumServicesStatusExW 1350 * 1351 * @implemented 1352 */ 1353 BOOL WINAPI 1354 EnumServicesStatusExW(SC_HANDLE hSCManager, 1355 SC_ENUM_TYPE InfoLevel, 1356 DWORD dwServiceType, 1357 DWORD dwServiceState, 1358 LPBYTE lpServices, 1359 DWORD cbBufSize, 1360 LPDWORD pcbBytesNeeded, 1361 LPDWORD lpServicesReturned, 1362 LPDWORD lpResumeHandle, 1363 LPCWSTR pszGroupName) 1364 { 1365 ENUM_SERVICE_STATUS_PROCESSW ServiceStatus; 1366 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; 1367 DWORD dwBufferSize; 1368 DWORD dwError; 1369 DWORD dwCount; 1370 1371 TRACE("EnumServicesStatusExW() called\n"); 1372 1373 if (InfoLevel != SC_ENUM_PROCESS_INFO) 1374 { 1375 SetLastError(ERROR_INVALID_LEVEL); 1376 return FALSE; 1377 } 1378 1379 if (!hSCManager) 1380 { 1381 SetLastError(ERROR_INVALID_HANDLE); 1382 return FALSE; 1383 } 1384 1385 if (pcbBytesNeeded == NULL || lpServicesReturned == NULL) 1386 { 1387 SetLastError(ERROR_INVALID_ADDRESS); 1388 return FALSE; 1389 } 1390 1391 if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW)) 1392 { 1393 lpStatusPtr = &ServiceStatus; 1394 dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW); 1395 } 1396 else 1397 { 1398 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; 1399 dwBufferSize = cbBufSize; 1400 } 1401 1402 RpcTryExcept 1403 { 1404 dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager, 1405 InfoLevel, 1406 dwServiceType, 1407 dwServiceState, 1408 (LPBYTE)lpStatusPtr, 1409 dwBufferSize, 1410 pcbBytesNeeded, 1411 lpServicesReturned, 1412 lpResumeHandle, 1413 (LPWSTR)pszGroupName); 1414 } 1415 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1416 { 1417 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1418 } 1419 RpcEndExcept; 1420 1421 if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) 1422 { 1423 if (InfoLevel == SC_ENUM_PROCESS_INFO) 1424 { 1425 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) 1426 { 1427 if (lpStatusPtr->lpServiceName) 1428 lpStatusPtr->lpServiceName = 1429 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); 1430 1431 if (lpStatusPtr->lpDisplayName) 1432 lpStatusPtr->lpDisplayName = 1433 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); 1434 1435 lpStatusPtr++; 1436 } 1437 } 1438 } 1439 1440 if (dwError != ERROR_SUCCESS) 1441 { 1442 TRACE("REnumServicesStatusExW() failed (Error %lu)\n", dwError); 1443 SetLastError(dwError); 1444 return FALSE; 1445 } 1446 1447 TRACE("EnumServicesStatusExW() done\n"); 1448 1449 return TRUE; 1450 } 1451 1452 1453 /********************************************************************** 1454 * GetServiceDisplayNameA 1455 * 1456 * @implemented 1457 */ 1458 BOOL WINAPI 1459 GetServiceDisplayNameA(SC_HANDLE hSCManager, 1460 LPCSTR lpServiceName, 1461 LPSTR lpDisplayName, 1462 LPDWORD lpcchBuffer) 1463 { 1464 DWORD dwError; 1465 LPSTR lpNameBuffer; 1466 CHAR szEmptyName[] = ""; 1467 1468 TRACE("GetServiceDisplayNameA() called\n"); 1469 TRACE("%p %s %p %p\n", hSCManager, 1470 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer); 1471 1472 if (!hSCManager) 1473 { 1474 SetLastError(ERROR_INVALID_HANDLE); 1475 return FALSE; 1476 } 1477 1478 if (!lpDisplayName || *lpcchBuffer < sizeof(CHAR)) 1479 { 1480 lpNameBuffer = szEmptyName; 1481 *lpcchBuffer = sizeof(CHAR); 1482 } 1483 else 1484 { 1485 lpNameBuffer = lpDisplayName; 1486 } 1487 1488 RpcTryExcept 1489 { 1490 dwError = RGetServiceDisplayNameA((SC_RPC_HANDLE)hSCManager, 1491 lpServiceName, 1492 lpNameBuffer, 1493 lpcchBuffer); 1494 } 1495 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1496 { 1497 /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */ 1498 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1499 } 1500 RpcEndExcept; 1501 1502 if (dwError != ERROR_SUCCESS) 1503 { 1504 TRACE("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError); 1505 SetLastError(dwError); 1506 return FALSE; 1507 } 1508 1509 return TRUE; 1510 } 1511 1512 1513 /********************************************************************** 1514 * GetServiceDisplayNameW 1515 * 1516 * @implemented 1517 */ 1518 BOOL WINAPI 1519 GetServiceDisplayNameW(SC_HANDLE hSCManager, 1520 LPCWSTR lpServiceName, 1521 LPWSTR lpDisplayName, 1522 LPDWORD lpcchBuffer) 1523 { 1524 DWORD dwError; 1525 LPWSTR lpNameBuffer; 1526 WCHAR szEmptyName[] = L""; 1527 1528 TRACE("GetServiceDisplayNameW() called\n"); 1529 1530 if (!hSCManager) 1531 { 1532 SetLastError(ERROR_INVALID_HANDLE); 1533 return FALSE; 1534 } 1535 1536 if (!lpDisplayName || *lpcchBuffer < sizeof(WCHAR)) 1537 { 1538 lpNameBuffer = szEmptyName; 1539 *lpcchBuffer = sizeof(WCHAR); 1540 } 1541 else 1542 { 1543 lpNameBuffer = lpDisplayName; 1544 } 1545 1546 RpcTryExcept 1547 { 1548 dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager, 1549 lpServiceName, 1550 lpNameBuffer, 1551 lpcchBuffer); 1552 } 1553 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1554 { 1555 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1556 } 1557 RpcEndExcept; 1558 1559 if (dwError != ERROR_SUCCESS) 1560 { 1561 TRACE("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError); 1562 SetLastError(dwError); 1563 return FALSE; 1564 } 1565 1566 return TRUE; 1567 } 1568 1569 1570 /********************************************************************** 1571 * GetServiceKeyNameA 1572 * 1573 * @implemented 1574 */ 1575 BOOL WINAPI 1576 GetServiceKeyNameA(SC_HANDLE hSCManager, 1577 LPCSTR lpDisplayName, 1578 LPSTR lpServiceName, 1579 LPDWORD lpcchBuffer) 1580 { 1581 DWORD dwError; 1582 LPSTR lpNameBuffer; 1583 CHAR szEmptyName[] = ""; 1584 1585 TRACE("GetServiceKeyNameA() called\n"); 1586 1587 if (!hSCManager) 1588 { 1589 SetLastError(ERROR_INVALID_HANDLE); 1590 return FALSE; 1591 } 1592 1593 if (!lpServiceName || *lpcchBuffer < sizeof(CHAR)) 1594 { 1595 lpNameBuffer = szEmptyName; 1596 *lpcchBuffer = sizeof(CHAR); 1597 } 1598 else 1599 { 1600 lpNameBuffer = lpServiceName; 1601 } 1602 1603 RpcTryExcept 1604 { 1605 dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager, 1606 lpDisplayName, 1607 lpNameBuffer, 1608 lpcchBuffer); 1609 } 1610 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1611 { 1612 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1613 } 1614 RpcEndExcept; 1615 1616 if (dwError != ERROR_SUCCESS) 1617 { 1618 TRACE("RGetServiceKeyNameA() failed (Error %lu)\n", dwError); 1619 SetLastError(dwError); 1620 return FALSE; 1621 } 1622 1623 return TRUE; 1624 } 1625 1626 1627 /********************************************************************** 1628 * GetServiceKeyNameW 1629 * 1630 * @implemented 1631 */ 1632 BOOL WINAPI 1633 GetServiceKeyNameW(SC_HANDLE hSCManager, 1634 LPCWSTR lpDisplayName, 1635 LPWSTR lpServiceName, 1636 LPDWORD lpcchBuffer) 1637 { 1638 DWORD dwError; 1639 LPWSTR lpNameBuffer; 1640 WCHAR szEmptyName[] = L""; 1641 1642 TRACE("GetServiceKeyNameW() called\n"); 1643 1644 if (!hSCManager) 1645 { 1646 SetLastError(ERROR_INVALID_HANDLE); 1647 return FALSE; 1648 } 1649 1650 if (!lpServiceName || *lpcchBuffer < sizeof(WCHAR)) 1651 { 1652 lpNameBuffer = szEmptyName; 1653 *lpcchBuffer = sizeof(WCHAR); 1654 } 1655 else 1656 { 1657 lpNameBuffer = lpServiceName; 1658 } 1659 1660 RpcTryExcept 1661 { 1662 dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager, 1663 lpDisplayName, 1664 lpNameBuffer, 1665 lpcchBuffer); 1666 } 1667 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1668 { 1669 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1670 } 1671 RpcEndExcept; 1672 1673 if (dwError != ERROR_SUCCESS) 1674 { 1675 TRACE("RGetServiceKeyNameW() failed (Error %lu)\n", dwError); 1676 SetLastError(dwError); 1677 return FALSE; 1678 } 1679 1680 return TRUE; 1681 } 1682 1683 1684 /********************************************************************** 1685 * I_ScGetCurrentGroupStateW 1686 * 1687 * @implemented 1688 */ 1689 DWORD WINAPI 1690 I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager, 1691 LPWSTR pszGroupName, 1692 LPDWORD pdwGroupState) 1693 { 1694 DWORD dwError; 1695 1696 TRACE("I_ScGetCurrentGroupStateW() called\n"); 1697 1698 RpcTryExcept 1699 { 1700 dwError = RI_ScGetCurrentGroupStateW((SC_RPC_HANDLE)hSCManager, 1701 pszGroupName, 1702 pdwGroupState); 1703 } 1704 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1705 { 1706 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1707 } 1708 RpcEndExcept 1709 1710 if (dwError != ERROR_SUCCESS) 1711 { 1712 TRACE("RI_ScGetCurrentGroupStateW() failed (Error %lu)\n", dwError); 1713 SetLastError(dwError); 1714 } 1715 1716 return dwError; 1717 } 1718 1719 1720 /********************************************************************** 1721 * LockServiceDatabase 1722 * 1723 * @implemented 1724 */ 1725 SC_LOCK WINAPI 1726 LockServiceDatabase(SC_HANDLE hSCManager) 1727 { 1728 SC_LOCK hLock; 1729 DWORD dwError; 1730 1731 TRACE("LockServiceDatabase(%x)\n", hSCManager); 1732 1733 RpcTryExcept 1734 { 1735 /* Call to services.exe using RPC */ 1736 dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager, 1737 (SC_RPC_LOCK *)&hLock); 1738 } 1739 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1740 { 1741 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1742 } 1743 RpcEndExcept; 1744 1745 if (dwError != ERROR_SUCCESS) 1746 { 1747 TRACE("RLockServiceDatabase() failed (Error %lu)\n", dwError); 1748 SetLastError(dwError); 1749 return NULL; 1750 } 1751 1752 TRACE("hLock = %p\n", hLock); 1753 1754 return hLock; 1755 } 1756 1757 1758 static VOID 1759 WaitForSCManager(VOID) 1760 { 1761 HANDLE hEvent; 1762 1763 TRACE("WaitForSCManager() called\n"); 1764 1765 /* Try to open the existing event */ 1766 hEvent = OpenEventW(SYNCHRONIZE, FALSE, SCM_START_EVENT); 1767 if (hEvent == NULL) 1768 { 1769 if (GetLastError() != ERROR_FILE_NOT_FOUND) return; 1770 1771 /* Try to create a new event */ 1772 hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT); 1773 if (hEvent == NULL) return; 1774 } 1775 1776 /* Wait for 3 minutes */ 1777 WaitForSingleObject(hEvent, 180000); 1778 CloseHandle(hEvent); 1779 1780 TRACE("ScmWaitForSCManager() done\n"); 1781 } 1782 1783 1784 /********************************************************************** 1785 * OpenSCManagerA 1786 * 1787 * @implemented 1788 */ 1789 SC_HANDLE WINAPI 1790 OpenSCManagerA(LPCSTR lpMachineName, 1791 LPCSTR lpDatabaseName, 1792 DWORD dwDesiredAccess) 1793 { 1794 SC_HANDLE hScm = NULL; 1795 DWORD dwError; 1796 1797 TRACE("OpenSCManagerA(%s, %s, %lx)\n", 1798 lpMachineName, lpDatabaseName, dwDesiredAccess); 1799 1800 WaitForSCManager(); 1801 1802 RpcTryExcept 1803 { 1804 /* Call to services.exe using RPC */ 1805 dwError = ROpenSCManagerA((LPSTR)lpMachineName, 1806 (LPSTR)lpDatabaseName, 1807 dwDesiredAccess, 1808 (SC_RPC_HANDLE *)&hScm); 1809 } 1810 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1811 { 1812 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1813 } 1814 RpcEndExcept; 1815 1816 if (dwError != ERROR_SUCCESS) 1817 { 1818 TRACE("ROpenSCManagerA() failed (Error %lu)\n", dwError); 1819 SetLastError(dwError); 1820 return NULL; 1821 } 1822 1823 TRACE("hScm = %p\n", hScm); 1824 1825 return hScm; 1826 } 1827 1828 1829 /********************************************************************** 1830 * OpenSCManagerW 1831 * 1832 * @implemented 1833 */ 1834 SC_HANDLE WINAPI 1835 OpenSCManagerW(LPCWSTR lpMachineName, 1836 LPCWSTR lpDatabaseName, 1837 DWORD dwDesiredAccess) 1838 { 1839 SC_HANDLE hScm = NULL; 1840 DWORD dwError; 1841 1842 TRACE("OpenSCManagerW(%S, %S, %lx)\n", 1843 lpMachineName, lpDatabaseName, dwDesiredAccess); 1844 1845 WaitForSCManager(); 1846 1847 RpcTryExcept 1848 { 1849 /* Call to services.exe using RPC */ 1850 dwError = ROpenSCManagerW((LPWSTR)lpMachineName, 1851 (LPWSTR)lpDatabaseName, 1852 dwDesiredAccess, 1853 (SC_RPC_HANDLE *)&hScm); 1854 } 1855 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1856 { 1857 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1858 } 1859 RpcEndExcept; 1860 1861 if (dwError != ERROR_SUCCESS) 1862 { 1863 TRACE("ROpenSCManagerW() failed (Error %lu)\n", dwError); 1864 SetLastError(dwError); 1865 return NULL; 1866 } 1867 1868 TRACE("hScm = %p\n", hScm); 1869 1870 return hScm; 1871 } 1872 1873 1874 /********************************************************************** 1875 * OpenServiceA 1876 * 1877 * @implemented 1878 */ 1879 SC_HANDLE WINAPI 1880 OpenServiceA(SC_HANDLE hSCManager, 1881 LPCSTR lpServiceName, 1882 DWORD dwDesiredAccess) 1883 { 1884 SC_HANDLE hService = NULL; 1885 DWORD dwError; 1886 1887 TRACE("OpenServiceA(%p, %s, %lx)\n", 1888 hSCManager, lpServiceName, dwDesiredAccess); 1889 1890 if (!hSCManager) 1891 { 1892 SetLastError(ERROR_INVALID_HANDLE); 1893 return NULL; 1894 } 1895 1896 RpcTryExcept 1897 { 1898 /* Call to services.exe using RPC */ 1899 dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager, 1900 (LPSTR)lpServiceName, 1901 dwDesiredAccess, 1902 (SC_RPC_HANDLE *)&hService); 1903 } 1904 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1905 { 1906 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1907 } 1908 RpcEndExcept; 1909 1910 SetLastError(dwError); 1911 if (dwError != ERROR_SUCCESS) 1912 { 1913 TRACE("ROpenServiceA() failed (Error %lu)\n", dwError); 1914 return NULL; 1915 } 1916 1917 TRACE("hService = %p\n", hService); 1918 1919 return hService; 1920 } 1921 1922 1923 /********************************************************************** 1924 * OpenServiceW 1925 * 1926 * @implemented 1927 */ 1928 SC_HANDLE WINAPI 1929 OpenServiceW(SC_HANDLE hSCManager, 1930 LPCWSTR lpServiceName, 1931 DWORD dwDesiredAccess) 1932 { 1933 SC_HANDLE hService = NULL; 1934 DWORD dwError; 1935 1936 TRACE("OpenServiceW(%p, %S, %lx)\n", 1937 hSCManager, lpServiceName, dwDesiredAccess); 1938 1939 if (!hSCManager) 1940 { 1941 SetLastError(ERROR_INVALID_HANDLE); 1942 return NULL; 1943 } 1944 1945 RpcTryExcept 1946 { 1947 /* Call to services.exe using RPC */ 1948 dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager, 1949 (LPWSTR)lpServiceName, 1950 dwDesiredAccess, 1951 (SC_RPC_HANDLE *)&hService); 1952 } 1953 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 1954 { 1955 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 1956 } 1957 RpcEndExcept; 1958 1959 SetLastError(dwError); 1960 if (dwError != ERROR_SUCCESS) 1961 { 1962 TRACE("ROpenServiceW() failed (Error %lu)\n", dwError); 1963 return NULL; 1964 } 1965 1966 TRACE("hService = %p\n", hService); 1967 1968 return hService; 1969 } 1970 1971 1972 /********************************************************************** 1973 * QueryServiceConfigA 1974 * 1975 * @implemented 1976 */ 1977 BOOL WINAPI 1978 QueryServiceConfigA(SC_HANDLE hService, 1979 LPQUERY_SERVICE_CONFIGA lpServiceConfig, 1980 DWORD cbBufSize, 1981 LPDWORD pcbBytesNeeded) 1982 { 1983 QUERY_SERVICE_CONFIGA ServiceConfig; 1984 LPQUERY_SERVICE_CONFIGA lpConfigPtr; 1985 DWORD dwBufferSize; 1986 DWORD dwError; 1987 1988 TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n", 1989 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded); 1990 1991 if (lpServiceConfig == NULL || 1992 cbBufSize < sizeof(QUERY_SERVICE_CONFIGA)) 1993 { 1994 lpConfigPtr = &ServiceConfig; 1995 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGA); 1996 } 1997 else 1998 { 1999 lpConfigPtr = lpServiceConfig; 2000 dwBufferSize = cbBufSize; 2001 } 2002 2003 RpcTryExcept 2004 { 2005 /* Call to services.exe using RPC */ 2006 dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService, 2007 (LPBYTE)lpConfigPtr, 2008 dwBufferSize, 2009 pcbBytesNeeded); 2010 } 2011 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2012 { 2013 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2014 } 2015 RpcEndExcept; 2016 2017 if (dwError != ERROR_SUCCESS) 2018 { 2019 TRACE("RQueryServiceConfigA() failed (Error %lu)\n", dwError); 2020 SetLastError(dwError); 2021 return FALSE; 2022 } 2023 2024 /* Adjust the pointers */ 2025 if (lpConfigPtr->lpBinaryPathName) 2026 lpConfigPtr->lpBinaryPathName = 2027 (LPSTR)((ULONG_PTR)lpConfigPtr + 2028 (ULONG_PTR)lpConfigPtr->lpBinaryPathName); 2029 2030 if (lpConfigPtr->lpLoadOrderGroup) 2031 lpConfigPtr->lpLoadOrderGroup = 2032 (LPSTR)((ULONG_PTR)lpConfigPtr + 2033 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup); 2034 2035 if (lpConfigPtr->lpDependencies) 2036 lpConfigPtr->lpDependencies = 2037 (LPSTR)((ULONG_PTR)lpConfigPtr + 2038 (ULONG_PTR)lpConfigPtr->lpDependencies); 2039 2040 if (lpConfigPtr->lpServiceStartName) 2041 lpConfigPtr->lpServiceStartName = 2042 (LPSTR)((ULONG_PTR)lpConfigPtr + 2043 (ULONG_PTR)lpConfigPtr->lpServiceStartName); 2044 2045 if (lpConfigPtr->lpDisplayName) 2046 lpConfigPtr->lpDisplayName = 2047 (LPSTR)((ULONG_PTR)lpConfigPtr + 2048 (ULONG_PTR)lpConfigPtr->lpDisplayName); 2049 2050 TRACE("QueryServiceConfigA() done\n"); 2051 2052 return TRUE; 2053 } 2054 2055 2056 /********************************************************************** 2057 * QueryServiceConfigW 2058 * 2059 * @implemented 2060 */ 2061 BOOL WINAPI 2062 QueryServiceConfigW(SC_HANDLE hService, 2063 LPQUERY_SERVICE_CONFIGW lpServiceConfig, 2064 DWORD cbBufSize, 2065 LPDWORD pcbBytesNeeded) 2066 { 2067 QUERY_SERVICE_CONFIGW ServiceConfig; 2068 LPQUERY_SERVICE_CONFIGW lpConfigPtr; 2069 DWORD dwBufferSize; 2070 DWORD dwError; 2071 2072 TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n", 2073 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded); 2074 2075 if (lpServiceConfig == NULL || 2076 cbBufSize < sizeof(QUERY_SERVICE_CONFIGW)) 2077 { 2078 lpConfigPtr = &ServiceConfig; 2079 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGW); 2080 } 2081 else 2082 { 2083 lpConfigPtr = lpServiceConfig; 2084 dwBufferSize = cbBufSize; 2085 } 2086 2087 RpcTryExcept 2088 { 2089 /* Call to services.exe using RPC */ 2090 dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService, 2091 (LPBYTE)lpConfigPtr, 2092 dwBufferSize, 2093 pcbBytesNeeded); 2094 } 2095 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2096 { 2097 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2098 } 2099 RpcEndExcept; 2100 2101 if (dwError != ERROR_SUCCESS) 2102 { 2103 TRACE("RQueryServiceConfigW() failed (Error %lu)\n", dwError); 2104 SetLastError(dwError); 2105 return FALSE; 2106 } 2107 2108 /* Adjust the pointers */ 2109 if (lpConfigPtr->lpBinaryPathName) 2110 lpConfigPtr->lpBinaryPathName = 2111 (LPWSTR)((ULONG_PTR)lpConfigPtr + 2112 (ULONG_PTR)lpConfigPtr->lpBinaryPathName); 2113 2114 if (lpConfigPtr->lpLoadOrderGroup) 2115 lpConfigPtr->lpLoadOrderGroup = 2116 (LPWSTR)((ULONG_PTR)lpConfigPtr + 2117 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup); 2118 2119 if (lpConfigPtr->lpDependencies) 2120 lpConfigPtr->lpDependencies = 2121 (LPWSTR)((ULONG_PTR)lpConfigPtr + 2122 (ULONG_PTR)lpConfigPtr->lpDependencies); 2123 2124 if (lpConfigPtr->lpServiceStartName) 2125 lpConfigPtr->lpServiceStartName = 2126 (LPWSTR)((ULONG_PTR)lpConfigPtr + 2127 (ULONG_PTR)lpConfigPtr->lpServiceStartName); 2128 2129 if (lpConfigPtr->lpDisplayName) 2130 lpConfigPtr->lpDisplayName = 2131 (LPWSTR)((ULONG_PTR)lpConfigPtr + 2132 (ULONG_PTR)lpConfigPtr->lpDisplayName); 2133 2134 TRACE("QueryServiceConfigW() done\n"); 2135 2136 return TRUE; 2137 } 2138 2139 2140 /********************************************************************** 2141 * QueryServiceConfig2A 2142 * 2143 * @implemented 2144 */ 2145 BOOL WINAPI 2146 QueryServiceConfig2A(SC_HANDLE hService, 2147 DWORD dwInfoLevel, 2148 LPBYTE lpBuffer, 2149 DWORD cbBufSize, 2150 LPDWORD pcbBytesNeeded) 2151 { 2152 SERVICE_DESCRIPTIONA ServiceDescription; 2153 SERVICE_FAILURE_ACTIONSA ServiceFailureActions; 2154 LPBYTE lpTempBuffer; 2155 BOOL bUseTempBuffer = FALSE; 2156 DWORD dwBufferSize; 2157 DWORD dwError; 2158 2159 TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n", 2160 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); 2161 2162 lpTempBuffer = lpBuffer; 2163 dwBufferSize = cbBufSize; 2164 2165 switch (dwInfoLevel) 2166 { 2167 case SERVICE_CONFIG_DESCRIPTION: 2168 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA))) 2169 { 2170 lpTempBuffer = (LPBYTE)&ServiceDescription; 2171 dwBufferSize = sizeof(SERVICE_DESCRIPTIONA); 2172 bUseTempBuffer = TRUE; 2173 } 2174 break; 2175 2176 case SERVICE_CONFIG_FAILURE_ACTIONS: 2177 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA))) 2178 { 2179 lpTempBuffer = (LPBYTE)&ServiceFailureActions; 2180 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA); 2181 bUseTempBuffer = TRUE; 2182 } 2183 break; 2184 2185 default: 2186 WARN("Unknown info level 0x%lx\n", dwInfoLevel); 2187 SetLastError(ERROR_INVALID_LEVEL); 2188 return FALSE; 2189 } 2190 2191 RpcTryExcept 2192 { 2193 /* Call to services.exe using RPC */ 2194 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService, 2195 dwInfoLevel, 2196 lpTempBuffer, 2197 dwBufferSize, 2198 pcbBytesNeeded); 2199 } 2200 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2201 { 2202 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2203 } 2204 RpcEndExcept; 2205 2206 if (dwError != ERROR_SUCCESS) 2207 { 2208 TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError); 2209 SetLastError(dwError); 2210 return FALSE; 2211 } 2212 2213 if (bUseTempBuffer != FALSE) 2214 { 2215 TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n"); 2216 *pcbBytesNeeded = dwBufferSize; 2217 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2218 return FALSE; 2219 } 2220 2221 switch (dwInfoLevel) 2222 { 2223 case SERVICE_CONFIG_DESCRIPTION: 2224 { 2225 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer; 2226 2227 if (lpPtr->lpDescription != NULL) 2228 lpPtr->lpDescription = 2229 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription); 2230 } 2231 break; 2232 2233 case SERVICE_CONFIG_FAILURE_ACTIONS: 2234 { 2235 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer; 2236 2237 if (lpPtr->lpRebootMsg != NULL) 2238 lpPtr->lpRebootMsg = 2239 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg); 2240 2241 if (lpPtr->lpCommand != NULL) 2242 lpPtr->lpCommand = 2243 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand); 2244 2245 if (lpPtr->lpsaActions != NULL) 2246 lpPtr->lpsaActions = 2247 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions); 2248 } 2249 break; 2250 } 2251 2252 TRACE("QueryServiceConfig2A() done\n"); 2253 2254 return TRUE; 2255 } 2256 2257 2258 /********************************************************************** 2259 * QueryServiceConfig2W 2260 * 2261 * @implemented 2262 */ 2263 BOOL WINAPI 2264 QueryServiceConfig2W(SC_HANDLE hService, 2265 DWORD dwInfoLevel, 2266 LPBYTE lpBuffer, 2267 DWORD cbBufSize, 2268 LPDWORD pcbBytesNeeded) 2269 { 2270 SERVICE_DESCRIPTIONW ServiceDescription; 2271 SERVICE_FAILURE_ACTIONSW ServiceFailureActions; 2272 LPBYTE lpTempBuffer; 2273 BOOL bUseTempBuffer = FALSE; 2274 DWORD dwBufferSize; 2275 DWORD dwError; 2276 2277 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n", 2278 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); 2279 2280 lpTempBuffer = lpBuffer; 2281 dwBufferSize = cbBufSize; 2282 2283 switch (dwInfoLevel) 2284 { 2285 case SERVICE_CONFIG_DESCRIPTION: 2286 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW))) 2287 { 2288 lpTempBuffer = (LPBYTE)&ServiceDescription; 2289 dwBufferSize = sizeof(SERVICE_DESCRIPTIONW); 2290 bUseTempBuffer = TRUE; 2291 } 2292 break; 2293 2294 case SERVICE_CONFIG_FAILURE_ACTIONS: 2295 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW))) 2296 { 2297 lpTempBuffer = (LPBYTE)&ServiceFailureActions; 2298 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW); 2299 bUseTempBuffer = TRUE; 2300 } 2301 break; 2302 2303 default: 2304 WARN("Unknown info level 0x%lx\n", dwInfoLevel); 2305 SetLastError(ERROR_INVALID_LEVEL); 2306 return FALSE; 2307 } 2308 2309 RpcTryExcept 2310 { 2311 /* Call to services.exe using RPC */ 2312 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService, 2313 dwInfoLevel, 2314 lpTempBuffer, 2315 dwBufferSize, 2316 pcbBytesNeeded); 2317 } 2318 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2319 { 2320 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2321 } 2322 RpcEndExcept; 2323 2324 if (dwError != ERROR_SUCCESS) 2325 { 2326 TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError); 2327 SetLastError(dwError); 2328 return FALSE; 2329 } 2330 2331 if (bUseTempBuffer != FALSE) 2332 { 2333 TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n"); 2334 *pcbBytesNeeded = dwBufferSize; 2335 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2336 return FALSE; 2337 } 2338 2339 switch (dwInfoLevel) 2340 { 2341 case SERVICE_CONFIG_DESCRIPTION: 2342 { 2343 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer; 2344 2345 if (lpPtr->lpDescription != NULL) 2346 lpPtr->lpDescription = 2347 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription); 2348 } 2349 break; 2350 2351 case SERVICE_CONFIG_FAILURE_ACTIONS: 2352 { 2353 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer; 2354 2355 if (lpPtr->lpRebootMsg != NULL) 2356 lpPtr->lpRebootMsg = 2357 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg); 2358 2359 if (lpPtr->lpCommand != NULL) 2360 lpPtr->lpCommand = 2361 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand); 2362 2363 if (lpPtr->lpsaActions != NULL) 2364 lpPtr->lpsaActions = 2365 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions); 2366 } 2367 break; 2368 } 2369 2370 TRACE("QueryServiceConfig2W() done\n"); 2371 2372 return TRUE; 2373 } 2374 2375 2376 /********************************************************************** 2377 * QueryServiceLockStatusA 2378 * 2379 * @implemented 2380 */ 2381 BOOL WINAPI 2382 QueryServiceLockStatusA(SC_HANDLE hSCManager, 2383 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, 2384 DWORD cbBufSize, 2385 LPDWORD pcbBytesNeeded) 2386 { 2387 QUERY_SERVICE_LOCK_STATUSA LockStatus; 2388 LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr; 2389 DWORD dwBufferSize; 2390 DWORD dwError; 2391 2392 TRACE("QueryServiceLockStatusA() called\n"); 2393 2394 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA)) 2395 { 2396 lpStatusPtr = &LockStatus; 2397 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA); 2398 } 2399 else 2400 { 2401 lpStatusPtr = lpLockStatus; 2402 dwBufferSize = cbBufSize; 2403 } 2404 2405 RpcTryExcept 2406 { 2407 /* Call to services.exe using RPC */ 2408 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager, 2409 (LPBYTE)lpStatusPtr, 2410 dwBufferSize, 2411 pcbBytesNeeded); 2412 } 2413 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2414 { 2415 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2416 } 2417 RpcEndExcept; 2418 2419 if (dwError != ERROR_SUCCESS) 2420 { 2421 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError); 2422 SetLastError(dwError); 2423 return FALSE; 2424 } 2425 2426 if (lpStatusPtr->lpLockOwner != NULL) 2427 { 2428 lpStatusPtr->lpLockOwner = 2429 (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner); 2430 } 2431 2432 TRACE("QueryServiceLockStatusA() done\n"); 2433 2434 return TRUE; 2435 } 2436 2437 2438 /********************************************************************** 2439 * QueryServiceLockStatusW 2440 * 2441 * @implemented 2442 */ 2443 BOOL WINAPI 2444 QueryServiceLockStatusW(SC_HANDLE hSCManager, 2445 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, 2446 DWORD cbBufSize, 2447 LPDWORD pcbBytesNeeded) 2448 { 2449 QUERY_SERVICE_LOCK_STATUSW LockStatus; 2450 LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr; 2451 DWORD dwBufferSize; 2452 DWORD dwError; 2453 2454 TRACE("QueryServiceLockStatusW() called\n"); 2455 2456 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW)) 2457 { 2458 lpStatusPtr = &LockStatus; 2459 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW); 2460 } 2461 else 2462 { 2463 lpStatusPtr = lpLockStatus; 2464 dwBufferSize = cbBufSize; 2465 } 2466 2467 RpcTryExcept 2468 { 2469 /* Call to services.exe using RPC */ 2470 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager, 2471 (LPBYTE)lpStatusPtr, 2472 dwBufferSize, 2473 pcbBytesNeeded); 2474 } 2475 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2476 { 2477 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2478 } 2479 RpcEndExcept; 2480 2481 if (dwError != ERROR_SUCCESS) 2482 { 2483 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError); 2484 SetLastError(dwError); 2485 return FALSE; 2486 } 2487 2488 if (lpStatusPtr->lpLockOwner != NULL) 2489 { 2490 lpStatusPtr->lpLockOwner = 2491 (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner); 2492 } 2493 2494 TRACE("QueryServiceLockStatusW() done\n"); 2495 2496 return TRUE; 2497 } 2498 2499 2500 /********************************************************************** 2501 * QueryServiceObjectSecurity 2502 * 2503 * @implemented 2504 */ 2505 BOOL WINAPI 2506 QueryServiceObjectSecurity(SC_HANDLE hService, 2507 SECURITY_INFORMATION dwSecurityInformation, 2508 PSECURITY_DESCRIPTOR lpSecurityDescriptor, 2509 DWORD cbBufSize, 2510 LPDWORD pcbBytesNeeded) 2511 { 2512 DWORD dwError; 2513 2514 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n", 2515 hService, dwSecurityInformation, lpSecurityDescriptor); 2516 2517 RpcTryExcept 2518 { 2519 /* Call to services.exe using RPC */ 2520 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService, 2521 dwSecurityInformation, 2522 (LPBYTE)lpSecurityDescriptor, 2523 cbBufSize, 2524 pcbBytesNeeded); 2525 } 2526 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2527 { 2528 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2529 } 2530 RpcEndExcept; 2531 2532 if (dwError != ERROR_SUCCESS) 2533 { 2534 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError); 2535 SetLastError(dwError); 2536 return FALSE; 2537 } 2538 2539 return TRUE; 2540 } 2541 2542 /********************************************************************** 2543 * SetServiceObjectSecurity 2544 * 2545 * @implemented 2546 */ 2547 BOOL WINAPI 2548 SetServiceObjectSecurity(SC_HANDLE hService, 2549 SECURITY_INFORMATION dwSecurityInformation, 2550 PSECURITY_DESCRIPTOR lpSecurityDescriptor) 2551 { 2552 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL; 2553 ULONG Length; 2554 NTSTATUS Status; 2555 DWORD dwError; 2556 2557 Length = 0; 2558 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor, 2559 SelfRelativeSD, 2560 &Length); 2561 if (Status != STATUS_BUFFER_TOO_SMALL) 2562 { 2563 SetLastError(ERROR_INVALID_PARAMETER); 2564 return FALSE; 2565 } 2566 2567 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length); 2568 if (SelfRelativeSD == NULL) 2569 { 2570 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 2571 return FALSE; 2572 } 2573 2574 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor, 2575 SelfRelativeSD, 2576 &Length); 2577 if (!NT_SUCCESS(Status)) 2578 { 2579 HeapFree(GetProcessHeap(), 0, SelfRelativeSD); 2580 SetLastError(RtlNtStatusToDosError(Status)); 2581 return FALSE; 2582 } 2583 2584 RpcTryExcept 2585 { 2586 /* Call to services.exe using RPC */ 2587 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService, 2588 dwSecurityInformation, 2589 (LPBYTE)SelfRelativeSD, 2590 Length); 2591 } 2592 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2593 { 2594 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2595 } 2596 RpcEndExcept; 2597 2598 HeapFree(GetProcessHeap(), 0, SelfRelativeSD); 2599 2600 if (dwError != ERROR_SUCCESS) 2601 { 2602 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError); 2603 SetLastError(dwError); 2604 return FALSE; 2605 } 2606 2607 return TRUE; 2608 } 2609 2610 2611 /********************************************************************** 2612 * QueryServiceStatus 2613 * 2614 * @implemented 2615 */ 2616 BOOL WINAPI 2617 QueryServiceStatus(SC_HANDLE hService, 2618 LPSERVICE_STATUS lpServiceStatus) 2619 { 2620 DWORD dwError; 2621 2622 TRACE("QueryServiceStatus(%p, %p)\n", 2623 hService, lpServiceStatus); 2624 2625 if (!hService) 2626 { 2627 SetLastError(ERROR_INVALID_HANDLE); 2628 return FALSE; 2629 } 2630 2631 RpcTryExcept 2632 { 2633 /* Call to services.exe using RPC */ 2634 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService, 2635 lpServiceStatus); 2636 } 2637 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2638 { 2639 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2640 } 2641 RpcEndExcept; 2642 2643 if (dwError != ERROR_SUCCESS) 2644 { 2645 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError); 2646 SetLastError(dwError); 2647 return FALSE; 2648 } 2649 2650 return TRUE; 2651 } 2652 2653 2654 /********************************************************************** 2655 * QueryServiceStatusEx 2656 * 2657 * @implemented 2658 */ 2659 BOOL WINAPI 2660 QueryServiceStatusEx(SC_HANDLE hService, 2661 SC_STATUS_TYPE InfoLevel, 2662 LPBYTE lpBuffer, 2663 DWORD cbBufSize, 2664 LPDWORD pcbBytesNeeded) 2665 { 2666 DWORD dwError; 2667 2668 TRACE("QueryServiceStatusEx() called\n"); 2669 2670 if (InfoLevel != SC_STATUS_PROCESS_INFO) 2671 { 2672 SetLastError(ERROR_INVALID_LEVEL); 2673 return FALSE; 2674 } 2675 2676 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) 2677 { 2678 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS); 2679 SetLastError(ERROR_INSUFFICIENT_BUFFER); 2680 return FALSE; 2681 } 2682 2683 RpcTryExcept 2684 { 2685 /* Call to services.exe using RPC */ 2686 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService, 2687 InfoLevel, 2688 lpBuffer, 2689 cbBufSize, 2690 pcbBytesNeeded); 2691 } 2692 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2693 { 2694 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2695 } 2696 RpcEndExcept; 2697 2698 if (dwError != ERROR_SUCCESS) 2699 { 2700 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError); 2701 SetLastError(dwError); 2702 return FALSE; 2703 } 2704 2705 return TRUE; 2706 } 2707 2708 2709 /********************************************************************** 2710 * StartServiceA 2711 * 2712 * @implemented 2713 */ 2714 BOOL WINAPI 2715 StartServiceA(SC_HANDLE hService, 2716 DWORD dwNumServiceArgs, 2717 LPCSTR *lpServiceArgVectors) 2718 { 2719 DWORD dwError; 2720 2721 RpcTryExcept 2722 { 2723 dwError = RStartServiceA((SC_RPC_HANDLE)hService, 2724 dwNumServiceArgs, 2725 (LPSTRING_PTRSA)lpServiceArgVectors); 2726 } 2727 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2728 { 2729 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2730 } 2731 RpcEndExcept; 2732 2733 if (dwError != ERROR_SUCCESS) 2734 { 2735 ERR("RStartServiceA() failed (Error %lu)\n", dwError); 2736 SetLastError(dwError); 2737 return FALSE; 2738 } 2739 2740 return TRUE; 2741 } 2742 2743 2744 /********************************************************************** 2745 * StartServiceW 2746 * 2747 * @implemented 2748 */ 2749 BOOL WINAPI 2750 StartServiceW(SC_HANDLE hService, 2751 DWORD dwNumServiceArgs, 2752 LPCWSTR *lpServiceArgVectors) 2753 { 2754 DWORD dwError; 2755 2756 RpcTryExcept 2757 { 2758 dwError = RStartServiceW((SC_RPC_HANDLE)hService, 2759 dwNumServiceArgs, 2760 (LPSTRING_PTRSW)lpServiceArgVectors); 2761 } 2762 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2763 { 2764 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2765 } 2766 RpcEndExcept; 2767 2768 if (dwError != ERROR_SUCCESS) 2769 { 2770 ERR("RStartServiceW() failed (Error %lu)\n", dwError); 2771 SetLastError(dwError); 2772 return FALSE; 2773 } 2774 2775 return TRUE; 2776 } 2777 2778 2779 /********************************************************************** 2780 * UnlockServiceDatabase 2781 * 2782 * @implemented 2783 */ 2784 BOOL WINAPI 2785 UnlockServiceDatabase(SC_LOCK ScLock) 2786 { 2787 DWORD dwError; 2788 2789 TRACE("UnlockServiceDatabase(%x)\n", ScLock); 2790 2791 RpcTryExcept 2792 { 2793 /* Call to services.exe using RPC */ 2794 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock); 2795 } 2796 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2797 { 2798 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2799 } 2800 RpcEndExcept; 2801 2802 if (dwError == ERROR_INVALID_HANDLE) 2803 dwError = ERROR_INVALID_SERVICE_LOCK; 2804 2805 if (dwError != ERROR_SUCCESS) 2806 { 2807 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError); 2808 SetLastError(dwError); 2809 return FALSE; 2810 } 2811 2812 return TRUE; 2813 } 2814 2815 2816 /********************************************************************** 2817 * NotifyBootConfigStatus 2818 * 2819 * @implemented 2820 */ 2821 BOOL WINAPI 2822 NotifyBootConfigStatus(BOOL BootAcceptable) 2823 { 2824 DWORD dwError; 2825 2826 TRACE("NotifyBootConfigStatus()\n"); 2827 2828 RpcTryExcept 2829 { 2830 /* Call to services.exe using RPC */ 2831 dwError = RNotifyBootConfigStatus(NULL, 2832 BootAcceptable); 2833 } 2834 RpcExcept(EXCEPTION_EXECUTE_HANDLER) 2835 { 2836 dwError = ScmRpcStatusToWinError(RpcExceptionCode()); 2837 } 2838 RpcEndExcept; 2839 2840 if (dwError != ERROR_SUCCESS) 2841 { 2842 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError); 2843 SetLastError(dwError); 2844 return FALSE; 2845 } 2846 2847 return TRUE; 2848 } 2849 2850 /* EOF */ 2851