mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 15:45:00 +00:00
services: Start a local RPC server.
This commit is contained in:
parent
c0be6047ef
commit
4275fbf603
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -20,6 +20,8 @@ dlls/actxprxy/actxprxy_servprov.h
|
||||||
dlls/actxprxy/actxprxy_servprov_i.c
|
dlls/actxprxy/actxprxy_servprov_i.c
|
||||||
dlls/actxprxy/actxprxy_servprov_p.c
|
dlls/actxprxy/actxprxy_servprov_p.c
|
||||||
dlls/advapi32/libadvapi32.def
|
dlls/advapi32/libadvapi32.def
|
||||||
|
dlls/advapi32/svcctl.h
|
||||||
|
dlls/advapi32/svcctl_c.c
|
||||||
dlls/advapi32/tests/*.ok
|
dlls/advapi32/tests/*.ok
|
||||||
dlls/advapi32/tests/advapi32_crosstest.exe
|
dlls/advapi32/tests/advapi32_crosstest.exe
|
||||||
dlls/advapi32/tests/testlist.c
|
dlls/advapi32/tests/testlist.c
|
||||||
|
@ -538,6 +540,7 @@ include/unknwn.h
|
||||||
include/urlhist.h
|
include/urlhist.h
|
||||||
include/urlmon.h
|
include/urlmon.h
|
||||||
include/wine/itss.h
|
include/wine/itss.h
|
||||||
|
include/wine/svcctl.h
|
||||||
include/wtypes.h
|
include/wtypes.h
|
||||||
include/xmldom.h
|
include/xmldom.h
|
||||||
include/xmldso.h
|
include/xmldso.h
|
||||||
|
@ -583,6 +586,8 @@ programs/rpcss/rpcss
|
||||||
programs/rundll32/rundll32
|
programs/rundll32/rundll32
|
||||||
programs/secedit/secedit
|
programs/secedit/secedit
|
||||||
programs/services/services
|
programs/services/services
|
||||||
|
programs/services/svcctl.h
|
||||||
|
programs/services/svcctl_s.c
|
||||||
programs/spoolsv/spoolsv
|
programs/spoolsv/spoolsv
|
||||||
programs/start/start
|
programs/start/start
|
||||||
programs/svchost/svchost
|
programs/svchost/svchost
|
||||||
|
|
|
@ -7,6 +7,7 @@ MODULE = advapi32.dll
|
||||||
IMPORTLIB = advapi32
|
IMPORTLIB = advapi32
|
||||||
IMPORTS = kernel32 ntdll
|
IMPORTS = kernel32 ntdll
|
||||||
EXTRALIBS = @SECURITYLIB@
|
EXTRALIBS = @SECURITYLIB@
|
||||||
|
DELAYIMPORTS = rpcrt4
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
advapi.c \
|
advapi.c \
|
||||||
|
@ -24,6 +25,8 @@ C_SRCS = \
|
||||||
security.c \
|
security.c \
|
||||||
service.c
|
service.c
|
||||||
|
|
||||||
|
IDL_C_SRCS = svcctl.idl
|
||||||
|
|
||||||
RC_SRCS = version.rc
|
RC_SRCS = version.rc
|
||||||
|
|
||||||
@MAKE_DLL_RULES@
|
@MAKE_DLL_RULES@
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
#include "lmcons.h"
|
#include "lmcons.h"
|
||||||
#include "lmserver.h"
|
#include "lmserver.h"
|
||||||
|
|
||||||
|
#include "svcctl.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(service);
|
WINE_DEFAULT_DEBUG_CHANNEL(service);
|
||||||
|
|
||||||
static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
|
static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
|
||||||
|
@ -45,6 +47,16 @@ static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
|
||||||
static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
|
static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
|
||||||
'L','O','C','K',0};
|
'L','O','C','K',0};
|
||||||
|
|
||||||
|
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
|
||||||
|
{
|
||||||
|
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
static const GENERIC_MAPPING scm_generic = {
|
static const GENERIC_MAPPING scm_generic = {
|
||||||
(STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
|
(STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
|
||||||
(STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
|
(STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
|
||||||
|
@ -117,6 +129,7 @@ struct sc_handle
|
||||||
SC_HANDLE_TYPE htype;
|
SC_HANDLE_TYPE htype;
|
||||||
DWORD ref_count;
|
DWORD ref_count;
|
||||||
sc_handle_destructor destroy;
|
sc_handle_destructor destroy;
|
||||||
|
SC_RPC_HANDLE server_handle; /* server-side handle */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_manager /* service control manager handle */
|
struct sc_manager /* service control manager handle */
|
||||||
|
@ -230,6 +243,102 @@ static inline LPWSTR SERV_dupmulti(LPCSTR str)
|
||||||
return wstr;
|
return wstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* RPC connection with servies.exe
|
||||||
|
*/
|
||||||
|
|
||||||
|
static BOOL check_services_exe(void)
|
||||||
|
{
|
||||||
|
static const WCHAR svcctl_started_event[] = SVCCTL_STARTED_EVENT;
|
||||||
|
HANDLE hEvent = OpenEventW(SYNCHRONIZE, FALSE, svcctl_started_event);
|
||||||
|
if (hEvent == NULL) /* need to start services.exe */
|
||||||
|
{
|
||||||
|
static const WCHAR services[] = {'\\','s','e','r','v','i','c','e','s','.','e','x','e',0};
|
||||||
|
PROCESS_INFORMATION out;
|
||||||
|
STARTUPINFOW si;
|
||||||
|
HANDLE wait_handles[2];
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
|
||||||
|
if (!GetSystemDirectoryW(path, MAX_PATH - strlenW(services)))
|
||||||
|
return FALSE;
|
||||||
|
strcatW(path, services);
|
||||||
|
ZeroMemory(&si, sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
if (!CreateProcessW(path, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &out))
|
||||||
|
{
|
||||||
|
ERR("Couldn't start services.exe: error %u\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
CloseHandle(out.hThread);
|
||||||
|
|
||||||
|
hEvent = CreateEventW(NULL, TRUE, FALSE, svcctl_started_event);
|
||||||
|
wait_handles[0] = hEvent;
|
||||||
|
wait_handles[1] = out.hProcess;
|
||||||
|
|
||||||
|
/* wait for the event to become available or the process to exit */
|
||||||
|
if ((WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE)) == WAIT_OBJECT_0 + 1)
|
||||||
|
{
|
||||||
|
DWORD exit_code;
|
||||||
|
GetExitCodeProcess(out.hProcess, &exit_code);
|
||||||
|
ERR("Unexpected termination of services.exe - exit code %d\n", exit_code);
|
||||||
|
CloseHandle(out.hProcess);
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("services.exe started successfully\n");
|
||||||
|
CloseHandle(out.hProcess);
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Waiting for services.exe to be available\n");
|
||||||
|
WaitForSingleObject(hEvent, INFINITE);
|
||||||
|
TRACE("Services.exe are available\n");
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
|
||||||
|
{
|
||||||
|
WCHAR transport[] = SVCCTL_TRANSPORT;
|
||||||
|
WCHAR endpoint[] = SVCCTL_ENDPOINT;
|
||||||
|
LPWSTR server_copy = NULL;
|
||||||
|
RPC_WSTR binding_str;
|
||||||
|
RPC_STATUS status;
|
||||||
|
handle_t rpc_handle;
|
||||||
|
|
||||||
|
/* unlike Windows we start services.exe on demand. We start it always as
|
||||||
|
* checking if this is our address can be tricky */
|
||||||
|
if (!check_services_exe())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
|
||||||
|
HeapFree(GetProcessHeap(), 0, server_copy);
|
||||||
|
if (status != RPC_S_OK)
|
||||||
|
{
|
||||||
|
ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
|
||||||
|
RpcStringFreeW(&binding_str);
|
||||||
|
|
||||||
|
if (status != RPC_S_OK)
|
||||||
|
{
|
||||||
|
ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpc_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
|
||||||
|
{
|
||||||
|
RpcBindingFree(&h);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* registry access functions and data
|
* registry access functions and data
|
||||||
*/
|
*/
|
||||||
|
@ -959,29 +1068,15 @@ SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
|
||||||
TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
|
TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
|
||||||
debugstr_w(lpDatabaseName), dwDesiredAccess);
|
debugstr_w(lpDatabaseName), dwDesiredAccess);
|
||||||
|
|
||||||
if( lpDatabaseName && lpDatabaseName[0] )
|
|
||||||
{
|
|
||||||
if( strcmpiW( lpDatabaseName, SERVICES_ACTIVE_DATABASEW ) == 0 )
|
|
||||||
{
|
|
||||||
/* noop, all right */
|
|
||||||
}
|
|
||||||
else if( strcmpiW( lpDatabaseName, SERVICES_FAILED_DATABASEW ) == 0 )
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_DATABASE_DOES_NOT_EXIST );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetLastError( ERROR_INVALID_NAME );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
|
manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
|
||||||
sc_handle_destroy_manager );
|
sc_handle_destroy_manager );
|
||||||
if (!manager)
|
if (!manager)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
|
||||||
|
if (r!=ERROR_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
|
r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
|
||||||
if (r!=ERROR_SUCCESS)
|
if (r!=ERROR_SUCCESS)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1093,10 +1188,28 @@ BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
CloseServiceHandle( SC_HANDLE hSCObject )
|
CloseServiceHandle( SC_HANDLE hSCObject )
|
||||||
{
|
{
|
||||||
|
struct sc_handle *obj;
|
||||||
|
DWORD err;
|
||||||
|
|
||||||
TRACE("%p\n", hSCObject);
|
TRACE("%p\n", hSCObject);
|
||||||
|
if (hSCObject == NULL)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
sc_handle_free( (struct sc_handle*) hSCObject );
|
obj = (struct sc_handle *)hSCObject;
|
||||||
|
if (obj->server_handle) /* service handles currently don't have RPC connections */
|
||||||
|
err = svcctl_CloseServiceHandle(&obj->server_handle);
|
||||||
|
else
|
||||||
|
err = ERROR_SUCCESS;
|
||||||
|
sc_handle_free( obj );
|
||||||
|
|
||||||
|
if (err != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
SetLastError(err);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
dlls/advapi32/svcctl.idl
Normal file
1
dlls/advapi32/svcctl.idl
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "wine/svcctl.idl"
|
|
@ -706,11 +706,8 @@ static void test_close(void)
|
||||||
/* NULL handle */
|
/* NULL handle */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CloseServiceHandle(NULL);
|
ret = CloseServiceHandle(NULL);
|
||||||
todo_wine
|
|
||||||
{
|
|
||||||
ok(!ret, "Expected failure\n");
|
ok(!ret, "Expected failure\n");
|
||||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
|
/* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ IDL_H_SRCS = \
|
||||||
urlhist.idl \
|
urlhist.idl \
|
||||||
urlmon.idl \
|
urlmon.idl \
|
||||||
wine/itss.idl \
|
wine/itss.idl \
|
||||||
|
wine/svcctl.idl \
|
||||||
wtypes.idl \
|
wtypes.idl \
|
||||||
xmldom.idl \
|
xmldom.idl \
|
||||||
xmldso.idl
|
xmldso.idl
|
||||||
|
|
59
include/wine/svcctl.idl
Normal file
59
include/wine/svcctl.idl
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* svcctl interface definitions - exported by services.exe to access the
|
||||||
|
* services database
|
||||||
|
*
|
||||||
|
* Copyright 2007 Google (Mikolaj Zalewski)
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "wtypes.idl";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* some defined for the C code
|
||||||
|
*/
|
||||||
|
cpp_quote("#define SVCCTL_TRANSPORT {'n','c','a','c','n','_','n','p',0}")
|
||||||
|
cpp_quote("#define SVCCTL_ENDPOINT {'\\\\','p','i','p','e','\\\\','s','v','c','c','t','l',0}")
|
||||||
|
|
||||||
|
/* Not the Windows event name - if needed the true one can be found in Inside Windows */
|
||||||
|
cpp_quote("#define SVCCTL_STARTED_EVENT {'_','_','w','i','n','e','_','S','v','c','c','t','l','S','t','a','r','t','e','d',0}")
|
||||||
|
|
||||||
|
|
||||||
|
[
|
||||||
|
uuid(367abb81-9844-35f1-ad32-98f038001003),
|
||||||
|
version(2.0),
|
||||||
|
pointer_default(unique),
|
||||||
|
endpoint("ncacn_np:[\\pipe\\svcctl]")
|
||||||
|
]
|
||||||
|
interface svcctl
|
||||||
|
{
|
||||||
|
/* handle types */
|
||||||
|
typedef [handle] LPCWSTR MACHINE_HANDLEW;
|
||||||
|
typedef [context_handle] void *SC_RPC_HANDLE;
|
||||||
|
|
||||||
|
/* Compatible with Windows function 0x00 */
|
||||||
|
DWORD svcctl_CloseServiceHandle(
|
||||||
|
[in,out] SC_RPC_HANDLE *handle
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Compatible with Windows function 0x0f */
|
||||||
|
DWORD svcctl_OpenSCManagerW(
|
||||||
|
[in,unique] MACHINE_HANDLEW MachineName,
|
||||||
|
[in,unique] LPCWSTR DatabaseName,
|
||||||
|
[in] DWORD dwAccessMask,
|
||||||
|
[out] SC_RPC_HANDLE *handle
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
|
@ -5,12 +5,15 @@ VPATH = @srcdir@
|
||||||
MODULE = services.exe
|
MODULE = services.exe
|
||||||
APPMODE = -mconsole
|
APPMODE = -mconsole
|
||||||
IMPORTS = kernel32
|
IMPORTS = kernel32
|
||||||
IMPORTS = advapi32 kernel32
|
IMPORTS = rpcrt4 advapi32 kernel32 ntdll
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
|
rpc.c \
|
||||||
services.c \
|
services.c \
|
||||||
utils.c
|
utils.c
|
||||||
|
|
||||||
|
IDL_S_SRCS = svcctl.idl
|
||||||
|
|
||||||
@MAKE_PROG_RULES@
|
@MAKE_PROG_RULES@
|
||||||
|
|
||||||
@DEPENDENCIES@ # everything below this line is overwritten by make depend
|
@DEPENDENCIES@ # everything below this line is overwritten by make depend
|
||||||
|
|
188
programs/services/rpc.c
Normal file
188
programs/services/rpc.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Services.exe - RPC functions
|
||||||
|
*
|
||||||
|
* Copyright 2007 Google (Mikolaj Zalewski)
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winternl.h>
|
||||||
|
#include <winsvc.h>
|
||||||
|
#include <ntsecapi.h>
|
||||||
|
#include <rpc.h>
|
||||||
|
|
||||||
|
#include "wine/list.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
#include "services.h"
|
||||||
|
#include "svcctl.h"
|
||||||
|
|
||||||
|
extern HANDLE __wine_make_process_system(void);
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(service);
|
||||||
|
|
||||||
|
static CRITICAL_SECTION g_handle_table_cs;
|
||||||
|
static CRITICAL_SECTION_DEBUG g_handle_table_cs_debug =
|
||||||
|
{
|
||||||
|
0, 0, &g_handle_table_cs,
|
||||||
|
{ &g_handle_table_cs_debug.ProcessLocksList,
|
||||||
|
&g_handle_table_cs_debug.ProcessLocksList },
|
||||||
|
0, 0, { (DWORD_PTR)(__FILE__ ": g_handle_table_cs") }
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION g_handle_table_cs = { &g_handle_table_cs_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static const GENERIC_MAPPING g_scm_generic =
|
||||||
|
{
|
||||||
|
(STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
|
||||||
|
(STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
|
||||||
|
(STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
|
||||||
|
SC_MANAGER_ALL_ACCESS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SC_HTYPE_DONT_CARE = 0,
|
||||||
|
SC_HTYPE_MANAGER,
|
||||||
|
SC_HTYPE_SERVICE
|
||||||
|
} SC_HANDLE_TYPE;
|
||||||
|
|
||||||
|
struct sc_handle
|
||||||
|
{
|
||||||
|
SC_HANDLE_TYPE type;
|
||||||
|
DWORD access;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_manager /* service control manager handle */
|
||||||
|
{
|
||||||
|
struct sc_handle hdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
DWORD svcctl_OpenSCManagerW(
|
||||||
|
MACHINE_HANDLEW MachineName, /* Note: this parameter is ignored */
|
||||||
|
LPCWSTR DatabaseName,
|
||||||
|
DWORD dwAccessMask,
|
||||||
|
SC_RPC_HANDLE *handle)
|
||||||
|
{
|
||||||
|
struct sc_manager *manager;
|
||||||
|
|
||||||
|
WINE_TRACE("(%s, %s, %x)\n", wine_dbgstr_w(MachineName), wine_dbgstr_w(DatabaseName), dwAccessMask);
|
||||||
|
|
||||||
|
if (DatabaseName != NULL && DatabaseName[0])
|
||||||
|
{
|
||||||
|
if (strcmpW(DatabaseName, SERVICES_FAILED_DATABASEW) == 0)
|
||||||
|
return ERROR_DATABASE_DOES_NOT_EXIST;
|
||||||
|
if (strcmpW(DatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
|
||||||
|
return ERROR_INVALID_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(manager = HeapAlloc(GetProcessHeap(), 0, sizeof(*manager))))
|
||||||
|
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
|
||||||
|
|
||||||
|
manager->hdr.type = SC_HTYPE_MANAGER;
|
||||||
|
|
||||||
|
if (dwAccessMask & MAXIMUM_ALLOWED)
|
||||||
|
dwAccessMask |= SC_MANAGER_ALL_ACCESS;
|
||||||
|
manager->hdr.access = dwAccessMask;
|
||||||
|
RtlMapGenericMask(&manager->hdr.access, &g_scm_generic);
|
||||||
|
*handle = &manager->hdr;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SC_RPC_HANDLE_destroy(SC_RPC_HANDLE handle)
|
||||||
|
{
|
||||||
|
struct sc_handle *hdr = (struct sc_handle *)handle;
|
||||||
|
switch (hdr->type)
|
||||||
|
{
|
||||||
|
case SC_HTYPE_MANAGER:
|
||||||
|
{
|
||||||
|
struct sc_manager *manager = (struct sc_manager *)hdr;
|
||||||
|
HeapFree(GetProcessHeap(), 0, manager);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WINE_ERR("invalid handle type %d\n", hdr->type);
|
||||||
|
RpcRaiseException(ERROR_INVALID_HANDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD svcctl_CloseServiceHandle(
|
||||||
|
SC_RPC_HANDLE *handle)
|
||||||
|
{
|
||||||
|
WINE_TRACE("(&%p)\n", *handle);
|
||||||
|
|
||||||
|
SC_RPC_HANDLE_destroy(*handle);
|
||||||
|
*handle = NULL;
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD RPC_MainLoop(void)
|
||||||
|
{
|
||||||
|
WCHAR transport[] = SVCCTL_TRANSPORT;
|
||||||
|
WCHAR endpoint[] = SVCCTL_ENDPOINT;
|
||||||
|
HANDLE hSleepHandle;
|
||||||
|
DWORD err;
|
||||||
|
|
||||||
|
if ((err = RpcServerUseProtseqEpW(transport, 0, endpoint, NULL)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WINE_ERR("RpcServerUseProtseq failed with error %u\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = RpcServerRegisterIf(svcctl_v2_0_s_ifspec, 0, 0)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WINE_ERR("RpcServerRegisterIf failed with error %u", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WINE_ERR("RpcServerListen failed with error %u\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
WINE_TRACE("Entered main loop\n");
|
||||||
|
hSleepHandle = __wine_make_process_system();
|
||||||
|
SetEvent(g_hStartedEvent);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = WaitForSingleObjectEx(hSleepHandle, INFINITE, TRUE);
|
||||||
|
WINE_TRACE("Wait returned %d\n", err);
|
||||||
|
} while (err != WAIT_OBJECT_0);
|
||||||
|
|
||||||
|
WINE_TRACE("Object signaled - wine shutdown\n");
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE handle)
|
||||||
|
{
|
||||||
|
SC_RPC_HANDLE_destroy(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
|
||||||
|
{
|
||||||
|
return HeapAlloc(GetProcessHeap(), 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, ptr);
|
||||||
|
}
|
|
@ -23,10 +23,12 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsvc.h>
|
#include <winsvc.h>
|
||||||
|
#include <rpc.h>
|
||||||
|
|
||||||
#include "wine/list.h"
|
#include "wine/list.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "svcctl.h"
|
||||||
|
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
|
|
||||||
|
@ -34,6 +36,8 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(service);
|
WINE_DEFAULT_DEBUG_CHANNEL(service);
|
||||||
|
|
||||||
|
HANDLE g_hStartedEvent;
|
||||||
|
|
||||||
static struct list g_services;
|
static struct list g_services;
|
||||||
|
|
||||||
/* Registry constants */
|
/* Registry constants */
|
||||||
|
@ -196,9 +200,11 @@ static DWORD load_services(void)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
static const WCHAR svcctl_started_event[] = SVCCTL_STARTED_EVENT;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
|
g_hStartedEvent = CreateEventW(NULL, TRUE, FALSE, svcctl_started_event);
|
||||||
list_init(&g_services);
|
list_init(&g_services);
|
||||||
if ((err = load_services()) != ERROR_SUCCESS)
|
if ((err = load_services()) != ERROR_SUCCESS)
|
||||||
return err;
|
return err;
|
||||||
return 0;
|
return RPC_MainLoop();
|
||||||
}
|
}
|
||||||
|
|
1
programs/services/svcctl.idl
Normal file
1
programs/services/svcctl.idl
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "wine/svcctl.idl"
|
Loading…
Reference in a new issue