diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index 782767fdcbc..16a602ed7b5 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -39,7 +39,8 @@ C_SRCS = \ stg_prop.c \ stg_stream.c \ storage32.c \ - stubmanager.c + stubmanager.c \ + usrmarshal.c C_SRCS16 = \ memlockbytes16.c \ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 44aca558eb3..26f7c6fa1fb 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -1,8 +1,8 @@ @ stdcall BindMoniker(ptr long ptr ptr) -@ stub CLIPFORMAT_UserFree -@ stub CLIPFORMAT_UserMarshal -@ stub CLIPFORMAT_UserSize -@ stub CLIPFORMAT_UserUnmarshal +@ stdcall CLIPFORMAT_UserFree(ptr ptr) +@ stdcall CLIPFORMAT_UserMarshal(ptr ptr ptr) +@ stdcall CLIPFORMAT_UserSize(ptr long ptr) +@ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr) @ stdcall CLSIDFromProgID(wstr ptr) @ stdcall CLSIDFromString(wstr ptr) @ stdcall CoAddRefServerProcess() @@ -107,30 +107,34 @@ @ stdcall GetHGlobalFromStream(ptr ptr) @ stub GetHookInterface @ stdcall GetRunningObjectTable(long ptr) -@ stub HACCEL_UserFree -@ stub HACCEL_UserMarshal -@ stub HACCEL_UserSize -@ stub HACCEL_UserUnmarshal -@ stub HBITMAP_UserFree -@ stub HBITMAP_UserMarshal -@ stub HBITMAP_UserSize -@ stub HBITMAP_UserUnmarshal +@ stdcall HACCEL_UserFree(ptr ptr) +@ stdcall HACCEL_UserMarshal(ptr ptr ptr) +@ stdcall HACCEL_UserSize(ptr long ptr) +@ stdcall HACCEL_UserUnmarshal(ptr ptr ptr) +@ stdcall HBITMAP_UserFree(ptr ptr) +@ stdcall HBITMAP_UserMarshal(ptr ptr ptr) +@ stdcall HBITMAP_UserSize(ptr long ptr) +@ stdcall HBITMAP_UserUnmarshal(ptr ptr ptr) @ stub HBRUSH_UserFree @ stub HBRUSH_UserMarshal @ stub HBRUSH_UserSize @ stub HBRUSH_UserUnmarshal -@ stub HENHMETAFILE_UserFree -@ stub HENHMETAFILE_UserMarshal -@ stub HENHMETAFILE_UserSize -@ stub HENHMETAFILE_UserUnmarshal -@ stub HGLOBAL_UserFree -@ stub HGLOBAL_UserMarshal -@ stub HGLOBAL_UserSize -@ stub HGLOBAL_UserUnmarshal -@ stub HMENU_UserFree -@ stub HMENU_UserMarshal -@ stub HMENU_UserSize -@ stub HMENU_UserUnmarshal +@ stdcall HDC_UserFree(ptr ptr) +@ stdcall HDC_UserMarshal(ptr ptr ptr) +@ stdcall HDC_UserSize(ptr long ptr) +@ stdcall HDC_UserUnmarshal(ptr ptr ptr) +@ stdcall HENHMETAFILE_UserFree(ptr ptr) +@ stdcall HENHMETAFILE_UserMarshal(ptr ptr ptr) +@ stdcall HENHMETAFILE_UserSize(ptr long ptr) +@ stdcall HENHMETAFILE_UserUnmarshal(ptr ptr ptr) +@ stdcall HGLOBAL_UserFree(ptr ptr) +@ stdcall HGLOBAL_UserMarshal(ptr ptr ptr) +@ stdcall HGLOBAL_UserSize(ptr long ptr) +@ stdcall HGLOBAL_UserUnmarshal(ptr ptr ptr) +@ stdcall HMENU_UserFree(ptr ptr) +@ stdcall HMENU_UserMarshal(ptr ptr ptr) +@ stdcall HMENU_UserSize(ptr long ptr) +@ stdcall HMENU_UserUnmarshal(ptr ptr ptr) @ stub HMETAFILEPICT_UserFree @ stub HMETAFILEPICT_UserMarshal @ stub HMETAFILEPICT_UserSize @@ -139,14 +143,14 @@ @ stub HMETAFILE_UserMarshal @ stub HMETAFILE_UserSize @ stub HMETAFILE_UserUnmarshal -@ stub HPALETTE_UserFree -@ stub HPALETTE_UserMarshal -@ stub HPALETTE_UserSize -@ stub HPALETTE_UserUnmarshal -@ stub HWND_UserFree -@ stub HWND_UserMarshal -@ stub HWND_UserSize -@ stub HWND_UserUnmarshal +@ stdcall HPALETTE_UserFree(ptr ptr) +@ stdcall HPALETTE_UserMarshal(ptr ptr ptr) +@ stdcall HPALETTE_UserSize(ptr long ptr) +@ stdcall HPALETTE_UserUnmarshal(ptr ptr ptr) +@ stdcall HWND_UserFree(ptr ptr) +@ stdcall HWND_UserMarshal(ptr ptr ptr) +@ stdcall HWND_UserSize(ptr long ptr) +@ stdcall HWND_UserUnmarshal(ptr ptr ptr) @ stdcall IIDFromString(wstr ptr) CLSIDFromString @ stub I_RemoteMain @ stdcall IsAccelerator(long long ptr long) @@ -227,14 +231,14 @@ @ stdcall RegisterDragDrop(long ptr) @ stdcall ReleaseStgMedium(ptr) @ stdcall RevokeDragDrop(long) -@ stub SNB_UserFree -@ stub SNB_UserMarshal -@ stub SNB_UserSize -@ stub SNB_UserUnmarshal -@ stub STGMEDIUM_UserFree -@ stub STGMEDIUM_UserMarshal -@ stub STGMEDIUM_UserSize -@ stub STGMEDIUM_UserUnmarshal +@ stdcall SNB_UserFree(ptr ptr) +@ stdcall SNB_UserMarshal(ptr ptr ptr) +@ stdcall SNB_UserSize(ptr long ptr) +@ stdcall SNB_UserUnmarshal(ptr ptr ptr) +@ stdcall STGMEDIUM_UserFree(ptr ptr) +@ stdcall STGMEDIUM_UserMarshal(ptr ptr ptr) +@ stdcall STGMEDIUM_UserSize(ptr long ptr) +@ stdcall STGMEDIUM_UserUnmarshal(ptr ptr ptr) @ stdcall SetConvertStg(ptr long) @ stub SetDocumentBitStg @ stdcall SetErrorInfo(long ptr) diff --git a/dlls/ole32/tests/Makefile.in b/dlls/ole32/tests/Makefile.in index a0049e9e695..eb747e4e2c0 100644 --- a/dlls/ole32/tests/Makefile.in +++ b/dlls/ole32/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = ole32.dll -IMPORTS = oleaut32 ole32 user32 kernel32 +IMPORTS = oleaut32 ole32 user32 gdi32 kernel32 EXTRALIBS = -luuid CTESTS = \ diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 032b544be02..cdd1ac97915 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -1666,6 +1666,190 @@ static void test_ROT(void) ok_no_locks(); } +static const char cf_marshaled[] = +{ + 0x9, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x9, 0x0, 0x0, 0x0, + 'M', 0x0, 'y', 0x0, + 'F', 0x0, 'o', 0x0, + 'r', 0x0, 'm', 0x0, + 'a', 0x0, 't', 0x0, + 0x0, 0x0 +}; + +static void test_marshal_CLIPFORMAT(void) +{ + unsigned char *buffer; + unsigned long size; + unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); + wireCLIPFORMAT wirecf; + CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat"); + CLIPFORMAT cf2; + + size = CLIPFORMAT_UserSize(&flags, 0, &cf); + ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Size should be %d, instead of %ld\n", sizeof(*wirecf) + sizeof(cf_marshaled), size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + CLIPFORMAT_UserMarshal(&flags, buffer, &cf); + wirecf = (wireCLIPFORMAT)buffer; + ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext); + ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, wirecf->u.dwValue); + ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n"); + + CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2); + ok(cf == cf2, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + + CLIPFORMAT_UserFree(&flags, &cf2); +} + +static void test_marshal_HWND(void) +{ + unsigned char *buffer; + unsigned long size; + unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION); + HWND hwnd = GetDesktopWindow(); + HWND hwnd2; + wireHWND wirehwnd; + + size = HWND_UserSize(&flags, 0, &hwnd); + ok(size == sizeof(*wirehwnd), "Size should be %d, instead of %ld\n", sizeof(*wirehwnd), size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + HWND_UserMarshal(&flags, buffer, &hwnd); + wirehwnd = (wireHWND)buffer; + ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext); + ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote); + + HWND_UserUnmarshal(&flags, buffer, &hwnd2); + ok(hwnd == hwnd2, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + + HWND_UserFree(&flags, &hwnd2); +} + +static void test_marshal_HGLOBAL(void) +{ + unsigned char *buffer; + unsigned long size; + unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION); + HGLOBAL hglobal; + HGLOBAL hglobal2; + unsigned char *wirehglobal; + int i; + + hglobal = NULL; + flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION); + size = HGLOBAL_UserSize(&flags, 0, &hglobal); + /* native is poorly programmed and allocates 4 bytes more than it needs to + * here - Wine doesn't have to emulate that */ + ok((size == 8) || (size == 12), "Size should be 12, instead of %ld\n", size); + buffer = HeapAlloc(GetProcessHeap(), 0, size); + HGLOBAL_UserMarshal(&flags, buffer, &hglobal); + wirehglobal = buffer; + ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal); + wirehglobal += sizeof(ULONG); + ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n"); + HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2); + ok(hglobal2 == hglobal, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + HGLOBAL_UserFree(&flags, &hglobal2); + + hglobal = GlobalAlloc(0, 4); + buffer = GlobalLock(hglobal); + for (i = 0; i < 4; i++) + buffer[i] = i; + GlobalUnlock(hglobal); + flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION); + size = HGLOBAL_UserSize(&flags, 0, &hglobal); + /* native is poorly programmed and allocates 4 bytes more than it needs to + * here - Wine doesn't have to emulate that */ + ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %ld\n", size); + buffer = HeapAlloc(GetProcessHeap(), 0, size); + HGLOBAL_UserMarshal(&flags, buffer, &hglobal); + wirehglobal = buffer; + ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal); + wirehglobal += sizeof(ULONG); + ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n"); + wirehglobal += sizeof(ULONG); + ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n"); + wirehglobal += sizeof(ULONG); + ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n"); + wirehglobal += sizeof(ULONG); + ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n"); + wirehglobal += sizeof(ULONG); + for (i = 0; i < 4; i++) + ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i); + HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2); + ok(hglobal2 != NULL, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + HGLOBAL_UserFree(&flags, &hglobal2); + GlobalFree(hglobal); +} + +static HENHMETAFILE create_emf(void) +{ + RECT rect = {0, 0, 100, 100}; + HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0"); + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL); + return CloseEnhMetaFile(hdc); +} + +static void test_marshal_HENHMETAFILE(void) +{ + unsigned char *buffer; + unsigned long size; + unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION); + HENHMETAFILE hemf; + HENHMETAFILE hemf2 = NULL; + unsigned char *wirehemf; + + hemf = create_emf(); + + size = HENHMETAFILE_UserSize(&flags, 0, &hemf); + ok(size > 20, "size should be at least 20 bytes, not %ld\n", size); + buffer = HeapAlloc(GetProcessHeap(), 0, size); + HENHMETAFILE_UserMarshal(&flags, buffer, &hemf); + wirehemf = buffer; + ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits + * at this point */ + + HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2); + ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n"); + HeapFree(GetProcessHeap(), 0, buffer); + HENHMETAFILE_UserFree(&flags, &hemf2); + DeleteEnhMetaFile(hemf); + + /* test NULL emf */ + hemf = NULL; + + size = HENHMETAFILE_UserSize(&flags, 0, &hemf); + ok(size == 8, "size should be 8 bytes, not %ld\n", size); + buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size); + HENHMETAFILE_UserMarshal(&flags, buffer, &hemf); + wirehemf = buffer; + ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf); + wirehemf += sizeof(DWORD); + + HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2); + ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n"); + HeapFree(GetProcessHeap(), 0, buffer); + HENHMETAFILE_UserFree(&flags, &hemf2); +} + START_TEST(marshal) { HMODULE hOle32 = GetModuleHandle("ole32"); @@ -1711,6 +1895,11 @@ START_TEST(marshal) test_ROT(); /* FIXME: test GIT */ + test_marshal_CLIPFORMAT(); + test_marshal_HWND(); + test_marshal_HGLOBAL(); + test_marshal_HENHMETAFILE(); + CoUninitialize(); return; diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c new file mode 100644 index 00000000000..294be089984 --- /dev/null +++ b/dlls/ole32/usrmarshal.c @@ -0,0 +1,800 @@ +/* + * Miscellaneous Marshaling Routines + * + * Copyright 2005 Robert Shearman + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winerror.h" + +#include "ole2.h" +#include "oleauto.h" +#include "rpcproxy.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) + +static void dump_user_flags(unsigned long *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)); + } +} + +unsigned long __RPC_USER CLIPFORMAT_UserSize(unsigned long *pFlags, unsigned long StartingSize, CLIPFORMAT *pCF) +{ + unsigned long size = StartingSize; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, pCF); + + size += sizeof(userCLIPFORMAT); + + /* only need to marshal the name if it is not a pre-defined type and + * we are going remote */ + if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)) + { + WCHAR format[255]; + INT ret; + size += 3 * sizeof(INT); + /* urg! this function is badly designed because it won't tell us how + * much space is needed without doing a dummy run of storing the + * name into a buffer */ + ret = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1); + if (!ret) + RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL); + size += (ret + 1) * sizeof(WCHAR); + } + return size; +} + +unsigned char * __RPC_USER CLIPFORMAT_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF) +{ + wireCLIPFORMAT wirecf = (wireCLIPFORMAT)pBuffer; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &0x%04x\n", pBuffer, *pCF); + + wirecf->u.dwValue = *pCF; + pBuffer += sizeof(*wirecf); + + /* only need to marshal the name if it is not a pre-defined type and + * we are going remote */ + if ((*pCF >= 0xc000) && (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE)) + { + WCHAR format[255]; + INT len; + wirecf->fContext = WDT_REMOTE_CALL; + len = GetClipboardFormatNameW(*pCF, format, sizeof(format)/sizeof(format[0])-1); + if (!len) + RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL); + len += 1; + *(INT *)pBuffer = len; + pBuffer += sizeof(INT); + *(INT *)pBuffer = 0; + pBuffer += sizeof(INT); + *(INT *)pBuffer = len; + pBuffer += sizeof(INT); + TRACE("marshaling format name %s\n", debugstr_wn(format, len-1)); + lstrcpynW((LPWSTR)pBuffer, format, len); + pBuffer += len * sizeof(WCHAR); + *(WCHAR *)pBuffer = '\0'; + pBuffer += sizeof(WCHAR); + } + else + wirecf->fContext = WDT_INPROC_CALL; + + return pBuffer; +} + +unsigned char * __RPC_USER CLIPFORMAT_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, CLIPFORMAT *pCF) +{ + wireCLIPFORMAT wirecf = (wireCLIPFORMAT)pBuffer; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, pCF); + + pBuffer += sizeof(*wirecf); + if (wirecf->fContext == WDT_INPROC_CALL) + *pCF = (CLIPFORMAT)wirecf->u.dwValue; + else if (wirecf->fContext == WDT_REMOTE_CALL) + { + CLIPFORMAT cf; + INT len = *(INT *)pBuffer; + pBuffer += sizeof(INT); + if (*(INT *)pBuffer != 0) + RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL); + pBuffer += sizeof(INT); + if (*(INT *)pBuffer != len) + RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL); + pBuffer += sizeof(INT); + if (((WCHAR *)pBuffer)[len] != '\0') + RaiseException(RPC_S_INVALID_BOUND, 0, 0, NULL); + TRACE("unmarshaling clip format %s\n", debugstr_w((LPCWSTR)pBuffer)); + cf = RegisterClipboardFormatW((LPCWSTR)pBuffer); + pBuffer += (len + 1) * sizeof(WCHAR); + if (!cf) + RaiseException(DV_E_CLIPFORMAT, 0, 0, NULL); + *pCF = cf; + } + else + /* code not really appropriate, but nearest I can find */ + RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); + return pBuffer; +} + +void __RPC_USER CLIPFORMAT_UserFree(unsigned long *pFlags, CLIPFORMAT *pCF) +{ + /* there is no inverse of the RegisterClipboardFormat function, + * so nothing to do */ +} + +static unsigned long __RPC_USER handle_UserSize(unsigned long *pFlags, unsigned long StartingSize, HANDLE *handle) +{ + if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE) + { + ERR("can't remote a local handle\n"); + RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); + return StartingSize; + } + return StartingSize + sizeof(RemotableHandle); +} + +static unsigned char * __RPC_USER handle_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HANDLE *handle) +{ + RemotableHandle *remhandle = (RemotableHandle *)pBuffer; + if (LOWORD(*pFlags) == MSHCTX_DIFFERENTMACHINE) + { + ERR("can't remote a local handle\n"); + RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); + return pBuffer; + } + remhandle->fContext = WDT_INPROC_CALL; + remhandle->u.hInproc = (LONG_PTR)*handle; + return pBuffer + sizeof(RemotableHandle); +} + +static unsigned char * __RPC_USER handle_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HANDLE *handle) +{ + RemotableHandle *remhandle = (RemotableHandle *)pBuffer; + if (remhandle->fContext != WDT_INPROC_CALL) + RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); + *handle = (HANDLE)remhandle->u.hInproc; + return pBuffer + sizeof(RemotableHandle); +} + +static void __RPC_USER handle_UserFree(unsigned long *pFlags, HANDLE *phMenu) +{ + /* nothing to do */ +} + +#define IMPL_WIREM_HANDLE(type) \ + unsigned long __RPC_USER type##_UserSize(unsigned long *pFlags, unsigned long StartingSize, type *handle) \ + { \ + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, handle); \ + return handle_UserSize(pFlags, StartingSize, (HANDLE *)handle); \ + } \ + \ + unsigned char * __RPC_USER type##_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, type *handle) \ + { \ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *handle); \ + return handle_UserMarshal(pFlags, pBuffer, (HANDLE *)handle); \ + } \ + \ + unsigned char * __RPC_USER type##_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, type *handle) \ + { \ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, handle); \ + return handle_UserUnmarshal(pFlags, pBuffer, (HANDLE *)handle); \ + } \ + \ + void __RPC_USER type##_UserFree(unsigned long *pFlags, type *handle) \ + { \ + TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *handle); \ + return handle_UserFree(pFlags, (HANDLE *)handle); \ + } + +IMPL_WIREM_HANDLE(HACCEL) +IMPL_WIREM_HANDLE(HMENU) +IMPL_WIREM_HANDLE(HWND) + +unsigned long __RPC_USER HGLOBAL_UserSize(unsigned long *pFlags, unsigned long StartingSize, HGLOBAL *phGlobal) +{ + unsigned long size = StartingSize; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, phGlobal); + + ALIGN_LENGTH(size, 3); + + size += sizeof(ULONG); + + if (LOWORD(*pFlags == MSHCTX_INPROC)) + size += sizeof(HGLOBAL); + else + { + size += sizeof(ULONG); + if (*phGlobal) + { + SIZE_T ret; + size += 3 * sizeof(ULONG); + ret = GlobalSize(*phGlobal); + size += (unsigned long)ret; + } + } + + return size; +} + +unsigned char * __RPC_USER HGLOBAL_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *phGlobal); + + ALIGN_POINTER(pBuffer, 3); + + if (LOWORD(*pFlags == MSHCTX_INPROC)) + { + if (sizeof(*phGlobal) == 8) + *(ULONG *)pBuffer = WDT_INPROC64_CALL; + else + *(ULONG *)pBuffer = WDT_INPROC_CALL; + pBuffer += sizeof(ULONG); + *(HGLOBAL *)pBuffer = *phGlobal; + pBuffer += sizeof(HGLOBAL); + } + else + { + *(ULONG *)pBuffer = WDT_REMOTE_CALL; + pBuffer += sizeof(ULONG); + *(ULONG *)pBuffer = (ULONG)*phGlobal; + pBuffer += sizeof(ULONG); + if (*phGlobal) + { + const unsigned char *memory; + SIZE_T size = GlobalSize(*phGlobal); + *(ULONG *)pBuffer = (ULONG)size; + pBuffer += sizeof(ULONG); + *(ULONG *)pBuffer = (ULONG)*phGlobal; + pBuffer += sizeof(ULONG); + *(ULONG *)pBuffer = (ULONG)size; + pBuffer += sizeof(ULONG); + + memory = GlobalLock(*phGlobal); + memcpy(pBuffer, memory, size); + pBuffer += size; + GlobalUnlock(*phGlobal); + } + } + + return pBuffer; +} + +unsigned char * __RPC_USER HGLOBAL_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HGLOBAL *phGlobal) +{ + ULONG fContext; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *phGlobal); + + ALIGN_POINTER(pBuffer, 3); + + fContext = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + + if (((fContext == WDT_INPROC_CALL) && (sizeof(*phGlobal) < 8)) || + ((fContext == WDT_INPROC64_CALL) && (sizeof(*phGlobal) == 8))) + { + *phGlobal = *(HGLOBAL *)pBuffer; + pBuffer += sizeof(*phGlobal); + } + else if (fContext == WDT_REMOTE_CALL) + { + ULONG handle; + + handle = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + + if (handle) + { + ULONG size; + void *memory; + + size = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + /* redunancy is bad - it means you have to check consistancy like + * this: */ + if (*(ULONG *)pBuffer != handle) + { + RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); + return pBuffer; + } + pBuffer += sizeof(ULONG); + /* redunancy is bad - it means you have to check consistancy like + * this: */ + if (*(ULONG *)pBuffer != size) + { + RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); + return pBuffer; + } + pBuffer += sizeof(ULONG); + + /* FIXME: check size is not too big */ + + *phGlobal = GlobalAlloc(GMEM_MOVEABLE, size); + memory = GlobalLock(*phGlobal); + memcpy(memory, pBuffer, size); + pBuffer += size; + GlobalUnlock(*phGlobal); + } + else + *phGlobal = NULL; + } + else + RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); + + return pBuffer; +} + +void __RPC_USER HGLOBAL_UserFree(unsigned long *pFlags, HGLOBAL *phGlobal) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *phGlobal); + + if (LOWORD(*pFlags != MSHCTX_INPROC) && *phGlobal) + GlobalFree(*phGlobal); +} + +unsigned long __RPC_USER HBITMAP_UserSize(unsigned long *pFlags, unsigned long StartingSize, HBITMAP *phBmp) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER HBITMAP_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HBITMAP *phBmp) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER HBITMAP_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HBITMAP *phBmp) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER HBITMAP_UserFree(unsigned long *pFlags, HBITMAP *phBmp) +{ + FIXME(":stub\n"); +} + +unsigned long __RPC_USER HDC_UserSize(unsigned long *pFlags, unsigned long StartingSize, HDC *phdc) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER HDC_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HDC *phdc) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER HDC_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HDC *phdc) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER HDC_UserFree(unsigned long *pFlags, HDC *phdc) +{ + FIXME(":stub\n"); +} + +unsigned long __RPC_USER HPALETTE_UserSize(unsigned long *pFlags, unsigned long StartingSize, HPALETTE *phPal) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER HPALETTE_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HPALETTE *phPal) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER HPALETTE_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HPALETTE *phPal) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER HPALETTE_UserFree(unsigned long *pFlags, HPALETTE *phPal) +{ + FIXME(":stub\n"); +} + + +unsigned long __RPC_USER HENHMETAFILE_UserSize(unsigned long *pFlags, unsigned long StartingSize, HENHMETAFILE *phEmf) +{ + unsigned long size = StartingSize; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, *phEmf); + + size += sizeof(ULONG); + if (LOWORD(*pFlags) == MSHCTX_INPROC) + size += sizeof(ULONG_PTR); + else + { + size += sizeof(ULONG); + + if (*phEmf) + { + UINT emfsize; + + size += 2 * sizeof(ULONG); + emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL); + size += emfsize; + } + } + + return size; +} + +unsigned char * __RPC_USER HENHMETAFILE_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, &%p\n", pBuffer, *phEmf); + + if (LOWORD(*pFlags) == MSHCTX_INPROC) + { + if (sizeof(*phEmf) == 8) + *(ULONG *)pBuffer = WDT_INPROC64_CALL; + else + *(ULONG *)pBuffer = WDT_INPROC_CALL; + pBuffer += sizeof(ULONG); + *(HENHMETAFILE *)pBuffer = *phEmf; + pBuffer += sizeof(HENHMETAFILE); + } + else + { + *(ULONG *)pBuffer = WDT_REMOTE_CALL; + pBuffer += sizeof(ULONG); + *(ULONG *)pBuffer = (ULONG)(ULONG_PTR)*phEmf; + pBuffer += sizeof(ULONG); + + if (*phEmf) + { + UINT emfsize = GetEnhMetaFileBits(*phEmf, 0, NULL); + + *(ULONG *)pBuffer = emfsize; + pBuffer += sizeof(ULONG); + *(ULONG *)pBuffer = emfsize; + pBuffer += sizeof(ULONG); + GetEnhMetaFileBits(*phEmf, emfsize, pBuffer); + pBuffer += emfsize; + } + } + + return pBuffer; +} + +unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, HENHMETAFILE *phEmf) +{ + ULONG fContext; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, phEmf); + + fContext = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + + if (((fContext == WDT_INPROC_CALL) && (sizeof(*phEmf) < 8)) || + ((fContext == WDT_INPROC64_CALL) && (sizeof(*phEmf) == 8))) + { + *phEmf = *(HENHMETAFILE *)pBuffer; + pBuffer += sizeof(*phEmf); + } + else if (fContext == WDT_REMOTE_CALL) + { + ULONG handle; + + handle = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + + if (handle) + { + ULONG size; + size = *(ULONG *)pBuffer; + pBuffer += sizeof(ULONG); + if (size != *(ULONG *)pBuffer) + { + RaiseException(RPC_X_BAD_STUB_DATA, 0, 0, NULL); + return pBuffer; + } + pBuffer += sizeof(ULONG); + *phEmf = SetEnhMetaFileBits(size, pBuffer); + pBuffer += size; + } + else + *phEmf = NULL; + } + else + RaiseException(RPC_S_INVALID_TAG, 0, 0, NULL); + + return pBuffer; +} + +void __RPC_USER HENHMETAFILE_UserFree(unsigned long *pFlags, HENHMETAFILE *phEmf) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", &%p\n", *phEmf); + + if (LOWORD(*pFlags) != MSHCTX_INPROC) + DeleteEnhMetaFile(*phEmf); +} + +unsigned long __RPC_USER STGMEDIUM_UserSize(unsigned long *pFlags, unsigned long StartingSize, STGMEDIUM *pStgMedium) +{ + unsigned long size = StartingSize; + + TRACE("("); dump_user_flags(pFlags); TRACE(", %ld, %p\n", StartingSize, pStgMedium); + + ALIGN_LENGTH(size, 3); + + size += 2 * sizeof(DWORD); + if (pStgMedium->tymed != TYMED_NULL) + size += sizeof(DWORD); + + switch (pStgMedium->tymed) + { + case TYMED_NULL: + TRACE("TYMED_NULL\n"); + break; + case TYMED_HGLOBAL: + TRACE("TYMED_HGLOBAL\n"); + size = HGLOBAL_UserSize(pFlags, size, &pStgMedium->u.hGlobal); + break; + case TYMED_FILE: + FIXME("TYMED_FILE\n"); + break; + case TYMED_ISTREAM: + FIXME("TYMED_ISTREAM\n"); + break; + case TYMED_ISTORAGE: + FIXME("TYMED_ISTORAGE\n"); + break; + case TYMED_GDI: + FIXME("TYMED_GDI\n"); + break; + case TYMED_MFPICT: + FIXME("TYMED_MFPICT\n"); + break; + case TYMED_ENHMF: + TRACE("TYMED_ENHMF\n"); + size = HENHMETAFILE_UserSize(pFlags, size, &pStgMedium->u.hEnhMetaFile); + break; + default: + RaiseException(DV_E_TYMED, 0, 0, NULL); + } + + if (pStgMedium->pUnkForRelease) + FIXME("buffer size pUnkForRelease\n"); + + return size; +} + +unsigned char * __RPC_USER STGMEDIUM_UserMarshal(unsigned long *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, pStgMedium); + + ALIGN_POINTER(pBuffer, 3); + + *(DWORD *)pBuffer = pStgMedium->tymed; + pBuffer += sizeof(DWORD); + if (pStgMedium->tymed != TYMED_NULL) + { + *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->u.pstg; + pBuffer += sizeof(DWORD); + } + *(DWORD *)pBuffer = (DWORD)(DWORD_PTR)pStgMedium->pUnkForRelease; + pBuffer += sizeof(DWORD); + + switch (pStgMedium->tymed) + { + case TYMED_NULL: + TRACE("TYMED_NULL\n"); + break; + case TYMED_HGLOBAL: + TRACE("TYMED_HGLOBAL\n"); + pBuffer = HGLOBAL_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal); + break; + case TYMED_FILE: + FIXME("TYMED_FILE\n"); + break; + case TYMED_ISTREAM: + FIXME("TYMED_ISTREAM\n"); + break; + case TYMED_ISTORAGE: + FIXME("TYMED_ISTORAGE\n"); + break; + case TYMED_GDI: + FIXME("TYMED_GDI\n"); + break; + case TYMED_MFPICT: + FIXME("TYMED_MFPICT\n"); + break; + case TYMED_ENHMF: + TRACE("TYMED_ENHMF\n"); + pBuffer = HENHMETAFILE_UserMarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile); + break; + default: + RaiseException(DV_E_TYMED, 0, 0, NULL); + } + + if (pStgMedium->pUnkForRelease) + FIXME("marshal pUnkForRelease\n"); + + return pBuffer; +} + +unsigned char * __RPC_USER STGMEDIUM_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, STGMEDIUM *pStgMedium) +{ + DWORD content; + DWORD releaseunk; + + ALIGN_POINTER(pBuffer, 3); + + TRACE("("); dump_user_flags(pFlags); TRACE(", %p, %p\n", pBuffer, pStgMedium); + + pStgMedium->tymed = *(DWORD *)pBuffer; + pBuffer += sizeof(DWORD); + if (pStgMedium->tymed != TYMED_NULL) + { + content = *(DWORD *)pBuffer; + pBuffer += sizeof(DWORD); + } + releaseunk = *(DWORD *)pBuffer; + pBuffer += sizeof(DWORD); + + switch (pStgMedium->tymed) + { + case TYMED_NULL: + TRACE("TYMED_NULL\n"); + break; + case TYMED_HGLOBAL: + TRACE("TYMED_HGLOBAL\n"); + pBuffer = HGLOBAL_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hGlobal); + break; + case TYMED_FILE: + FIXME("TYMED_FILE\n"); + break; + case TYMED_ISTREAM: + FIXME("TYMED_ISTREAM\n"); + break; + case TYMED_ISTORAGE: + FIXME("TYMED_ISTORAGE\n"); + break; + case TYMED_GDI: + FIXME("TYMED_GDI\n"); + break; + case TYMED_MFPICT: + FIXME("TYMED_MFPICT\n"); + break; + case TYMED_ENHMF: + TRACE("TYMED_ENHMF\n"); + pBuffer = HENHMETAFILE_UserUnmarshal(pFlags, pBuffer, &pStgMedium->u.hEnhMetaFile); + break; + default: + RaiseException(DV_E_TYMED, 0, 0, NULL); + } + + pStgMedium->pUnkForRelease = NULL; + if (releaseunk) + FIXME("unmarshal pUnkForRelease\n"); + + return pBuffer; +} + +void __RPC_USER STGMEDIUM_UserFree(unsigned long *pFlags, STGMEDIUM *pStgMedium) +{ + TRACE("("); dump_user_flags(pFlags); TRACE(", %p\n", pStgMedium); + + ReleaseStgMedium(pStgMedium); +} + +unsigned long __RPC_USER ASYNC_STGMEDIUM_UserSize(unsigned long *pFlags, unsigned long StartingSize, ASYNC_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserMarshal( unsigned long *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER ASYNC_STGMEDIUM_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, ASYNC_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER ASYNC_STGMEDIUM_UserFree(unsigned long *pFlags, ASYNC_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); +} + +unsigned long __RPC_USER FLAG_STGMEDIUM_UserSize(unsigned long *pFlags, unsigned long StartingSize, FLAG_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER FLAG_STGMEDIUM_UserMarshal( unsigned long *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER FLAG_STGMEDIUM_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, FLAG_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER FLAG_STGMEDIUM_UserFree(unsigned long *pFlags, FLAG_STGMEDIUM *pStgMedium) +{ + FIXME(":stub\n"); +} + +unsigned long __RPC_USER SNB_UserSize(unsigned long *pFlags, unsigned long StartingSize, SNB *pSnb) +{ + FIXME(":stub\n"); + return StartingSize; +} + +unsigned char * __RPC_USER SNB_UserMarshal( unsigned long *pFlags, unsigned char *pBuffer, SNB *pSnb) +{ + FIXME(":stub\n"); + return pBuffer; +} + +unsigned char * __RPC_USER SNB_UserUnmarshal(unsigned long *pFlags, unsigned char *pBuffer, SNB *pSnb) +{ + FIXME(":stub\n"); + return pBuffer; +} + +void __RPC_USER SNB_UserFree(unsigned long *pFlags, SNB *pSnb) +{ + FIXME(":stub\n"); +}