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