dmsynth: Implement IDirectMusicSynth_(Download|Unload) for waves.
[wine.git] / programs / rpcss / irotp.c
blob357a7f84cd93d52e59ab467962d7e215bf42f35e
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 free(rot_entry->object);
65 free(rot_entry->moniker);
66 free(rot_entry->moniker_data);
67 free(rot_entry);
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)
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%08lx\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
88 return E_INVALIDARG;
91 if (!(rot_entry = calloc(1, sizeof(*rot_entry))))
92 return E_OUTOFMEMORY;
94 rot_entry->refs = 1;
95 rot_entry->object = malloc(FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
96 if (!rot_entry->object)
98 rot_entry_release(rot_entry);
99 return E_OUTOFMEMORY;
101 rot_entry->object->ulCntData = obj->ulCntData;
102 memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
104 rot_entry->last_modified = *time;
106 rot_entry->moniker = malloc(FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
107 if (!rot_entry->moniker)
109 rot_entry_release(rot_entry);
110 return E_OUTOFMEMORY;
112 rot_entry->moniker->ulCntData = mk->ulCntData;
113 memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
115 if (!(rot_entry->moniker_data = malloc(FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]))))
117 rot_entry_release(rot_entry);
118 return E_OUTOFMEMORY;
120 rot_entry->moniker_data->ulCntData = data->ulCntData;
121 memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
123 EnterCriticalSection(&csRunningObjectTable);
125 hr = S_OK;
127 LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
129 if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
130 !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
132 hr = MK_S_MONIKERALREADYREGISTERED;
133 WINE_TRACE("moniker already registered with cookie %ld\n", existing_rot_entry->cookie);
134 break;
138 list_add_tail(&RunningObjectTable, &rot_entry->entry);
140 LeaveCriticalSection(&csRunningObjectTable);
142 /* gives a registration identifier to the registered object*/
143 *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
144 *ctxt_handle = rot_entry;
146 return hr;
149 HRESULT __cdecl IrotRevoke(
150 IrotHandle h,
151 IrotCookie cookie,
152 IrotContextHandle *ctxt_handle,
153 PInterfaceData *obj,
154 PInterfaceData *mk)
156 struct rot_entry *rot_entry;
158 WINE_TRACE("%ld\n", cookie);
160 EnterCriticalSection(&csRunningObjectTable);
161 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
163 if (rot_entry->cookie == cookie)
165 HRESULT hr = S_OK;
167 list_remove(&rot_entry->entry);
168 LeaveCriticalSection(&csRunningObjectTable);
170 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
171 *mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
172 if (*obj && *mk)
174 (*obj)->ulCntData = rot_entry->object->ulCntData;
175 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
176 (*mk)->ulCntData = rot_entry->moniker->ulCntData;
177 memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
179 else
181 MIDL_user_free(*obj);
182 MIDL_user_free(*mk);
183 hr = E_OUTOFMEMORY;
186 rot_entry_release(rot_entry);
187 *ctxt_handle = NULL;
188 return hr;
191 LeaveCriticalSection(&csRunningObjectTable);
193 return E_INVALIDARG;
196 HRESULT __cdecl IrotIsRunning(
197 IrotHandle h,
198 const MonikerComparisonData *data)
200 const struct rot_entry *rot_entry;
201 HRESULT hr = S_FALSE;
203 WINE_TRACE("\n");
205 EnterCriticalSection(&csRunningObjectTable);
207 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
209 if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
210 !memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
212 hr = S_OK;
213 break;
216 LeaveCriticalSection(&csRunningObjectTable);
218 return hr;
221 HRESULT __cdecl IrotGetObject(
222 IrotHandle h,
223 const MonikerComparisonData *moniker_data,
224 PInterfaceData *obj,
225 IrotCookie *cookie)
227 const struct rot_entry *rot_entry;
229 WINE_TRACE("%p\n", moniker_data);
231 *cookie = 0;
233 EnterCriticalSection(&csRunningObjectTable);
235 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
237 HRESULT hr = S_OK;
238 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
239 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
241 *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
242 if (*obj)
244 (*obj)->ulCntData = rot_entry->object->ulCntData;
245 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
247 *cookie = rot_entry->cookie;
249 else
250 hr = E_OUTOFMEMORY;
252 LeaveCriticalSection(&csRunningObjectTable);
254 return hr;
258 LeaveCriticalSection(&csRunningObjectTable);
260 return MK_E_UNAVAILABLE;
263 HRESULT __cdecl IrotNoteChangeTime(
264 IrotHandle h,
265 IrotCookie cookie,
266 const FILETIME *last_modified_time)
268 struct rot_entry *rot_entry;
270 WINE_TRACE("%ld %p\n", cookie, last_modified_time);
272 EnterCriticalSection(&csRunningObjectTable);
273 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
275 if (rot_entry->cookie == cookie)
277 rot_entry->last_modified = *last_modified_time;
278 LeaveCriticalSection(&csRunningObjectTable);
279 return S_OK;
282 LeaveCriticalSection(&csRunningObjectTable);
284 return E_INVALIDARG;
287 HRESULT __cdecl IrotGetTimeOfLastChange(
288 IrotHandle h,
289 const MonikerComparisonData *moniker_data,
290 FILETIME *time)
292 const struct rot_entry *rot_entry;
293 HRESULT hr = MK_E_UNAVAILABLE;
295 WINE_TRACE("%p\n", moniker_data);
297 memset(time, 0, sizeof(*time));
299 EnterCriticalSection(&csRunningObjectTable);
300 LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
302 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
303 !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
305 *time = rot_entry->last_modified;
306 hr = S_OK;
307 break;
310 LeaveCriticalSection(&csRunningObjectTable);
312 return hr;
315 HRESULT __cdecl IrotEnumRunning(
316 IrotHandle h,
317 PInterfaceList *list)
319 const struct rot_entry *rot_entry;
320 HRESULT hr = S_OK;
321 ULONG moniker_count = 0;
322 ULONG i = 0;
324 WINE_TRACE("\n");
326 EnterCriticalSection(&csRunningObjectTable);
328 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
329 moniker_count++;
331 *list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
332 if (*list)
334 (*list)->size = moniker_count;
335 LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
337 (*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
338 if (!(*list)->interfaces[i])
340 ULONG end = i - 1;
341 for (i = 0; i < end; i++)
342 MIDL_user_free((*list)->interfaces[i]);
343 MIDL_user_free(*list);
344 hr = E_OUTOFMEMORY;
345 break;
347 (*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
348 memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
349 i++;
352 else
353 hr = E_OUTOFMEMORY;
355 LeaveCriticalSection(&csRunningObjectTable);
357 return hr;
360 void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
362 struct rot_entry *rot_entry = ctxt_handle;
363 EnterCriticalSection(&csRunningObjectTable);
364 list_remove(&rot_entry->entry);
365 LeaveCriticalSection(&csRunningObjectTable);
366 rot_entry_release(rot_entry);
369 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
371 return I_RpcAllocate(size);
374 void __RPC_USER MIDL_user_free(void * p)
376 I_RpcFree(p);