Module: wine Branch: master Commit: 5bfbcb735bd05a5df9a8d7e96d832b3c1205b45f URL: https://source.winehq.org/git/wine.git/?a=commit;h=5bfbcb735bd05a5df9a8d7e96...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Feb 1 16:28:16 2019 +0100
ntoskrnl.exe: Implement KeExpandKernelStackAndCallout and KeExpandKernelStackAndCalloutEx.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntoskrnl.exe/ntoskrnl.c | 19 +++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 + dlls/ntoskrnl.exe/tests/driver.c | 84 +++++++++++++++++++++++++++++++++++-- include/ddk/ntddk.h | 3 ++ 4 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 298247b..f21d6f7 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2308,6 +2308,25 @@ VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject) }
/*********************************************************************** + * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size, + BOOLEAN wait, void *context) +{ + WARN("(%p %p %lu %x %p) semi-stub: ignoring stack expand\n", callout, parameter, size, wait, context); + callout(parameter); + return STATUS_SUCCESS; +} + +/*********************************************************************** + * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size) +{ + return KeExpandKernelStackAndCalloutEx(callout, parameter, size, TRUE, NULL); +} + +/*********************************************************************** * IoUnregisterFileSystem (NTOSKRNL.EXE.@) */ VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index df2f15b..40f5b27 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -44,6 +44,8 @@ @ stdcall -arch=arm,arm64,x86_64 KeAcquireInStackQueuedSpinLock(ptr ptr) @ stdcall -norelay KeAcquireInStackQueuedSpinLockAtDpcLevel(ptr ptr) @ stdcall KeEnterGuardedRegion() +@ stdcall KeExpandKernelStackAndCallout(ptr ptr long) +@ stdcall KeExpandKernelStackAndCalloutEx(ptr ptr long long ptr) @ stdcall KeLeaveGuardedRegion() @ stdcall -arch=arm,arm64,x86_64 KeReleaseInStackQueuedSpinLock(ptr) @ stdcall -norelay KeReleaseInStackQueuedSpinLockFromDpcLevel(ptr) diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 5c34b41..cbf8bdc 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -28,6 +28,7 @@ #include "winbase.h" #include "winternl.h" #include "winioctl.h" +#include "ddk/ntddk.h" #include "ddk/wdm.h"
#include "driver.h" @@ -68,10 +69,9 @@ static void WINAPIV kprintf(const char *format, ...) __ms_va_end(valist); }
-static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) +static void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) { const char *current_file; - __ms_va_list args;
if (!(current_file = drv_strrchr(file, '/')) && !(current_file = drv_strrchr(file, '\'))) @@ -79,7 +79,6 @@ static void WINAPIV ok_(const char *file, int line, int condition, const char *m else current_file++;
- __ms_va_start(args, msg); if (todo_level) { if (condition) @@ -113,6 +112,39 @@ static void WINAPIV ok_(const char *file, int line, int condition, const char *m InterlockedIncrement(&successes); } } +} + +static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + vok_(file, line, condition, msg, args); + __ms_va_end(args); +} + +void vskip_(const char *file, int line, const char *msg, __ms_va_list args) +{ + const char *current_file; + + if (!(current_file = drv_strrchr(file, '/')) && + !(current_file = drv_strrchr(file, '\'))) + current_file = file; + else + current_file++; + + kprintf("%s:%d: Tests skipped: ", current_file, line); + kvprintf(msg, args); + skipped++; +} + +void WINAPIV win_skip_(const char *file, int line, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + if (running_under_wine) + vok_(file, line, 0, msg, args); + else + vskip_(file, line, msg, args); __ms_va_end(args); }
@@ -140,6 +172,7 @@ static void winetest_end_todo(void) winetest_end_todo()) #define todo_wine todo_if(running_under_wine) #define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine) +#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__)
static void test_currentprocess(void) { @@ -498,6 +531,50 @@ static void test_sync(void) KeCancelTimer(&timer); }
+static int callout_cnt; + +static void WINAPI callout(void *parameter) +{ + ok(parameter == (void*)0xdeadbeef, "parameter = %p\n", parameter); + callout_cnt++; +} + +static void test_stack_callout(void) +{ + NTSTATUS (WINAPI *pKeExpandKernelStackAndCallout)(PEXPAND_STACK_CALLOUT,void*,SIZE_T); + NTSTATUS (WINAPI *pKeExpandKernelStackAndCalloutEx)(PEXPAND_STACK_CALLOUT,void*,SIZE_T,BOOLEAN,void*); + UNICODE_STRING str; + NTSTATUS ret; + + static const WCHAR KeExpandKernelStackAndCalloutW[] = + {'K','e','E','x','p','a','n','d','K','e','r','n','e','l','S','t','a','c','k','A','n','d','C','a','l','l','o','u','t',0}; + static const WCHAR KeExpandKernelStackAndCalloutExW[] = + {'K','e','E','x','p','a','n','d','K','e','r','n','e','l','S','t','a','c','k','A','n','d','C','a','l','l','o','u','t','E','x',0}; + + + RtlInitUnicodeString(&str, KeExpandKernelStackAndCalloutW); + pKeExpandKernelStackAndCallout = MmGetSystemRoutineAddress(&str); + if (pKeExpandKernelStackAndCallout) + { + callout_cnt = 0; + ret = pKeExpandKernelStackAndCallout(callout, (void*)0xdeadbeef, 4096); + ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCallout failed: %#x\n", ret); + ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt); + } + else win_skip("KeExpandKernelStackAndCallout is not available\n"); + + RtlInitUnicodeString(&str, KeExpandKernelStackAndCalloutExW); + pKeExpandKernelStackAndCalloutEx = MmGetSystemRoutineAddress(&str); + if (pKeExpandKernelStackAndCalloutEx) + { + callout_cnt = 0; + ret = pKeExpandKernelStackAndCalloutEx(callout, (void*)0xdeadbeef, 4096, FALSE, NULL); + ok(ret == STATUS_SUCCESS, "KeExpandKernelStackAndCalloutEx failed: %#x\n", ret); + ok(callout_cnt == 1, "callout_cnt = %u\n", callout_cnt); + } + else win_skip("KeExpandKernelStackAndCalloutEx is not available\n"); +} + static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -527,6 +604,7 @@ static NTSTATUS main_test(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *info) test_init_funcs(); test_load_driver(); test_sync(); + test_stack_callout();
/* print process report */ if (test_input->winetest_debug) diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index dc051e1..452e510 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -200,11 +200,14 @@ typedef VOID (WINAPI *PDRIVER_REINITIALIZE)(PDRIVER_OBJECT,PVOID,ULONG); typedef VOID (WINAPI *PLOAD_IMAGE_NOTIFY_ROUTINE)(PUNICODE_STRING,HANDLE,PIMAGE_INFO); typedef NTSTATUS (WINAPI *PIO_QUERY_DEVICE_ROUTINE)(PVOID,PUNICODE_STRING,INTERFACE_TYPE,ULONG, PKEY_VALUE_FULL_INFORMATION*,CONFIGURATION_TYPE,ULONG,PKEY_VALUE_FULL_INFORMATION*); +typedef void (NTAPI EXPAND_STACK_CALLOUT)(void*); +typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT;
NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE,PULONG,PCONFIGURATION_TYPE,PULONG, PCONFIGURATION_TYPE,PULONG,PIO_QUERY_DEVICE_ROUTINE,PVOID); void WINAPI IoRegisterDriverReinitialization(PDRIVER_OBJECT,PDRIVER_REINITIALIZE,PVOID); NTSTATUS WINAPI IoRegisterShutdownNotification(PDEVICE_OBJECT); +NTSTATUS WINAPI KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT,void*,SIZE_T); void WINAPI KeSetTargetProcessorDpc(PRKDPC,CCHAR); BOOLEAN WINAPI MmIsAddressValid(void *); NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE);