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