rpcss: Make rpcss a proper service.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1c5affa205
commit
8df5add2d7
|
@ -33,6 +33,7 @@
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
|
#include "winsvc.h"
|
||||||
#include "wtypes.h"
|
#include "wtypes.h"
|
||||||
#include "ole2.h"
|
#include "ole2.h"
|
||||||
|
|
||||||
|
@ -131,32 +132,52 @@ static IrotHandle get_irot_handle(void)
|
||||||
|
|
||||||
static BOOL start_rpcss(void)
|
static BOOL start_rpcss(void)
|
||||||
{
|
{
|
||||||
PROCESS_INFORMATION pi;
|
static const WCHAR rpcssW[] = {'R','p','c','S','s',0};
|
||||||
STARTUPINFOW si;
|
SC_HANDLE scm, service;
|
||||||
WCHAR cmd[MAX_PATH];
|
SERVICE_STATUS_PROCESS status;
|
||||||
static const WCHAR rpcss[] = {'\\','r','p','c','s','s','.','e','x','e',0};
|
BOOL ret = FALSE;
|
||||||
BOOL rslt;
|
|
||||||
void *redir;
|
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
ZeroMemory(&si, sizeof(STARTUPINFOA));
|
if (!(scm = OpenSCManagerW( NULL, NULL, 0 )))
|
||||||
si.cb = sizeof(STARTUPINFOA);
|
|
||||||
GetSystemDirectoryW( cmd, MAX_PATH - sizeof(rpcss)/sizeof(WCHAR) );
|
|
||||||
strcatW( cmd, rpcss );
|
|
||||||
|
|
||||||
Wow64DisableWow64FsRedirection( &redir );
|
|
||||||
rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi );
|
|
||||||
Wow64RevertWow64FsRedirection( redir );
|
|
||||||
|
|
||||||
if (rslt)
|
|
||||||
{
|
{
|
||||||
CloseHandle(pi.hProcess);
|
ERR( "failed to open service manager\n" );
|
||||||
CloseHandle(pi.hThread);
|
return FALSE;
|
||||||
Sleep(100);
|
|
||||||
}
|
}
|
||||||
|
if (!(service = OpenServiceW( scm, rpcssW, SERVICE_START | SERVICE_QUERY_STATUS )))
|
||||||
|
{
|
||||||
|
ERR( "failed to open RpcSs service\n" );
|
||||||
|
CloseServiceHandle( scm );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (StartServiceW( service, 0, NULL ) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
|
||||||
|
{
|
||||||
|
ULONGLONG start_time = GetTickCount64();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD dummy;
|
||||||
|
|
||||||
return rslt;
|
if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
|
||||||
|
(BYTE *)&status, sizeof(status), &dummy ))
|
||||||
|
break;
|
||||||
|
if (status.dwCurrentState == SERVICE_RUNNING)
|
||||||
|
{
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GetTickCount64() - start_time > 30000) break;
|
||||||
|
Sleep( 100 );
|
||||||
|
|
||||||
|
} while (status.dwCurrentState == SERVICE_START_PENDING);
|
||||||
|
|
||||||
|
if (status.dwCurrentState != SERVICE_RUNNING)
|
||||||
|
WARN( "RpcSs failed to start %u\n", status.dwCurrentState );
|
||||||
|
}
|
||||||
|
else ERR( "failed to start RpcSs service\n" );
|
||||||
|
|
||||||
|
CloseServiceHandle( service );
|
||||||
|
CloseServiceHandle( scm );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
|
static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
|
#include "winsvc.h"
|
||||||
|
|
||||||
#include "rpc.h"
|
#include "rpc.h"
|
||||||
|
|
||||||
|
@ -77,32 +78,52 @@ static const struct epm_endpoints
|
||||||
|
|
||||||
static BOOL start_rpcss(void)
|
static BOOL start_rpcss(void)
|
||||||
{
|
{
|
||||||
PROCESS_INFORMATION pi;
|
static const WCHAR rpcssW[] = {'R','p','c','S','s',0};
|
||||||
STARTUPINFOW si;
|
SC_HANDLE scm, service;
|
||||||
WCHAR cmd[MAX_PATH];
|
SERVICE_STATUS_PROCESS status;
|
||||||
static const WCHAR rpcss[] = {'\\','r','p','c','s','s','.','e','x','e',0};
|
BOOL ret = FALSE;
|
||||||
BOOL rslt;
|
|
||||||
void *redir;
|
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
ZeroMemory(&si, sizeof(STARTUPINFOA));
|
if (!(scm = OpenSCManagerW( NULL, NULL, 0 )))
|
||||||
si.cb = sizeof(STARTUPINFOA);
|
|
||||||
GetSystemDirectoryW( cmd, MAX_PATH - sizeof(rpcss)/sizeof(WCHAR) );
|
|
||||||
lstrcatW( cmd, rpcss );
|
|
||||||
|
|
||||||
Wow64DisableWow64FsRedirection( &redir );
|
|
||||||
rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi );
|
|
||||||
Wow64RevertWow64FsRedirection( redir );
|
|
||||||
|
|
||||||
if (rslt)
|
|
||||||
{
|
{
|
||||||
CloseHandle(pi.hProcess);
|
ERR( "failed to open service manager\n" );
|
||||||
CloseHandle(pi.hThread);
|
return FALSE;
|
||||||
Sleep(100);
|
|
||||||
}
|
}
|
||||||
|
if (!(service = OpenServiceW( scm, rpcssW, SERVICE_START | SERVICE_QUERY_STATUS )))
|
||||||
|
{
|
||||||
|
ERR( "failed to open RpcSs service\n" );
|
||||||
|
CloseServiceHandle( scm );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (StartServiceW( service, 0, NULL ) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
|
||||||
|
{
|
||||||
|
ULONGLONG start_time = GetTickCount64();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DWORD dummy;
|
||||||
|
|
||||||
return rslt;
|
if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
|
||||||
|
(BYTE *)&status, sizeof(status), &dummy ))
|
||||||
|
break;
|
||||||
|
if (status.dwCurrentState == SERVICE_RUNNING)
|
||||||
|
{
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (GetTickCount64() - start_time > 30000) break;
|
||||||
|
Sleep( 100 );
|
||||||
|
|
||||||
|
} while (status.dwCurrentState == SERVICE_START_PENDING);
|
||||||
|
|
||||||
|
if (status.dwCurrentState != SERVICE_RUNNING)
|
||||||
|
WARN( "RpcSs failed to start %u\n", status.dwCurrentState );
|
||||||
|
}
|
||||||
|
else ERR( "failed to start RpcSs service\n" );
|
||||||
|
|
||||||
|
CloseServiceHandle( service );
|
||||||
|
CloseServiceHandle( scm );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
|
static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
|
||||||
|
|
|
@ -121,6 +121,7 @@ AddReg=\
|
||||||
AddService=BITS,0,BITSService
|
AddService=BITS,0,BITSService
|
||||||
AddService=MSIServer,0,MSIService
|
AddService=MSIServer,0,MSIService
|
||||||
AddService=MountMgr,0x800,MountMgrService
|
AddService=MountMgr,0x800,MountMgrService
|
||||||
|
AddService=RpcSs,0,RpcSsService
|
||||||
AddService=Spooler,0,SpoolerService
|
AddService=Spooler,0,SpoolerService
|
||||||
AddService=StiSvc,0,StiService
|
AddService=StiSvc,0,StiService
|
||||||
AddService=TermService,0,TerminalServices
|
AddService=TermService,0,TerminalServices
|
||||||
|
@ -134,6 +135,7 @@ AddService=Schedule,0,TaskSchedulerService
|
||||||
AddService=BITS,0,BITSService
|
AddService=BITS,0,BITSService
|
||||||
AddService=MSIServer,0,MSIService
|
AddService=MSIServer,0,MSIService
|
||||||
AddService=MountMgr,0x800,MountMgrService
|
AddService=MountMgr,0x800,MountMgrService
|
||||||
|
AddService=RpcSs,0,RpcSsService
|
||||||
AddService=Spooler,0,SpoolerService
|
AddService=Spooler,0,SpoolerService
|
||||||
AddService=StiSvc,0,StiService
|
AddService=StiSvc,0,StiService
|
||||||
AddService=TermService,0,TerminalServices
|
AddService=TermService,0,TerminalServices
|
||||||
|
@ -147,6 +149,7 @@ AddService=Schedule,0,TaskSchedulerService
|
||||||
AddService=BITS,0,BITSService
|
AddService=BITS,0,BITSService
|
||||||
AddService=MSIServer,0,MSIService
|
AddService=MSIServer,0,MSIService
|
||||||
AddService=MountMgr,0x800,MountMgrService
|
AddService=MountMgr,0x800,MountMgrService
|
||||||
|
AddService=RpcSs,0,RpcSsService
|
||||||
AddService=Spooler,0,SpoolerService
|
AddService=Spooler,0,SpoolerService
|
||||||
AddService=StiSvc,0,StiService
|
AddService=StiSvc,0,StiService
|
||||||
AddService=TermService,0,TerminalServices
|
AddService=TermService,0,TerminalServices
|
||||||
|
@ -3165,6 +3168,14 @@ ServiceType=1
|
||||||
StartType=2
|
StartType=2
|
||||||
ErrorControl=1
|
ErrorControl=1
|
||||||
|
|
||||||
|
[RpcSsService]
|
||||||
|
Description="RPC service"
|
||||||
|
DisplayName="Remote Procedure Call (RPC)"
|
||||||
|
ServiceBinary="%11%\rpcss.exe"
|
||||||
|
ServiceType=32
|
||||||
|
StartType=3
|
||||||
|
ErrorControl=1
|
||||||
|
|
||||||
[SpoolerService]
|
[SpoolerService]
|
||||||
Description="Loads files to memory for later printing"
|
Description="Loads files to memory for later printing"
|
||||||
DisplayName="Print Spooler"
|
DisplayName="Print Spooler"
|
||||||
|
@ -3258,7 +3269,6 @@ HKLM,%CurrentVersionNT%\SvcHost,"netsvcs",0x00010008,"Schedule"
|
||||||
HKLM,%CurrentVersion%\RunServices,"winemenubuilder",2,"%11%\winemenubuilder.exe -a -r"
|
HKLM,%CurrentVersion%\RunServices,"winemenubuilder",2,"%11%\winemenubuilder.exe -a -r"
|
||||||
HKLM,"System\CurrentControlSet\Services\Eventlog\Application",,16
|
HKLM,"System\CurrentControlSet\Services\Eventlog\Application",,16
|
||||||
HKLM,"System\CurrentControlSet\Services\Eventlog\System",,16
|
HKLM,"System\CurrentControlSet\Services\Eventlog\System",,16
|
||||||
HKLM,"System\CurrentControlSet\Services\RpcSs",,16
|
|
||||||
HKLM,"System\CurrentControlSet\Services\Tcpip\Parameters",,16
|
HKLM,"System\CurrentControlSet\Services\Tcpip\Parameters",,16
|
||||||
HKLM,"System\CurrentControlSet\Services\VxD\MSTCP",,16
|
HKLM,"System\CurrentControlSet\Services\VxD\MSTCP",,16
|
||||||
HKLM,"System\CurrentControlSet\Services\Winsock\Parameters",,16
|
HKLM,"System\CurrentControlSet\Services\Winsock\Parameters",,16
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
MODULE = rpcss.exe
|
MODULE = rpcss.exe
|
||||||
APPMODE = -mconsole
|
APPMODE = -mconsole -municode
|
||||||
IMPORTS = rpcrt4
|
IMPORTS = rpcrt4 advapi32
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
epmp.c \
|
epmp.c \
|
||||||
|
|
|
@ -15,32 +15,6 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*
|
|
||||||
* ---- rpcss_main.c:
|
|
||||||
* Initialize and start serving requests. Bail if rpcss already is
|
|
||||||
* running.
|
|
||||||
*
|
|
||||||
* ---- RPCSS.EXE:
|
|
||||||
*
|
|
||||||
* Wine needs a server whose role is somewhat like that
|
|
||||||
* of rpcss.exe in windows. This is not a clone of
|
|
||||||
* windows rpcss at all. It has been given the same name, however,
|
|
||||||
* to provide for the possibility that at some point in the future,
|
|
||||||
* it may become interface compatible with the "real" rpcss.exe on
|
|
||||||
* Windows.
|
|
||||||
*
|
|
||||||
* ---- KNOWN BUGS / TODO:
|
|
||||||
*
|
|
||||||
* o Service hooks are unimplemented (if you bother to implement
|
|
||||||
* these, also implement net.exe, at least for "net start" and
|
|
||||||
* "net stop" (should be pretty easy I guess, assuming the rest
|
|
||||||
* of the services API infrastructure works.
|
|
||||||
*
|
|
||||||
* o There is a looming problem regarding listening on privileged
|
|
||||||
* ports. We will need to be able to coexist with SAMBA, and be able
|
|
||||||
* to function without running winelib code as root. This may
|
|
||||||
* take some doing, including significant reconceptualization of the
|
|
||||||
* role of rpcss.exe in wine.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -51,6 +25,7 @@
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
#include "winsvc.h"
|
||||||
#include "irot.h"
|
#include "irot.h"
|
||||||
#include "epm.h"
|
#include "epm.h"
|
||||||
|
|
||||||
|
@ -58,9 +33,9 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||||
|
|
||||||
|
static WCHAR rpcssW[] = {'R','p','c','S','s',0};
|
||||||
static HANDLE exit_event;
|
static HANDLE exit_event;
|
||||||
|
static SERVICE_STATUS_HANDLE service_handle;
|
||||||
extern HANDLE CDECL __wine_make_process_system(void);
|
|
||||||
|
|
||||||
static BOOL RPCSS_Initialize(void)
|
static BOOL RPCSS_Initialize(void)
|
||||||
{
|
{
|
||||||
|
@ -103,8 +78,6 @@ static BOOL RPCSS_Initialize(void)
|
||||||
if (status != RPC_S_OK)
|
if (status != RPC_S_OK)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
exit_event = __wine_make_process_system();
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -113,31 +86,76 @@ fail:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns false if we discover at the last moment that we
|
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
|
||||||
aren't ready to terminate */
|
|
||||||
static BOOL RPCSS_Shutdown(void)
|
|
||||||
{
|
{
|
||||||
RpcMgmtStopServerListening(NULL);
|
SERVICE_STATUS status;
|
||||||
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE);
|
|
||||||
RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE);
|
|
||||||
|
|
||||||
CloseHandle(exit_event);
|
status.dwServiceType = SERVICE_WIN32;
|
||||||
|
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||||
|
status.dwWin32ExitCode = 0;
|
||||||
|
status.dwServiceSpecificExitCode = 0;
|
||||||
|
status.dwCheckPoint = 0;
|
||||||
|
status.dwWaitHint = 0;
|
||||||
|
|
||||||
return TRUE;
|
switch (ctrl)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
TRACE( "shutting down\n" );
|
||||||
|
RpcMgmtStopServerListening( NULL );
|
||||||
|
RpcServerUnregisterIf( epm_v3_0_s_ifspec, NULL, TRUE );
|
||||||
|
RpcServerUnregisterIf( Irot_v0_2_s_ifspec, NULL, TRUE );
|
||||||
|
status.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
|
status.dwControlsAccepted = 0;
|
||||||
|
SetServiceStatus( service_handle, &status );
|
||||||
|
SetEvent( exit_event );
|
||||||
|
return NO_ERROR;
|
||||||
|
default:
|
||||||
|
FIXME( "got service ctrl %x\n", ctrl );
|
||||||
|
status.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
SetServiceStatus( service_handle, &status );
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
|
||||||
{
|
{
|
||||||
/*
|
SERVICE_STATUS status;
|
||||||
* We are invoked as a standard executable; we act in a
|
|
||||||
* "lazy" manner. We register our interfaces and endpoints, and hang around
|
|
||||||
* until we all user processes exit, and then silently terminate.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (RPCSS_Initialize()) {
|
TRACE( "starting service\n" );
|
||||||
WaitForSingleObject(exit_event, INFINITE);
|
|
||||||
RPCSS_Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
if (!RPCSS_Initialize()) return;
|
||||||
|
|
||||||
|
exit_event = CreateEventW( NULL, TRUE, FALSE, NULL );
|
||||||
|
|
||||||
|
service_handle = RegisterServiceCtrlHandlerExW( rpcssW, service_handler, NULL );
|
||||||
|
if (!service_handle) return;
|
||||||
|
|
||||||
|
status.dwServiceType = SERVICE_WIN32;
|
||||||
|
status.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||||
|
status.dwWin32ExitCode = 0;
|
||||||
|
status.dwServiceSpecificExitCode = 0;
|
||||||
|
status.dwCheckPoint = 0;
|
||||||
|
status.dwWaitHint = 10000;
|
||||||
|
SetServiceStatus( service_handle, &status );
|
||||||
|
|
||||||
|
WaitForSingleObject( exit_event, INFINITE );
|
||||||
|
|
||||||
|
status.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
status.dwControlsAccepted = 0;
|
||||||
|
SetServiceStatus( service_handle, &status );
|
||||||
|
TRACE( "service stopped\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain( int argc, WCHAR *argv[] )
|
||||||
|
{
|
||||||
|
static const SERVICE_TABLE_ENTRYW service_table[] =
|
||||||
|
{
|
||||||
|
{ rpcssW, ServiceMain },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
StartServiceCtrlDispatcherW( service_table );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue