Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/ole32/tests/storage32.c | 164 +++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+)
diff --git a/dlls/ole32/tests/storage32.c b/dlls/ole32/tests/storage32.c index eea78c6d3fe..da2e411eea4 100644 --- a/dlls/ole32/tests/storage32.c +++ b/dlls/ole32/tests/storage32.c @@ -3876,6 +3876,9 @@ static void test_custom_lockbytes(void)
hr = IStorage_Commit(stg, 0);
+ ok(lockbytes->contents != NULL, "lockbytes->contents should not be NULL\n"); + ok(*(DWORD *)lockbytes->contents == 0xe011cfd0, "contents: %08x\n", *(DWORD *)lockbytes->contents); + IStorage_Release(stg);
ok(!lockbytes->lock_called, "unexpected call to LockRegion\n"); @@ -3904,6 +3907,166 @@ static void test_custom_lockbytes(void) DeleteTestLockBytes(lockbytes); }
+struct byte_array_t +{ + ILockBytes ILockBytes_iface; + ILockBytes *lock_bytes; + HGLOBAL mem; + LONG ref; +}; + +static inline struct byte_array_t *byte_array_from_ILockBytes(ILockBytes *iface) +{ + return CONTAINING_RECORD(iface, struct byte_array_t, ILockBytes_iface); +} + +static HRESULT WINAPI byte_array_QueryInterface(ILockBytes *iface, REFIID iid, void **ppv) +{ + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_ILockBytes, iid)) + { + ILockBytes_AddRef(iface); + *ppv = iface; + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI byte_array_AddRef(ILockBytes *iface) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI byte_array_Release(ILockBytes *iface) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + ULONG ref = InterlockedDecrement(&This->ref); + if (!ref) + { + ILockBytes_Release(This->lock_bytes); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI byte_array_ReadAt(ILockBytes *iface, + ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_ReadAt(This->lock_bytes, ulOffset, pv, cb, pcbRead); +} + +static HRESULT WINAPI byte_array_WriteAt(ILockBytes *iface, + ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_WriteAt(This->lock_bytes, ulOffset, pv, cb, pcbWritten); +} + +static HRESULT WINAPI byte_array_Flush(ILockBytes *iface) +{ + return S_OK; +} + +static HRESULT WINAPI byte_array_SetSize(ILockBytes *iface, ULARGE_INTEGER cb) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_SetSize(This->lock_bytes, cb); +} + +static HRESULT WINAPI byte_array_LockRegion(ILockBytes *iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_LockRegion(This->lock_bytes, libOffset, cb, dwLockType); +} + +static HRESULT WINAPI byte_array_UnlockRegion(ILockBytes *iface, + ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_UnlockRegion(This->lock_bytes, libOffset, cb, dwLockType); +} + +static HRESULT WINAPI byte_array_Stat(ILockBytes *iface, + STATSTG *pstatstg, DWORD grfStatFlag) +{ + struct byte_array_t *This = byte_array_from_ILockBytes(iface); + return ILockBytes_Stat(This->lock_bytes, pstatstg, grfStatFlag); +} + +static const ILockBytesVtbl byte_array_Vtbl = +{ + byte_array_QueryInterface, + byte_array_AddRef, + byte_array_Release, + byte_array_ReadAt, + byte_array_WriteAt, + byte_array_Flush, + byte_array_SetSize, + byte_array_LockRegion, + byte_array_UnlockRegion, + byte_array_Stat +}; + +static struct byte_array_t *create_byte_array(void) +{ + struct byte_array_t *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (This) + { + HRESULT hr; + + This->ref = 1; + This->ILockBytes_iface.lpVtbl = &byte_array_Vtbl; + This->mem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 1024); + hr = CreateILockBytesOnHGlobal(This->mem, TRUE, &This->lock_bytes); + ok(hr == S_OK, "CreateILockBytesOnHGlobal error %#x\n", hr); + } + return This; +} + +static void test_custom_lockbytes_on_hglobal(void) +{ + static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 }; + struct byte_array_t *This; + HRESULT hr; + IStorage *stg; + IStream *stm; + DWORD *p; + + This = create_byte_array(); + + hr = StgCreateDocfileOnILockBytes(&This->ILockBytes_iface, STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE, 0, &stg); + ok(hr == S_OK, "got %#x\n", hr); + + hr = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); + ok(hr == S_OK, "got %#x\n", hr); + + IStream_Write(stm, "Hello World!", 12, NULL); + IStream_Release(stm); + + p = GlobalLock(This->mem); +todo_wine + ok(*p == 0, "got %#x\n", *p); + memset(p, 0, 512); + GlobalUnlock(This->mem); + + hr = IStorage_Commit(stg, STGC_DEFAULT); + ok(hr == S_OK, "got %#x\n", hr); + + IStorage_Release(stg); + + p = GlobalLock(This->mem); +todo_wine + ok(*p == 0xe011cfd0, "got %#x\n", *p); + GlobalUnlock(This->mem); + + ILockBytes_Release(&This->ILockBytes_iface); +} + START_TEST(storage32) { CHAR temp[MAX_PATH]; @@ -3953,4 +4116,5 @@ START_TEST(storage32) test_transacted_shared(); test_overwrite(); test_custom_lockbytes(); + test_custom_lockbytes_on_hglobal(); }
Why do we need a different custom ILockBytes implementation to test this?
"Esme Povirk (they/them)" esme@codeweavers.com wrote:
Why do we need a different custom ILockBytes implementation to test this?
Fair enough. I've sent new version that extends existing tests instead.