| /* |
| * Misc marshalling routines |
| * |
| * Copyright 2002 Ove Kaaven |
| * Copyright 2003 Mike Hearn |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <stdarg.h> |
| #include <string.h> |
| |
| #define COBJMACROS |
| #define NONAMELESSUNION |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "winuser.h" |
| #include "winerror.h" |
| |
| #include "ole2.h" |
| #include "oleauto.h" |
| #include "typelib.h" |
| #include "ocidl.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ole); |
| |
| #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align)) |
| #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) |
| #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) |
| #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) |
| |
| /* ole32 exports those, not defined in public headers */ |
| ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG*, ULONG, ULONG, IUnknown*, REFIID); |
| unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG*, ULONG, unsigned char*, IUnknown*, REFIID); |
| unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG*, unsigned char*, IUnknown**, REFIID); |
| |
| static void dump_user_flags(const ULONG *pFlags) |
| { |
| if (HIWORD(*pFlags) == NDR_LOCAL_DATA_REPRESENTATION) |
| TRACE("MAKELONG(NDR_LOCAL_REPRESENTATION, "); |
| else |
| TRACE("MAKELONG(0x%04x, ", HIWORD(*pFlags)); |
| switch (LOWORD(*pFlags)) |
| { |
| case MSHCTX_LOCAL: TRACE("MSHCTX_LOCAL)"); break; |
| case MSHCTX_NOSHAREDMEM: TRACE("MSHCTX_NOSHAREDMEM)"); break; |
| case MSHCTX_DIFFERENTMACHINE: TRACE("MSHCTX_DIFFERENTMACHINE)"); break; |
| case MSHCTX_INPROC: TRACE("MSHCTX_INPROC)"); break; |
| default: TRACE("%d)", LOWORD(*pFlags)); |
| } |
| } |
| |
| /* CLEANLOCALSTORAGE */ |
| |
| #define CLS_FUNCDESC 'f' |
| #define CLS_LIBATTR 'l' |
| #define CLS_TYPEATTR 't' |
| #define CLS_VARDESC 'v' |
| |
| ULONG WINAPI CLEANLOCALSTORAGE_UserSize(ULONG *pFlags, ULONG Start, CLEANLOCALSTORAGE *pstg) |
| { |
| ALIGN_LENGTH(Start, 3); |
| return Start + sizeof(DWORD); |
| } |
| |
| unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg) |
| { |
| ALIGN_POINTER(Buffer, 3); |
| *(DWORD*)Buffer = pstg->flags; |
| switch(pstg->flags) |
| { |
| case CLS_LIBATTR: |
| ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage); |
| break; |
| case CLS_TYPEATTR: |
| ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); |
| break; |
| case CLS_FUNCDESC: |
| ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); |
| break; |
| case CLS_VARDESC: |
| ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage); |
| break; |
| |
| default: |
| ERR("Unknown type %x\n", pstg->flags); |
| } |
| |
| *(VOID**)pstg->pStorage = NULL; |
| IUnknown_Release(pstg->pInterface); |
| pstg->pInterface = NULL; |
| |
| return Buffer + sizeof(DWORD); |
| } |
| |
| unsigned char * WINAPI CLEANLOCALSTORAGE_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstr) |
| { |
| ALIGN_POINTER(Buffer, 3); |
| pstr->flags = *(DWORD*)Buffer; |
| return Buffer + sizeof(DWORD); |
| } |
| |
| void WINAPI CLEANLOCALSTORAGE_UserFree(ULONG *pFlags, CLEANLOCALSTORAGE *pstr) |
| { |
| /* Nothing to do */ |
| } |
| |
| /* BSTR */ |
| |
| typedef struct |
| { |
| DWORD len; /* No. of chars not including trailing '\0' */ |
| DWORD byte_len; /* len * 2 or 0xffffffff if len == 0 */ |
| DWORD len2; /* == len */ |
| } bstr_wire_t; |
| |
| ULONG WINAPI BSTR_UserSize(ULONG *pFlags, ULONG Start, BSTR *pstr) |
| { |
| TRACE("(%x,%d,%p) => %p\n", *pFlags, Start, pstr, *pstr); |
| if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); |
| ALIGN_LENGTH(Start, 3); |
| Start += sizeof(bstr_wire_t) + ((SysStringByteLen(*pstr) + 1) & ~1); |
| TRACE("returning %d\n", Start); |
| return Start; |
| } |
| |
| unsigned char * WINAPI BSTR_UserMarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr) |
| { |
| bstr_wire_t *header; |
| DWORD len = SysStringByteLen(*pstr); |
| |
| TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); |
| if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); |
| |
| ALIGN_POINTER(Buffer, 3); |
| header = (bstr_wire_t*)Buffer; |
| header->len = header->len2 = (len + 1) / 2; |
| if (*pstr) |
| { |
| header->byte_len = len; |
| memcpy(header + 1, *pstr, header->len * 2); |
| } |
| else |
| header->byte_len = 0xffffffff; /* special case for a null bstr */ |
| |
| return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; |
| } |
| |
| unsigned char * WINAPI BSTR_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, BSTR *pstr) |
| { |
| bstr_wire_t *header; |
| TRACE("(%x,%p,%p) => %p\n", *pFlags, Buffer, pstr, *pstr); |
| |
| ALIGN_POINTER(Buffer, 3); |
| header = (bstr_wire_t*)Buffer; |
| if(header->len != header->len2) |
| FIXME("len %08x != len2 %08x\n", header->len, header->len2); |
| |
| if (header->byte_len == 0xffffffff) |
| { |
| SysFreeString(*pstr); |
| *pstr = NULL; |
| } |
| else SysReAllocStringLen( pstr, (OLECHAR *)(header + 1), header->len ); |
| |
| if (*pstr) TRACE("string=%s\n", debugstr_w(*pstr)); |
| return Buffer + sizeof(*header) + sizeof(OLECHAR) * header->len; |
| } |
| |
| void WINAPI BSTR_UserFree(ULONG *pFlags, BSTR *pstr) |
| { |
| TRACE("(%x,%p) => %p\n", *pFlags, pstr, *pstr); |
| SysFreeString(*pstr); |
| *pstr = NULL; |
| } |
| |
| /* VARIANT */ |
| |
| typedef struct |
| { |
| DWORD clSize; |
| DWORD rpcReserved; |
| USHORT vt; |
| USHORT wReserved1; |
| USHORT wReserved2; |
| USHORT wReserved3; |
| DWORD switch_is; |
| } variant_wire_t; |
| |
| unsigned int get_type_size(ULONG *pFlags, VARTYPE vt) |
| { |
| if (vt & VT_ARRAY) return 4; |
| |
| switch (vt & ~VT_BYREF) { |
| case VT_EMPTY: |
| case VT_NULL: |
| return 0; |
| case VT_I1: |
| case VT_UI1: |
| return sizeof(CHAR); |
| case VT_I2: |
| case VT_UI2: |
| return sizeof(SHORT); |
| case VT_I4: |
| case VT_UI4: |
| case VT_HRESULT: |
| return sizeof(LONG); |
| case VT_INT: |
| case VT_UINT: |
| return sizeof(INT); |
| case VT_R4: |
| return sizeof(FLOAT); |
| case VT_R8: |
| return sizeof(DOUBLE); |
| case VT_BOOL: |
| return sizeof(VARIANT_BOOL); |
| case VT_ERROR: |
| return sizeof(SCODE); |
| case VT_DATE: |
| return sizeof(DATE); |
| case VT_CY: |
| return sizeof(CY); |
| case VT_DECIMAL: |
| return sizeof(DECIMAL); |
| case VT_BSTR: |
| return sizeof(ULONG); |
| case VT_VARIANT: |
| return sizeof(VARIANT); |
| case VT_UNKNOWN: |
| case VT_DISPATCH: |
| case VT_RECORD: |
| return 0; |
| default: |
| FIXME("unhandled VT %d\n", vt); |
| return 0; |
| } |
| } |
| |
| static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt) |
| { |
| unsigned int size = get_type_size(pFlags, vt); |
| if(vt & VT_BYREF) return 3; |
| if(size == 0) return 0; |
| if(size <= 4) return size - 1; |
| return 7; |
| } |
| |
| /* WdtpInterfacePointer_UserSize takes care of 2 additional DWORDs to store marshalling buffer size */ |
| static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *punk) |
| { |
| ULONG size = 0; |
| |
| if (punk) |
| { |
| size = WdtpInterfacePointer_UserSize(pFlags, LOWORD(*pFlags), 0, punk, riid); |
| if (!size) |
| { |
| ERR("interface variant buffer size calculation failed\n"); |
| return 0; |
| } |
| } |
| size += sizeof(ULONG); |
| TRACE("wire-size extra of interface variant is %d\n", size); |
| return size; |
| } |
| |
| static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) |
| { |
| if (V_ISARRAY(pvar)) |
| { |
| if (V_ISBYREF(pvar)) |
| return LPSAFEARRAY_UserSize(pFlags, Start, V_ARRAYREF(pvar)); |
| else |
| return LPSAFEARRAY_UserSize(pFlags, Start, &V_ARRAY(pvar)); |
| } |
| |
| switch (V_VT(pvar)) { |
| case VT_BSTR: |
| return BSTR_UserSize(pFlags, Start, &V_BSTR(pvar)); |
| case VT_BSTR | VT_BYREF: |
| return BSTR_UserSize(pFlags, Start, V_BSTRREF(pvar)); |
| case VT_VARIANT | VT_BYREF: |
| return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar)); |
| case VT_UNKNOWN: |
| return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar)); |
| case VT_UNKNOWN | VT_BYREF: |
| return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar)); |
| case VT_DISPATCH: |
| return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); |
| case VT_DISPATCH | VT_BYREF: |
| return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); |
| case VT_RECORD: |
| FIXME("wire-size record\n"); |
| return Start; |
| case VT_SAFEARRAY: |
| case VT_SAFEARRAY | VT_BYREF: |
| FIXME("wire-size safearray: shouldn't be marshaling this\n"); |
| return Start; |
| default: |
| return Start; |
| } |
| } |
| |
| /* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer */ |
| static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer, |
| REFIID riid, IUnknown *punk) |
| { |
| TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk); |
| |
| /* first DWORD is used to store pointer itself, truncated on win64 */ |
| if(!punk) |
| { |
| memset(Buffer, 0, sizeof(ULONG)); |
| return Buffer + sizeof(ULONG); |
| } |
| else |
| { |
| *(DWORD*)Buffer = (DWORD_PTR)punk; |
| Buffer += sizeof(DWORD); |
| } |
| |
| return WdtpInterfacePointer_UserMarshal(pFlags, LOWORD(*pFlags), Buffer, punk, riid); |
| } |
| |
| /* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer */ |
| static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer, |
| REFIID riid, IUnknown **ppunk) |
| { |
| DWORD ptr; |
| |
| TRACE("pFlags=%d, Buffer=%p, ppUnk=%p\n", *pFlags, Buffer, ppunk); |
| |
| /* skip pointer part itself */ |
| ptr = *(DWORD*)Buffer; |
| Buffer += sizeof(DWORD); |
| |
| if(!ptr) |
| { |
| *ppunk = NULL; |
| return Buffer; |
| } |
| |
| return WdtpInterfacePointer_UserUnmarshal(pFlags, Buffer, ppunk, riid); |
| } |
| |
| ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar) |
| { |
| int align; |
| TRACE("(%x,%d,%p)\n", *pFlags, Start, pvar); |
| TRACE("vt=%04x\n", V_VT(pvar)); |
| |
| ALIGN_LENGTH(Start, 7); |
| Start += sizeof(variant_wire_t); |
| if(V_VT(pvar) & VT_BYREF) |
| Start += 4; |
| |
| align = get_type_alignment(pFlags, V_VT(pvar)); |
| ALIGN_LENGTH(Start, align); |
| if(V_VT(pvar) == (VT_VARIANT | VT_BYREF)) |
| Start += 4; |
| else |
| Start += get_type_size(pFlags, V_VT(pvar)); |
| Start = wire_extra_user_size(pFlags, Start, pvar); |
| |
| TRACE("returning %d\n", Start); |
| return Start; |
| } |
| |
| unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar) |
| { |
| variant_wire_t *header; |
| ULONG type_size; |
| int align; |
| unsigned char *Pos; |
| |
| TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar); |
| TRACE("vt=%04x\n", V_VT(pvar)); |
| |
| ALIGN_POINTER(Buffer, 7); |
| |
| header = (variant_wire_t *)Buffer; |
| |
| header->clSize = 0; /* fixed up at the end */ |
| header->rpcReserved = 0; |
| header->vt = pvar->n1.n2.vt; |
| header->wReserved1 = pvar->n1.n2.wReserved1; |
| header->wReserved2 = pvar->n1.n2.wReserved2; |
| header->wReserved3 = pvar->n1.n2.wReserved3; |
| header->switch_is = pvar->n1.n2.vt; |
| if(header->switch_is & VT_ARRAY) |
| header->switch_is &= ~VT_TYPEMASK; |
| |
| Pos = (unsigned char*)(header + 1); |
| type_size = get_type_size(pFlags, V_VT(pvar)); |
| align = get_type_alignment(pFlags, V_VT(pvar)); |
| ALIGN_POINTER(Pos, align); |
| |
| if(header->vt & VT_BYREF) |
| { |
| *(DWORD *)Pos = max(type_size, 4); |
| Pos += 4; |
| if((header->vt & VT_TYPEMASK) != VT_VARIANT) |
| { |
| memcpy(Pos, pvar->n1.n2.n3.byref, type_size); |
| Pos += type_size; |
| } |
| else |
| { |
| *(DWORD*)Pos = 'U' | 's' << 8 | 'e' << 16 | 'r' << 24; |
| Pos += 4; |
| } |
| } |
| else |
| { |
| if((header->vt & VT_TYPEMASK) == VT_DECIMAL) |
| memcpy(Pos, pvar, type_size); |
| else |
| memcpy(Pos, &pvar->n1.n2.n3, type_size); |
| Pos += type_size; |
| } |
| |
| if(header->vt & VT_ARRAY) |
| { |
| if(header->vt & VT_BYREF) |
| Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, V_ARRAYREF(pvar)); |
| else |
| Pos = LPSAFEARRAY_UserMarshal(pFlags, Pos, &V_ARRAY(pvar)); |
| } |
| else |
| { |
| switch (header->vt) |
| { |
| case VT_BSTR: |
| Pos = BSTR_UserMarshal(pFlags, Pos, &V_BSTR(pvar)); |
| break; |
| case VT_BSTR | VT_BYREF: |
| Pos = BSTR_UserMarshal(pFlags, Pos, V_BSTRREF(pvar)); |
| break; |
| case VT_VARIANT | VT_BYREF: |
| Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar)); |
| break; |
| case VT_UNKNOWN: |
| Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar)); |
| break; |
| case VT_UNKNOWN | VT_BYREF: |
| Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar)); |
| break; |
| case VT_DISPATCH: |
| Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar)); |
| break; |
| case VT_DISPATCH | VT_BYREF: |
| Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar)); |
| break; |
| case VT_RECORD: |
| FIXME("handle BRECORD by val\n"); |
| break; |
| case VT_RECORD | VT_BYREF: |
| FIXME("handle BRECORD by ref\n"); |
| break; |
| } |
| } |
| header->clSize = ((Pos - Buffer) + 7) >> 3; |
| TRACE("marshalled size=%d\n", header->clSize); |
| return Pos; |
| } |
| |
| unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, VARIANT *pvar) |
| { |
| variant_wire_t *header; |
| ULONG type_size; |
| int align; |
| unsigned char *Pos; |
| |
| TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar); |
| |
| ALIGN_POINTER(Buffer, 7); |
| |
| header = (variant_wire_t *)Buffer; |
| |
| Pos = (unsigned char*)(header + 1); |
| type_size = get_type_size(pFlags, header->vt); |
| align = get_type_alignment(pFlags, header->vt); |
| ALIGN_POINTER(Pos, align); |
| |
| if(header->vt & VT_BYREF) |
| { |
| ULONG mem_size; |
| Pos += 4; |
| |
| switch (header->vt & ~VT_BYREF) |
| { |
| /* these types have a different memory size compared to wire size */ |
| case VT_UNKNOWN: |
| case VT_DISPATCH: |
| case VT_BSTR: |
| mem_size = sizeof(void *); |
| break; |
| default: |
| mem_size = type_size; |
| break; |
| } |
| |
| if (V_VT(pvar) != header->vt) |
| { |
| VariantClear(pvar); |
| V_BYREF(pvar) = CoTaskMemAlloc(mem_size); |
| } |
| else if (!V_BYREF(pvar)) |
| V_BYREF(pvar) = CoTaskMemAlloc(mem_size); |
| memcpy(V_BYREF(pvar), Pos, type_size); |
| if((header->vt & VT_TYPEMASK) != VT_VARIANT) |
| Pos += type_size; |
| else |
| Pos += 4; |
| } |
| else |
| { |
| VariantClear(pvar); |
| if((header->vt & VT_TYPEMASK) == VT_DECIMAL) |
| memcpy(pvar, Pos, type_size); |
| else |
| memcpy(&pvar->n1.n2.n3, Pos, type_size); |
| Pos += type_size; |
| } |
| |
| pvar->n1.n2.vt = header->vt; |
| pvar->n1.n2.wReserved1 = header->wReserved1; |
| pvar->n1.n2.wReserved2 = header->wReserved2; |
| pvar->n1.n2.wReserved3 = header->wReserved3; |
| |
| if(header->vt & VT_ARRAY) |
| { |
| if(header->vt & VT_BYREF) |
| Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, V_ARRAYREF(pvar)); |
| else |
| Pos = LPSAFEARRAY_UserUnmarshal(pFlags, Pos, &V_ARRAY(pvar)); |
| } |
| else |
| { |
| switch (header->vt) |
| { |
| case VT_BSTR: |
| V_BSTR(pvar) = NULL; |
| Pos = BSTR_UserUnmarshal(pFlags, Pos, &V_BSTR(pvar)); |
| break; |
| case VT_BSTR | VT_BYREF: |
| *V_BSTRREF(pvar) = NULL; |
| Pos = BSTR_UserUnmarshal(pFlags, Pos, V_BSTRREF(pvar)); |
| break; |
| case VT_VARIANT | VT_BYREF: |
| Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar)); |
| break; |
| case VT_UNKNOWN: |
| Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar)); |
| break; |
| case VT_UNKNOWN | VT_BYREF: |
| Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar)); |
| break; |
| case VT_DISPATCH: |
| Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar)); |
| break; |
| case VT_DISPATCH | VT_BYREF: |
| Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar)); |
| break; |
| case VT_RECORD: |
| FIXME("handle BRECORD by val\n"); |
| break; |
| case VT_RECORD | VT_BYREF: |
| FIXME("handle BRECORD by ref\n"); |
| break; |
| } |
| } |
| return Pos; |
| } |
| |
| void WINAPI VARIANT_UserFree(ULONG *pFlags, VARIANT *pvar) |
| { |
| VARTYPE vt = V_VT(pvar); |
| PVOID ref = NULL; |
| |
| TRACE("(%x,%p)\n", *pFlags, pvar); |
| TRACE("vt=%04x\n", V_VT(pvar)); |
| |
| if (vt & VT_BYREF) ref = pvar->n1.n2.n3.byref; |
| |
| VariantClear(pvar); |
| if (!ref) return; |
| |
| if(vt & VT_ARRAY) |
| { |
| if (vt & VT_BYREF) |
| LPSAFEARRAY_UserFree(pFlags, V_ARRAYREF(pvar)); |
| else |
| LPSAFEARRAY_UserFree(pFlags, &V_ARRAY(pvar)); |
| } |
| else |
| { |
| switch (vt) |
| { |
| case VT_BSTR | VT_BYREF: |
| BSTR_UserFree(pFlags, V_BSTRREF(pvar)); |
| break; |
| case VT_VARIANT | VT_BYREF: |
| VARIANT_UserFree(pFlags, V_VARIANTREF(pvar)); |
| break; |
| case VT_RECORD | VT_BYREF: |
| FIXME("handle BRECORD by ref\n"); |
| break; |
| case VT_UNKNOWN | VT_BYREF: |
| case VT_DISPATCH | VT_BYREF: |
| IUnknown_Release(*V_UNKNOWNREF(pvar)); |
| break; |
| } |
| } |
| |
| CoTaskMemFree(ref); |
| } |
| |
| /* LPSAFEARRAY */ |
| |
| /* Get the number of cells in a SafeArray */ |
| static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa) |
| { |
| const SAFEARRAYBOUND* psab = psa->rgsabound; |
| USHORT cCount = psa->cDims; |
| ULONG ulNumCells = 1; |
| |
| while (cCount--) |
| { |
| /* This is a valid bordercase. See testcases. -Marcus */ |
| if (!psab->cElements) |
| return 0; |
| ulNumCells *= psab->cElements; |
| psab++; |
| } |
| return ulNumCells; |
| } |
| |
| static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa) |
| { |
| VARTYPE vt; |
| HRESULT hr; |
| |
| hr = SafeArrayGetVartype(psa, &vt); |
| if (FAILED(hr)) |
| { |
| if(psa->fFeatures & FADF_VARIANT) return SF_VARIANT; |
| |
| switch(psa->cbElements) |
| { |
| case 1: vt = VT_I1; break; |
| case 2: vt = VT_I2; break; |
| case 4: vt = VT_I4; break; |
| case 8: vt = VT_I8; break; |
| default: |
| RpcRaiseException(hr); |
| } |
| } |
| |
| if (psa->fFeatures & FADF_HAVEIID) |
| return SF_HAVEIID; |
| |
| switch (vt) |
| { |
| case VT_I1: |
| case VT_UI1: return SF_I1; |
| case VT_BOOL: |
| case VT_I2: |
| case VT_UI2: return SF_I2; |
| case VT_INT: |
| case VT_UINT: |
| case VT_I4: |
| case VT_UI4: |
| case VT_R4: return SF_I4; |
| case VT_DATE: |
| case VT_CY: |
| case VT_R8: |
| case VT_I8: |
| case VT_UI8: return SF_I8; |
| case VT_INT_PTR: |
| case VT_UINT_PTR: return (sizeof(UINT_PTR) == 4 ? SF_I4 : SF_I8); |
| case VT_BSTR: return SF_BSTR; |
| case VT_DISPATCH: return SF_DISPATCH; |
| case VT_VARIANT: return SF_VARIANT; |
| case VT_UNKNOWN: return SF_UNKNOWN; |
| /* Note: Return a non-zero size to indicate vt is valid. The actual size |
| * of a UDT is taken from the result of IRecordInfo_GetSize(). |
| */ |
| case VT_RECORD: return SF_RECORD; |
| default: return SF_ERROR; |
| } |
| } |
| |
| static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype) |
| { |
| if (sftype == SF_BSTR) |
| return sizeof(DWORD); |
| else if (sftype == SF_VARIANT) |
| return sizeof(variant_wire_t) - sizeof(DWORD); |
| else |
| return lpsa->cbElements; |
| } |
| |
| static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype) |
| { |
| if (sftype == SF_BSTR) |
| return sizeof(BSTR); |
| else if (sftype == SF_VARIANT) |
| return sizeof(VARIANT); |
| else |
| return wiresa->cbElements; |
| } |
| |
| ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa) |
| { |
| ULONG size = StartingSize; |
| |
| TRACE("("); dump_user_flags(pFlags); TRACE(", %d, %p\n", StartingSize, *ppsa); |
| |
| ALIGN_LENGTH(size, 3); |
| size += sizeof(ULONG); |
| if (*ppsa) |
| { |
| SAFEARRAY *psa = *ppsa; |
| ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); |
| SF_TYPE sftype; |
| HRESULT hr; |
| |
| size += sizeof(ULONG); |
| size += 2 * sizeof(USHORT) + 2 * sizeof(ULONG); |
| |
| sftype = SAFEARRAY_GetUnionType(psa); |
| size += sizeof(ULONG); |
| |
| size += sizeof(ULONG); |
| size += sizeof(ULONG); |
| if (sftype == SF_HAVEIID) |
| size += sizeof(IID); |
| |
| size += sizeof(psa->rgsabound[0]) * psa->cDims; |
| |
| size += sizeof(ULONG); |
| |
| switch (sftype) |
| { |
| case SF_BSTR: |
| { |
| BSTR* lpBstr; |
| |
| for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++) |
| size = BSTR_UserSize(pFlags, size, lpBstr); |
| |
| break; |
| } |
| case SF_DISPATCH: |
| case SF_UNKNOWN: |
| case SF_HAVEIID: |
| FIXME("size interfaces\n"); |
| break; |
| case SF_VARIANT: |
| { |
| VARIANT* lpVariant; |
| |
| for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++) |
| size = VARIANT_UserSize(pFlags, size, lpVariant); |
| |
| break; |
| } |
| case SF_RECORD: |
| { |
| IRecordInfo* pRecInfo = NULL; |
| |
| hr = SafeArrayGetRecordInfo(psa, &pRecInfo); |
| if (FAILED(hr)) |
| RpcRaiseException(hr); |
| |
| if (pRecInfo) |
| { |
| FIXME("size record info %p\n", pRecInfo); |
| |
| IRecordInfo_Release(pRecInfo); |
| } |
| break; |
| } |
| case SF_I8: |
| ALIGN_LENGTH(size, 7); |
| /* fallthrough */ |
| case SF_I1: |
| case SF_I2: |
| case SF_I4: |
| size += ulCellCount * psa->cbElements; |
| break; |
| default: |
| break; |
| } |
| |
| } |
| |
| return size; |
| } |
| |
| unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) |
| { |
| HRESULT hr; |
| |
| TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", Buffer, *ppsa); |
| |
| ALIGN_POINTER(Buffer, 3); |
| *(ULONG *)Buffer = *ppsa ? 0x1 : 0x0; |
| Buffer += sizeof(ULONG); |
| if (*ppsa) |
| { |
| VARTYPE vt; |
| SAFEARRAY *psa = *ppsa; |
| ULONG ulCellCount = SAFEARRAY_GetCellCount(psa); |
| SAFEARRAYBOUND *bound; |
| SF_TYPE sftype; |
| GUID guid; |
| INT i; |
| |
| sftype = SAFEARRAY_GetUnionType(psa); |
| |
| *(ULONG *)Buffer = psa->cDims; |
| Buffer += sizeof(ULONG); |
| *(USHORT *)Buffer = psa->cDims; |
| Buffer += sizeof(USHORT); |
| *(USHORT *)Buffer = psa->fFeatures; |
| Buffer += sizeof(USHORT); |
| *(ULONG *)Buffer = elem_wire_size(psa, sftype); |
| Buffer += sizeof(ULONG); |
| |
| hr = SafeArrayGetVartype(psa, &vt); |
| if (FAILED(hr)) vt = 0; |
| |
| *(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16); |
| Buffer += sizeof(ULONG); |
| |
| *(ULONG *)Buffer = sftype; |
| Buffer += sizeof(ULONG); |
| |
| *(ULONG *)Buffer = ulCellCount; |
| Buffer += sizeof(ULONG); |
| *(ULONG *)Buffer = psa->pvData ? 0x2 : 0x0; |
| Buffer += sizeof(ULONG); |
| if (sftype == SF_HAVEIID) |
| { |
| SafeArrayGetIID(psa, &guid); |
| memcpy(Buffer, &guid, sizeof(guid)); |
| Buffer += sizeof(guid); |
| } |
| |
| /* bounds are marshaled in opposite order comparing to storage layout */ |
| bound = (SAFEARRAYBOUND*)Buffer; |
| for (i = 0; i < psa->cDims; i++) |
| { |
| memcpy(bound++, &psa->rgsabound[psa->cDims-i-1], sizeof(psa->rgsabound[0])); |
| } |
| Buffer += sizeof(psa->rgsabound[0]) * psa->cDims; |
| |
| *(ULONG *)Buffer = ulCellCount; |
| Buffer += sizeof(ULONG); |
| |
| if (psa->pvData) |
| { |
| switch (sftype) |
| { |
| case SF_BSTR: |
| { |
| BSTR* lpBstr; |
| |
| for (lpBstr = psa->pvData; ulCellCount; ulCellCount--, lpBstr++) |
| Buffer = BSTR_UserMarshal(pFlags, Buffer, lpBstr); |
| |
| break; |
| } |
| case SF_DISPATCH: |
| case SF_UNKNOWN: |
| case SF_HAVEIID: |
| FIXME("marshal interfaces\n"); |
| break; |
| case SF_VARIANT: |
| { |
| VARIANT* lpVariant; |
| |
| for (lpVariant = psa->pvData; ulCellCount; ulCellCount--, lpVariant++) |
| Buffer = VARIANT_UserMarshal(pFlags, Buffer, lpVariant); |
| |
| break; |
| } |
| case SF_RECORD: |
| { |
| IRecordInfo* pRecInfo = NULL; |
| |
| hr = SafeArrayGetRecordInfo(psa, &pRecInfo); |
| if (FAILED(hr)) |
| RpcRaiseException(hr); |
| |
| if (pRecInfo) |
| { |
| FIXME("write record info %p\n", pRecInfo); |
| |
| IRecordInfo_Release(pRecInfo); |
| } |
| break; |
| } |
| |
| case SF_I8: |
| ALIGN_POINTER(Buffer, 7); |
| /* fallthrough */ |
| case SF_I1: |
| case SF_I2: |
| case SF_I4: |
| /* Just copy the data over */ |
| memcpy(Buffer, psa->pvData, ulCellCount * psa->cbElements); |
| Buffer += ulCellCount * psa->cbElements; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| } |
| return Buffer; |
| } |
| |
| #define FADF_AUTOSETFLAGS (FADF_HAVEIID | FADF_RECORD | FADF_HAVEVARTYPE | \ |
| FADF_BSTR | FADF_UNKNOWN | FADF_DISPATCH | \ |
| FADF_VARIANT | FADF_CREATEVECTOR) |
| |
| unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, LPSAFEARRAY *ppsa) |
| { |
| ULONG ptr; |
| wireSAFEARRAY wiresa; |
| ULONG cDims; |
| HRESULT hr; |
| SF_TYPE sftype; |
| ULONG cell_count; |
| GUID guid; |
| VARTYPE vt; |
| SAFEARRAYBOUND *wiresab; |
| |
| TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", Buffer, ppsa); |
| |
| ALIGN_POINTER(Buffer, 3); |
| ptr = *(ULONG *)Buffer; |
| Buffer += sizeof(ULONG); |
| |
| if (!ptr) |
| { |
| *ppsa = NULL; |
| |
| TRACE("NULL safe array unmarshaled\n"); |
| |
| return Buffer; |
| } |
| |
| cDims = *(ULONG *)Buffer; |
| Buffer += sizeof(ULONG); |
| |
| wiresa = (wireSAFEARRAY)Buffer; |
| Buffer += 2 * sizeof(USHORT) + 2 * sizeof(ULONG); |
| |
| if (cDims != wiresa->cDims) |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| |
| /* FIXME: there should be a limit on how large cDims can be */ |
| |
| vt = HIWORD(wiresa->cLocks); |
| |
| sftype = *(ULONG *)Buffer; |
| Buffer += sizeof(ULONG); |
| |
| cell_count = *(ULONG *)Buffer; |
| Buffer += sizeof(ULONG); |
| ptr = *(ULONG *)Buffer; |
| Buffer += sizeof(ULONG); |
| if (sftype == SF_HAVEIID) |
| { |
| memcpy(&guid, Buffer, sizeof(guid)); |
| Buffer += sizeof(guid); |
| } |
| |
| wiresab = (SAFEARRAYBOUND *)Buffer; |
| Buffer += sizeof(wiresab[0]) * wiresa->cDims; |
| |
| if(vt) |
| { |
| *ppsa = SafeArrayCreateEx(vt, wiresa->cDims, wiresab, NULL); |
| if (!*ppsa) RpcRaiseException(E_OUTOFMEMORY); |
| } |
| else |
| { |
| if (FAILED(SafeArrayAllocDescriptor(wiresa->cDims, ppsa))) |
| RpcRaiseException(E_OUTOFMEMORY); |
| memcpy((*ppsa)->rgsabound, wiresab, sizeof(SAFEARRAYBOUND) * wiresa->cDims); |
| } |
| |
| /* be careful about which flags we set since they could be a security |
| * risk */ |
| (*ppsa)->fFeatures &= FADF_AUTOSETFLAGS; |
| (*ppsa)->fFeatures |= (wiresa->fFeatures & ~(FADF_AUTOSETFLAGS)); |
| /* FIXME: there should be a limit on how large wiresa->cbElements can be */ |
| (*ppsa)->cbElements = elem_mem_size(wiresa, sftype); |
| (*ppsa)->cLocks = 0; |
| |
| /* SafeArrayCreateEx allocates the data for us, but |
| * SafeArrayAllocDescriptor doesn't */ |
| if(!vt) |
| { |
| hr = SafeArrayAllocData(*ppsa); |
| if (FAILED(hr)) |
| RpcRaiseException(hr); |
| } |
| |
| if ((*(ULONG *)Buffer != cell_count) || (SAFEARRAY_GetCellCount(*ppsa) != cell_count)) |
| RpcRaiseException(RPC_S_INVALID_BOUND); |
| Buffer += sizeof(ULONG); |
| |
| if (ptr) |
| { |
| switch (sftype) |
| { |
| case SF_BSTR: |
| { |
| BSTR* lpBstr; |
| |
| for (lpBstr = (*ppsa)->pvData; cell_count; cell_count--, lpBstr++) |
| Buffer = BSTR_UserUnmarshal(pFlags, Buffer, lpBstr); |
| |
| break; |
| } |
| case SF_DISPATCH: |
| case SF_UNKNOWN: |
| case SF_HAVEIID: |
| FIXME("marshal interfaces\n"); |
| break; |
| case SF_VARIANT: |
| { |
| VARIANT* lpVariant; |
| |
| for (lpVariant = (*ppsa)->pvData; cell_count; cell_count--, lpVariant++) |
| Buffer = VARIANT_UserUnmarshal(pFlags, Buffer, lpVariant); |
| |
| break; |
| } |
| case SF_RECORD: |
| { |
| FIXME("set record info\n"); |
| |
| break; |
| } |
| |
| case SF_I8: |
| ALIGN_POINTER(Buffer, 7); |
| /* fallthrough */ |
| case SF_I1: |
| case SF_I2: |
| case SF_I4: |
| /* Just copy the data over */ |
| memcpy((*ppsa)->pvData, Buffer, cell_count * (*ppsa)->cbElements); |
| Buffer += cell_count * (*ppsa)->cbElements; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| TRACE("safe array unmarshaled: %p\n", *ppsa); |
| |
| return Buffer; |
| } |
| |
| void WINAPI LPSAFEARRAY_UserFree(ULONG *pFlags, LPSAFEARRAY *ppsa) |
| { |
| TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *ppsa); |
| |
| SafeArrayDestroy(*ppsa); |
| } |
| |
| |
| ULONG WINAPI HFONT_UserSize(ULONG *pFlags, ULONG Start, HFONT *phfont) |
| { |
| FIXME(":stub\n"); |
| return 0; |
| } |
| |
| unsigned char * WINAPI HFONT_UserMarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont) |
| { |
| FIXME(":stub\n"); |
| return NULL; |
| } |
| |
| unsigned char * WINAPI HFONT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffer, HFONT *phfont) |
| { |
| FIXME(":stub\n"); |
| return NULL; |
| } |
| |
| void WINAPI HFONT_UserFree(ULONG *pFlags, HFONT *phfont) |
| { |
| FIXME(":stub\n"); |
| return; |
| } |
| |
| |
| /* IDispatch */ |
| /* exactly how Invoke is marshalled is not very clear to me yet, |
| * but the way I've done it seems to work for me */ |
| |
| HRESULT CALLBACK IDispatch_Invoke_Proxy( |
| IDispatch* This, |
| DISPID dispIdMember, |
| REFIID riid, |
| LCID lcid, |
| WORD wFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExcepInfo, |
| UINT* puArgErr) |
| { |
| HRESULT hr; |
| VARIANT VarResult; |
| UINT* rgVarRefIdx = NULL; |
| VARIANTARG* rgVarRef = NULL; |
| UINT u, cVarRef; |
| UINT uArgErr; |
| EXCEPINFO ExcepInfo; |
| |
| TRACE("(%p)->(%d,%s,%x,%x,%p,%p,%p,%p)\n", This, |
| dispIdMember, debugstr_guid(riid), |
| lcid, wFlags, pDispParams, pVarResult, |
| pExcepInfo, puArgErr); |
| |
| /* [out] args can't be null, use dummy vars if needed */ |
| if (!pVarResult) pVarResult = &VarResult; |
| if (!puArgErr) puArgErr = &uArgErr; |
| if (!pExcepInfo) pExcepInfo = &ExcepInfo; |
| |
| /* count by-ref args */ |
| for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) { |
| VARIANTARG* arg = &pDispParams->rgvarg[u]; |
| if (V_ISBYREF(arg)) { |
| cVarRef++; |
| } |
| } |
| if (cVarRef) { |
| rgVarRefIdx = CoTaskMemAlloc(sizeof(UINT)*cVarRef); |
| rgVarRef = CoTaskMemAlloc(sizeof(VARIANTARG)*cVarRef); |
| /* make list of by-ref args */ |
| for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) { |
| VARIANTARG* arg = &pDispParams->rgvarg[u]; |
| if (V_ISBYREF(arg)) { |
| rgVarRefIdx[cVarRef] = u; |
| VariantInit(&rgVarRef[cVarRef]); |
| VariantCopy(&rgVarRef[cVarRef], arg); |
| VariantClear(arg); |
| cVarRef++; |
| } |
| } |
| } else { |
| /* [out] args still can't be null, |
| * but we can point these anywhere in this case, |
| * since they won't be written to when cVarRef is 0 */ |
| rgVarRefIdx = puArgErr; |
| rgVarRef = pVarResult; |
| } |
| TRACE("passed by ref: %d args\n", cVarRef); |
| hr = IDispatch_RemoteInvoke_Proxy(This, |
| dispIdMember, |
| riid, |
| lcid, |
| wFlags, |
| pDispParams, |
| pVarResult, |
| pExcepInfo, |
| puArgErr, |
| cVarRef, |
| rgVarRefIdx, |
| rgVarRef); |
| if (cVarRef) { |
| for (u=0; u<cVarRef; u++) { |
| unsigned i = rgVarRefIdx[u]; |
| VariantCopy(&pDispParams->rgvarg[i], |
| &rgVarRef[u]); |
| VariantClear(&rgVarRef[u]); |
| } |
| CoTaskMemFree(rgVarRef); |
| CoTaskMemFree(rgVarRefIdx); |
| } |
| |
| if(pExcepInfo == &ExcepInfo) |
| { |
| SysFreeString(pExcepInfo->bstrSource); |
| SysFreeString(pExcepInfo->bstrDescription); |
| SysFreeString(pExcepInfo->bstrHelpFile); |
| } |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB IDispatch_Invoke_Stub( |
| IDispatch* This, |
| DISPID dispIdMember, |
| REFIID riid, |
| LCID lcid, |
| DWORD dwFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExcepInfo, |
| UINT* pArgErr, |
| UINT cVarRef, |
| UINT* rgVarRefIdx, |
| VARIANTARG* rgVarRef) |
| { |
| HRESULT hr = S_OK; |
| VARIANTARG *rgvarg, *arg; |
| UINT u; |
| |
| /* initialize out parameters, so that they can be marshalled |
| * in case the real Invoke doesn't initialize them */ |
| VariantInit(pVarResult); |
| memset(pExcepInfo, 0, sizeof(*pExcepInfo)); |
| *pArgErr = 0; |
| |
| /* let the real Invoke operate on a copy of the in parameters, |
| * so we don't risk losing pointers to allocated memory */ |
| rgvarg = pDispParams->rgvarg; |
| arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs); |
| if (!arg) return E_OUTOFMEMORY; |
| |
| /* init all args so we can call VariantClear on all the args if the copy |
| * below fails */ |
| for (u = 0; u < pDispParams->cArgs; u++) |
| VariantInit(&arg[u]); |
| |
| for (u = 0; u < pDispParams->cArgs; u++) { |
| hr = VariantCopy(&arg[u], &rgvarg[u]); |
| if (FAILED(hr)) |
| break; |
| } |
| |
| if (SUCCEEDED(hr)) { |
| /* copy ref args to arg array */ |
| for (u=0; u<cVarRef; u++) { |
| unsigned i = rgVarRefIdx[u]; |
| VariantCopy(&arg[i], &rgVarRef[u]); |
| } |
| |
| pDispParams->rgvarg = arg; |
| |
| hr = IDispatch_Invoke(This, |
| dispIdMember, |
| riid, |
| lcid, |
| dwFlags, |
| pDispParams, |
| pVarResult, |
| pExcepInfo, |
| pArgErr); |
| |
| /* copy ref args from arg array */ |
| for (u=0; u<cVarRef; u++) { |
| unsigned i = rgVarRefIdx[u]; |
| VariantCopy(&rgVarRef[u], &arg[i]); |
| } |
| } |
| |
| /* clear the duplicate argument list */ |
| for (u=0; u<pDispParams->cArgs; u++) |
| VariantClear(&arg[u]); |
| |
| pDispParams->rgvarg = rgvarg; |
| CoTaskMemFree(arg); |
| |
| return hr; |
| } |
| |
| /* IEnumVARIANT */ |
| |
| HRESULT CALLBACK IEnumVARIANT_Next_Proxy( |
| IEnumVARIANT* This, |
| ULONG celt, |
| VARIANT* rgVar, |
| ULONG* pCeltFetched) |
| { |
| ULONG fetched; |
| if (!pCeltFetched) |
| pCeltFetched = &fetched; |
| return IEnumVARIANT_RemoteNext_Proxy(This, |
| celt, |
| rgVar, |
| pCeltFetched); |
| } |
| |
| HRESULT __RPC_STUB IEnumVARIANT_Next_Stub( |
| IEnumVARIANT* This, |
| ULONG celt, |
| VARIANT* rgVar, |
| ULONG* pCeltFetched) |
| { |
| HRESULT hr; |
| *pCeltFetched = 0; |
| hr = IEnumVARIANT_Next(This, |
| celt, |
| rgVar, |
| pCeltFetched); |
| if (hr == S_OK) *pCeltFetched = celt; |
| return hr; |
| } |
| |
| /* TypeInfo related freers */ |
| |
| static void free_embedded_typedesc(TYPEDESC *tdesc); |
| static void free_embedded_arraydesc(ARRAYDESC *adesc) |
| { |
| switch(adesc->tdescElem.vt) |
| { |
| case VT_PTR: |
| case VT_SAFEARRAY: |
| free_embedded_typedesc(adesc->tdescElem.u.lptdesc); |
| CoTaskMemFree(adesc->tdescElem.u.lptdesc); |
| break; |
| case VT_CARRAY: |
| free_embedded_arraydesc(adesc->tdescElem.u.lpadesc); |
| CoTaskMemFree(adesc->tdescElem.u.lpadesc); |
| break; |
| } |
| } |
| |
| static void free_embedded_typedesc(TYPEDESC *tdesc) |
| { |
| switch(tdesc->vt) |
| { |
| case VT_PTR: |
| case VT_SAFEARRAY: |
| free_embedded_typedesc(tdesc->u.lptdesc); |
| CoTaskMemFree(tdesc->u.lptdesc); |
| break; |
| case VT_CARRAY: |
| free_embedded_arraydesc(tdesc->u.lpadesc); |
| CoTaskMemFree(tdesc->u.lpadesc); |
| break; |
| } |
| } |
| |
| static void free_embedded_elemdesc(ELEMDESC *edesc) |
| { |
| free_embedded_typedesc(&edesc->tdesc); |
| if(edesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) |
| CoTaskMemFree(edesc->u.paramdesc.pparamdescex); |
| } |
| |
| /* ITypeComp */ |
| |
| HRESULT CALLBACK ITypeComp_Bind_Proxy( |
| ITypeComp* This, |
| LPOLESTR szName, |
| ULONG lHashVal, |
| WORD wFlags, |
| ITypeInfo** ppTInfo, |
| DESCKIND* pDescKind, |
| BINDPTR* pBindPtr) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeComp_Bind_Stub( |
| ITypeComp* This, |
| LPOLESTR szName, |
| ULONG lHashVal, |
| WORD wFlags, |
| ITypeInfo** ppTInfo, |
| DESCKIND* pDescKind, |
| LPFUNCDESC* ppFuncDesc, |
| LPVARDESC* ppVarDesc, |
| ITypeComp** ppTypeComp, |
| CLEANLOCALSTORAGE* pDummy) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeComp_BindType_Proxy( |
| ITypeComp* This, |
| LPOLESTR szName, |
| ULONG lHashVal, |
| ITypeInfo** ppTInfo, |
| ITypeComp** ppTComp) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeComp_BindType_Stub( |
| ITypeComp* This, |
| LPOLESTR szName, |
| ULONG lHashVal, |
| ITypeInfo** ppTInfo) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| /* ITypeInfo */ |
| |
| HRESULT CALLBACK ITypeInfo_GetTypeAttr_Proxy( |
| ITypeInfo* This, |
| TYPEATTR** ppTypeAttr) |
| |
| { |
| CLEANLOCALSTORAGE stg; |
| TRACE("(%p, %p)\n", This, ppTypeAttr); |
| |
| stg.flags = 0; |
| stg.pStorage = NULL; |
| stg.pInterface = NULL; |
| |
| return ITypeInfo_RemoteGetTypeAttr_Proxy(This, ppTypeAttr, &stg); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetTypeAttr_Stub( |
| ITypeInfo* This, |
| LPTYPEATTR* ppTypeAttr, |
| CLEANLOCALSTORAGE* pDummy) |
| { |
| HRESULT hr; |
| TRACE("(%p, %p)\n", This, ppTypeAttr); |
| |
| hr = ITypeInfo_GetTypeAttr(This, ppTypeAttr); |
| if(hr != S_OK) |
| return hr; |
| |
| pDummy->flags = CLS_TYPEATTR; |
| ITypeInfo_AddRef(This); |
| pDummy->pInterface = (IUnknown*)This; |
| pDummy->pStorage = ppTypeAttr; |
| return hr; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetFuncDesc_Proxy( |
| ITypeInfo* This, |
| UINT index, |
| FUNCDESC** ppFuncDesc) |
| { |
| CLEANLOCALSTORAGE stg; |
| TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc); |
| |
| stg.flags = 0; |
| stg.pStorage = NULL; |
| stg.pInterface = NULL; |
| |
| return ITypeInfo_RemoteGetFuncDesc_Proxy(This, index, ppFuncDesc, &stg); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub( |
| ITypeInfo* This, |
| UINT index, |
| LPFUNCDESC* ppFuncDesc, |
| CLEANLOCALSTORAGE* pDummy) |
| { |
| HRESULT hr; |
| TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc); |
| |
| hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc); |
| if(hr != S_OK) |
| return hr; |
| |
| pDummy->flags = CLS_FUNCDESC; |
| ITypeInfo_AddRef(This); |
| pDummy->pInterface = (IUnknown*)This; |
| pDummy->pStorage = ppFuncDesc; |
| return hr; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetVarDesc_Proxy( |
| ITypeInfo* This, |
| UINT index, |
| VARDESC** ppVarDesc) |
| { |
| CLEANLOCALSTORAGE stg; |
| TRACE("(%p, %d, %p)\n", This, index, ppVarDesc); |
| |
| stg.flags = 0; |
| stg.pStorage = NULL; |
| stg.pInterface = NULL; |
| |
| return ITypeInfo_RemoteGetVarDesc_Proxy(This, index, ppVarDesc, &stg); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetVarDesc_Stub( |
| ITypeInfo* This, |
| UINT index, |
| LPVARDESC* ppVarDesc, |
| CLEANLOCALSTORAGE* pDummy) |
| { |
| HRESULT hr; |
| TRACE("(%p, %d, %p)\n", This, index, ppVarDesc); |
| |
| hr = ITypeInfo_GetVarDesc(This, index, ppVarDesc); |
| if(hr != S_OK) |
| return hr; |
| |
| pDummy->flags = CLS_VARDESC; |
| ITypeInfo_AddRef(This); |
| pDummy->pInterface = (IUnknown*)This; |
| pDummy->pStorage = ppVarDesc; |
| return hr; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetNames_Proxy( |
| ITypeInfo* This, |
| MEMBERID memid, |
| BSTR* rgBstrNames, |
| UINT cMaxNames, |
| UINT* pcNames) |
| { |
| TRACE("(%p, %08x, %p, %d, %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); |
| |
| return ITypeInfo_RemoteGetNames_Proxy(This, memid, rgBstrNames, cMaxNames, pcNames); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetNames_Stub( |
| ITypeInfo* This, |
| MEMBERID memid, |
| BSTR* rgBstrNames, |
| UINT cMaxNames, |
| UINT* pcNames) |
| { |
| TRACE("(%p, %08x, %p, %d, %p)\n", This, memid, rgBstrNames, cMaxNames, pcNames); |
| |
| return ITypeInfo_GetNames(This, memid, rgBstrNames, cMaxNames, pcNames); |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetIDsOfNames_Proxy( |
| ITypeInfo* This, |
| LPOLESTR* rgszNames, |
| UINT cNames, |
| MEMBERID* pMemId) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetIDsOfNames_Stub( |
| ITypeInfo* This) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_Invoke_Proxy( |
| ITypeInfo* This, |
| PVOID pvInstance, |
| MEMBERID memid, |
| WORD wFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExcepInfo, |
| UINT* puArgErr) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_Invoke_Stub( |
| ITypeInfo* This) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetDocumentation_Proxy(ITypeInfo *This, MEMBERID memid, |
| BSTR *name, BSTR *doc_string, |
| DWORD *help_context, BSTR *help_file) |
| { |
| DWORD dummy_help_context, flags = 0; |
| BSTR dummy_name, dummy_doc_string, dummy_help_file; |
| HRESULT hr; |
| TRACE("(%p, %08x, %p, %p, %p, %p)\n", This, memid, name, doc_string, help_context, help_file); |
| |
| if(!name) name = &dummy_name; |
| else flags = 1; |
| |
| if(!doc_string) doc_string = &dummy_doc_string; |
| else flags |= 2; |
| |
| if(!help_context) help_context = &dummy_help_context; |
| else flags |= 4; |
| |
| if(!help_file) help_file = &dummy_help_file; |
| else flags |= 8; |
| |
| hr = ITypeInfo_RemoteGetDocumentation_Proxy(This, memid, flags, name, doc_string, help_context, help_file); |
| |
| /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ |
| |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetDocumentation_Stub(ITypeInfo *This, MEMBERID memid, |
| DWORD flags, BSTR *name, BSTR *doc_string, |
| DWORD *help_context, BSTR *help_file) |
| { |
| TRACE("(%p, %08x, %08x, %p, %p, %p, %p)\n", This, memid, flags, name, doc_string, help_context, help_file); |
| |
| *name = *doc_string = *help_file = NULL; |
| *help_context = 0; |
| |
| if(!(flags & 1)) name = NULL; |
| if(!(flags & 2)) doc_string = NULL; |
| if(!(flags & 4)) help_context = NULL; |
| if(!(flags & 8)) help_file = NULL; |
| |
| return ITypeInfo_GetDocumentation(This, memid, name, doc_string, help_context, help_file); |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetDllEntry_Proxy(ITypeInfo *This, MEMBERID memid, |
| INVOKEKIND invkind, BSTR *dll_name, |
| BSTR* name, WORD *ordinal) |
| { |
| DWORD flags = 0; |
| BSTR dummy_dll_name, dummy_name; |
| WORD dummy_ordinal; |
| HRESULT hr; |
| TRACE("(%p, %08x, %x, %p, %p, %p)\n", This, memid, invkind, dll_name, name, ordinal); |
| |
| if(!dll_name) dll_name = &dummy_dll_name; |
| else flags = 1; |
| |
| if(!name) name = &dummy_name; |
| else flags |= 2; |
| |
| if(!ordinal) ordinal = &dummy_ordinal; |
| else flags |= 4; |
| |
| hr = ITypeInfo_RemoteGetDllEntry_Proxy(This, memid, invkind, flags, dll_name, name, ordinal); |
| |
| /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ |
| |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetDllEntry_Stub(ITypeInfo *This, MEMBERID memid, |
| INVOKEKIND invkind, DWORD flags, |
| BSTR *dll_name, BSTR *name, |
| WORD *ordinal) |
| { |
| TRACE("(%p, %08x, %x, %p, %p, %p)\n", This, memid, invkind, dll_name, name, ordinal); |
| |
| *dll_name = *name = NULL; |
| *ordinal = 0; |
| |
| if(!(flags & 1)) dll_name = NULL; |
| if(!(flags & 2)) name = NULL; |
| if(!(flags & 4)) ordinal = NULL; |
| |
| return ITypeInfo_GetDllEntry(This, memid, invkind, dll_name, name, ordinal); |
| } |
| |
| HRESULT CALLBACK ITypeInfo_AddressOfMember_Proxy( |
| ITypeInfo* This, |
| MEMBERID memid, |
| INVOKEKIND invKind, |
| PVOID* ppv) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_AddressOfMember_Stub( |
| ITypeInfo* This) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_CreateInstance_Proxy( |
| ITypeInfo* This, |
| IUnknown* pUnkOuter, |
| REFIID riid, |
| PVOID* ppvObj) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_CreateInstance_Stub( |
| ITypeInfo* This, |
| REFIID riid, |
| IUnknown** ppvObj) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeInfo_GetContainingTypeLib_Proxy( |
| ITypeInfo* This, |
| ITypeLib** ppTLib, |
| UINT* pIndex) |
| { |
| ITypeLib *pTL; |
| UINT index; |
| HRESULT hr; |
| |
| TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex ); |
| |
| hr = ITypeInfo_RemoteGetContainingTypeLib_Proxy(This, &pTL, &index); |
| if(SUCCEEDED(hr)) |
| { |
| if(pIndex) |
| *pIndex = index; |
| |
| if(ppTLib) |
| *ppTLib = pTL; |
| else |
| ITypeLib_Release(pTL); |
| } |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub( |
| ITypeInfo* This, |
| ITypeLib** ppTLib, |
| UINT* pIndex) |
| { |
| TRACE("(%p, %p, %p)\n", This, ppTLib, pIndex ); |
| return ITypeInfo_GetContainingTypeLib(This, ppTLib, pIndex); |
| } |
| |
| void CALLBACK ITypeInfo_ReleaseTypeAttr_Proxy( |
| ITypeInfo* This, |
| TYPEATTR* pTypeAttr) |
| { |
| TRACE("(%p, %p)\n", This, pTypeAttr); |
| free_embedded_typedesc(&pTypeAttr->tdescAlias); |
| CoTaskMemFree(pTypeAttr); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub( |
| ITypeInfo* This) |
| { |
| TRACE("nothing to do\n"); |
| return S_OK; |
| } |
| |
| void CALLBACK ITypeInfo_ReleaseFuncDesc_Proxy( |
| ITypeInfo* This, |
| FUNCDESC* pFuncDesc) |
| { |
| SHORT param; |
| TRACE("(%p, %p)\n", This, pFuncDesc); |
| |
| for(param = 0; param < pFuncDesc->cParams; param++) |
| free_embedded_elemdesc(pFuncDesc->lprgelemdescParam + param); |
| if(param) |
| CoTaskMemFree(pFuncDesc->lprgelemdescParam); |
| |
| free_embedded_elemdesc(&pFuncDesc->elemdescFunc); |
| |
| if(pFuncDesc->cScodes != 0 && pFuncDesc->cScodes != -1) |
| CoTaskMemFree(pFuncDesc->lprgscode); |
| |
| CoTaskMemFree(pFuncDesc); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub( |
| ITypeInfo* This) |
| { |
| TRACE("nothing to do\n"); |
| return S_OK; |
| } |
| |
| void CALLBACK ITypeInfo_ReleaseVarDesc_Proxy( |
| ITypeInfo* This, |
| VARDESC* pVarDesc) |
| { |
| TRACE("(%p, %p)\n", This, pVarDesc); |
| |
| CoTaskMemFree(pVarDesc->lpstrSchema); |
| |
| if(pVarDesc->varkind == VAR_CONST) |
| CoTaskMemFree(pVarDesc->u.lpvarValue); |
| |
| free_embedded_elemdesc(&pVarDesc->elemdescVar); |
| CoTaskMemFree(pVarDesc); |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub( |
| ITypeInfo* This) |
| { |
| TRACE("nothing to do\n"); |
| return S_OK; |
| } |
| |
| |
| /* ITypeInfo2 */ |
| |
| HRESULT CALLBACK ITypeInfo2_GetDocumentation2_Proxy(ITypeInfo2 *This, MEMBERID memid, |
| LCID lcid, BSTR *help_string, |
| DWORD *help_context, BSTR *help_dll) |
| { |
| DWORD dummy_help_context, flags = 0; |
| BSTR dummy_help_string, dummy_help_dll; |
| HRESULT hr; |
| TRACE("(%p, %08x, %08x, %p, %p, %p)\n", This, memid, lcid, help_string, help_context, help_dll); |
| |
| if(!help_string) help_string = &dummy_help_string; |
| else flags = 1; |
| |
| if(!help_context) help_context = &dummy_help_context; |
| else flags |= 2; |
| |
| if(!help_dll) help_dll = &dummy_help_dll; |
| else flags |= 4; |
| |
| hr = ITypeInfo2_RemoteGetDocumentation2_Proxy(This, memid, lcid, flags, help_string, help_context, help_dll); |
| |
| /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ |
| |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeInfo2_GetDocumentation2_Stub(ITypeInfo2 *This, MEMBERID memid, |
| LCID lcid, DWORD flags, |
| BSTR *help_string, DWORD *help_context, |
| BSTR *help_dll) |
| { |
| TRACE("(%p, %08x, %08x, %08x, %p, %p, %p)\n", This, memid, lcid, flags, help_string, help_context, help_dll); |
| |
| *help_string = *help_dll = NULL; |
| *help_context = 0; |
| |
| if(!(flags & 1)) help_string = NULL; |
| if(!(flags & 2)) help_context = NULL; |
| if(!(flags & 4)) help_dll = NULL; |
| |
| return ITypeInfo2_GetDocumentation2(This, memid, lcid, help_string, help_context, help_dll); |
| } |
| |
| /* ITypeLib */ |
| |
| UINT CALLBACK ITypeLib_GetTypeInfoCount_Proxy( |
| ITypeLib* This) |
| { |
| UINT count = 0; |
| TRACE("(%p)\n", This); |
| |
| ITypeLib_RemoteGetTypeInfoCount_Proxy(This, &count); |
| |
| return count; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_GetTypeInfoCount_Stub( |
| ITypeLib* This, |
| UINT* pcTInfo) |
| { |
| TRACE("(%p, %p)\n", This, pcTInfo); |
| *pcTInfo = ITypeLib_GetTypeInfoCount(This); |
| return S_OK; |
| } |
| |
| HRESULT CALLBACK ITypeLib_GetLibAttr_Proxy( |
| ITypeLib* This, |
| TLIBATTR** ppTLibAttr) |
| { |
| CLEANLOCALSTORAGE stg; |
| TRACE("(%p, %p)\n", This, ppTLibAttr); |
| |
| stg.flags = 0; |
| stg.pStorage = NULL; |
| stg.pInterface = NULL; |
| |
| return ITypeLib_RemoteGetLibAttr_Proxy(This, ppTLibAttr, &stg); |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_GetLibAttr_Stub( |
| ITypeLib* This, |
| LPTLIBATTR* ppTLibAttr, |
| CLEANLOCALSTORAGE* pDummy) |
| { |
| HRESULT hr; |
| TRACE("(%p, %p)\n", This, ppTLibAttr); |
| |
| hr = ITypeLib_GetLibAttr(This, ppTLibAttr); |
| if(hr != S_OK) |
| return hr; |
| |
| pDummy->flags = CLS_LIBATTR; |
| ITypeLib_AddRef(This); |
| pDummy->pInterface = (IUnknown*)This; |
| pDummy->pStorage = ppTLibAttr; |
| return hr; |
| } |
| |
| HRESULT CALLBACK ITypeLib_GetDocumentation_Proxy(ITypeLib *This, INT index, BSTR *name, |
| BSTR *doc_string, DWORD *help_context, |
| BSTR *help_file) |
| { |
| DWORD dummy_help_context, flags = 0; |
| BSTR dummy_name, dummy_doc_string, dummy_help_file; |
| HRESULT hr; |
| TRACE("(%p, %d, %p, %p, %p, %p)\n", This, index, name, doc_string, help_context, help_file); |
| |
| if(!name) name = &dummy_name; |
| else flags = 1; |
| |
| if(!doc_string) doc_string = &dummy_doc_string; |
| else flags |= 2; |
| |
| if(!help_context) help_context = &dummy_help_context; |
| else flags |= 4; |
| |
| if(!help_file) help_file = &dummy_help_file; |
| else flags |= 8; |
| |
| hr = ITypeLib_RemoteGetDocumentation_Proxy(This, index, flags, name, doc_string, help_context, help_file); |
| |
| /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ |
| |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_GetDocumentation_Stub(ITypeLib *This, INT index, DWORD flags, |
| BSTR *name, BSTR *doc_string, |
| DWORD *help_context, BSTR *help_file) |
| { |
| TRACE("(%p, %d, %08x, %p, %p, %p, %p)\n", This, index, flags, name, doc_string, help_context, help_file); |
| |
| *name = *doc_string = *help_file = NULL; |
| *help_context = 0; |
| |
| if(!(flags & 1)) name = NULL; |
| if(!(flags & 2)) doc_string = NULL; |
| if(!(flags & 4)) help_context = NULL; |
| if(!(flags & 8)) help_file = NULL; |
| |
| return ITypeLib_GetDocumentation(This, index, name, doc_string, help_context, help_file); |
| } |
| |
| HRESULT CALLBACK ITypeLib_IsName_Proxy( |
| ITypeLib* This, |
| LPOLESTR szNameBuf, |
| ULONG lHashVal, |
| BOOL* pfName) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_IsName_Stub( |
| ITypeLib* This, |
| LPOLESTR szNameBuf, |
| ULONG lHashVal, |
| BOOL* pfName, |
| BSTR* pBstrLibName) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeLib_FindName_Proxy( |
| ITypeLib* This, |
| LPOLESTR szNameBuf, |
| ULONG lHashVal, |
| ITypeInfo** ppTInfo, |
| MEMBERID* rgMemId, |
| USHORT* pcFound) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_FindName_Stub( |
| ITypeLib* This, |
| LPOLESTR szNameBuf, |
| ULONG lHashVal, |
| ITypeInfo** ppTInfo, |
| MEMBERID* rgMemId, |
| USHORT* pcFound, |
| BSTR* pBstrLibName) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| void CALLBACK ITypeLib_ReleaseTLibAttr_Proxy( |
| ITypeLib* This, |
| TLIBATTR* pTLibAttr) |
| { |
| TRACE("(%p, %p)\n", This, pTLibAttr); |
| CoTaskMemFree(pTLibAttr); |
| } |
| |
| HRESULT __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub( |
| ITypeLib* This) |
| { |
| TRACE("nothing to do\n"); |
| return S_OK; |
| } |
| |
| |
| /* ITypeLib2 */ |
| |
| HRESULT CALLBACK ITypeLib2_GetLibStatistics_Proxy( |
| ITypeLib2* This, |
| ULONG* pcUniqueNames, |
| ULONG* pcchUniqueNames) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib2_GetLibStatistics_Stub( |
| ITypeLib2* This, |
| ULONG* pcUniqueNames, |
| ULONG* pcchUniqueNames) |
| { |
| FIXME("not implemented\n"); |
| return E_FAIL; |
| } |
| |
| HRESULT CALLBACK ITypeLib2_GetDocumentation2_Proxy(ITypeLib2 *This, INT index, |
| LCID lcid, BSTR *help_string, |
| DWORD *help_context, BSTR *help_dll) |
| { |
| DWORD dummy_help_context, flags = 0; |
| BSTR dummy_help_string, dummy_help_dll; |
| HRESULT hr; |
| TRACE("(%p, %d, %08x, %p, %p, %p)\n", This, index, lcid, help_string, help_context, help_dll); |
| |
| if(!help_string) help_string = &dummy_help_string; |
| else flags = 1; |
| |
| if(!help_context) help_context = &dummy_help_context; |
| else flags |= 2; |
| |
| if(!help_dll) help_dll = &dummy_help_dll; |
| else flags |= 4; |
| |
| hr = ITypeLib2_RemoteGetDocumentation2_Proxy(This, index, lcid, flags, help_string, help_context, help_dll); |
| |
| /* We don't need to free the dummy BSTRs since the stub ensures that these will be NULLs. */ |
| |
| return hr; |
| } |
| |
| HRESULT __RPC_STUB ITypeLib2_GetDocumentation2_Stub(ITypeLib2 *This, INT index, LCID lcid, |
| DWORD flags, BSTR *help_string, |
| DWORD *help_context, BSTR *help_dll) |
| { |
| TRACE("(%p, %d, %08x, %08x, %p, %p, %p)\n", This, index, lcid, flags, help_string, help_context, help_dll); |
| |
| *help_string = *help_dll = NULL; |
| *help_context = 0; |
| |
| if(!(flags & 1)) help_string = NULL; |
| if(!(flags & 2)) help_context = NULL; |
| if(!(flags & 4)) help_dll = NULL; |
| |
| return ITypeLib2_GetDocumentation2(This, index, lcid, help_string, help_context, help_dll); |
| } |
| |
| HRESULT CALLBACK IPropertyBag_Read_Proxy( |
| IPropertyBag* This, |
| LPCOLESTR pszPropName, |
| VARIANT *pVar, |
| IErrorLog *pErrorLog) |
| { |
| IUnknown *pUnk = NULL; |
| TRACE("(%p, %s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); |
| |
| if(!pVar) |
| return E_POINTER; |
| |
| if(V_VT(pVar) & (VT_BYREF | VT_ARRAY | VT_VECTOR)) |
| { |
| FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar)); |
| return E_NOTIMPL; |
| } |
| |
| switch(V_VT(pVar)) |
| { |
| case VT_DISPATCH: |
| pUnk = (IUnknown*)V_DISPATCH(pVar); |
| break; |
| case VT_UNKNOWN: |
| pUnk = V_UNKNOWN(pVar); |
| break; |
| case VT_SAFEARRAY: |
| FIXME("Safearray support not yet implemented.\n"); |
| return E_NOTIMPL; |
| default: |
| FIXME("Unknown V_VT %d - support not yet implemented.\n", V_VT(pVar)); |
| return E_NOTIMPL; |
| } |
| |
| return IPropertyBag_RemoteRead_Proxy(This, pszPropName, pVar, pErrorLog, |
| V_VT(pVar), pUnk); |
| } |
| |
| HRESULT __RPC_STUB IPropertyBag_Read_Stub( |
| IPropertyBag* This, |
| LPCOLESTR pszPropName, |
| VARIANT *pVar, |
| IErrorLog *pErrorLog, |
| DWORD varType, |
| IUnknown *pUnkObj) |
| { |
| static const WCHAR emptyWstr[] = {0}; |
| IDispatch *disp; |
| HRESULT hr; |
| TRACE("(%p, %s, %p, %p, %x, %p)\n", This, debugstr_w(pszPropName), pVar, |
| pErrorLog, varType, pUnkObj); |
| |
| if(varType & (VT_BYREF | VT_ARRAY | VT_VECTOR)) |
| { |
| FIXME("Variant type %x is byref, array or vector. Not implemented.\n", V_VT(pVar)); |
| return E_NOTIMPL; |
| } |
| |
| V_VT(pVar) = varType; |
| switch(varType) |
| { |
| case VT_DISPATCH: |
| hr = IUnknown_QueryInterface(pUnkObj, &IID_IDispatch, (LPVOID*)&disp); |
| if(FAILED(hr)) |
| return hr; |
| IUnknown_Release(pUnkObj); |
| V_DISPATCH(pVar) = disp; |
| break; |
| case VT_UNKNOWN: |
| V_UNKNOWN(pVar) = pUnkObj; |
| break; |
| case VT_BSTR: |
| V_BSTR(pVar) = SysAllocString(emptyWstr); |
| break; |
| case VT_SAFEARRAY: |
| FIXME("Safearray support not yet implemented.\n"); |
| return E_NOTIMPL; |
| default: |
| break; |
| } |
| hr = IPropertyBag_Read(This, pszPropName, pVar, pErrorLog); |
| if(FAILED(hr)) |
| VariantClear(pVar); |
| |
| return hr; |
| } |
| |
| /* call_as/local stubs for ocidl.idl */ |
| |
| HRESULT CALLBACK IClassFactory2_CreateInstanceLic_Proxy( |
| IClassFactory2* This, |
| IUnknown *pUnkOuter, |
| IUnknown *pUnkReserved, |
| REFIID riid, |
| BSTR bstrKey, |
| PVOID *ppvObj) |
| { |
| TRACE("(%p, %s, %p)\n", pUnkOuter, debugstr_guid(riid), ppvObj); |
| |
| *ppvObj = NULL; |
| |
| if (pUnkOuter) |
| { |
| ERR("aggregation is not allowed on remote objects\n"); |
| return CLASS_E_NOAGGREGATION; |
| } |
| |
| return IClassFactory2_RemoteCreateInstanceLic_Proxy(This, riid, bstrKey, (IUnknown**)ppvObj); |
| } |
| |
| HRESULT __RPC_STUB IClassFactory2_CreateInstanceLic_Stub( |
| IClassFactory2* This, |
| REFIID riid, |
| BSTR bstrKey, |
| IUnknown **ppvObj) |
| { |
| TRACE("(%s, %p)\n", debugstr_guid(riid), ppvObj); |
| return IClassFactory2_CreateInstanceLic(This, NULL, NULL, riid, bstrKey, (void**)ppvObj); |
| } |
| |
| HRESULT CALLBACK IEnumConnections_Next_Proxy( |
| IEnumConnections* This, |
| ULONG cConnections, |
| LPCONNECTDATA rgcd, |
| ULONG *pcFetched) |
| { |
| ULONG fetched; |
| |
| TRACE("(%u, %p %p)\n", cConnections, rgcd, pcFetched); |
| |
| if (!pcFetched) |
| pcFetched = &fetched; |
| |
| return IEnumConnections_RemoteNext_Proxy(This, cConnections, rgcd, pcFetched); |
| } |
| |
| HRESULT __RPC_STUB IEnumConnections_Next_Stub( |
| IEnumConnections* This, |
| ULONG cConnections, |
| LPCONNECTDATA rgcd, |
| ULONG *pcFetched) |
| { |
| HRESULT hr; |
| |
| TRACE("(%u, %p, %p)\n", cConnections, rgcd, pcFetched); |
| |
| *pcFetched = 0; |
| hr = IEnumConnections_Next(This, cConnections, rgcd, pcFetched); |
| if (hr == S_OK) |
| *pcFetched = cConnections; |
| |
| return hr; |
| } |
| |
| HRESULT CALLBACK IEnumConnectionPoints_Next_Proxy( |
| IEnumConnectionPoints* This, |
| ULONG cConnections, |
| IConnectionPoint **ppCP, |
| ULONG *pcFetched) |
| { |
| ULONG fetched; |
| |
| TRACE("(%u, %p %p)\n", cConnections, ppCP, pcFetched); |
| |
| if (!pcFetched) |
| pcFetched = &fetched; |
| |
| return IEnumConnectionPoints_RemoteNext_Proxy(This, cConnections, ppCP, pcFetched); |
| } |
| |
| HRESULT __RPC_STUB IEnumConnectionPoints_Next_Stub( |
| IEnumConnectionPoints* This, |
| ULONG cConnections, |
| IConnectionPoint **ppCP, |
| ULONG *pcFetched) |
| { |
| HRESULT hr; |
| |
| TRACE("(%u, %p, %p)\n", cConnections, ppCP, pcFetched); |
| |
| *pcFetched = 0; |
| hr = IEnumConnectionPoints_Next(This, cConnections, ppCP, pcFetched); |
| if (hr == S_OK) |
| *pcFetched = cConnections; |
| |
| return hr; |
| } |
| |
| HRESULT CALLBACK IPersistMemory_Load_Proxy( |
| IPersistMemory* This, |
| LPVOID pMem, |
| ULONG cbSize) |
| { |
| TRACE("(%p, %u)\n", pMem, cbSize); |
| |
| if (!pMem) |
| return E_POINTER; |
| |
| return IPersistMemory_RemoteLoad_Proxy(This, pMem, cbSize); |
| } |
| |
| HRESULT __RPC_STUB IPersistMemory_Load_Stub( |
| IPersistMemory* This, |
| BYTE *pMem, |
| ULONG cbSize) |
| { |
| TRACE("(%p, %u)\n", pMem, cbSize); |
| return IPersistMemory_Load(This, pMem, cbSize); |
| } |
| |
| HRESULT CALLBACK IPersistMemory_Save_Proxy( |
| IPersistMemory* This, |
| LPVOID pMem, |
| BOOL fClearDirty, |
| ULONG cbSize) |
| { |
| TRACE("(%p, %d, %u)\n", pMem, fClearDirty, cbSize); |
| |
| if (!pMem) |
| return E_POINTER; |
| |
| return IPersistMemory_RemoteSave_Proxy(This, pMem, fClearDirty, cbSize); |
| } |
| |
| HRESULT __RPC_STUB IPersistMemory_Save_Stub( |
| IPersistMemory* This, |
| BYTE *pMem, |
| BOOL fClearDirty, |
| ULONG cbSize) |
| { |
| TRACE("(%p, %d, %u)\n", pMem, fClearDirty, cbSize); |
| return IPersistMemory_Save(This, pMem, fClearDirty, cbSize); |
| } |
| |
| void CALLBACK IAdviseSinkEx_OnViewStatusChange_Proxy( |
| IAdviseSinkEx* This, |
| DWORD dwViewStatus) |
| { |
| TRACE("(%p, 0x%08x)\n", This, dwViewStatus); |
| IAdviseSinkEx_RemoteOnViewStatusChange_Proxy(This, dwViewStatus); |
| } |
| |
| HRESULT __RPC_STUB IAdviseSinkEx_OnViewStatusChange_Stub( |
| IAdviseSinkEx* This, |
| DWORD dwViewStatus) |
| { |
| TRACE("(%p, 0x%08x)\n", This, dwViewStatus); |
| IAdviseSinkEx_OnViewStatusChange(This, dwViewStatus); |
| return S_OK; |
| } |
| |
| HRESULT CALLBACK IEnumOleUndoUnits_Next_Proxy( |
| IEnumOleUndoUnits* This, |
| ULONG cElt, |
| IOleUndoUnit **rgElt, |
| ULONG *pcEltFetched) |
| { |
| ULONG fetched; |
| |
| TRACE("(%u, %p %p)\n", cElt, rgElt, pcEltFetched); |
| |
| if (!pcEltFetched) |
| pcEltFetched = &fetched; |
| |
| return IEnumOleUndoUnits_RemoteNext_Proxy(This, cElt, rgElt, pcEltFetched); |
| } |
| |
| HRESULT __RPC_STUB IEnumOleUndoUnits_Next_Stub( |
| IEnumOleUndoUnits* This, |
| ULONG cElt, |
| IOleUndoUnit **rgElt, |
| ULONG *pcEltFetched) |
| { |
| HRESULT hr; |
| |
| TRACE("(%u, %p, %p)\n", cElt, rgElt, pcEltFetched); |
| |
| *pcEltFetched = 0; |
| hr = IEnumOleUndoUnits_Next(This, cElt, rgElt, pcEltFetched); |
| if (hr == S_OK) |
| *pcEltFetched = cElt; |
| |
| return hr; |
| } |
| |
| HRESULT CALLBACK IQuickActivate_QuickActivate_Proxy( |
| IQuickActivate* This, |
| QACONTAINER *pQaContainer, |
| QACONTROL *pQaControl) |
| { |
| FIXME("not implemented\n"); |
| return E_NOTIMPL; |
| } |
| |
| HRESULT __RPC_STUB IQuickActivate_QuickActivate_Stub( |
| IQuickActivate* This, |
| QACONTAINER *pQaContainer, |
| QACONTROL *pQaControl) |
| { |
| FIXME("not implemented\n"); |
| return E_NOTIMPL; |
| } |