diff --git a/reactos/include/idl/svcctl.idl b/reactos/include/idl/svcctl.idl new file mode 100644 index 00000000000..a0b5efe8672 --- /dev/null +++ b/reactos/include/idl/svcctl.idl @@ -0,0 +1,72 @@ +/* + * Service Control Manager (SCM) interface definition + */ + +//#include +//#include + +#define DWORD unsigned long +#define BOOL unsigned long +#define SC_HANDLE unsigned int +#define LPCSTR char* +#define LPCWSTR wchar_t* + +[ + uuid(367abb81-9844-35f1-ad32-98f038001003), + version(2.0), + pointer_default(unique), + explicit_handle +] +interface svcctl +{ +cpp_quote("#if 0"); + typedef struct _SERVICE_STATUS + { + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; + } SERVICE_STATUS, *LPSERVICE_STATUS; +cpp_quote("#endif"); + + /* Service 0 */ + DWORD ScmrCloseServiceHandle([in] handle_t BindingHandle, + [in] SC_HANDLE hSCObject); + + /* Service 1 */ +// BOOL ScmrControlService([in] handle_t BindingHandle, +// [in] SC_HANDLE hService, +// [in] DWORD dwControl, +// [out] LPSERVICE_STATUS lpServiceStatus); + + /* Service 2 */ + DWORD ScmrDeleteService([in] handle_t BindingHandle, + [in] SC_HANDLE hService); + + DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle, + [in, string, unique] LPCSTR lpMachineName, + [in, string, unique] LPCSTR lpDatabaseName, + [in] DWORD dwDesiredAccess, + [out] SC_HANDLE *hScm); + + DWORD ScmrOpenSCManagerW([in] handle_t BindingHandle, + [in, string, unique] LPCWSTR lpMachineName, + [in, string, unique] LPCWSTR lpDatabaseName, + [in] DWORD dwDesiredAccess, + [out] SC_HANDLE *hScm); + + SC_HANDLE ScmrOpenServiceA([in] handle_t BindingHandle, + [in] SC_HANDLE hSCManager, + [in, string] LPCSTR lpServiceName, + [in] DWORD dwDesiredAccess, + [out] SC_HANDLE *hScm); + + SC_HANDLE ScmrOpenServiceW([in] handle_t BindingHandle, + [in] SC_HANDLE hSCManager, + [in, string] LPCWSTR lpServiceName, + [in] DWORD dwDesiredAccess, + [out] SC_HANDLE *hScm); +} diff --git a/reactos/lib/advapi32/makefile b/reactos/lib/advapi32/makefile index 9d35be29271..80374888d01 100644 --- a/reactos/lib/advapi32/makefile +++ b/reactos/lib/advapi32/makefile @@ -16,7 +16,7 @@ TARGET_CFLAGS = -Wall -Werror -fno-builtin \ TARGET_LFLAGS = -nostartfiles -nostdlib -TARGET_SDKLIBS = ntdll.a kernel32.a +TARGET_SDKLIBS = ntdll.a kernel32.a rpcrt4.a TARGET_BASE = $(TARGET_BASE_LIB_ADVAPI32) @@ -51,7 +51,8 @@ SERVICE_OBJECTS = \ service/eventlog.o \ service/scm.o \ service/sctrl.o \ - service/undoc.o + service/undoc.o \ + service/svcctl_c.o TOKEN_OBJECTS = \ token/privilege.o \ @@ -67,8 +68,17 @@ TARGET_OBJECTS = \ DEP_OBJECTS = $(TARGET_OBJECTS) +TARGET_CLEAN = service/svcctl_c.c service/svcctl.h + include $(PATH_TO_TOP)/rules.mak include $(TOOLS_PATH)/helper.mk include $(TOOLS_PATH)/depend.mk + +WIDL_FLAGS = -o \ + -D _X86_ -D MIDL_PASS \ + -I $(PATH_TO_TOP)/w32api/include + +service/svcctl_c.c service/svcctl.h: $(PATH_TO_TOP)/include/idl/svcctl.idl + $(WIDL) $(WIDL_FLAGS) -h -H service/svcctl.h -c -C service/svcctl_c.c $(PATH_TO_TOP)/include/idl/svcctl.idl diff --git a/reactos/lib/advapi32/service/scm.c b/reactos/lib/advapi32/service/scm.c index 20faa01407a..edfc2d3afda 100644 --- a/reactos/lib/advapi32/service/scm.c +++ b/reactos/lib/advapi32/service/scm.c @@ -1,10 +1,10 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/advapi32/service/scm.c * PURPOSE: Service control manager functions * PROGRAMMER: Emanuele Aliberti + * Eric Kohl * UPDATE HISTORY: * 19990413 EA created * 19990515 EA @@ -13,11 +13,70 @@ /* INCLUDES ******************************************************************/ #include "advapi32.h" +#include "svcctl.h" + #define NDEBUG #include /* FUNCTIONS *****************************************************************/ +handle_t BindingHandle = NULL; + +static VOID +HandleBind(VOID) +{ + LPWSTR pszStringBinding; + RPC_STATUS status; + + if (BindingHandle != NULL) + return; + + status = RpcStringBindingComposeW(NULL, + L"ncacn_np", + NULL, + L"\\pipe\\ntsvcs", + NULL, + &pszStringBinding); + if (status) + { + DPRINT1("RpcStringBindingCompose returned 0x%x\n", status); + return; + } + + /* Set the binding handle that will be used to bind to the server. */ + status = RpcBindingFromStringBindingW(pszStringBinding, + &BindingHandle); + if (status) + { + DPRINT1("RpcBindingFromStringBinding returned 0x%x\n", status); + } + + status = RpcStringFreeW(&pszStringBinding); + if (status) + { + DPRINT1("RpcStringFree returned 0x%x\n", status); + } +} + + +#if 0 +static VOID +HandleUnbind(VOID) +{ + RPC_STATUS status; + + if (BindingHandle == NULL) + return; + + status = RpcBindingFree(&BindingHandle); + if (status) + { + DPRINT1("RpcBindingFree returned 0x%x\n", status); + } +} +#endif + + /********************************************************************** * ChangeServiceConfigA * @@ -75,17 +134,27 @@ ChangeServiceConfigW( * * @implemented */ -BOOL -STDCALL +BOOL STDCALL CloseServiceHandle(SC_HANDLE hSCObject) { - DPRINT("CloseServiceHandle() - called.\n"); + DWORD dwError; - if (!CloseHandle(hSCObject)) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - return TRUE; + DPRINT1("CloseServiceHandle() called\n"); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrCloseServiceHandle(BindingHandle, + (unsigned int)hSCObject); + DPRINT1("dwError %lu\n", dwError); + + if (dwError) + { + SetLastError(dwError); + return FALSE; + } + + return TRUE; } @@ -94,15 +163,36 @@ CloseServiceHandle(SC_HANDLE hSCObject) * * @unimplemented */ -BOOL -STDCALL +BOOL STDCALL ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus) { - DPRINT1("ControlService is unimplemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); +#if 0 + DWORD dwError; + + DPRINT1("ControlService(%x, %x, %p)\n", + hService, dwControl, lpServiceStatus); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrControlService(BindingHandle, + (unsigned int)hService, + dwControl, + lpServiceStatus); + if (dwError != ERROR_SUCCESS) + { + SetLastError(dwError); return FALSE; + } + + return TRUE; +#endif + + DPRINT1("ControlService is unimplemented\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; } @@ -165,13 +255,25 @@ CreateServiceW( * * @unimplemented */ -BOOL -STDCALL +BOOL STDCALL DeleteService(SC_HANDLE hService) { - DPRINT1("DeleteService is unimplemented\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + DWORD dwError; + + DPRINT1("DeleteService(%x)\n", hService); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrDeleteService(BindingHandle, + (unsigned int)hService); + if (dwError != ERROR_SUCCESS) + { + SetLastError(dwError); return FALSE; + } + + return TRUE; } @@ -410,6 +512,7 @@ GetServiceKeyNameW( return FALSE; } + /********************************************************************** * LockServiceDatabase * @@ -417,7 +520,7 @@ GetServiceKeyNameW( */ SC_LOCK STDCALL -LockServiceDatabase(SC_HANDLE hSCManager) +LockServiceDatabase(SC_HANDLE hSCManager) { DPRINT1("LockServiceDatabase is unimplemented\n"); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); @@ -425,36 +528,80 @@ LockServiceDatabase(SC_HANDLE hSCManager) } +static VOID +WaitForSCManager(VOID) +{ + HANDLE hEvent; + + DPRINT1("WaitForSCManager() called\n"); + + /* Try to open the existing event */ + hEvent = OpenEventW(SYNCHRONIZE, + FALSE, + L"SvcctrlStartEvent_A3725DX"); + if (hEvent == NULL) + { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + return; + + /* Try to create a new event */ + hEvent = CreateEventW(NULL, + TRUE, + FALSE, + L"SvcctrlStartEvent_A3725DX"); + if (hEvent == NULL) + { + /* Try to open the existing event again */ + hEvent = OpenEventW(SYNCHRONIZE, + FALSE, + L"SvcctrlStartEvent_A3725DX"); + if (hEvent == NULL) + return; + } + } + + /* Wait for 3 minutes */ + WaitForSingleObject(hEvent, 180000); + CloseHandle(hEvent); + + DPRINT1("ScmWaitForSCManager() done\n"); +} + + /********************************************************************** * OpenSCManagerA * - * @unplemented + * @implemented */ SC_HANDLE STDCALL OpenSCManagerA(LPCSTR lpMachineName, - LPCSTR lpDatabaseName, - DWORD dwDesiredAccess) + LPCSTR lpDatabaseName, + DWORD dwDesiredAccess) { - SC_HANDLE Handle; - UNICODE_STRING MachineNameW; - UNICODE_STRING DatabaseNameW; - ANSI_STRING MachineNameA; - ANSI_STRING DatabaseNameA; + SC_HANDLE hScm = NULL; + DWORD dwError; - DPRINT("OpenSCManagerA(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess); + DPRINT1("OpenSCManagerA(%s, %s, %lx)\n", + lpMachineName, lpDatabaseName, dwDesiredAccess); - RtlInitAnsiString(&MachineNameA, (LPSTR)lpMachineName); - RtlAnsiStringToUnicodeString(&MachineNameW, &MachineNameA, TRUE); - RtlInitAnsiString(&DatabaseNameA, (LPSTR)lpDatabaseName); - RtlAnsiStringToUnicodeString(&DatabaseNameW, &DatabaseNameA, TRUE); + WaitForSCManager(); - Handle = OpenSCManagerW(lpMachineName ? MachineNameW.Buffer : NULL, - lpDatabaseName ? DatabaseNameW.Buffer : NULL, - dwDesiredAccess); + HandleBind(); - RtlFreeHeap(GetProcessHeap(), 0, MachineNameW.Buffer); - RtlFreeHeap(GetProcessHeap(), 0, DatabaseNameW.Buffer); - return Handle; + /* Call to services.exe using RPC */ + dwError = ScmrOpenSCManagerA(BindingHandle, + (LPSTR)lpMachineName, + (LPSTR)lpDatabaseName, + dwDesiredAccess, + (unsigned int*)&hScm); + DPRINT1("hScm = %p\n", hScm); + if (dwError) + { + SetLastError(dwError); + return NULL; + } + + return hScm; } @@ -463,215 +610,111 @@ OpenSCManagerA(LPCSTR lpMachineName, * * @unimplemented */ -SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName, - LPCWSTR lpDatabaseName, - DWORD dwDesiredAccess) +SC_HANDLE STDCALL +OpenSCManagerW(LPCWSTR lpMachineName, + LPCWSTR lpDatabaseName, + DWORD dwDesiredAccess) { - HANDLE hPipe; - DWORD dwMode; - DWORD dwWait; - BOOL fSuccess; - HANDLE hStartEvent; - LPWSTR lpszPipeName = L"\\\\.\\pipe\\Ntsvcs"; + SC_HANDLE hScm = NULL; + DWORD dwError; - DPRINT("OpenSCManagerW(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess); + DPRINT1("OpenSCManagerW(%S, %S, %lx)\n", + lpMachineName, lpDatabaseName, dwDesiredAccess); - if (lpMachineName == NULL || wcslen(lpMachineName) == 0) - { - if (lpDatabaseName != NULL && wcscmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0) - { - DPRINT("OpenSCManagerW() - Invalid parameters.\n"); - return NULL; - } + WaitForSCManager(); - DPRINT("OpenSCManagerW() - OpenEvent(\"SvcctrlStartEvent_A3725DX\")\n"); + HandleBind(); - // Only connect to scm when event "SvcctrlStartEvent_A3725DX" is signaled - hStartEvent = OpenEventW(SYNCHRONIZE, FALSE, L"SvcctrlStartEvent_A3725DX"); - if (hStartEvent == NULL) - { - SetLastError(ERROR_DATABASE_DOES_NOT_EXIST); - DPRINT("OpenSCManagerW() - Failed to Open Event \"SvcctrlStartEvent_A3725DX\".\n"); - return NULL; - } + /* Call to services.exe using RPC */ + dwError = ScmrOpenSCManagerW(BindingHandle, + (LPWSTR)lpMachineName, + (LPWSTR)lpDatabaseName, + dwDesiredAccess, + (unsigned int*)&hScm); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrOpenSCManagerW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return NULL; + } - DPRINT("OpenSCManagerW() - Waiting forever on event handle: %x\n", hStartEvent); + DPRINT1("hScm = %p\n", hScm); -#if 1 - dwWait = WaitForSingleObject(hStartEvent, INFINITE); - if (dwWait == WAIT_FAILED) - { - DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n"); - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } -#else - { - DWORD Count; - - /* wait for event creation (by SCM) for max. 20 seconds */ - for (Count = 0; Count < 20; Count++) - { - dwWait = WaitForSingleObject(hStartEvent, 1000); - if (dwWait == WAIT_FAILED) - { - DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n"); - Sleep(1000); - } - else - { - break; - } - } - - if (dwWait == WAIT_FAILED) - { - DbgPrint("WL: Failed to wait on event \"SvcctrlStartEvent_A3725DX\"\n"); - } - - } -#endif - - DPRINT("OpenSCManagerW() - Closing handle to event...\n"); - - CloseHandle(hStartEvent); - - // Try to open a named pipe; wait for it, if necessary - while (1) - { - DWORD dwLastError; - DPRINT("OpenSCManagerW() - attempting to open named pipe to SCM.\n"); - hPipe = CreateFileW(lpszPipeName, // pipe name - dwDesiredAccess, - 0, // no sharing - NULL, // no security attributes - OPEN_EXISTING, // opens existing pipe - 0, // default attributes - NULL); // no template file - - DPRINT("OpenSCManagerW() - handle to named pipe: %x\n", hPipe); - // Break if the pipe handle is valid - if (hPipe != INVALID_HANDLE_VALUE) - { - break; - } - - // Exit if an error other than ERROR_PIPE_BUSY occurs - dwLastError = GetLastError(); - if (dwLastError != ERROR_PIPE_BUSY) - { - DPRINT("OpenSCManagerW() - returning at 4, dwLastError %d\n", dwLastError); - return NULL; - } - - // All pipe instances are busy, so wait for 20 seconds - if (!WaitNamedPipeW(lpszPipeName, 20000)) - { - DPRINT("OpenSCManagerW() - Failed on WaitNamedPipeW(...).\n"); - return NULL; - } - } - - // The pipe connected; change to message-read mode - dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time - if (!fSuccess) - { - CloseHandle(hPipe); - DPRINT("OpenSCManagerW() - Failed on SetNamedPipeHandleState(...).\n"); - return NULL; - } -#if 0 - // Send a message to the pipe server - lpvMessage = (argc > 1) ? argv[1] : "default message"; - - fSuccess = WriteFile( - hPipe, // pipe handle - lpvMessage, // message - strlen(lpvMessage) + 1, // message length - &cbWritten, // bytes written - NULL); // not overlapped - if (!fSuccess) - { - CloseHandle(hPipe); - DPRINT("OpenSCManagerW() - Failed to write to pipe.\n"); - return NULL; - } - - do - { - DPRINT("OpenSCManagerW() - in I/O loop to SCM...\n"); - // Read from the pipe - fSuccess = ReadFile( - hPipe, // pipe handle - chBuf, // buffer to receive reply - 512, // size of buffer - &cbRead, // number of bytes read - NULL); // not overlapped - - if (!fSuccess && GetLastError() != ERROR_MORE_DATA) - { - break; - } - - // Reply from the pipe is written to STDOUT. - if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL)) - { - break; - } - } while(!fSuccess); // repeat loop if ERROR_MORE_DATA - - DPRINT("OpenSCManagerW() - I/O loop completed.\n"); - //CloseHandle(hPipe); -#endif - DPRINT("OpenSCManagerW() - success, returning handle to pipe %x\n", hPipe); - return hPipe; - } - else - { - /* FIXME: Connect to remote SCM */ - DPRINT("OpenSCManagerW() - FIXME: Connect to remote SCM is unimplemented.\n"); - return NULL; - } + return hScm; } /********************************************************************** * OpenServiceA * - * @unimplemented + * @implemented */ SC_HANDLE STDCALL OpenServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess) { - DPRINT1("OpenServiceA is unimplemented, returning ERROR_SERVICE_DOES_NOT_EXIST for %s\n", lpServiceName); - SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); - return NULL; + SC_HANDLE hService = NULL; + DWORD dwError; + + DPRINT1("OpenServiceA(%p, %s, %lx)\n", + hSCManager, lpServiceName, dwDesiredAccess); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrOpenServiceA(BindingHandle, + (unsigned int)hSCManager, + (LPSTR)lpServiceName, + dwDesiredAccess, + (unsigned int*)&hService); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrOpenServiceA() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return NULL; + } + + DPRINT1("hService = %p\n", hService); + + return hService; } /********************************************************************** * OpenServiceW * - * @unimplemented + * @implemented */ -SC_HANDLE -STDCALL -OpenServiceW( - SC_HANDLE hSCManager, - LPCWSTR lpServiceName, - DWORD dwDesiredAccess - ) +SC_HANDLE STDCALL +OpenServiceW(SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + DWORD dwDesiredAccess) { - DPRINT1("OpenServiceW is unimplemented, returning ERROR_SERVICE_DOES_NOT_EXIST for %S\n", lpServiceName); - SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); - return NULL; + SC_HANDLE hService = NULL; + DWORD dwError; + + DPRINT1("OpenServiceW(%p, %S, %lx)\n", + hSCManager, lpServiceName, dwDesiredAccess); + + HandleBind(); + + /* Call to services.exe using RPC */ + dwError = ScmrOpenServiceW(BindingHandle, + (unsigned int)hSCManager, + (LPWSTR)lpServiceName, + dwDesiredAccess, + (unsigned int*)&hService); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmrOpenServiceW() failed (Error %lu)\n", dwError); + SetLastError(dwError); + return NULL; + } + + DPRINT1("hService = %p\n", hService); + + return hService; } @@ -860,4 +903,14 @@ UnlockServiceDatabase(SC_LOCK ScLock) } +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) +{ + return GlobalAlloc(GPTR,len); +} + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) +{ + GlobalFree(ptr); +} + /* EOF */ diff --git a/reactos/subsys/system/services/makefile b/reactos/subsys/system/services/makefile index 37442872d85..e109909b31f 100644 --- a/reactos/subsys/system/services/makefile +++ b/reactos/subsys/system/services/makefile @@ -10,14 +10,29 @@ TARGET_NAME = services TARGET_INSTALLDIR = system32 -TARGET_SDKLIBS = ntdll.a kernel32.a user32.a +TARGET_SDKLIBS = ntdll.a kernel32.a user32.a rpcrt4.a -TARGET_OBJECTS = $(TARGET_NAME).o database.o +TARGET_OBJECTS = svcctl_s.o database.o services.o rpcserver.o -TARGET_CFLAGS = -D__USE_W32API -Wall -Werror +TARGET_CFLAGS = -Wall -Werror -fno-builtin \ + -D__USE_W32API \ + -D_WIN32_IE=0x0500 \ + -D_WIN32_WINNT=0x501 \ + -DWINVER=0x600 \ + -DUNICODE \ + -D_UNICODE + +TARGET_CLEAN = svcctl_s.c svcctl_s.h + +DEP_OBJECTS = $(TARGET_OBJECTS) include $(PATH_TO_TOP)/rules.mak include $(TOOLS_PATH)/helper.mk +include $(TOOLS_PATH)/depend.mk + +svcctl_s.c svcctl_s.h: $(PATH_TO_TOP)/include/idl/svcctl.idl + $(WIDL) -o -h -H svcctl_s.h -s -S svcctl_s.c $(PATH_TO_TOP)/include/idl/svcctl.idl + # EOF diff --git a/reactos/subsys/system/services/rpcserver.c b/reactos/subsys/system/services/rpcserver.c new file mode 100644 index 00000000000..cabd6cb0c33 --- /dev/null +++ b/reactos/subsys/system/services/rpcserver.c @@ -0,0 +1,349 @@ +/* + + */ + +/* INCLUDES ****************************************************************/ + +#define NTOS_MODE_USER +#include +#include +#include + +#include "services.h" +#include "svcctl_s.h" + +#define NDEBUG +#include + + +/* GLOBALS *****************************************************************/ + +#define MANAGER_TAG 0x72674D68 /* 'hMgr' */ +#define SERVICE_TAG 0x63765368 /* 'hSvc' */ + +typedef struct _SCMGR_HANDLE +{ + DWORD Tag; + DWORD RefCount; + DWORD DesiredAccess; +} SCMGR_HANDLE; + + +typedef struct _MANAGER_HANDLE +{ + SCMGR_HANDLE Handle; + + /* FIXME: Insert more data here */ + + WCHAR DatabaseName[1]; +} MANAGER_HANDLE, *PMANAGER_HANDLE; + + +typedef struct _SERVICE_HANDLE +{ + SCMGR_HANDLE Handle; + + DWORD DesiredAccess; + PVOID DatabaseEntry; /* FIXME */ + + /* FIXME: Insert more data here */ + +} SERVICE_HANDLE, *PSERVICE_HANDLE; + + +/* FUNCTIONS ***************************************************************/ + +VOID +ScmStartRpcServer(VOID) +{ + RPC_STATUS Status; + + DPRINT("ScmStartRpcServer() called"); + + Status = RpcServerUseProtseqEp(L"ncacn_np", + 10, + L"\\pipe\\ntsvcs", + NULL); + if (Status != RPC_S_OK) + { + DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status); + return; + } + + Status = RpcServerRegisterIf(svcctl_ServerIfHandle, + NULL, + NULL); + if (Status != RPC_S_OK) + { + DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status); + return; + } + + Status = RpcServerListen(1, 20, TRUE); + if (Status != RPC_S_OK) + { + DPRINT1("RpcServerListen() failed (Status %lx)\n", Status); + return; + } + + DPRINT("ScmStartRpcServer() done"); +} + + +static DWORD +ScmCreateManagerHandle(LPWSTR lpDatabaseName, + SC_HANDLE *Handle, + DWORD dwDesiredAccess) +{ + PMANAGER_HANDLE Ptr; + + Ptr = GlobalAlloc(GPTR, + sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR)); + if (Ptr == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + Ptr->Handle.Tag = MANAGER_TAG; + Ptr->Handle.RefCount = 1; + Ptr->Handle.DesiredAccess = dwDesiredAccess; + + /* FIXME: initialize more data here */ + + wcscpy(Ptr->DatabaseName, lpDatabaseName); + + *Handle = (SC_HANDLE)Ptr; + + return ERROR_SUCCESS; +} + + +static DWORD +ScmCreateServiceHandle(LPVOID lpDatabaseEntry, + SC_HANDLE *Handle, + DWORD dwDesiredAccess) +{ + PMANAGER_HANDLE Ptr; + + Ptr = GlobalAlloc(GPTR, + sizeof(SERVICE_HANDLE)); + if (Ptr == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + Ptr->Handle.Tag = SERVICE_TAG; + Ptr->Handle.RefCount = 1; + Ptr->Handle.DesiredAccess = dwDesiredAccess; + + /* FIXME: initialize more data here */ + // Ptr->DatabaseEntry = lpDatabaseEntry; + + *Handle = (SC_HANDLE)Ptr; + + return ERROR_SUCCESS; +} + + +/* Service 0 */ +unsigned long +ScmrCloseServiceHandle(handle_t BindingHandle, + unsigned int hScObject) +{ + PMANAGER_HANDLE hManager; + + DPRINT("ScmrCloseServiceHandle() called\n"); + + DPRINT("hScObject = %X\n", hScObject); + + if (hScObject == 0) + return ERROR_INVALID_HANDLE; + + hManager = (PMANAGER_HANDLE)hScObject; + if (hManager->Handle.Tag == MANAGER_TAG) + { + DPRINT("Found manager handle\n"); + + hManager->Handle.RefCount--; + if (hManager->Handle.RefCount == 0) + { + /* FIXME: add cleanup code */ + + GlobalFree(hManager); + } + + DPRINT("ScmrCloseServiceHandle() done\n"); + return ERROR_SUCCESS; + } + else if (hManager->Handle.Tag == SERVICE_TAG) + { + DPRINT("Found service handle\n"); + + hManager->Handle.RefCount--; + if (hManager->Handle.RefCount == 0) + { + /* FIXME: add cleanup code */ + + GlobalFree(hManager); + } + + DPRINT("ScmrCloseServiceHandle() done\n"); + return ERROR_SUCCESS; + } + + DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag); + + return ERROR_INVALID_HANDLE; +} + + +/* Service 1 */ +#if 0 +unsigned long +ScmrControlService(handle_t BindingHandle, + unsigned int hService, + unsigned long dwControl, + LPSERVICE_STATUS lpServiceStatus) +{ + DPRINT("ScmrControlService() called\n"); + +#if 0 + lpServiceStatus->dwServiceType = 0x12345678; + lpServiceStatus->dwCurrentState = 0x98765432; + lpServiceStatus->dwControlsAccepted = 0xdeadbabe; + lpServiceStatus->dwWin32ExitCode = 0xbaadf00d; + lpServiceStatus->dwServiceSpecificExitCode = 0xdeadf00d; + lpServiceStatus->dwCheckPoint = 0xbaadbabe; + lpServiceStatus->dwWaitHint = 0x2468ACE1; +#endif + + return TRUE; +} +#endif + + +/* Service 2 */ +unsigned long +ScmrDeleteService(handle_t BindingHandle, + unsigned int hService) +{ + DPRINT("ScmrDeleteService() called\n"); + return ERROR_SUCCESS; +} + + +unsigned long +ScmrOpenSCManagerA(handle_t BindingHandle, + char *lpMachineName, + char *lpDatabaseName, + unsigned long dwDesiredAccess, + unsigned int *hScm) +{ + DPRINT("ScmrOpenSCManagerA() called\n"); + return ERROR_SUCCESS; +} + + +unsigned long +ScmrOpenSCManagerW(handle_t BindingHandle, + wchar_t *lpMachineName, + wchar_t *lpDatabaseName, + unsigned long dwDesiredAccess, + unsigned int *hScm) +{ + DWORD dwError; + SC_HANDLE hHandle; + + DPRINT("ScmrOpenSCManagerW() called\n"); + DPRINT("lpMachineName = %p\n", lpMachineName); + DPRINT("lpMachineName: %S\n", lpMachineName); + DPRINT("lpDataBaseName = %p\n", lpDatabaseName); + DPRINT("lpDataBaseName: %S\n", lpDatabaseName); + DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); + + dwError = ScmCreateManagerHandle(lpDatabaseName, + &hHandle, + dwDesiredAccess); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError); + return dwError; + } + + *hScm = (unsigned int)hHandle; + DPRINT("*hScm = %x\n", *hScm); + + DPRINT("ScmrOpenSCManagerW() done\n"); + + return ERROR_SUCCESS; +} + + +unsigned int +ScmrOpenServiceA(handle_t BindingHandle, + unsigned int hSCManager, + char *lpServiceName, + unsigned long dwDesiredAccess, + unsigned int *hService) +{ + DPRINT("ScmrOpenServiceA() called\n"); + return 0; +} + + +unsigned int +ScmrOpenServiceW(handle_t BindingHandle, + unsigned int hSCManager, + wchar_t *lpServiceName, + unsigned long dwDesiredAccess, + unsigned int *hService) +{ + PMANAGER_HANDLE hManager; + SC_HANDLE hHandle; + DWORD dwError; + + DPRINT("ScmrOpenServiceW() called\n"); + DPRINT("hSCManager = %x\n", hSCManager); + DPRINT("lpServiceName = %p\n", lpServiceName); + DPRINT("lpServiceName: %S\n", lpServiceName); + DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess); + + hManager = (PMANAGER_HANDLE)hSCManager; + if (hManager->Handle.Tag != MANAGER_TAG) + { + DPRINT1("Invalid manager handle!\n"); + return ERROR_INVALID_HANDLE; + } + + /* FIXME: Check desired access */ + + /* FIXME: Get service database entry */ + + /* Create a service handle */ + dwError = ScmCreateServiceHandle(NULL, + &hHandle, + dwDesiredAccess); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError); + return dwError; + } + + *hService = (unsigned int)hHandle; + DPRINT("*hService = %x\n", *hService); + + DPRINT("ScmrOpenServiceW() done\n"); + + return ERROR_SUCCESS; +} + + + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) +{ + return GlobalAlloc(GPTR, len); +} + + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) +{ + GlobalFree(ptr); +} + +/* EOF */ diff --git a/reactos/subsys/system/services/services.c b/reactos/subsys/system/services/services.c index 1a70ef11f3f..b8f6ed6db2f 100644 --- a/reactos/subsys/system/services/services.c +++ b/reactos/subsys/system/services/services.c @@ -50,18 +50,18 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId); /* FUNCTIONS *****************************************************************/ -void -PrintString(char* fmt,...) +VOID +PrintString(LPCSTR fmt, ...) { #ifdef DBG - char buffer[512]; - va_list ap; + CHAR buffer[512]; + va_list ap; - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); - OutputDebugStringA(buffer); + OutputDebugStringA(buffer); #endif } @@ -69,45 +69,50 @@ PrintString(char* fmt,...) BOOL ScmCreateStartEvent(PHANDLE StartEvent) { - HANDLE hEvent; + HANDLE hEvent; - hEvent = CreateEvent(NULL, - TRUE, + hEvent = CreateEvent(NULL, + TRUE, + FALSE, + _T("SvcctrlStartEvent_A3725DX")); + if (hEvent == NULL) + { + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SvcctrlStartEvent_A3725DX")); - if (hEvent == NULL) { - if (GetLastError() == ERROR_ALREADY_EXISTS) { - hEvent = OpenEvent(EVENT_ALL_ACCESS, - FALSE, - _T("SvcctrlStartEvent_A3725DX")); - if (hEvent == NULL) { - return FALSE; - } - } else { - return FALSE; - } + if (hEvent == NULL) + { + return FALSE; + } } - *StartEvent = hEvent; - return TRUE; + else + { + return FALSE; + } + } + + *StartEvent = hEvent; + + return TRUE; } BOOL -ScmNamedPipeHandleRequest( - PVOID Request, - DWORD RequestSize, - PVOID Reply, - LPDWORD ReplySize) +ScmNamedPipeHandleRequest(PVOID Request, + DWORD RequestSize, + PVOID Reply, + LPDWORD ReplySize) { - DbgPrint("SCM READ: %s\n", Request); + DbgPrint("SCM READ: %s\n", Request); - *ReplySize = 0; - return FALSE; + *ReplySize = 0; + return FALSE; } -DWORD -WINAPI +DWORD WINAPI ScmNamedPipeThread(LPVOID Context) { CHAR chRequest[PIPE_BUFSIZE]; @@ -121,7 +126,7 @@ ScmNamedPipeThread(LPVOID Context) hPipe = (HANDLE)Context; DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe); - + for (;;) { fSuccess = ReadFile(hPipe, &chRequest, @@ -150,7 +155,9 @@ ScmNamedPipeThread(LPVOID Context) return ERROR_SUCCESS; } -BOOL ScmCreateNamedPipe(VOID) + +BOOL +ScmCreateNamedPipe(VOID) { DWORD dwThreadId; BOOL fConnected; @@ -159,7 +166,7 @@ BOOL ScmCreateNamedPipe(VOID) DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n"); - hPipe = CreateNamedPipe("\\\\.\\pipe\\Ntsvcs", + hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\Ntsvcs"), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, @@ -202,8 +209,8 @@ BOOL ScmCreateNamedPipe(VOID) return TRUE; } -DWORD -WINAPI + +DWORD WINAPI ScmNamedPipeListenerThread(LPVOID Context) { // HANDLE hPipe; @@ -225,49 +232,56 @@ ScmNamedPipeListenerThread(LPVOID Context) return ERROR_SUCCESS; } -BOOL StartScmNamedPipeThreadListener(void) + +BOOL +StartScmNamedPipeThreadListener(VOID) { - DWORD dwThreadId; - HANDLE hThread; + DWORD dwThreadId; + HANDLE hThread; - hThread = CreateThread(NULL, - 0, - ScmNamedPipeListenerThread, - NULL, /*(LPVOID)hPipe,*/ - 0, - &dwThreadId); + hThread = CreateThread(NULL, + 0, + ScmNamedPipeListenerThread, + NULL, /*(LPVOID)hPipe,*/ + 0, + &dwThreadId); + if (!hThread) + { + DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError()); + return FALSE; + } - if (!hThread) { - DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError()); - return FALSE; - } - return TRUE; + return TRUE; } + VOID FASTCALL AcquireLoadDriverPrivilege(VOID) { - HANDLE hToken; - TOKEN_PRIVILEGES tkp; + HANDLE hToken; + TOKEN_PRIVILEGES tkp; - /* Get a token for this process. */ - if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { - /* Get the LUID for the debug privilege. */ - LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid); + /* Get a token for this process */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + /* Get the LUID for the debug privilege */ + LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid); - tkp.PrivilegeCount = 1; /* one privilege to set */ - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + /* One privilege to set */ + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - /* Get the debug privilege for this process. */ - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); - } + /* Get the debug privilege for this process */ + AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + } } + int STDCALL WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nShowCmd) + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd) { HANDLE hScmStartEvent; HANDLE hEvent; @@ -280,57 +294,44 @@ WinMain(HINSTANCE hInstance, /* Create start event */ if (!ScmCreateStartEvent(&hScmStartEvent)) - { - DPRINT1("SERVICES: Failed to create start event\n"); - ExitThread(0); - } + { + DPRINT1("SERVICES: Failed to create start event\n"); + ExitThread(0); + } DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent); +// ScmInitThreadManager(); + /* FIXME: more initialization */ /* Create the service database */ Status = ScmCreateServiceDataBase(); if (!NT_SUCCESS(Status)) - { - DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status); - ExitThread(0); - } + { + DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status); + ExitThread(0); + } /* Update service database */ ScmGetBootAndSystemDriverState(); -#if 0 - DPRINT("SERVICES: Attempting to create named pipe...\n"); - /* Create named pipe */ - if (!ScmCreateNamedPipe()) { - DPRINT1("SERVICES: Failed to create named pipe\n"); - ExitThread(0); - } - DPRINT("SERVICES: named pipe created successfully.\n"); -#else - DPRINT("SERVICES: Attempting to create named pipe listener...\n"); - if (!StartScmNamedPipeThreadListener()) { - DPRINT1("SERVICES: Failed to create named pipe listener thread.\n"); - ExitThread(0); - } - DPRINT("SERVICES: named pipe listener thread created.\n"); -#endif - /* FIXME: create listener thread for pipe */ - + /* Start the RPC server */ + 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(...); - + SetConsoleCtrlHandler(...); +#endif /* Start auto-start services */ ScmAutoStartServices(); @@ -344,16 +345,17 @@ WinMain(HINSTANCE hInstance, hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); WaitForSingleObject(hEvent, INFINITE); #else - for (;;) - { + for (;;) + { NtYieldExecution(); - } + } #endif DPRINT("SERVICES: Finished.\n"); ExitThread(0); - return(0); + + return 0; } /* EOF */ diff --git a/reactos/subsys/system/services/services.h b/reactos/subsys/system/services/services.h index 443ac04e98e..b7a6c37cebb 100644 --- a/reactos/subsys/system/services/services.h +++ b/reactos/subsys/system/services/services.h @@ -3,9 +3,10 @@ */ + /* services.c */ -void PrintString(char* fmt,...); +VOID PrintString(LPCSTR fmt, ...); /* database.c */ @@ -15,5 +16,10 @@ VOID ScmGetBootAndSystemDriverState(VOID); VOID ScmAutoStartServices(VOID); +/* rpcserver.c */ + +VOID ScmStartRpcServer(VOID); + + /* EOF */