diff --git a/base/system/services/database.c b/base/system/services/database.c index 1b7b2e67af915..a46e2de8372df 100644 --- a/base/system/services/database.c +++ b/base/system/services/database.c @@ -1311,180 +1311,14 @@ ScmGetBootAndSystemDriverState(VOID) DWORD -ScmControlService(HANDLE hControlPipe, - PWSTR pServiceName, - SERVICE_STATUS_HANDLE hServiceStatus, - DWORD dwControl) -{ - PSCM_CONTROL_PACKET ControlPacket; - SCM_REPLY_PACKET ReplyPacket; - - DWORD dwWriteCount = 0; - DWORD dwReadCount = 0; - DWORD PacketSize; - PWSTR Ptr; - DWORD dwError = ERROR_SUCCESS; - BOOL bResult; - OVERLAPPED Overlapped = {0}; - - DPRINT("ScmControlService() called\n"); - - /* Acquire the service control critical section, to synchronize requests */ - EnterCriticalSection(&ControlServiceCriticalSection); - - /* Calculate the total length of the start command line */ - PacketSize = sizeof(SCM_CONTROL_PACKET); - PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR)); - - ControlPacket = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - PacketSize); - if (ControlPacket == NULL) - { - LeaveCriticalSection(&ControlServiceCriticalSection); - return ERROR_NOT_ENOUGH_MEMORY; - } - - ControlPacket->dwSize = PacketSize; - ControlPacket->dwControl = dwControl; - ControlPacket->hServiceStatus = hServiceStatus; - - ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET); - - Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset); - wcscpy(Ptr, pServiceName); - - ControlPacket->dwArgumentsCount = 0; - ControlPacket->dwArgumentsOffset = 0; - - bResult = WriteFile(hControlPipe, - ControlPacket, - PacketSize, - &dwWriteCount, - &Overlapped); - if (bResult == FALSE) - { - DPRINT("WriteFile() returned FALSE\n"); - - dwError = GetLastError(); - if (dwError == ERROR_IO_PENDING) - { - DPRINT("dwError: ERROR_IO_PENDING\n"); - - dwError = WaitForSingleObject(hControlPipe, - PipeTimeout); - DPRINT("WaitForSingleObject() returned %lu\n", dwError); - - if (dwError == WAIT_TIMEOUT) - { - bResult = CancelIo(hControlPipe); - if (bResult == FALSE) - { - DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError()); - } - - dwError = ERROR_SERVICE_REQUEST_TIMEOUT; - goto Done; - } - else if (dwError == WAIT_OBJECT_0) - { - bResult = GetOverlappedResult(hControlPipe, - &Overlapped, - &dwWriteCount, - TRUE); - if (bResult == FALSE) - { - dwError = GetLastError(); - DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError); - - goto Done; - } - } - } - else - { - DPRINT1("WriteFile() failed (Error %lu)\n", dwError); - goto Done; - } - } - - /* Read the reply */ - Overlapped.hEvent = (HANDLE) NULL; - - bResult = ReadFile(hControlPipe, - &ReplyPacket, - sizeof(SCM_REPLY_PACKET), - &dwReadCount, - &Overlapped); - if (bResult == FALSE) - { - DPRINT("ReadFile() returned FALSE\n"); - - dwError = GetLastError(); - if (dwError == ERROR_IO_PENDING) - { - DPRINT("dwError: ERROR_IO_PENDING\n"); - - dwError = WaitForSingleObject(hControlPipe, - PipeTimeout); - DPRINT("WaitForSingleObject() returned %lu\n", dwError); - - if (dwError == WAIT_TIMEOUT) - { - bResult = CancelIo(hControlPipe); - if (bResult == FALSE) - { - DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError()); - } - - dwError = ERROR_SERVICE_REQUEST_TIMEOUT; - goto Done; - } - else if (dwError == WAIT_OBJECT_0) - { - bResult = GetOverlappedResult(hControlPipe, - &Overlapped, - &dwReadCount, - TRUE); - if (bResult == FALSE) - { - dwError = GetLastError(); - DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError); - - goto Done; - } - } - } - else - { - DPRINT1("ReadFile() failed (Error %lu)\n", dwError); - goto Done; - } - } - -Done: - /* Release the control packet */ - HeapFree(GetProcessHeap(), - 0, - ControlPacket); - - if (dwReadCount == sizeof(SCM_REPLY_PACKET)) - { - dwError = ReplyPacket.dwError; - } - - LeaveCriticalSection(&ControlServiceCriticalSection); - - DPRINT("ScmControlService() done\n"); - - return dwError; -} - - -static DWORD -ScmSendStartCommand(PSERVICE Service, - DWORD argc, - LPWSTR* argv) +ScmControlServiceEx( + _In_ PCWSTR pServiceName, + _In_ DWORD dwControl, + _In_ HANDLE hControlPipe, + _In_ SERVICE_STATUS_HANDLE hServiceStatus, + _In_opt_ DWORD dwServiceTag, + _In_opt_ DWORD argc, + _In_reads_opt_(argc) LPWSTR* argv) { DWORD dwError = ERROR_SUCCESS; PSCM_CONTROL_PACKET ControlPacket; @@ -1492,18 +1326,16 @@ ScmSendStartCommand(PSERVICE Service, DWORD PacketSize; DWORD i; PWSTR Ptr; - PWSTR *pOffPtr; - PWSTR pArgPtr; BOOL bResult; DWORD dwWriteCount = 0; DWORD dwReadCount = 0; OVERLAPPED Overlapped = {0}; - DPRINT("ScmSendStartCommand() called\n"); + DPRINT("ScmControlService('%S', dwControl = %d) called\n", pServiceName, dwControl); /* Calculate the total length of the start command line */ PacketSize = sizeof(SCM_CONTROL_PACKET); - PacketSize += (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR)); + PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR)); /* * Calculate the required packet size for the start argument vector 'argv', @@ -1528,20 +1360,18 @@ ScmSendStartCommand(PSERVICE Service, /* Allocate a control packet */ ControlPacket = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PacketSize); - if (ControlPacket == NULL) + if (!ControlPacket) return ERROR_NOT_ENOUGH_MEMORY; ControlPacket->dwSize = PacketSize; - ControlPacket->dwControl = (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS) - ? SERVICE_CONTROL_START_OWN - : SERVICE_CONTROL_START_SHARE; - ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; + ControlPacket->dwControl = dwControl; + ControlPacket->hServiceStatus = hServiceStatus; ControlPacket->dwServiceTag = Service->dwServiceTag; /* Copy the start command line */ ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET); Ptr = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset); - wcscpy(Ptr, Service->lpServiceName); + wcscpy(Ptr, pServiceName); ControlPacket->dwArgumentsCount = 0; ControlPacket->dwArgumentsOffset = 0; @@ -1549,7 +1379,10 @@ ScmSendStartCommand(PSERVICE Service, /* Copy the argument vector */ if (argc > 0 && argv != NULL) { - Ptr += wcslen(Service->lpServiceName) + 1; + PWSTR *pOffPtr; + PWSTR pArgPtr; + + Ptr += wcslen(pServiceName) + 1; pOffPtr = (PWSTR*)ALIGN_UP_POINTER(Ptr, PWSTR); pArgPtr = (PWSTR)((ULONG_PTR)pOffPtr + argc * sizeof(PWSTR)); @@ -1568,12 +1401,15 @@ ScmSendStartCommand(PSERVICE Service, } } - bResult = WriteFile(Service->lpImage->hControlPipe, + /* Acquire the service control critical section, to synchronize requests */ + EnterCriticalSection(&ControlServiceCriticalSection); + + bResult = WriteFile(hControlPipe, ControlPacket, PacketSize, &dwWriteCount, &Overlapped); - if (bResult == FALSE) + if (!bResult) { DPRINT("WriteFile() returned FALSE\n"); @@ -1582,32 +1418,29 @@ ScmSendStartCommand(PSERVICE Service, { DPRINT("dwError: ERROR_IO_PENDING\n"); - dwError = WaitForSingleObject(Service->lpImage->hControlPipe, + dwError = WaitForSingleObject(hControlPipe, PipeTimeout); DPRINT("WaitForSingleObject() returned %lu\n", dwError); if (dwError == WAIT_TIMEOUT) { - bResult = CancelIo(Service->lpImage->hControlPipe); - if (bResult == FALSE) - { + bResult = CancelIo(hControlPipe); + if (!bResult) DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError()); - } dwError = ERROR_SERVICE_REQUEST_TIMEOUT; goto Done; } else if (dwError == WAIT_OBJECT_0) { - bResult = GetOverlappedResult(Service->lpImage->hControlPipe, + bResult = GetOverlappedResult(hControlPipe, &Overlapped, &dwWriteCount, TRUE); - if (bResult == FALSE) + if (!bResult) { dwError = GetLastError(); DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError); - goto Done; } } @@ -1620,14 +1453,14 @@ ScmSendStartCommand(PSERVICE Service, } /* Read the reply */ - Overlapped.hEvent = (HANDLE) NULL; + Overlapped.hEvent = NULL; - bResult = ReadFile(Service->lpImage->hControlPipe, + bResult = ReadFile(hControlPipe, &ReplyPacket, - sizeof(SCM_REPLY_PACKET), + sizeof(ReplyPacket), &dwReadCount, &Overlapped); - if (bResult == FALSE) + if (!bResult) { DPRINT("ReadFile() returned FALSE\n"); @@ -1636,32 +1469,29 @@ ScmSendStartCommand(PSERVICE Service, { DPRINT("dwError: ERROR_IO_PENDING\n"); - dwError = WaitForSingleObject(Service->lpImage->hControlPipe, + dwError = WaitForSingleObject(hControlPipe, PipeTimeout); DPRINT("WaitForSingleObject() returned %lu\n", dwError); if (dwError == WAIT_TIMEOUT) { - bResult = CancelIo(Service->lpImage->hControlPipe); - if (bResult == FALSE) - { + bResult = CancelIo(hControlPipe); + if (!bResult) DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError()); - } dwError = ERROR_SERVICE_REQUEST_TIMEOUT; goto Done; } else if (dwError == WAIT_OBJECT_0) { - bResult = GetOverlappedResult(Service->lpImage->hControlPipe, + bResult = GetOverlappedResult(hControlPipe, &Overlapped, &dwReadCount, TRUE); - if (bResult == FALSE) + if (!bResult) { dwError = GetLastError(); DPRINT1("GetOverlappedResult() failed (Error %lu)\n", dwError); - goto Done; } } @@ -1674,21 +1504,49 @@ ScmSendStartCommand(PSERVICE Service, } Done: - /* Release the control packet */ - HeapFree(GetProcessHeap(), - 0, - ControlPacket); + /* Release the service control critical section */ + LeaveCriticalSection(&ControlServiceCriticalSection); - if (dwReadCount == sizeof(SCM_REPLY_PACKET)) - { - dwError = ReplyPacket.dwError; - } + /* Free the control packet */ + HeapFree(GetProcessHeap(), 0, ControlPacket); - DPRINT("ScmSendStartCommand() done\n"); + if (dwReadCount == sizeof(ReplyPacket)) + dwError = ReplyPacket.dwError; + DPRINT("ScmControlService() done\n"); return dwError; } +DWORD +ScmControlService( + _In_ PCWSTR pServiceName, + _In_ DWORD dwControl, + _In_ HANDLE hControlPipe, + _In_ SERVICE_STATUS_HANDLE hServiceStatus) +{ + return ScmControlServiceEx(pServiceName, + dwControl, + hControlPipe, + hServiceStatus, + 0, 0, NULL); +} + +static DWORD +ScmSendStartCommand( + _In_ PSERVICE Service, + _In_opt_ DWORD argc, + _In_reads_opt_(argc) LPWSTR* argv) +{ + /* Send the start command and return */ + return ScmControlServiceEx(Service->lpServiceName, + (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS) + ? SERVICE_CONTROL_START_OWN : SERVICE_CONTROL_START_SHARE, + Service->lpImage->hControlPipe, + (SERVICE_STATUS_HANDLE)Service, + Service->dwServiceTag, + argc, argv); +} + static DWORD ScmWaitForServiceConnect(PSERVICE Service) @@ -1771,7 +1629,7 @@ ScmWaitForServiceConnect(PSERVICE Service) DPRINT("Control pipe connected\n"); - Overlapped.hEvent = (HANDLE) NULL; + Overlapped.hEvent = NULL; /* Read the process id from pipe */ bResult = ReadFile(Service->lpImage->hControlPipe, @@ -2400,10 +2258,10 @@ ScmAutoShutdownServices(VOID) { /* Send the shutdown notification */ DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName); - ScmControlService(CurrentService->lpImage->hControlPipe, - CurrentService->lpServiceName, - (SERVICE_STATUS_HANDLE)CurrentService, - SERVICE_CONTROL_SHUTDOWN); + ScmControlService(CurrentService->lpServiceName, + SERVICE_CONTROL_SHUTDOWN, + CurrentService->lpImage->hControlPipe, + (SERVICE_STATUS_HANDLE)CurrentService); } ServiceEntry = ServiceEntry->Flink; diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index c84b67e6b246f..3ad015c80019c 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -1249,10 +1249,10 @@ RControlService( } /* Send control code to the service */ - dwError = ScmControlService(lpService->lpImage->hControlPipe, - lpService->lpServiceName, - (SERVICE_STATUS_HANDLE)lpService, - dwControl); + dwError = ScmControlService(lpService->lpServiceName, + dwControl, + lpService->lpImage->hControlPipe, + (SERVICE_STATUS_HANDLE)lpService); /* Return service status information */ RtlCopyMemory(lpServiceStatus, @@ -1765,10 +1765,10 @@ RSetServiceStatus( if (lpService->lpImage->dwImageRunCount == 0) { /* Stop the dispatcher thread */ - ScmControlService(lpService->lpImage->hControlPipe, - L"", - (SERVICE_STATUS_HANDLE)lpService, - SERVICE_CONTROL_STOP); + ScmControlService(L"", + SERVICE_CONTROL_STOP, + lpService->lpImage->hControlPipe, + (SERVICE_STATUS_HANDLE)lpService); /* Remove the service image */ ScmRemoveServiceImage(lpService->lpImage); diff --git a/base/system/services/services.h b/base/system/services/services.h index c333c10d47615..7fdff56ebdd01 100644 --- a/base/system/services/services.h +++ b/base/system/services/services.h @@ -18,10 +18,12 @@ #include #include #include + #define NTOS_MODE_USER #include #include #include + #include #include @@ -197,10 +199,12 @@ DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, VOID ScmDeleteServiceRecord(PSERVICE lpService); DWORD ScmMarkServiceForDelete(PSERVICE pService); -DWORD ScmControlService(HANDLE hControlPipe, - PWSTR pServiceName, - SERVICE_STATUS_HANDLE hServiceStatus, - DWORD dwControl); +DWORD +ScmControlService( + _In_ PCWSTR pServiceName, + _In_ DWORD dwControl, + _In_ HANDLE hControlPipe, + _In_ SERVICE_STATUS_HANDLE hServiceStatus); BOOL ScmLockDatabaseExclusive(VOID); BOOL ScmLockDatabaseShared(VOID);