winex11: Move handling of WM_STATE changes to a separate function, and call it direct...
[wine.git] / programs / rpcss / irotp.c
blob21ede3201d18af9c0e99bd1e3abf16a9ad6e5b55
1 /*
2 * Running Object Table
4 * Copyright 2007 Robert Shearman
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.
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.
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
21 #include <stdarg.h>
22 #include <string.h>
24 #include "winerror.h"
25 #include "windef.h"
26 #include "winbase.h"
28 #include "irot.h"
30 #include "wine/list.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
35 /* define the structure of the running object table elements */
36 struct rot_entry
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;
47 static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
49 static CRITICAL_SECTION csRunningObjectTable;
50 static CRITICAL_SECTION_DEBUG critsect_debug =
52 0, 0, &csRunningObjectTable,
53 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
54 0, 0, { (DWORD_PTR)(__FILE__ ": csRunningObjectTable") }
56 static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0 };
58 static LONG last_cookie = 1;
60 static inline void rot_entry_release(struct rot_entry *rot_entry)
62 if (!InterlockedDecrement(&rot_entry->refs))
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);
71 HRESULT 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)
81 struct rot_entry *rot_entry;
82 struct rot_entry *existing_rot_entry;
83 HRESULT hr;
85 if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
87 WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
88 return E_INVALIDARG;
91 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
92 if (!rot_entry)
93 return E_OUTOFMEMORY;
95 rot_entry->refs = 1;
96 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
97 if (!rot_entry->object)
99 rot_entry_release(rot_entry);
100 return E_OUTOFMEMORY;
102 rot_entry->object->ulCntData = obj->ulCntData;
103 memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
105 rot_entry->last_modified = *time;
107 rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
108 if (!rot_entry->moniker)
110 rot_entry_release(rot_entry);
111 return E_OUTOFMEMORY;
113 rot_entry->moniker->ulCntData = mk->ulCntData;
114 memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
116 rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
117 if (!rot_entry->moniker_data)
119 rot_entry_release(rot_entry);
120 return E_OUTOFMEMORY;
122 rot_entry->moniker_data->ulCntData = data->ulCntData;
123 memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
125 EnterCriticalSection(&csRunningObjectTable);
127 hr = S_OK;
129 LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
131 if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
132 !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
134 hr = MK_S_MONIKERALREADYREGISTERED;
135 WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry->cookie);
136 break;
140 if (hr == S_OK)
142 list_add_tail(&RunningObjectTable, &rot_entry->entry);
143 /* gives a registration identifier to the registered object*/
144 *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
145 *ctxt_handle = rot_entry;
147 else
149 rot_entry_release(rot_entry);
150 *cookie = existing_rot_entry->cookie;
151 InterlockedIncrement(&existing_rot_entry->refs);
152 *ctxt_handle = existing_rot_entry;
156 LeaveCriticalSection(&csRunningObjectTable);
158 return hr;
161 HRESULT IrotRevoke(
162 IrotHandle h,
163 IrotCookie cookie,
164 IrotContextHandle *ctxt_handle,
165 PInterfaceData *obj,
166 PInterfaceData *mk)
168 struct rot_entry *rot_entry;
170 WINE_TRACE("%d\n", cookie);
172 EnterCriticalSection(&csRunningObjectTable);
173 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
175 if (rot_entry->cookie == cookie)
177 HRESULT hr = S_OK;
179 list_remove(&rot_entry->entry);
180 LeaveCriticalSection(&csRunningObjectTable);
182 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
183 *mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
184 if (*obj && *mk)
186 (*obj)->ulCntData = rot_entry->object->ulCntData;
187 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
188 (*mk)->ulCntData = rot_entry->moniker->ulCntData;
189 memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
191 else
193 MIDL_user_free(*obj);
194 MIDL_user_free(*mk);
195 hr = E_OUTOFMEMORY;
198 rot_entry_release(rot_entry);
199 *ctxt_handle = NULL;
200 return hr;
203 LeaveCriticalSection(&csRunningObjectTable);
205 return E_INVALIDARG;
208 HRESULT IrotIsRunning(
209 IrotHandle h,
210 const MonikerComparisonData *data)
212 const struct rot_entry *rot_entry;
213 HRESULT hr = S_FALSE;
215 WINE_TRACE("\n");
217 EnterCriticalSection(&csRunningObjectTable);
219 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
221 if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
222 !memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
224 hr = S_OK;
225 break;
228 LeaveCriticalSection(&csRunningObjectTable);
230 return hr;
233 HRESULT IrotGetObject(
234 IrotHandle h,
235 const MonikerComparisonData *moniker_data,
236 PInterfaceData *obj,
237 IrotCookie *cookie)
239 const struct rot_entry *rot_entry;
241 WINE_TRACE("%p\n", moniker_data);
243 *cookie = 0;
245 EnterCriticalSection(&csRunningObjectTable);
247 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
249 HRESULT hr = S_OK;
250 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
251 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
253 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
254 if (*obj)
256 (*obj)->ulCntData = rot_entry->object->ulCntData;
257 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
259 *cookie = rot_entry->cookie;
261 else
262 hr = E_OUTOFMEMORY;
264 LeaveCriticalSection(&csRunningObjectTable);
266 return hr;
270 LeaveCriticalSection(&csRunningObjectTable);
272 return MK_E_UNAVAILABLE;
275 HRESULT IrotNoteChangeTime(
276 IrotHandle h,
277 IrotCookie cookie,
278 const FILETIME *last_modified_time)
280 struct rot_entry *rot_entry;
282 WINE_TRACE("%d %p\n", cookie, last_modified_time);
284 EnterCriticalSection(&csRunningObjectTable);
285 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
287 if (rot_entry->cookie == cookie)
289 rot_entry->last_modified = *last_modified_time;
290 LeaveCriticalSection(&csRunningObjectTable);
291 return S_OK;
294 LeaveCriticalSection(&csRunningObjectTable);
296 return E_INVALIDARG;
299 HRESULT IrotGetTimeOfLastChange(
300 IrotHandle h,
301 const MonikerComparisonData *moniker_data,
302 FILETIME *time)
304 const struct rot_entry *rot_entry;
305 HRESULT hr = MK_E_UNAVAILABLE;
307 WINE_TRACE("%p\n", moniker_data);
309 memset(time, 0, sizeof(*time));
311 EnterCriticalSection(&csRunningObjectTable);
312 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
314 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
315 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
317 *time = rot_entry->last_modified;
318 hr = S_OK;
319 break;
322 LeaveCriticalSection(&csRunningObjectTable);
324 return hr;
327 HRESULT IrotEnumRunning(
328 IrotHandle h,
329 PInterfaceList *list)
331 const struct rot_entry *rot_entry;
332 HRESULT hr = S_OK;
333 ULONG moniker_count = 0;
334 ULONG i = 0;
336 WINE_TRACE("\n");
338 EnterCriticalSection(&csRunningObjectTable);
340 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
341 moniker_count++;
343 *list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
344 if (*list)
346 (*list)->size = moniker_count;
347 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
349 (*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
350 if (!(*list)->interfaces[i])
352 ULONG end = i - 1;
353 for (i = 0; i < end; i++)
354 MIDL_user_free((*list)->interfaces[i]);
355 MIDL_user_free(*list);
356 hr = E_OUTOFMEMORY;
357 break;
359 (*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
360 memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
361 i++;
364 else
365 hr = E_OUTOFMEMORY;
367 LeaveCriticalSection(&csRunningObjectTable);
369 return hr;
372 void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
374 struct rot_entry *rot_entry = ctxt_handle;
375 EnterCriticalSection(&csRunningObjectTable);
376 list_remove(&rot_entry->entry);
377 LeaveCriticalSection(&csRunningObjectTable);
378 rot_entry_release(rot_entry);
381 void * __RPC_USER MIDL_user_allocate(size_t size)
383 return HeapAlloc(GetProcessHeap(), 0, size);
386 void __RPC_USER MIDL_user_free(void * p)
388 HeapFree(GetProcessHeap(), 0, p);