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