1 /*
2 * Running Object Table
3 *
4 * Copyright 2007 Robert Shearman
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 <stdarg.h>
22 #include <string.h>
23
24 #include "winerror.h"
25 #include "windef.h"
26 #include "winbase.h"
27
28 #include "irot_s.h"
29
30 #include "wine/list.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
34
35 /* define the structure of the running object table elements */
36 struct rot_entry
37 {
38 struct list entry;
39 InterfaceData *object; /* marshaled running object*/
40 InterfaceData *moniker; /* marshaled moniker that identifies this object */
41 MonikerComparisonData *moniker_data; /* moniker comparison data that identifies this object */
42 DWORD cookie; /* cookie identifying this object */
43 FILETIME last_modified;
44 LONG refs;
45 };
46
47 static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
48
49 static CRITICAL_SECTION csRunningObjectTable;
50 static CRITICAL_SECTION_DEBUG critsect_debug =
51 {
52 0, 0, &csRunningObjectTable,
53 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
54 0, 0, { (DWORD_PTR)(__FILE__ ": csRunningObjectTable") }
55 };
56 static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0 };
57
58 static LONG last_cookie = 1;
59
rot_entry_release(struct rot_entry * rot_entry)60 static inline void rot_entry_release(struct rot_entry *rot_entry)
61 {
62 if (!InterlockedDecrement(&rot_entry->refs))
63 {
64 HeapFree(GetProcessHeap(), 0, rot_entry->object);
65 HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
66 HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
67 HeapFree(GetProcessHeap(), 0, rot_entry);
68 }
69 }
70
IrotRegister(IrotHandle h,const MonikerComparisonData * data,const InterfaceData * obj,const InterfaceData * mk,const FILETIME * time,DWORD grfFlags,IrotCookie * cookie,IrotContextHandle * ctxt_handle)71 HRESULT __cdecl IrotRegister(
72 IrotHandle h,
73 const MonikerComparisonData *data,
74 const InterfaceData *obj,
75 const InterfaceData *mk,
76 const FILETIME *time,
77 DWORD grfFlags,
78 IrotCookie *cookie,
79 IrotContextHandle *ctxt_handle)
80 {
81 struct rot_entry *rot_entry;
82 struct rot_entry *existing_rot_entry;
83 HRESULT hr;
84
85 if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
86 {
87 WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
88 return E_INVALIDARG;
89 }
90
91 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
92 if (!rot_entry)
93 return E_OUTOFMEMORY;
94
95 rot_entry->refs = 1;
96 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
97 if (!rot_entry->object)
98 {
99 rot_entry_release(rot_entry);
100 return E_OUTOFMEMORY;
101 }
102 rot_entry->object->ulCntData = obj->ulCntData;
103 memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
104
105 rot_entry->last_modified = *time;
106
107 rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
108 if (!rot_entry->moniker)
109 {
110 rot_entry_release(rot_entry);
111 return E_OUTOFMEMORY;
112 }
113 rot_entry->moniker->ulCntData = mk->ulCntData;
114 memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
115
116 rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
117 if (!rot_entry->moniker_data)
118 {
119 rot_entry_release(rot_entry);
120 return E_OUTOFMEMORY;
121 }
122 rot_entry->moniker_data->ulCntData = data->ulCntData;
123 memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
124
125 EnterCriticalSection(&csRunningObjectTable);
126
127 hr = S_OK;
128
129 LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
130 {
131 if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
132 !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
133 {
134 hr = MK_S_MONIKERALREADYREGISTERED;
135 WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry->cookie);
136 break;
137 }
138 }
139
140 list_add_tail(&RunningObjectTable, &rot_entry->entry);
141
142 LeaveCriticalSection(&csRunningObjectTable);
143
144 /* gives a registration identifier to the registered object*/
145 *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
146 *ctxt_handle = rot_entry;
147
148 return hr;
149 }
150
IrotRevoke(IrotHandle h,IrotCookie cookie,IrotContextHandle * ctxt_handle,PInterfaceData * obj,PInterfaceData * mk)151 HRESULT __cdecl IrotRevoke(
152 IrotHandle h,
153 IrotCookie cookie,
154 IrotContextHandle *ctxt_handle,
155 PInterfaceData *obj,
156 PInterfaceData *mk)
157 {
158 struct rot_entry *rot_entry;
159
160 WINE_TRACE("%d\n", cookie);
161
162 EnterCriticalSection(&csRunningObjectTable);
163 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
164 {
165 if (rot_entry->cookie == cookie)
166 {
167 HRESULT hr = S_OK;
168
169 list_remove(&rot_entry->entry);
170 LeaveCriticalSection(&csRunningObjectTable);
171
172 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
173 *mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
174 if (*obj && *mk)
175 {
176 (*obj)->ulCntData = rot_entry->object->ulCntData;
177 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
178 (*mk)->ulCntData = rot_entry->moniker->ulCntData;
179 memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
180 }
181 else
182 {
183 MIDL_user_free(*obj);
184 MIDL_user_free(*mk);
185 hr = E_OUTOFMEMORY;
186 }
187
188 rot_entry_release(rot_entry);
189 *ctxt_handle = NULL;
190 return hr;
191 }
192 }
193 LeaveCriticalSection(&csRunningObjectTable);
194
195 return E_INVALIDARG;
196 }
197
IrotIsRunning(IrotHandle h,const MonikerComparisonData * data)198 HRESULT __cdecl IrotIsRunning(
199 IrotHandle h,
200 const MonikerComparisonData *data)
201 {
202 const struct rot_entry *rot_entry;
203 HRESULT hr = S_FALSE;
204
205 WINE_TRACE("\n");
206
207 EnterCriticalSection(&csRunningObjectTable);
208
209 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
210 {
211 if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
212 !memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
213 {
214 hr = S_OK;
215 break;
216 }
217 }
218 LeaveCriticalSection(&csRunningObjectTable);
219
220 return hr;
221 }
222
IrotGetObject(IrotHandle h,const MonikerComparisonData * moniker_data,PInterfaceData * obj,IrotCookie * cookie)223 HRESULT __cdecl IrotGetObject(
224 IrotHandle h,
225 const MonikerComparisonData *moniker_data,
226 PInterfaceData *obj,
227 IrotCookie *cookie)
228 {
229 const struct rot_entry *rot_entry;
230
231 WINE_TRACE("%p\n", moniker_data);
232
233 *cookie = 0;
234
235 EnterCriticalSection(&csRunningObjectTable);
236
237 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
238 {
239 HRESULT hr = S_OK;
240 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
241 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
242 {
243 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
244 if (*obj)
245 {
246 (*obj)->ulCntData = rot_entry->object->ulCntData;
247 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
248
249 *cookie = rot_entry->cookie;
250 }
251 else
252 hr = E_OUTOFMEMORY;
253
254 LeaveCriticalSection(&csRunningObjectTable);
255
256 return hr;
257 }
258 }
259
260 LeaveCriticalSection(&csRunningObjectTable);
261
262 return MK_E_UNAVAILABLE;
263 }
264
IrotNoteChangeTime(IrotHandle h,IrotCookie cookie,const FILETIME * last_modified_time)265 HRESULT __cdecl IrotNoteChangeTime(
266 IrotHandle h,
267 IrotCookie cookie,
268 const FILETIME *last_modified_time)
269 {
270 struct rot_entry *rot_entry;
271
272 WINE_TRACE("%d %p\n", cookie, last_modified_time);
273
274 EnterCriticalSection(&csRunningObjectTable);
275 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
276 {
277 if (rot_entry->cookie == cookie)
278 {
279 rot_entry->last_modified = *last_modified_time;
280 LeaveCriticalSection(&csRunningObjectTable);
281 return S_OK;
282 }
283 }
284 LeaveCriticalSection(&csRunningObjectTable);
285
286 return E_INVALIDARG;
287 }
288
IrotGetTimeOfLastChange(IrotHandle h,const MonikerComparisonData * moniker_data,FILETIME * time)289 HRESULT __cdecl IrotGetTimeOfLastChange(
290 IrotHandle h,
291 const MonikerComparisonData *moniker_data,
292 FILETIME *time)
293 {
294 const struct rot_entry *rot_entry;
295 HRESULT hr = MK_E_UNAVAILABLE;
296
297 WINE_TRACE("%p\n", moniker_data);
298
299 memset(time, 0, sizeof(*time));
300
301 EnterCriticalSection(&csRunningObjectTable);
302 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
303 {
304 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
305 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
306 {
307 *time = rot_entry->last_modified;
308 hr = S_OK;
309 break;
310 }
311 }
312 LeaveCriticalSection(&csRunningObjectTable);
313
314 return hr;
315 }
316
IrotEnumRunning(IrotHandle h,PInterfaceList * list)317 HRESULT __cdecl IrotEnumRunning(
318 IrotHandle h,
319 PInterfaceList *list)
320 {
321 const struct rot_entry *rot_entry;
322 HRESULT hr = S_OK;
323 ULONG moniker_count = 0;
324 ULONG i = 0;
325
326 WINE_TRACE("\n");
327
328 EnterCriticalSection(&csRunningObjectTable);
329
330 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
331 moniker_count++;
332
333 *list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
334 if (*list)
335 {
336 (*list)->size = moniker_count;
337 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
338 {
339 (*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
340 if (!(*list)->interfaces[i])
341 {
342 ULONG end = i - 1;
343 for (i = 0; i < end; i++)
344 MIDL_user_free((*list)->interfaces[i]);
345 MIDL_user_free(*list);
346 hr = E_OUTOFMEMORY;
347 break;
348 }
349 (*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
350 memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
351 i++;
352 }
353 }
354 else
355 hr = E_OUTOFMEMORY;
356
357 LeaveCriticalSection(&csRunningObjectTable);
358
359 return hr;
360 }
361
IrotContextHandle_rundown(IrotContextHandle ctxt_handle)362 void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
363 {
364 struct rot_entry *rot_entry = ctxt_handle;
365 EnterCriticalSection(&csRunningObjectTable);
366 list_remove(&rot_entry->entry);
367 LeaveCriticalSection(&csRunningObjectTable);
368 rot_entry_release(rot_entry);
369 }
370
MIDL_user_allocate(SIZE_T size)371 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
372 {
373 return HeapAlloc(GetProcessHeap(), 0, size);
374 }
375
MIDL_user_free(void * p)376 void __RPC_USER MIDL_user_free(void * p)
377 {
378 HeapFree(GetProcessHeap(), 0, p);
379 }
380