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
23 #include <wine/debug.h>
25 WINE_DEFAULT_DEBUG_CHANNEL(rpcss
);
27 /* define the structure of the running object table elements */
31 InterfaceData
*object
; /* marshaled running object*/
32 InterfaceData
*moniker
; /* marshaled moniker that identifies this object */
33 MonikerComparisonData
*moniker_data
; /* moniker comparison data that identifies this object */
34 DWORD cookie
; /* cookie identifying this object */
35 FILETIME last_modified
;
39 static struct list RunningObjectTable
= LIST_INIT(RunningObjectTable
);
41 static CRITICAL_SECTION csRunningObjectTable
;
42 static CRITICAL_SECTION_DEBUG critsect_debug
=
44 0, 0, &csRunningObjectTable
,
45 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
46 0, 0, { (DWORD_PTR
)(__FILE__
": csRunningObjectTable") }
48 static CRITICAL_SECTION csRunningObjectTable
= { &critsect_debug
, -1, 0, 0, 0, 0 };
50 static LONG last_cookie
= 1;
52 static inline void rot_entry_release(struct rot_entry
*rot_entry
)
54 if (!InterlockedDecrement(&rot_entry
->refs
))
56 HeapFree(GetProcessHeap(), 0, rot_entry
->object
);
57 HeapFree(GetProcessHeap(), 0, rot_entry
->moniker
);
58 HeapFree(GetProcessHeap(), 0, rot_entry
->moniker_data
);
59 HeapFree(GetProcessHeap(), 0, rot_entry
);
63 HRESULT __cdecl
IrotRegister(
65 const MonikerComparisonData
*data
,
66 const InterfaceData
*obj
,
67 const InterfaceData
*mk
,
71 IrotContextHandle
*ctxt_handle
)
73 struct rot_entry
*rot_entry
;
74 struct rot_entry
*existing_rot_entry
;
77 if (grfFlags
& ~(ROTFLAGS_REGISTRATIONKEEPSALIVE
|ROTFLAGS_ALLOWANYCLIENT
))
79 WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags
& ~(ROTFLAGS_REGISTRATIONKEEPSALIVE
|ROTFLAGS_ALLOWANYCLIENT
));
83 rot_entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*rot_entry
));
88 rot_entry
->object
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData
, abData
[obj
->ulCntData
]));
89 if (!rot_entry
->object
)
91 rot_entry_release(rot_entry
);
94 rot_entry
->object
->ulCntData
= obj
->ulCntData
;
95 memcpy(&rot_entry
->object
->abData
, obj
->abData
, obj
->ulCntData
);
97 rot_entry
->last_modified
= *time
;
99 rot_entry
->moniker
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData
, abData
[mk
->ulCntData
]));
100 if (!rot_entry
->moniker
)
102 rot_entry_release(rot_entry
);
103 return E_OUTOFMEMORY
;
105 rot_entry
->moniker
->ulCntData
= mk
->ulCntData
;
106 memcpy(&rot_entry
->moniker
->abData
, mk
->abData
, mk
->ulCntData
);
108 rot_entry
->moniker_data
= HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData
, abData
[data
->ulCntData
]));
109 if (!rot_entry
->moniker_data
)
111 rot_entry_release(rot_entry
);
112 return E_OUTOFMEMORY
;
114 rot_entry
->moniker_data
->ulCntData
= data
->ulCntData
;
115 memcpy(&rot_entry
->moniker_data
->abData
, data
->abData
, data
->ulCntData
);
117 EnterCriticalSection(&csRunningObjectTable
);
121 LIST_FOR_EACH_ENTRY(existing_rot_entry
, &RunningObjectTable
, struct rot_entry
, entry
)
123 if ((existing_rot_entry
->moniker_data
->ulCntData
== data
->ulCntData
) &&
124 !memcmp(&data
->abData
, &existing_rot_entry
->moniker_data
->abData
, data
->ulCntData
))
126 hr
= MK_S_MONIKERALREADYREGISTERED
;
127 WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry
->cookie
);
132 list_add_tail(&RunningObjectTable
, &rot_entry
->entry
);
134 LeaveCriticalSection(&csRunningObjectTable
);
136 /* gives a registration identifier to the registered object*/
137 *cookie
= rot_entry
->cookie
= InterlockedIncrement(&last_cookie
);
138 *ctxt_handle
= rot_entry
;
143 HRESULT __cdecl
IrotRevoke(
146 IrotContextHandle
*ctxt_handle
,
150 struct rot_entry
*rot_entry
;
152 WINE_TRACE("%d\n", cookie
);
154 EnterCriticalSection(&csRunningObjectTable
);
155 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, struct rot_entry
, entry
)
157 if (rot_entry
->cookie
== cookie
)
161 list_remove(&rot_entry
->entry
);
162 LeaveCriticalSection(&csRunningObjectTable
);
164 *obj
= MIDL_user_allocate(FIELD_OFFSET(InterfaceData
, abData
[rot_entry
->object
->ulCntData
]));
165 *mk
= MIDL_user_allocate(FIELD_OFFSET(InterfaceData
, abData
[rot_entry
->moniker
->ulCntData
]));
168 (*obj
)->ulCntData
= rot_entry
->object
->ulCntData
;
169 memcpy((*obj
)->abData
, rot_entry
->object
->abData
, (*obj
)->ulCntData
);
170 (*mk
)->ulCntData
= rot_entry
->moniker
->ulCntData
;
171 memcpy((*mk
)->abData
, rot_entry
->moniker
->abData
, (*mk
)->ulCntData
);
175 MIDL_user_free(*obj
);
180 rot_entry_release(rot_entry
);
185 LeaveCriticalSection(&csRunningObjectTable
);
190 HRESULT __cdecl
IrotIsRunning(
192 const MonikerComparisonData
*data
)
194 const struct rot_entry
*rot_entry
;
195 HRESULT hr
= S_FALSE
;
199 EnterCriticalSection(&csRunningObjectTable
);
201 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
203 if ((rot_entry
->moniker_data
->ulCntData
== data
->ulCntData
) &&
204 !memcmp(&data
->abData
, &rot_entry
->moniker_data
->abData
, data
->ulCntData
))
210 LeaveCriticalSection(&csRunningObjectTable
);
215 HRESULT __cdecl
IrotGetObject(
217 const MonikerComparisonData
*moniker_data
,
221 const struct rot_entry
*rot_entry
;
223 WINE_TRACE("%p\n", moniker_data
);
227 EnterCriticalSection(&csRunningObjectTable
);
229 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
232 if ((rot_entry
->moniker_data
->ulCntData
== moniker_data
->ulCntData
) &&
233 !memcmp(&moniker_data
->abData
, &rot_entry
->moniker_data
->abData
, moniker_data
->ulCntData
))
235 *obj
= MIDL_user_allocate(FIELD_OFFSET(InterfaceData
, abData
[rot_entry
->object
->ulCntData
]));
238 (*obj
)->ulCntData
= rot_entry
->object
->ulCntData
;
239 memcpy((*obj
)->abData
, rot_entry
->object
->abData
, (*obj
)->ulCntData
);
241 *cookie
= rot_entry
->cookie
;
246 LeaveCriticalSection(&csRunningObjectTable
);
252 LeaveCriticalSection(&csRunningObjectTable
);
254 return MK_E_UNAVAILABLE
;
257 HRESULT __cdecl
IrotNoteChangeTime(
260 const FILETIME
*last_modified_time
)
262 struct rot_entry
*rot_entry
;
264 WINE_TRACE("%d %p\n", cookie
, last_modified_time
);
266 EnterCriticalSection(&csRunningObjectTable
);
267 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, struct rot_entry
, entry
)
269 if (rot_entry
->cookie
== cookie
)
271 rot_entry
->last_modified
= *last_modified_time
;
272 LeaveCriticalSection(&csRunningObjectTable
);
276 LeaveCriticalSection(&csRunningObjectTable
);
281 HRESULT __cdecl
IrotGetTimeOfLastChange(
283 const MonikerComparisonData
*moniker_data
,
286 const struct rot_entry
*rot_entry
;
287 HRESULT hr
= MK_E_UNAVAILABLE
;
289 WINE_TRACE("%p\n", moniker_data
);
291 memset(time
, 0, sizeof(*time
));
293 EnterCriticalSection(&csRunningObjectTable
);
294 LIST_FOR_EACH_ENTRY(rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
296 if ((rot_entry
->moniker_data
->ulCntData
== moniker_data
->ulCntData
) &&
297 !memcmp(&moniker_data
->abData
, &rot_entry
->moniker_data
->abData
, moniker_data
->ulCntData
))
299 *time
= rot_entry
->last_modified
;
304 LeaveCriticalSection(&csRunningObjectTable
);
309 HRESULT __cdecl
IrotEnumRunning(
311 PInterfaceList
*list
)
313 const struct rot_entry
*rot_entry
;
315 ULONG moniker_count
= 0;
320 EnterCriticalSection(&csRunningObjectTable
);
322 LIST_FOR_EACH_ENTRY( rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
325 *list
= MIDL_user_allocate(FIELD_OFFSET(InterfaceList
, interfaces
[moniker_count
]));
328 (*list
)->size
= moniker_count
;
329 LIST_FOR_EACH_ENTRY( rot_entry
, &RunningObjectTable
, const struct rot_entry
, entry
)
331 (*list
)->interfaces
[i
] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData
, abData
[rot_entry
->moniker
->ulCntData
]));
332 if (!(*list
)->interfaces
[i
])
335 for (i
= 0; i
< end
; i
++)
336 MIDL_user_free((*list
)->interfaces
[i
]);
337 MIDL_user_free(*list
);
341 (*list
)->interfaces
[i
]->ulCntData
= rot_entry
->moniker
->ulCntData
;
342 memcpy((*list
)->interfaces
[i
]->abData
, rot_entry
->moniker
->abData
, rot_entry
->moniker
->ulCntData
);
349 LeaveCriticalSection(&csRunningObjectTable
);
354 void __RPC_USER
IrotContextHandle_rundown(IrotContextHandle ctxt_handle
)
356 struct rot_entry
*rot_entry
= ctxt_handle
;
357 EnterCriticalSection(&csRunningObjectTable
);
358 list_remove(&rot_entry
->entry
);
359 LeaveCriticalSection(&csRunningObjectTable
);
360 rot_entry_release(rot_entry
);
363 void * __RPC_USER
MIDL_user_allocate(SIZE_T size
)
365 return HeapAlloc(GetProcessHeap(), 0, size
);
368 void __RPC_USER
MIDL_user_free(void * p
)
370 HeapFree(GetProcessHeap(), 0, p
);