rpcrt4/rpcss: Remove old named pipe code for communicating with RPCSS process.
This commit is contained in:
parent
9e1c7a30c7
commit
45a3462c32
|
@ -25,8 +25,7 @@ C_SRCS = \
|
|||
rpc_message.c \
|
||||
rpc_server.c \
|
||||
rpc_transport.c \
|
||||
rpcrt4_main.c \
|
||||
rpcss_np_client.c
|
||||
rpcrt4_main.c
|
||||
|
||||
RC_SRCS = version.rc
|
||||
|
||||
|
|
|
@ -150,9 +150,6 @@ RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding);
|
|||
RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
|
||||
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId);
|
||||
RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection);
|
||||
BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply);
|
||||
HANDLE RPCRT4_GetMasterMutex(void);
|
||||
HANDLE RPCRT4_RpcssNPConnect(void);
|
||||
|
||||
static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection)
|
||||
{
|
||||
|
|
|
@ -53,19 +53,12 @@
|
|||
#include "rpcproxy.h"
|
||||
|
||||
#include "rpc_binding.h"
|
||||
#include "rpcss_np_client.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
|
||||
|
||||
static UUID uuid_nil;
|
||||
static HANDLE master_mutex;
|
||||
|
||||
HANDLE RPCRT4_GetMasterMutex(void)
|
||||
{
|
||||
return master_mutex;
|
||||
}
|
||||
|
||||
static CRITICAL_SECTION uuid_cs;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
|
@ -122,9 +115,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);
|
||||
if (!master_mutex)
|
||||
ERR("Failed to create master mutex\n");
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
|
@ -145,8 +135,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
CloseHandle(master_mutex);
|
||||
master_mutex = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -645,102 +633,6 @@ HRESULT WINAPI DllRegisterServer( void )
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static BOOL RPCRT4_StartRPCSS(void)
|
||||
{
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOA si;
|
||||
static char cmd[6];
|
||||
BOOL rslt;
|
||||
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFOA));
|
||||
si.cb = sizeof(STARTUPINFOA);
|
||||
|
||||
/* apparently it's not OK to use a constant string below */
|
||||
CopyMemory(cmd, "rpcss", 6);
|
||||
|
||||
/* FIXME: will this do the right thing when run as a test? */
|
||||
rslt = CreateProcessA(
|
||||
NULL, /* executable */
|
||||
cmd, /* command line */
|
||||
NULL, /* process security attributes */
|
||||
NULL, /* primary thread security attributes */
|
||||
FALSE, /* inherit handles */
|
||||
0, /* creation flags */
|
||||
NULL, /* use parent's environment */
|
||||
NULL, /* use parent's current directory */
|
||||
&si, /* STARTUPINFO pointer */
|
||||
&pi /* PROCESS_INFORMATION */
|
||||
);
|
||||
|
||||
if (rslt) {
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RPCRT4_RPCSSOnDemandCall (internal)
|
||||
*
|
||||
* Attempts to send a message to the RPCSS process
|
||||
* on the local machine, invoking it if necessary.
|
||||
* For remote RPCSS calls, use.... your imagination.
|
||||
*
|
||||
* PARAMS
|
||||
* msg [I] pointer to the RPCSS message
|
||||
* vardata_payload [I] pointer vardata portion of the RPCSS message
|
||||
* reply [O] pointer to reply structure
|
||||
*
|
||||
* RETURNS
|
||||
* TRUE if successful
|
||||
* FALSE otherwise
|
||||
*/
|
||||
BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply)
|
||||
{
|
||||
HANDLE client_handle;
|
||||
BOOL ret;
|
||||
int i, j = 0;
|
||||
|
||||
TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg, vardata_payload, reply);
|
||||
|
||||
client_handle = RPCRT4_RpcssNPConnect();
|
||||
|
||||
while (INVALID_HANDLE_VALUE == client_handle) {
|
||||
/* start the RPCSS process */
|
||||
if (!RPCRT4_StartRPCSS()) {
|
||||
ERR("Unable to start RPCSS process.\n");
|
||||
return FALSE;
|
||||
}
|
||||
/* wait for a connection (w/ periodic polling) */
|
||||
for (i = 0; i < 60; i++) {
|
||||
Sleep(200);
|
||||
client_handle = RPCRT4_RpcssNPConnect();
|
||||
if (INVALID_HANDLE_VALUE != client_handle) break;
|
||||
}
|
||||
/* we are only willing to try twice */
|
||||
if (j++ >= 1) break;
|
||||
}
|
||||
|
||||
if (INVALID_HANDLE_VALUE == client_handle) {
|
||||
/* no dice! */
|
||||
ERR("Unable to connect to RPCSS process!\n");
|
||||
SetLastError(RPC_E_SERVER_DIED_DNE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* great, we're connected. now send the message */
|
||||
ret = TRUE;
|
||||
if (!RPCRT4_SendReceiveNPMsg(client_handle, msg, vardata_payload, reply)) {
|
||||
ERR("Something is amiss: RPC_SendReceive failed.\n");
|
||||
ret = FALSE;
|
||||
}
|
||||
CloseHandle(client_handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_RPC_ERROR_TEXT 256
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* RPCSS named pipe client implementation
|
||||
*
|
||||
* Copyright (C) 2002 Greg Turner
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wine/rpcss_shared.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "rpc_binding.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
HANDLE RPCRT4_RpcssNPConnect(void)
|
||||
{
|
||||
HANDLE the_pipe;
|
||||
DWORD dwmode, wait_result;
|
||||
HANDLE master_mutex = RPCRT4_GetMasterMutex();
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
while (TRUE) {
|
||||
|
||||
wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT);
|
||||
switch (wait_result) {
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT:
|
||||
default:
|
||||
ERR("This should never happen: couldn't enter mutex.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to open the client side of the named pipe. */
|
||||
the_pipe = CreateFileA(
|
||||
NAME_RPCSS_NAMED_PIPE, /* pipe name */
|
||||
GENERIC_READ | GENERIC_WRITE, /* r/w access */
|
||||
0, /* no sharing */
|
||||
NULL, /* no security attributes */
|
||||
OPEN_EXISTING, /* open an existing pipe */
|
||||
0, /* default attributes */
|
||||
NULL /* no template file */
|
||||
);
|
||||
|
||||
if (the_pipe != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
if (GetLastError() != ERROR_PIPE_BUSY) {
|
||||
WARN("Unable to open named pipe %s (assuming unavailable).\n",
|
||||
debugstr_a(NAME_RPCSS_NAMED_PIPE));
|
||||
break;
|
||||
}
|
||||
|
||||
WARN("Named pipe busy (will wait)\n");
|
||||
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
ERR("Failed to release master mutex. Expect deadlock.\n");
|
||||
|
||||
/* wait for the named pipe. We are only willing to wait for 5 seconds.
|
||||
It should be available /very/ soon. */
|
||||
if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT))
|
||||
{
|
||||
ERR("Named pipe unavailable after waiting. Something is probably wrong.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (the_pipe != INVALID_HANDLE_VALUE) {
|
||||
dwmode = PIPE_READMODE_MESSAGE;
|
||||
/* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */
|
||||
if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL))
|
||||
WARN("Failed to set pipe handle state\n");
|
||||
}
|
||||
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
ERR("Uh oh, failed to leave the RPC Master Mutex!\n");
|
||||
|
||||
return the_pipe;
|
||||
}
|
||||
|
||||
BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PRPCSS_NP_REPLY reply)
|
||||
{
|
||||
DWORD count;
|
||||
UINT32 payload_offset;
|
||||
RPCSS_NP_MESSAGE vardata_payload_msg;
|
||||
|
||||
TRACE("(np == %p, msg == %p, vardata == %p, reply == %p)\n",
|
||||
np, msg, vardata, reply);
|
||||
|
||||
if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) {
|
||||
ERR("write failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count != sizeof(RPCSS_NP_MESSAGE)) {
|
||||
ERR("write count mismatch.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* process the vardata payload if necessary */
|
||||
vardata_payload_msg.message_type = RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG;
|
||||
vardata_payload_msg.vardata_payload_size = 0; /* meaningless */
|
||||
for ( payload_offset = 0; payload_offset < msg->vardata_payload_size;
|
||||
payload_offset += VARDATA_PAYLOAD_BYTES ) {
|
||||
TRACE("sending vardata payload. vd=%p, po=%d, ps=%d\n", vardata,
|
||||
payload_offset, msg->vardata_payload_size);
|
||||
ZeroMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES);
|
||||
CopyMemory(vardata_payload_msg.message.vardatapayloadmsg.payload,
|
||||
vardata,
|
||||
min( VARDATA_PAYLOAD_BYTES, msg->vardata_payload_size - payload_offset ));
|
||||
vardata += VARDATA_PAYLOAD_BYTES;
|
||||
if (! WriteFile(np, &vardata_payload_msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) {
|
||||
ERR("vardata write failed at %u bytes.\n", payload_offset);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) {
|
||||
ERR("read failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count != sizeof(RPCSS_NP_REPLY)) {
|
||||
ERR("read count mismatch. got %d.\n", count);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* message execution was successful */
|
||||
return TRUE;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Greg Turner
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __WINE_RPCSS_NP_CLIENT_H
|
||||
#define __WINE_RPCSS_NP_CLIENT_H
|
||||
|
||||
/* rpcss_np_client.c */
|
||||
HANDLE RPC_RpcssNPConnect(void);
|
||||
BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY);
|
||||
|
||||
#endif /* __RPCSS_NP_CLIENT_H */
|
|
@ -7,11 +7,9 @@ APPMODE = -mconsole
|
|||
IMPORTS = rpcrt4 kernel32 ntdll
|
||||
|
||||
C_SRCS = \
|
||||
epmap_server.c \
|
||||
epmp.c \
|
||||
irotp.c \
|
||||
np_server.c \
|
||||
rpcss_main.c
|
||||
irotp.c \
|
||||
rpcss_main.c
|
||||
|
||||
IDL_S_SRCS = \
|
||||
epm.idl \
|
||||
|
|
|
@ -1,210 +0,0 @@
|
|||
/*
|
||||
* RPC endpoint mapper server
|
||||
*
|
||||
* Copyright (C) 2001 Ove Kåven, TransGaming Technologies Inc,
|
||||
* Copyright (C) 2002 Greg Turner
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rpcss.h"
|
||||
#include "rpc.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
struct epmap_entry
|
||||
{
|
||||
struct epmap_entry *next;
|
||||
RPC_SYNTAX_IDENTIFIER iface;
|
||||
UUID object;
|
||||
char *protseq;
|
||||
char *endpoint;
|
||||
};
|
||||
|
||||
static struct epmap_entry *epmap;
|
||||
|
||||
static const UUID nil_object;
|
||||
|
||||
static char *mystrdup(const char *str) {
|
||||
char *rval;
|
||||
rval = LocalAlloc(LPTR, strlen(str)+1);
|
||||
CopyMemory(rval, str, strlen(str)+1);
|
||||
return rval;
|
||||
}
|
||||
|
||||
static struct epmap_entry *find_endpoint(const RPC_SYNTAX_IDENTIFIER *iface,
|
||||
const char *protseq, const UUID *object)
|
||||
{
|
||||
struct epmap_entry *map;
|
||||
for (map=epmap; map; map=map->next) {
|
||||
if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
|
||||
if (memcmp(&map->object, object, sizeof(UUID))) continue;
|
||||
if (strcmp(map->protseq, protseq)) continue;
|
||||
WINE_TRACE("found.\n");
|
||||
return map;
|
||||
}
|
||||
WINE_TRACE("not found.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void register_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
|
||||
const char *endpoint, const UUID *objects, int objcount,
|
||||
int no_replace)
|
||||
{
|
||||
int c;
|
||||
|
||||
WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i, no_replace == %i)\n",
|
||||
wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount, no_replace);
|
||||
|
||||
if (!objcount) {
|
||||
objects = &nil_object;
|
||||
objcount = 1;
|
||||
}
|
||||
|
||||
for (c=0; c<objcount; c++) {
|
||||
struct epmap_entry *map = NULL;
|
||||
if (!no_replace)
|
||||
map = find_endpoint(iface, protseq, &objects[c]);
|
||||
if (map) {
|
||||
LocalFree(map->endpoint);
|
||||
}
|
||||
else {
|
||||
map = LocalAlloc(LPTR, sizeof(struct epmap_entry));
|
||||
memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER));
|
||||
memcpy(&map->object, &objects[c], sizeof(UUID));
|
||||
map->protseq = mystrdup(protseq);
|
||||
map->next = epmap;
|
||||
epmap = map;
|
||||
}
|
||||
WINE_TRACE(" mapping endpoint (protseq == %s, endpoint == %s, uuid == %s)\n",
|
||||
wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), wine_dbgstr_guid(&objects[c]));
|
||||
map->endpoint = mystrdup(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
static void unregister_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
|
||||
const char *endpoint, const UUID *objects, int objcount)
|
||||
{
|
||||
struct epmap_entry *map, *prev, *nprev, *next;
|
||||
int c;
|
||||
|
||||
WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i)\n",
|
||||
wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount);
|
||||
|
||||
if (!objcount) {
|
||||
objects = &nil_object;
|
||||
objcount = 1;
|
||||
}
|
||||
prev=NULL;
|
||||
nprev=NULL;
|
||||
map=epmap;
|
||||
while(map) {
|
||||
next = map->next;
|
||||
nprev = map;
|
||||
if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) goto cont;
|
||||
for (c=0; c<objcount; c++)
|
||||
if (!memcmp(&map->object, &objects[c], sizeof(UUID))) break;
|
||||
if (c==objcount) goto cont;
|
||||
if (strcmp(map->protseq, protseq)) goto cont;
|
||||
|
||||
WINE_TRACE(" unmapping: (protseq == %s, endpoint == %s, uuid == %s)\n",
|
||||
wine_dbgstr_a(map->protseq), wine_dbgstr_a(map->endpoint),
|
||||
wine_dbgstr_guid(&map->object));
|
||||
|
||||
if (prev) prev->next = map->next;
|
||||
else epmap = map->next;
|
||||
nprev = prev;
|
||||
|
||||
LocalFree(map->protseq);
|
||||
LocalFree(map->endpoint);
|
||||
LocalFree(map);
|
||||
|
||||
cont:
|
||||
|
||||
prev = nprev;
|
||||
map = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
|
||||
const UUID *object, char *rslt_ep)
|
||||
{
|
||||
size_t len;
|
||||
struct epmap_entry *map;
|
||||
|
||||
if (!(map = find_endpoint(iface, protseq, object))) return;
|
||||
|
||||
len = min( MAX_RPCSS_NP_REPLY_STRING_LEN, strlen(map->endpoint)+1 );
|
||||
if (len) memcpy(rslt_ep, map->endpoint, len);
|
||||
}
|
||||
|
||||
static const char *get_string(const char**ptr, const char*end)
|
||||
{
|
||||
const char *str = *ptr, *nptr = str;
|
||||
|
||||
while (nptr < end && *nptr) nptr++;
|
||||
if (nptr == end)
|
||||
return NULL;
|
||||
*ptr = nptr + 1;
|
||||
return str;
|
||||
}
|
||||
|
||||
BOOL RPCSS_EpmapEmpty(void)
|
||||
{
|
||||
return (!epmap);
|
||||
}
|
||||
|
||||
void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count,
|
||||
int binding_count, int no_replace, char *vardata, long vardata_size)
|
||||
{
|
||||
const char *data = vardata;
|
||||
const char *end = data + vardata_size;
|
||||
const UUID *objects = (const UUID *)data;
|
||||
int c;
|
||||
|
||||
data += object_count * sizeof(UUID);
|
||||
for (c=0; c < binding_count; c++) {
|
||||
const char *protseq = get_string(&data, end);
|
||||
const char *endpoint = get_string(&data, end);
|
||||
if (protseq && endpoint)
|
||||
register_endpoint(&iface, protseq, endpoint, objects, object_count, no_replace);
|
||||
}
|
||||
}
|
||||
|
||||
void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count,
|
||||
int binding_count, char *vardata, long vardata_size)
|
||||
{
|
||||
const char *data = vardata;
|
||||
const char *end = data + vardata_size;
|
||||
const UUID *objects = (const UUID *)data;
|
||||
int c;
|
||||
|
||||
data += object_count * sizeof(UUID);
|
||||
for (c=0; c < binding_count; c++) {
|
||||
const char *protseq = get_string(&data, end);
|
||||
const char *endpoint = get_string(&data, end);
|
||||
if (protseq && endpoint)
|
||||
unregister_endpoint(&iface, protseq, endpoint, objects, object_count);
|
||||
}
|
||||
}
|
||||
|
||||
void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object, char *protseq, char *rslt_ep)
|
||||
{
|
||||
resolve_endpoint(&iface, protseq, &object, rslt_ep);
|
||||
}
|
|
@ -1,527 +0,0 @@
|
|||
/*
|
||||
* RPCSS named pipe server
|
||||
*
|
||||
* Copyright (C) 2002 Greg Turner
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "rpcss.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
static HANDLE np_server_end;
|
||||
static HANDLE np_server_work_event;
|
||||
static CRITICAL_SECTION np_server_cs;
|
||||
static LONG srv_thread_count;
|
||||
static BOOL server_live;
|
||||
|
||||
LONG RPCSS_SrvThreadCount(void)
|
||||
{
|
||||
return srv_thread_count;
|
||||
}
|
||||
|
||||
BOOL RPCSS_UnBecomePipeServer(void)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
|
||||
WINE_TRACE("shutting down pipe.\n");
|
||||
server_live = FALSE;
|
||||
if (!CloseHandle(np_server_end))
|
||||
WINE_WARN("Failed to close named pipe.\n");
|
||||
if (!CloseHandle(np_server_work_event))
|
||||
WINE_WARN("Failed to close the event handle.\n");
|
||||
DeleteCriticalSection(&np_server_cs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void RPCSS_ServerProcessRANMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
pReply->as_uint = 0;
|
||||
}
|
||||
|
||||
static void RPCSS_ServerProcessREGISTEREPMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply,
|
||||
char *vardata)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
|
||||
RPCSS_RegisterRpcEndpoints(
|
||||
pMsg->message.registerepmsg.iface,
|
||||
pMsg->message.registerepmsg.object_count,
|
||||
pMsg->message.registerepmsg.binding_count,
|
||||
pMsg->message.registerepmsg.no_replace,
|
||||
vardata,
|
||||
pMsg->vardata_payload_size
|
||||
);
|
||||
|
||||
/* no reply */
|
||||
pReply->as_uint = 0;
|
||||
}
|
||||
|
||||
static void RPCSS_ServerProcessUNREGISTEREPMessage(PRPCSS_NP_MESSAGE pMsg,
|
||||
PRPCSS_NP_REPLY pReply, char *vardata)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
|
||||
RPCSS_UnregisterRpcEndpoints(
|
||||
pMsg->message.unregisterepmsg.iface,
|
||||
pMsg->message.unregisterepmsg.object_count,
|
||||
pMsg->message.unregisterepmsg.binding_count,
|
||||
vardata,
|
||||
pMsg->vardata_payload_size
|
||||
);
|
||||
|
||||
/* no reply */
|
||||
pReply->as_uint = 0;
|
||||
}
|
||||
|
||||
static void RPCSS_ServerProcessRESOLVEEPMessage(PRPCSS_NP_MESSAGE pMsg,
|
||||
PRPCSS_NP_REPLY pReply, char *vardata)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
|
||||
/* for now, reply is placed into *pReply.as_string, on success, by RPCSS_ResolveRpcEndpoints */
|
||||
ZeroMemory(pReply->as_string, MAX_RPCSS_NP_REPLY_STRING_LEN);
|
||||
RPCSS_ResolveRpcEndpoints(
|
||||
pMsg->message.resolveepmsg.iface,
|
||||
pMsg->message.resolveepmsg.object,
|
||||
vardata,
|
||||
pReply->as_string
|
||||
);
|
||||
}
|
||||
|
||||
static void RPCSS_ServerProcessMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply, char *vardata)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
ZeroMemory(pReply, sizeof(*pReply));
|
||||
switch (pMsg->message_type) {
|
||||
case RPCSS_NP_MESSAGE_TYPEID_RANMSG:
|
||||
RPCSS_ServerProcessRANMessage(pMsg, pReply);
|
||||
break;
|
||||
case RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG:
|
||||
RPCSS_ServerProcessREGISTEREPMessage(pMsg, pReply, vardata);
|
||||
break;
|
||||
case RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG:
|
||||
RPCSS_ServerProcessUNREGISTEREPMessage(pMsg, pReply, vardata);
|
||||
break;
|
||||
case RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG:
|
||||
RPCSS_ServerProcessRESOLVEEPMessage(pMsg, pReply, vardata);
|
||||
break;
|
||||
default:
|
||||
WINE_ERR("Message type unknown!! No action taken.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* each message gets its own thread. this is it. */
|
||||
static DWORD WINAPI HandlerThread(LPVOID lpvPipeHandle)
|
||||
{
|
||||
RPCSS_NP_MESSAGE msg, vardata_payload_msg;
|
||||
char *c, *vardata = NULL;
|
||||
RPCSS_NP_REPLY reply;
|
||||
DWORD bytesread, written;
|
||||
BOOL success, had_payload = FALSE;
|
||||
HANDLE mypipe;
|
||||
|
||||
mypipe = (HANDLE) lpvPipeHandle;
|
||||
|
||||
WINE_TRACE("mypipe: %p\n", mypipe);
|
||||
|
||||
success = ReadFile(
|
||||
mypipe, /* pipe handle */
|
||||
(char *) &msg, /* message buffer */
|
||||
sizeof(RPCSS_NP_MESSAGE), /* message buffer size */
|
||||
&bytesread, /* receives number of bytes read */
|
||||
NULL /* not overlapped */
|
||||
);
|
||||
|
||||
if (msg.vardata_payload_size) {
|
||||
had_payload = TRUE;
|
||||
/* this fudge space allows us not to worry about exceeding the buffer space
|
||||
on the last read */
|
||||
vardata = LocalAlloc(LPTR, (msg.vardata_payload_size) + VARDATA_PAYLOAD_BYTES);
|
||||
if (!vardata) {
|
||||
WINE_ERR("vardata memory allocation failure.\n");
|
||||
success = FALSE;
|
||||
} else {
|
||||
for ( c = vardata; (c - vardata) < msg.vardata_payload_size;
|
||||
c += VARDATA_PAYLOAD_BYTES) {
|
||||
success = ReadFile(
|
||||
mypipe,
|
||||
(char *) &vardata_payload_msg,
|
||||
sizeof(RPCSS_NP_MESSAGE),
|
||||
&bytesread,
|
||||
NULL
|
||||
);
|
||||
if ( (!success) || (bytesread != sizeof(RPCSS_NP_MESSAGE)) ||
|
||||
(vardata_payload_msg.message_type != RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG) ) {
|
||||
WINE_ERR("vardata payload read failure! (s=%s,br=%d,mt=%u,mt_exp=%u\n",
|
||||
success ? "TRUE" : "FALSE", bytesread,
|
||||
vardata_payload_msg.message_type, RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG);
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
CopyMemory(c, vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES);
|
||||
WINE_TRACE("payload read.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success && (bytesread == sizeof(RPCSS_NP_MESSAGE))) {
|
||||
WINE_TRACE("read success.\n");
|
||||
/* process the message and send a reply, serializing requests. */
|
||||
EnterCriticalSection(&np_server_cs);
|
||||
WINE_TRACE("processing message.\n");
|
||||
RPCSS_ServerProcessMessage(&msg, &reply, vardata);
|
||||
LeaveCriticalSection(&np_server_cs);
|
||||
|
||||
if (had_payload) LocalFree(vardata);
|
||||
|
||||
WINE_TRACE("message processed, sending reply....\n");
|
||||
|
||||
success = WriteFile(
|
||||
mypipe, /* pipe handle */
|
||||
(char *) &reply, /* reply buffer */
|
||||
sizeof(RPCSS_NP_REPLY), /* reply buffer size */
|
||||
&written, /* receives number of bytes written */
|
||||
NULL /* not overlapped */
|
||||
);
|
||||
|
||||
if ( (!success) || (written != sizeof(RPCSS_NP_REPLY)) )
|
||||
WINE_WARN("Message reply failed. (success=%d, br=%d)\n", success, written);
|
||||
else
|
||||
WINE_TRACE("Reply sent successfully.\n");
|
||||
} else
|
||||
WINE_WARN("Message receipt failed.\n");
|
||||
|
||||
FlushFileBuffers(mypipe);
|
||||
DisconnectNamedPipe(mypipe);
|
||||
CloseHandle(mypipe);
|
||||
InterlockedDecrement(&srv_thread_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI NPMainWorkThread(LPVOID ignored)
|
||||
{
|
||||
BOOL connected;
|
||||
HANDLE hthread, master_mutex = RPCSS_GetMasterMutex();
|
||||
DWORD threadid, wait_result;
|
||||
|
||||
WINE_TRACE("\n");
|
||||
|
||||
while (server_live) {
|
||||
connected = ConnectNamedPipe(np_server_end, NULL) ?
|
||||
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
|
||||
|
||||
if (connected) {
|
||||
/* is "work" the act of connecting pipes, or the act of serving
|
||||
requests successfully? for now I will make it the former. */
|
||||
if (!SetEvent(np_server_work_event))
|
||||
WINE_WARN("failed to signal np_server_work_event.\n");
|
||||
|
||||
/* Create a thread for this client. */
|
||||
InterlockedIncrement(&srv_thread_count);
|
||||
hthread = CreateThread(
|
||||
NULL, /* no security attribute */
|
||||
0, /* default stack size */
|
||||
HandlerThread,
|
||||
(LPVOID) np_server_end, /* thread parameter */
|
||||
0, /* not suspended */
|
||||
&threadid /* returns thread ID (not used) */
|
||||
);
|
||||
|
||||
if (hthread) {
|
||||
WINE_TRACE("Spawned handler thread: %p\n", hthread);
|
||||
CloseHandle(hthread);
|
||||
|
||||
/* for safety's sake, hold the mutex while we switch the pipe */
|
||||
|
||||
wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT);
|
||||
|
||||
switch (wait_result) {
|
||||
case WAIT_ABANDONED: /* ? */
|
||||
case WAIT_OBJECT_0:
|
||||
/* we have ownership */
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT:
|
||||
default:
|
||||
/* huh? */
|
||||
wait_result = WAIT_FAILED;
|
||||
}
|
||||
|
||||
if (wait_result == WAIT_FAILED) {
|
||||
WINE_ERR("Couldn't enter master mutex. Expect problems.\n");
|
||||
} else {
|
||||
/* now create a new named pipe instance to listen on */
|
||||
np_server_end = CreateNamedPipe(
|
||||
NAME_RPCSS_NAMED_PIPE, /* pipe name */
|
||||
PIPE_ACCESS_DUPLEX, /* pipe open mode */
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, /* pipe-specific modes */
|
||||
PIPE_UNLIMITED_INSTANCES, /* maximum instances */
|
||||
sizeof(RPCSS_NP_REPLY), /* output buffer size */
|
||||
sizeof(RPCSS_NP_MESSAGE), /* input buffer size */
|
||||
2000, /* time-out interval */
|
||||
NULL /* SD */
|
||||
);
|
||||
|
||||
if (np_server_end == INVALID_HANDLE_VALUE) {
|
||||
WINE_ERR("Failed to recreate named pipe!\n");
|
||||
/* not sure what to do? */
|
||||
assert(FALSE);
|
||||
}
|
||||
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
WINE_ERR("Uh oh. Couldn't leave master mutex. Expect deadlock.\n");
|
||||
}
|
||||
} else {
|
||||
WINE_ERR("Failed to spawn handler thread!\n");
|
||||
DisconnectNamedPipe(np_server_end);
|
||||
InterlockedDecrement(&srv_thread_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
WINE_TRACE("Server thread shutdown.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HANDLE RPCSS_NPConnect(void)
|
||||
{
|
||||
HANDLE the_pipe;
|
||||
DWORD dwmode, wait_result;
|
||||
HANDLE master_mutex = RPCSS_GetMasterMutex();
|
||||
|
||||
WINE_TRACE("\n");
|
||||
|
||||
while (TRUE) {
|
||||
|
||||
wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT);
|
||||
switch (wait_result) {
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT:
|
||||
default:
|
||||
WINE_ERR("This should never happen: couldn't enter mutex.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to open the client side of the named pipe. */
|
||||
the_pipe = CreateFileA(
|
||||
NAME_RPCSS_NAMED_PIPE, /* pipe name */
|
||||
GENERIC_READ | GENERIC_WRITE, /* r/w access */
|
||||
0, /* no sharing */
|
||||
NULL, /* no security attributes */
|
||||
OPEN_EXISTING, /* open an existing pipe */
|
||||
0, /* default attributes */
|
||||
NULL /* no template file */
|
||||
);
|
||||
|
||||
if (the_pipe != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
if (GetLastError() != ERROR_PIPE_BUSY) {
|
||||
WINE_WARN("Unable to open named pipe %s (assuming unavailable).\n",
|
||||
wine_dbgstr_a(NAME_RPCSS_NAMED_PIPE));
|
||||
break;
|
||||
}
|
||||
|
||||
WINE_WARN("Named pipe busy (will wait)\n");
|
||||
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
WINE_ERR("Failed to release master mutex. Expect deadlock.\n");
|
||||
|
||||
/* wait for the named pipe. We are only
|
||||
willing to wait only 5 seconds. It should be available /very/ soon. */
|
||||
if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT))
|
||||
{
|
||||
WINE_ERR("Named pipe unavailable after waiting. Something is probably wrong.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (the_pipe != INVALID_HANDLE_VALUE) {
|
||||
dwmode = PIPE_READMODE_MESSAGE;
|
||||
/* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */
|
||||
if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL))
|
||||
WINE_WARN("Failed to set pipe handle state\n");
|
||||
}
|
||||
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
WINE_ERR("Uh oh, failed to leave the RPC Master Mutex!\n");
|
||||
|
||||
return the_pipe;
|
||||
}
|
||||
|
||||
static BOOL RPCSS_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, PRPCSS_NP_REPLY reply)
|
||||
{
|
||||
DWORD count;
|
||||
|
||||
WINE_TRACE("(np == %p, msg == %p, reply == %p)\n", np, msg, reply);
|
||||
|
||||
if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) {
|
||||
WINE_ERR("write failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count != sizeof(RPCSS_NP_MESSAGE)) {
|
||||
WINE_ERR("write count mismatch.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) {
|
||||
WINE_ERR("read failed.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count != sizeof(RPCSS_NP_REPLY)) {
|
||||
WINE_ERR("read count mismatch, got %d.\n", count);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* message execution was successful */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL RPCSS_BecomePipeServer(void)
|
||||
{
|
||||
RPCSS_NP_MESSAGE msg;
|
||||
RPCSS_NP_REPLY reply;
|
||||
BOOL rslt = TRUE;
|
||||
HANDLE client_handle, hthread, master_mutex = RPCSS_GetMasterMutex();
|
||||
DWORD threadid, wait_result;
|
||||
|
||||
WINE_TRACE("\n");
|
||||
|
||||
wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT);
|
||||
|
||||
switch (wait_result) {
|
||||
case WAIT_ABANDONED: /* ? */
|
||||
case WAIT_OBJECT_0:
|
||||
/* we have ownership */
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
case WAIT_TIMEOUT:
|
||||
default:
|
||||
WINE_ERR("Couldn't enter master mutex.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* now we have the master mutex. during this time we will
|
||||
*
|
||||
* o check if an rpcss already listens on the pipe. If so,
|
||||
* we will tell it we were invoked, which will cause the
|
||||
* other end to update its timeouts. After, we just return
|
||||
* false.
|
||||
*
|
||||
* o otherwise, we establish the pipe for ourselves and get
|
||||
* ready to listen on it
|
||||
*/
|
||||
|
||||
if ((client_handle = RPCSS_NPConnect()) != INVALID_HANDLE_VALUE) {
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RANMSG;
|
||||
msg.message.ranmsg.timeout = 1000;
|
||||
msg.vardata_payload_size = 0;
|
||||
if (!RPCSS_SendReceiveNPMsg(client_handle, &msg, &reply))
|
||||
WINE_ERR("Something is amiss: RPC_SendReceive failed.\n");
|
||||
CloseHandle(client_handle);
|
||||
rslt = FALSE;
|
||||
}
|
||||
if (rslt) {
|
||||
np_server_work_event = CreateEventA(NULL, FALSE, FALSE, "RpcNpServerWorkEvent");
|
||||
if (np_server_work_event == NULL) {
|
||||
/* dunno what we can do then */
|
||||
WINE_ERR("Unable to create the np_server_work_event\n");
|
||||
assert(FALSE);
|
||||
}
|
||||
InitializeCriticalSection(&np_server_cs);
|
||||
|
||||
np_server_end = CreateNamedPipe(
|
||||
NAME_RPCSS_NAMED_PIPE, /* pipe name */
|
||||
PIPE_ACCESS_DUPLEX, /* pipe open mode */
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, /* pipe-specific modes */
|
||||
PIPE_UNLIMITED_INSTANCES, /* maximum number of instances */
|
||||
sizeof(RPCSS_NP_REPLY), /* output buffer size */
|
||||
sizeof(RPCSS_NP_MESSAGE), /* input buffer size */
|
||||
2000, /* time-out interval */
|
||||
NULL /* SD */
|
||||
);
|
||||
|
||||
if (np_server_end == INVALID_HANDLE_VALUE) {
|
||||
WINE_ERR("Failed to create named pipe!\n");
|
||||
DeleteCriticalSection(&np_server_cs);
|
||||
if (!CloseHandle(np_server_work_event)) /* we will leak the handle... */
|
||||
WINE_WARN("Failed to close np_server_work_event handle!\n");
|
||||
np_server_work_event = NULL;
|
||||
np_server_end = NULL;
|
||||
rslt = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
server_live = rslt;
|
||||
|
||||
if (rslt) {
|
||||
/* OK, now spawn the (single) server thread */
|
||||
hthread = CreateThread(
|
||||
NULL, /* no security attribute */
|
||||
0, /* default stack size */
|
||||
NPMainWorkThread,
|
||||
NULL, /* thread parameter */
|
||||
0, /* not suspended */
|
||||
&threadid /* returns thread ID (not used) */
|
||||
);
|
||||
if (hthread) {
|
||||
WINE_TRACE("Created server thread.\n");
|
||||
CloseHandle(hthread);
|
||||
} else {
|
||||
WINE_ERR("Serious error: unable to create server thread!\n");
|
||||
if (!CloseHandle(np_server_work_event)) /* we will leak the handle... */
|
||||
WINE_WARN("Failed to close np_server_work_event handle!\n");
|
||||
if (!CloseHandle(np_server_end)) /* we will leak the handle... */
|
||||
WINE_WARN("Unable to close named pipe handle!\n");
|
||||
DeleteCriticalSection(&np_server_cs);
|
||||
np_server_end = NULL;
|
||||
np_server_work_event = NULL;
|
||||
rslt = FALSE;
|
||||
server_live = FALSE;
|
||||
}
|
||||
}
|
||||
if (!ReleaseMutex(master_mutex))
|
||||
WINE_ERR("Unable to leave master mutex!??\n");
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
BOOL RPCSS_NPDoWork(HANDLE exit_handle)
|
||||
{
|
||||
HANDLE handles[2];
|
||||
DWORD waitresult;
|
||||
|
||||
handles[0] = np_server_work_event;
|
||||
handles[1] = exit_handle;
|
||||
waitresult = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
|
||||
if (waitresult == WAIT_OBJECT_0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -21,28 +21,6 @@
|
|||
#ifndef __WINE_RPCSS_H
|
||||
#define __WINE_RPCSS_H
|
||||
|
||||
#include "wine/rpcss_shared.h"
|
||||
#include "windows.h"
|
||||
|
||||
/* in seconds */
|
||||
#define RPCSS_DEFAULT_MAX_LAZY_TIMEOUT 30
|
||||
|
||||
/* rpcss_main.c */
|
||||
HANDLE RPCSS_GetMasterMutex(void);
|
||||
|
||||
/* epmap_server.c */
|
||||
BOOL RPCSS_EpmapEmpty(void);
|
||||
BOOL RPCSS_NPDoWork(HANDLE exit_event);
|
||||
void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count,
|
||||
int binding_count, int no_replace, char *vardata, long vardata_size);
|
||||
void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count,
|
||||
int binding_count, char *vardata, long vardata_size);
|
||||
void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object,
|
||||
char *protseq, char *rslt_ep);
|
||||
|
||||
/* named_pipe_kludge.c */
|
||||
BOOL RPCSS_BecomePipeServer(void);
|
||||
BOOL RPCSS_UnBecomePipeServer(void);
|
||||
LONG RPCSS_SrvThreadCount(void);
|
||||
|
||||
#endif /* __WINE_RPCSS_H */
|
||||
|
|
|
@ -58,21 +58,10 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
static HANDLE master_mutex;
|
||||
static HANDLE exit_event;
|
||||
|
||||
extern HANDLE __wine_make_process_system(void);
|
||||
|
||||
HANDLE RPCSS_GetMasterMutex(void)
|
||||
{
|
||||
return master_mutex;
|
||||
}
|
||||
|
||||
static BOOL RPCSS_work(HANDLE exit_event)
|
||||
{
|
||||
return RPCSS_NPDoWork(exit_event);
|
||||
}
|
||||
|
||||
static BOOL RPCSS_Initialize(void)
|
||||
{
|
||||
static unsigned short irot_protseq[] = IROT_PROTSEQ;
|
||||
|
@ -83,21 +72,6 @@ static BOOL RPCSS_Initialize(void)
|
|||
|
||||
WINE_TRACE("\n");
|
||||
|
||||
master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);
|
||||
if (!master_mutex) {
|
||||
WINE_ERR("Failed to create master mutex\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!RPCSS_BecomePipeServer()) {
|
||||
WINE_WARN("Server already running: exiting.\n");
|
||||
|
||||
CloseHandle(master_mutex);
|
||||
master_mutex = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = RpcServerRegisterIf(epm_v3_0_s_ifspec, NULL, NULL);
|
||||
if (status != RPC_S_OK)
|
||||
return status;
|
||||
|
@ -136,14 +110,6 @@ fail:
|
|||
aren't ready to terminate */
|
||||
static BOOL RPCSS_Shutdown(void)
|
||||
{
|
||||
if (!RPCSS_UnBecomePipeServer())
|
||||
return FALSE;
|
||||
|
||||
if (!CloseHandle(master_mutex))
|
||||
WINE_WARN("Failed to release master mutex\n");
|
||||
|
||||
master_mutex = NULL;
|
||||
|
||||
RpcMgmtStopServerListening(NULL);
|
||||
RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE);
|
||||
RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE);
|
||||
|
@ -153,24 +119,16 @@ static BOOL RPCSS_Shutdown(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void RPCSS_MainLoop(void)
|
||||
{
|
||||
WINE_TRACE("\n");
|
||||
|
||||
while ( RPCSS_work(exit_event) )
|
||||
;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
/*
|
||||
* We are invoked as a standard executable; we act in a
|
||||
* "lazy" manner. We open up our pipe, and hang around until we all
|
||||
* user processes exit, and then silently terminate.
|
||||
* "lazy" manner. We register our interfaces and endpoints, and hang around
|
||||
* until we all user processes exit, and then silently terminate.
|
||||
*/
|
||||
|
||||
if (RPCSS_Initialize()) {
|
||||
RPCSS_MainLoop();
|
||||
WaitForSingleObject(exit_event, INFINITE);
|
||||
RPCSS_Shutdown();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue