Updated patch for x86_64 set_cpu_context implementation and add tests.

This commit is contained in:
Sebastian Lackner 2015-12-28 03:26:17 +01:00
parent dcdcf18047
commit 480c7249b5
8 changed files with 209 additions and 51 deletions

View File

@ -1,4 +1,4 @@
From 1d4383d08858f302927f08138bbe81093efbfd14 Mon Sep 17 00:00:00 2001
From 24da37188127f234bfefec34ef03cf45746a8402 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 Sep 2014 22:42:46 +0200
Subject: ntdll: Throw exception if invalid handle is passed to NtClose and
@ -10,7 +10,7 @@ Subject: ntdll: Throw exception if invalid handle is passed to NtClose and
2 files changed, 92 insertions(+)
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index 47a2614..bcc6d69 100644
index 3fadba7..6527501 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -38,6 +38,7 @@
@ -21,7 +21,7 @@ index 47a2614..bcc6d69 100644
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -343,6 +344,13 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
@@ -377,6 +378,13 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
return ret;
}
@ -35,7 +35,7 @@ index 47a2614..bcc6d69 100644
/* Everquest 2 / Pirates of the Burning Sea hooks NtClose, so we need a wrapper */
NTSTATUS close_handle( HANDLE handle )
{
@@ -356,6 +364,25 @@ NTSTATUS close_handle( HANDLE handle )
@@ -390,6 +398,25 @@ NTSTATUS close_handle( HANDLE handle )
}
SERVER_END_REQ;
if (fd != -1) close( fd );
@ -62,10 +62,10 @@ index 47a2614..bcc6d69 100644
}
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 5cbab71..7a97ae5 100644
index f355513..98d73f4 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -53,6 +53,7 @@ static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
@@ -52,6 +52,7 @@ static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@ -73,7 +73,7 @@ index 5cbab71..7a97ae5 100644
#if defined(__x86_64__)
static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
@@ -938,6 +939,16 @@ static void test_debugger(void)
@@ -937,6 +938,16 @@ static void test_debugger(void)
/* here we handle exception */
}
}
@ -90,7 +90,7 @@ index 5cbab71..7a97ae5 100644
else
ok(FALSE, "unexpected stage %x\n", stage);
@@ -1791,6 +1802,53 @@ static void test_ripevent(DWORD numexc)
@@ -1893,6 +1904,53 @@ static void test_ripevent(DWORD numexc)
pRtlRemoveVectoredExceptionHandler(vectored_handler);
}
@ -144,7 +144,7 @@ index 5cbab71..7a97ae5 100644
static void test_vectored_continue_handler(void)
{
PVOID handler1, handler2;
@@ -1843,6 +1901,7 @@ START_TEST(exception)
@@ -1945,6 +2003,7 @@ START_TEST(exception)
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
@ -152,7 +152,7 @@ index 5cbab71..7a97ae5 100644
pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess" );
@@ -1910,6 +1969,10 @@ START_TEST(exception)
@@ -2012,6 +2071,10 @@ START_TEST(exception)
test_ripevent(0);
test_stage = 6;
test_ripevent(1);
@ -163,16 +163,16 @@ index 5cbab71..7a97ae5 100644
}
else
skip( "RtlRaiseException not found\n" );
@@ -1923,6 +1986,7 @@ START_TEST(exception)
test_rtlraiseexception();
@@ -2026,6 +2089,7 @@ START_TEST(exception)
test_debug_registers();
test_outputdebugstring(1, FALSE);
test_ripevent(1);
+ test_closehandle(0);
test_vectored_continue_handler();
test_debugger();
test_simd_exceptions();
@@ -1942,6 +2006,7 @@ START_TEST(exception)
@@ -2046,6 +2110,7 @@ START_TEST(exception)
test_debug_registers();
test_outputdebugstring(1, FALSE);
test_ripevent(1);
+ test_closehandle(0);
@ -180,5 +180,5 @@ index 5cbab71..7a97ae5 100644
test_virtual_unwind();
--
2.1.3
2.6.4

View File

@ -1,4 +1,4 @@
From 51935986a1e973ab26dc3035905a47e1f19c6062 Mon Sep 17 00:00:00 2001
From 090cf9addeea643d624b4b7c3a6b0fbc04c9c253 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 Sep 2014 23:39:51 +0200
Subject: ntdll: OutputDebugString should throw the exception a second time, if
@ -38,10 +38,10 @@ index d4d66b2..981661b 100644
if (!mutex_inited)
{
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 7a97ae5..b0f0fac 100644
index 98d73f4..f9dd95d 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -1727,7 +1727,7 @@ static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *Exce
@@ -1829,7 +1829,7 @@ static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *Exce
return EXCEPTION_CONTINUE_SEARCH;
}
@ -50,7 +50,7 @@ index 7a97ae5..b0f0fac 100644
{
PVOID vectored_handler;
@@ -1742,13 +1742,8 @@ static void test_outputdebugstring(DWORD numexc, BOOL todo)
@@ -1844,13 +1844,8 @@ static void test_outputdebugstring(DWORD numexc, BOOL todo)
outputdebugstring_exceptions = 0;
OutputDebugStringA("Hello World");
@ -66,7 +66,7 @@ index 7a97ae5..b0f0fac 100644
pRtlRemoveVectoredExceptionHandler(vectored_handler);
}
@@ -1962,9 +1957,9 @@ START_TEST(exception)
@@ -2064,9 +2059,9 @@ START_TEST(exception)
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
test_stage = 3;
@ -78,24 +78,24 @@ index 7a97ae5..b0f0fac 100644
test_stage = 5;
test_ripevent(0);
test_stage = 6;
@@ -1984,7 +1979,7 @@ START_TEST(exception)
test_unwind();
@@ -2087,7 +2082,7 @@ START_TEST(exception)
test_exceptions();
test_rtlraiseexception();
test_debug_registers();
- test_outputdebugstring(1, FALSE);
+ test_outputdebugstring(1);
test_ripevent(1);
test_closehandle(0);
test_vectored_continue_handler();
@@ -2004,7 +1999,7 @@ START_TEST(exception)
pRtlLookupFunctionEntry = (void *)GetProcAddress( hntdll,
@@ -2108,7 +2103,7 @@ START_TEST(exception)
"RtlLookupFunctionEntry" );
test_debug_registers();
- test_outputdebugstring(1, FALSE);
+ test_outputdebugstring(1);
test_ripevent(1);
test_closehandle(0);
test_vectored_continue_handler();
--
2.1.3
2.6.4

View File

@ -0,0 +1 @@
Depends: ntdll-x86_64_set_cpu_context

View File

@ -1,14 +1,14 @@
From f70ddf43d18cfeae70f0021005048c628b08c2b3 Mon Sep 17 00:00:00 2001
From abaac4383f22f06b4d6e703d243f30de4bf90229 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 29 Nov 2015 00:34:04 +0100
Subject: ntdll: Allow to set debug registers separately in NtSetContextThread.
---
dlls/ntdll/signal_x86_64.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
dlls/ntdll/signal_x86_64.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 524de68..abe2072 100644
index 524de68..02710a4 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -1800,11 +1800,12 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext,
@ -26,7 +26,7 @@ index 524de68..abe2072 100644
"subq $40,%rsp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 40\n\t")
"ldmxcsr 0x34(%rdi)\n\t" /* context->MxCsr */
@@ -1852,6 +1853,29 @@ __ASM_GLOBAL_FUNC( set_cpu_context,
@@ -1852,6 +1853,25 @@ __ASM_GLOBAL_FUNC( set_cpu_context,
"movq 0xb0(%rdi),%rdi\n\t" /* context->Rdi */
"iretq" );
@ -39,10 +39,6 @@ index 524de68..abe2072 100644
+void set_cpu_context( const CONTEXT *context )
+{
+ DWORD flags = context->ContextFlags & ~CONTEXT_AMD64;
+
+ if (flags & CONTEXT_DEBUG_REGISTERS)
+ FIXME( "setting debug registers not supported\n" );
+
+ if (flags & CONTEXT_FULL)
+ {
+ if (!(flags & CONTEXT_CONTROL))
@ -57,5 +53,5 @@ index 524de68..abe2072 100644
* copy_context
*
--
2.6.2
2.6.4

View File

@ -0,0 +1,29 @@
From 71095e2e64ba74798bc037ad25ec9a14d59dbd4b Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 28 Dec 2015 01:59:47 +0100
Subject: ntdll: Receive debug registers from server on x86_64.
---
dlls/ntdll/thread.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index aaf7a71..1455eb1 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -830,9 +830,11 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
DWORD needed_flags = context->ContextFlags;
BOOL self = (handle == GetCurrentThread());
+ /* on i386/amd64 debug registers always require a server call */
#ifdef __i386__
- /* on i386 debug registers always require a server call */
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) self = FALSE;
+#elif defined(__x86_64__)
+ if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE;
#endif
if (!self)
--
2.6.4

View File

@ -0,0 +1,117 @@
From 2db0a83315fbe9f84369f0123ad1b5f27a4b202e Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 28 Dec 2015 03:00:56 +0100
Subject: ntdll/tests: Add tests for setting debug registers with
NtSetContextThread.
---
dlls/ntdll/tests/exception.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index a368997..f355513 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -1723,6 +1723,83 @@ static void test_dynamic_unwind(void)
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
+
+static void test_debug_registers(void)
+{
+ NTSTATUS status;
+ CONTEXT ctx, ctx2;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ ctx2.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ ctx.Dr0 = 0x42424240;
+ ctx.Dr2 = 0x126bb070;
+ ctx.Dr3 = 0x0badbad0;
+ ctx.Dr7 = 0xffff0115;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %08x\n", status);
+ status = pNtGetContextThread(GetCurrentThread(), &ctx2);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+ ctx2.Dr6 &= 0xf00f; ctx2.Dr7 &= ~0xdc00;
+ ok(ctx2.Dr0 == ctx.Dr0, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr0, (DWORD_PTR)ctx2.Dr0);
+ ok(ctx2.Dr1 == ctx.Dr1, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr1, (DWORD_PTR)ctx2.Dr1);
+ ok(ctx2.Dr2 == ctx.Dr2, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr2, (DWORD_PTR)ctx2.Dr2);
+ ok(ctx2.Dr3 == ctx.Dr3, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr3, (DWORD_PTR)ctx2.Dr3);
+ ok(ctx2.Dr6 == ctx.Dr6, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr6, (DWORD_PTR)ctx2.Dr6);
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+
+ ctx.Dr0 = 0x42424242;
+ ctx.Dr2 = 0x100f0fe7;
+ ctx.Dr3 = 0x0abebabe;
+ ctx.Dr7 = 0x115;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %08x\n", status);
+ status = pNtGetContextThread(GetCurrentThread(), &ctx2);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+ ctx2.Dr6 &= 0xf00f; ctx2.Dr7 &= ~0xdc00;
+ ok(ctx2.Dr0 == ctx.Dr0, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr0, (DWORD_PTR)ctx2.Dr0);
+ ok(ctx2.Dr1 == ctx.Dr1, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr1, (DWORD_PTR)ctx2.Dr1);
+ ok(ctx2.Dr2 == ctx.Dr2, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr2, (DWORD_PTR)ctx2.Dr2);
+ ok(ctx2.Dr3 == ctx.Dr3, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr3, (DWORD_PTR)ctx2.Dr3);
+ ok(ctx2.Dr6 == ctx.Dr6, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr6, (DWORD_PTR)ctx2.Dr6);
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+
+ /* setting Gx flags is not allowed */
+ ctx.Dr7 |= 0xaa;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %08x\n", status);
+ status = pNtGetContextThread(GetCurrentThread(), &ctx2);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+ ctx.Dr7 &= ~0xaa; ctx2.Dr7 &= ~0xdc00;
+todo_wine
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+
+ /* setting GE flag is not allowed on 32-bit, but on 64-bit */
+ ctx.Dr7 |= 0x200;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %08x\n", status);
+ status = pNtGetContextThread(GetCurrentThread(), &ctx2);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+#ifdef __i386__
+ ctx.Dr7 &= ~0x200; ctx2.Dr7 &= ~0xdc00;
+todo_wine
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+#else
+ ctx2.Dr7 &= ~0xdc00;
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+#endif
+
+ /* clearing LE flag is allowed */
+ ctx.Dr7 &= ~0x100;
+ status = pNtSetContextThread(GetCurrentThread(), &ctx);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %08x\n", status);
+ status = pNtGetContextThread(GetCurrentThread(), &ctx2);
+ ok(status == STATUS_SUCCESS, "NtGetContextThread failed with %x\n", status);
+ ctx2.Dr7 &= ~0xdc00;
+ ok(ctx2.Dr7 == ctx.Dr7, "expected %lx, got %lx\n", (DWORD_PTR)ctx.Dr7, (DWORD_PTR)ctx2.Dr7);
+}
+
static DWORD outputdebugstring_exceptions;
static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
@@ -1946,6 +2023,7 @@ START_TEST(exception)
test_unwind();
test_exceptions();
test_rtlraiseexception();
+ test_debug_registers();
test_outputdebugstring(1, FALSE);
test_ripevent(1);
test_vectored_continue_handler();
@@ -1965,6 +2043,7 @@ START_TEST(exception)
pRtlLookupFunctionEntry = (void *)GetProcAddress( hntdll,
"RtlLookupFunctionEntry" );
+ test_debug_registers();
test_outputdebugstring(1, FALSE);
test_ripevent(1);
test_vectored_continue_handler();
--
2.6.4

View File

@ -1962,6 +1962,13 @@ if test "$enable_ntdll_NtQueryEaFile" -eq 1; then
enable_ntdll_Syscall_Wrappers=1
fi
if test "$enable_ntdll_Exception" -eq 1; then
if test "$enable_ntdll_x86_64_set_cpu_context" -gt 1; then
abort "Patchset ntdll-x86_64_set_cpu_context disabled, but ntdll-Exception depends on that."
fi
enable_ntdll_x86_64_set_cpu_context=1
fi
if test "$enable_ntdll_DllRedirects" -eq 1; then
if test "$enable_ntdll_DllOverrides_WOW64" -gt 1; then
abort "Patchset ntdll-DllOverrides_WOW64 disabled, but ntdll-DllRedirects depends on that."
@ -4148,8 +4155,30 @@ if test "$enable_ntdll_DllRedirects" -eq 1; then
) >> "$patchlist"
fi
# Patchset ntdll-x86_64_set_cpu_context
# |
# | This patchset fixes the following Wine bugs:
# | * [#39454] Allow to set debug registers separately in NtSetContextThread
# |
# | Modified files:
# | * dlls/ntdll/signal_x86_64.c, dlls/ntdll/tests/exception.c, dlls/ntdll/thread.c
# |
if test "$enable_ntdll_x86_64_set_cpu_context" -eq 1; then
patch_apply ntdll-x86_64_set_cpu_context/0001-ntdll-Allow-to-set-debug-registers-separately-in-NtS.patch
patch_apply ntdll-x86_64_set_cpu_context/0002-ntdll-Receive-debug-registers-from-server-on-x86_64.patch
patch_apply ntdll-x86_64_set_cpu_context/0003-ntdll-tests-Add-tests-for-setting-debug-registers-wi.patch
(
echo '+ { "Sebastian Lackner", "ntdll: Allow to set debug registers separately in NtSetContextThread.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Receive debug registers from server on x86_64.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for setting debug registers with NtSetContextThread.", 1 },';
) >> "$patchlist"
fi
# Patchset ntdll-Exception
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * ntdll-x86_64_set_cpu_context
# |
# | Modified files:
# | * dlls/kernel32/debugger.c, dlls/ntdll/om.c, dlls/ntdll/tests/exception.c
# |
@ -4439,7 +4468,7 @@ fi
# Patchset ntdll-SystemRoot_Symlink
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * ntdll-Exception, ntdll-Syscall_Wrappers
# | * ntdll-x86_64_set_cpu_context, ntdll-Exception, ntdll-Syscall_Wrappers
# |
# | Modified files:
# | * dlls/ntdll/om.c
@ -4549,21 +4578,6 @@ if test "$enable_ntdll_Zero_mod_name" -eq 1; then
) >> "$patchlist"
fi
# Patchset ntdll-x86_64_set_cpu_context
# |
# | This patchset fixes the following Wine bugs:
# | * [#39454] Allow to set debug registers separately in NtSetContextThread
# |
# | Modified files:
# | * dlls/ntdll/signal_x86_64.c
# |
if test "$enable_ntdll_x86_64_set_cpu_context" -eq 1; then
patch_apply ntdll-x86_64_set_cpu_context/0001-ntdll-Allow-to-set-debug-registers-separately-in-NtS.patch
(
echo '+ { "Sebastian Lackner", "ntdll: Allow to set debug registers separately in NtSetContextThread.", 1 },';
) >> "$patchlist"
fi
# Patchset ntoskrnl-DriverTest
# |
# | Modified files:

View File

@ -1,4 +1,5 @@
wine-staging (1.9.0) UNRELEASED; urgency=low
* Updated patch for x86_64 set_cpu_context implementation and add tests.
* Added patch to align terminating null WCHAR in SysAllocStringByteLen.
* Added patch to avoid corruption of caret when SetCaretPos() is called.
* Added patch to avoid setting error when NULL is passed to SHMapHandle.