Skip to content

Commit

Permalink
10.0-rc1-1 patchset
Browse files Browse the repository at this point in the history
remove rawinput stuff until it's finished, haven't had time to work on it

build with LLVM polly (placebo)

more changes to hopefully improve stability performance, including build fixes for clang

testing keyboard input regression revert Revert-win32u-Simplify-the-logic-for-driver-messages.patch

some other things...
  • Loading branch information
whrvt committed Dec 9, 2024
1 parent 0112a35 commit 0773320
Show file tree
Hide file tree
Showing 116 changed files with 3,181 additions and 6,268 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
From 9b4099ed8b9ac0670396bdc50dbfa6f5bb435784 Mon Sep 17 00:00:00 2001
From: Evan Tang <[email protected]>
Date: Mon, 30 Oct 2023 11:40:41 -0500
Subject: [PATCH] ntdll: Don't allocate vprot entries until commit.

Reservations only consume address space, which can be much larger than
the amount of ram in the system, so allocating even one byte per page
can result in huge amounts of ram used.
---
dlls/ntdll/unix/virtual.c | 87 ++++++++++++++++++++++++++++++++-------
1 file changed, 73 insertions(+), 14 deletions(-)

diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index b2e1be9f53f..2e2d5ce2345 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -908,8 +908,7 @@ static BYTE get_page_vprot( const void *addr )
* Return the size of the region with equal masked vprot byte.
* Also return the protections for the first page.
* The function assumes that base and size are page aligned,
- * base + size does not wrap around and the range is within view so
- * vprot bytes are allocated for the range. */
+ * base + size does not wrap around, and the range is within view. */
static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vprot )
{
static const UINT_PTR word_from_byte = (UINT_PTR)0x101010101010101;
@@ -927,11 +926,24 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp
if (aligned_start_idx > end_idx) aligned_start_idx = end_idx;

#ifdef _WIN64
- vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift] + (curr_idx & pages_vprot_mask);
+ if (pages_vprot[curr_idx >> pages_vprot_shift])
+ {
+ vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift] + (curr_idx & pages_vprot_mask);
+ *vprot = *vprot_ptr;
+ }
+ else
+ {
+ *vprot = 0;
+ curr_idx = (curr_idx + pages_vprot_mask + 1) & ~pages_vprot_mask;
+ if (curr_idx > end_idx)
+ return size;
+ vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift];
+ assert(curr_idx >= aligned_start_idx);
+ }
#else
vprot_ptr = pages_vprot + curr_idx;
-#endif
*vprot = *vprot_ptr;
+#endif

/* Page count page table is at least the multiples of sizeof(UINT_PTR)
* so we don't have to worry about crossing the boundary on unaligned idx values. */
@@ -944,7 +956,17 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp
for (; curr_idx < end_idx; curr_idx += sizeof(UINT_PTR), vprot_ptr += sizeof(UINT_PTR))
{
#ifdef _WIN64
- if (!(curr_idx & pages_vprot_mask)) vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift];
+ if (!(curr_idx & pages_vprot_mask))
+ {
+ while (!(vprot_ptr = pages_vprot[curr_idx >> pages_vprot_shift]))
+ {
+ if (!(vprot_word & mask_word))
+ return (curr_idx - start_idx) << page_shift;
+ curr_idx += pages_vprot_mask + 1;
+ if (curr_idx >= end_idx)
+ return size;
+ }
+ }
#endif
if ((vprot_word ^ *(UINT_PTR *)vprot_ptr) & mask_word)
{
@@ -956,6 +978,21 @@ static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vp
return size;
}

+#ifdef _WIN64
+/***********************************************************************
+ * set_page_vprot_internal
+ *
+ * Helper function for set_page_vprot
+ */
+static void set_pages_vprot_internal( size_t idx, BYTE vprot, size_t len )
+{
+ if (pages_vprot[idx >> pages_vprot_shift])
+ memset(pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, len);
+ else if (vprot)
+ ERR("vprot table missing entry at %x!\n", (unsigned int)(idx >> pages_vprot_shift));
+}
+#endif
+
/***********************************************************************
* set_page_vprot
*
@@ -970,10 +1007,10 @@ static void set_page_vprot( const void *addr, size_t size, BYTE vprot )
while (idx >> pages_vprot_shift != end >> pages_vprot_shift)
{
size_t dir_size = pages_vprot_mask + 1 - (idx & pages_vprot_mask);
- memset( pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, dir_size );
+ set_pages_vprot_internal(idx, vprot, dir_size);
idx += dir_size;
}
- memset( pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask), vprot, end - idx );
+ set_pages_vprot_internal(idx, vprot, end - idx);
#else
memset( pages_vprot + idx, vprot, end - idx );
#endif
@@ -991,10 +1028,22 @@ static void set_page_vprot_bits( const void *addr, size_t size, BYTE set, BYTE c
size_t end = ((size_t)addr + size + page_mask) >> page_shift;

#ifdef _WIN64
- for ( ; idx < end; idx++)
+ while (idx < end)
{
- BYTE *ptr = pages_vprot[idx >> pages_vprot_shift] + (idx & pages_vprot_mask);
- *ptr = (*ptr & ~clear) | set;
+ size_t next = (idx + pages_vprot_mask + 1) & ~pages_vprot_mask;
+ BYTE *ptr = pages_vprot[idx >> pages_vprot_shift];
+ if (ptr)
+ {
+ size_t i = idx & pages_vprot_mask;
+ size_t table_end = min(next, end) - (idx & ~pages_vprot_mask);
+ for (; i < table_end; i++)
+ ptr[i] = (ptr[i] & ~clear) | set;
+ }
+ else if (set)
+ {
+ ERR("vprot table missing entry at %x!\n", (unsigned)(idx >> pages_vprot_shift));
+ }
+ idx = next;
}
#else
for ( ; idx < end; idx++) pages_vprot[idx] = (pages_vprot[idx] & ~clear) | set;
@@ -1482,6 +1531,10 @@ static void register_view( struct file_view *view )
static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t size, unsigned int vprot )
{
struct file_view *view;
+ /* If uncommitted, delay allocation until commit so we don't make vprot tables for reservations,
+ * which can be as large as the address space allows (128TB).
+ * WRITEWATCH doesn't yet support allocating on commit, so make an exception for that. */
+ BOOL write_vprot = !!(vprot & (VPROT_COMMITTED | VPROT_WRITEWATCH));
int unix_prot = get_unix_prot( vprot );

assert( !((UINT_PTR)base & page_mask) );
@@ -1499,7 +1552,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
delete_view( view );
}

- if (!alloc_pages_vprot( base, size )) return STATUS_NO_MEMORY;
+ if (write_vprot && !alloc_pages_vprot( base, size )) return STATUS_NO_MEMORY;

/* Create the view structure */

@@ -1512,7 +1565,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
view->base = base;
view->size = size;
view->protect = vprot;
- set_page_vprot( base, size, vprot );
+ set_page_vprot( base, size, write_vprot ? vprot : 0 );

register_view( view );

@@ -1649,6 +1702,8 @@ static BOOL set_vprot( struct file_view *view, void *base, size_t size, BYTE vpr
}
if (enable_write_exceptions && is_vprot_exec_write( vprot )) vprot |= VPROT_WRITEWATCH;
if (mprotect_exec( base, size, get_unix_prot(vprot) )) return FALSE;
+ /* Reserved pages may not have table entries yet, make those now */
+ if (vprot && !alloc_pages_vprot( base, size )) return FALSE;
set_page_vprot( base, size, vprot );
return TRUE;
}
@@ -2176,6 +2231,7 @@ done:
static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max_size, BYTE *vprot, BYTE vprot_mask )
{
SIZE_T offset, size;
+ BYTE extra = 0;

base = ROUND_ADDR( base, page_mask );
offset = (char *)base - (char *)view->base;
@@ -2196,7 +2252,8 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max
if (reply->committed)
{
*vprot |= VPROT_COMMITTED;
- set_page_vprot_bits( base, size, VPROT_COMMITTED, 0 );
+ extra = VPROT_COMMITTED;
+ vprot_mask &= ~VPROT_COMMITTED;
}
}
}
@@ -2206,7 +2263,9 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, size_t max
}
else size = min( view->size - offset, max_size );

- return get_vprot_range_size( base, size, vprot_mask, vprot );
+ size = get_vprot_range_size( base, size, vprot_mask, vprot );
+ *vprot |= extra;
+ return size;
}


--
GitLab

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
From e9d146653d292d5c05675a1c9d7f53473af3a95c Mon Sep 17 00:00:00 2001
From: Evan Tang <[email protected]>
Date: Mon, 30 Oct 2023 14:34:03 -0500
Subject: [PATCH] ntdll/tests: Add test for reserving massive amounts of
memory.

---
dlls/ntdll/tests/virtual.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index a9dec1b5a8a..808b67b9b27 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -2676,6 +2676,31 @@ static void test_query_image_information(void)
NtClose( file );
}

+static void test_massive_memory_reservation(void)
+{
+ /* Test to make sure large address space reservations don't use more ram than the system has.
+ * Most failures here will be the test getting killed by the OOM killer. */
+ int i;
+ for (i = 12; i < sizeof(void*) * 8; i++)
+ {
+ void* ptr;
+ BOOL is_ok;
+ SetLastError(0xdeadbeef);
+ ptr = VirtualAlloc(NULL, 1ull << i, MEM_RESERVE, PAGE_NOACCESS);
+ if (i < 40 && sizeof(void*) == 8) /* These should succeed */
+ is_ok = GetLastError() == 0xdeadbeef;
+ else if (i < 47) /* These might run out of address space */
+ is_ok = GetLastError() == 0xdeadbeef || GetLastError() == ERROR_NOT_ENOUGH_MEMORY;
+ else
+ is_ok = GetLastError() == ERROR_INVALID_PARAMETER;
+ ok(is_ok, "Unexpected error allocating 1 << %d: %lx.\n", i, GetLastError());
+ if (ptr)
+ VirtualFree(ptr, 1ull << i, MEM_RELEASE);
+ ptr = malloc(1ull << i);
+ free(ptr);
+ }
+}
+
START_TEST(virtual)
{
HMODULE mod;
@@ -2726,4 +2751,5 @@ START_TEST(virtual)
test_query_region_information();
test_query_image_information();
test_exec_memory_writes();
+ test_massive_memory_reservation();
}
--
GitLab

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
From b7333394d1a0dc94a02f7fd722914dce343f10c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= <[email protected]>
Date: Mon, 4 Dec 2023 02:38:19 +0200
Subject: [PATCH] kernelbase: Add test case for LoadLibraryEx() when hFile is
non-NULL

When hFile is non-NULL then LoadLibraryEx() should return NULL
with LastError set as ERROR_INVALID_PARAMETER
---
dlls/kernelbase/tests/file.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/dlls/kernelbase/tests/file.c b/dlls/kernelbase/tests/file.c
index 18dff0a32ab..b19360c8998 100644
--- a/dlls/kernelbase/tests/file.c
+++ b/dlls/kernelbase/tests/file.c
@@ -46,6 +46,23 @@ static void test_ioring_caps(void)
todo_wine ok(hr == S_OK, "got %#lx.\n", hr);
}

+static void test_load_library_ex_flags(void)
+{
+ HMODULE hmod;
+ DWORD last_error;
+
+ SetLastError(0x33);
+
+ /* Test if LoadLibraryEx can load a dll */
+ hmod = LoadLibraryExW(L"kernelbase.dll", NULL /* hFile */, LOAD_LIBRARY_SEARCH_SYSTEM32 /* dwFlags */);
+ ok(hmod != NULL, "LoadLibraryEx returned %p with LastError: %#lx.\n", hmod, GetLastError());
+
+ /* When hFile is non-NULL LoadLibraryEx should return NULL and set LastError to ERROR_INVALID_PARAMETER */
+ hmod = LoadLibraryExW(L"kernelbase.dll", (HANDLE)0x000003A0 /* random hFile */, 0 /* dwFlags */);
+ last_error = GetLastError();
+ ok(hmod == NULL && last_error == ERROR_INVALID_PARAMETER, "LoadLibraryEx returned %p with LastError: %#lx.\n", hmod, last_error);
+}
+
START_TEST(file)
{
HMODULE hmod;
@@ -54,4 +71,5 @@ START_TEST(file)
pQueryIoRingCapabilities = (void *)GetProcAddress(hmod, "QueryIoRingCapabilities");

test_ioring_caps();
+ test_load_library_ex_flags();
}
--
GitLab

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
From db34272389cc9d7b4ef7bdfc6708bc477ab37ff7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= <[email protected]>
Date: Fri, 1 Dec 2023 04:32:32 +0200
Subject: [PATCH] kernelbase: LoadLibraryEx enforce valid flag combinations

---
dlls/kernelbase/loader.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c
index 59b91596f13..8f40286b880 100644
--- a/dlls/kernelbase/loader.c
+++ b/dlls/kernelbase/loader.c
@@ -530,12 +530,19 @@ HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWOR
{
UNICODE_STRING str;
HMODULE module;
+ BOOL invalid_parameter;

- if (!name)
+ invalid_parameter = !name ||
+ file ||
+ ((flags & LOAD_LIBRARY_AS_DATAFILE) && (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) ||
+ ((flags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) && (flags & LOAD_WITH_ALTERED_SEARCH_PATH));
+
+ if (invalid_parameter)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
+
RtlInitUnicodeString( &str, name );
if (str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags );

--
GitLab

Loading

0 comments on commit 0773320

Please sign in to comment.