Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH 3/3] jscript: Correctly handle deleted entries in iterate_map.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=116388
Your paranoid android.
=== w7u_el (32 bit report) ===
mshtml:
script.c:644: Test failed: L"/index.html?es5.js:date_now: unexpected Date.now() result 1654621858533 expected 1654621858596"
June 7, 2022
[PATCH 5/5] ntdll: Implement RtlSetUserValueHeap.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/kernel32/tests/heap.c | 13 +++----------
dlls/ntdll/heap.c | 36 ++++++++++++++++++++++++++++++++----
2 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index c237d515648..d4022b0d949 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -354,9 +354,7 @@ static void test_HeapCreate(void)
ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() );
align |= (UINT_PTR)ptrs[i];
}
- todo_wine_if( sizeof(void *) == 8 )
ok( !(align & (8 * sizeof(void *) - 1)), "got wrong alignment\n" );
- todo_wine_if( sizeof(void *) == 8 )
ok( align & (8 * sizeof(void *)), "got wrong alignment\n" );
for (i = 0; i < ARRAY_SIZE(ptrs); ++i)
{
@@ -2217,7 +2215,7 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2;
- todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 )
+ todo_wine_if( alloc_size == 0x7efe9 )
ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) );
@@ -2292,7 +2290,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
ok( tmp_flags == 0x200, "got flags %#lx\n", tmp_flags );
ret = pRtlSetUserValueHeap( heap, 0, ptr0, (void *)0xdeadbeef );
- todo_wine
ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
SetLastError( 0xdeadbeef );
ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0, 0x1000 );
@@ -2319,13 +2316,9 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
"got flags %#lx\n", tmp_flags );
user_ptr = (void **)(ptr0 + alloc_size + tail_size);
- todo_wine
ok( user_ptr[1] == (void *)0xdeadbeef, "unexpected user value\n" );
- if (user_ptr[1] == (void *)0xdeadbeef)
- {
- user_ptr[0] = (void *)0xdeadbeef;
- user_ptr[1] = (void *)0xdeadbee0;
- }
+ user_ptr[0] = (void *)0xdeadbeef;
+ user_ptr[1] = (void *)0xdeadbee0;
tmp_ptr = NULL;
tmp_flags = 0;
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 6d9f949b6a9..64d4f6644af 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -105,10 +105,11 @@ C_ASSERT( sizeof(struct entry) == 2 * ALIGNMENT );
typedef struct
{
+ SIZE_T __pad[sizeof(SIZE_T) / sizeof(DWORD)];
struct list entry; /* entry in heap large blocks list */
SIZE_T data_size; /* size of user data */
SIZE_T block_size; /* total size of virtual memory block */
- DWORD pad[2]; /* padding to ensure 16-byte alignment of data */
+ void *user_value;
DWORD size; /* fields for compatibility with normal arenas */
DWORD magic; /* these must remain at the end of the structure */
} ARENA_LARGE;
@@ -362,6 +363,12 @@ static inline void mark_block_tail( struct block *block, DWORD flags )
memset( tail, ARENA_TAIL_FILLER, ALIGNMENT );
}
valgrind_make_noaccess( tail, ALIGNMENT );
+ if (flags & HEAP_ADD_USER_INFO)
+ {
+ if (flags & HEAP_TAIL_CHECKING_ENABLED || RUNNING_ON_VALGRIND) tail += ALIGNMENT;
+ valgrind_make_writable( tail + sizeof(void *), sizeof(void *) );
+ memset( tail + sizeof(void *), 0, sizeof(void *) );
+ }
}
/* initialize contents of a newly created block of memory */
@@ -2001,10 +2008,31 @@ BOOLEAN WINAPI RtlGetUserInfoHeap( HANDLE heap, ULONG flags, void *ptr, void **u
/***********************************************************************
* RtlSetUserValueHeap (NTDLL.@)
*/
-BOOLEAN WINAPI RtlSetUserValueHeap( HANDLE heap, ULONG flags, void *ptr, void *user_value )
+BOOLEAN WINAPI RtlSetUserValueHeap( HANDLE handle, ULONG flags, void *ptr, void *user_value )
{
- FIXME( "heap %p, flags %#x, ptr %p, user_value %p stub!\n", heap, flags, ptr, user_value );
- return FALSE;
+ ARENA_LARGE *large = (ARENA_LARGE *)ptr - 1;
+ struct block *block;
+ BOOLEAN ret = TRUE;
+ SUBHEAP *subheap;
+ HEAP *heap;
+ char *tmp;
+
+ TRACE( "handle %p, flags %#x, ptr %p, user_value %p.\n", handle, flags, ptr, user_value );
+
+ if (!(heap = HEAP_GetPtr( handle ))) return TRUE;
+
+ heap_lock( heap, flags );
+ if (!(block = unsafe_block_from_ptr( heap, ptr, &subheap ))) ret = FALSE;
+ else if (!subheap) large->user_value = user_value;
+ else
+ {
+ tmp = (char *)block + block_get_size( block ) - block->tail_size + sizeof(void *);
+ if ((heap_get_flags( heap, flags ) & HEAP_TAIL_CHECKING_ENABLED) || RUNNING_ON_VALGRIND) tmp += ALIGNMENT;
+ *(void **)tmp = user_value;
+ }
+ heap_unlock( heap, flags );
+
+ return ret;
}
/***********************************************************************
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
[PATCH 4/5] kernelbase: Cleanup and simplify LocalReAlloc.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/kernel32/heap.c | 2 +
dlls/kernel32/tests/heap.c | 11 ----
dlls/kernelbase/memory.c | 111 ++++++++++++++-----------------------
3 files changed, 45 insertions(+), 79 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c
index df094c94257..6a1a02c814b 100644
--- a/dlls/kernel32/heap.c
+++ b/dlls/kernel32/heap.c
@@ -315,6 +315,8 @@ HGLOBAL WINAPI GlobalHandle( const void *ptr )
*/
HGLOBAL WINAPI GlobalReAlloc( HGLOBAL handle, SIZE_T size, UINT flags )
{
+ struct mem_entry *mem;
+ if ((mem = unsafe_mem_from_HLOCAL( handle )) && mem->lock) return 0;
return LocalReAlloc( handle, size, flags );
}
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index 97f4d9c9fe3..c237d515648 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -1635,9 +1635,7 @@ static void test_GlobalAlloc(void)
mem = GlobalAlloc( GMEM_FIXED, 10 );
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = GlobalReAlloc( mem, 9, GMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = GlobalSize( mem );
ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1651,9 +1649,7 @@ static void test_GlobalAlloc(void)
"got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = GlobalReAlloc( mem, 1024 * 1024, GMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = GlobalSize( mem );
ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1988,9 +1984,7 @@ static void test_LocalAlloc(void)
mem = LocalAlloc( LMEM_FIXED, 10 );
ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = LocalReAlloc( mem, 9, LMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = LocalSize( mem );
ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2004,9 +1998,7 @@ static void test_LocalAlloc(void)
"got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = LocalReAlloc( mem, 1024 * 1024, LMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = LocalSize( mem );
ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2105,13 +2097,10 @@ static void test_LocalAlloc(void)
tmp_mem = LocalHandle( ptr );
ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" );
tmp_mem = LocalDiscard( mem );
- todo_wine
ok( !!tmp_mem, "LocalDiscard failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "LocalDiscard returned unexpected handle\n" );
ret = LocalUnlock( mem );
ok( !ret, "LocalUnlock succeeded, error %lu\n", GetLastError() );
- todo_wine
ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
tmp_mem = LocalDiscard( mem );
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index 776f0aafa18..341b859b555 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -868,6 +868,7 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
if (!size) mem->flags |= MEM_FLAG_DISCARDED;
else
{
+ if (size + HLOCAL_STORAGE < size) goto failed;
if (!(ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE ))) goto failed;
*(HLOCAL *)ptr = handle;
mem->ptr = (char *)ptr + HLOCAL_STORAGE;
@@ -967,7 +968,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
*/
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
{
- DWORD heap_flags = HEAP_ADD_USER_INFO;
+ DWORD heap_flags = HEAP_ADD_USER_INFO | HEAP_NO_SERIALIZE;
+ HANDLE heap = GetProcessHeap();
struct mem_entry *mem;
HLOCAL ret = 0;
void *ptr;
@@ -976,90 +978,63 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f
if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
- RtlLockHeap( GetProcessHeap() );
- if (flags & LMEM_MODIFY) /* modify flags */
+ RtlLockHeap( heap );
+ if ((ptr = unsafe_ptr_from_HLOCAL( handle )))
{
- if (unsafe_ptr_from_HLOCAL( handle ) && (flags & LMEM_MOVEABLE))
+ if (!(flags & LMEM_MOVEABLE))
{
- /* make a fixed block moveable
- * actually only NT is able to do this. But it's soo simple
- */
- if (handle == 0)
- {
- WARN_(globalmem)( "null handle\n" );
- SetLastError( ERROR_NOACCESS );
- }
- else
- {
- size = RtlSizeHeap( GetProcessHeap(), 0, handle );
- ret = LocalAlloc( flags, size );
- ptr = LocalLock( ret );
- memcpy( ptr, handle, size );
- LocalUnlock( ret );
- LocalFree( handle );
- }
+ heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
+ if (!(flags & LMEM_MODIFY) || !(flags & LMEM_MOVEABLE)) ret = handle;
+ else ret = HeapReAlloc( heap, heap_flags, ptr, size );
}
- else if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & LMEM_DISCARDABLE))
+ else if (flags & LMEM_MODIFY)
{
- /* change the flags to make our block "discardable" */
- mem->flags |= LMEM_DISCARDABLE >> 8;
- ret = handle;
+ size = RtlSizeHeap( heap, 0, handle );
+ ret = LocalAlloc( flags, size );
+ ptr = LocalLock( ret );
+ memcpy( ptr, handle, size );
+ LocalUnlock( ret );
+ LocalFree( handle );
}
- else SetLastError( ERROR_INVALID_PARAMETER );
+ else ret = HeapReAlloc( heap, heap_flags, handle, size );
}
- else
+ else if ((mem = unsafe_mem_from_HLOCAL( handle )))
{
- if ((ptr = unsafe_ptr_from_HLOCAL( handle )))
+ if (!(flags & LMEM_MODIFY))
{
- /* reallocate fixed memory */
- if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
- ret = HeapReAlloc( GetProcessHeap(), heap_flags, ptr, size );
- }
- else if ((mem = unsafe_mem_from_HLOCAL( handle )))
- {
- /* reallocate a moveable block */
- if (size != 0)
+ if (size)
{
- if (size <= INT_MAX - HLOCAL_STORAGE)
+ if (size + HLOCAL_STORAGE < size) ptr = NULL;
+ else if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE );
+ else ptr = HeapReAlloc( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE, size + HLOCAL_STORAGE );
+
+ if (!ptr) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ else
{
- if (mem->ptr)
- {
- if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)mem->ptr - HLOCAL_STORAGE,
- size + HLOCAL_STORAGE )))
- {
- mem->ptr = (char *)ptr + HLOCAL_STORAGE;
- ret = handle;
- }
- }
- else
- {
- if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
- {
- *(HLOCAL *)ptr = handle;
- mem->ptr = (char *)ptr + HLOCAL_STORAGE;
- ret = handle;
- }
- }
+ mem->flags &= ~MEM_FLAG_DISCARDED;
+ mem->ptr = (char *)ptr + HLOCAL_STORAGE;
+ ret = handle;
}
- else SetLastError( ERROR_OUTOFMEMORY );
}
else
{
- if (mem->lock == 0)
- {
- if (mem->ptr)
- {
- HeapFree( GetProcessHeap(), 0, (char *)mem->ptr - HLOCAL_STORAGE );
- mem->ptr = NULL;
- }
- ret = handle;
- }
- else WARN_(globalmem)( "not freeing memory associated with locked handle\n" );
+ if (mem->ptr) HeapFree( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE );
+ mem->flags |= MEM_FLAG_DISCARDED;
+ mem->lock = 0;
+ mem->ptr = NULL;
+ ret = handle;
}
}
- else SetLastError( ERROR_INVALID_HANDLE );
+ else if (flags & LMEM_DISCARDABLE)
+ {
+ mem->flags |= MEM_FLAG_DISCARDABLE;
+ ret = handle;
+ }
+ else SetLastError( ERROR_INVALID_PARAMETER );
}
- RtlUnlockHeap( GetProcessHeap() );
+ else SetLastError( ERROR_INVALID_HANDLE );
+ RtlUnlockHeap( heap );
+
return ret;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
[PATCH 3/5] kernelbase: Use HEAP_ADD_USER_INFO for HLOCAL allocations.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/kernelbase/memory.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index 736d3642995..776f0aafa18 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -713,6 +713,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
* Global/local heap functions
***********************************************************************/
+/* some undocumented flags (names are made up) */
+#define HEAP_ADD_USER_INFO 0x00000100
+
/* not compatible with windows */
struct kernelbase_global_data
{
@@ -826,15 +829,15 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL handle )
*/
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
{
+ DWORD heap_flags = HEAP_ADD_USER_INFO;
HANDLE heap = GetProcessHeap();
struct mem_entry *mem;
- DWORD heap_flags = 0;
HLOCAL handle;
void *ptr;
TRACE_(globalmem)( "flags %#x, size %#Ix\n", flags, size );
- if (flags & LMEM_ZEROINIT) heap_flags = HEAP_ZERO_MEMORY;
+ if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
if (!(flags & LMEM_MOVEABLE)) /* pointer */
{
@@ -964,13 +967,15 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
*/
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
{
+ DWORD heap_flags = HEAP_ADD_USER_INFO;
struct mem_entry *mem;
HLOCAL ret = 0;
- DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
void *ptr;
TRACE_(globalmem)( "handle %p, size %#Ix, flags %#x\n", handle, size, flags );
+ if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
+
RtlLockHeap( GetProcessHeap() );
if (flags & LMEM_MODIFY) /* modify flags */
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
[PATCH 2/5] ntdll: Add block padding when HEAP_ADD_USER_INFO flag is set.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/kernel32/tests/heap.c | 3 +--
dlls/ntdll/heap.c | 5 +++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index 91f582f36de..97f4d9c9fe3 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -2277,14 +2277,13 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags
expect_size = max( alloc_size, 2 * sizeof(void *) );
expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size + 2 * sizeof(void *) );
diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) );
- todo_wine
ok( diff == expect_size, "got diff %#Ix\n", diff );
ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
- todo_wine
+ todo_wine_if( global_flags & FLG_HEAP_ENABLE_FREE_CHECK )
ok( !memcmp( ptr0 + alloc_size + tail_size, padd_buf, 2 * sizeof(void *) ), "unexpected padding\n" );
tmp_ptr = (void *)0xdeadbeef;
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 0ecff6f6cba..6d9f949b6a9 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -212,6 +212,7 @@ C_ASSERT( offsetof(HEAP, subheap) <= COMMIT_MASK );
/* some undocumented flags (names are made up) */
#define HEAP_PRIVATE 0x00001000
+#define HEAP_ADD_USER_INFO 0x00000100
#define HEAP_PAGE_ALLOCS 0x01000000
#define HEAP_VALIDATE 0x10000000
#define HEAP_VALIDATE_ALL 0x20000000
@@ -451,7 +452,7 @@ static RTL_CRITICAL_SECTION_DEBUG process_heap_cs_debug =
static inline ULONG heap_get_flags( const HEAP *heap, ULONG flags )
{
if (flags & (HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED)) flags |= HEAP_CHECKING_ENABLED;
- flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY | HEAP_CHECKING_ENABLED;
+ flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY | HEAP_CHECKING_ENABLED | HEAP_ADD_USER_INFO;
return heap->flags | flags;
}
@@ -1476,7 +1477,7 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
static SIZE_T heap_get_block_size( HEAP *heap, ULONG flags, SIZE_T size )
{
- static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS;
+ static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS | HEAP_ADD_USER_INFO;
static const ULONG check_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_CHECKING_ENABLED;
SIZE_T overhead;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
[PATCH 1/5] ole32/tests: Update IStream_SetSize with large size test result.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
The high part is ignored, and OOM error is only returned if there's not
enough memory available, not because of GlobalReAlloc specific behavior.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/ole32/tests/hglobalstream.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/ole32/tests/hglobalstream.c b/dlls/ole32/tests/hglobalstream.c
index 237bcca9251..8310800a5c7 100644
--- a/dlls/ole32/tests/hglobalstream.c
+++ b/dlls/ole32/tests/hglobalstream.c
@@ -294,10 +294,9 @@ static void test_streamonhglobal(void)
/* test OOM condition */
ull.u.HighPart = -1;
- ull.u.LowPart = -1;
+ ull.u.LowPart = 0;
hr = IStream_SetSize(pStream, ull);
- ok(hr == E_OUTOFMEMORY || broken(hr == S_OK), /* win9x */
- "IStream_SetSize with large size should have returned E_OUTOFMEMORY instead of 0x%08lx\n", hr);
+ ok(hr == S_OK, "IStream_SetSize with large size should have returned S_OK instead of 0x%08lx\n", hr);
IStream_Release(pStream);
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
[PATCH 0/5] MR201: ntdll: Implement RtlSetUserValueHeap.
by Rémi Bernon
And prepare HLOCAL allocation to use it.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
June 7, 2022
Re: [PATCH v2 0/7] MR195: winhttp: Abort web socket receive operations when the socket handle is closed
by Paul Gofman (@gofman)
v2 changes:
- Make queue cancelling behaviour in `socket_handle_closing() independent of connection type (always as in 'secure');
- Change (fix) the condition for aborting socket operations in socket_handle_closing(). It doesn't currently make any difference as web socket connections are not cached anyway but it looks cleaner and will make more sense if the same code is reused for normal winhttp connections;
- Get rid of NF_OTHER_THREAD test flag introduced in v1 version and some of new NF_MAIN_THREAD flags. It turns out that most of the new tests which were using these flags are flaky, and now also we introduce the difference in Wine in this part by always taking 'secure' cancel style.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/195#note_1653
June 7, 2022
[PATCH v2 7/7] winhttp/tests: Add tests for closing web socket with pending operations.
by Paul Gofman
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/winhttp/tests/notification.c | 190 +++++++++++++++++++++++++++++-
1 file changed, 189 insertions(+), 1 deletion(-)
diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c
index 50874a49a07..55823b42b85 100644
--- a/dlls/winhttp/tests/notification.c
+++ b/dlls/winhttp/tests/notification.c
@@ -727,6 +727,55 @@ static const struct notification websocket_test3[] =
{ winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_MAIN_THREAD },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_SAVE_BUFFER },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
+
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
+};
+
+static struct notification websocket_test4[] =
+{
+ { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
+ { winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
+ { winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
+
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_SAVE_BUFFER },
+ { winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
+
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
+ { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
+};
+
+static const struct notification websocket_test5[] =
+{
+ { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
+ { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
+ { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
+ { winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
+ { winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
+
{ winhttp_websocket_shutdown, WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE, NF_MAIN_THREAD },
{ winhttp_websocket_shutdown, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SAVE_BUFFER | NF_SIGNAL },
{ winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE,
@@ -1065,7 +1114,8 @@ static void test_websocket(BOOL secure)
WaitForSingleObject( info.wait, INFINITE );
end_test( &info, __LINE__ );
- /* Test socket shutdown while receive is pending. */
+
+ /* Test socket handle close while web socket close is pending. */
info.test = websocket_test3;
info.count = ARRAY_SIZE( websocket_test3 );
info.index = 0;
@@ -1112,6 +1162,144 @@ static void test_websocket(BOOL secure)
WaitForSingleObject( info.wait, INFINITE );
ok( buffer[0] == 'R', "unexpected data\n" );
+ setup_test( &info, winhttp_websocket_close, __LINE__ );
+
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ err = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ info.buflen = 0xdeadbeef;
+ WinHttpCloseHandle( socket );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ ok( info.buflen == sizeof(*result), "got %u\n", info.buflen );
+ result = (WINHTTP_WEB_SOCKET_ASYNC_RESULT *)info.buffer;
+ ok( result->Operation == WINHTTP_WEB_SOCKET_CLOSE_OPERATION, "got %u\n", result->Operation );
+ todo_wine ok( !result->AsyncResult.dwResult, "got %Iu\n", result->AsyncResult.dwResult );
+ ok( result->AsyncResult.dwError == ERROR_WINHTTP_OPERATION_CANCELLED, "got %lu\n", result->AsyncResult.dwError );
+
+ setup_test( &info, winhttp_close_handle, __LINE__ );
+ WinHttpCloseHandle( request );
+ WaitForSingleObject( info.wait, INFINITE );
+ end_test( &info, __LINE__ );
+
+ /* Test socket handle close while receive is pending. */
+ info.test = websocket_test4;
+ info.count = ARRAY_SIZE( websocket_test4 );
+ info.index = 0;
+
+ setup_test( &info, winhttp_open_request, __LINE__ );
+ request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, secure ? WINHTTP_FLAG_SECURE : 0);
+ ok( request != NULL, "got %lu\n", err );
+
+ if (secure)
+ {
+ flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+ ret = WinHttpSetOption(request, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+ ok( ret, "failed to set security flags %lu\n", GetLastError() );
+ }
+
+ ret = WinHttpSetOption( request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+
+ setup_test( &info, winhttp_send_request, __LINE__ );
+ ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_receive_response, __LINE__ );
+ ret = WinHttpReceiveResponse( request, NULL );
+ ok( ret, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ size = sizeof(status);
+ ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+ ok( ret, "failed unexpectedly %lu\n", err );
+ ok( status == 101, "got %lu\n", status );
+
+ setup_test( &info, winhttp_websocket_complete_upgrade, __LINE__ );
+ socket = pWinHttpWebSocketCompleteUpgrade( request, (DWORD_PTR)context );
+ ok( socket != NULL, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_websocket_receive, __LINE__ );
+ buffer[0] = 0;
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+ ok( buffer[0] == 'R', "unexpected data\n" );
+
+ setup_test( &info, winhttp_websocket_close, __LINE__ );
+
+ info.buflen = 0xdeadbeef;
+
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+
+ WinHttpCloseHandle( socket );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ ok( info.buflen == sizeof(*result), "got %u\n", info.buflen );
+ result = (WINHTTP_WEB_SOCKET_ASYNC_RESULT *)info.buffer;
+ ok( result->Operation == WINHTTP_WEB_SOCKET_RECEIVE_OPERATION, "got %u\n", result->Operation );
+ ok( !result->AsyncResult.dwResult, "got %Iu\n", result->AsyncResult.dwResult );
+ ok( result->AsyncResult.dwError == ERROR_WINHTTP_OPERATION_CANCELLED, "got %lu\n", result->AsyncResult.dwError );
+
+ setup_test( &info, winhttp_close_handle, __LINE__ );
+ WinHttpCloseHandle( request );
+ WaitForSingleObject( info.wait, INFINITE );
+ end_test( &info, __LINE__ );
+
+ /* Test socket shutdown while receive is pending. */
+ info.test = websocket_test5;
+ info.count = ARRAY_SIZE( websocket_test5 );
+ info.index = 0;
+
+ setup_test( &info, winhttp_open_request, __LINE__ );
+ request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, secure ? WINHTTP_FLAG_SECURE : 0);
+ ok( request != NULL, "got %lu\n", err );
+
+ if (secure)
+ {
+ flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
+ ret = WinHttpSetOption(request, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
+ ok( ret, "failed to set security flags %lu\n", GetLastError() );
+ }
+
+ ret = WinHttpSetOption( request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+
+ setup_test( &info, winhttp_send_request, __LINE__ );
+ ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 );
+ ok( ret, "got %lu\n", GetLastError() );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_receive_response, __LINE__ );
+ ret = WinHttpReceiveResponse( request, NULL );
+ ok( ret, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ size = sizeof(status);
+ ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+ ok( ret, "failed unexpectedly %lu\n", err );
+ ok( status == 101, "got %lu\n", status );
+
+ setup_test( &info, winhttp_websocket_complete_upgrade, __LINE__ );
+ socket = pWinHttpWebSocketCompleteUpgrade( request, (DWORD_PTR)context );
+ ok( socket != NULL, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+
+ setup_test( &info, winhttp_websocket_receive, __LINE__ );
+ buffer[0] = 0;
+ err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
+ ok( err == ERROR_SUCCESS, "got %lu\n", err );
+ WaitForSingleObject( info.wait, INFINITE );
+ ok( buffer[0] == 'R', "unexpected data\n" );
+
err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
ok( err == ERROR_SUCCESS, "got %lu\n", err );
err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/195
June 7, 2022
[PATCH v2 6/7] winhttp: Support abort in task_socket_close().
by Paul Gofman
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/winhttp/request.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 269af0826c0..2754dc29163 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -4145,13 +4145,18 @@ static void task_socket_close( void *ctx, BOOL abort )
struct socket *socket = (struct socket *)s->task_hdr.obj;
DWORD ret;
- if (abort) return;
+ if (abort)
+ {
+ socket_close_complete( socket, ERROR_WINHTTP_OPERATION_CANCELLED );
+ return;
+ }
TRACE("running %p\n", ctx);
ret = socket_close( socket );
receive_io_complete( socket );
- socket_close_complete( socket, ret );
+ if (task_needs_completion( &s->task_hdr ))
+ socket_close_complete( socket, ret );
}
DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reason, DWORD len )
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/195
June 7, 2022