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