Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
03096546
Commit
03096546
authored
Nov 10, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
May 30, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Support MEM_COALESCE_PLACEHOLDERS in NtFreeVirtualMemory().
parent
d5f23441
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
125 additions
and
3 deletions
+125
-3
virtual.c
dlls/ntdll/tests/virtual.c
+70
-2
virtual.c
dlls/ntdll/unix/virtual.c
+55
-1
No files found.
dlls/ntdll/tests/virtual.c
View file @
03096546
...
@@ -295,9 +295,9 @@ static void test_NtAllocateVirtualMemoryEx(void)
...
@@ -295,9 +295,9 @@ static void test_NtAllocateVirtualMemoryEx(void)
{
{
MEMORY_BASIC_INFORMATION
mbi
;
MEMORY_BASIC_INFORMATION
mbi
;
MEM_EXTENDED_PARAMETER
ext
[
2
];
MEM_EXTENDED_PARAMETER
ext
[
2
];
char
*
p
,
*
p1
,
*
p2
,
*
p3
;
void
*
addresses
[
16
];
void
*
addresses
[
16
];
SIZE_T
size
,
size2
;
SIZE_T
size
,
size2
;
char
*
p
,
*
p1
,
*
p2
;
ULONG
granularity
;
ULONG
granularity
;
NTSTATUS
status
;
NTSTATUS
status
;
ULONG_PTR
count
;
ULONG_PTR
count
;
...
@@ -510,6 +510,7 @@ static void test_NtAllocateVirtualMemoryEx(void)
...
@@ -510,6 +510,7 @@ static void test_NtAllocateVirtualMemoryEx(void)
p1
=
addr1
;
p1
=
addr1
;
p2
=
p1
+
size
/
4
;
p2
=
p1
+
size
/
4
;
p3
=
p2
+
size
/
4
;
size2
=
size
/
4
;
size2
=
size
/
4
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
...
@@ -517,12 +518,79 @@ static void test_NtAllocateVirtualMemoryEx(void)
...
@@ -517,12 +518,79 @@ static void test_NtAllocateVirtualMemoryEx(void)
ok
(
size2
==
0x4000
,
"Unexpected size %#Ix.
\n
"
,
size2
);
ok
(
size2
==
0x4000
,
"Unexpected size %#Ix.
\n
"
,
size2
);
ok
(
p1
==
addr1
,
"Unexpected addr %p, expected %p.
\n
"
,
p1
,
addr1
);
ok
(
p1
==
addr1
,
"Unexpected addr %p, expected %p.
\n
"
,
p1
,
addr1
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p2
,
&
size2
,
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
check_region_size
(
p1
,
p2
-
p1
);
check_region_size
(
p2
,
p3
-
p2
);
check_region_size
(
p3
,
size
-
(
p3
-
p1
));
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size
,
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_INVALID_PARAMETER_4
,
"Unexpected status %08lx.
\n
"
,
status
);
size2
=
size
+
0x1000
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
size2
=
size
-
0x1000
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
p1
=
(
char
*
)
addr1
+
0x1000
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
p1
=
addr1
;
size2
=
0
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_INVALID_PARAMETER_3
,
"Unexpected status %08lx.
\n
"
,
status
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size
,
MEM_RELEASE
);
ok
(
status
==
STATUS_UNABLE_TO_FREE_VM
,
"Unexpected status %08lx.
\n
"
,
status
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
size
==
0x10000
,
"Unexpected size %#Ix.
\n
"
,
size
);
ok
(
p1
==
addr1
,
"Unexpected addr %p, expected %p.
\n
"
,
p1
,
addr1
);
check_region_size
(
p1
,
size
);
size2
=
size
/
4
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
size2
==
0x4000
,
"Unexpected size %#Ix.
\n
"
,
size2
);
ok
(
p1
==
addr1
,
"Unexpected addr %p, expected %p.
\n
"
,
p1
,
addr1
);
check_region_size
(
p1
,
size
/
4
);
check_region_size
(
p1
,
size
/
4
);
check_region_size
(
p2
,
size
-
size
/
4
);
check_region_size
(
p2
,
size
-
size
/
4
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
);
size2
=
size
-
size
/
4
;
status
=
pNtAllocateVirtualMemoryEx
(
NtCurrentProcess
(),
(
void
**
)
&
p2
,
&
size2
,
MEM_RESERVE
|
MEM_REPLACE_PLACEHOLDER
,
PAGE_READWRITE
,
NULL
,
0
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
size2
=
size
-
size
/
4
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p2
,
&
size2
,
MEM_RELEASE
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p2
,
&
size2
,
MEM_RELEASE
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
size2
==
0xc000
,
"Unexpected size %#Ix.
\n
"
,
size2
);
ok
(
p2
==
p1
+
size
/
4
,
"Unexpected addr %p, expected %p.
\n
"
,
p2
,
p1
+
size
/
4
);
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size
,
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
);
ok
(
status
==
STATUS_CONFLICTING_ADDRESSES
,
"Unexpected status %08lx.
\n
"
,
status
);
size2
=
size
/
4
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p1
,
&
size2
,
MEM_RELEASE
);
ok
(
status
==
STATUS_SUCCESS
,
"Unexpected status %08lx.
\n
"
,
status
);
ok
(
size2
==
0x4000
,
"Unexpected size %#Ix.
\n
"
,
size2
);
ok
(
p1
==
addr1
,
"Unexpected addr %p, expected %p.
\n
"
,
p1
,
addr1
);
size2
=
0
;
status
=
NtFreeVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
p3
,
&
size2
,
MEM_RELEASE
);
ok
(
status
==
STATUS_MEMORY_NOT_ALLOCATED
,
"Unexpected status %08lx.
\n
"
,
status
);
/* Split in two regions, specifying second half. */
/* Split in two regions, specifying second half. */
addr1
=
NULL
;
addr1
=
NULL
;
...
...
dlls/ntdll/unix/virtual.c
View file @
03096546
...
@@ -2295,6 +2295,53 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size )
...
@@ -2295,6 +2295,53 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size )
/***********************************************************************
/***********************************************************************
* coalesce_placeholders
*
* Coalesce placeholder views.
* virtual_mutex must be held by caller.
*/
static
NTSTATUS
coalesce_placeholders
(
struct
file_view
*
view
,
char
*
base
,
size_t
size
)
{
struct
rb_entry
*
next
;
struct
file_view
*
curr_view
,
*
next_view
;
unsigned
int
i
,
view_count
=
0
;
size_t
views_size
=
0
;
if
(
!
size
)
return
STATUS_INVALID_PARAMETER_3
;
if
(
base
!=
view
->
base
)
return
STATUS_CONFLICTING_ADDRESSES
;
curr_view
=
view
;
while
(
curr_view
->
protect
&
VPROT_FREE_PLACEHOLDER
)
{
++
view_count
;
views_size
+=
curr_view
->
size
;
if
(
views_size
>=
size
)
break
;
if
(
!
(
next
=
rb_next
(
&
curr_view
->
entry
)))
break
;
next_view
=
RB_ENTRY_VALUE
(
next
,
struct
file_view
,
entry
);
if
((
char
*
)
curr_view
->
base
+
curr_view
->
size
!=
next_view
->
base
)
break
;
curr_view
=
next_view
;
}
if
(
view_count
<
2
||
size
!=
views_size
)
return
STATUS_CONFLICTING_ADDRESSES
;
for
(
i
=
1
;
i
<
view_count
;
++
i
)
{
curr_view
=
RB_ENTRY_VALUE
(
rb_next
(
&
view
->
entry
),
struct
file_view
,
entry
);
unregister_view
(
curr_view
);
free_view
(
curr_view
);
}
unregister_view
(
view
);
view
->
size
=
views_size
;
register_view
(
view
);
VIRTUAL_DEBUG_DUMP_VIEW
(
view
);
return
STATUS_SUCCESS
;
}
/***********************************************************************
* allocate_dos_memory
* allocate_dos_memory
*
*
* Allocate the DOS memory range.
* Allocate the DOS memory range.
...
@@ -4445,7 +4492,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
...
@@ -4445,7 +4492,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
else
if
(
!
(
view
=
find_view
(
base
,
0
)))
status
=
STATUS_MEMORY_NOT_ALLOCATED
;
else
if
(
!
(
view
=
find_view
(
base
,
0
)))
status
=
STATUS_MEMORY_NOT_ALLOCATED
;
else
if
(
!
is_view_valloc
(
view
))
status
=
STATUS_INVALID_PARAMETER
;
else
if
(
!
is_view_valloc
(
view
))
status
=
STATUS_INVALID_PARAMETER
;
else
if
(
!
size
&&
base
!=
view
->
base
)
status
=
STATUS_FREE_VM_NOT_AT_BASE
;
else
if
(
!
size
&&
base
!=
view
->
base
)
status
=
STATUS_FREE_VM_NOT_AT_BASE
;
else
if
((
char
*
)
view
->
base
+
view
->
size
-
base
<
size
)
status
=
STATUS_UNABLE_TO_FREE_VM
;
else
if
((
char
*
)
view
->
base
+
view
->
size
-
base
<
size
&&
!
(
type
&
MEM_COALESCE_PLACEHOLDERS
))
status
=
STATUS_UNABLE_TO_FREE_VM
;
else
switch
(
type
)
else
switch
(
type
)
{
{
case
MEM_DECOMMIT
:
case
MEM_DECOMMIT
:
...
@@ -4458,6 +4506,12 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
...
@@ -4458,6 +4506,12 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
case
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
:
case
MEM_RELEASE
|
MEM_PRESERVE_PLACEHOLDER
:
status
=
free_pages_preserve_placeholder
(
view
,
base
,
size
);
status
=
free_pages_preserve_placeholder
(
view
,
base
,
size
);
break
;
break
;
case
MEM_RELEASE
|
MEM_COALESCE_PLACEHOLDERS
:
status
=
coalesce_placeholders
(
view
,
base
,
size
);
break
;
case
MEM_COALESCE_PLACEHOLDERS
:
status
=
STATUS_INVALID_PARAMETER_4
;
break
;
default:
default:
status
=
STATUS_INVALID_PARAMETER
;
status
=
STATUS_INVALID_PARAMETER
;
break
;
break
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment