-/*\r
- * RPC endpoint mapper\r
- *\r
- * Copyright 2002 Greg Turner\r
- * Copyright 2001 Ove Kåven, TransGaming Technologies\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- *\r
- * TODO:\r
- * - actually do things right\r
- */\r
-\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winerror.h"\r
-#include "winreg.h"\r
-\r
-#include "rpc.h"\r
-\r
-#include "wine/debug.h"\r
-\r
-#include "rpc_binding.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
-\r
-/* The "real" RPC portmapper endpoints that I know of are:\r
- *\r
- * ncadg_ip_udp: 135\r
- * ncacn_ip_tcp: 135\r
- * ncacn_np: \\pipe\epmapper (?)\r
- * ncalrpc: epmapper\r
- *\r
- * If the user's machine ran a DCE RPC daemon, it would\r
- * probably be possible to connect to it, but there are many\r
- * reasons not to, like:\r
- * - the user probably does *not* run one, and probably\r
- * shouldn't be forced to run one just for local COM\r
- * - very few Unix systems use DCE RPC... if they run a RPC\r
- * daemon at all, it's usually Sun RPC\r
- * - DCE RPC registrations are persistent and saved on disk,\r
- * while MS-RPC registrations are documented as non-persistent\r
- * and stored only in RAM, and auto-destroyed when the process\r
- * dies (something DCE RPC can't do)\r
- *\r
- * Of course, if the user *did* want to run a DCE RPC daemon anyway,\r
- * there would be interoperability advantages, like the possibility\r
- * of running a fully functional DCOM server using Wine...\r
- */\r
-\r
-/***********************************************************************\r
- * RpcEpRegisterA (RPCRT4.@)\r
- */\r
-RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,\r
- UUID_VECTOR *UuidVector, unsigned char *Annotation )\r
-{\r
- RPCSS_NP_MESSAGE msg;\r
- RPCSS_NP_REPLY reply;\r
- char *vardata_payload, *vp;\r
- PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;\r
- unsigned long c;\r
- RPC_STATUS rslt = RPC_S_OK;\r
-\r
- TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a(Annotation));\r
- TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
- for (c=0; c<BindingVector->Count; c++) {\r
- RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
- TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));\r
- TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));\r
- }\r
- if (UuidVector) {\r
- for (c=0; c<UuidVector->Count; c++)\r
- TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));\r
- }\r
-\r
- /* FIXME: Do something with annotation. */\r
-\r
- /* construct the message to rpcss */\r
- msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG;\r
- msg.message.registerepmsg.iface = If->InterfaceId;\r
- msg.message.registerepmsg.no_replace = 0;\r
-\r
- msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;\r
- msg.message.registerepmsg.binding_count = BindingVector->Count;\r
-\r
- /* calculate vardata payload size */\r
- msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID);\r
- for (c=0; c < msg.message.registerepmsg.binding_count; c++) {\r
- RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);\r
- msg.vardata_payload_size += strlen(bind->Protseq) + 1;\r
- msg.vardata_payload_size += strlen(bind->Endpoint) + 1;\r
- }\r
-\r
- /* allocate the payload buffer */\r
- vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);\r
- if (!vardata_payload)\r
- return RPC_S_OUT_OF_MEMORY;\r
-\r
- /* populate the payload data */\r
- for (c=0; c < msg.message.registerepmsg.object_count; c++) {\r
- CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));\r
- vp += sizeof(UUID);\r
- }\r
-\r
- for (c=0; c < msg.message.registerepmsg.binding_count; c++) {\r
- RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
- unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;\r
- CopyMemory(vp, bind->Protseq, pslen);\r
- vp += pslen;\r
- CopyMemory(vp, bind->Endpoint, eplen);\r
- vp += eplen;\r
- }\r
-\r
- /* send our request */\r
- if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))\r
- rslt = RPC_S_OUT_OF_MEMORY;\r
-\r
- /* free the payload buffer */\r
- LocalFree(vardata_payload);\r
-\r
- return rslt;\r
-}\r
-\r
-/***********************************************************************\r
- * RpcEpUnregister (RPCRT4.@)\r
- */\r
-RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,\r
- UUID_VECTOR *UuidVector )\r
-{\r
- RPCSS_NP_MESSAGE msg;\r
- RPCSS_NP_REPLY reply;\r
- char *vardata_payload, *vp;\r
- PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;\r
- unsigned long c;\r
- RPC_STATUS rslt = RPC_S_OK;\r
-\r
- TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);\r
- TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
- for (c=0; c<BindingVector->Count; c++) {\r
- RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
- TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));\r
- TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));\r
- }\r
- if (UuidVector) {\r
- for (c=0; c<UuidVector->Count; c++)\r
- TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));\r
- }\r
-\r
- /* construct the message to rpcss */\r
- msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG;\r
- msg.message.unregisterepmsg.iface = If->InterfaceId;\r
-\r
- msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;\r
- msg.message.unregisterepmsg.binding_count = BindingVector->Count;\r
-\r
- /* calculate vardata payload size */\r
- msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID);\r
- for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {\r
- RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);\r
- msg.vardata_payload_size += strlen(bind->Protseq) + 1;\r
- msg.vardata_payload_size += strlen(bind->Endpoint) + 1;\r
- }\r
-\r
- /* allocate the payload buffer */\r
- vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);\r
- if (!vardata_payload)\r
- return RPC_S_OUT_OF_MEMORY;\r
-\r
- /* populate the payload data */\r
- for (c=0; c < msg.message.unregisterepmsg.object_count; c++) {\r
- CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));\r
- vp += sizeof(UUID);\r
- }\r
-\r
- for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {\r
- RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);\r
- unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;\r
- CopyMemory(vp, bind->Protseq, pslen);\r
- vp += pslen;\r
- CopyMemory(vp, bind->Endpoint, eplen);\r
- vp += eplen;\r
- }\r
-\r
- /* send our request */\r
- if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))\r
- rslt = RPC_S_OUT_OF_MEMORY;\r
-\r
- /* free the payload buffer */\r
- LocalFree(vardata_payload);\r
-\r
- return rslt;\r
-}\r
-\r
-/***********************************************************************\r
- * RpcEpResolveBinding (RPCRT4.@)\r
- */\r
-RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )\r
-{\r
- RPCSS_NP_MESSAGE msg;\r
- RPCSS_NP_REPLY reply;\r
- PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec;\r
- RpcBinding* bind = (RpcBinding*)Binding;\r
-\r
- TRACE("(%p,%p)\n", Binding, IfSpec);\r
- TRACE(" protseq=%s\n", debugstr_a(bind->Protseq));\r
- TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid));\r
- TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));\r
-\r
- /* FIXME: totally untested */\r
-\r
- /* just return for fully bound handles */\r
- if (bind->Endpoint && (bind->Endpoint[0] != '\0'))\r
- return RPC_S_OK;\r
-\r
- /* construct the message to rpcss */\r
- msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG;\r
- msg.message.resolveepmsg.iface = If->InterfaceId;\r
- msg.message.resolveepmsg.object = bind->ObjectUuid;\r
- \r
- msg.vardata_payload_size = strlen(bind->Protseq) + 1;\r
-\r
- /* send the message */\r
- if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply))\r
- return RPC_S_OUT_OF_MEMORY;\r
-\r
- /* empty-string result means not registered */\r
- if (reply.as_string[0] == '\0')\r
- return EPT_S_NOT_REGISTERED;\r
- \r
- /* otherwise we fully bind the handle & return RPC_S_OK */\r
- return RPCRT4_ResolveBinding(Binding, reply.as_string);\r
-}\r
+/*
+ * RPC endpoint mapper
+ *
+ * Copyright 2002 Greg Turner
+ * Copyright 2001 Ove Kåven, TransGaming Technologies
+ *
+ * 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
+ *
+ * TODO:
+ * - actually do things right
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+
+#include "rpc.h"
+
+#include "wine/debug.h"
+
+#include "rpc_binding.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+/* The "real" RPC portmapper endpoints that I know of are:
+ *
+ * ncadg_ip_udp: 135
+ * ncacn_ip_tcp: 135
+ * ncacn_np: \\pipe\epmapper (?)
+ * ncalrpc: epmapper
+ *
+ * If the user's machine ran a DCE RPC daemon, it would
+ * probably be possible to connect to it, but there are many
+ * reasons not to, like:
+ * - the user probably does *not* run one, and probably
+ * shouldn't be forced to run one just for local COM
+ * - very few Unix systems use DCE RPC... if they run a RPC
+ * daemon at all, it's usually Sun RPC
+ * - DCE RPC registrations are persistent and saved on disk,
+ * while MS-RPC registrations are documented as non-persistent
+ * and stored only in RAM, and auto-destroyed when the process
+ * dies (something DCE RPC can't do)
+ *
+ * Of course, if the user *did* want to run a DCE RPC daemon anyway,
+ * there would be interoperability advantages, like the possibility
+ * of running a fully functional DCOM server using Wine...
+ */
+
+/***********************************************************************
+ * RpcEpRegisterA (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
+ UUID_VECTOR *UuidVector, unsigned char *Annotation )
+{
+ RPCSS_NP_MESSAGE msg;
+ RPCSS_NP_REPLY reply;
+ char *vardata_payload, *vp;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+ unsigned long c;
+ RPC_STATUS rslt = RPC_S_OK;
+
+ TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation));
+ TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
+ for (c=0; c<BindingVector->Count; c++) {
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);
+ TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));
+ TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));
+ }
+ if (UuidVector) {
+ for (c=0; c<UuidVector->Count; c++)
+ TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));
+ }
+
+ /* FIXME: Do something with annotation. */
+
+ /* construct the message to rpcss */
+ msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG;
+ msg.message.registerepmsg.iface = If->InterfaceId;
+ msg.message.registerepmsg.no_replace = 0;
+
+ msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;
+ msg.message.registerepmsg.binding_count = BindingVector->Count;
+
+ /* calculate vardata payload size */
+ msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID);
+ for (c=0; c < msg.message.registerepmsg.binding_count; c++) {
+ RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);
+ msg.vardata_payload_size += strlen(bind->Protseq) + 1;
+ msg.vardata_payload_size += strlen(bind->Endpoint) + 1;
+ }
+
+ /* allocate the payload buffer */
+ vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);
+ if (!vardata_payload)
+ return RPC_S_OUT_OF_MEMORY;
+
+ /* populate the payload data */
+ for (c=0; c < msg.message.registerepmsg.object_count; c++) {
+ CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));
+ vp += sizeof(UUID);
+ }
+
+ for (c=0; c < msg.message.registerepmsg.binding_count; c++) {
+ RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);
+ unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;
+ CopyMemory(vp, bind->Protseq, pslen);
+ vp += pslen;
+ CopyMemory(vp, bind->Endpoint, eplen);
+ vp += eplen;
+ }
+
+ /* send our request */
+ if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))
+ rslt = RPC_S_OUT_OF_MEMORY;
+
+ /* free the payload buffer */
+ LocalFree(vardata_payload);
+
+ return rslt;
+}
+
+/***********************************************************************
+ * RpcEpUnregister (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
+ UUID_VECTOR *UuidVector )
+{
+ RPCSS_NP_MESSAGE msg;
+ RPCSS_NP_REPLY reply;
+ char *vardata_payload, *vp;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+ unsigned long c;
+ RPC_STATUS rslt = RPC_S_OK;
+
+ TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);
+ TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
+ for (c=0; c<BindingVector->Count; c++) {
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]);
+ TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq));
+ TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint));
+ }
+ if (UuidVector) {
+ for (c=0; c<UuidVector->Count; c++)
+ TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c]));
+ }
+
+ /* construct the message to rpcss */
+ msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG;
+ msg.message.unregisterepmsg.iface = If->InterfaceId;
+
+ msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0;
+ msg.message.unregisterepmsg.binding_count = BindingVector->Count;
+
+ /* calculate vardata payload size */
+ msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID);
+ for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {
+ RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]);
+ msg.vardata_payload_size += strlen(bind->Protseq) + 1;
+ msg.vardata_payload_size += strlen(bind->Endpoint) + 1;
+ }
+
+ /* allocate the payload buffer */
+ vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size);
+ if (!vardata_payload)
+ return RPC_S_OUT_OF_MEMORY;
+
+ /* populate the payload data */
+ for (c=0; c < msg.message.unregisterepmsg.object_count; c++) {
+ CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID));
+ vp += sizeof(UUID);
+ }
+
+ for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) {
+ RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]);
+ unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1;
+ CopyMemory(vp, bind->Protseq, pslen);
+ vp += pslen;
+ CopyMemory(vp, bind->Endpoint, eplen);
+ vp += eplen;
+ }
+
+ /* send our request */
+ if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply))
+ rslt = RPC_S_OUT_OF_MEMORY;
+
+ /* free the payload buffer */
+ LocalFree(vardata_payload);
+
+ return rslt;
+}
+
+/***********************************************************************
+ * RpcEpResolveBinding (RPCRT4.@)
+ */
+RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
+{
+ RPCSS_NP_MESSAGE msg;
+ RPCSS_NP_REPLY reply;
+ PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec;
+ RpcBinding* bind = (RpcBinding*)Binding;
+
+ TRACE("(%p,%p)\n", Binding, IfSpec);
+ TRACE(" protseq=%s\n", debugstr_a(bind->Protseq));
+ TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid));
+ TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
+
+ /* FIXME: totally untested */
+
+ /* just return for fully bound handles */
+ if (bind->Endpoint && (bind->Endpoint[0] != '\0'))
+ return RPC_S_OK;
+
+ /* construct the message to rpcss */
+ msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG;
+ msg.message.resolveepmsg.iface = If->InterfaceId;
+ msg.message.resolveepmsg.object = bind->ObjectUuid;
+
+ msg.vardata_payload_size = strlen(bind->Protseq) + 1;
+
+ /* send the message */
+ if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply))
+ return RPC_S_OUT_OF_MEMORY;
+
+ /* empty-string result means not registered */
+ if (reply.as_string[0] == '\0')
+ return EPT_S_NOT_REGISTERED;
+
+ /* otherwise we fully bind the handle & return RPC_S_OK */
+ return RPCRT4_ResolveBinding(Binding, reply.as_string);
+}