[OLE32_WINETEST] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68470
This commit is contained in:
Amine Khaldi 2015-07-19 23:12:15 +00:00
parent bc504c5a3f
commit afe5b2c7bf
7 changed files with 721 additions and 42 deletions

View file

@ -22,4 +22,9 @@ add_executable(ole32_winetest ${SOURCE})
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)

View file

@ -102,7 +102,7 @@ static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFII
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 @@ static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt,
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 @@ static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID r
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
IDataObject_AddRef(iface);
*ppvObj = This;
*ppvObj = &This->IDataObject_iface;
return S_OK;
}
*ppvObj = NULL;

View file

@ -1563,7 +1563,7 @@ static void test_registered_object_thread_affinity(void)
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 @@ static void test_TreatAsClass(void)
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);

View file

@ -452,13 +452,16 @@ static void test_Register_Revoke(void)
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);

View file

@ -1688,6 +1688,113 @@ static void test_data_cache(void)
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 @@ static const IUnknownVtbl UnknownVtbl =
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 @@ START_TEST(ole2)
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();

View file

@ -61,6 +61,201 @@ static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
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)
{
ILockBytes *ilb = NULL;
@ -3157,22 +3352,22 @@ struct lock_test
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 roex_locked_bytes[] = { 0x193, 0x1bb, 0x1cf, -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 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 @@ static const struct lock_test lock_tests[] = {
{ 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 @@ static void test_locking(void)
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 @@ static void test_locking(void)
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 @@ static void test_locking(void)
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 @@ static void test_locking(void)
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;
@ -3646,6 +3844,54 @@ static void test_overwrite(void)
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)
{
CHAR temp[MAX_PATH];
@ -3694,4 +3940,5 @@ START_TEST(storage32)
test_locking();
test_transacted_shared();
test_overwrite();
test_custom_lockbytes();
}

View file

@ -50,13 +50,22 @@ unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal (ULONG *, unsigned char *,
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 @@ static void test_marshal_HGLOBAL(void)
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 @@ static void test_marshal_HMETAFILEPICT(void)
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);
@ -478,6 +485,17 @@ static void test_marshal_HMETAFILEPICT(void)
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(
LPUNKNOWN iface,
REFIID riid,
@ -498,12 +516,14 @@ static HRESULT WINAPI Test_IUnknown_QueryInterface(
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 @@ static const IStreamVtbl TestStream_Vtbl =
/* 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 @@ static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx)
/* 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 @@ static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx)
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 @@ static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx)
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 @@ static void test_marshal_STGMEDIUM(void)
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 */
@ -755,6 +779,211 @@ static void test_marshal_STGMEDIUM(void)
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)
{
CoInitialize(NULL);
@ -767,6 +996,10 @@ START_TEST(usrmarshal)
test_marshal_HMETAFILEPICT();
test_marshal_WdtpInterfacePointer();
test_marshal_STGMEDIUM();
test_marshal_SNB();
test_marshal_HDC();
test_marshal_HICON();
test_marshal_HBRUSH();
CoUninitialize();
}