xref: /reactos/base/services/rpcss/epmp.c (revision c2c66aff)
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 "rpcss.h"
22 
23 #include <wine/debug.h>
24 
25 WINE_DEFAULT_DEBUG_CHANNEL(ole);
26 
27 struct registered_ept_entry
28 {
29     struct list entry;
30     GUID object;
31     RPC_SYNTAX_IDENTIFIER iface;
32     RPC_SYNTAX_IDENTIFIER syntax;
33     char *protseq;
34     char *endpoint;
35     char *address;
36     char annotation[ept_max_annotation_size];
37 };
38 
39 static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list);
40 
41 static CRITICAL_SECTION csEpm;
42 static CRITICAL_SECTION_DEBUG critsect_debug =
43 {
44     0, 0, &csEpm,
45     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
46     0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") }
47 };
48 static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 };
49 
50 static const UUID nil_object;
51 
52 /* must be called inside csEpm */
53 static void delete_registered_ept_entry(struct registered_ept_entry *entry)
54 {
55     I_RpcFree(entry->protseq);
56     I_RpcFree(entry->endpoint);
57     I_RpcFree(entry->address);
58     list_remove(&entry->entry);
59     HeapFree(GetProcessHeap(), 0, entry);
60 }
61 
62 static struct registered_ept_entry *find_ept_entry(
63     const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax,
64     const char *protseq, const char *endpoint, const char *address,
65     const UUID *object)
66 {
67     struct registered_ept_entry *entry;
68     LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
69     {
70         if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
71         if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue;
72         if (strcmp(entry->protseq, protseq)) continue;
73         if (memcmp(&entry->object, object, sizeof(UUID))) continue;
74 	WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n",
75                    entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion,
76                    wine_dbgstr_guid(&entry->iface.SyntaxGUID),
77                    entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion,
78                    wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq,
79                    wine_dbgstr_guid(&entry->object));
80         return entry;
81     }
82     WINE_TRACE("not found\n");
83     return NULL;
84 }
85 
86 void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle)
87 {
88     WINE_FIXME("%p\n", entry_handle);
89 }
90 
91 void __cdecl ept_insert(handle_t h,
92                         unsigned32 num_ents,
93                         ept_entry_t entries[],
94                         boolean32 replace,
95                         error_status_t *status)
96 {
97     unsigned32 i;
98     RPC_STATUS rpc_status;
99 
100     WINE_TRACE("(%p, %u, %p, %u, %p)\n", h, num_ents, entries, replace, status);
101 
102     *status = RPC_S_OK;
103 
104     EnterCriticalSection(&csEpm);
105 
106     for (i = 0; i < num_ents; i++)
107     {
108         struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
109         if (!entry)
110         {
111             /* FIXME: cleanup code to delete added entries */
112             *status = EPT_S_CANT_PERFORM_OP;
113             break;
114         }
115         memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation));
116         rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax,
117                                   &entry->protseq, &entry->endpoint,
118                                   &entry->address);
119         if (rpc_status != RPC_S_OK)
120         {
121             WINE_WARN("TowerExplode failed %u\n", rpc_status);
122             *status = rpc_status;
123             HeapFree(GetProcessHeap(), 0, entry);
124             break; /* FIXME: more cleanup? */
125         }
126 
127         entry->object = entries[i].object;
128 
129         if (replace)
130         {
131             /* FIXME: correct find algorithm */
132             struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object);
133             if (old_entry) delete_registered_ept_entry(old_entry);
134         }
135         list_add_tail(&registered_ept_entry_list, &entry->entry);
136     }
137 
138     LeaveCriticalSection(&csEpm);
139 }
140 
141 void __cdecl ept_delete(handle_t h,
142                         unsigned32 num_ents,
143                         ept_entry_t entries[],
144                         error_status_t *status)
145 {
146     unsigned32 i;
147     RPC_STATUS rpc_status;
148 
149     *status = RPC_S_OK;
150 
151     WINE_TRACE("(%p, %u, %p, %p)\n", h, num_ents, entries, status);
152 
153     EnterCriticalSection(&csEpm);
154 
155     for (i = 0; i < num_ents; i++)
156     {
157         struct registered_ept_entry *entry;
158         RPC_SYNTAX_IDENTIFIER iface, syntax;
159         char *protseq;
160         char *endpoint;
161         char *address;
162         rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq,
163                                   &endpoint, &address);
164         if (rpc_status != RPC_S_OK)
165             break;
166         entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object);
167 
168         I_RpcFree(protseq);
169         I_RpcFree(endpoint);
170         I_RpcFree(address);
171 
172         if (entry)
173             delete_registered_ept_entry(entry);
174         else
175         {
176             *status = EPT_S_NOT_REGISTERED;
177             break;
178         }
179     }
180 
181     LeaveCriticalSection(&csEpm);
182 }
183 
184 void __cdecl ept_lookup(handle_t h,
185                         unsigned32 inquiry_type,
186                         uuid_p_t object,
187                         rpc_if_id_p_t interface_id,
188                         unsigned32 vers_option,
189                         ept_lookup_handle_t *entry_handle,
190                         unsigned32 max_ents,
191                         unsigned32 *num_ents,
192                         ept_entry_t entries[],
193                         error_status_t *status)
194 {
195     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
196 
197     *status = EPT_S_CANT_PERFORM_OP;
198 }
199 
200 void __cdecl ept_map(handle_t h,
201                      uuid_p_t object,
202                      twr_p_t map_tower,
203                      ept_lookup_handle_t *entry_handle,
204                      unsigned32 max_towers,
205                      unsigned32 *num_towers,
206                      twr_p_t *towers,
207                      error_status_t *status)
208 {
209     RPC_STATUS rpc_status;
210     RPC_SYNTAX_IDENTIFIER iface, syntax;
211     char *protseq;
212     struct registered_ept_entry *entry;
213 
214     *status = RPC_S_OK;
215     *num_towers = 0;
216 
217     WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower,
218           entry_handle, max_towers, num_towers, towers, status);
219 
220     rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq,
221                               NULL, NULL);
222     if (rpc_status != RPC_S_OK)
223     {
224         *status = rpc_status;
225         return;
226     }
227 
228     EnterCriticalSection(&csEpm);
229 
230     LIST_FOR_EACH_ENTRY(entry, &registered_ept_entry_list, struct registered_ept_entry, entry)
231     {
232         if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) &&
233             (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) &&
234             (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) &&
235             !memcmp(&entry->syntax, &syntax, sizeof(syntax)) &&
236             !strcmp(entry->protseq, protseq) &&
237             ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object)))
238         {
239             if (*num_towers < max_towers)
240             {
241                 rpc_status = TowerConstruct(&entry->iface, &entry->syntax,
242                                             entry->protseq, entry->endpoint,
243                                             entry->address,
244                                             &towers[*num_towers]);
245                 if (rpc_status != RPC_S_OK)
246                 {
247                     *status = rpc_status;
248                     break; /* FIXME: more cleanup? */
249                 }
250             }
251             (*num_towers)++;
252         }
253     }
254 
255     LeaveCriticalSection(&csEpm);
256 
257     I_RpcFree(protseq);
258 }
259 
260 void __cdecl ept_lookup_handle_free(handle_t h,
261                                     ept_lookup_handle_t *entry_handle,
262                                     error_status_t *status)
263 {
264     WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status);
265 
266     *status = EPT_S_CANT_PERFORM_OP;
267 }
268 
269 void __cdecl ept_inq_object(handle_t h,
270                             GUID *ept_object,
271                             error_status_t *status)
272 {
273     WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status);
274 
275     *status = EPT_S_CANT_PERFORM_OP;
276 }
277 
278 void __cdecl ept_mgmt_delete(handle_t h,
279                              boolean32 object_speced,
280                              uuid_p_t object,
281                              twr_p_t tower,
282                              error_status_t *status)
283 {
284     WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status);
285 
286     *status = EPT_S_CANT_PERFORM_OP;
287 }
288