RPC Merge (A_PL2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Starting to get dicey, here.  First, I am missing rpc_binding.h,
so for the moment, I've made a "pretend" one which allows things
to compile, but is probably wrong.  Either way, I'd appreciate
it if those in the know could take a look at this and make sure
I'm doing the right stuff overall.

Also, I'm not sure if I've entered the territory that Alexandre
isn't happy with.  I wasn't sure if disapproving of "the server parts"
means the wineserver parts 
(http://www.winehq.com/hypermail/wine-patches/2002/06/0102.html)
or the RPC Server parts, which contain the named-pipes hack.

Anyhow, here it is.  I haven't tested any of this stuff yet, and frankly,
I wouldn't expect it to work very well until I get the real rpc_binding.h.

BTW: There may be additional header files missing in Jürgen's
patch; I haven't checked yet.  If there are, I'll probably start
needing those as well, sooner or later.

Relative to A_PL1.

From Jürgen Schmied's RPC patches.
Minor changes may exist between this and the original 
patch but it's intended to be basically the same stuff.

LICENSE: X11

CHANGELOG:

* dlls/rpcrt4: rpcrt4.spec, rpcrt4_main.c,
  rpc_binding.c (new),  rpc_binding.h (new), Makefile.in: 
  Ove Kaaven <ovek@transgaming.com>
- implement RpcBindingInqObject, RpcBindingSetObject,
  RpcBindingVectorFree, RpcBindingToStringBindingA/W,
  RpcBindingFromStringBindingA/W, RpcStringBindingParseA/W, 
  I_RpcBindingSetAsync, RpcStringBindingComposeA/W,
  RpcBindingFree, UuidToStringW, and associated junk.

-- 
gmt

"If ye love wealth better than liberty, the tranquility
of servitude better than the animating contest of freedom,
go home from us in peace. We ask not your counsels or your
arms. Crouch down and lick the hands, which feed you. May
your chains set lightly upon you, and may posterity forget
that ye were our countrymen." 

-Samuel Adams
--- /dev/null	1969-12-31 18:00:00.000000000 -0600
+++ dlls/rpcrt4/rpc_binding.h	2002-10-04 09:15:23.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * 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
+ */
+
+/*
+ * Warning: this is not the real header file, just
+ * a placeholder until the real deal is available.
+ * I have no idea if this stuff is correct -gmt
+ */
+
+typedef struct {
+  long refs;
+  BOOL server;
+  LPSTR Protseq;
+  LPSTR NetworkAddr;
+  LPSTR Endpoint;
+  INT conn;
+  OVERLAPPED ovl;
+  RPC_BLOCKING_FN BlockingFn;
+  unsigned long ServerTid;
+  UUID ObjectUuid;
+} RpcBinding;
+
+/* Shared internal functions */
+LPWSTR RPCRT4_strdupWA(LPSTR src, INT slen);
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding);
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding);
--- /dev/null	1969-12-31 18:00:00.000000000 -0600
+++ dlls/rpcrt4/rpc_binding.c	2002-10-04 09:12:52.000000000 -0500
@@ -0,0 +1,743 @@
+/*
+ * RPC binding API
+ *
+ * Copyright 2001 Ove K�en, TransGaming Technologies
+ *
+ * TODO:
+ *  - a whole lot
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "wine/unicode.h"
+
+#include "rpc.h"
+
+#include "wine/debug.h"
+
+#include "rpc_binding.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+LPSTR RPCRT4_strdupAA(LPSTR src, INT slen)
+{
+  DWORD len;
+  LPSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlen(src);
+  len = slen;
+  s = HeapAlloc(GetProcessHeap(), 0, len+1);
+  memcpy(s, src, len);
+  s[len] = 0;
+  return s;
+}
+
+LPSTR RPCRT4_strdupAW(LPWSTR src, INT slen)
+{
+  DWORD len;
+  LPSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlenW(src);
+  len = WideCharToMultiByte(CP_ACP, 0, src, slen, NULL, 0, NULL, NULL);
+  s = HeapAlloc(GetProcessHeap(), 0, len+1);
+  WideCharToMultiByte(CP_ACP, 0, src, slen, s, len, NULL, NULL);
+  s[len] = 0;
+  return s;
+}
+
+LPWSTR RPCRT4_strdupWA(LPSTR src, INT slen)
+{
+  DWORD len;
+  LPWSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlen(src);
+  len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
+  s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
+  MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
+  s[len] = 0;
+  return s;
+}
+
+LPWSTR RPCRT4_strdupWW(LPWSTR src, INT slen)
+{
+  DWORD len;
+  LPWSTR s;
+  if (!src) return NULL;
+  if (slen == -1) slen = strlenW(src);
+  len = slen;
+  s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
+  memcpy(s, src, len*sizeof(WCHAR));
+  s[len] = 0;
+  return s;
+}
+
+void RPCRT4_strfree(LPSTR src)
+{
+  if (src) HeapFree(GetProcessHeap(), 0, src);
+}
+
+RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq)
+{
+  RpcBinding* NewBinding;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = server;
+  NewBinding->Protseq = RPCRT4_strdupAA(Protseq, strlen(Protseq)); /* FIXME: RPCRT4_strdupA */
+
+  TRACE("binding: %p\n", NewBinding);
+  *Binding = NewBinding;
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq)
+{
+  RpcBinding* NewBinding;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = server;
+  NewBinding->Protseq = RPCRT4_strdupAW(Protseq, strlenW(Protseq)); /* FIXME: RPCRT4_strdupW */
+
+  TRACE("binding: %p\n", NewBinding);
+  *Binding = NewBinding;
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr,  LPSTR Endpoint,  LPSTR NetworkOptions)
+{
+  RPCRT4_strfree(Binding->NetworkAddr);
+  Binding->NetworkAddr = RPCRT4_strdupAA(NetworkAddr, strlen(NetworkAddr)); /* FIXME: RPCRT4_strdupA */
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdupAA(Endpoint, strlen(Endpoint)); /* FIXME: RPCRT4_strdupA */
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions)
+{
+  RPCRT4_strfree(Binding->NetworkAddr);
+  Binding->NetworkAddr = RPCRT4_strdupAW(NetworkAddr, strlenW(NetworkAddr)); /* FIXME: RPCRT4_strdupW */
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdupAW(Endpoint, strlenW(Endpoint)); /* FIXME: RPCRT4_strdupW */
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint)
+{
+  RPCRT4_strfree(Binding->Endpoint);
+  Binding->Endpoint = RPCRT4_strdupAA(Endpoint, strlen(Endpoint)); /* FIXME: RPCRT4_strdup */
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
+{
+  if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID));
+  else UuidCreateNil(&Binding->ObjectUuid);
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding)
+{
+  RpcBinding* NewBinding;
+
+  NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
+  NewBinding->refs = 1;
+  NewBinding->server = OldBinding->server;
+  NewBinding->Protseq = RPCRT4_strdupAA(OldBinding->Protseq, strlen(OldBinding->Protseq)); /* FIXME: RPCRT4_strdup */
+  NewBinding->NetworkAddr = RPCRT4_strdupAA(OldBinding->NetworkAddr, strlen(OldBinding->NetworkAddr)); /* FIXME: RPCRT4_strdup */
+  NewBinding->Endpoint = RPCRT4_strdupAA(OldBinding->Endpoint, strlen(OldBinding->Endpoint)); /* FIXME: RPCRT4_strdup */
+  /* because of the way named pipes work, we'll transfer the connected pipe
+   * to the child, then reopen the server binding to continue listening */
+  NewBinding->conn = OldBinding->conn;
+  NewBinding->ovl = OldBinding->ovl;
+  OldBinding->conn = 0;
+  memset(&OldBinding->ovl, 0, sizeof(OldBinding->ovl));
+  *Binding = NewBinding;
+  RPCRT4_OpenBinding(OldBinding);
+
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding)
+{
+  InterlockedIncrement(&OldBinding->refs);
+  *Binding = OldBinding;
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
+{
+  if (InterlockedDecrement(&Binding->refs))
+    return RPC_S_OK;
+
+  TRACE("binding: %p\n", Binding);
+  RPCRT4_CloseBinding(Binding);
+  RPCRT4_strfree(Binding->Endpoint);
+  RPCRT4_strfree(Binding->NetworkAddr);
+  RPCRT4_strfree(Binding->Protseq);
+  HeapFree(GetProcessHeap(), 0, Binding);
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding)
+{
+  if (!Binding->conn) {
+    if (Binding->server) { /* server */
+      /* protseq=ncalrpc: supposed to use NT LPC ports,
+       * but we'll implement it with named pipes for now */
+      if (strcmp(Binding->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+       TRACE("listening on %s\n", pname);
+        Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Binding->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Binding->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+       TRACE("listening on %s\n", pname);
+        Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                         0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
+        HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+        if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) {
+          DWORD err = GetLastError();
+          if (err == ERROR_PIPE_CONNECTED) {
+            SetEvent(Binding->ovl.hEvent);
+            return RPC_S_OK;
+          }
+          return err;
+        }
+      }
+      else {
+       ERR("protseq %s not supported\n", Binding->Protseq);
+       return RPC_S_PROTSEQ_NOT_SUPPORTED;
+      }
+    }
+    else { /* client */
+      /* protseq=ncalrpc: supposed to use NT LPC ports,
+       * but we'll implement it with named pipes for now */
+      if (strcmp(Binding->Protseq, "ncalrpc") == 0) {
+        static LPSTR prefix = "\\\\.\\pipe\\lrpc\\";
+        LPSTR pname;
+       HANDLE conn;
+       DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+       TRACE("connecting to %s\n", pname);
+       while (TRUE) {
+         if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
+           conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                              OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+           if (conn != INVALID_HANDLE_VALUE) break;
+           err = GetLastError();
+           if (err == ERROR_PIPE_BUSY) continue;
+           TRACE("connection failed, error=%lx\n", err);
+           HeapFree(GetProcessHeap(), 0, pname);
+           return err;
+         }
+         else {
+           err = GetLastError();
+           TRACE("connection failed, error=%lx\n", err);
+           HeapFree(GetProcessHeap(), 0, pname);
+           return err;
+         }
+       }
+
+       /* success */
+       HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+       Binding->conn = conn;
+      }
+      /* protseq=ncacn_np: named pipes */
+      else if (strcmp(Binding->Protseq, "ncacn_np") == 0) {
+        static LPSTR prefix = "\\\\.";
+        LPSTR pname;
+       HANDLE conn;
+       DWORD err;
+
+        pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1);
+        strcat(strcpy(pname, prefix), Binding->Endpoint);
+       TRACE("connecting to %s\n", pname);
+       conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                          OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+       if (conn == INVALID_HANDLE_VALUE) {
+         err = GetLastError();
+         /* we don't need to handle ERROR_PIPE_BUSY here,
+          * the doc says that it is returned to the app */
+         TRACE("connection failed, error=%lx\n", err);
+         HeapFree(GetProcessHeap(), 0, pname);
+         return err;
+       }
+
+       /* success */
+       HeapFree(GetProcessHeap(), 0, pname);
+        memset(&Binding->ovl, 0, sizeof(Binding->ovl));
+        Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+       Binding->conn = conn;
+      }
+      else {
+       ERR("protseq %s not supported\n", Binding->Protseq);
+       return RPC_S_PROTSEQ_NOT_SUPPORTED;
+      }
+    }
+  }
+  return RPC_S_OK;
+}
+
+RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding)
+{
+  if (Binding->conn) {
+    CancelIo(Binding->conn);
+    CloseHandle(Binding->conn);
+    Binding->conn = 0;
+  }
+  if (Binding->ovl.hEvent) {
+    CloseHandle(Binding->ovl.hEvent);
+    Binding->ovl.hEvent = 0;
+  }
+  return RPC_S_OK;
+}
+
+/* utility functions for string composing and parsing */
+static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src)
+{
+  unsigned len = strlen(src);
+  memcpy(data, src, len*sizeof(CHAR));
+  return len;
+}
+
+static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src)
+{
+  unsigned len = strlenW(src);
+  memcpy(data, src, len*sizeof(WCHAR));
+  return len;
+}
+
+static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
+{
+  DWORD len = strlen(dst), slen = strlen(src);
+  LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
+  if (!ndst) HeapFree(GetProcessHeap(), 0, dst);
+  ndst[len] = ',';
+  memcpy(ndst+len+1, src, slen*sizeof(CHAR));
+  ndst[len+slen+1] = 0;
+  return ndst;
+}
+
+static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
+{
+  DWORD len = strlenW(dst), slen = strlenW(src);
+  LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
+  if (!ndst) HeapFree(GetProcessHeap(), 0, dst);
+  ndst[len] = ',';
+  memcpy(ndst+len+1, src, slen*sizeof(WCHAR));
+  ndst[len+slen+1] = 0;
+  return ndst;
+}
+
+#define RPC_STRING_BINDING_COMPOSE(char_t,strlen_t,strcopy_t) \
+  if (ObjUuid && *ObjUuid) len += strlen_t(ObjUuid) + 1; \
+  if (Protseq && *Protseq) len += strlen_t(Protseq) + 1; \
+  if (NetworkAddr && *NetworkAddr) len += strlen_t(NetworkAddr); \
+  if (Endpoint && *Endpoint) len += strlen_t(Endpoint) + 2; \
+  if (Options && *Options) len += strlen_t(Options) + 2; \
+  \
+  data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(char_t)); \
+  *StringBinding = data; \
+  \
+  if (ObjUuid && *ObjUuid) { \
+    data += strcopy_t(data, ObjUuid); \
+    *data++ = '@'; \
+  } \
+  if (Protseq && *Protseq) { \
+    data += strcopy_t(data, Protseq); \
+    *data++ = ':'; \
+  } \
+  if (NetworkAddr && *NetworkAddr) { \
+    data += strcopy_t(data, NetworkAddr); \
+  } \
+  if ((Endpoint && *Endpoint) || \
+      (Options && *Options)) { \
+    *data++ = '['; \
+    if (Endpoint && *Endpoint) { \
+      data += strcopy_t(data, Endpoint); \
+      if (Options && *Options) *data++ = ','; \
+    } \
+    if (Options && *Options) { \
+      data += strcopy_t(data, Options); \
+    } \
+    *data++ = ']'; \
+  } \
+  *data = 0;
+
+/***********************************************************************
+ *             RpcStringBindingComposeA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq,
+                                           LPSTR NetworkAddr, LPSTR Endpoint,
+                                           LPSTR Options, LPSTR* StringBinding )
+{
+  DWORD len = 1;
+  LPSTR data;
+
+  TRACE( "(%s,%s,%s,%s,%s,%p)\n",
+        debugstr_a( ObjUuid ), debugstr_a( Protseq ),
+        debugstr_a( NetworkAddr ), debugstr_a( Endpoint ),
+        debugstr_a( Options ), StringBinding );
+
+  RPC_STRING_BINDING_COMPOSE(CHAR,strlen,RPCRT4_strcopyA)
+
+  return RPC_S_OK;
+}
+
+/***********************************************************************
+ *             RpcStringBindingComposeW (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq,
+                                           LPWSTR NetworkAddr, LPWSTR Endpoint,
+                                           LPWSTR Options, LPWSTR* StringBinding )
+{
+  DWORD len = 1;
+  LPWSTR data;
+
+  TRACE("(%s,%s,%s,%s,%s,%p)\n",
+       debugstr_w( ObjUuid ), debugstr_w( Protseq ),
+       debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
+       debugstr_w( Options ), StringBinding);
+
+  RPC_STRING_BINDING_COMPOSE(WCHAR,strlenW,RPCRT4_strcopyW)
+
+  return RPC_S_OK;
+}
+
+#define RPC_STRING_BINDING_PARSE(char_t,strlen_t,strchr_t,strncmp_t,strdup_t,strconc_t) \
+  if (ObjUuid) *ObjUuid = NULL; \
+  if (Protseq) *Protseq = NULL; \
+  if (NetworkAddr) *NetworkAddr = NULL; \
+  if (Endpoint) *Endpoint = NULL; \
+  if (Options) *Options = NULL; \
+  \
+  data = StringBinding; \
+  \
+  next = strchr_t(data, '@'); \
+  if (next) { \
+    if (ObjUuid) *ObjUuid = strdup_t(data, next - data); \
+    data = next+1; \
+  } \
+  \
+  next = strchr_t(data, ':'); \
+  if (next) { \
+    if (Protseq) *Protseq = strdup_t(data, next - data); \
+    data = next+1; \
+  } \
+  \
+  next = strchr_t(data, '['); \
+  if (next) { \
+    char_t *close, *opt; \
+    \
+    if (NetworkAddr) *NetworkAddr = strdup_t(data, next - data); \
+    data = next+1; \
+    close = strchr_t(data, ']'); \
+    if (!close) goto fail; \
+    \
+    /* tokenize options */ \
+    while (data < close) { \
+      next = strchr_t(data, ','); \
+      if (!next || next > close) next = close; \
+      /* FIXME: this is kind of inefficient */ \
+      opt = strdup_t(data, next - data); \
+      data = next+1; \
+      \
+      /* parse option */ \
+      next = strchr_t(opt, '='); \
+      if (!next) { \
+       /* not an option, must be an endpoint */ \
+       if (*Endpoint) goto fail; \
+       *Endpoint = opt; \
+      } \
+      else { \
+       if (strncmp_t(opt, ep_opt, strlen_t(ep_opt)) == 0) { \
+         /* endpoint option */ \
+         if (*Endpoint) goto fail; \
+         *Endpoint = strdup_t(next+1, strlen_t(next+1)); \
+         HeapFree(GetProcessHeap(), 0, opt); \
+       } \
+       else { \
+         /* network option */ \
+         if (*Options) { \
+            /* FIXME: this is kind of inefficient */ \
+           *Options = strconc_t(*Options, opt); \
+           HeapFree(GetProcessHeap(), 0, opt); \
+         } \
+         else *Options = opt; \
+       } \
+      } \
+    } \
+    \
+    data = close+1; \
+    if (*data) goto fail; \
+  } \
+  else if (NetworkAddr) *NetworkAddr = strdup_t(data, strlen_t(data)); \
+
+/***********************************************************************
+ *             RpcStringBindingParseA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingParseA( LPSTR StringBinding, LPSTR *ObjUuid,
+                                         LPSTR *Protseq, LPSTR *NetworkAddr,
+                                         LPSTR *Endpoint, LPSTR *Options)
+{
+  CHAR *data, *next;
+  static CHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
+
+  TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a(StringBinding),
+       ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
+
+  RPC_STRING_BINDING_PARSE(CHAR,strlen,strchr,strncmp,RPCRT4_strdupAA,RPCRT4_strconcatA)
+
+  return RPC_S_OK;
+fail:
+  if (ObjUuid) RpcStringFreeA(ObjUuid);
+  if (Protseq) RpcStringFreeA(Protseq);
+  if (NetworkAddr) RpcStringFreeA(NetworkAddr);
+  if (Endpoint) RpcStringFreeA(Endpoint);
+  if (Options) RpcStringFreeA(Options);
+  return RPC_S_INVALID_STRING_BINDING;
+}
+
+/***********************************************************************
+ *             RpcStringBindingParseW (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcStringBindingParseW( LPWSTR StringBinding, LPWSTR *ObjUuid,
+                                         LPWSTR *Protseq, LPWSTR *NetworkAddr,
+                                         LPWSTR *Endpoint, LPWSTR *Options)
+{
+  WCHAR *data, *next;
+  static WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
+
+  TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
+       ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
+
+  RPC_STRING_BINDING_PARSE(WCHAR,strlenW,strchrW,strncmpW,RPCRT4_strdupWW,RPCRT4_strconcatW)
+
+  return RPC_S_OK;
+fail:
+  if (ObjUuid) RpcStringFreeW(ObjUuid);
+  if (Protseq) RpcStringFreeW(Protseq);
+  if (NetworkAddr) RpcStringFreeW(NetworkAddr);
+  if (Endpoint) RpcStringFreeW(Endpoint);
+  if (Options) RpcStringFreeW(Options);
+  return RPC_S_INVALID_STRING_BINDING;
+}
+
+/***********************************************************************
+ *             RpcBindingFree (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
+{
+  RPC_STATUS status;
+  TRACE("(%p) = %p\n", Binding, *Binding);
+  status = RPCRT4_DestroyBinding(*Binding);
+  if (status == RPC_S_OK) *Binding = 0;
+  return status;
+}
+  
+/***********************************************************************
+ *             RpcBindingVectorFree (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
+{
+  RPC_STATUS status;
+  unsigned long c;
+
+  TRACE("(%p)\n", BindingVector);
+  for (c=0; c<(*BindingVector)->Count; c++) {
+    status = RpcBindingFree(&(*BindingVector)->BindingH[c]);
+  }
+  HeapFree(GetProcessHeap(), 0, *BindingVector);
+  *BindingVector = NULL;
+  return RPC_S_OK;
+}
+  
+/***********************************************************************
+ *             RpcBindingInqObject (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
+{
+  RpcBinding* bind = (RpcBinding*)Binding;
+
+  TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
+  memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID));
+  return RPC_S_OK;
+}
+  
+/***********************************************************************
+ *             RpcBindingSetObject (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
+{
+  RpcBinding* bind = (RpcBinding*)Binding;
+
+  TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
+  if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
+  return RPCRT4_SetBindingObject(Binding, ObjectUuid);
+}
+
+/***********************************************************************
+ *             RpcBindingFromStringBindingA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding )
+{
+  RPC_STATUS ret;
+  RpcBinding* bind = NULL;
+  LPSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
+  UUID Uuid;
+
+  TRACE("(%s,%p)\n", debugstr_a(StringBinding), Binding);
+
+  ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
+                              &NetworkAddr, &Endpoint, &Options);
+  if (ret != RPC_S_OK) return ret;
+
+  ret = UuidFromStringA(ObjectUuid, &Uuid);
+
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_CreateBindingA(&bind, FALSE, Protseq);
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_SetBindingObject(bind, &Uuid);
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_CompleteBindingA(bind, NetworkAddr, Endpoint, Options);
+
+  RpcStringFreeA(&Options);
+  RpcStringFreeA(&Endpoint);
+  RpcStringFreeA(&NetworkAddr);
+  RpcStringFreeA(&Protseq);
+  RpcStringFreeA(&ObjectUuid);
+
+  if (ret == RPC_S_OK) *Binding = (RPC_BINDING_HANDLE)bind;
+  else RPCRT4_DestroyBinding(bind);
+
+  return ret;
+}
+  
+/***********************************************************************
+ *             RpcBindingFromStringBindingW (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
+{
+  RPC_STATUS ret;
+  RpcBinding* bind = NULL;
+  LPWSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
+  UUID Uuid;
+
+  TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
+
+  ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
+                              &NetworkAddr, &Endpoint, &Options);
+  if (ret != RPC_S_OK) return ret;
+
+  ret = UuidFromStringW(ObjectUuid, &Uuid);
+
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_SetBindingObject(bind, &Uuid);
+  if (ret == RPC_S_OK)
+    ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
+
+  RpcStringFreeW(&Options);
+  RpcStringFreeW(&Endpoint);
+  RpcStringFreeW(&NetworkAddr);
+  RpcStringFreeW(&Protseq);
+  RpcStringFreeW(&ObjectUuid);
+
+  if (ret == RPC_S_OK) *Binding = (RPC_BINDING_HANDLE)bind;
+  else RPCRT4_DestroyBinding(bind);
+
+  return ret;
+}
+  
+/***********************************************************************
+ *             RpcBindingToStringBindingA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, LPSTR* StringBinding )
+{
+  RPC_STATUS ret;
+  RpcBinding* bind = (RpcBinding*)Binding;
+  LPSTR ObjectUuid;
+
+  TRACE("(%p,%p)\n", Binding, StringBinding);
+
+  ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
+  if (ret != RPC_S_OK) return ret;
+
+  ret = RpcStringBindingComposeA(ObjectUuid, bind->Protseq, bind->NetworkAddr,
+                                 bind->Endpoint, NULL, StringBinding);
+
+  RpcStringFreeA(&ObjectUuid);
+
+  return ret;
+}
+  
+/***********************************************************************
+ *             RpcBindingToStringBindingW (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, LPWSTR* StringBinding )
+{
+  RPC_STATUS ret;
+  LPSTR str = NULL;
+  TRACE("(%p,%p)\n", Binding, StringBinding);
+  ret = RpcBindingToStringBindingA(Binding, &str);
+  *StringBinding = RPCRT4_strdupWA(str, -1);
+  RpcStringFreeA(&str);
+  return ret;
+}
+  
+/***********************************************************************
+ *             I_RpcBindingSetAsync (RPCRT4.@)
+ * NOTES
+ *  Exists in win9x and winNT, but with different number of arguments
+ *  (9x version has 3 arguments, NT has 2).
+ */
+RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn, unsigned long ServerTid )
+{
+  RpcBinding* bind = (RpcBinding*)Binding;
+
+  TRACE( "(%p,%p,%ld): stub\n", Binding, BlockingFn, ServerTid );
+
+  bind->BlockingFn = BlockingFn;
+  bind->ServerTid = ServerTid;
+
+  return RPC_S_OK;
+}
+
--- dlls/rpcrt4/rpcrt4.spec.A_PL1	2002-10-03 22:10:21.000000000 -0500
+++ dlls/rpcrt4/rpcrt4.spec	2002-10-03 23:58:20.000000000 -0500
@@ -41,7 +41,7 @@
 @ stub RpcBindingInqAuthInfoW
 @ stub RpcBindingInqAuthInfoExA
 @ stub RpcBindingInqAuthInfoExW
-@ stub RpcBindingInqObject
+@ stdcall RpcBindingInqObject(ptr ptr) RpcBindingInqObject
 @ stub RpcBindingInqOption
 @ stub RpcBindingReset
 @ stub RpcBindingServerFromClient
@@ -49,11 +49,11 @@
 @ stub RpcBindingSetAuthInfoW
 @ stub RpcBindingSetAuthInfoExA
 @ stub RpcBindingSetAuthInfoExW
-@ stub RpcBindingSetObject
+@ stdcall RpcBindingSetObject(ptr ptr) RpcBindingSetObject
 @ stub RpcBindingSetOption
-@ stub RpcBindingToStringBindingA
-@ stub RpcBindingToStringBindingW
-@ stub RpcBindingVectorFree
+@ stdcall RpcBindingToStringBindingA(ptr ptr) RpcBindingToStringBindingA
+@ stdcall RpcBindingToStringBindingW(ptr ptr) RpcBindingToStringBindingW
+@ stdcall RpcBindingVectorFree(ptr) RpcBindingVectorFree
 @ stub RpcCancelAsyncCall
 @ stub RpcCancelThread
 @ stub RpcCancelThreadEx
@@ -162,8 +162,8 @@
 @ stub RpcSsSwapClientAllocFree
 @ stdcall RpcStringBindingComposeA(str  str  str  str  str  ptr) RpcStringBindingComposeA
 @ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) RpcStringBindingComposeW
-@ stub RpcStringBindingParseA
-@ stub RpcStringBindingParseW
+@ stdcall RpcStringBindingParseA(str  ptr ptr ptr ptr ptr) RpcStringBindingParseA
+@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) RpcStringBindingParseW
 @ stdcall RpcStringFreeA(ptr) RpcStringFreeA
 @ stdcall RpcStringFreeW(ptr) RpcStringFreeW
 @ stub RpcTestCancel
@@ -181,7 +181,7 @@
 @ stdcall UuidHash(ptr ptr) UuidHash
 @ stdcall UuidIsNil(ptr ptr) UuidIsNil
 @ stdcall UuidToStringA(ptr ptr) UuidToStringA
-@ stub UuidToStringW
+@ stdcall UuidToStringW(ptr ptr) UuidToStringW
 
 @ stub CStdStubBuffer_QueryInterface
 @ stub CStdStubBuffer_AddRef
@@ -427,7 +427,8 @@
 @ stub I_RpcBindingInqWireIdForSnego
 @ stub I_RpcBindingIsClientLocal
 @ stub I_RpcBindingToStaticStringBindingW
-@ stub I_RpcBindingSetAsync # win9x
+@ stdcall I_RpcBindingSetAsync(ptr ptr long) I_RpcBindingSetAsync # win9x
+# NT version of I_RpcBindingSetAsync has 2 arguments, not 3
 @ stub I_RpcClearMutex
 @ stub I_RpcConnectionInqSockBuffSize
 @ stub I_RpcConnectionInqSockBuffSize2
--- dlls/rpcrt4/rpcrt4_main.c.A_PL1	2002-10-03 22:09:17.000000000 -0500
+++ dlls/rpcrt4/rpcrt4_main.c	2002-10-04 07:59:14.000000000 -0500
@@ -60,6 +60,8 @@
 # include <netinet/in.h>
 #endif
 
+#include "rpc_binding.h"
+
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -475,6 +477,31 @@
   return RPC_S_OK;
 }
 
+/*************************************************************************
+ *           UuidToStringW   [RPCRT4.@]
+ *
+ * Converts a UUID to a string.
+ *
+ *  S_OK if successful.
+ *  S_OUT_OF_MEMORY if unsucessful.
+ */
+RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, LPWSTR* StringUuid)
+{
+  char buf[37];
+
+  sprintf(buf, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+               Uuid->Data1, Uuid->Data2, Uuid->Data3,
+               Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2],
+               Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5],
+               Uuid->Data4[6], Uuid->Data4[7] );
+
+  *StringUuid = RPCRT4_strdupWA(buf, -1);
+
+  if(!(*StringUuid))
+    return RPC_S_OUT_OF_MEMORY;
+
+  return RPC_S_OK;
+}
 
 static const BYTE hex2bin[] =
 {
@@ -709,59 +736,6 @@
 }
 
 /***********************************************************************
- *		RpcStringBindingComposeA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcStringBindingComposeA( LPSTR ObjUuid, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint,
-                          LPSTR Options, LPSTR* StringBinding )
-{
-  FIXME( "(%s,%s,%s,%s,%s,%p): stub\n", ObjUuid, Protseq, NetworkAddr, Endpoint, Options, StringBinding );
-  *StringBinding = NULL;
-
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
-
-/***********************************************************************
- *		RpcStringBindingComposeW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcStringBindingComposeW( LPWSTR ObjUuid, LPWSTR Protseq, LPWSTR NetworkAddr, LPWSTR Endpoint,
-                          LPWSTR Options, LPWSTR* StringBinding )
-{
-  FIXME( "(%s,%s,%s,%s,%s,%p): stub\n", debugstr_w( ObjUuid ), debugstr_w( Protseq ), debugstr_w( NetworkAddr ),
-                                        debugstr_w( Endpoint ), debugstr_w( Options ), StringBinding );
-  *StringBinding = NULL;
-
-  return RPC_S_INVALID_STRING_UUID; /* Failure */
-}
-
-/***********************************************************************
- *		RpcBindingFree (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFree(RPC_BINDING_HANDLE* Binding)
-{
-  FIXME("(%p): stub\n", Binding);
-  return RPC_S_OK;
-}
-/***********************************************************************
- *		RpcBindingFromStringBindingA (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFromStringBindingA( LPSTR StringBinding, RPC_BINDING_HANDLE* Binding )
-{
-  FIXME( "(%s,%p): stub\n", StringBinding, Binding );
-
-  return RPC_S_INVALID_STRING_BINDING; /* As good as any failure code */
-}
-
-/***********************************************************************
- *		RpcBindingFromStringBindingW (RPCRT4.@)
- */
-RPC_STATUS WINAPI RpcBindingFromStringBindingW( LPWSTR StringBinding, RPC_BINDING_HANDLE* Binding )
-{
-  FIXME( "(%s,%p): stub\n", debugstr_w( StringBinding ), Binding );
-
-  return RPC_S_INVALID_STRING_BINDING; /* As good as any failure code */
-}
-
-/***********************************************************************
  *		NdrDllCanUnloadNow (RPCRT4.@)
  */
 HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
--- dlls/rpcrt4/Makefile.in.A_PL1	2002-10-04 09:25:14.000000000 -0500
+++ dlls/rpcrt4/Makefile.in	2002-10-03 23:26:40.000000000 -0500
@@ -10,6 +10,7 @@
 SYMBOLFILE = $(MODULE).tmp.o
 
 C_SRCS = \
+        rpc_binding.c \
 	rpcrt4_main.c
 
 @MAKE_DLL_RULES@

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux