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
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 */
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
;
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
);
73 const MonikerComparisonData
*data
,
74 const InterfaceData
*obj
,
75 const InterfaceData
*mk
,
79 IrotContextHandle
*ctxt_handle
)
81 struct rot_entry
*rot_entry
;
82 struct rot_entry
*existing_rot_entry
;
85 if (grfFlags
& ~(ROTFLAGS_REGISTRATIONKEEPSALIVE
|ROTFLAGS_ALLOWANYCLIENT
))
87 WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags
& ~(ROTFLAGS_REGISTRATIONKEEPSALIVE
|ROTFLAGS_ALLOWANYCLIENT
));
91 rot_entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*rot_entry
));
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
);
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
);
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
;
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
);
164 IrotContextHandle
*ctxt_handle
,
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
)
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
]));
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
);
193 MIDL_user_free(*obj
);
198 rot_entry_release(rot_entry
);
203 LeaveCriticalSection(&csRunningObjectTable
);
208 HRESULT
IrotIsRunning(
210 const MonikerComparisonData
*data
)
212 const struct rot_entry
*rot_entry
;
213 HRESULT hr
= S_FALSE
;
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
))
228 LeaveCriticalSection(&csRunningObjectTable
);
233 HRESULT
IrotGetObject(
235 const MonikerComparisonData
*moniker_data
,
239 const struct rot_entry
*rot_entry
;
241 WINE_TRACE("%p\n", moniker_data
);
245 EnterCriticalSection(&csRunningObjectTable
);
247 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
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
]));
256 (*obj
)->ulCntData
= rot_entry
->object
->ulCntData
;
257 memcpy((*obj
)->abData
, rot_entry
->object
->abData
, (*obj
)->ulCntData
);
259 *cookie
= rot_entry
->cookie
;
264 LeaveCriticalSection(&csRunningObjectTable
);
270 LeaveCriticalSection(&csRunningObjectTable
);
272 return MK_E_UNAVAILABLE
;
275 HRESULT
IrotNoteChangeTime(
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
);
294 LeaveCriticalSection(&csRunningObjectTable
);
299 HRESULT
IrotGetTimeOfLastChange(
301 const MonikerComparisonData
*moniker_data
,
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
;
322 LeaveCriticalSection(&csRunningObjectTable
);
327 HRESULT
IrotEnumRunning(
329 PInterfaceList
*list
)
331 const struct rot_entry
*rot_entry
;
333 ULONG moniker_count
= 0;
338 EnterCriticalSection(&csRunningObjectTable
);
340 LIST_FOR_EACH_ENTRY( rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
343 *list
= MIDL_user_allocate(FIELD_OFFSET(InterfaceList
, interfaces
[moniker_count
]));
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
])
353 for (i
= 0; i
< end
; i
++)
354 MIDL_user_free((*list
)->interfaces
[i
]);
355 MIDL_user_free(*list
);
359 (*list
)->interfaces
[i
]->ulCntData
= rot_entry
->moniker
->ulCntData
;
360 memcpy((*list
)->interfaces
[i
]->abData
, rot_entry
->moniker
->abData
, rot_entry
->moniker
->ulCntData
);
367 LeaveCriticalSection(&csRunningObjectTable
);
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
);