Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrpcserver.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Service Control Manager 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: base/system/services/rpcserver.c 00005 * PURPOSE: RPC server interface for the advapi32 calls 00006 * COPYRIGHT: Copyright 2005-2006 Eric Kohl 00007 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org> 00008 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org> 00009 */ 00010 00011 /* INCLUDES ****************************************************************/ 00012 00013 #include "services.h" 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* GLOBALS *****************************************************************/ 00019 00020 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */ 00021 #define SERVICE_TAG 0x63765368 /* 'hSvc' */ 00022 00023 typedef struct _SCMGR_HANDLE 00024 { 00025 DWORD Tag; 00026 DWORD DesiredAccess; 00027 } SCMGR_HANDLE; 00028 00029 00030 typedef struct _MANAGER_HANDLE 00031 { 00032 SCMGR_HANDLE Handle; 00033 WCHAR DatabaseName[1]; 00034 } MANAGER_HANDLE, *PMANAGER_HANDLE; 00035 00036 00037 typedef struct _SERVICE_HANDLE 00038 { 00039 SCMGR_HANDLE Handle; 00040 PSERVICE ServiceEntry; 00041 } SERVICE_HANDLE, *PSERVICE_HANDLE; 00042 00043 00044 #define SC_MANAGER_READ \ 00045 (STANDARD_RIGHTS_READ | \ 00046 SC_MANAGER_QUERY_LOCK_STATUS | \ 00047 SC_MANAGER_ENUMERATE_SERVICE) 00048 00049 #define SC_MANAGER_WRITE \ 00050 (STANDARD_RIGHTS_WRITE | \ 00051 SC_MANAGER_MODIFY_BOOT_CONFIG | \ 00052 SC_MANAGER_CREATE_SERVICE) 00053 00054 #define SC_MANAGER_EXECUTE \ 00055 (STANDARD_RIGHTS_EXECUTE | \ 00056 SC_MANAGER_LOCK | \ 00057 SC_MANAGER_ENUMERATE_SERVICE | \ 00058 SC_MANAGER_CONNECT | \ 00059 SC_MANAGER_CREATE_SERVICE) 00060 00061 00062 #define SERVICE_READ \ 00063 (STANDARD_RIGHTS_READ | \ 00064 SERVICE_INTERROGATE | \ 00065 SERVICE_ENUMERATE_DEPENDENTS | \ 00066 SERVICE_QUERY_STATUS | \ 00067 SERVICE_QUERY_CONFIG) 00068 00069 #define SERVICE_WRITE \ 00070 (STANDARD_RIGHTS_WRITE | \ 00071 SERVICE_CHANGE_CONFIG) 00072 00073 #define SERVICE_EXECUTE \ 00074 (STANDARD_RIGHTS_EXECUTE | \ 00075 SERVICE_USER_DEFINED_CONTROL | \ 00076 SERVICE_PAUSE_CONTINUE | \ 00077 SERVICE_STOP | \ 00078 SERVICE_START) 00079 00080 #define TAG_ARRAY_SIZE 32 00081 00082 /* VARIABLES ***************************************************************/ 00083 00084 static GENERIC_MAPPING 00085 ScmManagerMapping = {SC_MANAGER_READ, 00086 SC_MANAGER_WRITE, 00087 SC_MANAGER_EXECUTE, 00088 SC_MANAGER_ALL_ACCESS}; 00089 00090 static GENERIC_MAPPING 00091 ScmServiceMapping = {SERVICE_READ, 00092 SERVICE_WRITE, 00093 SERVICE_EXECUTE, 00094 SERVICE_ALL_ACCESS}; 00095 00096 00097 /* FUNCTIONS ***************************************************************/ 00098 00099 VOID 00100 ScmStartRpcServer(VOID) 00101 { 00102 RPC_STATUS Status; 00103 00104 DPRINT("ScmStartRpcServer() called\n"); 00105 00106 Status = RpcServerUseProtseqEpW(L"ncacn_np", 00107 10, 00108 L"\\pipe\\ntsvcs", 00109 NULL); 00110 if (Status != RPC_S_OK) 00111 { 00112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status); 00113 return; 00114 } 00115 00116 Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec, 00117 NULL, 00118 NULL); 00119 if (Status != RPC_S_OK) 00120 { 00121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); 00122 return; 00123 } 00124 00125 Status = RpcServerListen(1, 20, TRUE); 00126 if (Status != RPC_S_OK) 00127 { 00128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); 00129 return; 00130 } 00131 00132 DPRINT("ScmStartRpcServer() done\n"); 00133 } 00134 00135 00136 static DWORD 00137 ScmCreateManagerHandle(LPWSTR lpDatabaseName, 00138 SC_HANDLE *Handle) 00139 { 00140 PMANAGER_HANDLE Ptr; 00141 00142 if (lpDatabaseName == NULL) 00143 lpDatabaseName = SERVICES_ACTIVE_DATABASEW; 00144 00145 if (_wcsicmp(lpDatabaseName, SERVICES_FAILED_DATABASEW) == 0) 00146 { 00147 DPRINT("Database %S, does not exist\n", lpDatabaseName); 00148 return ERROR_DATABASE_DOES_NOT_EXIST; 00149 } 00150 else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0) 00151 { 00152 DPRINT("Invalid Database name %S.\n", lpDatabaseName); 00153 return ERROR_INVALID_NAME; 00154 } 00155 00156 Ptr = HeapAlloc(GetProcessHeap(), 00157 HEAP_ZERO_MEMORY, 00158 FIELD_OFFSET(MANAGER_HANDLE, DatabaseName[wcslen(lpDatabaseName) + 1])); 00159 if (Ptr == NULL) 00160 return ERROR_NOT_ENOUGH_MEMORY; 00161 00162 Ptr->Handle.Tag = MANAGER_TAG; 00163 00164 wcscpy(Ptr->DatabaseName, lpDatabaseName); 00165 00166 *Handle = (SC_HANDLE)Ptr; 00167 00168 return ERROR_SUCCESS; 00169 } 00170 00171 00172 static DWORD 00173 ScmCreateServiceHandle(PSERVICE lpServiceEntry, 00174 SC_HANDLE *Handle) 00175 { 00176 PSERVICE_HANDLE Ptr; 00177 00178 Ptr = HeapAlloc(GetProcessHeap(), 00179 HEAP_ZERO_MEMORY, 00180 sizeof(SERVICE_HANDLE)); 00181 if (Ptr == NULL) 00182 return ERROR_NOT_ENOUGH_MEMORY; 00183 00184 Ptr->Handle.Tag = SERVICE_TAG; 00185 00186 Ptr->ServiceEntry = lpServiceEntry; 00187 00188 *Handle = (SC_HANDLE)Ptr; 00189 00190 return ERROR_SUCCESS; 00191 } 00192 00193 00194 static PMANAGER_HANDLE 00195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle) 00196 { 00197 PMANAGER_HANDLE pManager = NULL; 00198 00199 _SEH2_TRY 00200 { 00201 if (((PMANAGER_HANDLE)Handle)->Handle.Tag == MANAGER_TAG) 00202 pManager = (PMANAGER_HANDLE)Handle; 00203 } 00204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00205 { 00206 DPRINT1("Exception: Invalid Service Manager handle!\n"); 00207 } 00208 _SEH2_END; 00209 00210 return pManager; 00211 } 00212 00213 00214 static PSERVICE_HANDLE 00215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle) 00216 { 00217 PSERVICE_HANDLE pService = NULL; 00218 00219 _SEH2_TRY 00220 { 00221 if (((PSERVICE_HANDLE)Handle)->Handle.Tag == SERVICE_TAG) 00222 pService = (PSERVICE_HANDLE)Handle; 00223 } 00224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00225 { 00226 DPRINT1("Exception: Invalid Service handle!\n"); 00227 } 00228 _SEH2_END; 00229 00230 return pService; 00231 } 00232 00233 00234 static DWORD 00235 ScmCheckAccess(SC_HANDLE Handle, 00236 DWORD dwDesiredAccess) 00237 { 00238 PMANAGER_HANDLE hMgr; 00239 00240 hMgr = (PMANAGER_HANDLE)Handle; 00241 if (hMgr->Handle.Tag == MANAGER_TAG) 00242 { 00243 RtlMapGenericMask(&dwDesiredAccess, 00244 &ScmManagerMapping); 00245 00246 hMgr->Handle.DesiredAccess = dwDesiredAccess; 00247 00248 return ERROR_SUCCESS; 00249 } 00250 else if (hMgr->Handle.Tag == SERVICE_TAG) 00251 { 00252 RtlMapGenericMask(&dwDesiredAccess, 00253 &ScmServiceMapping); 00254 00255 hMgr->Handle.DesiredAccess = dwDesiredAccess; 00256 00257 return ERROR_SUCCESS; 00258 } 00259 00260 return ERROR_INVALID_HANDLE; 00261 } 00262 00263 00264 DWORD 00265 ScmAssignNewTag(PSERVICE lpService) 00266 { 00267 HKEY hKey = NULL; 00268 DWORD dwError; 00269 DWORD dwGroupTagCount = 0; 00270 PDWORD pdwGroupTags = NULL; 00271 DWORD dwFreeTag = 0; 00272 DWORD dwTagUsedBase = 1; 00273 BOOLEAN TagUsed[TAG_ARRAY_SIZE]; 00274 INT nTagOffset; 00275 DWORD i; 00276 DWORD cbDataSize; 00277 PLIST_ENTRY ServiceEntry; 00278 PSERVICE CurrentService; 00279 00280 ASSERT(lpService != NULL); 00281 ASSERT(lpService->lpGroup != NULL); 00282 00283 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 00284 L"System\\CurrentControlSet\\Control\\GroupOrderList", 00285 0, 00286 KEY_READ, 00287 &hKey); 00288 00289 if (dwError != ERROR_SUCCESS) 00290 goto findFreeTag; 00291 00292 /* query value length */ 00293 cbDataSize = 0; 00294 dwError = RegQueryValueExW(hKey, 00295 lpService->lpGroup->szGroupName, 00296 NULL, 00297 NULL, 00298 NULL, 00299 &cbDataSize); 00300 00301 if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA) 00302 goto findFreeTag; 00303 00304 pdwGroupTags = HeapAlloc(GetProcessHeap(), 0, cbDataSize); 00305 if (!pdwGroupTags) 00306 { 00307 dwError = ERROR_NOT_ENOUGH_MEMORY; 00308 goto cleanup; 00309 } 00310 00311 dwError = RegQueryValueExW(hKey, 00312 lpService->lpGroup->szGroupName, 00313 NULL, 00314 NULL, 00315 (LPBYTE)pdwGroupTags, 00316 &cbDataSize); 00317 00318 if (dwError != ERROR_SUCCESS) 00319 goto findFreeTag; 00320 00321 if (cbDataSize < sizeof(pdwGroupTags[0])) 00322 goto findFreeTag; 00323 00324 dwGroupTagCount = min(pdwGroupTags[0], cbDataSize / sizeof(pdwGroupTags[0]) - 1); 00325 00326 findFreeTag: 00327 do 00328 { 00329 /* mark all tags as unused */ 00330 for (i = 0; i < TAG_ARRAY_SIZE; i++) 00331 TagUsed[i] = FALSE; 00332 00333 /* mark tags in GroupOrderList as used */ 00334 for (i = 1; i <= dwGroupTagCount; i++) 00335 { 00336 nTagOffset = pdwGroupTags[i] - dwTagUsedBase; 00337 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE) 00338 TagUsed[nTagOffset] = TRUE; 00339 } 00340 00341 /* mark tags in service list as used */ 00342 ServiceEntry = lpService->ServiceListEntry.Flink; 00343 while (ServiceEntry != &lpService->ServiceListEntry) 00344 { 00345 ASSERT(ServiceEntry != NULL); 00346 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); 00347 if (CurrentService->lpGroup == lpService->lpGroup) 00348 { 00349 nTagOffset = CurrentService->dwTag - dwTagUsedBase; 00350 if (nTagOffset >= 0 && nTagOffset < TAG_ARRAY_SIZE) 00351 TagUsed[nTagOffset] = TRUE; 00352 } 00353 00354 ServiceEntry = ServiceEntry->Flink; 00355 } 00356 00357 /* find unused tag, if any */ 00358 for (i = 0; i < TAG_ARRAY_SIZE; i++) 00359 { 00360 if (!TagUsed[i]) 00361 { 00362 dwFreeTag = dwTagUsedBase + i; 00363 break; 00364 } 00365 } 00366 00367 dwTagUsedBase += TAG_ARRAY_SIZE; 00368 } while (!dwFreeTag); 00369 00370 cleanup: 00371 if (pdwGroupTags) 00372 HeapFree(GetProcessHeap(), 0, pdwGroupTags); 00373 00374 if (hKey) 00375 RegCloseKey(hKey); 00376 00377 if (dwFreeTag) 00378 { 00379 lpService->dwTag = dwFreeTag; 00380 DPRINT("Assigning new tag %lu to service %S in group %S\n", 00381 lpService->dwTag, lpService->lpServiceName, lpService->lpGroup->szGroupName); 00382 dwError = ERROR_SUCCESS; 00383 } 00384 else 00385 { 00386 DPRINT1("Failed to assign new tag to service %S, error=%lu\n", 00387 lpService->lpServiceName, dwError); 00388 } 00389 00390 return dwError; 00391 } 00392 00393 00394 /* Create a path suitable for the bootloader out of the full path */ 00395 DWORD 00396 ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName) 00397 { 00398 DWORD ServiceNameLen, BufferSize, ExpandedLen; 00399 WCHAR Dest; 00400 WCHAR *Expanded; 00401 UNICODE_STRING NtPathName, SystemRoot, LinkTarget; 00402 OBJECT_ATTRIBUTES ObjectAttributes; 00403 NTSTATUS Status; 00404 HANDLE SymbolicLinkHandle; 00405 00406 DPRINT("ScmConvertToBootPathName %S\n", CanonName); 00407 00408 ServiceNameLen = wcslen(CanonName); 00409 00410 /* First check, if it's already good */ 00411 if (ServiceNameLen > 12 && 00412 !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12)) 00413 { 00414 *RelativeName = HeapAlloc(GetProcessHeap(), 00415 HEAP_ZERO_MEMORY, 00416 (ServiceNameLen + 1) * sizeof(WCHAR)); 00417 if (*RelativeName == NULL) 00418 { 00419 DPRINT("Error allocating memory for boot driver name!\n"); 00420 return ERROR_NOT_ENOUGH_MEMORY; 00421 } 00422 00423 /* Copy it */ 00424 wcscpy(*RelativeName, CanonName); 00425 00426 DPRINT("Bootdriver name %S\n", *RelativeName); 00427 return ERROR_SUCCESS; 00428 } 00429 00430 /* If it has %SystemRoot% prefix, substitute it to \System*/ 00431 if (ServiceNameLen > 13 && 00432 !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13)) 00433 { 00434 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */ 00435 *RelativeName = HeapAlloc(GetProcessHeap(), 00436 HEAP_ZERO_MEMORY, 00437 ServiceNameLen * sizeof(WCHAR)); 00438 00439 if (*RelativeName == NULL) 00440 { 00441 DPRINT("Error allocating memory for boot driver name!\n"); 00442 return ERROR_NOT_ENOUGH_MEMORY; 00443 } 00444 00445 /* Copy it */ 00446 wcscpy(*RelativeName, L"\\SystemRoot\\"); 00447 wcscat(*RelativeName, CanonName + 13); 00448 00449 DPRINT("Bootdriver name %S\n", *RelativeName); 00450 return ERROR_SUCCESS; 00451 } 00452 00453 /* Get buffer size needed for expanding env strings */ 00454 BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1); 00455 00456 if (BufferSize <= 1) 00457 { 00458 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n"); 00459 return ERROR_INVALID_ENVIRONMENT; 00460 } 00461 00462 /* Allocate memory, since the size is known now */ 00463 Expanded = HeapAlloc(GetProcessHeap(), 00464 HEAP_ZERO_MEMORY, 00465 (BufferSize + 1) * sizeof(WCHAR)); 00466 if (!Expanded) 00467 { 00468 DPRINT("Error allocating memory for boot driver name!\n"); 00469 return ERROR_NOT_ENOUGH_MEMORY; 00470 } 00471 00472 /* Expand it */ 00473 if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) > 00474 BufferSize) 00475 { 00476 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n"); 00477 HeapFree(GetProcessHeap(), 0, Expanded); 00478 return ERROR_NOT_ENOUGH_MEMORY; 00479 } 00480 00481 /* Convert to NY-style path */ 00482 if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL)) 00483 { 00484 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n"); 00485 return ERROR_INVALID_ENVIRONMENT; 00486 } 00487 00488 DPRINT("Converted to NT-style %wZ\n", &NtPathName); 00489 00490 /* No need to keep the dos-path anymore */ 00491 HeapFree(GetProcessHeap(), 0, Expanded); 00492 00493 /* Copy it to the allocated place */ 00494 Expanded = HeapAlloc(GetProcessHeap(), 00495 HEAP_ZERO_MEMORY, 00496 NtPathName.Length + sizeof(UNICODE_NULL)); 00497 if (!Expanded) 00498 { 00499 DPRINT("Error allocating memory for boot driver name!\n"); 00500 return ERROR_NOT_ENOUGH_MEMORY; 00501 } 00502 00503 ExpandedLen = NtPathName.Length / sizeof(WCHAR); 00504 wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen); 00505 Expanded[ExpandedLen] = UNICODE_NULL; 00506 00507 if (ServiceNameLen > ExpandedLen && 00508 !_wcsnicmp(Expanded, CanonName, ExpandedLen)) 00509 { 00510 /* Only \SystemRoot\ is missing */ 00511 *RelativeName = HeapAlloc(GetProcessHeap(), 00512 HEAP_ZERO_MEMORY, 00513 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR)); 00514 if (*RelativeName == NULL) 00515 { 00516 DPRINT("Error allocating memory for boot driver name!\n"); 00517 HeapFree(GetProcessHeap(), 0, Expanded); 00518 return ERROR_NOT_ENOUGH_MEMORY; 00519 } 00520 00521 wcscpy(*RelativeName, L"\\SystemRoot\\"); 00522 wcscat(*RelativeName, CanonName + ExpandedLen); 00523 00524 RtlFreeUnicodeString(&NtPathName); 00525 return ERROR_SUCCESS; 00526 } 00527 00528 /* The most complex case starts here */ 00529 RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot"); 00530 InitializeObjectAttributes(&ObjectAttributes, 00531 &SystemRoot, 00532 OBJ_CASE_INSENSITIVE, 00533 NULL, 00534 NULL); 00535 00536 /* Open this symlink */ 00537 Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); 00538 00539 if (NT_SUCCESS(Status)) 00540 { 00541 LinkTarget.Length = 0; 00542 LinkTarget.MaximumLength = 0; 00543 00544 DPRINT("Opened symbolic link object\n"); 00545 00546 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize); 00547 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) 00548 { 00549 /* Check if required buffer size is sane */ 00550 if (BufferSize > 0xFFFD) 00551 { 00552 DPRINT("Too large buffer required\n"); 00553 *RelativeName = 0; 00554 00555 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00556 HeapFree(GetProcessHeap(), 0, Expanded); 00557 return ERROR_NOT_ENOUGH_MEMORY; 00558 } 00559 00560 /* Alloc the string */ 00561 LinkTarget.Length = (USHORT)BufferSize; 00562 LinkTarget.MaximumLength = LinkTarget.Length + sizeof(UNICODE_NULL); 00563 LinkTarget.Buffer = HeapAlloc(GetProcessHeap(), 00564 HEAP_ZERO_MEMORY, 00565 LinkTarget.MaximumLength); 00566 if (!LinkTarget.Buffer) 00567 { 00568 DPRINT("Unable to alloc buffer\n"); 00569 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00570 HeapFree(GetProcessHeap(), 0, Expanded); 00571 return ERROR_NOT_ENOUGH_MEMORY; 00572 } 00573 00574 /* Do a real query now */ 00575 Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize); 00576 if (NT_SUCCESS(Status)) 00577 { 00578 DPRINT("LinkTarget: %wZ\n", &LinkTarget); 00579 00580 ExpandedLen = LinkTarget.Length / sizeof(WCHAR); 00581 if ((ServiceNameLen > ExpandedLen) && 00582 !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen)) 00583 { 00584 *RelativeName = HeapAlloc(GetProcessHeap(), 00585 HEAP_ZERO_MEMORY, 00586 (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR)); 00587 00588 if (*RelativeName == NULL) 00589 { 00590 DPRINT("Unable to alloc buffer\n"); 00591 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00592 HeapFree(GetProcessHeap(), 0, Expanded); 00593 RtlFreeUnicodeString(&NtPathName); 00594 return ERROR_NOT_ENOUGH_MEMORY; 00595 } 00596 00597 /* Copy it over, substituting the first part 00598 with SystemRoot */ 00599 wcscpy(*RelativeName, L"\\SystemRoot\\"); 00600 wcscat(*RelativeName, CanonName+ExpandedLen+1); 00601 00602 /* Cleanup */ 00603 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00604 HeapFree(GetProcessHeap(), 0, Expanded); 00605 RtlFreeUnicodeString(&NtPathName); 00606 00607 /* Return success */ 00608 return ERROR_SUCCESS; 00609 } 00610 else 00611 { 00612 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00613 HeapFree(GetProcessHeap(), 0, Expanded); 00614 RtlFreeUnicodeString(&NtPathName); 00615 return ERROR_INVALID_PARAMETER; 00616 } 00617 } 00618 else 00619 { 00620 DPRINT("Error, Status = %08X\n", Status); 00621 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00622 HeapFree(GetProcessHeap(), 0, Expanded); 00623 RtlFreeUnicodeString(&NtPathName); 00624 return ERROR_INVALID_PARAMETER; 00625 } 00626 } 00627 else 00628 { 00629 DPRINT("Error, Status = %08X\n", Status); 00630 if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle); 00631 HeapFree(GetProcessHeap(), 0, Expanded); 00632 RtlFreeUnicodeString(&NtPathName); 00633 return ERROR_INVALID_PARAMETER; 00634 } 00635 } 00636 else 00637 { 00638 DPRINT("Error, Status = %08X\n", Status); 00639 HeapFree(GetProcessHeap(), 0, Expanded); 00640 return ERROR_INVALID_PARAMETER; 00641 } 00642 00643 /* Failure */ 00644 *RelativeName = NULL; 00645 return ERROR_INVALID_PARAMETER; 00646 } 00647 00648 00649 DWORD 00650 ScmCanonDriverImagePath(DWORD dwStartType, 00651 const wchar_t *lpServiceName, 00652 wchar_t **lpCanonName) 00653 { 00654 DWORD ServiceNameLen, Result; 00655 UNICODE_STRING NtServiceName; 00656 WCHAR *RelativeName; 00657 const WCHAR *SourceName = lpServiceName; 00658 00659 /* Calculate the length of the service's name */ 00660 ServiceNameLen = wcslen(lpServiceName); 00661 00662 /* 12 is wcslen(L"\\SystemRoot\\") */ 00663 if (ServiceNameLen > 12 && 00664 !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12)) 00665 { 00666 /* SystemRoot prefix is already included */ 00667 *lpCanonName = HeapAlloc(GetProcessHeap(), 00668 HEAP_ZERO_MEMORY, 00669 (ServiceNameLen + 1) * sizeof(WCHAR)); 00670 00671 if (*lpCanonName == NULL) 00672 { 00673 DPRINT("Error allocating memory for canonized service name!\n"); 00674 return ERROR_NOT_ENOUGH_MEMORY; 00675 } 00676 00677 /* If it's a boot-time driver, it must be systemroot relative */ 00678 if (dwStartType == SERVICE_BOOT_START) 00679 SourceName += 12; 00680 00681 /* Copy it */ 00682 wcscpy(*lpCanonName, SourceName); 00683 00684 DPRINT("Canonicalized name %S\n", *lpCanonName); 00685 return NO_ERROR; 00686 } 00687 00688 /* Check if it has %SystemRoot% (len=13) */ 00689 if (ServiceNameLen > 13 && 00690 !_wcsnicmp(L"%SystemRoot%\\", lpServiceName, 13)) 00691 { 00692 /* Substitute %SystemRoot% with \\SystemRoot\\ */ 00693 *lpCanonName = HeapAlloc(GetProcessHeap(), 00694 HEAP_ZERO_MEMORY, 00695 (ServiceNameLen + 1) * sizeof(WCHAR)); 00696 00697 if (*lpCanonName == NULL) 00698 { 00699 DPRINT("Error allocating memory for canonized service name!\n"); 00700 return ERROR_NOT_ENOUGH_MEMORY; 00701 } 00702 00703 /* If it's a boot-time driver, it must be systemroot relative */ 00704 if (dwStartType == SERVICE_BOOT_START) 00705 wcscpy(*lpCanonName, L"\\SystemRoot\\"); 00706 00707 wcscat(*lpCanonName, lpServiceName + 13); 00708 00709 DPRINT("Canonicalized name %S\n", *lpCanonName); 00710 return NO_ERROR; 00711 } 00712 00713 /* Check if it's a relative path name */ 00714 if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':') 00715 { 00716 *lpCanonName = HeapAlloc(GetProcessHeap(), 00717 HEAP_ZERO_MEMORY, 00718 (ServiceNameLen + 1) * sizeof(WCHAR)); 00719 00720 if (*lpCanonName == NULL) 00721 { 00722 DPRINT("Error allocating memory for canonized service name!\n"); 00723 return ERROR_NOT_ENOUGH_MEMORY; 00724 } 00725 00726 /* Just copy it over without changing */ 00727 wcscpy(*lpCanonName, lpServiceName); 00728 00729 return NO_ERROR; 00730 } 00731 00732 /* It seems to be a DOS path, convert it */ 00733 if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL)) 00734 { 00735 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n"); 00736 return ERROR_INVALID_PARAMETER; 00737 } 00738 00739 *lpCanonName = HeapAlloc(GetProcessHeap(), 00740 HEAP_ZERO_MEMORY, 00741 NtServiceName.Length + sizeof(WCHAR)); 00742 00743 if (*lpCanonName == NULL) 00744 { 00745 DPRINT("Error allocating memory for canonized service name!\n"); 00746 RtlFreeUnicodeString(&NtServiceName); 00747 return ERROR_NOT_ENOUGH_MEMORY; 00748 } 00749 00750 /* Copy the string */ 00751 wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR)); 00752 00753 /* The unicode string is not needed anymore */ 00754 RtlFreeUnicodeString(&NtServiceName); 00755 00756 if (dwStartType != SERVICE_BOOT_START) 00757 { 00758 DPRINT("Canonicalized name %S\n", *lpCanonName); 00759 return NO_ERROR; 00760 } 00761 00762 /* The service is boot-started, so must be relative */ 00763 Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName); 00764 if (Result) 00765 { 00766 /* There is a problem, free name and return */ 00767 HeapFree(GetProcessHeap(), 0, *lpCanonName); 00768 DPRINT("Error converting named!\n"); 00769 return Result; 00770 } 00771 00772 ASSERT(RelativeName); 00773 00774 /* Copy that string */ 00775 wcscpy(*lpCanonName, RelativeName + 12); 00776 00777 /* Free the allocated buffer */ 00778 HeapFree(GetProcessHeap(), 0, RelativeName); 00779 00780 DPRINT("Canonicalized name %S\n", *lpCanonName); 00781 00782 /* Success */ 00783 return NO_ERROR; 00784 } 00785 00786 00787 /* Internal recursive function */ 00788 /* Need to search for every dependency on every service */ 00789 static DWORD 00790 Int_EnumDependentServicesW(HKEY hServicesKey, 00791 PSERVICE lpService, 00792 DWORD dwServiceState, 00793 PSERVICE *lpServices, 00794 LPDWORD pcbBytesNeeded, 00795 LPDWORD lpServicesReturned) 00796 { 00797 DWORD dwError = ERROR_SUCCESS; 00798 WCHAR szNameBuf[MAX_PATH]; 00799 WCHAR szValueBuf[MAX_PATH]; 00800 WCHAR *lpszNameBuf = szNameBuf; 00801 WCHAR *lpszValueBuf = szValueBuf; 00802 DWORD dwSize; 00803 DWORD dwNumSubKeys; 00804 DWORD dwIteration; 00805 PSERVICE lpCurrentService; 00806 HKEY hServiceEnumKey; 00807 DWORD dwCurrentServiceState = SERVICE_ACTIVE; 00808 DWORD dwDependServiceStrPtr = 0; 00809 DWORD dwRequiredSize = 0; 00810 00811 /* Get the number of service keys */ 00812 dwError = RegQueryInfoKeyW(hServicesKey, 00813 NULL, 00814 NULL, 00815 NULL, 00816 &dwNumSubKeys, 00817 NULL, 00818 NULL, 00819 NULL, 00820 NULL, 00821 NULL, 00822 NULL, 00823 NULL); 00824 if (dwError != ERROR_SUCCESS) 00825 { 00826 DPRINT("ERROR! Unable to get number of services keys.\n"); 00827 return dwError; 00828 } 00829 00830 /* Iterate the service keys to see if another service depends on the this service */ 00831 for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++) 00832 { 00833 dwSize = MAX_PATH; 00834 dwError = RegEnumKeyExW(hServicesKey, 00835 dwIteration, 00836 lpszNameBuf, 00837 &dwSize, 00838 NULL, 00839 NULL, 00840 NULL, 00841 NULL); 00842 if (dwError != ERROR_SUCCESS) 00843 return dwError; 00844 00845 /* Open the Service key */ 00846 dwError = RegOpenKeyExW(hServicesKey, 00847 lpszNameBuf, 00848 0, 00849 KEY_READ, 00850 &hServiceEnumKey); 00851 if (dwError != ERROR_SUCCESS) 00852 return dwError; 00853 00854 dwSize = MAX_PATH; 00855 00856 /* Check for the DependOnService Value */ 00857 dwError = RegQueryValueExW(hServiceEnumKey, 00858 L"DependOnService", 00859 NULL, 00860 NULL, 00861 (LPBYTE)lpszValueBuf, 00862 &dwSize); 00863 00864 /* FIXME: Handle load order. */ 00865 00866 /* If the service found has a DependOnService value */ 00867 if (dwError == ERROR_SUCCESS) 00868 { 00869 dwDependServiceStrPtr = 0; 00870 00871 /* Can be more than one Dependencies in the DependOnService string */ 00872 while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0) 00873 { 00874 if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0) 00875 { 00876 /* Get the current enumed service pointer */ 00877 lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf); 00878 00879 /* Check for valid Service */ 00880 if (!lpCurrentService) 00881 { 00882 /* This should never happen! */ 00883 DPRINT("This should not happen at this point, report to Developer\n"); 00884 return ERROR_NOT_FOUND; 00885 } 00886 00887 /* Determine state the service is in */ 00888 if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED) 00889 dwCurrentServiceState = SERVICE_INACTIVE; 00890 00891 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */ 00892 if ((dwCurrentServiceState == dwServiceState) || 00893 (dwServiceState == SERVICE_STATE_ALL)) 00894 { 00895 /* Calculate the required size */ 00896 dwRequiredSize += sizeof(SERVICE_STATUS); 00897 dwRequiredSize += ((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR)); 00898 dwRequiredSize += ((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 00899 00900 /* Add the size for service name and display name pointers */ 00901 dwRequiredSize += (2 * sizeof(PVOID)); 00902 00903 /* increase the BytesNeeded size */ 00904 *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize; 00905 00906 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency 00907 comes first */ 00908 00909 /* Recursive call to check for its dependencies */ 00910 Int_EnumDependentServicesW(hServicesKey, 00911 lpCurrentService, 00912 dwServiceState, 00913 lpServices, 00914 pcbBytesNeeded, 00915 lpServicesReturned); 00916 00917 /* If the lpServices is valid set the service pointer */ 00918 if (lpServices) 00919 lpServices[*lpServicesReturned] = lpCurrentService; 00920 00921 *lpServicesReturned = *lpServicesReturned + 1; 00922 } 00923 } 00924 00925 dwDependServiceStrPtr += (wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1); 00926 } 00927 } 00928 else if (*pcbBytesNeeded) 00929 { 00930 dwError = ERROR_SUCCESS; 00931 } 00932 00933 RegCloseKey(hServiceEnumKey); 00934 } 00935 00936 return dwError; 00937 } 00938 00939 00940 /* Function 0 */ 00941 DWORD RCloseServiceHandle( 00942 LPSC_RPC_HANDLE hSCObject) 00943 { 00944 PMANAGER_HANDLE hManager; 00945 PSERVICE_HANDLE hService; 00946 PSERVICE lpService; 00947 HKEY hServicesKey; 00948 DWORD dwError; 00949 DWORD pcbBytesNeeded = 0; 00950 DWORD dwServicesReturned = 0; 00951 00952 DPRINT("RCloseServiceHandle() called\n"); 00953 00954 DPRINT("hSCObject = %p\n", *hSCObject); 00955 00956 if (*hSCObject == 0) 00957 return ERROR_INVALID_HANDLE; 00958 00959 hManager = ScmGetServiceManagerFromHandle(*hSCObject); 00960 hService = ScmGetServiceFromHandle(*hSCObject); 00961 00962 if (hManager != NULL) 00963 { 00964 DPRINT("Found manager handle\n"); 00965 00966 /* FIXME: add handle cleanup code */ 00967 00968 HeapFree(GetProcessHeap(), 0, hManager); 00969 hManager = NULL; 00970 00971 *hSCObject = NULL; 00972 00973 DPRINT("RCloseServiceHandle() done\n"); 00974 return ERROR_SUCCESS; 00975 } 00976 else if (hService != NULL) 00977 { 00978 DPRINT("Found service handle\n"); 00979 00980 /* Lock the service database exlusively */ 00981 ScmLockDatabaseExclusive(); 00982 00983 /* Get the pointer to the service record */ 00984 lpService = hService->ServiceEntry; 00985 00986 /* FIXME: add handle cleanup code */ 00987 00988 /* Free the handle */ 00989 HeapFree(GetProcessHeap(), 0, hService); 00990 hService = NULL; 00991 00992 ASSERT(lpService->dwRefCount > 0); 00993 00994 lpService->dwRefCount--; 00995 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n", 00996 lpService->dwRefCount); 00997 00998 if (lpService->dwRefCount == 0) 00999 { 01000 /* If this service has been marked for deletion */ 01001 if (lpService->bDeleted) 01002 { 01003 /* Open the Services Reg key */ 01004 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 01005 L"System\\CurrentControlSet\\Services", 01006 0, 01007 KEY_SET_VALUE | KEY_READ, 01008 &hServicesKey); 01009 if (dwError != ERROR_SUCCESS) 01010 { 01011 DPRINT("Failed to open services key\n"); 01012 ScmUnlockDatabase(); 01013 return dwError; 01014 } 01015 01016 /* Call the internal function with NULL, just to get bytes we need */ 01017 Int_EnumDependentServicesW(hServicesKey, 01018 lpService, 01019 SERVICE_ACTIVE, 01020 NULL, 01021 &pcbBytesNeeded, 01022 &dwServicesReturned); 01023 01024 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */ 01025 if (pcbBytesNeeded) 01026 { 01027 DPRINT("Deletion failed due to running dependencies.\n"); 01028 RegCloseKey(hServicesKey); 01029 ScmUnlockDatabase(); 01030 return ERROR_SUCCESS; 01031 } 01032 01033 /* There are no references and no runnning dependencies, 01034 it is now safe to delete the service */ 01035 01036 /* Delete the Service Key */ 01037 dwError = RegDeleteKeyW(hServicesKey, 01038 lpService->lpServiceName); 01039 01040 RegCloseKey(hServicesKey); 01041 01042 if (dwError != ERROR_SUCCESS) 01043 { 01044 DPRINT("Failed to Delete the Service Registry key\n"); 01045 ScmUnlockDatabase(); 01046 return dwError; 01047 } 01048 01049 /* Delete the Service */ 01050 ScmDeleteServiceRecord(lpService); 01051 } 01052 } 01053 01054 ScmUnlockDatabase(); 01055 01056 *hSCObject = NULL; 01057 01058 DPRINT("RCloseServiceHandle() done\n"); 01059 return ERROR_SUCCESS; 01060 } 01061 01062 DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag); 01063 01064 return ERROR_INVALID_HANDLE; 01065 } 01066 01067 01068 /* Function 1 */ 01069 DWORD RControlService( 01070 SC_RPC_HANDLE hService, 01071 DWORD dwControl, 01072 LPSERVICE_STATUS lpServiceStatus) 01073 { 01074 PSERVICE_HANDLE hSvc; 01075 PSERVICE lpService; 01076 ACCESS_MASK DesiredAccess; 01077 DWORD dwError = ERROR_SUCCESS; 01078 DWORD pcbBytesNeeded = 0; 01079 DWORD dwServicesReturned = 0; 01080 DWORD dwControlsAccepted; 01081 DWORD dwCurrentState; 01082 HKEY hServicesKey = NULL; 01083 01084 DPRINT("RControlService() called\n"); 01085 01086 if (ScmShutdown) 01087 return ERROR_SHUTDOWN_IN_PROGRESS; 01088 01089 /* Check the service handle */ 01090 hSvc = ScmGetServiceFromHandle(hService); 01091 if (hSvc == NULL) 01092 { 01093 DPRINT1("Invalid service handle!\n"); 01094 return ERROR_INVALID_HANDLE; 01095 } 01096 01097 /* Check the service entry point */ 01098 lpService = hSvc->ServiceEntry; 01099 if (lpService == NULL) 01100 { 01101 DPRINT1("lpService == NULL!\n"); 01102 return ERROR_INVALID_HANDLE; 01103 } 01104 01105 /* Check access rights */ 01106 switch (dwControl) 01107 { 01108 case SERVICE_CONTROL_STOP: 01109 DesiredAccess = SERVICE_STOP; 01110 break; 01111 01112 case SERVICE_CONTROL_PAUSE: 01113 case SERVICE_CONTROL_CONTINUE: 01114 DesiredAccess = SERVICE_PAUSE_CONTINUE; 01115 break; 01116 01117 case SERVICE_INTERROGATE: 01118 DesiredAccess = SERVICE_INTERROGATE; 01119 break; 01120 01121 default: 01122 if (dwControl >= 128 && dwControl <= 255) 01123 DesiredAccess = SERVICE_USER_DEFINED_CONTROL; 01124 else 01125 return ERROR_INVALID_PARAMETER; 01126 break; 01127 } 01128 01129 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01130 DesiredAccess)) 01131 return ERROR_ACCESS_DENIED; 01132 01133 /* Return the current service status information */ 01134 RtlCopyMemory(lpServiceStatus, 01135 &lpService->Status, 01136 sizeof(SERVICE_STATUS)); 01137 01138 if (dwControl == SERVICE_CONTROL_STOP) 01139 { 01140 /* Check if the service has dependencies running as windows 01141 doesn't stop a service that does */ 01142 01143 /* Open the Services Reg key */ 01144 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 01145 L"System\\CurrentControlSet\\Services", 01146 0, 01147 KEY_READ, 01148 &hServicesKey); 01149 if (dwError != ERROR_SUCCESS) 01150 { 01151 DPRINT("Failed to open services key\n"); 01152 return dwError; 01153 } 01154 01155 /* Call the internal function with NULL, just to get bytes we need */ 01156 Int_EnumDependentServicesW(hServicesKey, 01157 lpService, 01158 SERVICE_ACTIVE, 01159 NULL, 01160 &pcbBytesNeeded, 01161 &dwServicesReturned); 01162 01163 RegCloseKey(hServicesKey); 01164 01165 /* If pcbBytesNeeded is not zero then there are services running that 01166 are dependent on this service */ 01167 if (pcbBytesNeeded != 0) 01168 { 01169 DPRINT("Service has running dependencies. Failed to stop service.\n"); 01170 return ERROR_DEPENDENT_SERVICES_RUNNING; 01171 } 01172 } 01173 01174 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 01175 { 01176 /* Send control code to the driver */ 01177 dwError = ScmControlDriver(lpService, 01178 dwControl, 01179 lpServiceStatus); 01180 } 01181 else 01182 { 01183 dwControlsAccepted = lpService->Status.dwControlsAccepted; 01184 dwCurrentState = lpService->Status.dwCurrentState; 01185 01186 /* Return ERROR_SERVICE_NOT_ACTIVE if the service has not been started */ 01187 if (lpService->lpImage == NULL || dwCurrentState == SERVICE_STOPPED) 01188 return ERROR_SERVICE_NOT_ACTIVE; 01189 01190 /* Check the current state before sending a control request */ 01191 switch (dwCurrentState) 01192 { 01193 case SERVICE_STOP_PENDING: 01194 case SERVICE_STOPPED: 01195 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; 01196 01197 case SERVICE_START_PENDING: 01198 switch (dwControl) 01199 { 01200 case SERVICE_CONTROL_STOP: 01201 break; 01202 01203 case SERVICE_CONTROL_INTERROGATE: 01204 RtlCopyMemory(lpServiceStatus, 01205 &lpService->Status, 01206 sizeof(SERVICE_STATUS)); 01207 return ERROR_SUCCESS; 01208 01209 default: 01210 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL; 01211 } 01212 break; 01213 } 01214 01215 /* Check if the control code is acceptable to the service */ 01216 switch (dwControl) 01217 { 01218 case SERVICE_CONTROL_STOP: 01219 if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0) 01220 return ERROR_INVALID_SERVICE_CONTROL; 01221 break; 01222 01223 case SERVICE_CONTROL_PAUSE: 01224 case SERVICE_CONTROL_CONTINUE: 01225 if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0) 01226 return ERROR_INVALID_SERVICE_CONTROL; 01227 break; 01228 } 01229 01230 /* Send control code to the service */ 01231 dwError = ScmControlService(lpService, 01232 dwControl); 01233 01234 /* Return service status information */ 01235 RtlCopyMemory(lpServiceStatus, 01236 &lpService->Status, 01237 sizeof(SERVICE_STATUS)); 01238 } 01239 01240 if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded)) 01241 dwError = ERROR_DEPENDENT_SERVICES_RUNNING; 01242 01243 return dwError; 01244 } 01245 01246 01247 /* Function 2 */ 01248 DWORD RDeleteService( 01249 SC_RPC_HANDLE hService) 01250 { 01251 PSERVICE_HANDLE hSvc; 01252 PSERVICE lpService; 01253 DWORD dwError; 01254 01255 DPRINT("RDeleteService() called\n"); 01256 01257 if (ScmShutdown) 01258 return ERROR_SHUTDOWN_IN_PROGRESS; 01259 01260 hSvc = ScmGetServiceFromHandle(hService); 01261 if (hSvc == NULL) 01262 { 01263 DPRINT1("Invalid service handle!\n"); 01264 return ERROR_INVALID_HANDLE; 01265 } 01266 01267 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01268 DELETE)) 01269 return ERROR_ACCESS_DENIED; 01270 01271 lpService = hSvc->ServiceEntry; 01272 if (lpService == NULL) 01273 { 01274 DPRINT("lpService == NULL!\n"); 01275 return ERROR_INVALID_HANDLE; 01276 } 01277 01278 /* Lock the service database exclusively */ 01279 ScmLockDatabaseExclusive(); 01280 01281 if (lpService->bDeleted) 01282 { 01283 DPRINT("The service has already been marked for delete!\n"); 01284 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 01285 goto Done; 01286 } 01287 01288 /* Mark service for delete */ 01289 lpService->bDeleted = TRUE; 01290 01291 dwError = ScmMarkServiceForDelete(lpService); 01292 01293 Done:; 01294 /* Unlock the service database */ 01295 ScmUnlockDatabase(); 01296 01297 DPRINT("RDeleteService() done\n"); 01298 01299 return dwError; 01300 } 01301 01302 01303 /* Function 3 */ 01304 DWORD RLockServiceDatabase( 01305 SC_RPC_HANDLE hSCManager, 01306 LPSC_RPC_LOCK lpLock) 01307 { 01308 PMANAGER_HANDLE hMgr; 01309 01310 DPRINT("RLockServiceDatabase() called\n"); 01311 01312 *lpLock = 0; 01313 01314 hMgr = ScmGetServiceManagerFromHandle(hSCManager); 01315 if (hMgr == NULL) 01316 { 01317 DPRINT1("Invalid service manager handle!\n"); 01318 return ERROR_INVALID_HANDLE; 01319 } 01320 01321 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess, 01322 SC_MANAGER_LOCK)) 01323 return ERROR_ACCESS_DENIED; 01324 01325 // return ScmLockDatabase(0, hMgr->0xC, hLock); 01326 01327 /* FIXME: Lock the database */ 01328 *lpLock = (SC_RPC_LOCK)0x12345678; /* Dummy! */ 01329 01330 return ERROR_SUCCESS; 01331 } 01332 01333 01334 /* Function 4 */ 01335 DWORD RQueryServiceObjectSecurity( 01336 SC_RPC_HANDLE hService, 01337 SECURITY_INFORMATION dwSecurityInformation, 01338 LPBYTE lpSecurityDescriptor, 01339 DWORD cbBufSize, 01340 LPBOUNDED_DWORD_256K pcbBytesNeeded) 01341 { 01342 PSERVICE_HANDLE hSvc; 01343 PSERVICE lpService; 01344 ULONG DesiredAccess = 0; 01345 NTSTATUS Status; 01346 DWORD dwBytesNeeded; 01347 DWORD dwError; 01348 01349 01350 SECURITY_DESCRIPTOR ObjectDescriptor; 01351 01352 DPRINT("RQueryServiceObjectSecurity() called\n"); 01353 01354 hSvc = ScmGetServiceFromHandle(hService); 01355 if (hSvc == NULL) 01356 { 01357 DPRINT1("Invalid service handle!\n"); 01358 return ERROR_INVALID_HANDLE; 01359 } 01360 01361 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION | 01362 GROUP_SECURITY_INFORMATION | 01363 OWNER_SECURITY_INFORMATION)) 01364 DesiredAccess |= READ_CONTROL; 01365 01366 if (dwSecurityInformation & SACL_SECURITY_INFORMATION) 01367 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 01368 01369 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01370 DesiredAccess)) 01371 { 01372 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 01373 return ERROR_ACCESS_DENIED; 01374 } 01375 01376 lpService = hSvc->ServiceEntry; 01377 if (lpService == NULL) 01378 { 01379 DPRINT("lpService == NULL!\n"); 01380 return ERROR_INVALID_HANDLE; 01381 } 01382 01383 /* Lock the service database */ 01384 ScmLockDatabaseShared(); 01385 01386 01387 /* hack */ 01388 Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION); 01389 01390 Status = RtlQuerySecurityObject(&ObjectDescriptor /* lpService->lpSecurityDescriptor */, 01391 dwSecurityInformation, 01392 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor, 01393 cbBufSize, 01394 &dwBytesNeeded); 01395 01396 /* Unlock the service database */ 01397 ScmUnlockDatabase(); 01398 01399 if (NT_SUCCESS(Status)) 01400 { 01401 *pcbBytesNeeded = dwBytesNeeded; 01402 dwError = STATUS_SUCCESS; 01403 } 01404 else if (Status == STATUS_BUFFER_TOO_SMALL) 01405 { 01406 *pcbBytesNeeded = dwBytesNeeded; 01407 dwError = ERROR_INSUFFICIENT_BUFFER; 01408 } 01409 else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT) 01410 { 01411 dwError = ERROR_GEN_FAILURE; 01412 } 01413 else 01414 { 01415 dwError = RtlNtStatusToDosError(Status); 01416 } 01417 01418 return dwError; 01419 } 01420 01421 01422 /* Function 5 */ 01423 DWORD RSetServiceObjectSecurity( 01424 SC_RPC_HANDLE hService, 01425 DWORD dwSecurityInformation, 01426 LPBYTE lpSecurityDescriptor, 01427 DWORD dwSecuityDescriptorSize) 01428 { 01429 PSERVICE_HANDLE hSvc; 01430 PSERVICE lpService; 01431 ULONG DesiredAccess = 0; 01432 /* HANDLE hToken = NULL; */ 01433 HKEY hServiceKey; 01434 /* NTSTATUS Status; */ 01435 DWORD dwError; 01436 01437 DPRINT("RSetServiceObjectSecurity() called\n"); 01438 01439 hSvc = ScmGetServiceFromHandle(hService); 01440 if (hSvc == NULL) 01441 { 01442 DPRINT1("Invalid service handle!\n"); 01443 return ERROR_INVALID_HANDLE; 01444 } 01445 01446 if (dwSecurityInformation == 0 || 01447 dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION 01448 | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)) 01449 return ERROR_INVALID_PARAMETER; 01450 01451 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)) 01452 return ERROR_INVALID_PARAMETER; 01453 01454 if (dwSecurityInformation & SACL_SECURITY_INFORMATION) 01455 DesiredAccess |= ACCESS_SYSTEM_SECURITY; 01456 01457 if (dwSecurityInformation & DACL_SECURITY_INFORMATION) 01458 DesiredAccess |= WRITE_DAC; 01459 01460 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) 01461 DesiredAccess |= WRITE_OWNER; 01462 01463 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) && 01464 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL)) 01465 return ERROR_INVALID_PARAMETER; 01466 01467 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) && 01468 (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL)) 01469 return ERROR_INVALID_PARAMETER; 01470 01471 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01472 DesiredAccess)) 01473 { 01474 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 01475 return ERROR_ACCESS_DENIED; 01476 } 01477 01478 lpService = hSvc->ServiceEntry; 01479 if (lpService == NULL) 01480 { 01481 DPRINT("lpService == NULL!\n"); 01482 return ERROR_INVALID_HANDLE; 01483 } 01484 01485 if (lpService->bDeleted) 01486 return ERROR_SERVICE_MARKED_FOR_DELETE; 01487 01488 #if 0 01489 RpcImpersonateClient(NULL); 01490 01491 Status = NtOpenThreadToken(NtCurrentThread(), 01492 8, 01493 TRUE, 01494 &hToken); 01495 if (!NT_SUCCESS(Status)) 01496 return RtlNtStatusToDosError(Status); 01497 01498 RpcRevertToSelf(); 01499 #endif 01500 01501 /* Lock the service database exclusive */ 01502 ScmLockDatabaseExclusive(); 01503 01504 #if 0 01505 Status = RtlSetSecurityObject(dwSecurityInformation, 01506 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor, 01507 &lpService->lpSecurityDescriptor, 01508 &ScmServiceMapping, 01509 hToken); 01510 if (!NT_SUCCESS(Status)) 01511 { 01512 dwError = RtlNtStatusToDosError(Status); 01513 goto Done; 01514 } 01515 #endif 01516 01517 dwError = ScmOpenServiceKey(lpService->lpServiceName, 01518 READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE, 01519 &hServiceKey); 01520 if (dwError != ERROR_SUCCESS) 01521 goto Done; 01522 01523 UNIMPLEMENTED; 01524 dwError = ERROR_SUCCESS; 01525 // dwError = ScmWriteSecurityDescriptor(hServiceKey, 01526 // lpService->lpSecurityDescriptor); 01527 01528 RegFlushKey(hServiceKey); 01529 RegCloseKey(hServiceKey); 01530 01531 Done: 01532 01533 #if 0 01534 if (hToken != NULL) 01535 NtClose(hToken); 01536 #endif 01537 01538 /* Unlock service database */ 01539 ScmUnlockDatabase(); 01540 01541 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError); 01542 01543 return dwError; 01544 } 01545 01546 01547 /* Function 6 */ 01548 DWORD RQueryServiceStatus( 01549 SC_RPC_HANDLE hService, 01550 LPSERVICE_STATUS lpServiceStatus) 01551 { 01552 PSERVICE_HANDLE hSvc; 01553 PSERVICE lpService; 01554 01555 DPRINT("RQueryServiceStatus() called\n"); 01556 01557 if (ScmShutdown) 01558 return ERROR_SHUTDOWN_IN_PROGRESS; 01559 01560 hSvc = ScmGetServiceFromHandle(hService); 01561 if (hSvc == NULL) 01562 { 01563 DPRINT1("Invalid service handle!\n"); 01564 return ERROR_INVALID_HANDLE; 01565 } 01566 01567 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01568 SERVICE_QUERY_STATUS)) 01569 { 01570 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 01571 return ERROR_ACCESS_DENIED; 01572 } 01573 01574 lpService = hSvc->ServiceEntry; 01575 if (lpService == NULL) 01576 { 01577 DPRINT("lpService == NULL!\n"); 01578 return ERROR_INVALID_HANDLE; 01579 } 01580 01581 /* Lock the service database shared */ 01582 ScmLockDatabaseShared(); 01583 01584 /* Return service status information */ 01585 RtlCopyMemory(lpServiceStatus, 01586 &lpService->Status, 01587 sizeof(SERVICE_STATUS)); 01588 01589 /* Unlock the service database */ 01590 ScmUnlockDatabase(); 01591 01592 return ERROR_SUCCESS; 01593 } 01594 01595 01596 static BOOL 01597 ScmIsValidServiceState(DWORD dwCurrentState) 01598 { 01599 switch (dwCurrentState) 01600 { 01601 case SERVICE_STOPPED: 01602 case SERVICE_START_PENDING: 01603 case SERVICE_STOP_PENDING: 01604 case SERVICE_RUNNING: 01605 case SERVICE_CONTINUE_PENDING: 01606 case SERVICE_PAUSE_PENDING: 01607 case SERVICE_PAUSED: 01608 return TRUE; 01609 01610 default: 01611 return FALSE; 01612 } 01613 } 01614 01615 01616 /* Function 7 */ 01617 DWORD RSetServiceStatus( 01618 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 01619 LPSERVICE_STATUS lpServiceStatus) 01620 { 01621 PSERVICE lpService; 01622 DWORD dwPreviousState; 01623 LPCWSTR lpErrorStrings[2]; 01624 WCHAR szErrorBuffer[32]; 01625 01626 DPRINT("RSetServiceStatus() called\n"); 01627 DPRINT("hServiceStatus = %p\n", hServiceStatus); 01628 DPRINT("dwServiceType = %lu\n", lpServiceStatus->dwServiceType); 01629 DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState); 01630 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted); 01631 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode); 01632 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode); 01633 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint); 01634 DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint); 01635 01636 if (hServiceStatus == 0) 01637 { 01638 DPRINT("hServiceStatus == NULL!\n"); 01639 return ERROR_INVALID_HANDLE; 01640 } 01641 01642 lpService = (PSERVICE)hServiceStatus; 01643 if (lpService == NULL) 01644 { 01645 DPRINT("lpService == NULL!\n"); 01646 return ERROR_INVALID_HANDLE; 01647 } 01648 01649 /* Check current state */ 01650 if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState)) 01651 { 01652 DPRINT("Invalid service state!\n"); 01653 return ERROR_INVALID_DATA; 01654 } 01655 01656 /* Check service type */ 01657 if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) && 01658 (lpServiceStatus->dwServiceType & SERVICE_DRIVER)) 01659 { 01660 DPRINT("Invalid service type!\n"); 01661 return ERROR_INVALID_DATA; 01662 } 01663 01664 /* Check accepted controls */ 01665 if (lpServiceStatus->dwControlsAccepted & ~0xFF) 01666 { 01667 DPRINT("Invalid controls accepted!\n"); 01668 return ERROR_INVALID_DATA; 01669 } 01670 01671 /* Lock the service database exclusively */ 01672 ScmLockDatabaseExclusive(); 01673 01674 /* Save the current service state */ 01675 dwPreviousState = lpService->Status.dwCurrentState; 01676 01677 RtlCopyMemory(&lpService->Status, 01678 lpServiceStatus, 01679 sizeof(SERVICE_STATUS)); 01680 01681 /* Unlock the service database */ 01682 ScmUnlockDatabase(); 01683 01684 /* Log a failed service stop */ 01685 if ((lpServiceStatus->dwCurrentState == SERVICE_STOPPED) && 01686 (dwPreviousState != SERVICE_STOPPED)) 01687 { 01688 if (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS) 01689 { 01690 swprintf(szErrorBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode); 01691 lpErrorStrings[0] = lpService->lpDisplayName; 01692 lpErrorStrings[1] = szErrorBuffer; 01693 01694 ScmLogError(EVENT_SERVICE_EXIT_FAILED, 01695 2, 01696 lpErrorStrings); 01697 } 01698 } 01699 01700 DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState); 01701 DPRINT("RSetServiceStatus() done\n"); 01702 01703 return ERROR_SUCCESS; 01704 } 01705 01706 01707 /* Function 8 */ 01708 DWORD RUnlockServiceDatabase( 01709 LPSC_RPC_LOCK Lock) 01710 { 01711 UNIMPLEMENTED; 01712 return ERROR_SUCCESS; 01713 } 01714 01715 01716 /* Function 9 */ 01717 DWORD RNotifyBootConfigStatus( 01718 SVCCTL_HANDLEW lpMachineName, 01719 DWORD BootAcceptable) 01720 { 01721 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName, BootAcceptable); 01722 return ERROR_SUCCESS; 01723 01724 // UNIMPLEMENTED; 01725 // return ERROR_CALL_NOT_IMPLEMENTED; 01726 } 01727 01728 01729 /* Function 10 */ 01730 DWORD RI_ScSetServiceBitsW( 01731 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 01732 DWORD dwServiceBits, 01733 int bSetBitsOn, 01734 int bUpdateImmediately, 01735 wchar_t *lpString) 01736 { 01737 UNIMPLEMENTED; 01738 return ERROR_CALL_NOT_IMPLEMENTED; 01739 } 01740 01741 01742 /* Function 11 */ 01743 DWORD RChangeServiceConfigW( 01744 SC_RPC_HANDLE hService, 01745 DWORD dwServiceType, 01746 DWORD dwStartType, 01747 DWORD dwErrorControl, 01748 LPWSTR lpBinaryPathName, 01749 LPWSTR lpLoadOrderGroup, 01750 LPDWORD lpdwTagId, 01751 LPBYTE lpDependencies, 01752 DWORD dwDependSize, 01753 LPWSTR lpServiceStartName, 01754 LPBYTE lpPassword, 01755 DWORD dwPwSize, 01756 LPWSTR lpDisplayName) 01757 { 01758 DWORD dwError = ERROR_SUCCESS; 01759 PSERVICE_HANDLE hSvc; 01760 PSERVICE lpService = NULL; 01761 HKEY hServiceKey = NULL; 01762 LPWSTR lpDisplayNameW = NULL; 01763 LPWSTR lpImagePathW = NULL; 01764 01765 DPRINT("RChangeServiceConfigW() called\n"); 01766 DPRINT("dwServiceType = %lu\n", dwServiceType); 01767 DPRINT("dwStartType = %lu\n", dwStartType); 01768 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 01769 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 01770 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 01771 DPRINT("lpDisplayName = %S\n", lpDisplayName); 01772 01773 if (ScmShutdown) 01774 return ERROR_SHUTDOWN_IN_PROGRESS; 01775 01776 hSvc = ScmGetServiceFromHandle(hService); 01777 if (hSvc == NULL) 01778 { 01779 DPRINT1("Invalid service handle!\n"); 01780 return ERROR_INVALID_HANDLE; 01781 } 01782 01783 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 01784 SERVICE_CHANGE_CONFIG)) 01785 { 01786 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 01787 return ERROR_ACCESS_DENIED; 01788 } 01789 01790 lpService = hSvc->ServiceEntry; 01791 if (lpService == NULL) 01792 { 01793 DPRINT("lpService == NULL!\n"); 01794 return ERROR_INVALID_HANDLE; 01795 } 01796 01797 /* Lock the service database exclusively */ 01798 ScmLockDatabaseExclusive(); 01799 01800 if (lpService->bDeleted) 01801 { 01802 DPRINT("The service has already been marked for delete!\n"); 01803 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 01804 goto done; 01805 } 01806 01807 /* Open the service key */ 01808 dwError = ScmOpenServiceKey(lpService->szServiceName, 01809 KEY_SET_VALUE, 01810 &hServiceKey); 01811 if (dwError != ERROR_SUCCESS) 01812 goto done; 01813 01814 /* Write service data to the registry */ 01815 /* Set the display name */ 01816 if (lpDisplayName != NULL && *lpDisplayName != 0) 01817 { 01818 RegSetValueExW(hServiceKey, 01819 L"DisplayName", 01820 0, 01821 REG_SZ, 01822 (LPBYTE)lpDisplayName, 01823 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 01824 01825 /* Update the display name */ 01826 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 01827 0, 01828 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 01829 if (lpDisplayNameW == NULL) 01830 { 01831 dwError = ERROR_NOT_ENOUGH_MEMORY; 01832 goto done; 01833 } 01834 01835 if (lpService->lpDisplayName != lpService->lpServiceName) 01836 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 01837 01838 lpService->lpDisplayName = lpDisplayNameW; 01839 } 01840 01841 if (dwServiceType != SERVICE_NO_CHANGE) 01842 { 01843 /* Set the service type */ 01844 dwError = RegSetValueExW(hServiceKey, 01845 L"Type", 01846 0, 01847 REG_DWORD, 01848 (LPBYTE)&dwServiceType, 01849 sizeof(DWORD)); 01850 if (dwError != ERROR_SUCCESS) 01851 goto done; 01852 01853 lpService->Status.dwServiceType = dwServiceType; 01854 } 01855 01856 if (dwStartType != SERVICE_NO_CHANGE) 01857 { 01858 /* Set the start value */ 01859 dwError = RegSetValueExW(hServiceKey, 01860 L"Start", 01861 0, 01862 REG_DWORD, 01863 (LPBYTE)&dwStartType, 01864 sizeof(DWORD)); 01865 if (dwError != ERROR_SUCCESS) 01866 goto done; 01867 01868 lpService->dwStartType = dwStartType; 01869 } 01870 01871 if (dwErrorControl != SERVICE_NO_CHANGE) 01872 { 01873 /* Set the error control value */ 01874 dwError = RegSetValueExW(hServiceKey, 01875 L"ErrorControl", 01876 0, 01877 REG_DWORD, 01878 (LPBYTE)&dwErrorControl, 01879 sizeof(DWORD)); 01880 if (dwError != ERROR_SUCCESS) 01881 goto done; 01882 01883 lpService->dwErrorControl = dwErrorControl; 01884 } 01885 01886 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 01887 { 01888 /* Set the image path */ 01889 lpImagePathW = lpBinaryPathName; 01890 01891 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 01892 { 01893 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 01894 lpBinaryPathName, 01895 &lpImagePathW); 01896 01897 if (dwError != ERROR_SUCCESS) 01898 goto done; 01899 } 01900 01901 dwError = RegSetValueExW(hServiceKey, 01902 L"ImagePath", 01903 0, 01904 REG_EXPAND_SZ, 01905 (LPBYTE)lpImagePathW, 01906 (wcslen(lpImagePathW) + 1) * sizeof(WCHAR)); 01907 01908 if (lpImagePathW != lpBinaryPathName) 01909 HeapFree(GetProcessHeap(), 0, lpImagePathW); 01910 01911 if (dwError != ERROR_SUCCESS) 01912 goto done; 01913 } 01914 01915 /* Set the group name */ 01916 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 01917 { 01918 dwError = RegSetValueExW(hServiceKey, 01919 L"Group", 01920 0, 01921 REG_SZ, 01922 (LPBYTE)lpLoadOrderGroup, 01923 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); 01924 if (dwError != ERROR_SUCCESS) 01925 goto done; 01926 01927 dwError = ScmSetServiceGroup(lpService, 01928 lpLoadOrderGroup); 01929 if (dwError != ERROR_SUCCESS) 01930 goto done; 01931 } 01932 01933 if (lpdwTagId != NULL) 01934 { 01935 dwError = ScmAssignNewTag(lpService); 01936 if (dwError != ERROR_SUCCESS) 01937 goto done; 01938 01939 dwError = RegSetValueExW(hServiceKey, 01940 L"Tag", 01941 0, 01942 REG_DWORD, 01943 (LPBYTE)&lpService->dwTag, 01944 sizeof(DWORD)); 01945 if (dwError != ERROR_SUCCESS) 01946 goto done; 01947 01948 *lpdwTagId = lpService->dwTag; 01949 } 01950 01951 /* Write dependencies */ 01952 if (lpDependencies != NULL && *lpDependencies != 0) 01953 { 01954 dwError = ScmWriteDependencies(hServiceKey, 01955 (LPWSTR)lpDependencies, 01956 dwDependSize); 01957 if (dwError != ERROR_SUCCESS) 01958 goto done; 01959 } 01960 01961 if (lpPassword != NULL) 01962 { 01963 /* FIXME: Write password */ 01964 } 01965 01966 done: 01967 if (hServiceKey != NULL) 01968 RegCloseKey(hServiceKey); 01969 01970 /* Unlock the service database */ 01971 ScmUnlockDatabase(); 01972 01973 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError); 01974 01975 return dwError; 01976 } 01977 01978 01979 /* Function 12 */ 01980 DWORD RCreateServiceW( 01981 SC_RPC_HANDLE hSCManager, 01982 LPCWSTR lpServiceName, 01983 LPCWSTR lpDisplayName, 01984 DWORD dwDesiredAccess, 01985 DWORD dwServiceType, 01986 DWORD dwStartType, 01987 DWORD dwErrorControl, 01988 LPCWSTR lpBinaryPathName, 01989 LPCWSTR lpLoadOrderGroup, 01990 LPDWORD lpdwTagId, 01991 LPBYTE lpDependencies, 01992 DWORD dwDependSize, 01993 LPCWSTR lpServiceStartName, 01994 LPBYTE lpPassword, 01995 DWORD dwPwSize, 01996 LPSC_RPC_HANDLE lpServiceHandle) 01997 { 01998 PMANAGER_HANDLE hManager; 01999 DWORD dwError = ERROR_SUCCESS; 02000 PSERVICE lpService = NULL; 02001 SC_HANDLE hServiceHandle = NULL; 02002 LPWSTR lpImagePath = NULL; 02003 HKEY hServiceKey = NULL; 02004 LPWSTR lpObjectName; 02005 02006 DPRINT("RCreateServiceW() called\n"); 02007 DPRINT("lpServiceName = %S\n", lpServiceName); 02008 DPRINT("lpDisplayName = %S\n", lpDisplayName); 02009 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess); 02010 DPRINT("dwServiceType = %lu\n", dwServiceType); 02011 DPRINT("dwStartType = %lu\n", dwStartType); 02012 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 02013 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); 02014 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); 02015 DPRINT("lpdwTagId = %p\n", lpdwTagId); 02016 02017 if (ScmShutdown) 02018 return ERROR_SHUTDOWN_IN_PROGRESS; 02019 02020 hManager = ScmGetServiceManagerFromHandle(hSCManager); 02021 if (hManager == NULL) 02022 { 02023 DPRINT1("Invalid service manager handle!\n"); 02024 return ERROR_INVALID_HANDLE; 02025 } 02026 02027 /* Check access rights */ 02028 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 02029 SC_MANAGER_CREATE_SERVICE)) 02030 { 02031 DPRINT("Insufficient access rights! 0x%lx\n", 02032 hManager->Handle.DesiredAccess); 02033 return ERROR_ACCESS_DENIED; 02034 } 02035 02036 if (wcslen(lpServiceName) == 0) 02037 { 02038 return ERROR_INVALID_NAME; 02039 } 02040 02041 if (wcslen(lpBinaryPathName) == 0) 02042 { 02043 return ERROR_INVALID_PARAMETER; 02044 } 02045 02046 /* Check for invalid service type value */ 02047 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 02048 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER) && 02049 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_OWN_PROCESS) && 02050 ((dwServiceType & ~SERVICE_INTERACTIVE_PROCESS) != SERVICE_WIN32_SHARE_PROCESS)) 02051 return ERROR_INVALID_PARAMETER; 02052 02053 /* Check for invalid start type value */ 02054 if ((dwStartType != SERVICE_BOOT_START) && 02055 (dwStartType != SERVICE_SYSTEM_START) && 02056 (dwStartType != SERVICE_AUTO_START) && 02057 (dwStartType != SERVICE_DEMAND_START) && 02058 (dwStartType != SERVICE_DISABLED)) 02059 return ERROR_INVALID_PARAMETER; 02060 02061 /* Only drivers can be boot start or system start services */ 02062 if ((dwStartType == SERVICE_BOOT_START) || 02063 (dwStartType == SERVICE_SYSTEM_START)) 02064 { 02065 if ((dwServiceType != SERVICE_KERNEL_DRIVER) && 02066 (dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)) 02067 return ERROR_INVALID_PARAMETER; 02068 } 02069 02070 /* Check for invalid error control value */ 02071 if ((dwErrorControl != SERVICE_ERROR_IGNORE) && 02072 (dwErrorControl != SERVICE_ERROR_NORMAL) && 02073 (dwErrorControl != SERVICE_ERROR_SEVERE) && 02074 (dwErrorControl != SERVICE_ERROR_CRITICAL)) 02075 return ERROR_INVALID_PARAMETER; 02076 02077 if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) && 02078 (lpServiceStartName)) 02079 { 02080 return ERROR_INVALID_PARAMETER; 02081 } 02082 02083 if (lpdwTagId && (!lpLoadOrderGroup || !*lpLoadOrderGroup)) 02084 { 02085 return ERROR_INVALID_PARAMETER; 02086 } 02087 02088 /* Lock the service database exclusively */ 02089 ScmLockDatabaseExclusive(); 02090 02091 lpService = ScmGetServiceEntryByName(lpServiceName); 02092 if (lpService) 02093 { 02094 /* Unlock the service database */ 02095 ScmUnlockDatabase(); 02096 02097 /* Check if it is marked for deletion */ 02098 if (lpService->bDeleted) 02099 return ERROR_SERVICE_MARKED_FOR_DELETE; 02100 02101 /* Return Error exist */ 02102 return ERROR_SERVICE_EXISTS; 02103 } 02104 02105 if (lpDisplayName != NULL && 02106 ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL) 02107 { 02108 /* Unlock the service database */ 02109 ScmUnlockDatabase(); 02110 02111 return ERROR_DUPLICATE_SERVICE_NAME; 02112 } 02113 02114 if (dwServiceType & SERVICE_DRIVER) 02115 { 02116 dwError = ScmCanonDriverImagePath(dwStartType, 02117 lpBinaryPathName, 02118 &lpImagePath); 02119 if (dwError != ERROR_SUCCESS) 02120 goto done; 02121 } 02122 else 02123 { 02124 if (dwStartType == SERVICE_BOOT_START || 02125 dwStartType == SERVICE_SYSTEM_START) 02126 { 02127 /* Unlock the service database */ 02128 ScmUnlockDatabase(); 02129 02130 return ERROR_INVALID_PARAMETER; 02131 } 02132 } 02133 02134 /* Allocate a new service entry */ 02135 dwError = ScmCreateNewServiceRecord(lpServiceName, 02136 &lpService); 02137 if (dwError != ERROR_SUCCESS) 02138 goto done; 02139 02140 /* Fill the new service entry */ 02141 lpService->Status.dwServiceType = dwServiceType; 02142 lpService->dwStartType = dwStartType; 02143 lpService->dwErrorControl = dwErrorControl; 02144 02145 /* Fill the display name */ 02146 if (lpDisplayName != NULL && 02147 *lpDisplayName != 0 && 02148 _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0) 02149 { 02150 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 0, 02151 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 02152 if (lpService->lpDisplayName == NULL) 02153 { 02154 dwError = ERROR_NOT_ENOUGH_MEMORY; 02155 goto done; 02156 } 02157 wcscpy(lpService->lpDisplayName, lpDisplayName); 02158 } 02159 02160 /* Assign the service to a group */ 02161 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 02162 { 02163 dwError = ScmSetServiceGroup(lpService, 02164 lpLoadOrderGroup); 02165 if (dwError != ERROR_SUCCESS) 02166 goto done; 02167 } 02168 02169 /* Assign a new tag */ 02170 if (lpdwTagId != NULL) 02171 { 02172 dwError = ScmAssignNewTag(lpService); 02173 if (dwError != ERROR_SUCCESS) 02174 goto done; 02175 } 02176 02177 /* Write service data to the registry */ 02178 /* Create the service key */ 02179 dwError = ScmCreateServiceKey(lpServiceName, 02180 KEY_WRITE, 02181 &hServiceKey); 02182 if (dwError != ERROR_SUCCESS) 02183 goto done; 02184 02185 /* Set the display name */ 02186 if (lpDisplayName != NULL && *lpDisplayName != 0) 02187 { 02188 RegSetValueExW(hServiceKey, 02189 L"DisplayName", 02190 0, 02191 REG_SZ, 02192 (LPBYTE)lpDisplayName, 02193 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); 02194 } 02195 02196 /* Set the service type */ 02197 dwError = RegSetValueExW(hServiceKey, 02198 L"Type", 02199 0, 02200 REG_DWORD, 02201 (LPBYTE)&dwServiceType, 02202 sizeof(DWORD)); 02203 if (dwError != ERROR_SUCCESS) 02204 goto done; 02205 02206 /* Set the start value */ 02207 dwError = RegSetValueExW(hServiceKey, 02208 L"Start", 02209 0, 02210 REG_DWORD, 02211 (LPBYTE)&dwStartType, 02212 sizeof(DWORD)); 02213 if (dwError != ERROR_SUCCESS) 02214 goto done; 02215 02216 /* Set the error control value */ 02217 dwError = RegSetValueExW(hServiceKey, 02218 L"ErrorControl", 02219 0, 02220 REG_DWORD, 02221 (LPBYTE)&dwErrorControl, 02222 sizeof(DWORD)); 02223 if (dwError != ERROR_SUCCESS) 02224 goto done; 02225 02226 /* Set the image path */ 02227 if (dwServiceType & SERVICE_WIN32) 02228 { 02229 dwError = RegSetValueExW(hServiceKey, 02230 L"ImagePath", 02231 0, 02232 REG_EXPAND_SZ, 02233 (LPBYTE)lpBinaryPathName, 02234 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR)); 02235 if (dwError != ERROR_SUCCESS) 02236 goto done; 02237 } 02238 else if (dwServiceType & SERVICE_DRIVER) 02239 { 02240 dwError = RegSetValueExW(hServiceKey, 02241 L"ImagePath", 02242 0, 02243 REG_EXPAND_SZ, 02244 (LPBYTE)lpImagePath, 02245 (wcslen(lpImagePath) + 1) * sizeof(WCHAR)); 02246 if (dwError != ERROR_SUCCESS) 02247 goto done; 02248 } 02249 02250 /* Set the group name */ 02251 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 02252 { 02253 dwError = RegSetValueExW(hServiceKey, 02254 L"Group", 02255 0, 02256 REG_SZ, 02257 (LPBYTE)lpLoadOrderGroup, 02258 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); 02259 if (dwError != ERROR_SUCCESS) 02260 goto done; 02261 } 02262 02263 if (lpdwTagId != NULL) 02264 { 02265 dwError = RegSetValueExW(hServiceKey, 02266 L"Tag", 02267 0, 02268 REG_DWORD, 02269 (LPBYTE)&lpService->dwTag, 02270 sizeof(DWORD)); 02271 if (dwError != ERROR_SUCCESS) 02272 goto done; 02273 } 02274 02275 /* Write dependencies */ 02276 if (lpDependencies != NULL && *lpDependencies != 0) 02277 { 02278 dwError = ScmWriteDependencies(hServiceKey, 02279 (LPCWSTR)lpDependencies, 02280 dwDependSize); 02281 if (dwError != ERROR_SUCCESS) 02282 goto done; 02283 } 02284 02285 /* Write service start name */ 02286 if (dwServiceType & SERVICE_WIN32) 02287 { 02288 lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem"; 02289 dwError = RegSetValueExW(hServiceKey, 02290 L"ObjectName", 02291 0, 02292 REG_SZ, 02293 (LPBYTE)lpObjectName, 02294 (wcslen(lpObjectName) + 1) * sizeof(WCHAR)); 02295 if (dwError != ERROR_SUCCESS) 02296 goto done; 02297 } 02298 02299 if (lpPassword != NULL) 02300 { 02301 /* FIXME: Write password */ 02302 } 02303 02304 dwError = ScmCreateServiceHandle(lpService, 02305 &hServiceHandle); 02306 if (dwError != ERROR_SUCCESS) 02307 goto done; 02308 02309 dwError = ScmCheckAccess(hServiceHandle, 02310 dwDesiredAccess); 02311 if (dwError != ERROR_SUCCESS) 02312 goto done; 02313 02314 lpService->dwRefCount = 1; 02315 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount); 02316 02317 done:; 02318 /* Unlock the service database */ 02319 ScmUnlockDatabase(); 02320 02321 if (hServiceKey != NULL) 02322 RegCloseKey(hServiceKey); 02323 02324 if (dwError == ERROR_SUCCESS) 02325 { 02326 DPRINT("hService %p\n", hServiceHandle); 02327 *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle; 02328 02329 if (lpdwTagId != NULL) 02330 *lpdwTagId = lpService->dwTag; 02331 } 02332 else 02333 { 02334 if (lpService != NULL && 02335 lpService->lpServiceName != NULL) 02336 { 02337 /* Release the display name buffer */ 02338 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 02339 } 02340 02341 if (hServiceHandle) 02342 { 02343 /* Remove the service handle */ 02344 HeapFree(GetProcessHeap(), 0, hServiceHandle); 02345 } 02346 02347 if (lpService != NULL) 02348 { 02349 /* FIXME: remove the service entry */ 02350 } 02351 } 02352 02353 if (lpImagePath != NULL) 02354 HeapFree(GetProcessHeap(), 0, lpImagePath); 02355 02356 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError); 02357 02358 return dwError; 02359 } 02360 02361 02362 /* Function 13 */ 02363 DWORD REnumDependentServicesW( 02364 SC_RPC_HANDLE hService, 02365 DWORD dwServiceState, 02366 LPBYTE lpServices, 02367 DWORD cbBufSize, 02368 LPBOUNDED_DWORD_256K pcbBytesNeeded, 02369 LPBOUNDED_DWORD_256K lpServicesReturned) 02370 { 02371 DWORD dwError = ERROR_SUCCESS; 02372 DWORD dwServicesReturned = 0; 02373 DWORD dwServiceCount; 02374 HKEY hServicesKey = NULL; 02375 PSERVICE_HANDLE hSvc; 02376 PSERVICE lpService = NULL; 02377 PSERVICE *lpServicesArray = NULL; 02378 LPENUM_SERVICE_STATUSW lpServicesPtr = NULL; 02379 LPWSTR lpStr; 02380 02381 *pcbBytesNeeded = 0; 02382 *lpServicesReturned = 0; 02383 02384 DPRINT("REnumDependentServicesW() called\n"); 02385 02386 hSvc = ScmGetServiceFromHandle(hService); 02387 if (hSvc == NULL) 02388 { 02389 DPRINT1("Invalid service handle!\n"); 02390 return ERROR_INVALID_HANDLE; 02391 } 02392 02393 lpService = hSvc->ServiceEntry; 02394 02395 /* Check access rights */ 02396 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 02397 SC_MANAGER_ENUMERATE_SERVICE)) 02398 { 02399 DPRINT("Insufficient access rights! 0x%lx\n", 02400 hSvc->Handle.DesiredAccess); 02401 return ERROR_ACCESS_DENIED; 02402 } 02403 02404 /* Open the Services Reg key */ 02405 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 02406 L"System\\CurrentControlSet\\Services", 02407 0, 02408 KEY_READ, 02409 &hServicesKey); 02410 if (dwError != ERROR_SUCCESS) 02411 return dwError; 02412 02413 /* First determine the bytes needed and get the number of dependent services */ 02414 dwError = Int_EnumDependentServicesW(hServicesKey, 02415 lpService, 02416 dwServiceState, 02417 NULL, 02418 pcbBytesNeeded, 02419 &dwServicesReturned); 02420 if (dwError != ERROR_SUCCESS) 02421 goto Done; 02422 02423 /* If buffer size is less than the bytes needed or pointer is null */ 02424 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 02425 { 02426 dwError = ERROR_MORE_DATA; 02427 goto Done; 02428 } 02429 02430 /* Allocate memory for array of service pointers */ 02431 lpServicesArray = HeapAlloc(GetProcessHeap(), 02432 0, 02433 (dwServicesReturned + 1) * sizeof(PSERVICE)); 02434 if (!lpServicesArray) 02435 { 02436 DPRINT1("Could not allocate a buffer!!\n"); 02437 dwError = ERROR_NOT_ENOUGH_MEMORY; 02438 goto Done; 02439 } 02440 02441 dwServicesReturned = 0; 02442 *pcbBytesNeeded = 0; 02443 02444 dwError = Int_EnumDependentServicesW(hServicesKey, 02445 lpService, 02446 dwServiceState, 02447 lpServicesArray, 02448 pcbBytesNeeded, 02449 &dwServicesReturned); 02450 if (dwError != ERROR_SUCCESS) 02451 { 02452 goto Done; 02453 } 02454 02455 lpServicesPtr = (LPENUM_SERVICE_STATUSW) lpServices; 02456 lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW))); 02457 02458 /* Copy EnumDepenedentService to Buffer */ 02459 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 02460 { 02461 lpService = lpServicesArray[dwServiceCount]; 02462 02463 /* Copy status info */ 02464 memcpy(&lpServicesPtr->ServiceStatus, 02465 &lpService->Status, 02466 sizeof(SERVICE_STATUS)); 02467 02468 /* Copy display name */ 02469 wcscpy(lpStr, lpService->lpDisplayName); 02470 lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 02471 lpStr += (wcslen(lpService->lpDisplayName) + 1); 02472 02473 /* Copy service name */ 02474 wcscpy(lpStr, lpService->lpServiceName); 02475 lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 02476 lpStr += (wcslen(lpService->lpServiceName) + 1); 02477 02478 lpServicesPtr ++; 02479 } 02480 02481 *lpServicesReturned = dwServicesReturned; 02482 02483 Done: 02484 if (lpServicesArray != NULL) 02485 HeapFree(GetProcessHeap(), 0, lpServicesArray); 02486 02487 RegCloseKey(hServicesKey); 02488 02489 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError); 02490 02491 return dwError; 02492 } 02493 02494 02495 /* Function 14 */ 02496 DWORD REnumServicesStatusW( 02497 SC_RPC_HANDLE hSCManager, 02498 DWORD dwServiceType, 02499 DWORD dwServiceState, 02500 LPBYTE lpBuffer, 02501 DWORD dwBufSize, 02502 LPBOUNDED_DWORD_256K pcbBytesNeeded, 02503 LPBOUNDED_DWORD_256K lpServicesReturned, 02504 LPBOUNDED_DWORD_256K lpResumeHandle) 02505 { 02506 PMANAGER_HANDLE hManager; 02507 PSERVICE lpService; 02508 DWORD dwError = ERROR_SUCCESS; 02509 PLIST_ENTRY ServiceEntry; 02510 PSERVICE CurrentService; 02511 DWORD dwState; 02512 DWORD dwRequiredSize; 02513 DWORD dwServiceCount; 02514 DWORD dwSize; 02515 DWORD dwLastResumeCount = 0; 02516 LPENUM_SERVICE_STATUSW lpStatusPtr; 02517 LPWSTR lpStringPtr; 02518 02519 DPRINT("REnumServicesStatusW() called\n"); 02520 02521 if (ScmShutdown) 02522 return ERROR_SHUTDOWN_IN_PROGRESS; 02523 02524 hManager = ScmGetServiceManagerFromHandle(hSCManager); 02525 if (hManager == NULL) 02526 { 02527 DPRINT1("Invalid service manager handle!\n"); 02528 return ERROR_INVALID_HANDLE; 02529 } 02530 02531 02532 *pcbBytesNeeded = 0; 02533 *lpServicesReturned = 0; 02534 02535 if ((dwServiceType == 0) || 02536 ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0)) 02537 { 02538 DPRINT("Not a valid Service Type!\n"); 02539 return ERROR_INVALID_PARAMETER; 02540 } 02541 02542 if ((dwServiceState != SERVICE_ACTIVE) && 02543 (dwServiceState != SERVICE_INACTIVE) && 02544 (dwServiceState != SERVICE_STATE_ALL)) 02545 { 02546 DPRINT("Not a valid Service State!\n"); 02547 return ERROR_INVALID_PARAMETER; 02548 } 02549 02550 /* Check access rights */ 02551 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 02552 SC_MANAGER_ENUMERATE_SERVICE)) 02553 { 02554 DPRINT("Insufficient access rights! 0x%lx\n", 02555 hManager->Handle.DesiredAccess); 02556 return ERROR_ACCESS_DENIED; 02557 } 02558 02559 if (lpResumeHandle) 02560 dwLastResumeCount = *lpResumeHandle; 02561 02562 /* Lock the service database shared */ 02563 ScmLockDatabaseShared(); 02564 02565 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 02566 if (lpService == NULL) 02567 { 02568 dwError = ERROR_SUCCESS; 02569 goto Done; 02570 } 02571 02572 dwRequiredSize = 0; 02573 dwServiceCount = 0; 02574 02575 for (ServiceEntry = &lpService->ServiceListEntry; 02576 ServiceEntry != &ServiceListHead; 02577 ServiceEntry = ServiceEntry->Flink) 02578 { 02579 CurrentService = CONTAINING_RECORD(ServiceEntry, 02580 SERVICE, 02581 ServiceListEntry); 02582 02583 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 02584 continue; 02585 02586 dwState = SERVICE_ACTIVE; 02587 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 02588 dwState = SERVICE_INACTIVE; 02589 02590 if ((dwState & dwServiceState) == 0) 02591 continue; 02592 02593 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 02594 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 02595 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 02596 02597 if (dwRequiredSize + dwSize > dwBufSize) 02598 { 02599 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 02600 break; 02601 } 02602 02603 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 02604 dwRequiredSize += dwSize; 02605 dwServiceCount++; 02606 dwLastResumeCount = CurrentService->dwResumeCount; 02607 } 02608 02609 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 02610 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 02611 02612 for (; 02613 ServiceEntry != &ServiceListHead; 02614 ServiceEntry = ServiceEntry->Flink) 02615 { 02616 CurrentService = CONTAINING_RECORD(ServiceEntry, 02617 SERVICE, 02618 ServiceListEntry); 02619 02620 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 02621 continue; 02622 02623 dwState = SERVICE_ACTIVE; 02624 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 02625 dwState = SERVICE_INACTIVE; 02626 02627 if ((dwState & dwServiceState) == 0) 02628 continue; 02629 02630 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) + 02631 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 02632 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 02633 02634 dwError = ERROR_MORE_DATA; 02635 } 02636 02637 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 02638 02639 if (lpResumeHandle) 02640 *lpResumeHandle = dwLastResumeCount; 02641 02642 *lpServicesReturned = dwServiceCount; 02643 *pcbBytesNeeded = dwRequiredSize; 02644 02645 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer; 02646 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 02647 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW)); 02648 02649 dwRequiredSize = 0; 02650 for (ServiceEntry = &lpService->ServiceListEntry; 02651 ServiceEntry != &ServiceListHead; 02652 ServiceEntry = ServiceEntry->Flink) 02653 { 02654 CurrentService = CONTAINING_RECORD(ServiceEntry, 02655 SERVICE, 02656 ServiceListEntry); 02657 02658 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 02659 continue; 02660 02661 dwState = SERVICE_ACTIVE; 02662 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 02663 dwState = SERVICE_INACTIVE; 02664 02665 if ((dwState & dwServiceState) == 0) 02666 continue; 02667 02668 dwSize = sizeof(ENUM_SERVICE_STATUSW) + 02669 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 02670 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 02671 02672 if (dwRequiredSize + dwSize > dwBufSize) 02673 break; 02674 02675 /* Copy the service name */ 02676 wcscpy(lpStringPtr, CurrentService->lpServiceName); 02677 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 02678 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 02679 02680 /* Copy the display name */ 02681 wcscpy(lpStringPtr, CurrentService->lpDisplayName); 02682 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 02683 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 02684 02685 /* Copy the status information */ 02686 memcpy(&lpStatusPtr->ServiceStatus, 02687 &CurrentService->Status, 02688 sizeof(SERVICE_STATUS)); 02689 02690 lpStatusPtr++; 02691 dwRequiredSize += dwSize; 02692 } 02693 02694 if (dwError == ERROR_SUCCESS) 02695 { 02696 *pcbBytesNeeded = 0; 02697 if (lpResumeHandle) *lpResumeHandle = 0; 02698 } 02699 02700 Done:; 02701 /* Unlock the service database */ 02702 ScmUnlockDatabase(); 02703 02704 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError); 02705 02706 return dwError; 02707 } 02708 02709 02710 /* Function 15 */ 02711 DWORD ROpenSCManagerW( 02712 LPWSTR lpMachineName, 02713 LPWSTR lpDatabaseName, 02714 DWORD dwDesiredAccess, 02715 LPSC_RPC_HANDLE lpScHandle) 02716 { 02717 DWORD dwError; 02718 SC_HANDLE hHandle; 02719 02720 DPRINT("ROpenSCManagerW() called\n"); 02721 DPRINT("lpMachineName = %p\n", lpMachineName); 02722 DPRINT("lpMachineName: %S\n", lpMachineName); 02723 DPRINT("lpDataBaseName = %p\n", lpDatabaseName); 02724 DPRINT("lpDataBaseName: %S\n", lpDatabaseName); 02725 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 02726 02727 if (ScmShutdown) 02728 return ERROR_SHUTDOWN_IN_PROGRESS; 02729 02730 if (!lpScHandle) 02731 return ERROR_INVALID_PARAMETER; 02732 02733 dwError = ScmCreateManagerHandle(lpDatabaseName, 02734 &hHandle); 02735 if (dwError != ERROR_SUCCESS) 02736 { 02737 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError); 02738 return dwError; 02739 } 02740 02741 /* Check the desired access */ 02742 dwError = ScmCheckAccess(hHandle, 02743 dwDesiredAccess | SC_MANAGER_CONNECT); 02744 if (dwError != ERROR_SUCCESS) 02745 { 02746 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 02747 HeapFree(GetProcessHeap(), 0, hHandle); 02748 return dwError; 02749 } 02750 02751 *lpScHandle = (SC_RPC_HANDLE)hHandle; 02752 DPRINT("*hScm = %p\n", *lpScHandle); 02753 02754 DPRINT("ROpenSCManagerW() done\n"); 02755 02756 return ERROR_SUCCESS; 02757 } 02758 02759 02760 /* Function 16 */ 02761 DWORD ROpenServiceW( 02762 SC_RPC_HANDLE hSCManager, 02763 LPWSTR lpServiceName, 02764 DWORD dwDesiredAccess, 02765 LPSC_RPC_HANDLE lpServiceHandle) 02766 { 02767 PSERVICE lpService; 02768 PMANAGER_HANDLE hManager; 02769 SC_HANDLE hHandle; 02770 DWORD dwError = ERROR_SUCCESS; 02771 02772 DPRINT("ROpenServiceW() called\n"); 02773 DPRINT("hSCManager = %p\n", hSCManager); 02774 DPRINT("lpServiceName = %p\n", lpServiceName); 02775 DPRINT("lpServiceName: %S\n", lpServiceName); 02776 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); 02777 02778 if (ScmShutdown) 02779 return ERROR_SHUTDOWN_IN_PROGRESS; 02780 02781 hManager = ScmGetServiceManagerFromHandle(hSCManager); 02782 if (hManager == NULL) 02783 { 02784 DPRINT1("Invalid service manager handle!\n"); 02785 return ERROR_INVALID_HANDLE; 02786 } 02787 02788 if (!lpServiceHandle) 02789 return ERROR_INVALID_PARAMETER; 02790 02791 if (!lpServiceName) 02792 return ERROR_INVALID_ADDRESS; 02793 02794 /* Lock the service database exclusive */ 02795 ScmLockDatabaseExclusive(); 02796 02797 /* Get service database entry */ 02798 lpService = ScmGetServiceEntryByName(lpServiceName); 02799 if (lpService == NULL) 02800 { 02801 DPRINT("Could not find a service!\n"); 02802 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 02803 goto Done; 02804 } 02805 02806 /* Create a service handle */ 02807 dwError = ScmCreateServiceHandle(lpService, 02808 &hHandle); 02809 if (dwError != ERROR_SUCCESS) 02810 { 02811 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError); 02812 goto Done; 02813 } 02814 02815 /* Check the desired access */ 02816 dwError = ScmCheckAccess(hHandle, 02817 dwDesiredAccess); 02818 if (dwError != ERROR_SUCCESS) 02819 { 02820 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError); 02821 HeapFree(GetProcessHeap(), 0, hHandle); 02822 goto Done; 02823 } 02824 02825 lpService->dwRefCount++; 02826 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount); 02827 02828 *lpServiceHandle = (SC_RPC_HANDLE)hHandle; 02829 DPRINT("*hService = %p\n", *lpServiceHandle); 02830 02831 Done:; 02832 /* Unlock the service database */ 02833 ScmUnlockDatabase(); 02834 02835 DPRINT("ROpenServiceW() done\n"); 02836 02837 return dwError; 02838 } 02839 02840 02841 /* Function 17 */ 02842 DWORD RQueryServiceConfigW( 02843 SC_RPC_HANDLE hService, 02844 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig, 02845 DWORD cbBufSize, 02846 LPBOUNDED_DWORD_8K pcbBytesNeeded) 02847 { 02848 LPQUERY_SERVICE_CONFIGW lpServiceConfig = (LPQUERY_SERVICE_CONFIGW)lpBuf; 02849 DWORD dwError = ERROR_SUCCESS; 02850 PSERVICE_HANDLE hSvc; 02851 PSERVICE lpService = NULL; 02852 HKEY hServiceKey = NULL; 02853 LPWSTR lpImagePath = NULL; 02854 LPWSTR lpServiceStartName = NULL; 02855 LPWSTR lpDependencies = NULL; 02856 DWORD dwDependenciesLength = 0; 02857 DWORD dwRequiredSize; 02858 LPQUERY_SERVICE_CONFIGW lpConfig = NULL; 02859 WCHAR lpEmptyString[] = {0,0}; 02860 LPWSTR lpStr; 02861 02862 DPRINT("RQueryServiceConfigW() called\n"); 02863 02864 if (ScmShutdown) 02865 return ERROR_SHUTDOWN_IN_PROGRESS; 02866 02867 hSvc = ScmGetServiceFromHandle(hService); 02868 if (hSvc == NULL) 02869 { 02870 DPRINT1("Invalid service handle!\n"); 02871 return ERROR_INVALID_HANDLE; 02872 } 02873 02874 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 02875 SERVICE_QUERY_CONFIG)) 02876 { 02877 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 02878 return ERROR_ACCESS_DENIED; 02879 } 02880 02881 lpService = hSvc->ServiceEntry; 02882 if (lpService == NULL) 02883 { 02884 DPRINT("lpService == NULL!\n"); 02885 return ERROR_INVALID_HANDLE; 02886 } 02887 02888 /* Lock the service database shared */ 02889 ScmLockDatabaseShared(); 02890 02891 dwError = ScmOpenServiceKey(lpService->lpServiceName, 02892 KEY_READ, 02893 &hServiceKey); 02894 if (dwError != ERROR_SUCCESS) 02895 goto Done; 02896 02897 /* Read the image path */ 02898 dwError = ScmReadString(hServiceKey, 02899 L"ImagePath", 02900 &lpImagePath); 02901 if (dwError != ERROR_SUCCESS) 02902 goto Done; 02903 02904 /* Read the service start name */ 02905 ScmReadString(hServiceKey, 02906 L"ObjectName", 02907 &lpServiceStartName); 02908 02909 /* Read the dependencies */ 02910 ScmReadDependencies(hServiceKey, 02911 &lpDependencies, 02912 &dwDependenciesLength); 02913 02914 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW); 02915 02916 if (lpImagePath != NULL) 02917 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR)); 02918 else 02919 dwRequiredSize += 2 * sizeof(WCHAR); 02920 02921 if (lpService->lpGroup != NULL) 02922 dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR)); 02923 else 02924 dwRequiredSize += 2 * sizeof(WCHAR); 02925 02926 if (lpDependencies != NULL) 02927 dwRequiredSize += dwDependenciesLength * sizeof(WCHAR); 02928 else 02929 dwRequiredSize += 2 * sizeof(WCHAR); 02930 02931 if (lpServiceStartName != NULL) 02932 dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR)); 02933 else 02934 dwRequiredSize += 2 * sizeof(WCHAR); 02935 02936 if (lpService->lpDisplayName != NULL) 02937 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR)); 02938 else 02939 dwRequiredSize += 2 * sizeof(WCHAR); 02940 02941 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 02942 { 02943 dwError = ERROR_INSUFFICIENT_BUFFER; 02944 } 02945 else 02946 { 02947 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig; 02948 lpConfig->dwServiceType = lpService->Status.dwServiceType; 02949 lpConfig->dwStartType = lpService->dwStartType; 02950 lpConfig->dwErrorControl = lpService->dwErrorControl; 02951 lpConfig->dwTagId = lpService->dwTag; 02952 02953 lpStr = (LPWSTR)(lpConfig + 1); 02954 02955 /* Append the image path */ 02956 if (lpImagePath != NULL) 02957 { 02958 wcscpy(lpStr, lpImagePath); 02959 } 02960 else 02961 { 02962 wcscpy(lpStr, lpEmptyString); 02963 } 02964 02965 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 02966 lpStr += (wcslen(lpStr) + 1); 02967 02968 /* Append the group name */ 02969 if (lpService->lpGroup != NULL) 02970 { 02971 wcscpy(lpStr, lpService->lpGroup->lpGroupName); 02972 } 02973 else 02974 { 02975 wcscpy(lpStr, lpEmptyString); 02976 } 02977 02978 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 02979 lpStr += (wcslen(lpStr) + 1); 02980 02981 /* Append Dependencies */ 02982 if (lpDependencies != NULL) 02983 { 02984 memcpy(lpStr, 02985 lpDependencies, 02986 dwDependenciesLength * sizeof(WCHAR)); 02987 } 02988 else 02989 { 02990 wcscpy(lpStr, lpEmptyString); 02991 } 02992 02993 lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 02994 if (lpDependencies != NULL) 02995 lpStr += dwDependenciesLength * sizeof(WCHAR); 02996 else 02997 lpStr += (wcslen(lpStr) + 1); 02998 02999 /* Append the service start name */ 03000 if (lpServiceStartName != NULL) 03001 { 03002 wcscpy(lpStr, lpServiceStartName); 03003 } 03004 else 03005 { 03006 wcscpy(lpStr, lpEmptyString); 03007 } 03008 03009 lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 03010 lpStr += (wcslen(lpStr) + 1); 03011 03012 /* Append the display name */ 03013 if (lpService->lpDisplayName != NULL) 03014 { 03015 wcscpy(lpStr, lpService->lpDisplayName); 03016 } 03017 else 03018 { 03019 wcscpy(lpStr, lpEmptyString); 03020 } 03021 03022 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 03023 } 03024 03025 if (pcbBytesNeeded != NULL) 03026 *pcbBytesNeeded = dwRequiredSize; 03027 03028 Done:; 03029 /* Unlock the service database */ 03030 ScmUnlockDatabase(); 03031 03032 if (lpImagePath != NULL) 03033 HeapFree(GetProcessHeap(), 0, lpImagePath); 03034 03035 if (lpServiceStartName != NULL) 03036 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 03037 03038 if (lpDependencies != NULL) 03039 HeapFree(GetProcessHeap(), 0, lpDependencies); 03040 03041 if (hServiceKey != NULL) 03042 RegCloseKey(hServiceKey); 03043 03044 DPRINT("RQueryServiceConfigW() done\n"); 03045 03046 return dwError; 03047 } 03048 03049 03050 /* Function 18 */ 03051 DWORD RQueryServiceLockStatusW( 03052 SC_RPC_HANDLE hSCManager, 03053 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, 03054 DWORD cbBufSize, 03055 LPBOUNDED_DWORD_4K pcbBytesNeeded) 03056 { 03057 UNIMPLEMENTED; 03058 return ERROR_CALL_NOT_IMPLEMENTED; 03059 } 03060 03061 03062 /* Function 19 */ 03063 DWORD RStartServiceW( 03064 SC_RPC_HANDLE hService, 03065 DWORD argc, 03066 LPSTRING_PTRSW argv) 03067 { 03068 DWORD dwError = ERROR_SUCCESS; 03069 PSERVICE_HANDLE hSvc; 03070 PSERVICE lpService = NULL; 03071 DWORD i; 03072 03073 DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv); 03074 DPRINT(" argc: %lu\n", argc); 03075 if (argv != NULL) 03076 { 03077 for (i = 0; i < argc; i++) 03078 { 03079 DPRINT(" argv[%lu]: %S\n", i, argv[i]); 03080 } 03081 } 03082 03083 if (ScmShutdown) 03084 return ERROR_SHUTDOWN_IN_PROGRESS; 03085 03086 hSvc = ScmGetServiceFromHandle(hService); 03087 if (hSvc == NULL) 03088 { 03089 DPRINT1("Invalid service handle!\n"); 03090 return ERROR_INVALID_HANDLE; 03091 } 03092 03093 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 03094 SERVICE_START)) 03095 { 03096 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 03097 return ERROR_ACCESS_DENIED; 03098 } 03099 03100 lpService = hSvc->ServiceEntry; 03101 if (lpService == NULL) 03102 { 03103 DPRINT("lpService == NULL!\n"); 03104 return ERROR_INVALID_HANDLE; 03105 } 03106 03107 if (lpService->dwStartType == SERVICE_DISABLED) 03108 return ERROR_SERVICE_DISABLED; 03109 03110 if (lpService->bDeleted) 03111 return ERROR_SERVICE_MARKED_FOR_DELETE; 03112 03113 /* Start the service */ 03114 dwError = ScmStartService(lpService, argc, (LPWSTR*)argv); 03115 03116 return dwError; 03117 } 03118 03119 03120 /* Function 20 */ 03121 DWORD RGetServiceDisplayNameW( 03122 SC_RPC_HANDLE hSCManager, 03123 LPCWSTR lpServiceName, 03124 LPWSTR lpDisplayName, 03125 DWORD *lpcchBuffer) 03126 { 03127 // PMANAGER_HANDLE hManager; 03128 PSERVICE lpService; 03129 DWORD dwLength; 03130 DWORD dwError; 03131 03132 DPRINT("RGetServiceDisplayNameW() called\n"); 03133 DPRINT("hSCManager = %p\n", hSCManager); 03134 DPRINT("lpServiceName: %S\n", lpServiceName); 03135 DPRINT("lpDisplayName: %p\n", lpDisplayName); 03136 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 03137 03138 // hManager = (PMANAGER_HANDLE)hSCManager; 03139 // if (hManager->Handle.Tag != MANAGER_TAG) 03140 // { 03141 // DPRINT("Invalid manager handle!\n"); 03142 // return ERROR_INVALID_HANDLE; 03143 // } 03144 03145 /* Get service database entry */ 03146 lpService = ScmGetServiceEntryByName(lpServiceName); 03147 if (lpService == NULL) 03148 { 03149 DPRINT("Could not find a service!\n"); 03150 03151 /* If the service could not be found and lpcchBuffer is less than 2, windows 03152 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 03153 if (*lpcchBuffer < 2) 03154 { 03155 *lpcchBuffer = 2; 03156 if (lpDisplayName != NULL) 03157 { 03158 *lpDisplayName = '\0'; 03159 } 03160 } 03161 03162 return ERROR_SERVICE_DOES_NOT_EXIST; 03163 } 03164 03165 if (!lpService->lpDisplayName) 03166 { 03167 dwLength = wcslen(lpService->lpServiceName); 03168 03169 if (lpDisplayName != NULL && 03170 *lpcchBuffer > dwLength) 03171 { 03172 wcscpy(lpDisplayName, lpService->lpServiceName); 03173 } 03174 } 03175 else 03176 { 03177 dwLength = wcslen(lpService->lpDisplayName); 03178 03179 if (lpDisplayName != NULL && 03180 *lpcchBuffer > dwLength) 03181 { 03182 wcscpy(lpDisplayName, lpService->lpDisplayName); 03183 } 03184 } 03185 03186 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 03187 03188 *lpcchBuffer = dwLength; 03189 03190 return dwError; 03191 } 03192 03193 03194 /* Function 21 */ 03195 DWORD RGetServiceKeyNameW( 03196 SC_RPC_HANDLE hSCManager, 03197 LPCWSTR lpDisplayName, 03198 LPWSTR lpServiceName, 03199 DWORD *lpcchBuffer) 03200 { 03201 // PMANAGER_HANDLE hManager; 03202 PSERVICE lpService; 03203 DWORD dwLength; 03204 DWORD dwError; 03205 03206 DPRINT("RGetServiceKeyNameW() called\n"); 03207 DPRINT("hSCManager = %p\n", hSCManager); 03208 DPRINT("lpDisplayName: %S\n", lpDisplayName); 03209 DPRINT("lpServiceName: %p\n", lpServiceName); 03210 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 03211 03212 // hManager = (PMANAGER_HANDLE)hSCManager; 03213 // if (hManager->Handle.Tag != MANAGER_TAG) 03214 // { 03215 // DPRINT("Invalid manager handle!\n"); 03216 // return ERROR_INVALID_HANDLE; 03217 // } 03218 03219 /* Get service database entry */ 03220 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName); 03221 if (lpService == NULL) 03222 { 03223 DPRINT("Could not find a service!\n"); 03224 03225 /* If the service could not be found and lpcchBuffer is less than 2, windows 03226 puts null in lpDisplayName and puts 2 in lpcchBuffer */ 03227 if (*lpcchBuffer < 2) 03228 { 03229 *lpcchBuffer = 2; 03230 if (lpServiceName != NULL) 03231 { 03232 *lpServiceName = '\0'; 03233 } 03234 } 03235 03236 return ERROR_SERVICE_DOES_NOT_EXIST; 03237 } 03238 03239 dwLength = wcslen(lpService->lpServiceName); 03240 03241 if (lpServiceName != NULL && 03242 *lpcchBuffer > dwLength) 03243 { 03244 wcscpy(lpServiceName, lpService->lpServiceName); 03245 *lpcchBuffer = dwLength; 03246 return ERROR_SUCCESS; 03247 } 03248 03249 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 03250 03251 *lpcchBuffer = dwLength; 03252 03253 return dwError; 03254 } 03255 03256 03257 /* Function 22 */ 03258 DWORD RI_ScSetServiceBitsA( 03259 RPC_SERVICE_STATUS_HANDLE hServiceStatus, 03260 DWORD dwServiceBits, 03261 int bSetBitsOn, 03262 int bUpdateImmediately, 03263 char *lpString) 03264 { 03265 UNIMPLEMENTED; 03266 return ERROR_CALL_NOT_IMPLEMENTED; 03267 } 03268 03269 03270 /* Function 23 */ 03271 DWORD RChangeServiceConfigA( 03272 SC_RPC_HANDLE hService, 03273 DWORD dwServiceType, 03274 DWORD dwStartType, 03275 DWORD dwErrorControl, 03276 LPSTR lpBinaryPathName, 03277 LPSTR lpLoadOrderGroup, 03278 LPDWORD lpdwTagId, 03279 LPSTR lpDependencies, 03280 DWORD dwDependSize, 03281 LPSTR lpServiceStartName, 03282 LPBYTE lpPassword, 03283 DWORD dwPwSize, 03284 LPSTR lpDisplayName) 03285 { 03286 DWORD dwError = ERROR_SUCCESS; 03287 PSERVICE_HANDLE hSvc; 03288 PSERVICE lpService = NULL; 03289 HKEY hServiceKey = NULL; 03290 LPWSTR lpDisplayNameW = NULL; 03291 LPWSTR lpBinaryPathNameW = NULL; 03292 LPWSTR lpCanonicalImagePathW = NULL; 03293 LPWSTR lpLoadOrderGroupW = NULL; 03294 LPWSTR lpDependenciesW = NULL; 03295 // LPWSTR lpPasswordW = NULL; 03296 03297 DPRINT("RChangeServiceConfigA() called\n"); 03298 DPRINT("dwServiceType = %lu\n", dwServiceType); 03299 DPRINT("dwStartType = %lu\n", dwStartType); 03300 DPRINT("dwErrorControl = %lu\n", dwErrorControl); 03301 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName); 03302 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup); 03303 DPRINT("lpDisplayName = %s\n", lpDisplayName); 03304 03305 if (ScmShutdown) 03306 return ERROR_SHUTDOWN_IN_PROGRESS; 03307 03308 hSvc = ScmGetServiceFromHandle(hService); 03309 if (hSvc == NULL) 03310 { 03311 DPRINT1("Invalid service handle!\n"); 03312 return ERROR_INVALID_HANDLE; 03313 } 03314 03315 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 03316 SERVICE_CHANGE_CONFIG)) 03317 { 03318 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 03319 return ERROR_ACCESS_DENIED; 03320 } 03321 03322 lpService = hSvc->ServiceEntry; 03323 if (lpService == NULL) 03324 { 03325 DPRINT("lpService == NULL!\n"); 03326 return ERROR_INVALID_HANDLE; 03327 } 03328 03329 /* Lock the service database exclusively */ 03330 ScmLockDatabaseExclusive(); 03331 03332 if (lpService->bDeleted) 03333 { 03334 DPRINT("The service has already been marked for delete!\n"); 03335 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 03336 goto done; 03337 } 03338 03339 /* Open the service key */ 03340 dwError = ScmOpenServiceKey(lpService->szServiceName, 03341 KEY_SET_VALUE, 03342 &hServiceKey); 03343 if (dwError != ERROR_SUCCESS) 03344 goto done; 03345 03346 /* Write service data to the registry */ 03347 03348 if (lpDisplayName != NULL && *lpDisplayName != 0) 03349 { 03350 /* Set the display name */ 03351 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 03352 0, 03353 (strlen(lpDisplayName) + 1) * sizeof(WCHAR)); 03354 if (lpDisplayNameW == NULL) 03355 { 03356 dwError = ERROR_NOT_ENOUGH_MEMORY; 03357 goto done; 03358 } 03359 03360 MultiByteToWideChar(CP_ACP, 03361 0, 03362 lpDisplayName, 03363 -1, 03364 lpDisplayNameW, 03365 strlen(lpDisplayName) + 1); 03366 03367 RegSetValueExW(hServiceKey, 03368 L"DisplayName", 03369 0, 03370 REG_SZ, 03371 (LPBYTE)lpDisplayNameW, 03372 (wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR)); 03373 03374 /* Update lpService->lpDisplayName */ 03375 if (lpService->lpDisplayName) 03376 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); 03377 03378 lpService->lpDisplayName = lpDisplayNameW; 03379 } 03380 03381 if (dwServiceType != SERVICE_NO_CHANGE) 03382 { 03383 /* Set the service type */ 03384 dwError = RegSetValueExW(hServiceKey, 03385 L"Type", 03386 0, 03387 REG_DWORD, 03388 (LPBYTE)&dwServiceType, 03389 sizeof(DWORD)); 03390 if (dwError != ERROR_SUCCESS) 03391 goto done; 03392 03393 lpService->Status.dwServiceType = dwServiceType; 03394 } 03395 03396 if (dwStartType != SERVICE_NO_CHANGE) 03397 { 03398 /* Set the start value */ 03399 dwError = RegSetValueExW(hServiceKey, 03400 L"Start", 03401 0, 03402 REG_DWORD, 03403 (LPBYTE)&dwStartType, 03404 sizeof(DWORD)); 03405 if (dwError != ERROR_SUCCESS) 03406 goto done; 03407 03408 lpService->dwStartType = dwStartType; 03409 } 03410 03411 if (dwErrorControl != SERVICE_NO_CHANGE) 03412 { 03413 /* Set the error control value */ 03414 dwError = RegSetValueExW(hServiceKey, 03415 L"ErrorControl", 03416 0, 03417 REG_DWORD, 03418 (LPBYTE)&dwErrorControl, 03419 sizeof(DWORD)); 03420 if (dwError != ERROR_SUCCESS) 03421 goto done; 03422 03423 lpService->dwErrorControl = dwErrorControl; 03424 } 03425 03426 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) 03427 { 03428 /* Set the image path */ 03429 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 03430 0, 03431 (strlen(lpBinaryPathName) + 1) * sizeof(WCHAR)); 03432 if (lpBinaryPathNameW == NULL) 03433 { 03434 dwError = ERROR_NOT_ENOUGH_MEMORY; 03435 goto done; 03436 } 03437 03438 MultiByteToWideChar(CP_ACP, 03439 0, 03440 lpBinaryPathName, 03441 -1, 03442 lpBinaryPathNameW, 03443 strlen(lpBinaryPathName) + 1); 03444 03445 if (lpService->Status.dwServiceType & SERVICE_DRIVER) 03446 { 03447 dwError = ScmCanonDriverImagePath(lpService->dwStartType, 03448 lpBinaryPathNameW, 03449 &lpCanonicalImagePathW); 03450 03451 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 03452 03453 if (dwError != ERROR_SUCCESS) 03454 goto done; 03455 03456 lpBinaryPathNameW = lpCanonicalImagePathW; 03457 } 03458 03459 dwError = RegSetValueExW(hServiceKey, 03460 L"ImagePath", 03461 0, 03462 REG_EXPAND_SZ, 03463 (LPBYTE)lpBinaryPathNameW, 03464 (wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR)); 03465 03466 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 03467 03468 if (dwError != ERROR_SUCCESS) 03469 goto done; 03470 } 03471 03472 /* Set the group name */ 03473 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0) 03474 { 03475 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 03476 0, 03477 (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); 03478 if (lpLoadOrderGroupW == NULL) 03479 { 03480 dwError = ERROR_NOT_ENOUGH_MEMORY; 03481 goto done; 03482 } 03483 03484 MultiByteToWideChar(CP_ACP, 03485 0, 03486 lpLoadOrderGroup, 03487 -1, 03488 lpLoadOrderGroupW, 03489 strlen(lpLoadOrderGroup) + 1); 03490 03491 dwError = RegSetValueExW(hServiceKey, 03492 L"Group", 03493 0, 03494 REG_SZ, 03495 (LPBYTE)lpLoadOrderGroupW, 03496 (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR)); 03497 if (dwError != ERROR_SUCCESS) 03498 { 03499 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 03500 goto done; 03501 } 03502 03503 dwError = ScmSetServiceGroup(lpService, 03504 lpLoadOrderGroupW); 03505 03506 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 03507 03508 if (dwError != ERROR_SUCCESS) 03509 goto done; 03510 } 03511 03512 if (lpdwTagId != NULL) 03513 { 03514 dwError = ScmAssignNewTag(lpService); 03515 if (dwError != ERROR_SUCCESS) 03516 goto done; 03517 03518 dwError = RegSetValueExW(hServiceKey, 03519 L"Tag", 03520 0, 03521 REG_DWORD, 03522 (LPBYTE)&lpService->dwTag, 03523 sizeof(DWORD)); 03524 if (dwError != ERROR_SUCCESS) 03525 goto done; 03526 03527 *lpdwTagId = lpService->dwTag; 03528 } 03529 03530 /* Write dependencies */ 03531 if (lpDependencies != NULL && *lpDependencies != 0) 03532 { 03533 lpDependenciesW = HeapAlloc(GetProcessHeap(), 03534 0, 03535 (strlen(lpDependencies) + 1) * sizeof(WCHAR)); 03536 if (lpDependenciesW == NULL) 03537 { 03538 dwError = ERROR_NOT_ENOUGH_MEMORY; 03539 goto done; 03540 } 03541 03542 MultiByteToWideChar(CP_ACP, 03543 0, 03544 lpDependencies, 03545 dwDependSize, 03546 lpDependenciesW, 03547 strlen(lpDependencies) + 1); 03548 03549 dwError = ScmWriteDependencies(hServiceKey, 03550 (LPWSTR)lpDependenciesW, 03551 dwDependSize); 03552 03553 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 03554 } 03555 03556 if (lpPassword != NULL) 03557 { 03558 /* FIXME: Write password */ 03559 } 03560 03561 done: 03562 /* Unlock the service database */ 03563 ScmUnlockDatabase(); 03564 03565 if (hServiceKey != NULL) 03566 RegCloseKey(hServiceKey); 03567 03568 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError); 03569 03570 return dwError; 03571 } 03572 03573 03574 /* Function 24 */ 03575 DWORD RCreateServiceA( 03576 SC_RPC_HANDLE hSCManager, 03577 LPSTR lpServiceName, 03578 LPSTR lpDisplayName, 03579 DWORD dwDesiredAccess, 03580 DWORD dwServiceType, 03581 DWORD dwStartType, 03582 DWORD dwErrorControl, 03583 LPSTR lpBinaryPathName, 03584 LPSTR lpLoadOrderGroup, 03585 LPDWORD lpdwTagId, 03586 LPBYTE lpDependencies, 03587 DWORD dwDependSize, 03588 LPSTR lpServiceStartName, 03589 LPBYTE lpPassword, 03590 DWORD dwPwSize, 03591 LPSC_RPC_HANDLE lpServiceHandle) 03592 { 03593 DWORD dwError = ERROR_SUCCESS; 03594 LPWSTR lpServiceNameW = NULL; 03595 LPWSTR lpDisplayNameW = NULL; 03596 LPWSTR lpBinaryPathNameW = NULL; 03597 LPWSTR lpLoadOrderGroupW = NULL; 03598 LPWSTR lpDependenciesW = NULL; 03599 LPWSTR lpServiceStartNameW = NULL; 03600 DWORD dwDependenciesLength = 0; 03601 DWORD dwLength; 03602 int len; 03603 LPCSTR lpStr; 03604 03605 if (lpServiceName) 03606 { 03607 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0); 03608 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 03609 if (!lpServiceNameW) 03610 { 03611 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03612 goto cleanup; 03613 } 03614 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len); 03615 } 03616 03617 if (lpDisplayName) 03618 { 03619 len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0); 03620 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 03621 if (!lpDisplayNameW) 03622 { 03623 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03624 goto cleanup; 03625 } 03626 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len); 03627 } 03628 03629 if (lpBinaryPathName) 03630 { 03631 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0); 03632 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 03633 if (!lpBinaryPathNameW) 03634 { 03635 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03636 goto cleanup; 03637 } 03638 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len); 03639 } 03640 03641 if (lpLoadOrderGroup) 03642 { 03643 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0); 03644 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 03645 if (!lpLoadOrderGroupW) 03646 { 03647 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03648 goto cleanup; 03649 } 03650 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len); 03651 } 03652 03653 if (lpDependencies) 03654 { 03655 lpStr = (LPCSTR)lpDependencies; 03656 while (*lpStr) 03657 { 03658 dwLength = strlen(lpStr) + 1; 03659 dwDependenciesLength += dwLength; 03660 lpStr = lpStr + dwLength; 03661 } 03662 dwDependenciesLength++; 03663 03664 lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR)); 03665 if (!lpDependenciesW) 03666 { 03667 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03668 goto cleanup; 03669 } 03670 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength); 03671 } 03672 03673 if (lpServiceStartName) 03674 { 03675 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0); 03676 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 03677 if (!lpServiceStartNameW) 03678 { 03679 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03680 goto cleanup; 03681 } 03682 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len); 03683 } 03684 03685 dwError = RCreateServiceW(hSCManager, 03686 lpServiceNameW, 03687 lpDisplayNameW, 03688 dwDesiredAccess, 03689 dwServiceType, 03690 dwStartType, 03691 dwErrorControl, 03692 lpBinaryPathNameW, 03693 lpLoadOrderGroupW, 03694 lpdwTagId, 03695 (LPBYTE)lpDependenciesW, 03696 dwDependenciesLength, 03697 lpServiceStartNameW, 03698 lpPassword, 03699 dwPwSize, 03700 lpServiceHandle); 03701 03702 cleanup: 03703 if (lpServiceNameW !=NULL) 03704 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 03705 03706 if (lpDisplayNameW != NULL) 03707 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 03708 03709 if (lpBinaryPathNameW != NULL) 03710 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW); 03711 03712 if (lpLoadOrderGroupW != NULL) 03713 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); 03714 03715 if (lpDependenciesW != NULL) 03716 HeapFree(GetProcessHeap(), 0, lpDependenciesW); 03717 03718 if (lpServiceStartNameW != NULL) 03719 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW); 03720 03721 return dwError; 03722 } 03723 03724 03725 /* Function 25 */ 03726 DWORD REnumDependentServicesA( 03727 SC_RPC_HANDLE hService, 03728 DWORD dwServiceState, 03729 LPBYTE lpServices, 03730 DWORD cbBufSize, 03731 LPBOUNDED_DWORD_256K pcbBytesNeeded, 03732 LPBOUNDED_DWORD_256K lpServicesReturned) 03733 { 03734 DWORD dwError = ERROR_SUCCESS; 03735 DWORD dwServicesReturned = 0; 03736 DWORD dwServiceCount; 03737 HKEY hServicesKey = NULL; 03738 PSERVICE_HANDLE hSvc; 03739 PSERVICE lpService = NULL; 03740 PSERVICE *lpServicesArray = NULL; 03741 LPENUM_SERVICE_STATUSA lpServicesPtr = NULL; 03742 LPSTR lpStr; 03743 03744 *pcbBytesNeeded = 0; 03745 *lpServicesReturned = 0; 03746 03747 DPRINT("REnumDependentServicesA() called\n"); 03748 03749 hSvc = ScmGetServiceFromHandle(hService); 03750 if (hSvc == NULL) 03751 { 03752 DPRINT1("Invalid service handle!\n"); 03753 return ERROR_INVALID_HANDLE; 03754 } 03755 03756 lpService = hSvc->ServiceEntry; 03757 03758 /* Check access rights */ 03759 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 03760 SC_MANAGER_ENUMERATE_SERVICE)) 03761 { 03762 DPRINT("Insufficient access rights! 0x%lx\n", 03763 hSvc->Handle.DesiredAccess); 03764 return ERROR_ACCESS_DENIED; 03765 } 03766 03767 /* Open the Services Reg key */ 03768 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 03769 L"System\\CurrentControlSet\\Services", 03770 0, 03771 KEY_READ, 03772 &hServicesKey); 03773 03774 if (dwError != ERROR_SUCCESS) 03775 return dwError; 03776 03777 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for 03778 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded 03779 are the same for both. Verified in WINXP. */ 03780 03781 /* First determine the bytes needed and get the number of dependent services*/ 03782 dwError = Int_EnumDependentServicesW(hServicesKey, 03783 lpService, 03784 dwServiceState, 03785 NULL, 03786 pcbBytesNeeded, 03787 &dwServicesReturned); 03788 if (dwError != ERROR_SUCCESS) 03789 goto Done; 03790 03791 /* If buffer size is less than the bytes needed or pointer is null*/ 03792 if ((!lpServices) || (cbBufSize < *pcbBytesNeeded)) 03793 { 03794 dwError = ERROR_MORE_DATA; 03795 goto Done; 03796 } 03797 03798 /* Allocate memory for array of service pointers */ 03799 lpServicesArray = HeapAlloc(GetProcessHeap(), 03800 0, 03801 (dwServicesReturned + 1) * sizeof(PSERVICE)); 03802 if (!lpServicesArray) 03803 { 03804 DPRINT("Could not allocate a buffer!!\n"); 03805 dwError = ERROR_NOT_ENOUGH_MEMORY; 03806 goto Done; 03807 } 03808 03809 dwServicesReturned = 0; 03810 *pcbBytesNeeded = 0; 03811 03812 dwError = Int_EnumDependentServicesW(hServicesKey, 03813 lpService, 03814 dwServiceState, 03815 lpServicesArray, 03816 pcbBytesNeeded, 03817 &dwServicesReturned); 03818 if (dwError != ERROR_SUCCESS) 03819 { 03820 goto Done; 03821 } 03822 03823 lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices; 03824 lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA))); 03825 03826 /* Copy EnumDepenedentService to Buffer */ 03827 for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++) 03828 { 03829 lpService = lpServicesArray[dwServiceCount]; 03830 03831 /* Copy the status info */ 03832 memcpy(&lpServicesPtr->ServiceStatus, 03833 &lpService->Status, 03834 sizeof(SERVICE_STATUS)); 03835 03836 /* Copy display name */ 03837 WideCharToMultiByte(CP_ACP, 03838 0, 03839 lpService->lpDisplayName, 03840 -1, 03841 lpStr, 03842 wcslen(lpService->lpDisplayName), 03843 0, 03844 0); 03845 lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 03846 lpStr += strlen(lpStr) + 1; 03847 03848 /* Copy service name */ 03849 WideCharToMultiByte(CP_ACP, 03850 0, 03851 lpService->lpServiceName, 03852 -1, 03853 lpStr, 03854 wcslen(lpService->lpServiceName), 03855 0, 03856 0); 03857 lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices); 03858 lpStr += strlen(lpStr) + 1; 03859 03860 lpServicesPtr ++; 03861 } 03862 03863 *lpServicesReturned = dwServicesReturned; 03864 03865 Done: 03866 if (lpServicesArray) 03867 HeapFree(GetProcessHeap(), 0, lpServicesArray); 03868 03869 RegCloseKey(hServicesKey); 03870 03871 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError); 03872 03873 return dwError; 03874 } 03875 03876 03877 /* Function 26 */ 03878 DWORD REnumServicesStatusA( 03879 SC_RPC_HANDLE hSCManager, 03880 DWORD dwServiceType, 03881 DWORD dwServiceState, 03882 LPBYTE lpBuffer, 03883 DWORD dwBufSize, 03884 LPBOUNDED_DWORD_256K pcbBytesNeeded, 03885 LPBOUNDED_DWORD_256K lpServicesReturned, 03886 LPBOUNDED_DWORD_256K lpResumeHandle) 03887 { 03888 LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL; 03889 LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL; 03890 LPWSTR lpStringPtrW; 03891 LPSTR lpStringPtrA; 03892 DWORD dwError; 03893 DWORD dwServiceCount; 03894 03895 DPRINT("REnumServicesStatusA() called\n"); 03896 03897 if ((dwBufSize > 0) && (lpBuffer)) 03898 { 03899 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize); 03900 if (!lpStatusPtrW) 03901 { 03902 DPRINT("Failed to allocate buffer!\n"); 03903 return ERROR_NOT_ENOUGH_MEMORY; 03904 } 03905 } 03906 03907 dwError = REnumServicesStatusW(hSCManager, 03908 dwServiceType, 03909 dwServiceState, 03910 (LPBYTE)lpStatusPtrW, 03911 dwBufSize, 03912 pcbBytesNeeded, 03913 lpServicesReturned, 03914 lpResumeHandle); 03915 03916 /* if no services were returned then we are Done */ 03917 if (*lpServicesReturned == 0) 03918 goto Done; 03919 03920 lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer; 03921 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 03922 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA)); 03923 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 03924 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW)); 03925 03926 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 03927 { 03928 /* Copy the service name */ 03929 WideCharToMultiByte(CP_ACP, 03930 0, 03931 lpStringPtrW, 03932 -1, 03933 lpStringPtrA, 03934 wcslen(lpStringPtrW), 03935 0, 03936 0); 03937 03938 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 03939 lpStringPtrA += wcslen(lpStringPtrW) + 1; 03940 lpStringPtrW += wcslen(lpStringPtrW) + 1; 03941 03942 /* Copy the display name */ 03943 WideCharToMultiByte(CP_ACP, 03944 0, 03945 lpStringPtrW, 03946 -1, 03947 lpStringPtrA, 03948 wcslen(lpStringPtrW), 03949 0, 03950 0); 03951 03952 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 03953 lpStringPtrA += wcslen(lpStringPtrW) + 1; 03954 lpStringPtrW += wcslen(lpStringPtrW) + 1; 03955 03956 /* Copy the status information */ 03957 memcpy(&lpStatusPtrA->ServiceStatus, 03958 &lpStatusPtrW->ServiceStatus, 03959 sizeof(SERVICE_STATUS)); 03960 03961 lpStatusPtrA++; 03962 } 03963 03964 Done:; 03965 if (lpStatusPtrW) 03966 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 03967 03968 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError); 03969 03970 return dwError; 03971 } 03972 03973 03974 /* Function 27 */ 03975 DWORD ROpenSCManagerA( 03976 LPSTR lpMachineName, 03977 LPSTR lpDatabaseName, 03978 DWORD dwDesiredAccess, 03979 LPSC_RPC_HANDLE lpScHandle) 03980 { 03981 UNICODE_STRING MachineName; 03982 UNICODE_STRING DatabaseName; 03983 DWORD dwError; 03984 03985 DPRINT("ROpenSCManagerA() called\n"); 03986 03987 if (lpMachineName) 03988 RtlCreateUnicodeStringFromAsciiz(&MachineName, 03989 lpMachineName); 03990 03991 if (lpDatabaseName) 03992 RtlCreateUnicodeStringFromAsciiz(&DatabaseName, 03993 lpDatabaseName); 03994 03995 dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL, 03996 lpDatabaseName ? DatabaseName.Buffer : NULL, 03997 dwDesiredAccess, 03998 lpScHandle); 03999 04000 if (lpMachineName) 04001 RtlFreeUnicodeString(&MachineName); 04002 04003 if (lpDatabaseName) 04004 RtlFreeUnicodeString(&DatabaseName); 04005 04006 return dwError; 04007 } 04008 04009 04010 /* Function 28 */ 04011 DWORD ROpenServiceA( 04012 SC_RPC_HANDLE hSCManager, 04013 LPSTR lpServiceName, 04014 DWORD dwDesiredAccess, 04015 LPSC_RPC_HANDLE lpServiceHandle) 04016 { 04017 UNICODE_STRING ServiceName; 04018 DWORD dwError; 04019 04020 DPRINT("ROpenServiceA() called\n"); 04021 04022 if (lpServiceName) 04023 RtlCreateUnicodeStringFromAsciiz(&ServiceName, 04024 lpServiceName); 04025 04026 dwError = ROpenServiceW(hSCManager, 04027 lpServiceName ? ServiceName.Buffer : NULL, 04028 dwDesiredAccess, 04029 lpServiceHandle); 04030 04031 if (lpServiceName) 04032 RtlFreeUnicodeString(&ServiceName); 04033 04034 return dwError; 04035 } 04036 04037 04038 /* Function 29 */ 04039 DWORD RQueryServiceConfigA( 04040 SC_RPC_HANDLE hService, 04041 LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig, 04042 DWORD cbBufSize, 04043 LPBOUNDED_DWORD_8K pcbBytesNeeded) 04044 { 04045 LPQUERY_SERVICE_CONFIGA lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)lpBuf; 04046 DWORD dwError = ERROR_SUCCESS; 04047 PSERVICE_HANDLE hSvc; 04048 PSERVICE lpService = NULL; 04049 HKEY hServiceKey = NULL; 04050 LPWSTR lpImagePath = NULL; 04051 LPWSTR lpServiceStartName = NULL; 04052 LPWSTR lpDependencies = NULL; 04053 DWORD dwDependenciesLength = 0; 04054 DWORD dwRequiredSize; 04055 LPQUERY_SERVICE_CONFIGA lpConfig = NULL; 04056 CHAR lpEmptyString[]={0,0}; 04057 LPSTR lpStr; 04058 04059 DPRINT("RQueryServiceConfigA() called\n"); 04060 04061 if (ScmShutdown) 04062 return ERROR_SHUTDOWN_IN_PROGRESS; 04063 04064 hSvc = ScmGetServiceFromHandle(hService); 04065 if (hSvc == NULL) 04066 { 04067 DPRINT1("Invalid service handle!\n"); 04068 return ERROR_INVALID_HANDLE; 04069 } 04070 04071 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 04072 SERVICE_QUERY_CONFIG)) 04073 { 04074 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 04075 return ERROR_ACCESS_DENIED; 04076 } 04077 04078 lpService = hSvc->ServiceEntry; 04079 if (lpService == NULL) 04080 { 04081 DPRINT("lpService == NULL!\n"); 04082 return ERROR_INVALID_HANDLE; 04083 } 04084 04085 /* Lock the service database shared */ 04086 ScmLockDatabaseShared(); 04087 04088 dwError = ScmOpenServiceKey(lpService->lpServiceName, 04089 KEY_READ, 04090 &hServiceKey); 04091 if (dwError != ERROR_SUCCESS) 04092 goto Done; 04093 04094 /* Read the image path */ 04095 dwError = ScmReadString(hServiceKey, 04096 L"ImagePath", 04097 &lpImagePath); 04098 if (dwError != ERROR_SUCCESS) 04099 goto Done; 04100 04101 /* Read the service start name */ 04102 ScmReadString(hServiceKey, 04103 L"ObjectName", 04104 &lpServiceStartName); 04105 04106 /* Read the dependencies */ 04107 ScmReadDependencies(hServiceKey, 04108 &lpDependencies, 04109 &dwDependenciesLength); 04110 04111 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW); 04112 04113 if (lpImagePath != NULL) 04114 dwRequiredSize += wcslen(lpImagePath) + 1; 04115 else 04116 dwRequiredSize += 2; 04117 04118 if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL)) 04119 dwRequiredSize += wcslen(lpService->lpGroup->lpGroupName) + 1; 04120 else 04121 dwRequiredSize += 2; 04122 04123 /* Add Dependencies length */ 04124 if (lpDependencies != NULL) 04125 dwRequiredSize += dwDependenciesLength; 04126 else 04127 dwRequiredSize += 2; 04128 04129 if (lpServiceStartName != NULL) 04130 dwRequiredSize += wcslen(lpServiceStartName) + 1; 04131 else 04132 dwRequiredSize += 2; 04133 04134 if (lpService->lpDisplayName != NULL) 04135 dwRequiredSize += wcslen(lpService->lpDisplayName) + 1; 04136 else 04137 dwRequiredSize += 2; 04138 04139 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize) 04140 { 04141 dwError = ERROR_INSUFFICIENT_BUFFER; 04142 } 04143 else 04144 { 04145 lpConfig = (LPQUERY_SERVICE_CONFIGA)lpServiceConfig; 04146 lpConfig->dwServiceType = lpService->Status.dwServiceType; 04147 lpConfig->dwStartType = lpService->dwStartType; 04148 lpConfig->dwErrorControl = lpService->dwErrorControl; 04149 lpConfig->dwTagId = lpService->dwTag; 04150 04151 lpStr = (LPSTR)(lpServiceConfig + 1); 04152 04153 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings. 04154 Verified in WINXP*/ 04155 04156 if (lpImagePath) 04157 { 04158 WideCharToMultiByte(CP_ACP, 04159 0, 04160 lpImagePath, 04161 -1, 04162 lpStr, 04163 wcslen(lpImagePath) + 1, 04164 0, 04165 0); 04166 } 04167 else 04168 { 04169 strcpy(lpStr, lpEmptyString); 04170 } 04171 04172 lpConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 04173 lpStr += (strlen((LPSTR)lpStr) + 1); 04174 04175 if (lpService->lpGroup && lpService->lpGroup->lpGroupName) 04176 { 04177 WideCharToMultiByte(CP_ACP, 04178 0, 04179 lpService->lpGroup->lpGroupName, 04180 -1, 04181 lpStr, 04182 wcslen(lpService->lpGroup->lpGroupName) + 1, 04183 0, 04184 0); 04185 } 04186 else 04187 { 04188 strcpy(lpStr, lpEmptyString); 04189 } 04190 04191 lpConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 04192 lpStr += (strlen(lpStr) + 1); 04193 04194 /* Append Dependencies */ 04195 if (lpDependencies) 04196 { 04197 WideCharToMultiByte(CP_ACP, 04198 0, 04199 lpDependencies, 04200 dwDependenciesLength, 04201 lpStr, 04202 dwDependenciesLength, 04203 0, 04204 0); 04205 } 04206 else 04207 { 04208 strcpy(lpStr, lpEmptyString); 04209 } 04210 04211 lpConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 04212 if (lpDependencies) 04213 lpStr += dwDependenciesLength; 04214 else 04215 lpStr += (strlen(lpStr) + 1); 04216 04217 if (lpServiceStartName) 04218 { 04219 WideCharToMultiByte(CP_ACP, 04220 0, 04221 lpServiceStartName, 04222 -1, 04223 lpStr, 04224 wcslen(lpServiceStartName) + 1, 04225 0, 04226 0); 04227 } 04228 else 04229 { 04230 strcpy(lpStr, lpEmptyString); 04231 } 04232 04233 lpConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 04234 lpStr += (strlen(lpStr) + 1); 04235 04236 if (lpService->lpDisplayName) 04237 { 04238 WideCharToMultiByte(CP_ACP, 04239 0, 04240 lpService->lpDisplayName, 04241 -1, 04242 lpStr, 04243 wcslen(lpService->lpDisplayName) + 1, 04244 0, 04245 0); 04246 } 04247 else 04248 { 04249 strcpy(lpStr, lpEmptyString); 04250 } 04251 04252 lpConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig); 04253 } 04254 04255 if (pcbBytesNeeded != NULL) 04256 *pcbBytesNeeded = dwRequiredSize; 04257 04258 Done:; 04259 /* Unlock the service database */ 04260 ScmUnlockDatabase(); 04261 04262 if (lpImagePath != NULL) 04263 HeapFree(GetProcessHeap(), 0, lpImagePath); 04264 04265 if (lpServiceStartName != NULL) 04266 HeapFree(GetProcessHeap(), 0, lpServiceStartName); 04267 04268 if (lpDependencies != NULL) 04269 HeapFree(GetProcessHeap(), 0, lpDependencies); 04270 04271 if (hServiceKey != NULL) 04272 RegCloseKey(hServiceKey); 04273 04274 DPRINT("RQueryServiceConfigA() done\n"); 04275 04276 return dwError; 04277 } 04278 04279 04280 /* Function 30 */ 04281 DWORD RQueryServiceLockStatusA( 04282 SC_RPC_HANDLE hSCManager, 04283 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, 04284 DWORD cbBufSize, 04285 LPBOUNDED_DWORD_4K pcbBytesNeeded) 04286 { 04287 UNIMPLEMENTED; 04288 return ERROR_CALL_NOT_IMPLEMENTED; 04289 } 04290 04291 04292 /* Function 31 */ 04293 DWORD RStartServiceA( 04294 SC_RPC_HANDLE hService, 04295 DWORD argc, 04296 LPSTRING_PTRSA argv) 04297 { 04298 DWORD dwError = ERROR_SUCCESS; 04299 PSERVICE_HANDLE hSvc; 04300 PSERVICE lpService = NULL; 04301 LPWSTR *lpVector = NULL; 04302 DWORD i; 04303 DWORD dwLength; 04304 04305 DPRINT("RStartServiceA() called\n"); 04306 04307 if (ScmShutdown) 04308 return ERROR_SHUTDOWN_IN_PROGRESS; 04309 04310 hSvc = ScmGetServiceFromHandle(hService); 04311 if (hSvc == NULL) 04312 { 04313 DPRINT1("Invalid service handle!\n"); 04314 return ERROR_INVALID_HANDLE; 04315 } 04316 04317 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 04318 SERVICE_START)) 04319 { 04320 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 04321 return ERROR_ACCESS_DENIED; 04322 } 04323 04324 lpService = hSvc->ServiceEntry; 04325 if (lpService == NULL) 04326 { 04327 DPRINT("lpService == NULL!\n"); 04328 return ERROR_INVALID_HANDLE; 04329 } 04330 04331 if (lpService->dwStartType == SERVICE_DISABLED) 04332 return ERROR_SERVICE_DISABLED; 04333 04334 if (lpService->bDeleted) 04335 return ERROR_SERVICE_MARKED_FOR_DELETE; 04336 04337 /* Build a Unicode argument vector */ 04338 if (argc > 0) 04339 { 04340 lpVector = HeapAlloc(GetProcessHeap(), 04341 HEAP_ZERO_MEMORY, 04342 argc * sizeof(LPWSTR)); 04343 if (lpVector == NULL) 04344 return ERROR_NOT_ENOUGH_MEMORY; 04345 04346 for (i = 0; i < argc; i++) 04347 { 04348 dwLength = MultiByteToWideChar(CP_ACP, 04349 0, 04350 ((LPSTR*)argv)[i], 04351 -1, 04352 NULL, 04353 0); 04354 04355 lpVector[i] = HeapAlloc(GetProcessHeap(), 04356 HEAP_ZERO_MEMORY, 04357 dwLength * sizeof(WCHAR)); 04358 if (lpVector[i] == NULL) 04359 { 04360 dwError = ERROR_NOT_ENOUGH_MEMORY; 04361 goto done; 04362 } 04363 04364 MultiByteToWideChar(CP_ACP, 04365 0, 04366 ((LPSTR*)argv)[i], 04367 -1, 04368 lpVector[i], 04369 dwLength); 04370 } 04371 } 04372 04373 /* Start the service */ 04374 dwError = ScmStartService(lpService, argc, lpVector); 04375 04376 done: 04377 /* Free the Unicode argument vector */ 04378 if (lpVector != NULL) 04379 { 04380 for (i = 0; i < argc; i++) 04381 { 04382 if (lpVector[i] != NULL) 04383 HeapFree(GetProcessHeap(), 0, lpVector[i]); 04384 } 04385 HeapFree(GetProcessHeap(), 0, lpVector); 04386 } 04387 04388 return dwError; 04389 } 04390 04391 04392 /* Function 32 */ 04393 DWORD RGetServiceDisplayNameA( 04394 SC_RPC_HANDLE hSCManager, 04395 LPCSTR lpServiceName, 04396 LPSTR lpDisplayName, 04397 LPBOUNDED_DWORD_4K lpcchBuffer) 04398 { 04399 // PMANAGER_HANDLE hManager; 04400 PSERVICE lpService = NULL; 04401 DWORD dwLength; 04402 DWORD dwError; 04403 LPWSTR lpServiceNameW; 04404 04405 DPRINT("RGetServiceDisplayNameA() called\n"); 04406 DPRINT("hSCManager = %p\n", hSCManager); 04407 DPRINT("lpServiceName: %s\n", lpServiceName); 04408 DPRINT("lpDisplayName: %p\n", lpDisplayName); 04409 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 04410 04411 // hManager = (PMANAGER_HANDLE)hSCManager; 04412 // if (hManager->Handle.Tag != MANAGER_TAG) 04413 // { 04414 // DPRINT("Invalid manager handle!\n"); 04415 // return ERROR_INVALID_HANDLE; 04416 // } 04417 04418 if (lpServiceName != NULL) 04419 { 04420 dwLength = strlen(lpServiceName) + 1; 04421 lpServiceNameW = HeapAlloc(GetProcessHeap(), 04422 HEAP_ZERO_MEMORY, 04423 dwLength * sizeof(WCHAR)); 04424 if (!lpServiceNameW) 04425 return ERROR_NOT_ENOUGH_MEMORY; 04426 04427 MultiByteToWideChar(CP_ACP, 04428 0, 04429 lpServiceName, 04430 -1, 04431 lpServiceNameW, 04432 dwLength); 04433 04434 lpService = ScmGetServiceEntryByName(lpServiceNameW); 04435 04436 HeapFree(GetProcessHeap(), 0, lpServiceNameW); 04437 } 04438 04439 if (lpService == NULL) 04440 { 04441 DPRINT("Could not find a service!\n"); 04442 04443 /* If the service could not be found and lpcchBuffer is 0, windows 04444 puts null in lpDisplayName and puts 1 in lpcchBuffer */ 04445 if (*lpcchBuffer == 0) 04446 { 04447 *lpcchBuffer = 1; 04448 if (lpDisplayName != NULL) 04449 { 04450 *lpDisplayName = '\0'; 04451 } 04452 } 04453 return ERROR_SERVICE_DOES_NOT_EXIST; 04454 } 04455 04456 if (!lpService->lpDisplayName) 04457 { 04458 dwLength = wcslen(lpService->lpServiceName); 04459 if (lpDisplayName != NULL && 04460 *lpcchBuffer > dwLength) 04461 { 04462 WideCharToMultiByte(CP_ACP, 04463 0, 04464 lpService->lpServiceName, 04465 wcslen(lpService->lpServiceName), 04466 lpDisplayName, 04467 dwLength + 1, 04468 NULL, 04469 NULL); 04470 return ERROR_SUCCESS; 04471 } 04472 } 04473 else 04474 { 04475 dwLength = wcslen(lpService->lpDisplayName); 04476 if (lpDisplayName != NULL && 04477 *lpcchBuffer > dwLength) 04478 { 04479 WideCharToMultiByte(CP_ACP, 04480 0, 04481 lpService->lpDisplayName, 04482 wcslen(lpService->lpDisplayName), 04483 lpDisplayName, 04484 dwLength + 1, 04485 NULL, 04486 NULL); 04487 return ERROR_SUCCESS; 04488 } 04489 } 04490 04491 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 04492 04493 *lpcchBuffer = dwLength * 2; 04494 04495 return dwError; 04496 } 04497 04498 04499 /* Function 33 */ 04500 DWORD RGetServiceKeyNameA( 04501 SC_RPC_HANDLE hSCManager, 04502 LPCSTR lpDisplayName, 04503 LPSTR lpServiceName, 04504 LPBOUNDED_DWORD_4K lpcchBuffer) 04505 { 04506 PSERVICE lpService; 04507 DWORD dwLength; 04508 DWORD dwError; 04509 LPWSTR lpDisplayNameW; 04510 04511 DPRINT("RGetServiceKeyNameA() called\n"); 04512 DPRINT("hSCManager = %p\n", hSCManager); 04513 DPRINT("lpDisplayName: %s\n", lpDisplayName); 04514 DPRINT("lpServiceName: %p\n", lpServiceName); 04515 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer); 04516 04517 dwLength = strlen(lpDisplayName) + 1; 04518 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 04519 HEAP_ZERO_MEMORY, 04520 dwLength * sizeof(WCHAR)); 04521 if (!lpDisplayNameW) 04522 return ERROR_NOT_ENOUGH_MEMORY; 04523 04524 MultiByteToWideChar(CP_ACP, 04525 0, 04526 lpDisplayName, 04527 -1, 04528 lpDisplayNameW, 04529 dwLength); 04530 04531 lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW); 04532 04533 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 04534 04535 if (lpService == NULL) 04536 { 04537 DPRINT("Could not find the service!\n"); 04538 04539 /* If the service could not be found and lpcchBuffer is 0, 04540 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */ 04541 if (*lpcchBuffer == 0) 04542 { 04543 *lpcchBuffer = 1; 04544 if (lpServiceName != NULL) 04545 { 04546 *lpServiceName = '\0'; 04547 } 04548 } 04549 04550 return ERROR_SERVICE_DOES_NOT_EXIST; 04551 } 04552 04553 dwLength = wcslen(lpService->lpServiceName); 04554 if (lpServiceName != NULL && 04555 *lpcchBuffer > dwLength) 04556 { 04557 WideCharToMultiByte(CP_ACP, 04558 0, 04559 lpService->lpServiceName, 04560 wcslen(lpService->lpServiceName), 04561 lpServiceName, 04562 dwLength + 1, 04563 NULL, 04564 NULL); 04565 return ERROR_SUCCESS; 04566 } 04567 04568 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; 04569 04570 *lpcchBuffer = dwLength * 2; 04571 04572 return dwError; 04573 } 04574 04575 04576 /* Function 34 */ 04577 DWORD RI_ScGetCurrentGroupStateW( 04578 SC_RPC_HANDLE hSCManager, 04579 LPWSTR lpLoadOrderGroup, 04580 LPDWORD lpState) 04581 { 04582 UNIMPLEMENTED; 04583 return ERROR_CALL_NOT_IMPLEMENTED; 04584 } 04585 04586 04587 /* Function 35 */ 04588 DWORD REnumServiceGroupW( 04589 SC_RPC_HANDLE hSCManager, 04590 DWORD dwServiceType, 04591 DWORD dwServiceState, 04592 LPBYTE lpBuffer, 04593 DWORD cbBufSize, 04594 LPBOUNDED_DWORD_256K pcbBytesNeeded, 04595 LPBOUNDED_DWORD_256K lpServicesReturned, 04596 LPBOUNDED_DWORD_256K lpResumeIndex, 04597 LPCWSTR pszGroupName) 04598 { 04599 UNIMPLEMENTED; 04600 return ERROR_CALL_NOT_IMPLEMENTED; 04601 } 04602 04603 04604 // 04605 // WARNING: This function is untested 04606 // 04607 /* Function 36 */ 04608 DWORD RChangeServiceConfig2A( 04609 SC_RPC_HANDLE hService, 04610 SC_RPC_CONFIG_INFOA Info) 04611 { 04612 SC_RPC_CONFIG_INFOW InfoW; 04613 DWORD dwRet, dwLength; 04614 PVOID ptr = NULL; 04615 04616 DPRINT("RChangeServiceConfig2A() called\n"); 04617 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 04618 04619 InfoW.dwInfoLevel = Info.dwInfoLevel; 04620 04621 if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 04622 { 04623 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW; 04624 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA; 04625 04626 //lpServiceDescriptonA = Info.psd; 04627 04631 dwLength = (strlen(Info.lpDescription) + 1) * sizeof(WCHAR); 04632 04633 lpServiceDescriptonW = HeapAlloc(GetProcessHeap(), 04634 0, 04635 dwLength + sizeof(SERVICE_DESCRIPTIONW)); 04636 if (!lpServiceDescriptonW) 04637 { 04638 return ERROR_NOT_ENOUGH_MEMORY; 04639 } 04640 04641 lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1); 04642 04643 MultiByteToWideChar(CP_ACP, 04644 0, 04645 Info.lpDescription, 04646 -1, 04647 lpServiceDescriptonW->lpDescription, 04648 dwLength); 04649 04650 ptr = lpServiceDescriptonW; 04651 InfoW.psd = lpServiceDescriptonW; 04653 } 04654 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 04655 { 04656 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; 04657 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; 04658 DWORD dwRebootLen = 0; 04659 DWORD dwCommandLen = 0; 04660 04661 lpServiceFailureActionsA = Info.psfa; 04662 04663 if (lpServiceFailureActionsA) 04664 { 04665 if (lpServiceFailureActionsA->lpRebootMsg) 04666 { 04667 dwRebootLen = (strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR); 04668 } 04669 if (lpServiceFailureActionsA->lpCommand) 04670 { 04671 dwCommandLen = (strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR); 04672 } 04673 dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW); 04674 04675 lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(), 04676 0, 04677 dwLength); 04678 if (!lpServiceFailureActionsW) 04679 { 04680 return ERROR_NOT_ENOUGH_MEMORY; 04681 } 04682 04683 lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; 04684 lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; 04685 CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION)); 04686 04687 if (lpServiceFailureActionsA->lpRebootMsg) 04688 { 04689 MultiByteToWideChar(CP_ACP, 04690 0, 04691 lpServiceFailureActionsA->lpRebootMsg, 04692 -1, 04693 lpServiceFailureActionsW->lpRebootMsg, 04694 dwRebootLen); 04695 } 04696 04697 if (lpServiceFailureActionsA->lpCommand) 04698 { 04699 MultiByteToWideChar(CP_ACP, 04700 0, 04701 lpServiceFailureActionsA->lpCommand, 04702 -1, 04703 lpServiceFailureActionsW->lpCommand, 04704 dwCommandLen); 04705 } 04706 04707 ptr = lpServiceFailureActionsW; 04708 } 04709 } 04710 04711 dwRet = RChangeServiceConfig2W(hService, InfoW); 04712 04713 HeapFree(GetProcessHeap(), 0, ptr); 04714 04715 return dwRet; 04716 } 04717 04718 04719 /* Function 37 */ 04720 DWORD RChangeServiceConfig2W( 04721 SC_RPC_HANDLE hService, 04722 SC_RPC_CONFIG_INFOW Info) 04723 { 04724 DWORD dwError = ERROR_SUCCESS; 04725 PSERVICE_HANDLE hSvc; 04726 PSERVICE lpService = NULL; 04727 HKEY hServiceKey = NULL; 04728 04729 DPRINT("RChangeServiceConfig2W() called\n"); 04730 DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel); 04731 04732 if (ScmShutdown) 04733 return ERROR_SHUTDOWN_IN_PROGRESS; 04734 04735 hSvc = ScmGetServiceFromHandle(hService); 04736 if (hSvc == NULL) 04737 { 04738 DPRINT1("Invalid service handle!\n"); 04739 return ERROR_INVALID_HANDLE; 04740 } 04741 04742 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 04743 SERVICE_CHANGE_CONFIG)) 04744 { 04745 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 04746 return ERROR_ACCESS_DENIED; 04747 } 04748 04749 lpService = hSvc->ServiceEntry; 04750 if (lpService == NULL) 04751 { 04752 DPRINT("lpService == NULL!\n"); 04753 return ERROR_INVALID_HANDLE; 04754 } 04755 04756 /* Lock the service database exclusively */ 04757 ScmLockDatabaseExclusive(); 04758 04759 if (lpService->bDeleted) 04760 { 04761 DPRINT("The service has already been marked for delete!\n"); 04762 dwError = ERROR_SERVICE_MARKED_FOR_DELETE; 04763 goto done; 04764 } 04765 04766 /* Open the service key */ 04767 dwError = ScmOpenServiceKey(lpService->szServiceName, 04768 KEY_SET_VALUE, 04769 &hServiceKey); 04770 if (dwError != ERROR_SUCCESS) 04771 goto done; 04772 04773 if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 04774 { 04775 LPSERVICE_DESCRIPTIONW lpServiceDescription; 04776 04777 lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd; 04778 04779 if (lpServiceDescription != NULL && 04780 lpServiceDescription->lpDescription != NULL) 04781 { 04782 DPRINT("Setting value %S\n", lpServiceDescription->lpDescription); 04783 dwError = RegSetValueExW(hServiceKey, 04784 L"Description", 04785 0, 04786 REG_SZ, 04787 (LPBYTE)lpServiceDescription->lpDescription, 04788 (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR)); 04789 if (dwError != ERROR_SUCCESS) 04790 goto done; 04791 } 04792 } 04793 else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 04794 { 04795 UNIMPLEMENTED; 04796 dwError = ERROR_CALL_NOT_IMPLEMENTED; 04797 goto done; 04798 } 04799 04800 done: 04801 /* Unlock the service database */ 04802 ScmUnlockDatabase(); 04803 04804 if (hServiceKey != NULL) 04805 RegCloseKey(hServiceKey); 04806 04807 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError); 04808 04809 return dwError; 04810 } 04811 04812 04813 /* Function 38 */ 04814 DWORD RQueryServiceConfig2A( 04815 SC_RPC_HANDLE hService, 04816 DWORD dwInfoLevel, 04817 LPBYTE lpBuffer, 04818 DWORD cbBufSize, 04819 LPBOUNDED_DWORD_8K pcbBytesNeeded) 04820 { 04821 DWORD dwError = ERROR_SUCCESS; 04822 PSERVICE_HANDLE hSvc; 04823 PSERVICE lpService = NULL; 04824 HKEY hServiceKey = NULL; 04825 LPWSTR lpDescriptionW = NULL; 04826 04827 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n", 04828 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); 04829 04830 if (!lpBuffer) 04831 return ERROR_INVALID_ADDRESS; 04832 04833 if (ScmShutdown) 04834 return ERROR_SHUTDOWN_IN_PROGRESS; 04835 04836 hSvc = ScmGetServiceFromHandle(hService); 04837 if (hSvc == NULL) 04838 { 04839 DPRINT1("Invalid service handle!\n"); 04840 return ERROR_INVALID_HANDLE; 04841 } 04842 04843 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 04844 SERVICE_QUERY_CONFIG)) 04845 { 04846 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 04847 return ERROR_ACCESS_DENIED; 04848 } 04849 04850 lpService = hSvc->ServiceEntry; 04851 if (lpService == NULL) 04852 { 04853 DPRINT("lpService == NULL!\n"); 04854 return ERROR_INVALID_HANDLE; 04855 } 04856 04857 /* Lock the service database shared */ 04858 ScmLockDatabaseShared(); 04859 04860 dwError = ScmOpenServiceKey(lpService->lpServiceName, 04861 KEY_READ, 04862 &hServiceKey); 04863 if (dwError != ERROR_SUCCESS) 04864 goto done; 04865 04866 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 04867 { 04868 LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer; 04869 LPSTR lpStr; 04870 04871 dwError = ScmReadString(hServiceKey, 04872 L"Description", 04873 &lpDescriptionW); 04874 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 04875 goto done; 04876 04877 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA); 04878 if (dwError == ERROR_SUCCESS) 04879 *pcbBytesNeeded += ((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR)); 04880 04881 if (cbBufSize < *pcbBytesNeeded) 04882 { 04883 dwError = ERROR_INSUFFICIENT_BUFFER; 04884 goto done; 04885 } 04886 04887 if (dwError == ERROR_SUCCESS) 04888 { 04889 lpStr = (LPSTR)(lpServiceDescription + 1); 04890 04891 WideCharToMultiByte(CP_ACP, 04892 0, 04893 lpDescriptionW, 04894 -1, 04895 lpStr, 04896 wcslen(lpDescriptionW), 04897 NULL, 04898 NULL); 04899 lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 04900 } 04901 else 04902 { 04903 lpServiceDescription->lpDescription = NULL; 04904 dwError = ERROR_SUCCESS; 04905 goto done; 04906 } 04907 } 04908 else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS) 04909 { 04910 UNIMPLEMENTED; 04911 dwError = ERROR_CALL_NOT_IMPLEMENTED; 04912 goto done; 04913 } 04914 04915 done: 04916 /* Unlock the service database */ 04917 ScmUnlockDatabase(); 04918 04919 if (lpDescriptionW != NULL) 04920 HeapFree(GetProcessHeap(), 0, lpDescriptionW); 04921 04922 if (hServiceKey != NULL) 04923 RegCloseKey(hServiceKey); 04924 04925 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError); 04926 04927 return dwError; 04928 } 04929 04930 04931 /* Function 39 */ 04932 DWORD RQueryServiceConfig2W( 04933 SC_RPC_HANDLE hService, 04934 DWORD dwInfoLevel, 04935 LPBYTE lpBuffer, 04936 DWORD cbBufSize, 04937 LPBOUNDED_DWORD_8K pcbBytesNeeded) 04938 { 04939 DWORD dwError = ERROR_SUCCESS; 04940 PSERVICE_HANDLE hSvc; 04941 PSERVICE lpService = NULL; 04942 HKEY hServiceKey = NULL; 04943 DWORD dwRequiredSize; 04944 LPWSTR lpDescription = NULL; 04945 LPWSTR lpFailureCommand = NULL; 04946 LPWSTR lpRebootMessage = NULL; 04947 04948 DPRINT("RQueryServiceConfig2W() called\n"); 04949 04950 if (!lpBuffer) 04951 return ERROR_INVALID_ADDRESS; 04952 04953 if (ScmShutdown) 04954 return ERROR_SHUTDOWN_IN_PROGRESS; 04955 04956 hSvc = ScmGetServiceFromHandle(hService); 04957 if (hSvc == NULL) 04958 { 04959 DPRINT1("Invalid service handle!\n"); 04960 return ERROR_INVALID_HANDLE; 04961 } 04962 04963 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 04964 SERVICE_QUERY_CONFIG)) 04965 { 04966 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 04967 return ERROR_ACCESS_DENIED; 04968 } 04969 04970 lpService = hSvc->ServiceEntry; 04971 if (lpService == NULL) 04972 { 04973 DPRINT("lpService == NULL!\n"); 04974 return ERROR_INVALID_HANDLE; 04975 } 04976 04977 /* Lock the service database shared */ 04978 ScmLockDatabaseShared(); 04979 04980 dwError = ScmOpenServiceKey(lpService->lpServiceName, 04981 KEY_READ, 04982 &hServiceKey); 04983 if (dwError != ERROR_SUCCESS) 04984 goto done; 04985 04986 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) 04987 { 04988 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer; 04989 LPWSTR lpStr; 04990 04991 dwError = ScmReadString(hServiceKey, 04992 L"Description", 04993 &lpDescription); 04994 if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_NOT_FOUND) 04995 goto done; 04996 04997 *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONW); 04998 if (dwError == ERROR_SUCCESS) 04999 *pcbBytesNeeded += ((wcslen(lpDescription) + 1) * sizeof(WCHAR)); 05000 05001 if (cbBufSize < *pcbBytesNeeded) 05002 { 05003 dwError = ERROR_INSUFFICIENT_BUFFER; 05004 goto done; 05005 } 05006 05007 if (dwError == ERROR_SUCCESS) 05008 { 05009 lpStr = (LPWSTR)(lpServiceDescription + 1); 05010 wcscpy(lpStr, lpDescription); 05011 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription); 05012 } 05013 else 05014 { 05015 lpServiceDescription->lpDescription = NULL; 05016 dwError = ERROR_SUCCESS; 05017 } 05018 } 05019 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) 05020 { 05021 LPWSTR lpStr; 05022 LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer; 05023 05024 UNIMPLEMENTED; 05025 05026 dwError = ScmReadString(hServiceKey, 05027 L"FailureCommand", 05028 &lpFailureCommand); 05029 05030 dwError = ScmReadString(hServiceKey, 05031 L"RebootMessage", 05032 &lpRebootMessage); 05033 05034 dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW); 05035 05036 if (lpFailureCommand) 05037 dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR); 05038 05039 if (lpRebootMessage) 05040 dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR); 05041 05042 if (cbBufSize < dwRequiredSize) 05043 { 05044 *pcbBytesNeeded = dwRequiredSize; 05045 dwError = ERROR_INSUFFICIENT_BUFFER; 05046 goto done; 05047 } 05048 05049 lpFailureActions->cActions = 0; 05050 lpFailureActions->dwResetPeriod = 0; 05051 lpFailureActions->lpCommand = NULL; 05052 lpFailureActions->lpRebootMsg = NULL; 05053 lpFailureActions->lpsaActions = NULL; 05054 05055 lpStr = (LPWSTR)(lpFailureActions + 1); 05056 if (lpRebootMessage) 05057 { 05058 wcscpy(lpStr, lpRebootMessage); 05059 lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage); 05060 lpStr += wcslen(lpRebootMessage) + 1; 05061 } 05062 05063 if (lpFailureCommand) 05064 { 05065 wcscpy(lpStr, lpFailureCommand); 05066 lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand); 05067 lpStr += wcslen(lpRebootMessage) + 1; 05068 } 05069 dwError = STATUS_SUCCESS; 05070 goto done; 05071 } 05072 05073 done: 05074 /* Unlock the service database */ 05075 ScmUnlockDatabase(); 05076 05077 if (lpDescription != NULL) 05078 HeapFree(GetProcessHeap(), 0, lpDescription); 05079 05080 if (lpRebootMessage != NULL) 05081 HeapFree(GetProcessHeap(), 0, lpRebootMessage); 05082 05083 if (lpFailureCommand != NULL) 05084 HeapFree(GetProcessHeap(), 0, lpFailureCommand); 05085 05086 if (hServiceKey != NULL) 05087 RegCloseKey(hServiceKey); 05088 05089 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError); 05090 05091 return dwError; 05092 } 05093 05094 05095 /* Function 40 */ 05096 DWORD RQueryServiceStatusEx( 05097 SC_RPC_HANDLE hService, 05098 SC_STATUS_TYPE InfoLevel, 05099 LPBYTE lpBuffer, 05100 DWORD cbBufSize, 05101 LPBOUNDED_DWORD_8K pcbBytesNeeded) 05102 { 05103 LPSERVICE_STATUS_PROCESS lpStatus; 05104 PSERVICE_HANDLE hSvc; 05105 PSERVICE lpService; 05106 05107 DPRINT("RQueryServiceStatusEx() called\n"); 05108 05109 if (ScmShutdown) 05110 return ERROR_SHUTDOWN_IN_PROGRESS; 05111 05112 if (InfoLevel != SC_STATUS_PROCESS_INFO) 05113 return ERROR_INVALID_LEVEL; 05114 05115 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS); 05116 05117 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) 05118 return ERROR_INSUFFICIENT_BUFFER; 05119 05120 hSvc = ScmGetServiceFromHandle(hService); 05121 if (hSvc == NULL) 05122 { 05123 DPRINT1("Invalid service handle!\n"); 05124 return ERROR_INVALID_HANDLE; 05125 } 05126 05127 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, 05128 SERVICE_QUERY_STATUS)) 05129 { 05130 DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); 05131 return ERROR_ACCESS_DENIED; 05132 } 05133 05134 lpService = hSvc->ServiceEntry; 05135 if (lpService == NULL) 05136 { 05137 DPRINT("lpService == NULL!\n"); 05138 return ERROR_INVALID_HANDLE; 05139 } 05140 05141 /* Lock the service database shared */ 05142 ScmLockDatabaseShared(); 05143 05144 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer; 05145 05146 /* Return service status information */ 05147 RtlCopyMemory(lpStatus, 05148 &lpService->Status, 05149 sizeof(SERVICE_STATUS)); 05150 05151 lpStatus->dwProcessId = (lpService->lpImage != NULL) ? lpService->lpImage->dwProcessId : 0; /* FIXME */ 05152 lpStatus->dwServiceFlags = 0; /* FIXME */ 05153 05154 /* Unlock the service database */ 05155 ScmUnlockDatabase(); 05156 05157 return ERROR_SUCCESS; 05158 } 05159 05160 05161 /* Function 41 */ 05162 DWORD REnumServicesStatusExA( 05163 SC_RPC_HANDLE hSCManager, 05164 SC_ENUM_TYPE InfoLevel, 05165 DWORD dwServiceType, 05166 DWORD dwServiceState, 05167 LPBYTE lpBuffer, 05168 DWORD cbBufSize, 05169 LPBOUNDED_DWORD_256K pcbBytesNeeded, 05170 LPBOUNDED_DWORD_256K lpServicesReturned, 05171 LPBOUNDED_DWORD_256K lpResumeIndex, 05172 LPCSTR pszGroupName) 05173 { 05174 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL; 05175 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL; 05176 LPWSTR lpStringPtrW; 05177 LPSTR lpStringPtrA; 05178 LPWSTR pszGroupNameW = NULL; 05179 DWORD dwError; 05180 DWORD dwServiceCount; 05181 05182 DPRINT("REnumServicesStatusExA() called\n"); 05183 05184 if (pszGroupName) 05185 { 05186 pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR)); 05187 if (!pszGroupNameW) 05188 { 05189 DPRINT("Failed to allocate buffer!\n"); 05190 return ERROR_NOT_ENOUGH_MEMORY; 05191 } 05192 05193 MultiByteToWideChar(CP_ACP, 05194 0, 05195 pszGroupName, 05196 -1, 05197 pszGroupNameW, 05198 strlen(pszGroupName) + 1); 05199 } 05200 05201 if ((cbBufSize > 0) && (lpBuffer)) 05202 { 05203 lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize); 05204 if (!lpStatusPtrW) 05205 { 05206 DPRINT("Failed to allocate buffer!\n"); 05207 return ERROR_NOT_ENOUGH_MEMORY; 05208 } 05209 } 05210 05211 dwError = REnumServicesStatusExW(hSCManager, 05212 InfoLevel, 05213 dwServiceType, 05214 dwServiceState, 05215 (LPBYTE)lpStatusPtrW, 05216 cbBufSize, 05217 pcbBytesNeeded, 05218 lpServicesReturned, 05219 lpResumeIndex, 05220 pszGroupNameW); 05221 05222 /* if no services were returned then we are Done */ 05223 if (*lpServicesReturned == 0) 05224 goto Done; 05225 05226 lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer; 05227 lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer + 05228 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA)); 05229 lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 05230 *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 05231 05232 for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++) 05233 { 05234 /* Copy the service name */ 05235 WideCharToMultiByte(CP_ACP, 05236 0, 05237 lpStringPtrW, 05238 -1, 05239 lpStringPtrA, 05240 wcslen(lpStringPtrW), 05241 0, 05242 0); 05243 05244 lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 05245 lpStringPtrA += wcslen(lpStringPtrW) + 1; 05246 lpStringPtrW += wcslen(lpStringPtrW) + 1; 05247 05248 /* Copy the display name */ 05249 WideCharToMultiByte(CP_ACP, 05250 0, 05251 lpStringPtrW, 05252 -1, 05253 lpStringPtrA, 05254 wcslen(lpStringPtrW), 05255 0, 05256 0); 05257 05258 lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer); 05259 lpStringPtrA += wcslen(lpStringPtrW) + 1; 05260 lpStringPtrW += wcslen(lpStringPtrW) + 1; 05261 05262 /* Copy the status information */ 05263 memcpy(&lpStatusPtrA->ServiceStatusProcess, 05264 &lpStatusPtrW->ServiceStatusProcess, 05265 sizeof(SERVICE_STATUS)); 05266 05267 lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrW->ServiceStatusProcess.dwProcessId; /* FIXME */ 05268 lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 05269 lpStatusPtrA++; 05270 } 05271 05272 Done:; 05273 if (pszGroupNameW) 05274 HeapFree(GetProcessHeap(), 0, pszGroupNameW); 05275 05276 if (lpStatusPtrW) 05277 HeapFree(GetProcessHeap(), 0, lpStatusPtrW); 05278 05279 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError); 05280 05281 return dwError; 05282 } 05283 05284 05285 /* Function 42 */ 05286 DWORD REnumServicesStatusExW( 05287 SC_RPC_HANDLE hSCManager, 05288 SC_ENUM_TYPE InfoLevel, 05289 DWORD dwServiceType, 05290 DWORD dwServiceState, 05291 LPBYTE lpBuffer, 05292 DWORD cbBufSize, 05293 LPBOUNDED_DWORD_256K pcbBytesNeeded, 05294 LPBOUNDED_DWORD_256K lpServicesReturned, 05295 LPBOUNDED_DWORD_256K lpResumeIndex, 05296 LPCWSTR pszGroupName) 05297 { 05298 PMANAGER_HANDLE hManager; 05299 PSERVICE lpService; 05300 DWORD dwError = ERROR_SUCCESS; 05301 PLIST_ENTRY ServiceEntry; 05302 PSERVICE CurrentService; 05303 DWORD dwState; 05304 DWORD dwRequiredSize; 05305 DWORD dwServiceCount; 05306 DWORD dwSize; 05307 DWORD dwLastResumeCount = 0; 05308 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; 05309 LPWSTR lpStringPtr; 05310 05311 DPRINT("REnumServicesStatusExW() called\n"); 05312 05313 if (ScmShutdown) 05314 return ERROR_SHUTDOWN_IN_PROGRESS; 05315 05316 if (InfoLevel != SC_ENUM_PROCESS_INFO) 05317 return ERROR_INVALID_LEVEL; 05318 05319 hManager = ScmGetServiceManagerFromHandle(hSCManager); 05320 if (hManager == NULL) 05321 { 05322 DPRINT1("Invalid service manager handle!\n"); 05323 return ERROR_INVALID_HANDLE; 05324 } 05325 05326 *pcbBytesNeeded = 0; 05327 *lpServicesReturned = 0; 05328 05329 if ((dwServiceType == 0) || 05330 ((dwServiceType & ~(SERVICE_DRIVER | SERVICE_WIN32)) != 0)) 05331 { 05332 DPRINT("Not a valid Service Type!\n"); 05333 return ERROR_INVALID_PARAMETER; 05334 } 05335 05336 if ((dwServiceState != SERVICE_ACTIVE) && 05337 (dwServiceState != SERVICE_INACTIVE) && 05338 (dwServiceState != SERVICE_STATE_ALL)) 05339 { 05340 DPRINT("Not a valid Service State!\n"); 05341 return ERROR_INVALID_PARAMETER; 05342 } 05343 05344 /* Check access rights */ 05345 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess, 05346 SC_MANAGER_ENUMERATE_SERVICE)) 05347 { 05348 DPRINT("Insufficient access rights! 0x%lx\n", 05349 hManager->Handle.DesiredAccess); 05350 return ERROR_ACCESS_DENIED; 05351 } 05352 05353 if (lpResumeIndex) 05354 dwLastResumeCount = *lpResumeIndex; 05355 05356 /* Lock the service database shared */ 05357 ScmLockDatabaseShared(); 05358 05359 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); 05360 if (lpService == NULL) 05361 { 05362 dwError = ERROR_SUCCESS; 05363 goto Done; 05364 } 05365 05366 dwRequiredSize = 0; 05367 dwServiceCount = 0; 05368 05369 for (ServiceEntry = &lpService->ServiceListEntry; 05370 ServiceEntry != &ServiceListHead; 05371 ServiceEntry = ServiceEntry->Flink) 05372 { 05373 CurrentService = CONTAINING_RECORD(ServiceEntry, 05374 SERVICE, 05375 ServiceListEntry); 05376 05377 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 05378 continue; 05379 05380 dwState = SERVICE_ACTIVE; 05381 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 05382 dwState = SERVICE_INACTIVE; 05383 05384 if ((dwState & dwServiceState) == 0) 05385 continue; 05386 05387 if (pszGroupName) 05388 { 05389 if (*pszGroupName == 0) 05390 { 05391 if (CurrentService->lpGroup != NULL) 05392 continue; 05393 } 05394 else 05395 { 05396 if ((CurrentService->lpGroup == NULL) || 05397 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName)) 05398 continue; 05399 } 05400 } 05401 05402 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 05403 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 05404 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 05405 05406 if (dwRequiredSize + dwSize <= cbBufSize) 05407 { 05408 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName); 05409 dwRequiredSize += dwSize; 05410 dwServiceCount++; 05411 dwLastResumeCount = CurrentService->dwResumeCount; 05412 } 05413 else 05414 { 05415 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName); 05416 break; 05417 } 05418 05419 } 05420 05421 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize); 05422 DPRINT("dwServiceCount: %lu\n", dwServiceCount); 05423 05424 for (; 05425 ServiceEntry != &ServiceListHead; 05426 ServiceEntry = ServiceEntry->Flink) 05427 { 05428 CurrentService = CONTAINING_RECORD(ServiceEntry, 05429 SERVICE, 05430 ServiceListEntry); 05431 05432 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 05433 continue; 05434 05435 dwState = SERVICE_ACTIVE; 05436 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 05437 dwState = SERVICE_INACTIVE; 05438 05439 if ((dwState & dwServiceState) == 0) 05440 continue; 05441 05442 if (pszGroupName) 05443 { 05444 if (*pszGroupName == 0) 05445 { 05446 if (CurrentService->lpGroup != NULL) 05447 continue; 05448 } 05449 else 05450 { 05451 if ((CurrentService->lpGroup == NULL) || 05452 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName)) 05453 continue; 05454 } 05455 } 05456 05457 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 05458 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 05459 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR))); 05460 05461 dwError = ERROR_MORE_DATA; 05462 } 05463 05464 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); 05465 05466 if (lpResumeIndex) 05467 *lpResumeIndex = dwLastResumeCount; 05468 05469 *lpServicesReturned = dwServiceCount; 05470 *pcbBytesNeeded = dwRequiredSize; 05471 05472 /* If there was no services that matched */ 05473 if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA)) 05474 { 05475 dwError = ERROR_SERVICE_DOES_NOT_EXIST; 05476 goto Done; 05477 } 05478 05479 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer; 05480 lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + 05481 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW)); 05482 05483 dwRequiredSize = 0; 05484 for (ServiceEntry = &lpService->ServiceListEntry; 05485 ServiceEntry != &ServiceListHead; 05486 ServiceEntry = ServiceEntry->Flink) 05487 { 05488 CurrentService = CONTAINING_RECORD(ServiceEntry, 05489 SERVICE, 05490 ServiceListEntry); 05491 05492 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0) 05493 continue; 05494 05495 dwState = SERVICE_ACTIVE; 05496 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED) 05497 dwState = SERVICE_INACTIVE; 05498 05499 if ((dwState & dwServiceState) == 0) 05500 continue; 05501 05502 if (pszGroupName) 05503 { 05504 if (*pszGroupName == 0) 05505 { 05506 if (CurrentService->lpGroup != NULL) 05507 continue; 05508 } 05509 else 05510 { 05511 if ((CurrentService->lpGroup == NULL) || 05512 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName)) 05513 continue; 05514 } 05515 } 05516 05517 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + 05518 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + 05519 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); 05520 05521 if (dwRequiredSize + dwSize <= cbBufSize) 05522 { 05523 /* Copy the service name */ 05524 wcscpy(lpStringPtr, 05525 CurrentService->lpServiceName); 05526 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 05527 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1); 05528 05529 /* Copy the display name */ 05530 wcscpy(lpStringPtr, 05531 CurrentService->lpDisplayName); 05532 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer); 05533 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1); 05534 05535 /* Copy the status information */ 05536 memcpy(&lpStatusPtr->ServiceStatusProcess, 05537 &CurrentService->Status, 05538 sizeof(SERVICE_STATUS)); 05539 lpStatusPtr->ServiceStatusProcess.dwProcessId = 05540 (CurrentService->lpImage != NULL) ? CurrentService->lpImage->dwProcessId : 0; /* FIXME */ 05541 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ 05542 05543 lpStatusPtr++; 05544 dwRequiredSize += dwSize; 05545 } 05546 else 05547 { 05548 break; 05549 } 05550 } 05551 05552 if (dwError == 0) 05553 { 05554 *pcbBytesNeeded = 0; 05555 if (lpResumeIndex) 05556 *lpResumeIndex = 0; 05557 } 05558 05559 Done:; 05560 /* Unlock the service database */ 05561 ScmUnlockDatabase(); 05562 05563 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError); 05564 05565 return dwError; 05566 } 05567 05568 05569 /* Function 43 */ 05570 DWORD RSendTSMessage( 05571 handle_t BindingHandle) /* FIXME */ 05572 { 05573 UNIMPLEMENTED; 05574 return ERROR_CALL_NOT_IMPLEMENTED; 05575 } 05576 05577 05578 /* Function 44 */ 05579 DWORD RCreateServiceWOW64A( 05580 handle_t BindingHandle, 05581 LPSTR lpServiceName, 05582 LPSTR lpDisplayName, 05583 DWORD dwDesiredAccess, 05584 DWORD dwServiceType, 05585 DWORD dwStartType, 05586 DWORD dwErrorControl, 05587 LPSTR lpBinaryPathName, 05588 LPSTR lpLoadOrderGroup, 05589 LPDWORD lpdwTagId, 05590 LPBYTE lpDependencies, 05591 DWORD dwDependSize, 05592 LPSTR lpServiceStartName, 05593 LPBYTE lpPassword, 05594 DWORD dwPwSize, 05595 LPSC_RPC_HANDLE lpServiceHandle) 05596 { 05597 UNIMPLEMENTED; 05598 return ERROR_CALL_NOT_IMPLEMENTED; 05599 } 05600 05601 05602 /* Function 45 */ 05603 DWORD RCreateServiceWOW64W( 05604 handle_t BindingHandle, 05605 LPWSTR lpServiceName, 05606 LPWSTR lpDisplayName, 05607 DWORD dwDesiredAccess, 05608 DWORD dwServiceType, 05609 DWORD dwStartType, 05610 DWORD dwErrorControl, 05611 LPWSTR lpBinaryPathName, 05612 LPWSTR lpLoadOrderGroup, 05613 LPDWORD lpdwTagId, 05614 LPBYTE lpDependencies, 05615 DWORD dwDependSize, 05616 LPWSTR lpServiceStartName, 05617 LPBYTE lpPassword, 05618 DWORD dwPwSize, 05619 LPSC_RPC_HANDLE lpServiceHandle) 05620 { 05621 UNIMPLEMENTED; 05622 return ERROR_CALL_NOT_IMPLEMENTED; 05623 } 05624 05625 05626 /* Function 46 */ 05627 DWORD RQueryServiceTagInfo( 05628 handle_t BindingHandle) /* FIXME */ 05629 { 05630 UNIMPLEMENTED; 05631 return ERROR_CALL_NOT_IMPLEMENTED; 05632 } 05633 05634 05635 /* Function 47 */ 05636 DWORD RNotifyServiceStatusChange( 05637 SC_RPC_HANDLE hService, 05638 SC_RPC_NOTIFY_PARAMS NotifyParams, 05639 GUID *pClientProcessGuid, 05640 GUID *pSCMProcessGuid, 05641 PBOOL pfCreateRemoteQueue, 05642 LPSC_NOTIFY_RPC_HANDLE phNotify) 05643 { 05644 UNIMPLEMENTED; 05645 return ERROR_CALL_NOT_IMPLEMENTED; 05646 } 05647 05648 05649 /* Function 48 */ 05650 DWORD RGetNotifyResults( 05651 SC_NOTIFY_RPC_HANDLE hNotify, 05652 PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams) 05653 { 05654 UNIMPLEMENTED; 05655 return ERROR_CALL_NOT_IMPLEMENTED; 05656 } 05657 05658 05659 /* Function 49 */ 05660 DWORD RCloseNotifyHandle( 05661 LPSC_NOTIFY_RPC_HANDLE phNotify, 05662 PBOOL pfApcFired) 05663 { 05664 UNIMPLEMENTED; 05665 return ERROR_CALL_NOT_IMPLEMENTED; 05666 } 05667 05668 05669 /* Function 50 */ 05670 DWORD RControlServiceExA( 05671 SC_RPC_HANDLE hService, 05672 DWORD dwControl, 05673 DWORD dwInfoLevel) 05674 { 05675 UNIMPLEMENTED; 05676 return ERROR_CALL_NOT_IMPLEMENTED; 05677 } 05678 05679 05680 /* Function 51 */ 05681 DWORD RControlServiceExW( 05682 SC_RPC_HANDLE hService, 05683 DWORD dwControl, 05684 DWORD dwInfoLevel) 05685 { 05686 UNIMPLEMENTED; 05687 return ERROR_CALL_NOT_IMPLEMENTED; 05688 } 05689 05690 05691 /* Function 52 */ 05692 DWORD RSendPnPMessage( 05693 handle_t BindingHandle) /* FIXME */ 05694 { 05695 UNIMPLEMENTED; 05696 return ERROR_CALL_NOT_IMPLEMENTED; 05697 } 05698 05699 05700 /* Function 53 */ 05701 DWORD RValidatePnPService( 05702 handle_t BindingHandle) /* FIXME */ 05703 { 05704 UNIMPLEMENTED; 05705 return ERROR_CALL_NOT_IMPLEMENTED; 05706 } 05707 05708 05709 /* Function 54 */ 05710 DWORD ROpenServiceStatusHandle( 05711 handle_t BindingHandle) /* FIXME */ 05712 { 05713 UNIMPLEMENTED; 05714 return ERROR_CALL_NOT_IMPLEMENTED; 05715 } 05716 05717 05718 /* Function 55 */ 05719 DWORD RFunction55( 05720 handle_t BindingHandle) /* FIXME */ 05721 { 05722 UNIMPLEMENTED; 05723 return ERROR_CALL_NOT_IMPLEMENTED; 05724 } 05725 05726 05727 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len) 05728 { 05729 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); 05730 } 05731 05732 05733 void __RPC_USER midl_user_free(void __RPC_FAR * ptr) 05734 { 05735 HeapFree(GetProcessHeap(), 0, ptr); 05736 } 05737 05738 05739 void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject) 05740 { 05741 } 05742 05743 05744 void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock) 05745 { 05746 } 05747 05748 05749 void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify) 05750 { 05751 } 05752 05753 /* EOF */ Generated on Sun May 27 2012 04:17:56 for ReactOS by
1.7.6.1
|