Commit 8df5add2 authored by Alexandre Julliard's avatar Alexandre Julliard

rpcss: Make rpcss a proper service.

parent 1c5affa2
...@@ -33,6 +33,7 @@ ...@@ -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) ...@@ -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) ); ERR( "failed to open service manager\n" );
strcatW( cmd, rpcss ); return FALSE;
}
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;
Wow64DisableWow64FsRedirection( &redir ); if (!QueryServiceStatusEx( service, SC_STATUS_PROCESS_INFO,
rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi ); (BYTE *)&status, sizeof(status), &dummy ))
Wow64RevertWow64FsRedirection( redir ); break;
if (status.dwCurrentState == SERVICE_RUNNING)
{
ret = TRUE;
break;
}
if (GetTickCount64() - start_time > 30000) break;
Sleep( 100 );
if (rslt) } while (status.dwCurrentState == SERVICE_START_PENDING);
{
CloseHandle(pi.hProcess); if (status.dwCurrentState != SERVICE_RUNNING)
CloseHandle(pi.hThread); WARN( "RpcSs failed to start %u\n", status.dwCurrentState );
Sleep(100);
} }
else ERR( "failed to start RpcSs service\n" );
return rslt; 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 @@ ...@@ -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 ...@@ -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) ); ERR( "failed to open service manager\n" );
lstrcatW( cmd, rpcss ); return FALSE;
}
Wow64DisableWow64FsRedirection( &redir ); if (!(service = OpenServiceW( scm, rpcssW, SERVICE_START | SERVICE_QUERY_STATUS )))
rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi ); {
Wow64RevertWow64FsRedirection( redir ); ERR( "failed to open RpcSs service\n" );
CloseServiceHandle( scm );
if (rslt) return FALSE;
}
if (StartServiceW( service, 0, NULL ) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
{ {
CloseHandle(pi.hProcess); ULONGLONG start_time = GetTickCount64();
CloseHandle(pi.hThread); do
Sleep(100); {
DWORD dummy;
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" );
return rslt; 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=\ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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" ...@@ -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
......
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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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: ...@@ -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) SERVICE_STATUS status;
status.dwServiceType = SERVICE_WIN32;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
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;
}
}
static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
{ {
RpcMgmtStopServerListening(NULL); SERVICE_STATUS status;
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE);
RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE);
CloseHandle(exit_event); TRACE( "starting service\n" );
return TRUE; 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 main( int argc, char **argv ) int wmain( int argc, WCHAR *argv[] )
{ {
/* static const SERVICE_TABLE_ENTRYW service_table[] =
* We are invoked as a standard executable; we act in a {
* "lazy" manner. We register our interfaces and endpoints, and hang around { rpcssW, ServiceMain },
* until we all user processes exit, and then silently terminate. { NULL, NULL }
*/ };
if (RPCSS_Initialize()) { StartServiceCtrlDispatcherW( service_table );
WaitForSingleObject(exit_event, INFINITE); return 0;
RPCSS_Shutdown();
}
return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment