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
aab0d25a
Commit
aab0d25a
authored
Oct 21, 2014
by
Sebastian Lackner
Committed by
Alexandre Julliard
Oct 21, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Add support for ATL thunk 'MOV this,ecx; JMP func'.
parent
1e3f15d8
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
63 additions
and
22 deletions
+63
-22
virtual.c
dlls/kernel32/tests/virtual.c
+26
-5
signal_i386.c
dlls/ntdll/signal_i386.c
+37
-17
No files found.
dlls/kernel32/tests/virtual.c
View file @
aab0d25a
...
@@ -1882,7 +1882,7 @@ static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPA
...
@@ -1882,7 +1882,7 @@ static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPA
pNtCurrentTeb
()
->
Tib
.
ExceptionList
=
&
frame
;
pNtCurrentTeb
()
->
Tib
.
ExceptionList
=
&
frame
;
num_guard_page_calls
=
num_execute_fault_calls
=
0
;
num_guard_page_calls
=
num_execute_fault_calls
=
0
;
ret
=
SendMessageA
(
hWnd
,
WM_USER
,
0
,
0
);
ret
=
SendMessageA
(
hWnd
,
uMsg
,
wParam
,
lParam
);
pNtCurrentTeb
()
->
Tib
.
ExceptionList
=
frame
.
Prev
;
pNtCurrentTeb
()
->
Tib
.
ExceptionList
=
frame
.
Prev
;
...
@@ -1900,14 +1900,18 @@ static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
...
@@ -1900,14 +1900,18 @@ static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
static
LRESULT
CALLBACK
atl_test_func
(
HWND
hWnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
static
LRESULT
CALLBACK
atl_test_func
(
HWND
hWnd
,
UINT
uMsg
,
WPARAM
wParam
,
LPARAM
lParam
)
{
{
DWORD
arg
=
(
DWORD
)
hWnd
;
DWORD
arg
=
(
DWORD
)
hWnd
;
ok
(
arg
==
0x11223344
,
"arg is 0x%08x instead of 0x11223344
\n
"
,
arg
);
if
(
uMsg
==
WM_USER
)
ok
(
arg
==
0x11223344
,
"arg is 0x%08x instead of 0x11223344
\n
"
,
arg
);
else
ok
(
arg
!=
0x11223344
,
"arg is unexpectedly 0x11223344
\n
"
);
return
43
;
return
43
;
}
}
static
void
test_atl_thunk_emulation
(
ULONG
dep_flags
)
static
void
test_atl_thunk_emulation
(
ULONG
dep_flags
)
{
{
static
const
char
code_jmp
[]
=
{
0xE9
,
0x00
,
0x00
,
0x00
,
0x00
};
static
const
char
code_jmp
[]
=
{
0xE9
,
0x00
,
0x00
,
0x00
,
0x00
};
static
const
char
code_atl
[]
=
{
0xC7
,
0x44
,
0x24
,
0x04
,
0x44
,
0x33
,
0x22
,
0x11
,
0xE9
,
0x00
,
0x00
,
0x00
,
0x00
};
static
const
char
code_atl1
[]
=
{
0xC7
,
0x44
,
0x24
,
0x04
,
0x44
,
0x33
,
0x22
,
0x11
,
0xE9
,
0x00
,
0x00
,
0x00
,
0x00
};
static
const
char
code_atl2
[]
=
{
0xB9
,
0x44
,
0x33
,
0x22
,
0x11
,
0xE9
,
0x00
,
0x00
,
0x00
,
0x00
};
static
const
char
cls_name
[]
=
"atl_thunk_class"
;
static
const
char
cls_name
[]
=
"atl_thunk_class"
;
DWORD
ret
,
size
,
old_prot
;
DWORD
ret
,
size
,
old_prot
;
ULONG
old_flags
=
MEM_EXECUTE_OPTION_ENABLE
;
ULONG
old_flags
=
MEM_EXECUTE_OPTION_ENABLE
;
...
@@ -2008,7 +2012,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
...
@@ -2008,7 +2012,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
/* Now test with a proper ATL thunk instruction. */
/* Now test with a proper ATL thunk instruction. */
memcpy
(
base
,
code_atl
,
sizeof
(
code_atl
)
);
memcpy
(
base
,
code_atl
1
,
sizeof
(
code_atl1
)
);
*
(
DWORD
*
)(
base
+
9
)
=
(
DWORD_PTR
)
atl_test_func
-
(
DWORD_PTR
)(
base
+
13
);
*
(
DWORD
*
)(
base
+
9
)
=
(
DWORD_PTR
)
atl_test_func
-
(
DWORD_PTR
)(
base
+
13
);
success
=
VirtualProtect
(
base
,
size
,
PAGE_EXECUTE_READWRITE
,
&
old_prot
);
success
=
VirtualProtect
(
base
,
size
,
PAGE_EXECUTE_READWRITE
,
&
old_prot
);
...
@@ -2077,6 +2081,23 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
...
@@ -2077,6 +2081,23 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
win_skip
(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found
\n
"
);
win_skip
(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found
\n
"
);
}
}
/* Test alternative ATL thunk instructions. */
memcpy
(
base
,
code_atl2
,
sizeof
(
code_atl2
)
);
*
(
DWORD
*
)(
base
+
6
)
=
(
DWORD_PTR
)
atl_test_func
-
(
DWORD_PTR
)(
base
+
10
);
success
=
VirtualProtect
(
base
,
size
,
PAGE_READWRITE
,
&
old_prot
);
ok
(
success
,
"VirtualProtect failed %u
\n
"
,
GetLastError
()
);
ret
=
send_message_excpt
(
hWnd
,
WM_USER
+
1
,
0
,
0
);
/* FIXME: we don't check the content of the register ECX yet */
ok
(
ret
==
43
,
"call returned wrong result, expected 43, got %d
\n
"
,
ret
);
ok
(
num_guard_page_calls
==
0
,
"expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions
\n
"
,
num_guard_page_calls
);
if
((
dep_flags
&
MEM_EXECUTE_OPTION_DISABLE
)
&&
(
dep_flags
&
MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
))
ok
(
num_execute_fault_calls
==
1
,
"expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions
\n
"
,
num_execute_fault_calls
);
else
ok
(
num_execute_fault_calls
==
0
,
"expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions
\n
"
,
num_execute_fault_calls
);
/* Restore the JMP instruction, set to executable, and then destroy the Window */
/* Restore the JMP instruction, set to executable, and then destroy the Window */
memcpy
(
base
,
code_jmp
,
sizeof
(
code_jmp
)
);
memcpy
(
base
,
code_jmp
,
sizeof
(
code_jmp
)
);
...
@@ -2194,7 +2215,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
...
@@ -2194,7 +2215,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
/* Now test with a proper ATL thunk instruction. */
/* Now test with a proper ATL thunk instruction. */
memcpy
(
base
,
code_atl
,
sizeof
(
code_atl
)
);
memcpy
(
base
,
code_atl
1
,
sizeof
(
code_atl1
)
);
*
(
DWORD
*
)(
base
+
9
)
=
(
DWORD_PTR
)
atl_test_func
-
(
DWORD_PTR
)(
base
+
13
);
*
(
DWORD
*
)(
base
+
9
)
=
(
DWORD_PTR
)
atl_test_func
-
(
DWORD_PTR
)(
base
+
13
);
count
=
64
;
count
=
64
;
...
...
dlls/ntdll/signal_i386.c
View file @
aab0d25a
...
@@ -1616,12 +1616,22 @@ static inline BOOL check_invalid_gs( CONTEXT *context )
...
@@ -1616,12 +1616,22 @@ static inline BOOL check_invalid_gs( CONTEXT *context )
#include "pshpack1.h"
#include "pshpack1.h"
struct
atl_thunk
union
atl_thunk
{
{
DWORD
movl
;
/* movl this,4(%esp) */
struct
DWORD
this
;
{
BYTE
jmp
;
/* jmp func */
DWORD
movl
;
/* movl this,4(%esp) */
int
func
;
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t1
;
struct
{
BYTE
movl
;
/* movl this,ecx */
DWORD
this
;
BYTE
jmp
;
/* jmp func */
int
func
;
}
t2
;
};
};
#include "poppack.h"
#include "poppack.h"
...
@@ -1632,26 +1642,36 @@ struct atl_thunk
...
@@ -1632,26 +1642,36 @@ struct atl_thunk
*/
*/
static
BOOL
check_atl_thunk
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
static
BOOL
check_atl_thunk
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
)
{
{
const
struct
atl_thunk
*
thunk
=
(
const
struct
atl_thunk
*
)
rec
->
ExceptionInformation
[
1
];
const
union
atl_thunk
*
thunk
=
(
const
union
atl_thunk
*
)
rec
->
ExceptionInformation
[
1
];
struct
atl_thunk
thunk_copy
;
union
atl_thunk
thunk_copy
;
BOOL
ret
=
FALSE
;
SIZE_T
thunk_len
;
if
(
virtual_uninterrupted_read_memory
(
thunk
,
&
thunk_copy
,
sizeof
(
*
thunk
)
)
!=
sizeof
(
*
thunk
))
thunk_len
=
virtual_uninterrupted_read_memory
(
thunk
,
&
thunk_copy
,
sizeof
(
*
thunk
)
);
return
FALSE
;
if
(
!
thunk_len
)
return
FALSE
;
if
(
thunk_copy
.
movl
==
0x042444c7
&&
thunk_copy
.
jmp
==
0xe9
)
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t1
)
&&
thunk_copy
.
t1
.
movl
==
0x042444c7
&&
thunk_copy
.
t1
.
jmp
==
0xe9
)
{
{
if
(
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
context
->
Esp
+
1
,
if
(
virtual_uninterrupted_write_memory
(
(
DWORD
*
)
context
->
Esp
+
1
,
&
thunk_copy
.
this
,
sizeof
(
DWORD
)
)
==
sizeof
(
DWORD
))
&
thunk_copy
.
t
1
.
t
his
,
sizeof
(
DWORD
)
)
==
sizeof
(
DWORD
))
{
{
context
->
Eip
=
(
DWORD_PTR
)(
&
thunk
->
func
+
1
)
+
thunk_copy
.
func
;
context
->
Eip
=
(
DWORD_PTR
)(
&
thunk
->
t1
.
func
+
1
)
+
thunk_copy
.
t1
.
func
;
TRACE
(
"emulating ATL thunk at %p, func=%08x arg=%08x
\n
"
,
TRACE
(
"emulating ATL thunk
type 1
at %p, func=%08x arg=%08x
\n
"
,
thunk
,
context
->
Eip
,
thunk_copy
.
this
);
thunk
,
context
->
Eip
,
thunk_copy
.
t
1
.
t
his
);
ret
=
TRUE
;
ret
urn
TRUE
;
}
}
}
}
else
if
(
thunk_len
>=
sizeof
(
thunk_copy
.
t2
)
&&
thunk_copy
.
t2
.
movl
==
0xb9
&&
thunk_copy
.
t2
.
jmp
==
0xe9
)
{
context
->
Ecx
=
thunk_copy
.
t2
.
this
;
context
->
Eip
=
(
DWORD_PTR
)(
&
thunk
->
t2
.
func
+
1
)
+
thunk_copy
.
t2
.
func
;
TRACE
(
"emulating ATL thunk type 2 at %p, func=%08x ecx=%08x
\n
"
,
thunk
,
context
->
Eip
,
context
->
Ecx
);
return
TRUE
;
}
return
ret
;
return
FALSE
;
}
}
...
...
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