Author: akhaldi Date: Sun Jul 19 23:12:15 2015 New Revision: 68470
URL: http://svn.reactos.org/svn/reactos?rev=68470&view=rev Log: [OLE32_WINETEST] Sync with Wine Staging 1.7.47. CORE-9924
Modified: trunk/rostests/winetests/ole32/CMakeLists.txt trunk/rostests/winetests/ole32/clipboard.c trunk/rostests/winetests/ole32/compobj.c trunk/rostests/winetests/ole32/dragdrop.c trunk/rostests/winetests/ole32/ole2.c trunk/rostests/winetests/ole32/storage32.c trunk/rostests/winetests/ole32/usrmarshal.c
Modified: trunk/rostests/winetests/ole32/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/CMakeLists... ============================================================================== --- trunk/rostests/winetests/ole32/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/CMakeLists.txt [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -22,4 +22,9 @@ target_link_libraries(ole32_winetest uuid) set_module_type(ole32_winetest win32cui) add_importlibs(ole32_winetest oleaut32 ole32 user32 gdi32 advapi32 msvcrt kernel32) + +if(MSVC) + add_importlibs(ole32_winetest ntdll) +endif() + add_cd_file(TARGET ole32_winetest DESTINATION reactos/bin FOR all)
Modified: trunk/rostests/winetests/ole32/clipboard.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/clipboard.... ============================================================================== --- trunk/rostests/winetests/ole32/clipboard.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/clipboard.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -102,7 +102,7 @@
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) { IEnumFORMATETC_AddRef(iface); - *ppvObj = This; + *ppvObj = &This->IEnumFORMATETC_iface; return S_OK; } *ppvObj = NULL; @@ -135,7 +135,8 @@ EnumFormatImpl *This = impl_from_IEnumFORMATETC(iface); ULONG count, i;
- trace("next: count %d cur %d\n", celt, This->cur); + if (winetest_debug > 1) + trace("next: count %d cur %d\n", celt, This->cur);
if(!rgelt) return E_INVALIDARG; @@ -207,7 +208,7 @@
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) { IDataObject_AddRef(iface); - *ppvObj = This; + *ppvObj = &This->IDataObject_iface; return S_OK; } *ppvObj = NULL;
Modified: trunk/rostests/winetests/ole32/compobj.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/compobj.c?... ============================================================================== --- trunk/rostests/winetests/ole32/compobj.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/compobj.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -1563,7 +1563,7 @@ ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); GetExitCodeThread(thread, &exitcode); hr = exitcode; - ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different " + ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different " "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); @@ -1973,7 +1973,12 @@ ok(lr == ERROR_SUCCESS, "Couldn't open CLSID key\n");
lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL); - ok(lr == ERROR_SUCCESS, "Couldn't create class key\n"); + if (lr) { + win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", + GetLastError()); + RegCloseKey(clsidkey); + return; + }
hr = pCoTreatAsClass(&deadbeef, &deadbeef); ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
Modified: trunk/rostests/winetests/ole32/dragdrop.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/dragdrop.c... ============================================================================== --- trunk/rostests/winetests/ole32/dragdrop.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/dragdrop.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -452,13 +452,16 @@
ok(droptarget_refs >= 1, "DropTarget refs should be at least one\n"); OleUninitialize(); - ok(droptarget_refs >= 1, "DropTarget refs should be at least one\n"); - - hr = RevokeDragDrop(hwnd); - ok_ole_success(hr, "RevokeDragDrop"); - ok(droptarget_refs == 0 || - broken(droptarget_refs == 1), /* NT4 */ - "DropTarget refs should be zero not %d\n", droptarget_refs); + + /* Win 8 releases the ref in OleUninitialize() */ + if (droptarget_refs >= 1) + { + hr = RevokeDragDrop(hwnd); + ok_ole_success(hr, "RevokeDragDrop"); + ok(droptarget_refs == 0 || + broken(droptarget_refs == 1), /* NT4 */ + "DropTarget refs should be zero not %d\n", droptarget_refs); + }
hr = RevokeDragDrop(NULL); ok(hr == DRAGDROP_E_INVALIDHWND, "RevokeDragDrop with NULL hwnd should return DRAGDROP_E_INVALIDHWND instead of 0x%08x\n", hr);
Modified: trunk/rostests/winetests/ole32/ole2.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/ole2.c?rev... ============================================================================== --- trunk/rostests/winetests/ole32/ole2.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/ole2.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -1688,6 +1688,113 @@ IStorage_Release(pStorage); }
+ +static const WCHAR CONTENTS[] = {'C','O','N','T','E','N','T','S',0}; + +/* 2 x 1 x 32 bpp dib. PelsPerMeter = 200x400 */ +static BYTE dib[] = +{ + 0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, + + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, + 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static IStorage *create_storage( int num ) +{ + IStorage *stg; + IStream *stm; + HRESULT hr; + ULONG written; + + hr = StgCreateDocfile( NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &stg ); + ok( hr == S_OK, "got %08x\n", hr); + hr = IStorage_SetClass( stg, &CLSID_Picture_Dib ); + ok( hr == S_OK, "got %08x\n", hr); + hr = IStorage_CreateStream( stg, CONTENTS, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stm ); + ok( hr == S_OK, "got %08x\n", hr); + if (num == 1) /* Set biXPelsPerMeter = 0 */ + { + dib[0x26] = 0; + dib[0x27] = 0; + } + hr = IStream_Write( stm, dib, sizeof(dib), &written ); + ok( hr == S_OK, "got %08x\n", hr); + IStream_Release( stm ); + return stg; +} + +static void test_data_cache_dib_contents_stream(int num) +{ + HRESULT hr; + IUnknown *unk; + IPersistStorage *persist; + IDataObject *data; + IViewObject2 *view; + IStorage *stg; + FORMATETC fmt = {CF_DIB, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM med; + CLSID cls; + SIZEL sz; + + hr = CreateDataCache( NULL, &CLSID_Picture_Metafile, &IID_IUnknown, (void *)&unk ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + hr = IUnknown_QueryInterface( unk, &IID_IPersistStorage, (void *)&persist ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + hr = IUnknown_QueryInterface( unk, &IID_IDataObject, (void *)&data ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + hr = IUnknown_QueryInterface( unk, &IID_IViewObject2, (void *)&view ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + + stg = create_storage( num ); + + hr = IPersistStorage_Load( persist, stg ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + IStorage_Release( stg ); + + hr = IPersistStorage_GetClassID( persist, &cls ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + ok( IsEqualCLSID( &cls, &CLSID_Picture_Dib ), "class id mismatch\n" ); + + hr = IDataObject_GetData( data, &fmt, &med ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + if (SUCCEEDED(hr)) + { + ok( med.tymed == TYMED_HGLOBAL, "got %x\n", med.tymed ); + ReleaseStgMedium( &med ); + } + + hr = IViewObject2_GetExtent( view, DVASPECT_CONTENT, -1, NULL, &sz ); + ok( SUCCEEDED(hr), "got %08x\n", hr ); + if (num == 0) + { + ok( sz.cx == 1000, "got %d\n", sz.cx ); + ok( sz.cy == 250, "got %d\n", sz.cy ); + } + else + { + HDC hdc = GetDC( 0 ); + LONG x = 2 * 2540 / GetDeviceCaps( hdc, LOGPIXELSX ); + LONG y = 1 * 2540 / GetDeviceCaps( hdc, LOGPIXELSY ); + ok( sz.cx == x, "got %d %d\n", sz.cx, x ); + ok( sz.cy == y, "got %d %d\n", sz.cy, y ); + + ReleaseDC( 0, hdc ); + } + + IViewObject2_Release( view ); + IDataObject_Release( data ); + IPersistStorage_Release( persist ); + IUnknown_Release( unk ); +} + static void test_default_handler(void) { HRESULT hr; @@ -1970,14 +2077,90 @@ Unknown_Release };
+static HRESULT WINAPI OleRun_QueryInterface(IRunnableObject *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IRunnableObject)) { + *ppv = iface; + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI OleRun_AddRef(IRunnableObject *iface) +{ + return 2; +} + +static ULONG WINAPI OleRun_Release(IRunnableObject *iface) +{ + return 1; +} + +static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid) +{ + ok(0, "unxpected\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleRun_Run(IRunnableObject *iface, LPBINDCTX ctx) +{ + ok(ctx == NULL, "got %p\n", ctx); + return 0xdeadc0de; +} + +static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface) +{ + ok(0, "unxpected\n"); + return FALSE; +} + +static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock, + BOOL last_unlock_closes) +{ + ok(0, "unxpected\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained) +{ + ok(0, "unxpected\n"); + return E_NOTIMPL; +} + +static const IRunnableObjectVtbl oleruntestvtbl = +{ + OleRun_QueryInterface, + OleRun_AddRef, + OleRun_Release, + OleRun_GetRunningClass, + OleRun_Run, + OleRun_IsRunning, + OleRun_LockRunning, + OleRun_SetContainedObject +}; + static IUnknown unknown = { &UnknownVtbl }; +static IRunnableObject testrunnable = { &oleruntestvtbl };
static void test_OleRun(void) { HRESULT hr;
+ /* doesn't support IRunnableObject */ hr = OleRun(&unknown); ok(hr == S_OK, "OleRun failed 0x%08x\n", hr); + + hr = OleRun((IUnknown*)&testrunnable); + ok(hr == 0xdeadc0de, "got 0x%08x\n", hr); }
static void test_OleLockRunning(void) @@ -2393,6 +2576,8 @@ ok_ole_success(hr, "CoRevokeClassObject");
test_data_cache(); + test_data_cache_dib_contents_stream( 0 ); + test_data_cache_dib_contents_stream( 1 ); test_default_handler(); test_runnable(); test_OleRun();
Modified: trunk/rostests/winetests/ole32/storage32.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/storage32.... ============================================================================== --- trunk/rostests/winetests/ole32/storage32.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/storage32.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -59,6 +59,201 @@ WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL); WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL); return lstrcmpA(stra1, stra2); +} + +typedef struct TestLockBytes { + ILockBytes ILockBytes_iface; + LONG ref; + BYTE* contents; + ULONG size; + ULONG buffer_size; + HRESULT lock_hr; + ULONG locks_supported; + ULONG lock_called; +} TestLockBytes; + +static inline TestLockBytes *impl_from_ILockBytes(ILockBytes *iface) +{ + return CONTAINING_RECORD(iface, TestLockBytes, ILockBytes_iface); +} + +static HRESULT WINAPI TestLockBytes_QueryInterface(ILockBytes *iface, REFIID iid, + void **ppv) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_ILockBytes, iid)) + *ppv = &This->ILockBytes_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI TestLockBytes_AddRef(ILockBytes *iface) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + ULONG ref = InterlockedIncrement(&This->ref); + return ref; +} + +static ULONG WINAPI TestLockBytes_Release(ILockBytes *iface) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + ULONG ref = InterlockedDecrement(&This->ref); + return ref; +} + +static HRESULT WINAPI TestLockBytes_ReadAt(ILockBytes *iface, + ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + ULONG dummy; + + if (!pv) return E_INVALIDARG; + + if (!pcbRead) pcbRead = &dummy; + + if (ulOffset.QuadPart >= This->size) + { + *pcbRead = 0; + return S_OK; + } + + cb = min(cb, This->size - ulOffset.QuadPart); + + *pcbRead = cb; + memcpy(pv, &This->contents[ulOffset.QuadPart], cb); + + return S_OK; +} + +static HRESULT WINAPI TestLockBytes_WriteAt(ILockBytes *iface, + ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + HRESULT hr; + ULONG dummy; + + if (!pv) return E_INVALIDARG; + + if (!pcbWritten) pcbWritten = &dummy; + + if (ulOffset.QuadPart + cb > This->size) + { + ULARGE_INTEGER new_size; + new_size.QuadPart = ulOffset.QuadPart + cb; + hr = ILockBytes_SetSize(iface, new_size); + if (FAILED(hr)) return hr; + } + + *pcbWritten = cb; + memcpy(&This->contents[ulOffset.QuadPart], pv, cb); + + return S_OK; +} + +static HRESULT WINAPI TestLockBytes_Flush(ILockBytes *iface) +{ + return S_OK; +} + +static HRESULT WINAPI TestLockBytes_SetSize(ILockBytes *iface, + ULARGE_INTEGER cb) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + + if (This->buffer_size < cb.QuadPart) + { + ULONG new_buffer_size = max(This->buffer_size * 2, cb.QuadPart); + BYTE* new_buffer = HeapAlloc(GetProcessHeap(), 0, new_buffer_size); + if (!new_buffer) return E_OUTOFMEMORY; + memcpy(new_buffer, This->contents, This->size); + HeapFree(GetProcessHeap(), 0, This->contents); + This->contents = new_buffer; + } + + if (cb.QuadPart > This->size) + memset(&This->contents[This->size], 0, cb.QuadPart - This->size); + + This->size = cb.QuadPart; + + return S_OK; +} + +static HRESULT WINAPI TestLockBytes_LockRegion(ILockBytes *iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + This->lock_called++; + return This->lock_hr; +} + +static HRESULT WINAPI TestLockBytes_UnlockRegion(ILockBytes *iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + return This->lock_hr; +} + +static HRESULT WINAPI TestLockBytes_Stat(ILockBytes *iface, + STATSTG *pstatstg, DWORD grfStatFlag) +{ + TestLockBytes *This = impl_from_ILockBytes(iface); + static const WCHAR dummy_name[] = {'d','u','m','m','y',0}; + + if (!pstatstg) return E_INVALIDARG; + + memset(pstatstg, 0, sizeof(STATSTG)); + + if (!(grfStatFlag & STATFLAG_NONAME)) + { + pstatstg->pwcsName = CoTaskMemAlloc(sizeof(dummy_name)); + if (!pstatstg->pwcsName) return E_OUTOFMEMORY; + memcpy(pstatstg->pwcsName, dummy_name, sizeof(dummy_name)); + } + + pstatstg->type = STGTY_LOCKBYTES; + pstatstg->cbSize.QuadPart = This->size; + pstatstg->grfLocksSupported = This->locks_supported; + + return S_OK; +} + +static ILockBytesVtbl TestLockBytes_Vtbl = { + TestLockBytes_QueryInterface, + TestLockBytes_AddRef, + TestLockBytes_Release, + TestLockBytes_ReadAt, + TestLockBytes_WriteAt, + TestLockBytes_Flush, + TestLockBytes_SetSize, + TestLockBytes_LockRegion, + TestLockBytes_UnlockRegion, + TestLockBytes_Stat +}; + +static void CreateTestLockBytes(TestLockBytes **This) +{ + *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**This)); + + if (*This) + { + (*This)->ILockBytes_iface.lpVtbl = &TestLockBytes_Vtbl; + (*This)->ref = 1; + } +} + +static void DeleteTestLockBytes(TestLockBytes *This) +{ + ok(This->ILockBytes_iface.lpVtbl == &TestLockBytes_Vtbl, "test lock bytes %p deleted with incorrect vtable\n", This); + ok(This->ref == 1, "test lock bytes %p deleted with %i references instead of 1\n", This, This->ref); + HeapFree(GetProcessHeap(), 0, This->contents); + HeapFree(GetProcessHeap(), 0, This); }
static void test_hglobal_storage_stat(void) @@ -3157,22 +3352,22 @@ BOOL todo; };
-static const int priority_locked_bytes[] = { 0x58, 0x81, 0x93, -1 }; -static const int rwex_locked_bytes[] = { 0x93, 0xa7, 0xbb, 0xcf, -1 }; -static const int rw_locked_bytes[] = { 0x93, 0xa7, -1 }; -static const int nosn_locked_bytes[] = { 0x6c, 0x93, 0xa7, 0xcf, -1 }; -static const int rwdw_locked_bytes[] = { 0x93, 0xa7, 0xcf, -1 }; -static const int wodw_locked_bytes[] = { 0xa7, 0xcf, -1 }; -static const int tr_locked_bytes[] = { 0x93, -1 }; +static const int priority_locked_bytes[] = { 0x158, 0x181, 0x193, -1 }; +static const int rwex_locked_bytes[] = { 0x193, 0x1a7, 0x1bb, 0x1cf, -1 }; +static const int rw_locked_bytes[] = { 0x193, 0x1a7, -1 }; +static const int nosn_locked_bytes[] = { 0x16c, 0x193, 0x1a7, 0x1cf, -1 }; +static const int rwdw_locked_bytes[] = { 0x193, 0x1a7, 0x1cf, -1 }; +static const int wodw_locked_bytes[] = { 0x1a7, 0x1cf, -1 }; +static const int tr_locked_bytes[] = { 0x193, -1 }; static const int no_locked_bytes[] = { -1 }; -static const int roex_locked_bytes[] = { 0x93, 0xbb, 0xcf, -1 }; - -static const int rwex_fail_ranges[] = { 0x93,0xe3, -1 }; -static const int rw_fail_ranges[] = { 0xbb,0xe3, -1 }; -static const int rwdw_fail_ranges[] = { 0xa7,0xe3, -1 }; -static const int dw_fail_ranges[] = { 0xa7,0xcf, -1 }; -static const int tr_fail_ranges[] = { 0xbb,0xcf, -1 }; -static const int pr_fail_ranges[] = { 0x80,0x81, 0xbb,0xcf, -1 }; +static const int roex_locked_bytes[] = { 0x193, 0x1bb, 0x1cf, -1 }; + +static const int rwex_fail_ranges[] = { 0x193,0x1e3, -1 }; +static const int rw_fail_ranges[] = { 0x1bb,0x1e3, -1 }; +static const int rwdw_fail_ranges[] = { 0x1a7,0x1e3, -1 }; +static const int dw_fail_ranges[] = { 0x1a7,0x1cf, -1 }; +static const int tr_fail_ranges[] = { 0x1bb,0x1cf, -1 }; +static const int pr_fail_ranges[] = { 0x180,0x181, 0x1bb,0x1cf, -1 }; static const int roex_fail_ranges[] = { 0x0,-1 };
static const struct lock_test lock_tests[] = { @@ -3189,8 +3384,8 @@ { STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, rwdw_fail_ranges, FALSE }, { STGM_READ|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ, FILE_SHARE_READ, no_locked_bytes, dw_fail_ranges, TRUE }, { STGM_READ|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, tr_locked_bytes, tr_fail_ranges, FALSE }, - { STGM_READ|STGM_SHARE_EXCLUSIVE, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE }, - { STGM_READ|STGM_SHARE_EXCLUSIVE|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE }, + { STGM_READ|STGM_SHARE_EXCLUSIVE, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, FALSE }, + { STGM_READ|STGM_SHARE_EXCLUSIVE|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, FALSE }, };
static BOOL can_open(LPCWSTR filename, DWORD access, DWORD sharing) @@ -3317,7 +3512,7 @@ ol.u.s.OffsetHigh = 0; ol.hEvent = NULL;
- for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++) + for (ol.u.s.Offset = 0x7ffffe00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++) { if (LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol)) locked = FALSE; @@ -3329,7 +3524,7 @@
UnlockFileEx(hfile, 0, 1, 0, &ol);
- if ((ol.u.s.Offset&0xff) == *next_lock) + if ((ol.u.s.Offset&0x1ff) == *next_lock) { expect_locked = TRUE; next_lock++; @@ -3366,14 +3561,17 @@ ol.u.s.OffsetHigh = 0; ol.hEvent = NULL;
- for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++) + for (ol.u.s.Offset = 0x7ffffe00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++) { if (ol.u.s.Offset == 0x7fffff92 || (ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READWRITE)) || (ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READ))) continue; /* This makes opens hang */
- LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol); + if (ol.u.s.Offset < 0x7fffff00) + LockFileEx(hfile, 0, 0, 1, 0, &ol); + else + LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol);
hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg); ok(hr == S_OK || hr == STG_E_LOCKVIOLATION || hr == STG_E_SHAREVIOLATION, "failed with unexpected hr %x\n", hr); @@ -3383,11 +3581,11 @@
failed = FAILED(hr);
- if (!expect_failed && (ol.u.s.Offset&0xff) == next_range[0]) + if (!expect_failed && (ol.u.s.Offset&0x1ff) == next_range[0]) { expect_failed = TRUE; } - else if (expect_failed && (ol.u.s.Offset&0xff) == next_range[1]) + else if (expect_failed && (ol.u.s.Offset&0x1ff) == next_range[1]) { expect_failed = FALSE; next_range += 2; @@ -3644,6 +3842,54 @@ CloseHandle(hfile);
DeleteFileA(filenameA); +} + +static void test_custom_lockbytes(void) +{ + static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; + TestLockBytes* lockbytes; + HRESULT hr; + IStorage* stg; + IStream* stm; + + CreateTestLockBytes(&lockbytes); + + hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); + ok(hr==S_OK, "StgCreateDocfileOnILockBytes failed %x\n", hr); + + hr = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stm); + ok(hr==S_OK, "IStorage_CreateStream failed %x\n", hr); + + IStream_Release(stm); + + hr = IStorage_Commit(stg, 0); + + IStorage_Release(stg); + + ok(!lockbytes->lock_called, "unexpected call to LockRegion\n"); + + lockbytes->locks_supported = LOCK_WRITE|LOCK_EXCLUSIVE|LOCK_ONLYONCE; + + hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); + ok(hr==S_OK, "StgCreateDocfileOnILockBytes failed %x\n", hr); + + hr = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stm); + ok(hr==S_OK, "IStorage_CreateStream failed %x\n", hr); + + IStream_Release(stm); + + hr = IStorage_Commit(stg, 0); + + IStorage_Release(stg); + + ok(lockbytes->lock_called, "expected LockRegion to be called\n"); + + lockbytes->lock_hr = STG_E_INVALIDFUNCTION; + + hr = StgCreateDocfileOnILockBytes(&lockbytes->ILockBytes_iface, STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, 0, &stg); + ok(hr==STG_E_INVALIDFUNCTION, "StgCreateDocfileOnILockBytes failed %x\n", hr); + + DeleteTestLockBytes(lockbytes); }
START_TEST(storage32) @@ -3694,4 +3940,5 @@ test_locking(); test_transacted_shared(); test_overwrite(); -} + test_custom_lockbytes(); +}
Modified: trunk/rostests/winetests/ole32/usrmarshal.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/usrmarshal... ============================================================================== --- trunk/rostests/winetests/ole32/usrmarshal.c [iso-8859-1] (original) +++ trunk/rostests/winetests/ole32/usrmarshal.c [iso-8859-1] Sun Jul 19 23:12:15 2015 @@ -50,13 +50,22 @@ unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *, unsigned char *, HMETAFILEPICT *); void __RPC_USER HMETAFILEPICT_UserFree(ULONG *, HMETAFILEPICT *);
+ULONG __RPC_USER HBRUSH_UserSize(ULONG *, ULONG, HBRUSH *); +unsigned char * __RPC_USER HBRUSH_UserMarshal(ULONG *, unsigned char *, HBRUSH *); +unsigned char * __RPC_USER HBRUSH_UserUnmarshal(ULONG *, unsigned char *, HBRUSH *); +void __RPC_USER HBRUSH_UserFree(ULONG *, HBRUSH *); + +static BOOL g_expect_user_alloc; static void * WINAPI user_allocate(SIZE_T size) { + ok(g_expect_user_alloc, "unexpected user_allocate call\n"); return CoTaskMemAlloc(size); }
+static BOOL g_expect_user_free; static void WINAPI user_free(void *p) { + ok(g_expect_user_free, "unexpected user_free call\n"); CoTaskMemFree(p); }
@@ -207,7 +216,6 @@ GlobalUnlock(hglobal); actual_size = GlobalSize(hglobal); expected_size = actual_size + 5 * sizeof(DWORD); - trace("%d: actual size %d\n", block_size, actual_size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal); /* native is poorly programmed and allocates 4/8 bytes more than it needs to @@ -410,7 +418,6 @@ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); size = HMETAFILEPICT_UserSize(&umcb.Flags, 0, &hmfp); ok(size > 20, "size should be at least 20 bytes, not %d\n", size); - trace("size is %d\n", size); buffer = HeapAlloc(GetProcessHeap(), 0, size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE); buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer, &hmfp); @@ -476,6 +483,17 @@ HeapFree(GetProcessHeap(), 0, buffer); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE); HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2); +} + +typedef struct +{ + IUnknown IUnknown_iface; + LONG refs; +} TestUnknown; + +static inline TestUnknown *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface); }
static HRESULT WINAPI Test_IUnknown_QueryInterface( @@ -498,12 +516,14 @@
static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface) { - return 2; /* non-heap-based object */ + TestUnknown *This = impl_from_IUnknown(iface); + return InterlockedIncrement(&This->refs); }
static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface) { - return 1; /* non-heap-based object */ + TestUnknown *This = impl_from_IUnknown(iface); + return InterlockedDecrement(&This->refs); }
static const IUnknownVtbl TestUnknown_Vtbl = @@ -548,7 +568,7 @@ /* the rest can be NULLs */ };
-static IUnknown Test_Unknown = { &TestUnknown_Vtbl }; +static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 }; static IStream Test_Stream = { &TestStream_Vtbl };
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID); @@ -588,7 +608,8 @@ /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then the result of CoMarshalInterface called with the LOWORD of the ctx */
- unk = &Test_Unknown; + unk = &Test_Unknown.IUnknown_iface; + Test_Unknown.refs = 1;
CreateStreamOnHGlobal(h, TRUE, &stm); CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL); @@ -596,15 +617,17 @@ IStream_Seek(stm, zero, STREAM_SEEK_CUR, &pos); marshal_size = pos.u.LowPart; marshal_data = GlobalLock(h); - trace("marshal_size %x\n", marshal_size); +todo_wine + ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx); size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown); ok(size >= marshal_size + 2 * sizeof(DWORD), "marshal size %x got %x\n", marshal_size, size); - trace("WdtpInterfacePointer_UserSize returned %x\n", size); buffer = HeapAlloc(GetProcessHeap(), 0, size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown); +todo_wine + ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs); wireip = buffer;
ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer); @@ -625,6 +648,7 @@ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx); WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown); ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n"); + ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs); HeapFree(GetProcessHeap(), 0, buffer); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); IUnknown_Release(unk2); @@ -657,7 +681,7 @@ unsigned char *buffer, *buffer_end, *expect_buffer, *expect_buffer_end; ULONG size, expect_size; STGMEDIUM med, med2; - IUnknown *unk = &Test_Unknown; + IUnknown *unk = &Test_Unknown.IUnknown_iface; IStream *stm = &Test_Stream;
/* TYMED_NULL with pUnkForRelease */ @@ -753,6 +777,211 @@ STGMEDIUM_UserFree(&umcb.Flags, &med2);
HeapFree(GetProcessHeap(), 0, expect_buffer); +} + +static void test_marshal_SNB(void) +{ + static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0}; + static const WCHAR str2W[] = {'s','t','r','2',0}; + unsigned char *buffer, *src, *mbuf; + MIDL_STUB_MESSAGE stub_msg; + WCHAR **ptrW, *dataW; + USER_MARSHAL_CB umcb; + RPC_MESSAGE rpc_msg; + RemSNB *wiresnb; + SNB snb, snb2; + ULONG size; + + /* 4 bytes alignment */ + snb = NULL; + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = SNB_UserSize(&umcb.Flags, 3, &snb); + ok(size == 16, "Size should be 16, instead of %d\n", size); + + /* NULL block */ + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = SNB_UserSize(&umcb.Flags, 0, &snb); + ok(size == 12, "Size should be 12, instead of %d\n", size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb); + ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size); + + wiresnb = (RemSNB*)buffer; + ok(wiresnb->ulCntStr == 0, "got %u\n", wiresnb->ulCntStr); + ok(wiresnb->ulCntChar == 0, "got %u\n", wiresnb->ulCntChar); + ok(*(ULONG*)wiresnb->rgString == 0, "got %u\n", *(ULONG*)wiresnb->rgString); + + snb2 = NULL; + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2); + ok(snb2 == NULL, "got %p\n", snb2); + + HeapFree(GetProcessHeap(), 0, buffer); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + SNB_UserFree(&umcb.Flags, &snb2); + + /* block with actual data */ + + /* allocate source block, n+1 pointers first, then data */ + src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W)); + ptrW = (WCHAR**)src; + dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*)); + ptrW++; + *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W)); + ptrW++; + *ptrW = NULL; + lstrcpyW(dataW, str1W); + dataW += lstrlenW(str1W) + 1; + lstrcpyW(dataW, str2W); + + snb = (SNB)src; + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = SNB_UserSize(&umcb.Flags, 0, &snb); + ok(size == 38, "Size should be 38, instead of %d\n", size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + SNB_UserMarshal(&umcb.Flags, buffer, &snb); + + wiresnb = (RemSNB*)buffer; + ok(wiresnb->ulCntStr == 13, "got %u\n", wiresnb->ulCntStr); + ok(wiresnb->ulCntChar == 2, "got %u\n", wiresnb->ulCntChar); + /* payload length is stored one more time, as ULONG */ + ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %u\n", *(ULONG*)wiresnb->rgString); + dataW = &wiresnb->rgString[2]; + ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW)); + dataW += sizeof(str1W)/sizeof(WCHAR); + ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW)); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + + g_expect_user_alloc = TRUE; + snb2 = NULL; + SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2); + g_expect_user_alloc = FALSE; + + ptrW = snb2; + ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW)); + ptrW++; + ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW)); + ptrW++; + ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2); + + HeapFree(GetProcessHeap(), 0, buffer); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + + g_expect_user_free = TRUE; + SNB_UserFree(&umcb.Flags, &snb2); + g_expect_user_free = FALSE; + + HeapFree(GetProcessHeap(), 0, src); +} + +static void test_marshal_HDC(void) +{ + MIDL_STUB_MESSAGE stub_msg; + HDC hdc = GetDC(0), hdc2; + USER_MARSHAL_CB umcb; + RPC_MESSAGE rpc_msg; + unsigned char *buffer; + wireHDC wirehdc; + ULONG size; + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HDC_UserSize(&umcb.Flags, 0, &hdc); + ok(size == sizeof(*wirehdc), "Wrong size %d\n", size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HDC_UserMarshal(&umcb.Flags, buffer, &hdc); + wirehdc = (wireHDC)buffer; + ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc->fContext); + ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %x\n", hdc, wirehdc->u.hRemote); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HDC_UserUnmarshal(&umcb.Flags, buffer, &hdc2); + ok(hdc == hdc2, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + HDC_UserFree(&umcb.Flags, &hdc2); + ReleaseDC(0, hdc); +} + +static void test_marshal_HICON(void) +{ + static const BYTE bmp_bits[1024]; + MIDL_STUB_MESSAGE stub_msg; + HICON hIcon, hIcon2; + USER_MARSHAL_CB umcb; + RPC_MESSAGE rpc_msg; + unsigned char *buffer; + wireHICON wirehicon; + ULONG size; + + hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits); + ok(hIcon != 0, "CreateIcon failed\n"); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HICON_UserSize(&umcb.Flags, 0, &hIcon); + ok(size == sizeof(*wirehicon), "Wrong size %d\n", size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HICON_UserMarshal(&umcb.Flags, buffer, &hIcon); + wirehicon = (wireHICON)buffer; + ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon->fContext); + ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %x\n", hIcon, wirehicon->u.hRemote); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HICON_UserUnmarshal(&umcb.Flags, buffer, &hIcon2); + ok(hIcon == hIcon2, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + HICON_UserFree(&umcb.Flags, &hIcon2); + DestroyIcon(hIcon); +} + +static void test_marshal_HBRUSH(void) +{ + MIDL_STUB_MESSAGE stub_msg; + HBRUSH hBrush, hBrush2; + USER_MARSHAL_CB umcb; + RPC_MESSAGE rpc_msg; + unsigned char *buffer; + LOGBRUSH logbrush; + wireHBRUSH wirehbrush; + ULONG size; + + logbrush.lbStyle = BS_SOLID; + logbrush.lbColor = RGB(0, 0, 0); + logbrush.lbHatch = 0; + + hBrush = CreateBrushIndirect(&logbrush); + ok(hBrush != 0, "CreateBrushIndirect failed\n"); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HBRUSH_UserSize(&umcb.Flags, 0, &hBrush); + ok(size == sizeof(*wirehbrush), "Wrong size %d\n", size); + + buffer = HeapAlloc(GetProcessHeap(), 0, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HBRUSH_UserMarshal(&umcb.Flags, buffer, &hBrush); + wirehbrush = (wireHBRUSH)buffer; + ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush->fContext); + ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %x\n", hBrush, wirehbrush->u.hRemote); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + HBRUSH_UserUnmarshal(&umcb.Flags, buffer, &hBrush2); + ok(hBrush == hBrush2, "Didn't unmarshal properly\n"); + HeapFree(GetProcessHeap(), 0, buffer); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + HBRUSH_UserFree(&umcb.Flags, &hBrush2); + DeleteObject(hBrush); }
START_TEST(usrmarshal) @@ -767,6 +996,10 @@ test_marshal_HMETAFILEPICT(); test_marshal_WdtpInterfacePointer(); test_marshal_STGMEDIUM(); + test_marshal_SNB(); + test_marshal_HDC(); + test_marshal_HICON(); + test_marshal_HBRUSH();
CoUninitialize(); }