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
3469ebf9
Commit
3469ebf9
authored
Jul 01, 2021
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement RtlWow64GetThreadSelectorEntry().
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
dbabe2fa
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
207 additions
and
1 deletion
+207
-1
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-0
process.c
dlls/ntdll/process.c
+67
-0
wow64.c
dlls/ntdll/tests/wow64.c
+137
-0
signal_i386.c
dlls/ntdll/unix/signal_i386.c
+1
-1
winternl.h
include/winternl.h
+1
-0
No files found.
dlls/ntdll/ntdll.spec
View file @
3469ebf9
...
...
@@ -1079,6 +1079,7 @@
@ stdcall RtlWow64GetCurrentMachine()
@ stdcall RtlWow64GetProcessMachines(long ptr ptr)
@ stdcall -arch=win64 RtlWow64GetThreadContext(long ptr)
@ stdcall -arch=win64 RtlWow64GetThreadSelectorEntry(long ptr long ptr)
@ stdcall RtlWow64IsWowGuestMachineSupported(long ptr)
@ stdcall -arch=win64 RtlWow64SetThreadContext(long ptr)
@ stub RtlWriteMemoryStream
...
...
dlls/ntdll/process.c
View file @
3469ebf9
...
...
@@ -178,6 +178,73 @@ NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *co
return
NtSetInformationThread
(
handle
,
ThreadWow64Context
,
context
,
sizeof
(
*
context
)
);
}
/******************************************************************************
* RtlWow64GetThreadSelectorEntry (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlWow64GetThreadSelectorEntry
(
HANDLE
handle
,
THREAD_DESCRIPTOR_INFORMATION
*
info
,
ULONG
size
,
ULONG
*
retlen
)
{
DWORD
sel
;
WOW64_CONTEXT
context
=
{
WOW64_CONTEXT_CONTROL
|
WOW64_CONTEXT_SEGMENTS
};
LDT_ENTRY
entry
=
{
0
};
if
(
size
!=
sizeof
(
*
info
))
return
STATUS_INFO_LENGTH_MISMATCH
;
if
(
RtlWow64GetThreadContext
(
handle
,
&
context
))
{
/* hardcoded values */
context
.
SegCs
=
0x23
;
#ifdef __x86_64__
__asm__
(
"movw %%fs,%0"
:
"=m"
(
context
.
SegFs
)
);
__asm__
(
"movw %%ss,%0"
:
"=m"
(
context
.
SegSs
)
);
#else
context
.
SegSs
=
0x2b
;
context
.
SegFs
=
0x53
;
#endif
}
sel
=
info
->
Selector
|
3
;
if
(
sel
==
0x03
)
goto
done
;
/* null selector */
/* set common data */
entry
.
HighWord
.
Bits
.
Dpl
=
3
;
entry
.
HighWord
.
Bits
.
Pres
=
1
;
entry
.
HighWord
.
Bits
.
Default_Big
=
1
;
if
(
sel
==
context
.
SegCs
)
/* code selector */
{
entry
.
LimitLow
=
0xffff
;
entry
.
HighWord
.
Bits
.
LimitHi
=
0xf
;
entry
.
HighWord
.
Bits
.
Type
=
0x1b
;
/* code */
entry
.
HighWord
.
Bits
.
Granularity
=
1
;
}
else
if
(
sel
==
context
.
SegSs
)
/* data selector */
{
entry
.
LimitLow
=
0xffff
;
entry
.
HighWord
.
Bits
.
LimitHi
=
0xf
;
entry
.
HighWord
.
Bits
.
Type
=
0x13
;
/* data */
entry
.
HighWord
.
Bits
.
Granularity
=
1
;
}
else
if
(
sel
==
context
.
SegFs
)
/* TEB selector */
{
THREAD_BASIC_INFORMATION
tbi
;
entry
.
LimitLow
=
0xfff
;
entry
.
HighWord
.
Bits
.
Type
=
0x13
;
/* data */
if
(
!
NtQueryInformationThread
(
handle
,
ThreadBasicInformation
,
&
tbi
,
sizeof
(
tbi
),
NULL
))
{
ULONG
addr
=
(
ULONG_PTR
)
tbi
.
TebBaseAddress
+
0x2000
;
/* 32-bit teb offset */
entry
.
BaseLow
=
addr
;
entry
.
HighWord
.
Bytes
.
BaseMid
=
addr
>>
16
;
entry
.
HighWord
.
Bytes
.
BaseHi
=
addr
>>
24
;
}
}
else
return
STATUS_UNSUCCESSFUL
;
done:
info
->
Entry
=
entry
;
if
(
retlen
)
*
retlen
=
sizeof
(
entry
);
return
STATUS_SUCCESS
;
}
#endif
/**********************************************************************
...
...
dlls/ntdll/tests/wow64.c
View file @
3469ebf9
...
...
@@ -24,9 +24,11 @@
static
NTSTATUS
(
WINAPI
*
pNtQuerySystemInformationEx
)(
SYSTEM_INFORMATION_CLASS
,
void
*
,
ULONG
,
void
*
,
ULONG
,
ULONG
*
);
static
USHORT
(
WINAPI
*
pRtlWow64GetCurrentMachine
)(
void
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetProcessMachines
)(
HANDLE
,
WORD
*
,
WORD
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetThreadContext
)(
HANDLE
,
WOW64_CONTEXT
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64IsWowGuestMachineSupported
)(
USHORT
,
BOOLEAN
*
);
#ifdef _WIN64
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetCpuAreaInfo
)(
WOW64_CPURESERVED
*
,
ULONG
,
WOW64_CPU_AREA_INFO
*
);
static
NTSTATUS
(
WINAPI
*
pRtlWow64GetThreadSelectorEntry
)(
HANDLE
,
THREAD_DESCRIPTOR_INFORMATION
*
,
ULONG
,
ULONG
*
);
#else
static
NTSTATUS
(
WINAPI
*
pNtWow64AllocateVirtualMemory64
)(
HANDLE
,
ULONG64
*
,
ULONG64
,
ULONG64
*
,
ULONG
,
ULONG
);
static
NTSTATUS
(
WINAPI
*
pNtWow64ReadVirtualMemory64
)(
HANDLE
,
ULONG64
,
void
*
,
ULONG64
,
ULONG64
*
);
...
...
@@ -46,9 +48,11 @@ static void init(void)
GET_PROC
(
NtQuerySystemInformationEx
);
GET_PROC
(
RtlWow64GetCurrentMachine
);
GET_PROC
(
RtlWow64GetProcessMachines
);
GET_PROC
(
RtlWow64GetThreadContext
);
GET_PROC
(
RtlWow64IsWowGuestMachineSupported
);
#ifdef _WIN64
GET_PROC
(
RtlWow64GetCpuAreaInfo
);
GET_PROC
(
RtlWow64GetThreadSelectorEntry
);
#else
GET_PROC
(
NtWow64AllocateVirtualMemory64
);
GET_PROC
(
NtWow64ReadVirtualMemory64
);
...
...
@@ -410,6 +414,138 @@ static void test_peb_teb(void)
"WowTebOffset set to %x
\n
"
,
NtCurrentTeb
()
->
WowTebOffset
);
}
static
void
test_selectors
(
void
)
{
THREAD_DESCRIPTOR_INFORMATION
info
;
NTSTATUS
status
;
ULONG
base
,
limit
,
sel
,
retlen
;
I386_CONTEXT
context
=
{
CONTEXT_I386_CONTROL
|
CONTEXT_I386_SEGMENTS
};
#ifdef _WIN64
if
(
!
pRtlWow64GetThreadSelectorEntry
)
{
win_skip
(
"RtlWow64GetThreadSelectorEntry not supported
\n
"
);
return
;
}
if
(
!
pRtlWow64GetThreadContext
||
pRtlWow64GetThreadContext
(
GetCurrentThread
(),
&
context
))
{
/* hardcoded values */
context
.
SegCs
=
0x23
;
context
.
SegSs
=
0x2b
;
context
.
SegFs
=
0x53
;
}
#define GET_ENTRY(info,size,ret) \
pRtlWow64GetThreadSelectorEntry( GetCurrentThread(), info, size, ret )
#else
GetThreadContext
(
GetCurrentThread
(),
&
context
);
#define GET_ENTRY(info,size,ret) \
NtQueryInformationThread( GetCurrentThread(), ThreadDescriptorTableEntry, info, size, ret )
#endif
trace
(
"cs %04x ss %04x fs %04x
\n
"
,
context
.
SegCs
,
context
.
SegSs
,
context
.
SegFs
);
retlen
=
0xdeadbeef
;
info
.
Selector
=
0
;
status
=
GET_ENTRY
(
&
info
,
sizeof
(
info
)
-
1
,
&
retlen
);
ok
(
status
==
STATUS_INFO_LENGTH_MISMATCH
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
0xdeadbeef
,
"len set %u
\n
"
,
retlen
);
retlen
=
0xdeadbeef
;
status
=
GET_ENTRY
(
&
info
,
sizeof
(
info
)
+
1
,
&
retlen
);
ok
(
status
==
STATUS_INFO_LENGTH_MISMATCH
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
0xdeadbeef
,
"len set %u
\n
"
,
retlen
);
retlen
=
0xdeadbeef
;
status
=
GET_ENTRY
(
NULL
,
0
,
&
retlen
);
ok
(
status
==
STATUS_INFO_LENGTH_MISMATCH
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
0xdeadbeef
,
"len set %u
\n
"
,
retlen
);
status
=
GET_ENTRY
(
&
info
,
sizeof
(
info
),
NULL
);
ok
(
!
status
,
"wrong status %x
\n
"
,
status
);
for
(
info
.
Selector
=
0
;
info
.
Selector
<
0x100
;
info
.
Selector
++
)
{
retlen
=
0xdeadbeef
;
status
=
GET_ENTRY
(
&
info
,
sizeof
(
info
),
&
retlen
);
base
=
(
info
.
Entry
.
BaseLow
|
(
info
.
Entry
.
HighWord
.
Bytes
.
BaseMid
<<
16
)
|
(
info
.
Entry
.
HighWord
.
Bytes
.
BaseHi
<<
24
));
limit
=
(
info
.
Entry
.
LimitLow
|
info
.
Entry
.
HighWord
.
Bits
.
LimitHi
<<
16
);
sel
=
info
.
Selector
|
3
;
if
(
sel
==
0x03
)
/* null selector */
{
ok
(
!
status
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
sizeof
(
info
.
Entry
),
"len set %u
\n
"
,
retlen
);
ok
(
!
base
,
"wrong base %x
\n
"
,
base
);
ok
(
!
limit
,
"wrong limit %x
\n
"
,
limit
);
ok
(
!
info
.
Entry
.
HighWord
.
Bytes
.
Flags1
,
"wrong flags1 %x
\n
"
,
info
.
Entry
.
HighWord
.
Bytes
.
Flags1
);
ok
(
!
info
.
Entry
.
HighWord
.
Bytes
.
Flags2
,
"wrong flags2 %x
\n
"
,
info
.
Entry
.
HighWord
.
Bytes
.
Flags2
);
}
else
if
(
sel
==
context
.
SegCs
)
/* 32-bit code selector */
{
ok
(
!
status
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
sizeof
(
info
.
Entry
),
"len set %u
\n
"
,
retlen
);
ok
(
!
base
,
"wrong base %x
\n
"
,
base
);
ok
(
limit
==
0xfffff
,
"wrong limit %x
\n
"
,
limit
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Type
==
0x1b
,
"wrong type %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Type
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Dpl
==
3
,
"wrong dpl %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Dpl
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Pres
,
"wrong pres
\n
"
);
ok
(
!
info
.
Entry
.
HighWord
.
Bits
.
Sys
,
"wrong sys
\n
"
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Default_Big
,
"wrong big
\n
"
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Granularity
,
"wrong granularity
\n
"
);
}
else
if
(
sel
==
context
.
SegSs
)
/* 32-bit data selector */
{
ok
(
!
status
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
sizeof
(
info
.
Entry
),
"len set %u
\n
"
,
retlen
);
ok
(
!
base
,
"wrong base %x
\n
"
,
base
);
ok
(
limit
==
0xfffff
,
"wrong limit %x
\n
"
,
limit
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Type
==
0x13
,
"wrong type %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Type
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Dpl
==
3
,
"wrong dpl %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Dpl
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Pres
,
"wrong pres
\n
"
);
ok
(
!
info
.
Entry
.
HighWord
.
Bits
.
Sys
,
"wrong sys
\n
"
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Default_Big
,
"wrong big
\n
"
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Granularity
,
"wrong granularity
\n
"
);
}
else
if
(
sel
==
context
.
SegFs
)
/* TEB selector */
{
ok
(
!
status
,
"wrong status %x
\n
"
,
status
);
ok
(
retlen
==
sizeof
(
info
.
Entry
),
"len set %u
\n
"
,
retlen
);
#ifdef _WIN64
if
(
NtCurrentTeb
()
->
WowTebOffset
==
0x2000
)
ok
(
base
==
(
ULONG_PTR
)
NtCurrentTeb
()
+
0x2000
,
"wrong base %x / %p
\n
"
,
base
,
NtCurrentTeb
()
);
#else
ok
(
base
==
(
ULONG_PTR
)
NtCurrentTeb
(),
"wrong base %x / %p
\n
"
,
base
,
NtCurrentTeb
()
);
#endif
ok
(
limit
==
0xfff
||
broken
(
limit
==
0x4000
),
/* <= win8 */
"wrong limit %x
\n
"
,
limit
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Type
==
0x13
,
"wrong type %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Type
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Dpl
==
3
,
"wrong dpl %x
\n
"
,
info
.
Entry
.
HighWord
.
Bits
.
Dpl
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Pres
,
"wrong pres
\n
"
);
ok
(
!
info
.
Entry
.
HighWord
.
Bits
.
Sys
,
"wrong sys
\n
"
);
ok
(
info
.
Entry
.
HighWord
.
Bits
.
Default_Big
,
"wrong big
\n
"
);
ok
(
!
info
.
Entry
.
HighWord
.
Bits
.
Granularity
,
"wrong granularity
\n
"
);
}
else
if
(
!
status
)
{
ok
(
retlen
==
sizeof
(
info
.
Entry
),
"len set %u
\n
"
,
retlen
);
trace
(
"succeeded for %x base %x limit %x type %x
\n
"
,
sel
,
base
,
limit
,
info
.
Entry
.
HighWord
.
Bits
.
Type
);
}
else
{
ok
(
status
==
STATUS_UNSUCCESSFUL
||
((
sel
&
4
)
&&
(
status
==
STATUS_NO_LDT
))
||
broken
(
status
==
STATUS_ACCESS_VIOLATION
),
/* <= win8 */
"%x: wrong status %x
\n
"
,
info
.
Selector
,
status
);
ok
(
retlen
==
0xdeadbeef
,
"len set %u
\n
"
,
retlen
);
}
}
#undef GET_ENTRY
}
#ifdef _WIN64
static
void
test_cpu_area
(
void
)
...
...
@@ -783,6 +919,7 @@ START_TEST(wow64)
init
();
test_query_architectures
();
test_peb_teb
();
test_selectors
();
#ifndef _WIN64
test_nt_wow64
();
test_modules
();
...
...
dlls/ntdll/unix/signal_i386.c
View file @
3469ebf9
...
...
@@ -2111,7 +2111,7 @@ NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_
THREAD_DESCRIPTOR_INFORMATION
*
info
=
data
;
NTSTATUS
status
=
STATUS_SUCCESS
;
if
(
len
<
sizeof
(
*
info
))
return
STATUS_INFO_LENGTH_MISMATCH
;
if
(
len
!=
sizeof
(
*
info
))
return
STATUS_INFO_LENGTH_MISMATCH
;
if
(
info
->
Selector
>>
16
)
return
STATUS_UNSUCCESSFUL
;
if
(
is_gdt_sel
(
info
->
Selector
))
...
...
include/winternl.h
View file @
3469ebf9
...
...
@@ -4406,6 +4406,7 @@ NTSYSAPI int __cdecl _strnicmp(LPCSTR,LPCSTR,size_t);
NTSYSAPI
NTSTATUS
WINAPI
RtlWow64GetCpuAreaInfo
(
WOW64_CPURESERVED
*
,
ULONG
,
WOW64_CPU_AREA_INFO
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlWow64GetCurrentCpuArea
(
USHORT
*
,
void
**
,
void
**
);
NTSYSAPI
NTSTATUS
WINAPI
RtlWow64GetThreadContext
(
HANDLE
,
WOW64_CONTEXT
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlWow64GetThreadSelectorEntry
(
HANDLE
,
THREAD_DESCRIPTOR_INFORMATION
*
,
ULONG
,
ULONG
*
);
NTSYSAPI
NTSTATUS
WINAPI
RtlWow64SetThreadContext
(
HANDLE
,
const
WOW64_CONTEXT
*
);
#else
NTSYSAPI
NTSTATUS
WINAPI
NtWow64AllocateVirtualMemory64
(
HANDLE
,
ULONG64
*
,
ULONG64
,
ULONG64
*
,
ULONG
,
ULONG
);
...
...
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