xref: /reactos/base/services/rpcss/epmp.c (revision cc439606)
1 /*
2  * Endpoint Mapper
3  *
4  * Copyright (C) 2007 Robert Shearman for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "epm_s.h"
22 
23 #include "wine/debug.h"
24 #include "wine/list.h"
25 
26 WINE_DEFAULT_DEBUG_CHANNEL(ole);
27 
28 struct registered_ept_entry
29 {
30     struct list entry;
31     GUID object;
32     RPC_SYNTAX_IDENTIFIER iface;
33     RPC_SYNTAX_IDENTIFIER syntax;
34     char *protseq;
35     char *endpoint;
36     char *address;
37     char annotation[ept_max_annotation_size];
38 };
39 
40 static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list);
41 
42 static CRITICAL_SECTION csEpm;
43 static CRITICAL_SECTION_DEBUG critsect_debug =
44 {
45     0, 0, &csEpm,
46     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
47     0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") }
48 };
49 static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 };
50 
51 static const UUID nil_object;
52 
53 /* must be called inside csEpm */
54 static void delete_registered_ept_entry(struct registered_ept_entry *entry)
55 {
56     I_RpcFree(entry->protseq);
57     I_RpcFree(entry->endpoint);
58     I_RpcFree(entry->address);
59     list_remove(&entry->entry);
60     HeapFree(GetProcessHeap(), 0, entry);
61 }
62 
63 static struct registered_ept_entry *find_ept_entry(
64     const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax,
65     const char *protseq, const char *endpoint, const char *address,
66     const UUID *object)
67 {
68     struct registered_ept_entry *entry;
69     LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
70     {
71         if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
72         if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
73         if (strcmp(entry->protseq, protseq)) continue;
74         if (memcmp(&entry->object, object, sizeof(UUID))) continue;
75 	WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n",
76                    entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion,
77                    wine_dbgstr_guid(&entry->iface.SyntaxGUID),
78                    entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion,
79                    wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq,
80                    wine_dbgstr_guid(&entry->object));
81         return entry;
82     }
83     WINE_TRACE("not found\n");
84     return NULL;
85 }
86 
87 void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle)
88 {
89     WINE_FIXME("%p\n", entry_handle);
90 }
91 
92 void __cdecl ept_insert(handle_t h,
93                         unsigned32 num_ents,
94                         ept_entry_t entries[],
95                         boolean32 replace,
96                         error_status_t *status)
97 {
98     unsigned32 i;
99     RPC_STATUS rpc_status;
100 
101     WINE_TRACE("(%p, %u, %p, %u, %p)\n", h, num_ents, entries, replace, status);
102 
103     *status = RPC_S_OK;
104 
105     EnterCriticalSection(&csEpm);
106 
107     for (i = 0; i < num_ents; i++)
108     {
109         struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
110         if (!entry)
111         {
112             /* FIXME: cleanup code to delete added entries */
113             *status = EPT_S_CANT_PERFORM_OP;
114             break;
115         }
116         memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation));
117         rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax,
118                                   &entry->protseq, &entry->endpoint,
119                                   &entry->address);
120         if (rpc_status != RPC_S_OK)
121         {
122             WINE_WARN("TowerExplode failed %u\n", rpc_status);
123             *status = rpc_status;
124             HeapFree(GetProcessHeap(), 0, entry);
125             break; /* FIXME: more cleanup? */
126         }
127 
128         entry->object = entries[i].object;
129 
130         if (replace)
131         {
132             /* FIXME: correct find algorithm */
133             struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object);
134             if (old_entry) delete_registered_ept_entry(old_entry);
135         }
136         list_add_tail(&registered_ept_entry_list, &entry->entry);
137     }
138 
139     LeaveCriticalSection(&csEpm);
140 }
141 
142 void __cdecl ept_delete(handle_t h,
143                         unsigned32 num_ents,
144                         ept_entry_t entries[],
145                         error_status_t *status)
146 {
147     unsigned32 i;
148     RPC_STATUS rpc_status;
149 
150     *status = RPC_S_OK;
151 
152     WINE_TRACE("(%p, %u, %p, %p)\n", h, num_ents, entries, status);
153 
154     EnterCriticalSection(&csEpm);
155 
156     for (i = 0; i < num_ents; i++)
157     {
158         struct registered_ept_entry *entry;
159         RPC_SYNTAX_IDENTIFIER iface, syntax;
160         char *protseq;
161         char *endpoint;
162         char *address;
163         rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq,
164                                   &endpoint, &address);
165         if (rpc_status != RPC_S_OK)
166             break;
167         entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object);
168 
169         I_RpcFree(protseq);
170         I_RpcFree(endpoint);
171         I_RpcFree(address);
172 
173         if (entry)
174             delete_registered_ept_entry(entry);
175         else
176         {
177             *status = EPT_S_NOT_REGISTERED;
178             break;
179         }
180     }
181 
182     LeaveCriticalSection(&csEpm);
183 }
184 
185 void __cdecl ept_lookup(handle_t h,
186                         unsigned32 inquiry_type,
187                         uuid_p_t object,
188                         rpc_if_id_p_t interface_id,
189                         unsigned32 vers_option,
190                         ept_lookup_handle_t *entry_handle,
191                         unsigned32 max_ents,
192                         unsigned32 *num_ents,
193                         ept_entry_t entries[],
194                         error_status_t *status)
195 {
196     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
197 
198     *status = EPT_S_CANT_PERFORM_OP;
199 }
200 
201 void __cdecl ept_map(handle_t h,
202                      uuid_p_t object,
203                      twr_p_t map_tower,
204                      ept_lookup_handle_t *entry_handle,
205                      unsigned32 max_towers,
206                      unsigned32 *num_towers,
207                      twr_p_t *towers,
208                      error_status_t *status)
209 {
210     RPC_STATUS rpc_status;
211     RPC_SYNTAX_IDENTIFIER iface, syntax;
212     char *protseq;
213     struct registered_ept_entry *entry;
214 
215     *status = RPC_S_OK;
216     *num_towers = 0;
217 
218     WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower,
219           entry_handle, max_towers, num_towers, towers, status);
220 
221     rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq,
222                               NULL, NULL);
223     if (rpc_status != RPC_S_OK)
224     {
225         *status = rpc_status;
226         return;
227     }
228 
229     EnterCriticalSection(&csEpm);
230 
231     LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
232     {
233         if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) &&
234             (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) &&
235             (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) &&
236             !memcmp(&entry->syntax, &syntax, sizeof(syntax)) &&
237             !strcmp(entry->protseq, protseq) &&
238             ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object)))
239         {
240             if (*num_towers < max_towers)
241             {
242                 rpc_status = TowerConstruct(&entry->iface, &entry->syntax,
243                                             entry->protseq, entry->endpoint,
244                                             entry->address,
245                                             &towers[*num_towers]);
246                 if (rpc_status != RPC_S_OK)
247                 {
248                     *status = rpc_status;
249                     break; /* FIXME: more cleanup? */
250                 }
251             }
252             (*num_towers)++;
253         }
254     }
255 
256     LeaveCriticalSection(&csEpm);
257 
258     I_RpcFree(protseq);
259 }
260 
261 void __cdecl ept_lookup_handle_free(handle_t h,
262                                     ept_lookup_handle_t *entry_handle,
263                                     error_status_t *status)
264 {
265     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
266 
267     *status = EPT_S_CANT_PERFORM_OP;
268 }
269 
270 void __cdecl ept_inq_object(handle_t h,
271                             GUID *ept_object,
272                             error_status_t *status)
273 {
274     WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status);
275 
276     *status = EPT_S_CANT_PERFORM_OP;
277 }
278 
279 void __cdecl ept_mgmt_delete(handle_t h,
280                              boolean32 object_speced,
281                              uuid_p_t object,
282                              twr_p_t tower,
283                              error_status_t *status)
284 {
285     WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status);
286 
287     *status = EPT_S_CANT_PERFORM_OP;
288 }
289