usrmarshal.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. /*
  2. * Misc marshalling routines
  3. *
  4. * Copyright 2002 Ove Kaaven
  5. * Copyright 2003 Mike Hearn
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <stdarg.h>
  22. #include <string.h>
  23. #define COBJMACROS
  24. #define NONAMELESSUNION
  25. #define NONAMELESSSTRUCT
  26. #include "windef.h"
  27. #include "winbase.h"
  28. #include "wingdi.h"
  29. #include "winuser.h"
  30. #include "winerror.h"
  31. #include "ole2.h"
  32. #include "oleauto.h"
  33. #include "rpcproxy.h"
  34. #include "wine/debug.h"
  35. WINE_DEFAULT_DEBUG_CHANNEL(ole);
  36. /* FIXME: not supposed to be here */
  37. const CLSID CLSID_PSDispatch = {
  38. 0x20420, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
  39. };
  40. static CStdPSFactoryBuffer PSFactoryBuffer;
  41. CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer)
  42. extern const ExtendedProxyFileInfo oaidl_ProxyFileInfo;
  43. const ProxyFileInfo* OLEAUT32_ProxyFileList[] = {
  44. &oaidl_ProxyFileInfo,
  45. NULL
  46. };
  47. HRESULT OLEAUTPS_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
  48. {
  49. return NdrDllGetClassObject(rclsid, riid, ppv, OLEAUT32_ProxyFileList,
  50. &CLSID_PSDispatch, &PSFactoryBuffer);
  51. }
  52. /* CLEANLOCALSTORAGE */
  53. /* I'm not sure how this is supposed to work yet */
  54. unsigned long WINAPI CLEANLOCALSTORAGE_UserSize(unsigned long *pFlags, unsigned long Start, CLEANLOCALSTORAGE *pstg)
  55. {
  56. return Start + sizeof(DWORD);
  57. }
  58. unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg)
  59. {
  60. *(DWORD*)Buffer = 0;
  61. return Buffer + sizeof(DWORD);
  62. }
  63. unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr)
  64. {
  65. return Buffer + sizeof(DWORD);
  66. }
  67. void WINAPI CLEANLOCALSTORAGE_UserFree(unsigned long *pFlags, CLEANLOCALSTORAGE *pstr)
  68. {
  69. }
  70. /* BSTR */
  71. unsigned long WINAPI BSTR_UserSize(unsigned long *pFlags, unsigned long Start, BSTR *pstr)
  72. {
  73. TRACE("(%lx,%ld,%p) => %p\n", *pFlags, Start, pstr, *pstr);
  74. if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
  75. Start += sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (SysStringLen(*pstr) - 1);
  76. TRACE("returning %ld\n", Start);
  77. return Start;
  78. }
  79. unsigned char * WINAPI BSTR_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
  80. {
  81. wireBSTR str = (wireBSTR)Buffer;
  82. TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
  83. if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
  84. str->fFlags = 0;
  85. str->clSize = SysStringLen(*pstr);
  86. if (str->clSize)
  87. memcpy(&str->asData, *pstr, sizeof(OLECHAR) * str->clSize);
  88. return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
  89. }
  90. unsigned char * WINAPI BSTR_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, BSTR *pstr)
  91. {
  92. wireBSTR str = (wireBSTR)Buffer;
  93. TRACE("(%lx,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr);
  94. if (str->clSize) {
  95. SysReAllocStringLen(pstr, (OLECHAR*)&str->asData, str->clSize);
  96. }
  97. else if (*pstr) {
  98. SysFreeString(*pstr);
  99. *pstr = NULL;
  100. }
  101. if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr));
  102. return Buffer + sizeof(FLAGGED_WORD_BLOB) + sizeof(OLECHAR) * (str->clSize - 1);
  103. }
  104. void WINAPI BSTR_UserFree(unsigned long *pFlags, BSTR *pstr)
  105. {
  106. TRACE("(%lx,%p) => %p\n", *pFlags, pstr, *pstr);
  107. if (*pstr) {
  108. SysFreeString(*pstr);
  109. *pstr = NULL;
  110. }
  111. }
  112. /* VARIANT */
  113. /* I'm not too sure how to do this yet */
  114. #define VARIANT_wiresize sizeof(struct _wireVARIANT)
  115. static unsigned wire_size(VARTYPE vt)
  116. {
  117. if (vt & VT_ARRAY) return 0;
  118. switch (vt & ~VT_BYREF) {
  119. case VT_EMPTY:
  120. case VT_NULL:
  121. return 0;
  122. case VT_I1:
  123. case VT_UI1:
  124. return sizeof(CHAR);
  125. case VT_I2:
  126. case VT_UI2:
  127. return sizeof(SHORT);
  128. case VT_I4:
  129. case VT_UI4:
  130. return sizeof(LONG);
  131. case VT_INT:
  132. case VT_UINT:
  133. return sizeof(INT);
  134. case VT_R4:
  135. return sizeof(FLOAT);
  136. case VT_R8:
  137. return sizeof(DOUBLE);
  138. case VT_BOOL:
  139. return sizeof(VARIANT_BOOL);
  140. case VT_ERROR:
  141. return sizeof(SCODE);
  142. case VT_DATE:
  143. return sizeof(DATE);
  144. case VT_CY:
  145. return sizeof(CY);
  146. case VT_DECIMAL:
  147. return sizeof(DECIMAL);
  148. case VT_BSTR:
  149. case VT_VARIANT:
  150. case VT_UNKNOWN:
  151. case VT_DISPATCH:
  152. case VT_SAFEARRAY:
  153. case VT_RECORD:
  154. return 0;
  155. default:
  156. FIXME("unhandled VT %d\n", vt);
  157. return 0;
  158. }
  159. }
  160. static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
  161. {
  162. ULONG size;
  163. HRESULT hr;
  164. if (V_VT(pvar) & VT_ARRAY) {
  165. FIXME("wire-size safearray\n");
  166. return 0;
  167. }
  168. switch (V_VT(pvar)) {
  169. case VT_BSTR:
  170. return BSTR_UserSize(pFlags, 0, &V_BSTR(pvar));
  171. case VT_BSTR | VT_BYREF:
  172. return BSTR_UserSize(pFlags, 0, V_BSTRREF(pvar));
  173. case VT_SAFEARRAY:
  174. case VT_SAFEARRAY | VT_BYREF:
  175. FIXME("wire-size safearray\n");
  176. return 0;
  177. case VT_VARIANT | VT_BYREF:
  178. return VARIANT_UserSize(pFlags, 0, V_VARIANTREF(pvar));
  179. case VT_UNKNOWN:
  180. case VT_DISPATCH:
  181. /* find the buffer size of the marshalled dispatch interface */
  182. hr = CoGetMarshalSizeMax(&size, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
  183. if (FAILED(hr)) {
  184. ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%lx\n", hr);
  185. return 0;
  186. }
  187. size += sizeof(ULONG); /* we have to store the buffersize in the stream */
  188. TRACE("wire-size extra of dispatch variant is %ld\n", size);
  189. return size;
  190. case VT_RECORD:
  191. FIXME("wire-size record\n");
  192. return 0;
  193. default:
  194. return 0;
  195. }
  196. }
  197. /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer. returns Buffer on failure, new position otherwise */
  198. static unsigned char* dispatch_variant_marshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) {
  199. IStream *working;
  200. HGLOBAL working_mem;
  201. void *working_memlocked;
  202. unsigned char *oldpos;
  203. ULONG size;
  204. HRESULT hr;
  205. TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
  206. oldpos = Buffer;
  207. /* CoMarshalInterface needs a stream, whereas at this level we are operating in terms of buffers.
  208. * We create a stream on an HGLOBAL, so we can simply do a memcpy to move it to the buffer.
  209. * in rpcrt4/ndr_ole.c, a simple IStream implementation is wrapped around the buffer object,
  210. * but that would be overkill here, hence this implementation. We save the size because the unmarshal
  211. * code has no way to know how long the marshalled buffer is. */
  212. size = wire_extra(pFlags, pvar);
  213. working_mem = GlobalAlloc(0, size);
  214. if (!working_mem) return oldpos;
  215. hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
  216. if (hr != S_OK) {
  217. GlobalFree(working_mem);
  218. return oldpos;
  219. }
  220. hr = CoMarshalInterface(working, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
  221. if (hr != S_OK) {
  222. IStream_Release(working); /* this also releases the hglobal */
  223. return oldpos;
  224. }
  225. working_memlocked = GlobalLock(working_mem);
  226. memcpy(Buffer, &size, sizeof(ULONG)); /* copy the buffersize */
  227. Buffer += sizeof(ULONG);
  228. memcpy(Buffer, working_memlocked, size);
  229. GlobalUnlock(working_mem);
  230. IStream_Release(working);
  231. TRACE("done, size=%ld\n", sizeof(ULONG) + size);
  232. return Buffer + sizeof(ULONG) + size;
  233. }
  234. /* helper: called for VT_DISPATCH variants to unmarshal the buffer back into a dispatch variant. returns Buffer on failure, new position otherwise */
  235. static unsigned char *dispatch_variant_unmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar) {
  236. IStream *working;
  237. HGLOBAL working_mem;
  238. void *working_memlocked;
  239. unsigned char *oldpos;
  240. ULONG size;
  241. HRESULT hr;
  242. TRACE("pFlags=%ld, Buffer=%p, pvar=%p\n", *pFlags, Buffer, pvar);
  243. oldpos = Buffer;
  244. /* get the buffersize */
  245. memcpy(&size, Buffer, sizeof(ULONG));
  246. TRACE("buffersize=%ld\n", size);
  247. Buffer += sizeof(ULONG);
  248. working_mem = GlobalAlloc(0, size);
  249. if (!working_mem) return oldpos;
  250. hr = CreateStreamOnHGlobal(working_mem, TRUE, &working);
  251. if (hr != S_OK) {
  252. GlobalFree(working_mem);
  253. return oldpos;
  254. }
  255. working_memlocked = GlobalLock(working_mem);
  256. /* now we copy the contents of the marshalling buffer to working_memlocked, unlock it, and demarshal the stream */
  257. memcpy(working_memlocked, Buffer, size);
  258. GlobalUnlock(working_mem);
  259. hr = CoUnmarshalInterface(working, &IID_IDispatch, (void**)&V_DISPATCH(pvar));
  260. if (hr != S_OK) {
  261. IStream_Release(working);
  262. return oldpos;
  263. }
  264. IStream_Release(working); /* this also frees the underlying hglobal */
  265. TRACE("done, processed=%ld bytes\n", sizeof(ULONG) + size);
  266. return Buffer + sizeof(ULONG) + size;
  267. }
  268. unsigned long WINAPI VARIANT_UserSize(unsigned long *pFlags, unsigned long Start, VARIANT *pvar)
  269. {
  270. TRACE("(%lx,%ld,%p)\n", *pFlags, Start, pvar);
  271. TRACE("vt=%04x\n", V_VT(pvar));
  272. Start += VARIANT_wiresize + wire_extra(pFlags, pvar);
  273. TRACE("returning %ld\n", Start);
  274. return Start;
  275. }
  276. unsigned char * WINAPI VARIANT_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
  277. {
  278. wireVARIANT var = (wireVARIANT)Buffer;
  279. unsigned size, extra;
  280. unsigned char *Pos = Buffer + VARIANT_wiresize;
  281. TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
  282. TRACE("vt=%04x\n", V_VT(pvar));
  283. memset(var, 0, sizeof(*var));
  284. var->clSize = sizeof(*var);
  285. var->vt = pvar->n1.n2.vt;
  286. var->rpcReserved = var->vt;
  287. if ((var->vt & VT_ARRAY) ||
  288. ((var->vt & VT_TYPEMASK) == VT_SAFEARRAY))
  289. var->vt = VT_ARRAY | (var->vt & VT_BYREF);
  290. if (var->vt == VT_DECIMAL) {
  291. /* special case because decVal is on a different level */
  292. var->u.decVal = pvar->n1.decVal;
  293. return Pos;
  294. }
  295. size = wire_size(V_VT(pvar));
  296. extra = wire_extra(pFlags, pvar);
  297. var->wReserved1 = pvar->n1.n2.wReserved1;
  298. var->wReserved2 = pvar->n1.n2.wReserved2;
  299. var->wReserved3 = pvar->n1.n2.wReserved3;
  300. if (size) {
  301. if (var->vt & VT_BYREF)
  302. memcpy(&var->u.cVal, pvar->n1.n2.n3.byref, size);
  303. else
  304. memcpy(&var->u.cVal, &pvar->n1.n2.n3, size);
  305. }
  306. if (!extra) return Pos;
  307. switch (var->vt) {
  308. case VT_BSTR:
  309. Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar));
  310. break;
  311. case VT_BSTR | VT_BYREF:
  312. Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar));
  313. break;
  314. case VT_VARIANT | VT_BYREF:
  315. Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
  316. break;
  317. case VT_DISPATCH | VT_BYREF:
  318. FIXME("handle DISPATCH by ref\n");
  319. break;
  320. case VT_DISPATCH:
  321. /* this should probably call WdtpInterfacePointer_UserMarshal in ole32.dll */
  322. Pos = dispatch_variant_marshal(pFlags, Pos, pvar);
  323. break;
  324. case VT_RECORD:
  325. FIXME("handle BRECORD by val\n");
  326. break;
  327. case VT_RECORD | VT_BYREF:
  328. FIXME("handle BRECORD by ref\n");
  329. break;
  330. default:
  331. FIXME("handle unknown complex type\n");
  332. break;
  333. }
  334. var->clSize = Pos - Buffer;
  335. TRACE("marshalled size=%ld\n", var->clSize);
  336. return Pos;
  337. }
  338. unsigned char * WINAPI VARIANT_UserUnmarshal(unsigned long *pFlags, unsigned char *Buffer, VARIANT *pvar)
  339. {
  340. wireVARIANT var = (wireVARIANT)Buffer;
  341. unsigned size;
  342. unsigned char *Pos = Buffer + VARIANT_wiresize;
  343. TRACE("(%lx,%p,%p)\n", *pFlags, Buffer, pvar);
  344. VariantInit(pvar);
  345. pvar->n1.n2.vt = var->rpcReserved;
  346. TRACE("marshalled: clSize=%ld, vt=%04x\n", var->clSize, var->vt);
  347. TRACE("vt=%04x\n", V_VT(pvar));
  348. TRACE("reserved: %d, %d, %d\n", var->wReserved1, var->wReserved2, var->wReserved3);
  349. TRACE("val: %ld\n", var->u.lVal);
  350. if (var->vt == VT_DECIMAL) {
  351. /* special case because decVal is on a different level */
  352. pvar->n1.decVal = var->u.decVal;
  353. return Pos;
  354. }
  355. size = wire_size(V_VT(pvar));
  356. pvar->n1.n2.wReserved1 = var->wReserved1;
  357. pvar->n1.n2.wReserved2 = var->wReserved2;
  358. pvar->n1.n2.wReserved3 = var->wReserved3;
  359. if (size) {
  360. if (var->vt & VT_BYREF) {
  361. pvar->n1.n2.n3.byref = CoTaskMemAlloc(size);
  362. memcpy(pvar->n1.n2.n3.byref, &var->u.cVal, size);
  363. }
  364. else
  365. memcpy(&pvar->n1.n2.n3, &var->u.cVal, size);
  366. }
  367. if (var->clSize <= VARIANT_wiresize) return Pos;
  368. switch (var->vt) {
  369. case VT_BSTR:
  370. Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar));
  371. break;
  372. case VT_BSTR | VT_BYREF:
  373. pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(BSTR));
  374. *(BSTR*)pvar->n1.n2.n3.byref = NULL;
  375. Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar));
  376. break;
  377. case VT_VARIANT | VT_BYREF:
  378. pvar->n1.n2.n3.byref = CoTaskMemAlloc(sizeof(VARIANT));
  379. Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
  380. break;
  381. case VT_RECORD:
  382. FIXME("handle BRECORD by val\n");
  383. break;
  384. case VT_RECORD | VT_BYREF:
  385. FIXME("handle BRECORD by ref\n");
  386. break;
  387. case VT_DISPATCH:
  388. Pos = dispatch_variant_unmarshal(pFlags, Pos, pvar);
  389. break;
  390. case VT_DISPATCH | VT_BYREF:
  391. FIXME("handle DISPATCH by ref\n");
  392. default:
  393. FIXME("handle unknown complex type\n");
  394. break;
  395. }
  396. if (Pos != Buffer + var->clSize) {
  397. ERR("size difference during unmarshal\n");
  398. }
  399. return Buffer + var->clSize;
  400. }
  401. void WINAPI VARIANT_UserFree(unsigned long *pFlags, VARIANT *pvar)
  402. {
  403. VARTYPE vt = V_VT(pvar);
  404. PVOID ref = NULL;
  405. TRACE("(%lx,%p)\n", *pFlags, pvar);
  406. TRACE("vt=%04x\n", V_VT(pvar));
  407. if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref;
  408. VariantClear(pvar);
  409. if (!ref) return;
  410. switch (vt) {
  411. case VT_BSTR | VT_BYREF:
  412. BSTR_UserFree(pFlags, ref);
  413. break;
  414. case VT_VARIANT | VT_BYREF:
  415. VARIANT_UserFree(pFlags, ref);
  416. break;
  417. case VT_RECORD | VT_BYREF:
  418. FIXME("handle BRECORD by ref\n");
  419. break;
  420. default:
  421. FIXME("handle unknown complex type\n");
  422. break;
  423. }
  424. CoTaskMemFree(ref);
  425. }
  426. /* IDispatch */
  427. /* exactly how Invoke is marshalled is not very clear to me yet,
  428. * but the way I've done it seems to work for me */
  429. HRESULT CALLBACK IDispatch_Invoke_Proxy(
  430. IDispatch* This,
  431. DISPID dispIdMember,
  432. REFIID riid,
  433. LCID lcid,
  434. WORD wFlags,
  435. DISPPARAMS* pDispParams,
  436. VARIANT* pVarResult,
  437. EXCEPINFO* pExcepInfo,
  438. UINT* puArgErr)
  439. {
  440. HRESULT hr;
  441. VARIANT VarResult;
  442. UINT* rgVarRefIdx = NULL;
  443. VARIANTARG* rgVarRef = NULL;
  444. UINT u, cVarRef;
  445. TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
  446. dispIdMember, debugstr_guid(riid),
  447. lcid, wFlags, pDispParams, pVarResult,
  448. pExcepInfo, puArgErr);
  449. /* [out] args can't be null, use dummy vars if needed */
  450. if (!pVarResult) pVarResult = &VarResult;
  451. /* count by-ref args */
  452. for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
  453. VARIANTARG* arg = &pDispParams->rgvarg[u];
  454. if (V_VT(arg) & VT_BYREF) {
  455. cVarRef++;
  456. }
  457. }
  458. if (cVarRef) {
  459. rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef);
  460. rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef);
  461. /* make list of by-ref args */
  462. for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
  463. VARIANTARG* arg = &pDispParams->rgvarg[u];
  464. if (V_VT(arg) & VT_BYREF) {
  465. rgVarRefIdx[cVarRef] = u;
  466. VariantInit(&rgVarRef[cVarRef]);
  467. cVarRef++;
  468. }
  469. }
  470. } else {
  471. /* [out] args still can't be null,
  472. * but we can point these anywhere in this case,
  473. * since they won't be written to when cVarRef is 0 */
  474. rgVarRefIdx = puArgErr;
  475. rgVarRef = pVarResult;
  476. }
  477. TRACE("passed by ref: %d args\n", cVarRef);
  478. hr = IDispatch_RemoteInvoke_Proxy(This,
  479. dispIdMember,
  480. riid,
  481. lcid,
  482. wFlags,
  483. pDispParams,
  484. pVarResult,
  485. pExcepInfo,
  486. puArgErr,
  487. cVarRef,
  488. rgVarRefIdx,
  489. rgVarRef);
  490. if (cVarRef) {
  491. for (u=0; u<cVarRef; u++) {
  492. unsigned i = rgVarRefIdx[u];
  493. VariantCopy(&pDispParams->rgvarg[i],
  494. &rgVarRef[u]);
  495. VariantClear(&rgVarRef[u]);
  496. }
  497. CoTaskMemFree(rgVarRef);
  498. CoTaskMemFree(rgVarRefIdx);
  499. }
  500. return hr;
  501. }
  502. HRESULT __RPC_STUB IDispatch_Invoke_Stub(
  503. IDispatch* This,
  504. DISPID dispIdMember,
  505. REFIID riid,
  506. LCID lcid,
  507. DWORD dwFlags,
  508. DISPPARAMS* pDispParams,
  509. VARIANT* pVarResult,
  510. EXCEPINFO* pExcepInfo,
  511. UINT* pArgErr,
  512. UINT cVarRef,
  513. UINT* rgVarRefIdx,
  514. VARIANTARG* rgVarRef)
  515. {
  516. HRESULT hr;
  517. VARIANTARG *rgvarg, *arg;
  518. UINT u;
  519. /* let the real Invoke operate on a copy of the in parameters,
  520. * so we don't risk losing pointers to allocated memory */
  521. rgvarg = pDispParams->rgvarg;
  522. arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
  523. for (u=0; u<pDispParams->cArgs; u++) {
  524. VariantInit(&arg[u]);
  525. VariantCopy(&arg[u], &rgvarg[u]);
  526. }
  527. pDispParams->rgvarg = arg;
  528. /* initialize out parameters, so that they can be marshalled
  529. * in case the real Invoke doesn't initialize them */
  530. VariantInit(pVarResult);
  531. memset(pExcepInfo, 0, sizeof(*pExcepInfo));
  532. *pArgErr = 0;
  533. hr = IDispatch_Invoke(This,
  534. dispIdMember,
  535. riid,
  536. lcid,
  537. dwFlags,
  538. pDispParams,
  539. pVarResult,
  540. pExcepInfo,
  541. pArgErr);
  542. /* copy ref args to out list */
  543. for (u=0; u<cVarRef; u++) {
  544. unsigned i = rgVarRefIdx[u];
  545. VariantInit(&rgVarRef[u]);
  546. VariantCopy(&rgVarRef[u], &arg[i]);
  547. /* clear original if equal, to avoid double-free */
  548. if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
  549. VariantClear(&rgvarg[i]);
  550. }
  551. /* clear the duplicate argument list */
  552. for (u=0; u<pDispParams->cArgs; u++) {
  553. VariantClear(&arg[u]);
  554. }
  555. pDispParams->rgvarg = rgvarg;
  556. CoTaskMemFree(arg);
  557. return hr;
  558. }
  559. /* IEnumVARIANT */
  560. HRESULT CALLBACK IEnumVARIANT_Next_Proxy(
  561. IEnumVARIANT* This,
  562. ULONG celt,
  563. VARIANT* rgVar,
  564. ULONG* pCeltFetched)
  565. {
  566. ULONG fetched;
  567. if (!pCeltFetched)
  568. pCeltFetched = &fetched;
  569. return IEnumVARIANT_RemoteNext_Proxy(This,
  570. celt,
  571. rgVar,
  572. pCeltFetched);
  573. }
  574. HRESULT __RPC_STUB IEnumVARIANT_Next_Stub(
  575. IEnumVARIANT* This,
  576. ULONG celt,
  577. VARIANT* rgVar,
  578. ULONG* pCeltFetched)
  579. {
  580. HRESULT hr;
  581. *pCeltFetched = 0;
  582. hr = IEnumVARIANT_Next(This,
  583. celt,
  584. rgVar,
  585. pCeltFetched);
  586. if (hr == S_OK) *pCeltFetched = celt;
  587. return hr;
  588. }
  589. /* ITypeComp */
  590. HRESULT CALLBACK ITypeComp_Bind_Proxy(
  591. ITypeComp* This,
  592. LPOLESTR szName,
  593. ULONG lHashVal,
  594. WORD wFlags,
  595. ITypeInfo** ppTInfo,
  596. DESCKIND* pDescKind,
  597. BINDPTR* pBindPtr)
  598. {
  599. FIXME("not implemented\n");
  600. return E_FAIL;
  601. }
  602. HRESULT __RPC_STUB ITypeComp_Bind_Stub(
  603. ITypeComp* This,
  604. LPOLESTR szName,
  605. ULONG lHashVal,
  606. WORD wFlags,
  607. ITypeInfo** ppTInfo,
  608. DESCKIND* pDescKind,
  609. LPFUNCDESC* ppFuncDesc,
  610. LPVARDESC* ppVarDesc,
  611. ITypeComp** ppTypeComp,
  612. CLEANLOCALSTORAGE* pDummy)
  613. {
  614. FIXME("not implemented\n");
  615. return E_FAIL;
  616. }
  617. HRESULT CALLBACK ITypeComp_BindType_Proxy(
  618. ITypeComp* This,
  619. LPOLESTR szName,
  620. ULONG lHashVal,
  621. ITypeInfo** ppTInfo,
  622. ITypeComp** ppTComp)
  623. {
  624. FIXME("not implemented\n");
  625. return E_FAIL;
  626. }
  627. HRESULT __RPC_STUB ITypeComp_BindType_Stub(
  628. ITypeComp* This,
  629. LPOLESTR szName,
  630. ULONG lHashVal,
  631. ITypeInfo** ppTInfo)
  632. {
  633. FIXME("not implemented\n");
  634. return E_FAIL;
  635. }
  636. /* ITypeInfo */
  637. HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy(
  638. ITypeInfo* This,
  639. TYPEATTR** ppTypeAttr)
  640. {
  641. FIXME("not implemented\n");
  642. return E_FAIL;
  643. }
  644. HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
  645. ITypeInfo* This,
  646. LPTYPEATTR* ppTypeAttr,
  647. CLEANLOCALSTORAGE* pDummy)
  648. {
  649. FIXME("not implemented\n");
  650. return E_FAIL;
  651. }
  652. HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy(
  653. ITypeInfo* This,
  654. UINT index,
  655. FUNCDESC** ppFuncDesc)
  656. {
  657. FIXME("not implemented\n");
  658. return E_FAIL;
  659. }
  660. HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
  661. ITypeInfo* This,
  662. UINT index,
  663. LPFUNCDESC* ppFuncDesc,
  664. CLEANLOCALSTORAGE* pDummy)
  665. {
  666. FIXME("not implemented\n");
  667. return E_FAIL;
  668. }
  669. HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy(
  670. ITypeInfo* This,
  671. UINT index,
  672. VARDESC** ppVarDesc)
  673. {
  674. FIXME("not implemented\n");
  675. return E_FAIL;
  676. }
  677. HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub(
  678. ITypeInfo* This,
  679. UINT index,
  680. LPVARDESC* ppVarDesc,
  681. CLEANLOCALSTORAGE* pDummy)
  682. {
  683. FIXME("not implemented\n");
  684. return E_FAIL;
  685. }
  686. HRESULT CALLBACK ITypeInfo_GetNames_Proxy(
  687. ITypeInfo* This,
  688. MEMBERID memid,
  689. BSTR* rgBstrNames,
  690. UINT cMaxNames,
  691. UINT* pcNames)
  692. {
  693. FIXME("not implemented\n");
  694. return E_FAIL;
  695. }
  696. HRESULT __RPC_STUB ITypeInfo_GetNames_Stub(
  697. ITypeInfo* This,
  698. MEMBERID memid,
  699. BSTR* rgBstrNames,
  700. UINT cMaxNames,
  701. UINT* pcNames)
  702. {
  703. FIXME("not implemented\n");
  704. return E_FAIL;
  705. }
  706. HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy(
  707. ITypeInfo* This,
  708. LPOLESTR* rgszNames,
  709. UINT cNames,
  710. MEMBERID* pMemId)
  711. {
  712. FIXME("not implemented\n");
  713. return E_FAIL;
  714. }
  715. HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
  716. ITypeInfo* This)
  717. {
  718. FIXME("not implemented\n");
  719. return E_FAIL;
  720. }
  721. HRESULT CALLBACK ITypeInfo_Invoke_Proxy(
  722. ITypeInfo* This,
  723. PVOID pvInstance,
  724. MEMBERID memid,
  725. WORD wFlags,
  726. DISPPARAMS* pDispParams,
  727. VARIANT* pVarResult,
  728. EXCEPINFO* pExcepInfo,
  729. UINT* puArgErr)
  730. {
  731. FIXME("not implemented\n");
  732. return E_FAIL;
  733. }
  734. HRESULT __RPC_STUB ITypeInfo_Invoke_Stub(
  735. ITypeInfo* This)
  736. {
  737. FIXME("not implemented\n");
  738. return E_FAIL;
  739. }
  740. HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(
  741. ITypeInfo* This,
  742. MEMBERID memid,
  743. BSTR* pBstrName,
  744. BSTR* pBstrDocString,
  745. DWORD* pdwHelpContext,
  746. BSTR* pBstrHelpFile)
  747. {
  748. FIXME("not implemented\n");
  749. return E_FAIL;
  750. }
  751. HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(
  752. ITypeInfo* This,
  753. MEMBERID memid,
  754. DWORD refPtrFlags,
  755. BSTR* pBstrName,
  756. BSTR* pBstrDocString,
  757. DWORD* pdwHelpContext,
  758. BSTR* pBstrHelpFile)
  759. {
  760. FIXME("not implemented\n");
  761. return E_FAIL;
  762. }
  763. HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(
  764. ITypeInfo* This,
  765. MEMBERID memid,
  766. INVOKEKIND invKind,
  767. BSTR* pBstrDllName,
  768. BSTR* pBstrName,
  769. WORD* pwOrdinal)
  770. {
  771. FIXME("not implemented\n");
  772. return E_FAIL;
  773. }
  774. HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(
  775. ITypeInfo* This,
  776. MEMBERID memid,
  777. INVOKEKIND invKind,
  778. DWORD refPtrFlags,
  779. BSTR* pBstrDllName,
  780. BSTR* pBstrName,
  781. WORD* pwOrdinal)
  782. {
  783. FIXME("not implemented\n");
  784. return E_FAIL;
  785. }
  786. HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy(
  787. ITypeInfo* This,
  788. MEMBERID memid,
  789. INVOKEKIND invKind,
  790. PVOID* ppv)
  791. {
  792. FIXME("not implemented\n");
  793. return E_FAIL;
  794. }
  795. HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub(
  796. ITypeInfo* This)
  797. {
  798. FIXME("not implemented\n");
  799. return E_FAIL;
  800. }
  801. HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy(
  802. ITypeInfo* This,
  803. IUnknown* pUnkOuter,
  804. REFIID riid,
  805. PVOID* ppvObj)
  806. {
  807. FIXME("not implemented\n");
  808. return E_FAIL;
  809. }
  810. HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub(
  811. ITypeInfo* This,
  812. REFIID riid,
  813. IUnknown** ppvObj)
  814. {
  815. FIXME("not implemented\n");
  816. return E_FAIL;
  817. }
  818. HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy(
  819. ITypeInfo* This,
  820. ITypeLib** ppTLib,
  821. UINT* pIndex)
  822. {
  823. FIXME("not implemented\n");
  824. return E_FAIL;
  825. }
  826. HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
  827. ITypeInfo* This,
  828. ITypeLib** ppTLib,
  829. UINT* pIndex)
  830. {
  831. FIXME("not implemented\n");
  832. return E_FAIL;
  833. }
  834. void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy(
  835. ITypeInfo* This,
  836. TYPEATTR* pTypeAttr)
  837. {
  838. FIXME("not implemented\n");
  839. }
  840. HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
  841. ITypeInfo* This)
  842. {
  843. FIXME("not implemented\n");
  844. return E_FAIL;
  845. }
  846. void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy(
  847. ITypeInfo* This,
  848. FUNCDESC* pFuncDesc)
  849. {
  850. FIXME("not implemented\n");
  851. }
  852. HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
  853. ITypeInfo* This)
  854. {
  855. FIXME("not implemented\n");
  856. return E_FAIL;
  857. }
  858. void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy(
  859. ITypeInfo* This,
  860. VARDESC* pVarDesc)
  861. {
  862. FIXME("not implemented\n");
  863. }
  864. HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
  865. ITypeInfo* This)
  866. {
  867. FIXME("not implemented\n");
  868. return E_FAIL;
  869. }
  870. /* ITypeInfo2 */
  871. HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(
  872. ITypeInfo2* This,
  873. MEMBERID memid,
  874. LCID lcid,
  875. BSTR* pbstrHelpString,
  876. DWORD* pdwHelpStringContext,
  877. BSTR* pbstrHelpStringDll)
  878. {
  879. FIXME("not implemented\n");
  880. return E_FAIL;
  881. }
  882. HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(
  883. ITypeInfo2* This,
  884. MEMBERID memid,
  885. LCID lcid,
  886. DWORD refPtrFlags,
  887. BSTR* pbstrHelpString,
  888. DWORD* pdwHelpStringContext,
  889. BSTR* pbstrHelpStringDll)
  890. {
  891. FIXME("not implemented\n");
  892. return E_FAIL;
  893. }
  894. /* ITypeLib */
  895. UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy(
  896. ITypeLib* This)
  897. {
  898. FIXME("not implemented\n");
  899. return E_FAIL;
  900. }
  901. HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
  902. ITypeLib* This,
  903. UINT* pcTInfo)
  904. {
  905. FIXME("not implemented\n");
  906. return E_FAIL;
  907. }
  908. HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy(
  909. ITypeLib* This,
  910. TLIBATTR** ppTLibAttr)
  911. {
  912. FIXME("not implemented\n");
  913. return E_FAIL;
  914. }
  915. HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub(
  916. ITypeLib* This,
  917. LPTLIBATTR* ppTLibAttr,
  918. CLEANLOCALSTORAGE* pDummy)
  919. {
  920. FIXME("not implemented\n");
  921. return E_FAIL;
  922. }
  923. HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(
  924. ITypeLib* This,
  925. INT index,
  926. BSTR* pBstrName,
  927. BSTR* pBstrDocString,
  928. DWORD* pdwHelpContext,
  929. BSTR* pBstrHelpFile)
  930. {
  931. FIXME("not implemented\n");
  932. return E_FAIL;
  933. }
  934. HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(
  935. ITypeLib* This,
  936. INT index,
  937. DWORD refPtrFlags,
  938. BSTR* pBstrName,
  939. BSTR* pBstrDocString,
  940. DWORD* pdwHelpContext,
  941. BSTR* pBstrHelpFile)
  942. {
  943. FIXME("not implemented\n");
  944. return E_FAIL;
  945. }
  946. HRESULT CALLBACK ITypeLib_IsName_Proxy(
  947. ITypeLib* This,
  948. LPOLESTR szNameBuf,
  949. ULONG lHashVal,
  950. BOOL* pfName)
  951. {
  952. FIXME("not implemented\n");
  953. return E_FAIL;
  954. }
  955. HRESULT __RPC_STUB ITypeLib_IsName_Stub(
  956. ITypeLib* This,
  957. LPOLESTR szNameBuf,
  958. ULONG lHashVal,
  959. BOOL* pfName,
  960. BSTR* pBstrLibName)
  961. {
  962. FIXME("not implemented\n");
  963. return E_FAIL;
  964. }
  965. HRESULT CALLBACK ITypeLib_FindName_Proxy(
  966. ITypeLib* This,
  967. LPOLESTR szNameBuf,
  968. ULONG lHashVal,
  969. ITypeInfo** ppTInfo,
  970. MEMBERID* rgMemId,
  971. USHORT* pcFound)
  972. {
  973. FIXME("not implemented\n");
  974. return E_FAIL;
  975. }
  976. HRESULT __RPC_STUB ITypeLib_FindName_Stub(
  977. ITypeLib* This,
  978. LPOLESTR szNameBuf,
  979. ULONG lHashVal,
  980. ITypeInfo** ppTInfo,
  981. MEMBERID* rgMemId,
  982. USHORT* pcFound,
  983. BSTR* pBstrLibName)
  984. {
  985. FIXME("not implemented\n");
  986. return E_FAIL;
  987. }
  988. void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy(
  989. ITypeLib* This,
  990. TLIBATTR* pTLibAttr)
  991. {
  992. FIXME("not implemented\n");
  993. }
  994. HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
  995. ITypeLib* This)
  996. {
  997. FIXME("not implemented\n");
  998. return E_FAIL;
  999. }
  1000. /* ITypeLib2 */
  1001. HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy(
  1002. ITypeLib2* This,
  1003. ULONG* pcUniqueNames,
  1004. ULONG* pcchUniqueNames)
  1005. {
  1006. FIXME("not implemented\n");
  1007. return E_FAIL;
  1008. }
  1009. HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub(
  1010. ITypeLib2* This,
  1011. ULONG* pcUniqueNames,
  1012. ULONG* pcchUniqueNames)
  1013. {
  1014. FIXME("not implemented\n");
  1015. return E_FAIL;
  1016. }
  1017. HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(
  1018. ITypeLib2* This,
  1019. INT index,
  1020. LCID lcid,
  1021. BSTR* pbstrHelpString,
  1022. DWORD* pdwHelpStringContext,
  1023. BSTR* pbstrHelpStringDll)
  1024. {
  1025. FIXME("not implemented\n");
  1026. return E_FAIL;
  1027. }
  1028. HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(
  1029. ITypeLib2* This,
  1030. INT index,
  1031. LCID lcid,
  1032. DWORD refPtrFlags,
  1033. BSTR* pbstrHelpString,
  1034. DWORD* pdwHelpStringContext,
  1035. BSTR* pbstrHelpStringDll)
  1036. {
  1037. FIXME("not implemented\n");
  1038. return E_FAIL;
  1039. }