ntdll: Fixed tape.c compilation on Solaris.
[wine] / programs / rpcss / epmap_server.c
1 /*
2  * RPC endpoint mapper server
3  *
4  * Copyright (C) 2001 Ove Kåven, TransGaming Technologies Inc,
5  * Copyright (C) 2002 Greg Turner
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <assert.h>
23 #include <string.h>
24
25 #include "rpcss.h"
26 #include "rpc.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(ole);
30
31 struct epmap_entry
32 {
33     struct epmap_entry *next;
34     RPC_SYNTAX_IDENTIFIER iface;
35     UUID object;
36     char *protseq;
37     char *endpoint;
38 };
39
40 static struct epmap_entry *epmap;
41
42 static const UUID nil_object;
43
44 static char *mystrdup(const char *str) {
45     char *rval;
46     rval = LocalAlloc(LPTR, strlen(str)+1);
47     CopyMemory(rval, str, strlen(str)+1);
48     return rval;
49 }
50
51 static struct epmap_entry *find_endpoint(const RPC_SYNTAX_IDENTIFIER *iface,
52                                          const char *protseq, const UUID *object)
53 {
54     struct epmap_entry *map;
55     for (map=epmap; map; map=map->next) {
56         if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
57         if (memcmp(&map->object, object, sizeof(UUID))) continue;
58         if (strcmp(map->protseq, protseq)) continue;
59         WINE_TRACE("found.\n");
60         return map;
61     }
62     WINE_TRACE("not found.\n");
63     return NULL;
64 }
65
66 static void register_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
67                               const char *endpoint, const UUID *objects, int objcount,
68                               int no_replace)
69 {
70     int c;
71
72     WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i, no_replace == %i)\n",
73       wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount, no_replace);
74
75     if (!objcount) {
76         objects = &nil_object;
77         objcount = 1;
78     }
79
80     for (c=0; c<objcount; c++) {
81         struct epmap_entry *map = NULL;
82         if (!no_replace)
83             map = find_endpoint(iface, protseq, &objects[c]);
84         if (map) {
85             LocalFree(map->endpoint);
86         }
87         else {
88             map = LocalAlloc(LPTR, sizeof(struct epmap_entry));
89             memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER));
90             memcpy(&map->object, &objects[c], sizeof(UUID));
91             map->protseq = mystrdup(protseq);
92             map->next = epmap;
93             epmap = map;
94         }
95         WINE_TRACE("  mapping endpoint (protseq == %s, endpoint == %s, uuid == %s)\n",
96           wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), wine_dbgstr_guid(&objects[c]));
97         map->endpoint = mystrdup(endpoint);
98     }
99 }
100
101 static void unregister_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
102                                 const char *endpoint, const UUID *objects, int objcount)
103 {
104     struct epmap_entry *map, *prev, *nprev, *next;
105     int c;
106     
107     WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i)\n", 
108       wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount);
109     
110     if (!objcount) {
111         objects = &nil_object;
112         objcount = 1;
113     }
114     prev=NULL;
115     nprev=NULL;
116     map=epmap;
117     while(map) {
118         next = map->next;
119         nprev = map;
120         if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) goto cont;
121         for (c=0; c<objcount; c++)
122             if (!memcmp(&map->object, &objects[c], sizeof(UUID))) break;
123         if (c==objcount) goto cont;
124         if (strcmp(map->protseq, protseq)) goto cont;
125         
126         WINE_TRACE("  unmapping: (protseq == %s, endpoint == %s, uuid == %s)\n",
127           wine_dbgstr_a(map->protseq), wine_dbgstr_a(map->endpoint),
128           wine_dbgstr_guid(&map->object));
129         
130         if (prev) prev->next = map->next;
131         else epmap = map->next;
132         nprev = prev;
133
134         LocalFree(map->protseq);
135         LocalFree(map->endpoint);
136         LocalFree(map);
137
138         cont:
139
140         prev = nprev;
141         map = next;
142     }
143 }
144
145 static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq,
146                              const UUID *object, char *rslt_ep)
147 {
148     size_t len;
149     struct epmap_entry *map;
150
151     if (!(map = find_endpoint(iface, protseq, object))) return;
152
153     len = min( MAX_RPCSS_NP_REPLY_STRING_LEN, strlen(map->endpoint)+1 );
154     if (len) memcpy(rslt_ep, map->endpoint, len);
155 }
156
157 static const char *get_string(const char**ptr, const char*end)
158 {
159     const char *str = *ptr, *nptr = str;
160
161     while (nptr < end && *nptr) nptr++;
162     if (nptr == end)
163         return NULL;
164     *ptr = nptr + 1;
165     return str;
166 }
167
168 BOOL RPCSS_EpmapEmpty(void)
169 {
170   return (!epmap);
171 }
172
173 void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, 
174   int binding_count, int no_replace, char *vardata, long vardata_size)
175 {
176     const char *data = vardata;
177     const char *end = data + vardata_size;
178     const UUID *objects = (const UUID *)data;
179     int c;
180
181     data += object_count * sizeof(UUID);
182     for (c=0; c < binding_count; c++) {
183         const char *protseq = get_string(&data, end);
184         const char *endpoint = get_string(&data, end);
185         if (protseq && endpoint)
186             register_endpoint(&iface, protseq, endpoint, objects, object_count, no_replace);
187     }
188 }
189
190 void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count,
191   int binding_count, char *vardata, long vardata_size)
192 {
193     const char *data = vardata;
194     const char *end = data + vardata_size;
195     const UUID *objects = (const UUID *)data;
196     int c;
197
198     data += object_count * sizeof(UUID);
199     for (c=0; c < binding_count; c++) {
200         const char *protseq = get_string(&data, end);
201         const char *endpoint = get_string(&data, end);
202         if (protseq && endpoint)
203             unregister_endpoint(&iface, protseq, endpoint, objects, object_count);
204     }
205 }
206
207 void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object, char *protseq, char *rslt_ep)
208 {
209     resolve_endpoint(&iface, protseq, &object, rslt_ep);
210 }