irotp.c 11 KB

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