diff --git a/reactos/include/idl/svcctl.idl b/reactos/include/idl/svcctl.idl index 7b592cee2c0..105d2f019c8 100644 --- a/reactos/include/idl/svcctl.idl +++ b/reactos/include/idl/svcctl.idl @@ -9,7 +9,9 @@ #define BOOL unsigned long #define SC_HANDLE unsigned int #define SC_LOCK unsigned int +#define LPSTR char* #define LPCSTR char* +#define LPWSTR wchar_t* #define LPCWSTR wchar_t* #define LPDWORD unsigned long* @@ -127,6 +129,14 @@ cpp_quote("#endif") [out] SC_HANDLE *hScm); + /* Function 20 */ + DWORD ScmrGetServiceDisplayNameW([in] handle_t BindingHandle, + [in] SC_HANDLE hSCManager, + [in, string, ref] LPCWSTR lpServiceName, + [out, size_is(*lpcchBuffer), unique] LPWSTR lpDisplayName, + [in, out, ref] LPDWORD lpcchBuffer); + + /* Function 27 */ DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle, [in, string, unique] LPCSTR lpMachineName, diff --git a/reactos/lib/advapi32/service/scm.c b/reactos/lib/advapi32/service/scm.c index 36a9285a2d1..5de26b7ba97 100644 --- a/reactos/lib/advapi32/service/scm.c +++ b/reactos/lib/advapi32/service/scm.c @@ -566,19 +566,33 @@ GetServiceDisplayNameA( /********************************************************************** * GetServiceDisplayNameW * - * @unimplemented + * @implemented */ -BOOL -STDCALL -GetServiceDisplayNameW( - SC_HANDLE hSCManager, - LPCWSTR lpServiceName, - LPWSTR lpDisplayName, - LPDWORD lpcchBuffer) +BOOL STDCALL +GetServiceDisplayNameW(SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + LPWSTR lpDisplayName, + LPDWORD lpcchBuffer) { - DPRINT1("GetServiceDisplayNameW is unimplemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + DWORD dwError; + + DPRINT("GetServiceDisplayNameW() called\n"); + + HandleBind(); + + dwError = ScmrGetServiceDisplayNameW(BindingHandle, + (unsigned int)hSCManager, + (LPWSTR)lpServiceName, + lpDisplayName, + lpcchBuffer); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrGetServiceDisplayNameW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return FALSE; + } + + return TRUE; } @@ -606,14 +620,33 @@ GetServiceKeyNameA( * * @unimplemented */ -BOOL -STDCALL -GetServiceKeyNameW( - SC_HANDLE hSCManager, - LPCWSTR lpDisplayName, - LPWSTR lpServiceName, - LPDWORD lpcchBuffer) +BOOL STDCALL +GetServiceKeyNameW(SC_HANDLE hSCManager, + LPCWSTR lpDisplayName, + LPWSTR lpServiceName, + LPDWORD lpcchBuffer) { +#if 0 + DWORD dwError; + + DPRINT("GetServiceKeyNameW() called\n"); + + HandleBind(); + + dwError = ScmrGetServiceKeyNameW(BindingHandle, + (unsigned int)hSCManager, + (LPWSTR)lpDisplayName, + lpServiceName, + lpcchBuffer); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrGetServiceKeyNameW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return FALSE; + } + + return TRUE; +#endif DPRINT1("GetServiceKeyNameW is unimplemented\n"); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; diff --git a/reactos/subsys/system/services/database.c b/reactos/subsys/system/services/database.c index 2c28e9da7eb..1e1179eb957 100644 --- a/reactos/subsys/system/services/database.c +++ b/reactos/subsys/system/services/database.c @@ -84,6 +84,35 @@ ScmGetServiceEntryByName(LPWSTR lpServiceName) } +PSERVICE +ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName) +{ + PLIST_ENTRY ServiceEntry; + PSERVICE CurrentService; + + DPRINT("ScmGetServiceEntryByDisplayName() called\n"); + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, + SERVICE, + ServiceListEntry); + if (_wcsicmp(CurrentService->lpDisplayName, lpDisplayName) == 0) + { + DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName); + return CurrentService; + } + + ServiceEntry = ServiceEntry->Flink; + } + + DPRINT("Couldn't find a matching service\n"); + + return NULL; +} + + static NTSTATUS STDCALL CreateGroupOrderListRoutine(PWSTR ValueName, ULONG ValueType, @@ -204,6 +233,7 @@ CreateServiceListEntry(LPWSTR lpServiceName) /* Copy service name */ wcscpy(Service->szServiceName, lpServiceName); Service->lpServiceName = Service->szServiceName; + Service->lpDisplayName = Service->lpServiceName; /* Get service data */ RtlZeroMemory(&QueryTable, @@ -284,6 +314,7 @@ ScmCreateNewServiceRecord(LPWSTR lpServiceName, /* Copy service name */ wcscpy(lpService->szServiceName, lpServiceName); lpService->lpServiceName = lpService->szServiceName; + lpService->lpDisplayName = lpService->lpServiceName; /* Append service entry */ InsertTailList(&ServiceListHead, diff --git a/reactos/subsys/system/services/rpcserver.c b/reactos/subsys/system/services/rpcserver.c index 64da1b8731f..27b04060163 100644 --- a/reactos/subsys/system/services/rpcserver.c +++ b/reactos/subsys/system/services/rpcserver.c @@ -283,6 +283,9 @@ ScmrControlService(handle_t BindingHandle, DPRINT1("ScmrControlService() called\n"); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + hSvc = (PSERVICE_HANDLE)hService; if (hSvc->Handle.Tag != SERVICE_TAG) { @@ -325,6 +328,9 @@ ScmrDeleteService(handle_t BindingHandle, DPRINT1("ScmrDeleteService() called\n"); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + hSvc = (PSERVICE_HANDLE)hService; if (hSvc->Handle.Tag != SERVICE_TAG) return ERROR_INVALID_HANDLE; @@ -409,6 +415,9 @@ ScmrQueryServiceStatus(handle_t BindingHandle, DPRINT("ScmrQueryServiceStatus() called\n"); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + hSvc = (PSERVICE_HANDLE)hService; if (hSvc->Handle.Tag != SERVICE_TAG) { @@ -488,6 +497,10 @@ ScmrChangeServiceConfigW(handle_t BiningHandle, unsigned long dwPasswordLength, wchar_t *lpDisplayName) { + DWORD dwError = ERROR_SUCCESS; + PSERVICE_HANDLE hSvc; + PSERVICE lpService = NULL; + DPRINT1("ScmrChangeServiceConfigW() called\n"); DPRINT1("dwServiceType = %lu\n", dwServiceType); DPRINT1("dwStartType = %lu\n", dwStartType); @@ -496,7 +509,35 @@ ScmrChangeServiceConfigW(handle_t BiningHandle, DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); DPRINT1("lpDisplayName = %S\n", lpDisplayName); - return ERROR_SUCCESS; + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + + hSvc = (PSERVICE_HANDLE)hService; + if (hSvc->Handle.Tag != SERVICE_TAG) + { + DPRINT1("Invalid handle tag!\n"); + return ERROR_INVALID_HANDLE; + } + + if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess, + SERVICE_CHANGE_CONFIG)) + { + DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess); + return ERROR_ACCESS_DENIED; + } + + lpService = hSvc->ServiceEntry; + if (lpService == NULL) + { + DPRINT1("lpService == NULL!\n"); + return ERROR_INVALID_HANDLE; + } + + /* FIXME: ... */ + + DPRINT1("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError); + + return dwError; } @@ -580,6 +621,9 @@ ScmrCreateServiceW(handle_t BindingHandle, DPRINT1("lpBinaryPathName = %S\n", lpBinaryPathName); DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + hManager = (PMANAGER_HANDLE)hSCManager; if (hManager->Handle.Tag != MANAGER_TAG) { @@ -625,6 +669,23 @@ ScmrCreateServiceW(handle_t BindingHandle, lpService->dwStartType = dwStartType; lpService->dwErrorControl = dwErrorControl; + /* Fill the display name */ + if (lpDisplayName != NULL && + *lpDisplayName != 0 && + wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0) + { + lpService->lpDisplayName = HeapAlloc(GetProcessHeap, 0, + (wcslen(lpDisplayName) + 1) * sizeof(WCHAR)); + if (lpService->lpDisplayName == NULL) + { + dwError = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + wcscpy(lpService->lpDisplayName, lpDisplayName); + } + + + /* FIXME: set lpLoadOrderGroup, lpDependencies etc. */ @@ -756,6 +817,10 @@ done:; } else { + /* Release the display name buffer */ + if (lpService->lpServiceName != lpService->lpDisplayName) + HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName); + if (hServiceHandle != NULL) { /* Remove the service handle */ @@ -795,6 +860,9 @@ ScmrOpenSCManagerW(handle_t BindingHandle, DPRINT("lpDataBaseName: %S\n", lpDatabaseName); DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + dwError = ScmCreateManagerHandle(lpDatabaseName, &hHandle); if (dwError != ERROR_SUCCESS) @@ -841,6 +909,9 @@ ScmrOpenServiceW(handle_t BindingHandle, DPRINT("lpServiceName: %S\n", lpServiceName); DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); + if (ScmShutdown) + return ERROR_SHUTDOWN_IN_PROGRESS; + hManager = (PMANAGER_HANDLE)hSCManager; if (hManager->Handle.Tag != MANAGER_TAG) { @@ -886,6 +957,55 @@ ScmrOpenServiceW(handle_t BindingHandle, } +/* Function 20 */ +unsigned long +ScmrGetServiceDisplayNameW(handle_t BindingHandle, + unsigned int hSCManager, + wchar_t *lpServiceName, + wchar_t *lpDisplayName, /* [out, unique] */ + unsigned long *lpcchBuffer) +{ +// PMANAGER_HANDLE hManager; + PSERVICE lpService; + DWORD dwLength; + DWORD dwError; + + DPRINT1("ScmrGetServiceDisplayNameW() called\n"); + DPRINT1("hSCManager = %x\n", hSCManager); + DPRINT1("lpServiceName: %S\n", lpServiceName); + DPRINT1("lpDisplayName: %p\n", lpDisplayName); + DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer); + +// hManager = (PMANAGER_HANDLE)hSCManager; +// if (hManager->Handle.Tag != MANAGER_TAG) +// { +// DPRINT1("Invalid manager handle!\n"); +// return ERROR_INVALID_HANDLE; +// } + + /* Get service database entry */ + lpService = ScmGetServiceEntryByName(lpServiceName); + if (lpService == NULL) + { + DPRINT1("Could not find a service!\n"); + return ERROR_SERVICE_DOES_NOT_EXIST; + } + + dwLength = wcslen(lpService->lpDisplayName); + + if (lpDisplayName != NULL && + *lpcchBuffer > dwLength) + { + wcscpy(lpDisplayName, lpService->lpDisplayName); + } + + dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER; + + *lpcchBuffer = dwLength; + + return dwError; +} + /* Function 27 */ unsigned long diff --git a/reactos/subsys/system/services/services.c b/reactos/subsys/system/services/services.c index f834c5611dd..e6baff358e9 100644 --- a/reactos/subsys/system/services/services.c +++ b/reactos/subsys/system/services/services.c @@ -40,6 +40,8 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId); #define PIPE_BUFSIZE 1024 #define PIPE_TIMEOUT 1000 +BOOL ScmShutdown = FALSE; + /* FUNCTIONS *****************************************************************/ @@ -286,6 +288,23 @@ AcquireLoadDriverPrivilege(VOID) } +BOOL WINAPI +ShutdownHandlerRoutine(DWORD dwCtrlType) +{ + DPRINT1("ShutdownHandlerRoutine() called\n"); + + if (dwCtrlType == CTRL_SHUTDOWN_EVENT) + { + DPRINT1("Shutdown event received!\n"); + ScmShutdown = TRUE; + + /* FIXME: Shut all services down */ + } + + return TRUE; +} + + int STDCALL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, @@ -330,17 +349,15 @@ WinMain(HINSTANCE hInstance, ScmStartRpcServer(); /* Register service process with CSRSS */ -// RegisterServicesProcess(GetCurrentProcessId()); + RegisterServicesProcess(GetCurrentProcessId()); DPRINT("SERVICES: Initialized.\n"); /* Signal start event */ SetEvent(hScmStartEvent); -#if 0 - /* FIXME: register event handler (used for system shutdown) */ - SetConsoleCtrlHandler(...); -#endif + /* Register event handler (used for system shutdown) */ + SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE); /* Start auto-start services */ ScmAutoStartServices(); diff --git a/reactos/subsys/system/services/services.h b/reactos/subsys/system/services/services.h index fcecdc28d4c..cb38b3f36bb 100644 --- a/reactos/subsys/system/services/services.h +++ b/reactos/subsys/system/services/services.h @@ -13,6 +13,7 @@ typedef struct _SERVICE { LIST_ENTRY ServiceListEntry; LPWSTR lpServiceName; + LPWSTR lpDisplayName; UNICODE_STRING ServiceGroup; SERVICE_STATUS Status; @@ -32,6 +33,13 @@ typedef struct _SERVICE } SERVICE, *PSERVICE; +/* VARIABLES ***************************************************************/ + +extern BOOL ScmShutdown; + + +/* FUNCTIONS ***************************************************************/ + /* config.c */ DWORD ScmWriteDependencies(HKEY hServiceKey, @@ -46,6 +54,7 @@ VOID ScmGetBootAndSystemDriverState(VOID); VOID ScmAutoStartServices(VOID); PSERVICE ScmGetServiceEntryByName(LPWSTR lpServiceName); +PSERVICE ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName); DWORD ScmCreateNewServiceRecord(LPWSTR lpServiceName, PSERVICE *lpServiceRecord); DWORD ScmMarkServiceForDelete(PSERVICE pService);