| /* |
| * 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; |
| } |