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