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
a865a4f6
Commit
a865a4f6
authored
Jul 24, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Allocate 64-bit TEB and PEB in WoW64 mode.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
e3b059b5
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
131 additions
and
46 deletions
+131
-46
loader.c
dlls/ntdll/loader.c
+16
-3
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+4
-0
info.c
dlls/ntdll/tests/info.c
+42
-0
server.c
dlls/ntdll/unix/server.c
+13
-1
signal_i386.c
dlls/ntdll/unix/signal_i386.c
+3
-3
unix_private.h
dlls/ntdll/unix/unix_private.h
+12
-5
virtual.c
dlls/ntdll/unix/virtual.c
+41
-34
No files found.
dlls/ntdll/loader.c
View file @
a865a4f6
...
...
@@ -3906,7 +3906,6 @@ void __wine_process_init(void)
UNICODE_STRING
nt_name
;
MEMORY_BASIC_INFORMATION
meminfo
;
INITIAL_TEB
stack
;
ULONG_PTR
val
;
TEB
*
teb
=
NtCurrentTeb
();
PEB
*
peb
=
teb
->
Peb
;
...
...
@@ -3935,8 +3934,9 @@ void __wine_process_init(void)
InitializeListHead
(
&
ldr
.
InMemoryOrderModuleList
);
InitializeListHead
(
&
ldr
.
InInitializationOrderModuleList
);
NtQueryInformationProcess
(
GetCurrentProcess
(),
ProcessWow64Information
,
&
val
,
sizeof
(
val
),
NULL
);
is_wow64
=
!!
val
;
#ifndef _WIN64
is_wow64
=
!!
NtCurrentTeb64
();
#endif
init_unix_codepage
();
init_directories
();
...
...
@@ -4008,6 +4008,19 @@ void __wine_process_init(void)
NtTerminateProcess
(
GetCurrentProcess
(),
status
);
}
#ifndef _WIN64
if
(
NtCurrentTeb64
())
{
PEB64
*
peb64
=
UlongToPtr
(
NtCurrentTeb64
()
->
Peb
);
peb64
->
ImageBaseAddress
=
PtrToUlong
(
peb
->
ImageBaseAddress
);
peb64
->
OSMajorVersion
=
peb
->
OSMajorVersion
;
peb64
->
OSMinorVersion
=
peb
->
OSMinorVersion
;
peb64
->
OSBuildNumber
=
peb
->
OSBuildNumber
;
peb64
->
OSPlatformId
=
peb
->
OSPlatformId
;
peb64
->
SessionId
=
peb
->
SessionId
;
}
#endif
/* the main exe needs to be the first in the load order list */
RemoveEntryList
(
&
wm
->
ldr
.
InLoadOrderLinks
);
InsertHeadList
(
&
peb
->
LdrData
->
InLoadOrderModuleList
,
&
wm
->
ldr
.
InLoadOrderLinks
);
...
...
dlls/ntdll/ntdll_misc.h
View file @
a865a4f6
...
...
@@ -129,6 +129,10 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
return
(
struct
ntdll_thread_data
*
)
&
NtCurrentTeb
()
->
GdiTebBatch
;
}
#ifndef _WIN64
static
inline
TEB64
*
NtCurrentTeb64
(
void
)
{
return
(
TEB64
*
)
NtCurrentTeb
()
->
GdiBatchCount
;
}
#endif
#define HASH_STRING_ALGORITHM_DEFAULT 0
#define HASH_STRING_ALGORITHM_X65599 1
#define HASH_STRING_ALGORITHM_INVALID 0xffffffff
...
...
dlls/ntdll/tests/info.c
View file @
a865a4f6
...
...
@@ -2636,6 +2636,47 @@ static void test_thread_info(void)
ok
(
len
==
0xdeadbeef
,
"wrong len %u
\n
"
,
len
);
}
static
void
test_wow64
(
void
)
{
#ifndef _WIN64
if
(
is_wow64
)
{
PEB64
*
peb64
;
TEB64
*
teb64
=
(
TEB64
*
)
NtCurrentTeb
()
->
GdiBatchCount
;
ok
(
!!
teb64
,
"GdiBatchCount not set
\n
"
);
ok
(
(
char
*
)
NtCurrentTeb
()
+
NtCurrentTeb
()
->
WowTebOffset
==
(
char
*
)
teb64
||
broken
(
!
NtCurrentTeb
()
->
WowTebOffset
),
/* pre-win10 */
"wrong WowTebOffset %x (%p/%p)
\n
"
,
NtCurrentTeb
()
->
WowTebOffset
,
teb64
,
NtCurrentTeb
()
);
ok
(
(
char
*
)
teb64
+
0x2000
==
(
char
*
)
NtCurrentTeb
(),
"unexpected diff %p / %p
\n
"
,
teb64
,
NtCurrentTeb
()
);
ok
(
teb64
->
Tib
.
ExceptionList
==
PtrToUlong
(
NtCurrentTeb
()
),
"wrong Tib.ExceptionList %s / %p
\n
"
,
wine_dbgstr_longlong
(
teb64
->
Tib
.
ExceptionList
),
NtCurrentTeb
()
);
ok
(
teb64
->
Tib
.
Self
==
PtrToUlong
(
teb64
),
"wrong Tib.Self %s / %p
\n
"
,
wine_dbgstr_longlong
(
teb64
->
Tib
.
Self
),
teb64
);
ok
(
teb64
->
StaticUnicodeString
.
Buffer
==
PtrToUlong
(
teb64
->
StaticUnicodeBuffer
),
"wrong StaticUnicodeString %s / %p
\n
"
,
wine_dbgstr_longlong
(
teb64
->
StaticUnicodeString
.
Buffer
),
teb64
->
StaticUnicodeBuffer
);
ok
(
teb64
->
ClientId
.
UniqueProcess
==
GetCurrentProcessId
(),
"wrong pid %s / %x
\n
"
,
wine_dbgstr_longlong
(
teb64
->
ClientId
.
UniqueProcess
),
GetCurrentProcessId
()
);
ok
(
teb64
->
ClientId
.
UniqueThread
==
GetCurrentThreadId
(),
"wrong tid %s / %x
\n
"
,
wine_dbgstr_longlong
(
teb64
->
ClientId
.
UniqueThread
),
GetCurrentThreadId
()
);
peb64
=
ULongToPtr
(
teb64
->
Peb
);
ok
(
peb64
->
ImageBaseAddress
==
PtrToUlong
(
NtCurrentTeb
()
->
Peb
->
ImageBaseAddress
),
"wrong ImageBaseAddress %s / %p
\n
"
,
wine_dbgstr_longlong
(
peb64
->
ImageBaseAddress
),
NtCurrentTeb
()
->
Peb
->
ImageBaseAddress
);
ok
(
peb64
->
OSBuildNumber
==
NtCurrentTeb
()
->
Peb
->
OSBuildNumber
,
"wrong OSBuildNumber %x / %x
\n
"
,
peb64
->
OSBuildNumber
,
NtCurrentTeb
()
->
Peb
->
OSBuildNumber
);
ok
(
peb64
->
OSPlatformId
==
NtCurrentTeb
()
->
Peb
->
OSPlatformId
,
"wrong OSPlatformId %x / %x
\n
"
,
peb64
->
OSPlatformId
,
NtCurrentTeb
()
->
Peb
->
OSPlatformId
);
return
;
}
#endif
ok
(
!
NtCurrentTeb
()
->
GdiBatchCount
,
"GdiBatchCount set to %x
\n
"
,
NtCurrentTeb
()
->
GdiBatchCount
);
ok
(
!
NtCurrentTeb
()
->
WowTebOffset
,
"WowTebOffset set to %x
\n
"
,
NtCurrentTeb
()
->
WowTebOffset
);
}
START_TEST
(
info
)
{
char
**
argv
;
...
...
@@ -2693,6 +2734,7 @@ START_TEST(info)
test_thread_lookup
();
test_affinity
();
test_wow64
();
/* belongs to its own file */
test_readvirtualmemory
();
...
...
dlls/ntdll/unix/server.c
View file @
a865a4f6
...
...
@@ -1551,7 +1551,19 @@ size_t server_init_thread( void *entry_point, BOOL *suspend )
}
SERVER_END_REQ
;
is_wow64
=
!
is_win64
&&
(
server_cpus
&
((
1
<<
CPU_x86_64
)
|
(
1
<<
CPU_ARM64
)))
!=
0
;
#ifndef _WIN64
is_wow64
=
(
server_cpus
&
((
1
<<
CPU_x86_64
)
|
(
1
<<
CPU_ARM64
)))
!=
0
;
if
(
is_wow64
)
{
TEB64
*
teb64
=
(
TEB64
*
)((
char
*
)
NtCurrentTeb
()
-
teb_offset
);
NtCurrentTeb
()
->
GdiBatchCount
=
PtrToUlong
(
teb64
);
NtCurrentTeb
()
->
WowTebOffset
=
-
teb_offset
;
teb64
->
ClientId
.
UniqueProcess
=
PtrToUlong
(
NtCurrentTeb
()
->
ClientId
.
UniqueProcess
);
teb64
->
ClientId
.
UniqueThread
=
PtrToUlong
(
NtCurrentTeb
()
->
ClientId
.
UniqueThread
);
}
#endif
ntdll_get_thread_data
()
->
wow64_redir
=
is_wow64
;
switch
(
ret
)
...
...
dlls/ntdll/unix/signal_i386.c
View file @
a865a4f6
...
...
@@ -540,7 +540,7 @@ static inline TEB *get_current_teb(void)
{
unsigned
long
esp
;
__asm__
(
"movl %%esp,%0"
:
"=g"
(
esp
)
);
return
(
TEB
*
)(
esp
&
~
signal_stack_mask
);
return
(
TEB
*
)(
(
esp
&
~
signal_stack_mask
)
+
teb_offset
);
}
...
...
@@ -1937,7 +1937,7 @@ static void ldt_set_fs( WORD sel, TEB *teb )
struct
modify_ldt_s
ldt_info
=
{
sel
>>
3
};
ldt_info
.
base_addr
=
teb
;
ldt_info
.
limit
=
teb
_size
-
1
;
ldt_info
.
limit
=
page
_size
-
1
;
ldt_info
.
seg_32bit
=
1
;
if
(
set_thread_area
(
&
ldt_info
)
<
0
)
perror
(
"set_thread_area"
);
#elif defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__)
...
...
@@ -2052,7 +2052,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
static
int
first_thread
=
1
;
sigset_t
sigset
;
int
idx
;
LDT_ENTRY
entry
=
ldt_make_entry
(
teb
,
teb
_size
-
1
,
LDT_FLAGS_DATA
|
LDT_FLAGS_32BIT
);
LDT_ENTRY
entry
=
ldt_make_entry
(
teb
,
page
_size
-
1
,
LDT_FLAGS_DATA
|
LDT_FLAGS_32BIT
);
if
(
first_thread
)
/* no locking for first thread */
{
...
...
dlls/ntdll/unix/unix_private.h
View file @
a865a4f6
...
...
@@ -71,7 +71,17 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
return
(
struct
ntdll_thread_data
*
)
&
NtCurrentTeb
()
->
GdiTebBatch
;
}
static
const
UINT_PTR
page_size
=
0x1000
;
static
const
SIZE_T
page_size
=
0x1000
;
static
const
SIZE_T
signal_stack_mask
=
0xffff
;
#ifdef _WIN64
static
const
SIZE_T
teb_size
=
0x2000
;
static
const
SIZE_T
teb_offset
=
0
;
static
const
SIZE_T
signal_stack_size
=
0x10000
-
0x2000
;
#else
static
const
SIZE_T
teb_size
=
0x3000
;
/* TEB64 + TEB */
static
const
SIZE_T
teb_offset
=
0x2000
;
static
const
SIZE_T
signal_stack_size
=
0x10000
-
0x3000
;
#endif
/* callbacks to PE ntdll from the Unix side */
extern
void
(
WINAPI
*
pDbgUiRemoteBreakin
)(
void
*
arg
)
DECLSPEC_HIDDEN
;
...
...
@@ -144,9 +154,6 @@ extern BOOL is_wow64 DECLSPEC_HIDDEN;
extern
HANDLE
keyed_event
DECLSPEC_HIDDEN
;
extern
timeout_t
server_start_time
DECLSPEC_HIDDEN
;
extern
sigset_t
server_block_set
DECLSPEC_HIDDEN
;
extern
SIZE_T
signal_stack_size
DECLSPEC_HIDDEN
;
extern
SIZE_T
signal_stack_mask
DECLSPEC_HIDDEN
;
static
const
SIZE_T
teb_size
=
0x1000
*
sizeof
(
void
*
)
/
4
;
extern
struct
_KUSER_SHARED_DATA
*
user_shared_data
DECLSPEC_HIDDEN
;
#ifdef __i386__
extern
struct
ldt_copy
__wine_ldt_copy
DECLSPEC_HIDDEN
;
...
...
@@ -278,7 +285,7 @@ static inline IMAGE_NT_HEADERS *get_exe_nt_header(void)
static
inline
void
*
get_signal_stack
(
void
)
{
return
(
char
*
)
NtCurrentTeb
()
+
teb_size
;
return
(
char
*
)
NtCurrentTeb
()
+
teb_size
-
teb_offset
;
}
static
inline
size_t
ntdll_wcslen
(
const
WCHAR
*
str
)
...
...
dlls/ntdll/unix/virtual.c
View file @
a865a4f6
...
...
@@ -154,12 +154,9 @@ static void *working_set_limit = (void *)0x7fff0000;
struct
_KUSER_SHARED_DATA
*
user_shared_data
=
(
void
*
)
0x7ffe0000
;
SIZE_T
signal_stack_size
=
0
;
SIZE_T
signal_stack_mask
=
0
;
/* TEB allocation blocks */
static
TEB
*
teb_block
;
static
TEB
*
next_free_teb
;
static
void
*
teb_block
;
static
void
*
*
next_free_teb
;
static
int
teb_block_pos
;
static
struct
list
teb_list
=
LIST_INIT
(
teb_list
);
...
...
@@ -2361,7 +2358,7 @@ void virtual_init(void)
const
struct
preload_info
**
preload_info
=
dlsym
(
RTLD_DEFAULT
,
"wine_main_preload_info"
);
const
char
*
preload
=
getenv
(
"WINEPRELOADRESERVE"
);
struct
alloc_virtual_heap
alloc_views
;
size_t
size
,
align
;
size_t
size
;
int
i
;
pthread_mutexattr_t
attr
;
...
...
@@ -2389,13 +2386,6 @@ void virtual_init(void)
}
}
size
=
teb_size
+
max
(
MINSIGSTKSZ
,
8192
);
/* find the first power of two not smaller than size */
align
=
page_shift
;
while
((
1u
<<
align
)
<
size
)
align
++
;
signal_stack_mask
=
(
1
<<
align
)
-
1
;
signal_stack_size
=
(
1
<<
align
)
-
teb_size
;
/* try to find space in a reserved area for the views and pages protection table */
#ifdef _WIN64
pages_vprot_size
=
((
size_t
)
address_space_limit
>>
page_shift
>>
pages_vprot_shift
)
+
1
;
...
...
@@ -2566,6 +2556,19 @@ static void init_teb( TEB *teb, PEB *peb )
{
struct
ntdll_thread_data
*
thread_data
=
(
struct
ntdll_thread_data
*
)
&
teb
->
GdiTebBatch
;
#ifndef _WIN64
TEB64
*
teb64
=
(
TEB64
*
)((
char
*
)
teb
-
teb_offset
);
teb64
->
Peb
=
PtrToUlong
(
(
char
*
)
peb
+
page_size
);
teb64
->
Tib
.
Self
=
PtrToUlong
(
teb64
);
teb64
->
Tib
.
ExceptionList
=
PtrToUlong
(
teb
);
teb64
->
ActivationContextStackPointer
=
PtrToUlong
(
&
teb64
->
ActivationContextStack
);
teb64
->
ActivationContextStack
.
FrameListCache
.
Flink
=
teb64
->
ActivationContextStack
.
FrameListCache
.
Blink
=
PtrToUlong
(
&
teb64
->
ActivationContextStack
.
FrameListCache
);
teb64
->
StaticUnicodeString
.
Buffer
=
PtrToUlong
(
teb64
->
StaticUnicodeBuffer
);
teb64
->
StaticUnicodeString
.
MaximumLength
=
sizeof
(
teb64
->
StaticUnicodeBuffer
);
#endif
teb
->
Peb
=
peb
;
teb
->
Tib
.
Self
=
&
teb
->
Tib
;
teb
->
Tib
.
ExceptionList
=
(
void
*
)
~
0ul
;
...
...
@@ -2589,10 +2592,11 @@ TEB *virtual_alloc_first_teb(void)
{
TEB
*
teb
;
PEB
*
peb
;
void
*
ptr
;
NTSTATUS
status
;
SIZE_T
data_size
=
page_size
;
SIZE_T
peb_size
=
page_size
;
SIZE_T
block_size
=
signal_stack_
size
+
teb_size
;
SIZE_T
peb_size
=
page_size
*
(
is_win64
?
1
:
2
)
;
SIZE_T
block_size
=
signal_stack_
mask
+
1
;
SIZE_T
total
=
32
*
block_size
;
/* reserve space for shared user data */
...
...
@@ -2604,12 +2608,13 @@ TEB *virtual_alloc_first_teb(void)
exit
(
1
);
}
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
teb_block
,
0
,
&
total
,
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
&
teb_block
,
0
,
&
total
,
MEM_RESERVE
|
MEM_TOP_DOWN
,
PAGE_READWRITE
);
teb_block_pos
=
30
;
teb
=
(
TEB
*
)((
char
*
)
teb_block
+
30
*
block_size
);
ptr
=
((
char
*
)
teb_block
+
30
*
block_size
);
teb
=
(
TEB
*
)((
char
*
)
ptr
+
teb_offset
);
peb
=
(
PEB
*
)((
char
*
)
teb_block
+
32
*
block_size
-
peb_size
);
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
teb
,
0
,
&
block_size
,
MEM_COMMIT
,
PAGE_READWRITE
);
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
ptr
,
0
,
&
block_size
,
MEM_COMMIT
,
PAGE_READWRITE
);
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
peb
,
0
,
&
peb_size
,
MEM_COMMIT
,
PAGE_READWRITE
);
init_teb
(
teb
,
peb
);
*
(
ULONG_PTR
*
)
peb
->
Reserved
=
get_image_address
();
...
...
@@ -2623,46 +2628,46 @@ TEB *virtual_alloc_first_teb(void)
NTSTATUS
virtual_alloc_teb
(
TEB
**
ret_teb
)
{
sigset_t
sigset
;
TEB
*
teb
=
NULL
;
TEB
*
teb
;
void
*
ptr
=
NULL
;
NTSTATUS
status
=
STATUS_SUCCESS
;
SIZE_T
teb
_size
=
signal_stack_mask
+
1
;
SIZE_T
block
_size
=
signal_stack_mask
+
1
;
server_enter_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
if
(
next_free_teb
)
{
teb
=
next_free_teb
;
next_free_teb
=
*
(
TEB
**
)
teb
;
memset
(
teb
,
0
,
sizeof
(
*
teb
)
);
ptr
=
next_free_teb
;
next_free_teb
=
*
(
void
**
)
ptr
;
memset
(
ptr
,
0
,
teb_size
);
}
else
{
if
(
!
teb_block_pos
)
{
void
*
addr
=
NULL
;
SIZE_T
total
=
32
*
teb_size
;
SIZE_T
total
=
32
*
block_size
;
if
((
status
=
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
&
add
r
,
0
,
&
total
,
if
((
status
=
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
&
pt
r
,
0
,
&
total
,
MEM_RESERVE
,
PAGE_READWRITE
)))
{
server_leave_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
return
status
;
}
teb_block
=
add
r
;
teb_block
=
pt
r
;
teb_block_pos
=
32
;
}
teb
=
(
TEB
*
)((
char
*
)
teb_block
+
--
teb_block_pos
*
teb
_size
);
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
teb
,
0
,
&
teb
_size
,
ptr
=
((
char
*
)
teb_block
+
--
teb_block_pos
*
block
_size
);
NtAllocateVirtualMemory
(
NtCurrentProcess
(),
(
void
**
)
&
ptr
,
0
,
&
block
_size
,
MEM_COMMIT
,
PAGE_READWRITE
);
}
*
ret_teb
=
teb
=
(
TEB
*
)((
char
*
)
ptr
+
teb_offset
);
init_teb
(
teb
,
NtCurrentTeb
()
->
Peb
);
*
ret_teb
=
teb
;
server_leave_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
if
((
status
=
signal_alloc_thread
(
teb
)))
{
server_enter_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
*
(
TEB
**
)
teb
=
next_free_teb
;
next_free_teb
=
teb
;
*
(
void
**
)
ptr
=
next_free_teb
;
next_free_teb
=
ptr
;
server_leave_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
}
return
status
;
...
...
@@ -2675,6 +2680,7 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
void
virtual_free_teb
(
TEB
*
teb
)
{
struct
ntdll_thread_data
*
thread_data
=
(
struct
ntdll_thread_data
*
)
&
teb
->
GdiTebBatch
;
void
*
ptr
;
SIZE_T
size
;
sigset_t
sigset
;
...
...
@@ -2692,8 +2698,9 @@ void virtual_free_teb( TEB *teb )
server_enter_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
list_remove
(
&
thread_data
->
entry
);
*
(
TEB
**
)
teb
=
next_free_teb
;
next_free_teb
=
teb
;
ptr
=
(
char
*
)
teb
-
teb_offset
;
*
(
void
**
)
ptr
=
next_free_teb
;
next_free_teb
=
ptr
;
server_leave_uninterrupted_section
(
&
virtual_mutex
,
&
sigset
);
}
...
...
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