From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/tests/wintypes.c | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-)
diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 90bd32513f8..727c36511f3 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -17,6 +17,7 @@ */ #define COBJMACROS #include <stdarg.h> +#include <stdint.h>
#include "windef.h" #include "winbase.h" @@ -134,9 +135,23 @@ static void test_interfaces(void) RoUninitialize(); }
+static UINT32 get_max_capacity(void) +{ + SYSTEM_INFO sys_info; + UINT_PTR max_addr; + + if (is_wow64) return 0x7FFEFFFF; + + GetNativeSystemInfo( &sys_info ); + max_addr = (UINT_PTR)sys_info.lpMaximumApplicationAddress; + + return (max_addr > UINT32_MAX) ? UINT32_MAX : max_addr; +} + static void test_IBufferStatics(void) { static const WCHAR *class_name = L"Windows.Storage.Streams.Buffer"; + UINT32 capacity, max_capacity, length; IBufferFactory *buffer_factory = NULL; IActivationFactory *factory = NULL; IBuffer *buffer = NULL; @@ -175,8 +190,95 @@ static void test_IBufferStatics(void) hr = IBufferFactory_Create(buffer_factory, 0, &buffer); todo_wine ok(hr == S_OK, "IBufferFactory_Create failed, hr %#lx.\n", hr); - if (hr == S_OK) IBuffer_Release(buffer); + if (hr != S_OK) goto done; + + check_interface(buffer, &IID_IAgileObject, TRUE); + + if (0) /* Crash on Windows */ + { + hr = IBuffer_get_Capacity(buffer, NULL); + ok(hr == E_INVALIDARG, "IBuffer_get_Capacity failed, hr %#lx.\n", hr); + } + + capacity = 0xdeadbeef; + hr = IBuffer_get_Capacity(buffer, &capacity); + todo_wine + ok(hr == S_OK, "IBuffer_get_Capacity failed, hr %#lx.\n", hr); + todo_wine + ok(capacity == 0, "IBuffer_get_Capacity returned capacity %u.\n", capacity); + + if (0) /* Crash on Windows */ + { + hr = IBuffer_get_Length(buffer, NULL); + ok(hr == E_INVALIDARG, "IBuffer_get_Length failed, hr %#lx.\n", hr); + } + + length = 0xdeadbeef; + hr = IBuffer_get_Length(buffer, &length); + todo_wine + ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); + todo_wine + ok(length == 0, "IBuffer_get_Length returned length %u.\n", length); + + hr = IBuffer_put_Length(buffer, 1); + todo_wine + ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr); + + IBuffer_Release(buffer); + + capacity = 0xdeadbeef; + max_capacity = get_max_capacity(); + buffer = (void *)0xdeadbeef; + hr = IBufferFactory_Create(buffer_factory, capacity, &buffer); + todo_wine + ok(hr == S_OK || (hr == E_OUTOFMEMORY && capacity > max_capacity), "IBufferFactory_Create failed, hr %#lx.\n", hr); + if (hr == E_OUTOFMEMORY) /* 32-bit memory limitation, Large Address Aware is ignored */ + { + todo_wine + ok(buffer == NULL, "IBufferFactory_Create returned buffer %p.\n", buffer); + goto done; + } + + capacity = 0; + hr = IBuffer_get_Capacity(buffer, &capacity); + todo_wine + ok(hr == S_OK, "IBuffer_get_Capacity failed, hr %#lx.\n", hr); + todo_wine + ok(capacity == 0xdeadbeef, "IBuffer_get_Capacity returned capacity %u.\n", capacity); + + length = 0xdeadbeef; + hr = IBuffer_get_Length(buffer, &length); + todo_wine + ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); + todo_wine + ok(length == 0, "IBuffer_get_Length returned length %u.\n", length); + + hr = IBuffer_put_Length(buffer, 1); + todo_wine + ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); + length = 0xdeadbeef; + hr = IBuffer_get_Length(buffer, &length); + todo_wine + ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); + todo_wine + ok(length == 1, "IBuffer_get_Length returned length %u.\n", length); + + hr = IBuffer_put_Length(buffer, 0xdeadbeef + 1); + todo_wine + ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr); + + hr = IBuffer_put_Length(buffer, 0xdeadbeef); + todo_wine + ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); + length = 0; + hr = IBuffer_get_Length(buffer, &length); + todo_wine + ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); + todo_wine + ok(length == 0xdeadbeef, "IBuffer_get_Length returned length %u.\n", length);
+ IBuffer_Release(buffer); +done: IBufferFactory_Release(buffer_factory); IActivationFactory_Release(factory); RoUninitialize();
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/buffer.c | 150 ++++++++++++++++++++++++++++++++- dlls/wintypes/tests/wintypes.c | 4 - 2 files changed, 148 insertions(+), 6 deletions(-)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index a5dc7d2d1f7..a80397bfd5d 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdint.h> + #include "private.h"
WINE_DEFAULT_DEBUG_CHANNEL(wintypes); @@ -114,12 +116,156 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+struct buffer +{ + IBuffer IBuffer_iface; + LONG ref; + + UINT32 capacity; + UINT32 length; + BYTE *data; +}; + +static inline struct buffer *impl_from_IBuffer( IBuffer *iface ) +{ + return CONTAINING_RECORD( iface, struct buffer, IBuffer_iface ); +} + +static HRESULT WINAPI buffer_QueryInterface( IBuffer *iface, REFIID iid, void **out ) +{ + struct buffer *impl = impl_from_IBuffer( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IBuffer )) + { + *out = &impl->IBuffer_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI buffer_AddRef( IBuffer *iface ) +{ + struct buffer *impl = impl_from_IBuffer( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI buffer_Release( IBuffer *iface ) +{ + struct buffer *impl = impl_from_IBuffer( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) + { + free( impl->data ); + free( impl ); + } + return ref; +} + +static HRESULT WINAPI buffer_GetIids( IBuffer *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI buffer_GetRuntimeClassName( IBuffer *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI buffer_GetTrustLevel( IBuffer *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI buffer_get_Capacity( IBuffer *iface, UINT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI buffer_get_Length( IBuffer *iface, UINT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI buffer_put_Length( IBuffer *iface, UINT32 value ) +{ + FIXME( "iface %p, value %u stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const struct IBufferVtbl buffer_vtbl = +{ + buffer_QueryInterface, + buffer_AddRef, + buffer_Release, + /* IInspectable methods */ + buffer_GetIids, + buffer_GetRuntimeClassName, + buffer_GetTrustLevel, + /* IBuffer methods */ + buffer_get_Capacity, + buffer_get_Length, + buffer_put_Length, +}; + DEFINE_IINSPECTABLE( buffer_factory_statics, IBufferFactory, struct buffer_factory_statics, IActivationFactory_iface )
+static UINT32 get_max_capacity(void) +{ + SYSTEM_INFO sys_info; + UINT_PTR max_addr; + BOOL is_wow64; + + IsWow64Process( GetCurrentProcess(), &is_wow64 ); + if (is_wow64) return 0x7FFEFFFF; + + GetNativeSystemInfo( &sys_info ); + max_addr = (UINT_PTR)sys_info.lpMaximumApplicationAddress; + + return (max_addr > UINT32_MAX) ? UINT32_MAX : max_addr; +} + static HRESULT WINAPI buffer_factory_statics_Create( IBufferFactory *iface, UINT32 capacity, IBuffer **value ) { - FIXME( "iface %p, capacity %u, value %p stub!\n", iface, capacity, value ); - return E_NOTIMPL; + struct buffer *impl; + + TRACE( "iface %p, capacity %u, value %p\n", iface, capacity, value ); + + *value = NULL; + + if (capacity > get_max_capacity() || !(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; + + impl->IBuffer_iface.lpVtbl = &buffer_vtbl; + impl->ref = 1; + impl->capacity = capacity; + impl->length = 0; + if (!(impl->data = malloc( capacity ))) + { + free( impl ); + return E_OUTOFMEMORY; + } + + *value = &impl->IBuffer_iface; + TRACE( "created IBuffer %p.\n", *value ); + return S_OK; }
static const struct IBufferFactoryVtbl buffer_factory_statics_vtbl = diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 727c36511f3..f759744e754 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -188,9 +188,7 @@ static void test_IBufferStatics(void) }
hr = IBufferFactory_Create(buffer_factory, 0, &buffer); - todo_wine ok(hr == S_OK, "IBufferFactory_Create failed, hr %#lx.\n", hr); - if (hr != S_OK) goto done;
check_interface(buffer, &IID_IAgileObject, TRUE);
@@ -230,11 +228,9 @@ static void test_IBufferStatics(void) max_capacity = get_max_capacity(); buffer = (void *)0xdeadbeef; hr = IBufferFactory_Create(buffer_factory, capacity, &buffer); - todo_wine ok(hr == S_OK || (hr == E_OUTOFMEMORY && capacity > max_capacity), "IBufferFactory_Create failed, hr %#lx.\n", hr); if (hr == E_OUTOFMEMORY) /* 32-bit memory limitation, Large Address Aware is ignored */ { - todo_wine ok(buffer == NULL, "IBufferFactory_Create returned buffer %p.\n", buffer); goto done; }
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/buffer.c | 8 ++++++-- dlls/wintypes/tests/wintypes.c | 4 ---- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index a80397bfd5d..2e2e4ceced0 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -195,8 +195,12 @@ static HRESULT WINAPI buffer_GetTrustLevel( IBuffer *iface, TrustLevel *trust_le
static HRESULT WINAPI buffer_get_Capacity( IBuffer *iface, UINT32 *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct buffer *impl = impl_from_IBuffer( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->capacity; + return S_OK; }
static HRESULT WINAPI buffer_get_Length( IBuffer *iface, UINT32 *value ) diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index f759744e754..53ef796d539 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -200,9 +200,7 @@ static void test_IBufferStatics(void)
capacity = 0xdeadbeef; hr = IBuffer_get_Capacity(buffer, &capacity); - todo_wine ok(hr == S_OK, "IBuffer_get_Capacity failed, hr %#lx.\n", hr); - todo_wine ok(capacity == 0, "IBuffer_get_Capacity returned capacity %u.\n", capacity);
if (0) /* Crash on Windows */ @@ -237,9 +235,7 @@ static void test_IBufferStatics(void)
capacity = 0; hr = IBuffer_get_Capacity(buffer, &capacity); - todo_wine ok(hr == S_OK, "IBuffer_get_Capacity failed, hr %#lx.\n", hr); - todo_wine ok(capacity == 0xdeadbeef, "IBuffer_get_Capacity returned capacity %u.\n", capacity);
length = 0xdeadbeef;
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/buffer.c | 10 ++++++++-- dlls/wintypes/tests/wintypes.c | 4 ---- 2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index 2e2e4ceced0..da59d28aa86 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -211,8 +211,14 @@ static HRESULT WINAPI buffer_get_Length( IBuffer *iface, UINT32 *value )
static HRESULT WINAPI buffer_put_Length( IBuffer *iface, UINT32 value ) { - FIXME( "iface %p, value %u stub!\n", iface, value ); - return E_NOTIMPL; + struct buffer *impl = impl_from_IBuffer( iface ); + + TRACE( "iface %p, value %u\n", iface, value ); + + if (value > impl->capacity) return E_INVALIDARG; + + impl->length = value; + return S_OK; }
static const struct IBufferVtbl buffer_vtbl = diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 53ef796d539..1ceab853591 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -217,7 +217,6 @@ static void test_IBufferStatics(void) ok(length == 0, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 1); - todo_wine ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr);
IBuffer_Release(buffer); @@ -246,7 +245,6 @@ static void test_IBufferStatics(void) ok(length == 0, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 1); - todo_wine ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); length = 0xdeadbeef; hr = IBuffer_get_Length(buffer, &length); @@ -256,11 +254,9 @@ static void test_IBufferStatics(void) ok(length == 1, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 0xdeadbeef + 1); - todo_wine ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr);
hr = IBuffer_put_Length(buffer, 0xdeadbeef); - todo_wine ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); length = 0; hr = IBuffer_get_Length(buffer, &length);
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/buffer.c | 8 ++++++-- dlls/wintypes/tests/wintypes.c | 8 -------- 2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index da59d28aa86..437bb1d526d 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -205,8 +205,12 @@ static HRESULT WINAPI buffer_get_Capacity( IBuffer *iface, UINT32 *value )
static HRESULT WINAPI buffer_get_Length( IBuffer *iface, UINT32 *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct buffer *impl = impl_from_IBuffer( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->length; + return S_OK; }
static HRESULT WINAPI buffer_put_Length( IBuffer *iface, UINT32 value ) diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 1ceab853591..d6f4c2d7006 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -211,9 +211,7 @@ static void test_IBufferStatics(void)
length = 0xdeadbeef; hr = IBuffer_get_Length(buffer, &length); - todo_wine ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); - todo_wine ok(length == 0, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 1); @@ -239,18 +237,14 @@ static void test_IBufferStatics(void)
length = 0xdeadbeef; hr = IBuffer_get_Length(buffer, &length); - todo_wine ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); - todo_wine ok(length == 0, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 1); ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); length = 0xdeadbeef; hr = IBuffer_get_Length(buffer, &length); - todo_wine ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); - todo_wine ok(length == 1, "IBuffer_get_Length returned length %u.\n", length);
hr = IBuffer_put_Length(buffer, 0xdeadbeef + 1); @@ -260,9 +254,7 @@ static void test_IBufferStatics(void) ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); length = 0; hr = IBuffer_get_Length(buffer, &length); - todo_wine ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); - todo_wine ok(length == 0xdeadbeef, "IBuffer_get_Length returned length %u.\n", length);
IBuffer_Release(buffer);
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/buffer.c | 49 ++++++++++++++++++++++++++++++++++ dlls/wintypes/tests/wintypes.c | 12 +++++++++ 2 files changed, 61 insertions(+)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index 437bb1d526d..07b9484f6e5 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -20,6 +20,8 @@ #include <stdint.h>
#include "private.h" +#include "initguid.h" +#include "robuffer.h"
WINE_DEFAULT_DEBUG_CHANNEL(wintypes);
@@ -119,6 +121,7 @@ static const struct IActivationFactoryVtbl factory_vtbl = struct buffer { IBuffer IBuffer_iface; + IBufferByteAccess IBufferByteAccess_iface; LONG ref;
UINT32 capacity; @@ -147,6 +150,13 @@ static HRESULT WINAPI buffer_QueryInterface( IBuffer *iface, REFIID iid, void ** return S_OK; }
+ if (IsEqualGUID( iid, &IID_IBufferByteAccess )) + { + *out = &impl->IBufferByteAccess_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -240,6 +250,44 @@ static const struct IBufferVtbl buffer_vtbl = buffer_put_Length, };
+static inline struct buffer *impl_from_IBufferByteAccess( IBufferByteAccess *iface ) +{ + return CONTAINING_RECORD( iface, struct buffer, IBufferByteAccess_iface ); +} + +static HRESULT WINAPI buffer_byte_access_QueryInterface( IBufferByteAccess *iface, REFIID iid, void **out ) +{ + struct buffer *impl = impl_from_IBufferByteAccess( iface ); + return IBuffer_QueryInterface( &impl->IBuffer_iface, iid, out ); +} + +static ULONG WINAPI buffer_byte_access_AddRef( IBufferByteAccess *iface ) +{ + struct buffer *impl = impl_from_IBufferByteAccess( iface ); + return IBuffer_AddRef( &impl->IBuffer_iface ); +} + +static ULONG WINAPI buffer_byte_access_Release( IBufferByteAccess *iface ) +{ + struct buffer *impl = impl_from_IBufferByteAccess( iface ); + return IBuffer_Release( &impl->IBuffer_iface ); +} + +static HRESULT WINAPI buffer_byte_access_Buffer( IBufferByteAccess *iface, byte **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const struct IBufferByteAccessVtbl buffer_byte_access_vtbl = +{ + buffer_byte_access_QueryInterface, + buffer_byte_access_AddRef, + buffer_byte_access_Release, + /* IBufferByteAccess methods */ + buffer_byte_access_Buffer, +}; + DEFINE_IINSPECTABLE( buffer_factory_statics, IBufferFactory, struct buffer_factory_statics, IActivationFactory_iface )
static UINT32 get_max_capacity(void) @@ -268,6 +316,7 @@ static HRESULT WINAPI buffer_factory_statics_Create( IBufferFactory *iface, UINT if (capacity > get_max_capacity() || !(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY;
impl->IBuffer_iface.lpVtbl = &buffer_vtbl; + impl->IBufferByteAccess_iface.lpVtbl = &buffer_byte_access_vtbl; impl->ref = 1; impl->capacity = capacity; impl->length = 0; diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index d6f4c2d7006..4f8b2481e37 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -36,6 +36,8 @@ #define WIDL_using_Windows_Storage_Streams #include "windows.storage.streams.h"
+#include "robuffer.h" + #include "wine/test.h"
static BOOL is_wow64; @@ -151,6 +153,7 @@ static UINT32 get_max_capacity(void) static void test_IBufferStatics(void) { static const WCHAR *class_name = L"Windows.Storage.Streams.Buffer"; + IBufferByteAccess *buffer_byte_access = NULL; UINT32 capacity, max_capacity, length; IBufferFactory *buffer_factory = NULL; IActivationFactory *factory = NULL; @@ -177,6 +180,7 @@ static void test_IBufferStatics(void) check_interface(factory, &IID_IUnknown, TRUE); check_interface(factory, &IID_IInspectable, TRUE); check_interface(factory, &IID_IAgileObject, TRUE); + check_interface(factory, &IID_IBufferByteAccess, FALSE);
hr = IActivationFactory_QueryInterface(factory, &IID_IBufferFactory, (void **)&buffer_factory); ok(hr == S_OK, "QueryInterface IID_IBufferFactory failed, hr %#lx.\n", hr); @@ -217,6 +221,14 @@ static void test_IBufferStatics(void) hr = IBuffer_put_Length(buffer, 1); ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr);
+ hr = IBuffer_QueryInterface(buffer, &IID_IBufferByteAccess, (void **)&buffer_byte_access); + ok(hr == S_OK, "QueryInterface IID_IBufferByteAccess failed, hr %#lx.\n", hr); + + check_interface(buffer_byte_access, &IID_IInspectable, TRUE); + check_interface(buffer_byte_access, &IID_IAgileObject, TRUE); + check_interface(buffer_byte_access, &IID_IBuffer, TRUE); + + IBufferByteAccess_Release(buffer_byte_access); IBuffer_Release(buffer);
capacity = 0xdeadbeef;
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/wintypes/tests/wintypes.c | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 4f8b2481e37..3bb88cfe0aa 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -160,6 +160,7 @@ static void test_IBufferStatics(void) IBuffer *buffer = NULL; HSTRING str; HRESULT hr; + BYTE *data;
hr = RoInitialize(RO_INIT_MULTITHREADED); ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr); @@ -228,6 +229,19 @@ static void test_IBufferStatics(void) check_interface(buffer_byte_access, &IID_IAgileObject, TRUE); check_interface(buffer_byte_access, &IID_IBuffer, TRUE);
+ if (0) /* Crash on Windows */ + { + hr = IBufferByteAccess_Buffer(buffer_byte_access, NULL); + ok(hr == E_INVALIDARG, "IBufferByteAccess_Buffer failed, hr %#lx.\n", hr); + } + + data = NULL; + hr = IBufferByteAccess_Buffer(buffer_byte_access, &data); + todo_wine + ok(hr == S_OK, "IBufferByteAccess_Buffer failed, hr %#lx.\n", hr); + todo_wine + ok(data != NULL, "IBufferByteAccess_Buffer returned NULL data.\n"); + IBufferByteAccess_Release(buffer_byte_access); IBuffer_Release(buffer);
@@ -269,6 +283,33 @@ static void test_IBufferStatics(void) ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); ok(length == 0xdeadbeef, "IBuffer_get_Length returned length %u.\n", length);
+ hr = IBuffer_QueryInterface(buffer, &IID_IBufferByteAccess, (void **)&buffer_byte_access); + ok(hr == S_OK, "QueryInterface IID_IBufferByteAccess failed, hr %#lx.\n", hr); + + hr = IBufferByteAccess_Buffer(buffer_byte_access, &data); + todo_wine + ok(hr == S_OK, "IBufferByteAccess_Buffer failed, hr %#lx.\n", hr); + if (hr != S_OK) goto done2; + + /* Windows does not zero out data when changing Length */ + + hr = IBuffer_put_Length(buffer, 0); + ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); + data[0] = 1; + data[10] = 10; + length = 0xdeadbeef; + hr = IBuffer_get_Length(buffer, &length); + ok(hr == S_OK, "IBuffer_get_Length failed, hr %#lx.\n", hr); + ok(length == 0, "IBuffer_get_Length returned length %u.\n", length); + hr = IBuffer_put_Length(buffer, 1); + ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); + todo_wine + ok(data[0] == 1, "Buffer returned %#x.\n", data[0]); + todo_wine + ok(data[10] == 10, "Buffer returned %#x.\n", data[10]); + + IBufferByteAccess_Release(buffer_byte_access); +done2: IBuffer_Release(buffer); done: IBufferFactory_Release(buffer_factory);
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55759 --- dlls/wintypes/buffer.c | 8 ++++++-- dlls/wintypes/tests/wintypes.c | 7 ------- 2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/dlls/wintypes/buffer.c b/dlls/wintypes/buffer.c index 07b9484f6e5..3575ad3b0ee 100644 --- a/dlls/wintypes/buffer.c +++ b/dlls/wintypes/buffer.c @@ -275,8 +275,12 @@ static ULONG WINAPI buffer_byte_access_Release( IBufferByteAccess *iface )
static HRESULT WINAPI buffer_byte_access_Buffer( IBufferByteAccess *iface, byte **value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + struct buffer *impl = impl_from_IBufferByteAccess( iface ); + + TRACE( "iface %p, value %p\n", iface, value ); + + *value = impl->data; + return S_OK; }
static const struct IBufferByteAccessVtbl buffer_byte_access_vtbl = diff --git a/dlls/wintypes/tests/wintypes.c b/dlls/wintypes/tests/wintypes.c index 3bb88cfe0aa..3b62bd2434f 100644 --- a/dlls/wintypes/tests/wintypes.c +++ b/dlls/wintypes/tests/wintypes.c @@ -237,9 +237,7 @@ static void test_IBufferStatics(void)
data = NULL; hr = IBufferByteAccess_Buffer(buffer_byte_access, &data); - todo_wine ok(hr == S_OK, "IBufferByteAccess_Buffer failed, hr %#lx.\n", hr); - todo_wine ok(data != NULL, "IBufferByteAccess_Buffer returned NULL data.\n");
IBufferByteAccess_Release(buffer_byte_access); @@ -287,9 +285,7 @@ static void test_IBufferStatics(void) ok(hr == S_OK, "QueryInterface IID_IBufferByteAccess failed, hr %#lx.\n", hr);
hr = IBufferByteAccess_Buffer(buffer_byte_access, &data); - todo_wine ok(hr == S_OK, "IBufferByteAccess_Buffer failed, hr %#lx.\n", hr); - if (hr != S_OK) goto done2;
/* Windows does not zero out data when changing Length */
@@ -303,13 +299,10 @@ static void test_IBufferStatics(void) ok(length == 0, "IBuffer_get_Length returned length %u.\n", length); hr = IBuffer_put_Length(buffer, 1); ok(hr == S_OK, "IBuffer_put_Length failed, hr %#lx.\n", hr); - todo_wine ok(data[0] == 1, "Buffer returned %#x.\n", data[0]); - todo_wine ok(data[10] == 10, "Buffer returned %#x.\n", data[10]);
IBufferByteAccess_Release(buffer_byte_access); -done2: IBuffer_Release(buffer); done: IBufferFactory_Release(buffer_factory);
Rémi Bernon (@rbernon) commented about dlls/wintypes/tests/wintypes.c:
- ok(hr == E_INVALIDARG, "IBuffer_put_Length failed, hr %#lx.\n", hr);
- IBuffer_Release(buffer);
- capacity = 0xdeadbeef;
- max_capacity = get_max_capacity();
- buffer = (void *)0xdeadbeef;
- hr = IBufferFactory_Create(buffer_factory, capacity, &buffer);
- todo_wine
- ok(hr == S_OK || (hr == E_OUTOFMEMORY && capacity > max_capacity), "IBufferFactory_Create failed, hr %#lx.\n", hr);
- if (hr == E_OUTOFMEMORY) /* 32-bit memory limitation, Large Address Aware is ignored */
- {
todo_wine
ok(buffer == NULL, "IBufferFactory_Create returned buffer %p.\n", buffer);
goto done;
- }
Is it really useful to test such corner case here?
Rémi Bernon (@rbernon) commented about dlls/wintypes/buffer.c:
- TRACE( "iface %p, capacity %u, value %p\n", iface, capacity, value );
- *value = NULL;
- if (capacity > get_max_capacity() || !(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY;
- impl->IBuffer_iface.lpVtbl = &buffer_vtbl;
- impl->ref = 1;
- impl->capacity = capacity;
- impl->length = 0;
- if (!(impl->data = malloc( capacity )))
- {
free( impl );
return E_OUTOFMEMORY;
- }
If buffer cannot grow, we should use a single allocation instead and let malloc decide whether it succeeds without having a specific limit. Use a variable sized struct buffer, like hstring_vector in dlls/windows.globalization/main.c (please include a similar C_ASSERT too).