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