Equivalent to RPC_E_PL0 (there is one trivial adjustment: I alphabetized the Makefile.in part).
Just the unmerged server parts. Not a hint to apply. -- gmt "Oh, and of course, the fastest way to dig a tunnel is to dig at both sides." -- The Linux Advanced Routing HOWTO
diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/dlls/rpcrt4/Makefile.in ./dlls/rpcrt4/Makefile.in --- ../wine.vanilla/dlls/rpcrt4/Makefile.in 2002-10-21 19:41:17.000000000 -0500 +++ ./dlls/rpcrt4/Makefile.in 2002-10-23 23:45:35.000000000 -0500 @@ -19,6 +19,7 @@ ndr_ole.c \ ndr_stubless.c \ rpc_binding.c \ + rpc_epmap.c \ rpc_message.c \ rpc_server.c \ rpcrt4_main.c diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/dlls/rpcrt4/rpc_epmap.c ./dlls/rpcrt4/rpc_epmap.c --- ../wine.vanilla/dlls/rpcrt4/rpc_epmap.c 1969-12-31 18:00:00.000000000 -0600 +++ ./dlls/rpcrt4/rpc_epmap.c 2002-10-23 23:20:56.000000000 -0500 @@ -0,0 +1,172 @@ +/* + * RPC endpoint mapper + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * TODO: + * - actually do things right + */ + +#include <stdio.h> +#include <string.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" + +#include "wine/server.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... + * + * But for now, I'll just use the wineserver... + */ + +/*********************************************************************** + * RpcEpRegisterA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector, + UUID_VECTOR* UuidVector, LPSTR Annotation ) +{ + NTSTATUS ret; + PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + unsigned long c; + + TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a(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, bind->Protseq); + TRACE(" endpoint[%ld]=%s\n", c, bind->Endpoint); + } + if (UuidVector) { + for (c=0; c<UuidVector->Count; c++) + TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + } + + SERVER_START_REQ( register_rpc_endpoints ) + { + wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) ); + if (UuidVector) { + req->objects = UuidVector->Count; + for (c=0; c<req->objects; c++) + wine_server_add_data( req, UuidVector->Uuid[c], sizeof(UUID) ); + } + else req->objects = 0; + req->bindings = BindingVector->Count; + for (c=0; c<req->bindings; c++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); + wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 ); + wine_server_add_data( req, bind->Endpoint, strlen(bind->Endpoint)+1 ); + } + req->no_replace = 0; + /* FIXME: annotation */ + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + return RtlNtStatusToDosError(ret); +} + +/*********************************************************************** + * RpcEpUnregister (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR* BindingVector, + UUID_VECTOR* UuidVector ) +{ + NTSTATUS ret; + PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + unsigned long c; + + 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, bind->Protseq); + TRACE(" endpoint[%ld]=%s\n", c, bind->Endpoint); + } + if (UuidVector) { + for (c=0; c<UuidVector->Count; c++) + TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + } + + SERVER_START_REQ( unregister_rpc_endpoints ) + { + wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) ); + if (UuidVector) { + req->objects = UuidVector->Count; + for (c=0; c<req->objects; c++) + wine_server_add_data( req, UuidVector->Uuid[c], sizeof(UUID) ); + } + else req->objects = 0; + req->bindings = BindingVector->Count; + for (c=0; c<req->bindings; c++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); + wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 ); + wine_server_add_data( req, bind->Endpoint, strlen(bind->Endpoint)+1 ); + } + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + return RtlNtStatusToDosError(ret); +} + +/*********************************************************************** + * RpcEpResolveBinding (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) +{ + NTSTATUS ret; + PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; + RpcBinding* bind = (RpcBinding*)Binding; + char Endpoint[64]; + + TRACE("(%p,%p)\n", Binding, IfSpec); + TRACE(" protseq=%s\n", bind->Protseq); + TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid)); + TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); + + SERVER_START_REQ( resolve_rpc_endpoint ) + { + wine_server_add_data( req, &If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) ); + wine_server_add_data( req, &bind->ObjectUuid, sizeof(UUID) ); + wine_server_add_data( req, bind->Protseq, strlen(bind->Protseq)+1 ); + wine_server_set_reply( req, Endpoint, sizeof(Endpoint) ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + if (ret) return RtlNtStatusToDosError(ret); + + return RPCRT4_ResolveBinding(Binding, Endpoint); +} + diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/dlls/rpcrt4/rpcrt4.spec ./dlls/rpcrt4/rpcrt4.spec --- ../wine.vanilla/dlls/rpcrt4/rpcrt4.spec 2002-10-21 19:41:17.000000000 -0500 +++ ./dlls/rpcrt4/rpcrt4.spec 2002-10-23 23:20:56.000000000 -0500 @@ -55,12 +55,12 @@ @ stub RpcCertGeneratePrincipalNameA @ stub RpcCertGeneratePrincipalNameW @ stub RpcCompleteAsyncCall -@ stub RpcEpRegisterA +@ stdcall RpcEpRegisterA(ptr ptr ptr str) RpcEpRegisterA @ stub RpcEpRegisterW @ stub RpcEpRegisterNoReplaceA @ stub RpcEpRegisterNoReplaceW -@ stub RpcEpResolveBinding -@ stub RpcEpUnregister +@ stdcall RpcEpResolveBinding(ptr ptr) RpcEpResolveBinding +@ stdcall RpcEpUnregister(ptr ptr ptr) RpcEpUnregister @ stub RpcGetAsyncCallStatus @ stub RpcIfIdVectorFree @ stub RpcIfInqId diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/include/wine/server_protocol.h ./include/wine/server_protocol.h --- ../wine.vanilla/include/wine/server_protocol.h 2002-10-21 18:43:05.000000000 -0500 +++ ./include/wine/server_protocol.h 2002-10-23 23:20:56.000000000 -0500 @@ -2737,6 +2737,48 @@ +struct register_rpc_endpoints_request +{ + struct request_header __header; + int objects; + int bindings; + int no_replace; + /* VARARG(eps,bytes); */ +}; +struct register_rpc_endpoints_reply +{ + struct reply_header __header; +}; + + + +struct unregister_rpc_endpoints_request +{ + struct request_header __header; + int objects; + int bindings; + /* VARARG(eps,bytes); */ +}; +struct unregister_rpc_endpoints_reply +{ + struct reply_header __header; +}; + + + +struct resolve_rpc_endpoint_request +{ + struct request_header __header; + /* VARARG(binding,bytes); */ +}; +struct resolve_rpc_endpoint_reply +{ + struct reply_header __header; + /* VARARG(ep,bytes); */ +}; + + + struct attach_thread_input_request { struct request_header __header; @@ -3024,6 +3066,9 @@ REQ_remove_window_property, REQ_get_window_property, REQ_get_window_properties, + REQ_register_rpc_endpoints, + REQ_unregister_rpc_endpoints, + REQ_resolve_rpc_endpoint, REQ_attach_thread_input, REQ_get_thread_input, REQ_set_foreground_window, @@ -3195,6 +3240,9 @@ struct remove_window_property_request remove_window_property_request; struct get_window_property_request get_window_property_request; struct get_window_properties_request get_window_properties_request; + struct register_rpc_endpoints_request register_rpc_endpoints_request; + struct unregister_rpc_endpoints_request unregister_rpc_endpoints_request; + struct resolve_rpc_endpoint_request resolve_rpc_endpoint_request; struct attach_thread_input_request attach_thread_input_request; struct get_thread_input_request get_thread_input_request; struct set_foreground_window_request set_foreground_window_request; @@ -3364,6 +3412,9 @@ struct remove_window_property_reply remove_window_property_reply; struct get_window_property_reply get_window_property_reply; struct get_window_properties_reply get_window_properties_reply; + struct register_rpc_endpoints_reply register_rpc_endpoints_reply; + struct unregister_rpc_endpoints_reply unregister_rpc_endpoints_reply; + struct resolve_rpc_endpoint_reply resolve_rpc_endpoint_reply; struct attach_thread_input_reply attach_thread_input_reply; struct get_thread_input_reply get_thread_input_reply; struct set_foreground_window_reply set_foreground_window_reply; @@ -3374,6 +3425,6 @@ struct set_caret_info_reply set_caret_info_reply; }; -#define SERVER_PROTOCOL_VERSION 88 +#define SERVER_PROTOCOL_VERSION 89 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/server/Makefile.in ./server/Makefile.in --- ../wine.vanilla/server/Makefile.in 2002-10-18 20:00:59.000000000 -0500 +++ ./server/Makefile.in 2002-10-23 23:20:56.000000000 -0500 @@ -29,6 +29,7 @@ queue.c \ registry.c \ request.c \ + rpc_epmap.c \ select.c \ semaphore.c \ serial.c \ diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/server/protocol.def ./server/protocol.def --- ../wine.vanilla/server/protocol.def 2002-10-21 18:43:04.000000000 -0500 +++ ./server/protocol.def 2002-10-23 23:20:56.000000000 -0500 @@ -1917,6 +1917,31 @@ @END +/* Register RPC endpoints */ +@REQ(register_rpc_endpoints) + int objects; /* number of objects */ + int bindings; /* number of bindings */ + int no_replace; /* don't replace existing endpoints */ + VARARG(eps,bytes); /* list of bindings and objects */ +@END + + +/* Unregister RPC endpoints */ +@REQ(unregister_rpc_endpoints) + int objects; /* number of objects */ + int bindings; /* number of bindings */ + VARARG(eps,bytes); /* list of bindings and objects */ +@END + + +/* Resolve RPC endpoint */ +@REQ(resolve_rpc_endpoint) + VARARG(binding,bytes); /* unmapped binding */ +@REPLY + VARARG(ep,bytes); /* mapped endpoint */ +@END + + /* Attach (or detach) thread inputs */ @REQ(attach_thread_input) thread_id_t tid_from; /* thread to be attached */ diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/server/request.h ./server/request.h --- ../wine.vanilla/server/request.h 2002-10-16 20:24:33.000000000 -0500 +++ ./server/request.h 2002-10-23 23:20:56.000000000 -0500 @@ -259,6 +259,9 @@ DECL_HANDLER(remove_window_property); DECL_HANDLER(get_window_property); DECL_HANDLER(get_window_properties); +DECL_HANDLER(register_rpc_endpoints); +DECL_HANDLER(unregister_rpc_endpoints); +DECL_HANDLER(resolve_rpc_endpoint); DECL_HANDLER(attach_thread_input); DECL_HANDLER(get_thread_input); DECL_HANDLER(set_foreground_window); @@ -429,6 +432,9 @@ (req_handler)req_remove_window_property, (req_handler)req_get_window_property, (req_handler)req_get_window_properties, + (req_handler)req_register_rpc_endpoints, + (req_handler)req_unregister_rpc_endpoints, + (req_handler)req_resolve_rpc_endpoint, (req_handler)req_attach_thread_input, (req_handler)req_get_thread_input, (req_handler)req_set_foreground_window, diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/server/rpc_epmap.c ./server/rpc_epmap.c --- ../wine.vanilla/server/rpc_epmap.c 1969-12-31 18:00:00.000000000 -0600 +++ ./server/rpc_epmap.c 2002-10-23 23:20:56.000000000 -0500 @@ -0,0 +1,191 @@ +/* + * RPC endpoint mapper + * + * Copyright (C) 2001 Ove Kåven, TransGaming Technologies Inc. + */ + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "unicode.h" +#include "request.h" +#include "process.h" + +#include "rpc.h" + +struct epmap_entry +{ + struct epmap_entry *next; + RPC_SYNTAX_IDENTIFIER iface; + UUID object; + char *protseq; + char *endpoint; +}; + +struct epmap_entry *epmap; + +static const UUID nil_object; + +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; + return map; + } + 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; + + 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) { + free(map->endpoint); + } + else { + map = mem_alloc(sizeof(struct epmap_entry)); + memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER)); + memcpy(&map->object, &objects[c], sizeof(UUID)); + map->protseq = strdup(protseq); + map->next = epmap; + epmap = map; + } + map->endpoint = strdup(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; + + if (!objcount) { + objects = &nil_object; + objcount = 1; + } + + for (prev=NULL,nprev=NULL,map=epmap,next=map->next; map; prev=nprev,map=next,next=map->next) { + nprev = map; + if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; + for (c=0; c<objcount; c++) + if (!memcmp(&map->object, &objects[c], sizeof(UUID))) break; + if (c==objcount) continue; + if (strcmp(map->protseq, protseq)) continue; + + if (prev) prev->next = map->next; + else epmap = map->next; + nprev = prev; + + free(map->protseq); + free(map->endpoint); + free(map); + } +} + +static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq, + const UUID *object) +{ + size_t len; + char *data; + struct epmap_entry *map; + + if (!(map = find_endpoint(iface, protseq, object))) { + set_error( EPT_NT_NOT_REGISTERED ); + return; + } + + len = min( get_reply_max_size(), strlen(map->endpoint)+1 ); + if (len && ((data = set_reply_data_size(len)))) + memcpy(data, map->endpoint, len); +} + +static const void *get_struct(const char**ptr, const char*end, size_t size) +{ + const char *data = *ptr; + + *ptr = data + size; + if (*ptr > end) { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + + return data; +} + +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) { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + *ptr = nptr + 1; + + return str; +} + +DECL_HANDLER(register_rpc_endpoints) +{ + const char *data = get_req_data(); + const char *end = data + get_req_data_size(); + const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER)); + const UUID *objects = get_struct(&data, end, req->objects * sizeof(UUID)); + if (iface && objects) { + int c; + for (c=0; c<req->bindings; c++) { + const char *protseq = get_string(&data, end); + const char *endpoint = get_string(&data, end); + if (protseq && endpoint) + register_endpoint(iface, protseq, endpoint, objects, req->objects, req->no_replace); + } + } +} + +DECL_HANDLER(unregister_rpc_endpoints) +{ + const char *data = get_req_data(); + const char *end = data + get_req_data_size(); + const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER)); + const UUID *objects = get_struct(&data, end, req->objects * sizeof(UUID)); + if (iface && objects) { + int c; + for (c=0; c<req->bindings; c++) { + const char *protseq = get_string(&data, end); + const char *endpoint = get_string(&data, end); + if (protseq && endpoint) + unregister_endpoint(iface, protseq, endpoint, objects, req->objects); + } + } +} + +DECL_HANDLER(resolve_rpc_endpoint) +{ + const char *data = get_req_data(); + const char *end = data + get_req_data_size(); + const RPC_SYNTAX_IDENTIFIER *iface = get_struct(&data, end, sizeof(RPC_SYNTAX_IDENTIFIER)); + const UUID *object = get_struct(&data, end, sizeof(UUID)); + const char *protseq = get_string(&data, end); + if (iface && object && protseq) { + resolve_endpoint(iface, protseq, object); + } +} diff -urN -x doall -x doconfig -x gmt-cfg-vars -x unpatch -x CVS -x 'bigdif*' ../wine.vanilla/server/trace.c ./server/trace.c --- ../wine.vanilla/server/trace.c 2002-10-18 20:00:59.000000000 -0500 +++ ./server/trace.c 2002-10-23 23:20:56.000000000 -0500 @@ -2176,6 +2176,35 @@ dump_varargs_properties( cur_size ); } +static void dump_register_rpc_endpoints_request( const struct register_rpc_endpoints_request *req ) +{ + fprintf( stderr, " objects=%d,", req->objects ); + fprintf( stderr, " bindings=%d,", req->bindings ); + fprintf( stderr, " no_replace=%d,", req->no_replace ); + fprintf( stderr, " eps=" ); + dump_varargs_bytes( cur_size ); +} + +static void dump_unregister_rpc_endpoints_request( const struct unregister_rpc_endpoints_request *req ) +{ + fprintf( stderr, " objects=%d,", req->objects ); + fprintf( stderr, " bindings=%d,", req->bindings ); + fprintf( stderr, " eps=" ); + dump_varargs_bytes( cur_size ); +} + +static void dump_resolve_rpc_endpoint_request( const struct resolve_rpc_endpoint_request *req ) +{ + fprintf( stderr, " binding=" ); + dump_varargs_bytes( cur_size ); +} + +static void dump_resolve_rpc_endpoint_reply( const struct resolve_rpc_endpoint_reply *req ) +{ + fprintf( stderr, " ep=" ); + dump_varargs_bytes( cur_size ); +} + static void dump_attach_thread_input_request( const struct attach_thread_input_request *req ) { fprintf( stderr, " tid_from=%08x,", req->tid_from ); @@ -2439,6 +2468,9 @@ (dump_func)dump_remove_window_property_request, (dump_func)dump_get_window_property_request, (dump_func)dump_get_window_properties_request, + (dump_func)dump_register_rpc_endpoints_request, + (dump_func)dump_unregister_rpc_endpoints_request, + (dump_func)dump_resolve_rpc_endpoint_request, (dump_func)dump_attach_thread_input_request, (dump_func)dump_get_thread_input_request, (dump_func)dump_set_foreground_window_request, @@ -2607,6 +2639,9 @@ (dump_func)dump_get_window_property_reply, (dump_func)dump_get_window_properties_reply, (dump_func)0, + (dump_func)0, + (dump_func)dump_resolve_rpc_endpoint_reply, + (dump_func)0, (dump_func)dump_get_thread_input_reply, (dump_func)dump_set_foreground_window_reply, (dump_func)dump_set_focus_window_reply, @@ -2773,6 +2808,9 @@ "remove_window_property", "get_window_property", "get_window_properties", + "register_rpc_endpoints", + "unregister_rpc_endpoints", + "resolve_rpc_endpoint", "attach_thread_input", "get_thread_input", "set_foreground_window",