/*
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <assert.h>
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "ntstatus.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 = NULL;
  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));
      the_pipe = NULL;
      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 only 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");
      return NULL;
    }

  }

  if (the_pipe) {
    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 %ld, expected %u.\n", count, sizeof(RPCSS_NP_REPLY));
    return FALSE;
  }

  /* message execution was successful */
  return TRUE;
}
