blob: 2be05dbc869088a7b6eb50d9859a3623cff5c4f7 [file] [log] [blame]
/*
* 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;
UUID *objects = (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 = (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);
}