| /* |
| * RPC endpoint mapper server |
| * |
| * Copyright (C) 2001 Ove Kåven, TransGaming Technologies Inc, |
| * 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 <string.h> |
| |
| #include "rpcss.h" |
| #include "rpc.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ole); |
| |
| struct epmap_entry |
| { |
| struct epmap_entry *next; |
| RPC_SYNTAX_IDENTIFIER iface; |
| UUID object; |
| char *protseq; |
| char *endpoint; |
| }; |
| |
| static struct epmap_entry *epmap; |
| |
| static const UUID nil_object; |
| |
| static char *mystrdup(const char *str) { |
| char *rval; |
| rval = LocalAlloc(LPTR, strlen(str)+1); |
| CopyMemory(rval, str, strlen(str)+1); |
| return rval; |
| } |
| |
| 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; |
| WINE_TRACE("found.\n"); |
| return map; |
| } |
| WINE_TRACE("not found.\n"); |
| 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; |
| |
| WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i, no_replace == %i)\n", |
| wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount, no_replace); |
| |
| 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) { |
| LocalFree(map->endpoint); |
| } |
| else { |
| map = LocalAlloc(LPTR, sizeof(struct epmap_entry)); |
| memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER)); |
| memcpy(&map->object, &objects[c], sizeof(UUID)); |
| map->protseq = mystrdup(protseq); |
| map->next = epmap; |
| epmap = map; |
| } |
| WINE_TRACE(" mapping endpoint (protseq == %s, endpoint == %s, uuid == %s)\n", |
| wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), wine_dbgstr_guid(&objects[c])); |
| map->endpoint = mystrdup(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; |
| |
| WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i)\n", |
| wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount); |
| |
| if (!objcount) { |
| objects = &nil_object; |
| objcount = 1; |
| } |
| prev=NULL; |
| nprev=NULL; |
| map=epmap; |
| while(map) { |
| next = map->next; |
| nprev = map; |
| if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) goto cont; |
| for (c=0; c<objcount; c++) |
| if (!memcmp(&map->object, &objects[c], sizeof(UUID))) break; |
| if (c==objcount) goto cont; |
| if (strcmp(map->protseq, protseq)) goto cont; |
| |
| WINE_TRACE(" unmapping: (protseq == %s, endpoint == %s, uuid == %s)\n", |
| wine_dbgstr_a(map->protseq), wine_dbgstr_a(map->endpoint), |
| wine_dbgstr_guid(&map->object)); |
| |
| if (prev) prev->next = map->next; |
| else epmap = map->next; |
| nprev = prev; |
| |
| LocalFree(map->protseq); |
| LocalFree(map->endpoint); |
| LocalFree(map); |
| |
| cont: |
| |
| prev = nprev; |
| map = next; |
| } |
| } |
| |
| static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq, |
| const UUID *object, char *rslt_ep) |
| { |
| size_t len; |
| struct epmap_entry *map; |
| |
| if (!(map = find_endpoint(iface, protseq, object))) return; |
| |
| len = min( MAX_RPCSS_NP_REPLY_STRING_LEN, strlen(map->endpoint)+1 ); |
| if (len) memcpy(rslt_ep, map->endpoint, len); |
| } |
| |
| 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) |
| return NULL; |
| *ptr = nptr + 1; |
| return str; |
| } |
| |
| BOOL RPCSS_EpmapEmpty(void) |
| { |
| return (!epmap); |
| } |
| |
| void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, |
| int binding_count, int no_replace, char *vardata, long vardata_size) |
| { |
| const char *data = vardata; |
| const char *end = data + vardata_size; |
| const UUID *objects = (const UUID *)data; |
| int c; |
| |
| data += object_count * sizeof(UUID); |
| for (c=0; c < binding_count; c++) { |
| const char *protseq = get_string(&data, end); |
| const char *endpoint = get_string(&data, end); |
| if (protseq && endpoint) |
| register_endpoint(&iface, protseq, endpoint, objects, object_count, no_replace); |
| } |
| } |
| |
| void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, |
| int binding_count, char *vardata, long vardata_size) |
| { |
| const char *data = vardata; |
| const char *end = data + vardata_size; |
| const UUID *objects = (const UUID *)data; |
| int c; |
| |
| data += object_count * sizeof(UUID); |
| for (c=0; c < binding_count; c++) { |
| const char *protseq = get_string(&data, end); |
| const char *endpoint = get_string(&data, end); |
| if (protseq && endpoint) |
| unregister_endpoint(&iface, protseq, endpoint, objects, object_count); |
| } |
| } |
| |
| void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object, char *protseq, char *rslt_ep) |
| { |
| resolve_endpoint(&iface, protseq, &object, rslt_ep); |
| } |