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