[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[reactos.git] / base / services / rpcss / epmp.c
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 }