ntoskrnl.exe: Implement ZwLoadDriver and ZwUnloadDriver based on services API.
Sebastian Lackner
sebastian at fds-team.de
Mon Aug 22 09:12:53 CDT 2016
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
This hides the complicated services API behind some easy to use functions :)
The timeout are a bit arbitrary and can be adjusted if they do not work well
enough in practice. Based on Arics feedback this solution is confirmed to work
for his purpose.
dlls/ntoskrnl.exe/Makefile.in | 1
dlls/ntoskrnl.exe/ntoskrnl.c | 164 ++++++++++++++++++++++++++++++++++++
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4
3 files changed, 167 insertions(+), 2 deletions(-)
diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in
index 875be8e..b459c54 100644
--- a/dlls/ntoskrnl.exe/Makefile.in
+++ b/dlls/ntoskrnl.exe/Makefile.in
@@ -1,5 +1,6 @@
MODULE = ntoskrnl.exe
IMPORTLIB = ntoskrnl
+IMPORTS = advapi32
C_SRCS = \
instr.c \
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index d9ebc40..fab767f 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007 Alexandre Julliard
* Copyright (C) 2010 Damjan Jovanovic
+ * Copyright (C) 2016 Sebastian Lackner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,6 +31,7 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
+#include "winsvc.h"
#include "winternl.h"
#include "excpt.h"
#include "winioctl.h"
@@ -2641,3 +2643,165 @@ NTSTATUS WINAPI IoAttachDevice(DEVICE_OBJECT *source, UNICODE_STRING *target, DE
FIXME("(%p, %s, %p): stub\n", source, debugstr_us(target), attached);
return STATUS_NOT_IMPLEMENTED;
}
+
+
+static NTSTATUS open_driver( const UNICODE_STRING *driver_name, SC_HANDLE *service )
+{
+ QUERY_SERVICE_CONFIGW *service_config = NULL;
+ SC_HANDLE manager_handle;
+ DWORD config_size = 0;
+ WCHAR *name;
+
+ if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
+ {
+ WARN( "failed to connect to service manager\n" );
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, driver_name->Length + sizeof(WCHAR) )))
+ {
+ CloseServiceHandle( manager_handle );
+ return STATUS_NO_MEMORY;
+ }
+
+ memcpy( name, driver_name->Buffer, driver_name->Length );
+ name[ driver_name->Length/sizeof(WCHAR) ] = 0;
+ *service = OpenServiceW( manager_handle, name, SERVICE_ALL_ACCESS );
+ HeapFree( GetProcessHeap(), 0, name );
+ CloseServiceHandle( manager_handle );
+
+ if (!*service)
+ {
+ WARN( "failed to open service %s\n", debugstr_us(driver_name) );
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ QueryServiceConfigW( *service, NULL, 0, &config_size );
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ WARN( "failed to query service config\n" );
+ goto error;
+ }
+
+ if (!(service_config = RtlAllocateHeap( GetProcessHeap(), 0, config_size )))
+ goto error;
+
+ if (!QueryServiceConfigW( *service, service_config, config_size, &config_size ))
+ {
+ WARN( "failed to query service config\n" );
+ goto error;
+ }
+
+ if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER &&
+ service_config->dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)
+ {
+ WARN( "service %s is not a kernel driver\n", debugstr_us(driver_name) );
+ goto error;
+ }
+
+ TRACE( "opened service for driver %s\n", debugstr_us(driver_name) );
+ RtlFreeHeap( GetProcessHeap(), 0, service_config );
+ return STATUS_SUCCESS;
+
+error:
+ CloseServiceHandle( *service );
+ RtlFreeHeap( GetProcessHeap(), 0, service_config );
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+/***********************************************************************
+ * ZwLoadDriver (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *driver_name )
+{
+ SERVICE_STATUS_PROCESS service_status;
+ SC_HANDLE service_handle;
+ NTSTATUS status;
+ DWORD bytes;
+ int i;
+
+ TRACE( "(%s)\n", debugstr_us(driver_name) );
+
+ if ((status = open_driver( driver_name, &service_handle )) != STATUS_SUCCESS)
+ return status;
+
+ TRACE( "trying to start %s\n", debugstr_us(driver_name) );
+
+ for (i = 0; i < 100; i++) /* 10 sec timeout */
+ {
+ if (StartServiceW( service_handle, 0, NULL )) break;
+ if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) break;
+ if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) goto error;
+ Sleep(100);
+ }
+ if (i == 100) goto error;
+
+ for (i = 0; i < 100; i++) /* 10 sec timeout */
+ {
+ if (!QueryServiceStatusEx( service_handle, SC_STATUS_PROCESS_INFO,
+ (BYTE *)&service_status, sizeof(service_status), &bytes )) goto error;
+ if (service_status.dwCurrentState != SERVICE_START_PENDING) break;
+ Sleep(100);
+ }
+
+ if (service_status.dwCurrentState == SERVICE_RUNNING)
+ {
+ if (service_status.dwProcessId != GetCurrentProcessId())
+ FIXME( "driver %s was loaded into a different process\n", debugstr_us(driver_name) );
+
+ status = STATUS_SUCCESS;
+ goto done;
+ }
+
+error:
+ WARN( "failed to start service %s\n", debugstr_us(driver_name) );
+ status = STATUS_UNSUCCESSFUL;
+
+done:
+ TRACE( "returning status %08x\n", status );
+ CloseServiceHandle( service_handle );
+ return status;
+}
+
+
+/***********************************************************************
+ * ZwUnloadDriver (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI ZwUnloadDriver( const UNICODE_STRING *driver_name )
+{
+ SERVICE_STATUS service_status;
+ SC_HANDLE service_handle;
+ NTSTATUS status;
+ int i;
+
+ TRACE( "(%s)\n", debugstr_us(driver_name) );
+
+ if ((status = open_driver( driver_name, &service_handle )) != STATUS_SUCCESS)
+ return status;
+
+ if (!ControlService( service_handle, SERVICE_CONTROL_STOP, &service_status ))
+ goto error;
+
+ for (i = 0; i < 100; i++) /* 10 sec timeout */
+ {
+ if (!QueryServiceStatus( service_handle, &service_status )) goto error;
+ if (service_status.dwCurrentState != SERVICE_STOP_PENDING) break;
+ Sleep(100);
+ }
+
+ if (service_status.dwCurrentState == SERVICE_STOPPED)
+ {
+ status = STATUS_SUCCESS;
+ goto done;
+ }
+
+error:
+ WARN( "failed to stop service %s\n", debugstr_us(driver_name) );
+ status = STATUS_UNSUCCESSFUL;
+
+done:
+ TRACE( "returning status %08x\n", status );
+ CloseServiceHandle( service_handle );
+ return status;
+}
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 5acfe6f..5408e91 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1314,7 +1314,7 @@
@ stdcall ZwFsControlFile(long long long long long long long long long long) ntdll.ZwFsControlFile
@ stdcall ZwInitiatePowerAction(long long long long) ntdll.ZwInitiatePowerAction
@ stdcall ZwIsProcessInJob(long long) ntdll.ZwIsProcessInJob
-@ stdcall ZwLoadDriver(ptr) ntdll.ZwLoadDriver
+@ stdcall ZwLoadDriver(ptr)
@ stdcall ZwLoadKey(ptr ptr) ntdll.ZwLoadKey
@ stdcall ZwMakeTemporaryObject(long) ntdll.ZwMakeTemporaryObject
@ stdcall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) ntdll.ZwMapViewOfSection
@@ -1384,7 +1384,7 @@
@ stdcall ZwTerminateJobObject(long long) ntdll.ZwTerminateJobObject
@ stdcall ZwTerminateProcess(long long) ntdll.ZwTerminateProcess
@ stub ZwTranslateFilePath
-@ stdcall ZwUnloadDriver(ptr) ntdll.ZwUnloadDriver
+@ stdcall ZwUnloadDriver(ptr)
@ stdcall ZwUnloadKey(long) ntdll.ZwUnloadKey
@ stdcall ZwUnmapViewOfSection(long ptr) ntdll.ZwUnmapViewOfSection
@ stdcall ZwWaitForMultipleObjects(long ptr long long ptr) ntdll.ZwWaitForMultipleObjects
--
2.9.0
More information about the wine-patches
mailing list