Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
3de37fef
Commit
3de37fef
authored
Apr 30, 2013
by
Dmitry Timoshkov
Committed by
Alexandre Julliard
Apr 30, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Add some tests for PEB and loader locks.
parent
10476af6
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
161 additions
and
9 deletions
+161
-9
loader.c
dlls/kernel32/tests/loader.c
+161
-9
No files found.
dlls/kernel32/tests/loader.c
View file @
3de37fef
...
...
@@ -53,6 +53,10 @@ static void (WINAPI *pLdrShutdownProcess)(void);
static
BOOLEAN
(
WINAPI
*
pRtlDllShutdownInProgress
)(
void
);
static
NTSTATUS
(
WINAPI
*
pNtAllocateVirtualMemory
)(
HANDLE
,
PVOID
*
,
ULONG
,
SIZE_T
*
,
ULONG
,
ULONG
);
static
NTSTATUS
(
WINAPI
*
pNtFreeVirtualMemory
)(
HANDLE
,
PVOID
*
,
SIZE_T
*
,
ULONG
);
static
NTSTATUS
(
WINAPI
*
pLdrLockLoaderLock
)(
ULONG
,
ULONG
*
,
ULONG
*
);
static
NTSTATUS
(
WINAPI
*
pLdrUnlockLoaderLock
)(
ULONG
,
ULONG
);
static
void
(
WINAPI
*
pRtlAcquirePebLock
)(
void
);
static
void
(
WINAPI
*
pRtlReleasePebLock
)(
void
);
static
PVOID
RVAToAddr
(
DWORD_PTR
rva
,
HMODULE
module
)
{
...
...
@@ -1054,12 +1058,14 @@ nt4_is_broken:
}
#define MAX_COUNT 10
static
HANDLE
attached_thread
[
MAX_COUNT
]
,
stop_event
,
event
,
mutex
,
semaphore
;
static
HANDLE
attached_thread
[
MAX_COUNT
];
static
DWORD
attached_thread_count
;
static
int
test_dll_phase
;
HANDLE
stop_event
,
event
,
mutex
,
semaphore
,
loader_lock_event
,
peb_lock_event
,
ack_event
;
static
int
test_dll_phase
,
inside_loader_lock
,
inside_peb_lock
;
static
DWORD
WINAPI
mutex_thread_proc
(
void
*
param
)
{
HANDLE
wait_list
[
3
];
DWORD
ret
;
ret
=
WaitForSingleObject
(
mutex
,
0
);
...
...
@@ -1067,10 +1073,31 @@ static DWORD WINAPI mutex_thread_proc(void *param)
SetEvent
(
param
);
wait_list
[
0
]
=
stop_event
;
wait_list
[
1
]
=
loader_lock_event
;
wait_list
[
2
]
=
peb_lock_event
;
while
(
1
)
{
trace
(
"%04u: mutex_thread_proc: still alive
\n
"
,
GetCurrentThreadId
());
if
(
WaitForSingleObject
(
stop_event
,
50
)
!=
WAIT_TIMEOUT
)
break
;
ret
=
WaitForMultipleObjects
(
3
,
wait_list
,
FALSE
,
50
);
if
(
ret
==
WAIT_OBJECT_0
)
break
;
else
if
(
ret
==
WAIT_OBJECT_0
+
1
)
{
ULONG
loader_lock_magic
;
trace
(
"%04u: mutex_thread_proc: Entering loader lock
\n
"
,
GetCurrentThreadId
());
ret
=
pLdrLockLoaderLock
(
0
,
NULL
,
&
loader_lock_magic
);
ok
(
!
ret
,
"LdrLockLoaderLock error %#x
\n
"
,
ret
);
inside_loader_lock
++
;
SetEvent
(
ack_event
);
}
else
if
(
ret
==
WAIT_OBJECT_0
+
2
)
{
trace
(
"%04u: mutex_thread_proc: Entering PEB lock
\n
"
,
GetCurrentThreadId
());
pRtlAcquirePebLock
();
inside_peb_lock
++
;
SetEvent
(
ack_event
);
}
}
trace
(
"%04u: mutex_thread_proc: exiting
\n
"
,
GetCurrentThreadId
());
...
...
@@ -1113,6 +1140,13 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
static
LONG
noop_thread_started
;
DWORD
ret
;
ok
(
!
inside_loader_lock
,
"inside_loader_lock should not be set
\n
"
);
/* FIXME: remove once Wine is fixed */
if
(
inside_peb_lock
&&
reason
==
DLL_PROCESS_DETACH
)
todo_wine
ok
(
!
inside_peb_lock
,
"inside_peb_lock should not be set
\n
"
);
else
ok
(
!
inside_peb_lock
,
"inside_peb_lock should not be set
\n
"
);
switch
(
reason
)
{
case
DLL_PROCESS_ATTACH
:
...
...
@@ -1133,6 +1167,13 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
trace
(
"dll: %p, DLL_PROCESS_DETACH, %p
\n
"
,
hinst
,
param
);
if
(
test_dll_phase
==
4
||
test_dll_phase
==
5
)
{
todo_wine
ok
(
0
,
"dll_entry_point(DLL_PROCESS_DETACH) should not be called
\n
"
);
break
;
}
if
(
test_dll_phase
==
0
||
test_dll_phase
==
3
)
ok
(
param
!=
NULL
,
"dll: param %p
\n
"
,
param
);
else
...
...
@@ -1369,6 +1410,18 @@ static void child_process(const char *dll_name, DWORD target_offset)
event
=
CreateEvent
(
NULL
,
TRUE
,
FALSE
,
NULL
);
ok
(
event
!=
0
,
"CreateEvent error %d
\n
"
,
GetLastError
());
SetLastError
(
0xdeadbeef
);
loader_lock_event
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ok
(
loader_lock_event
!=
0
,
"CreateEvent error %d
\n
"
,
GetLastError
());
SetLastError
(
0xdeadbeef
);
peb_lock_event
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ok
(
peb_lock_event
!=
0
,
"CreateEvent error %d
\n
"
,
GetLastError
());
SetLastError
(
0xdeadbeef
);
ack_event
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
ok
(
ack_event
!=
0
,
"CreateEvent error %d
\n
"
,
GetLastError
());
file
=
CreateFile
(
dll_name
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
file
==
INVALID_HANDLE_VALUE
)
{
...
...
@@ -1527,6 +1580,42 @@ todo_wine
CloseHandle
(
stop_event
);
break
;
case
4
:
trace
(
"setting loader_lock_event
\n
"
);
SetEvent
(
loader_lock_event
);
WaitForSingleObject
(
ack_event
,
1000
);
ok
(
inside_loader_lock
!=
0
,
"inside_loader_lock is not set
\n
"
);
/* calling NtTerminateProcess should not cause a deadlock */
trace
(
"call NtTerminateProcess(0, 198)
\n
"
);
ret
=
pNtTerminateProcess
(
0
,
198
);
ok
(
!
ret
,
"NtTerminateProcess error %#x
\n
"
,
ret
);
*
child_failures
=
winetest_get_failures
();
/* Windows fails to release loader lock acquired from another thread,
* so the LdrUnlockLoaderLock call fails here and ExitProcess deadlocks
* later on, so NtTerminateProcess is used instead.
*/
trace
(
"call NtTerminateProcess(GetCurrentProcess(), 198)
\n
"
);
pNtTerminateProcess
(
GetCurrentProcess
(),
198
);
ok
(
0
,
"NtTerminateProcess should not return
\n
"
);
break
;
case
5
:
trace
(
"setting peb_lock_event
\n
"
);
SetEvent
(
peb_lock_event
);
WaitForSingleObject
(
ack_event
,
1000
);
ok
(
inside_peb_lock
!=
0
,
"inside_peb_lock is not set
\n
"
);
*
child_failures
=
winetest_get_failures
();
/* calling ExitProcess should cause a deadlock */
trace
(
"call ExitProcess(198)
\n
"
);
ExitProcess
(
198
);
ok
(
0
,
"ExitProcess should not return
\n
"
);
break
;
default:
assert
(
0
);
break
;
...
...
@@ -1534,6 +1623,7 @@ todo_wine
if
(
test_dll_phase
==
0
)
expected_code
=
195
;
else
if
(
test_dll_phase
==
3
)
expected_code
=
196
;
else
if
(
test_dll_phase
==
4
)
expected_code
=
198
;
else
expected_code
=
STILL_ACTIVE
;
if
(
expected_code
==
STILL_ACTIVE
)
...
...
@@ -1561,7 +1651,7 @@ todo_wine
*
child_failures
=
winetest_get_failures
();
trace
(
"call ExitProcess()
\n
"
);
trace
(
"call ExitProcess(
195
)
\n
"
);
ExitProcess
(
195
);
}
...
...
@@ -1685,8 +1775,9 @@ static void test_ExitProcess(void)
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 0"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
3
0000
);
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
1
0000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
TerminateProcess
(
pi
.
hProcess
,
0
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
ok
(
ret
==
195
,
"expected exit code 195, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
...
...
@@ -1702,8 +1793,9 @@ static void test_ExitProcess(void)
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 1"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
3
0000
);
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
1
0000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
TerminateProcess
(
pi
.
hProcess
,
0
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
ok
(
ret
==
195
,
"expected exit code 195, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
...
...
@@ -1719,8 +1811,9 @@ static void test_ExitProcess(void)
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 2"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
3
0000
);
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
1
0000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
TerminateProcess
(
pi
.
hProcess
,
0
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
ok
(
ret
==
197
,
"expected exit code 197, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
...
...
@@ -1736,8 +1829,9 @@ static void test_ExitProcess(void)
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 3"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
3
0000
);
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
1
0000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
TerminateProcess
(
pi
.
hProcess
,
0
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
ok
(
ret
==
195
,
"expected exit code 195, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
...
...
@@ -1748,6 +1842,60 @@ static void test_ExitProcess(void)
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hProcess
);
/* phase 4 */
if
(
pLdrLockLoaderLock
&&
pLdrUnlockLoaderLock
)
{
*
child_failures
=
-
1
;
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 4"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
10000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
TerminateProcess
(
pi
.
hProcess
,
0
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
ok
(
ret
==
198
,
"expected exit code 198, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
{
trace
(
"%d failures in child process
\n
"
,
*
child_failures
);
winetest_add_failures
(
*
child_failures
);
}
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hProcess
);
}
else
win_skip
(
"LdrLockLoaderLock/LdrUnlockLoaderLock are not available on this platform
\n
"
);
/* phase 5 */
if
(
pRtlAcquirePebLock
&&
pRtlReleasePebLock
)
{
*
child_failures
=
-
1
;
sprintf
(
cmdline
,
"
\"
%s
\"
loader %s %u 5"
,
argv
[
0
],
dll_name
,
target_offset
);
ret
=
CreateProcess
(
argv
[
0
],
cmdline
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
);
ok
(
ret
,
"CreateProcess(%s) error %d
\n
"
,
cmdline
,
GetLastError
());
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
5000
);
todo_wine
ok
(
ret
==
WAIT_TIMEOUT
,
"child process should fail to terminate
\n
"
);
if
(
ret
!=
WAIT_OBJECT_0
)
{
trace
(
"terminating child process
\n
"
);
TerminateProcess
(
pi
.
hProcess
,
199
);
}
ret
=
WaitForSingleObject
(
pi
.
hProcess
,
1000
);
ok
(
ret
==
WAIT_OBJECT_0
,
"child process failed to terminate
\n
"
);
GetExitCodeProcess
(
pi
.
hProcess
,
&
ret
);
todo_wine
ok
(
ret
==
199
,
"expected exit code 199, got %u
\n
"
,
ret
);
if
(
*
child_failures
)
{
trace
(
"%d failures in child process
\n
"
,
*
child_failures
);
winetest_add_failures
(
*
child_failures
);
}
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hProcess
);
}
else
win_skip
(
"RtlAcquirePebLock/RtlReleasePebLock are not available on this platform
\n
"
);
/* test remote process termination */
SetLastError
(
0xdeadbeef
);
ret
=
CreateProcess
(
argv
[
0
],
NULL
,
NULL
,
NULL
,
FALSE
,
CREATE_SUSPENDED
,
NULL
,
NULL
,
&
si
,
&
pi
);
...
...
@@ -1800,7 +1948,7 @@ static void test_ExitProcess(void)
/* Calling GetExitCodeThread() without waiting for thread termination
* leads to different results due to a race condition.
*/
ret
=
WaitForSingleObject
(
thread
,
100
);
ret
=
WaitForSingleObject
(
thread
,
100
0
);
ok
(
ret
==
WAIT_OBJECT_0
,
"WaitForSingleObject failed: %x
\n
"
,
ret
);
GetExitCodeThread
(
thread
,
&
ret
);
ok
(
ret
==
199
,
"expected exit code 199, got %u
\n
"
,
ret
);
...
...
@@ -1929,6 +2077,10 @@ START_TEST(loader)
pRtlDllShutdownInProgress
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"RtlDllShutdownInProgress"
);
pNtAllocateVirtualMemory
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"NtAllocateVirtualMemory"
);
pNtFreeVirtualMemory
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"NtFreeVirtualMemory"
);
pLdrLockLoaderLock
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"LdrLockLoaderLock"
);
pLdrUnlockLoaderLock
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"LdrUnlockLoaderLock"
);
pRtlAcquirePebLock
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"RtlAcquirePebLock"
);
pRtlReleasePebLock
=
(
void
*
)
GetProcAddress
(
GetModuleHandle
(
"ntdll.dll"
),
"RtlReleasePebLock"
);
mapping
=
CreateFileMapping
(
INVALID_HANDLE_VALUE
,
NULL
,
PAGE_READWRITE
,
0
,
4096
,
"winetest_loader"
);
ok
(
mapping
!=
0
,
"CreateFileMapping failed
\n
"
);
...
...
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