Sebastian Lackner : ntoskrnl.exe: Implement ZwLoadDriver and ZwUnloadDriver based on services API.
Alexandre Julliard
julliard at winehq.org
Thu Aug 25 10:39:37 CDT 2016
Module: wine
Branch: master
Commit: a7e9fa625327a4f50d25053e092783a7e82f8584
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a7e9fa625327a4f50d25053e092783a7e82f8584
Author: Sebastian Lackner <sebastian at fds-team.de>
Date: Wed Aug 24 06:11:07 2016 +0200
ntoskrnl.exe: Implement ZwLoadDriver and ZwUnloadDriver based on services API.
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntoskrnl.exe/Makefile.in | 1 +
dlls/ntoskrnl.exe/ntoskrnl.c | 183 ++++++++++++++++++++++++++++++++++--
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 +-
3 files changed, 180 insertions(+), 8 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..7c35d14 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"
@@ -66,6 +68,13 @@ KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
+static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
+ '\\','M','a','c','h','i','n','e',
+ '\\','S','y','s','t','e','m',
+ '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
+ '\\','S','e','r','v','i','c','e','s',
+ '\\',0};
+
/* tid of the thread running client request */
static DWORD request_thread;
@@ -871,12 +880,6 @@ PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device,
static void build_driver_keypath( const WCHAR *name, UNICODE_STRING *keypath )
{
static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
- static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
- '\\','M','a','c','h','i','n','e',
- '\\','S','y','s','t','e','m',
- '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
- '\\','S','e','r','v','i','c','e','s',
- '\\',0};
WCHAR *str;
/* Check what prefix is present */
@@ -2641,3 +2644,171 @@ 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 *service_name, SC_HANDLE *service )
+{
+ QUERY_SERVICE_CONFIGW *service_config = NULL;
+ SC_HANDLE manager_handle;
+ DWORD config_size = 0;
+ WCHAR *name;
+
+ if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, service_name->Length + sizeof(WCHAR) )))
+ return STATUS_NO_MEMORY;
+
+ memcpy( name, service_name->Buffer, service_name->Length );
+ name[ service_name->Length / sizeof(WCHAR) ] = 0;
+
+ if (strncmpW( name, servicesW, strlenW(servicesW) ))
+ {
+ FIXME( "service name %s is not a keypath\n", debugstr_us(service_name) );
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
+ {
+ WARN( "failed to connect to service manager\n" );
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ *service = OpenServiceW( manager_handle, name + strlenW(servicesW), SERVICE_ALL_ACCESS );
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ CloseServiceHandle( manager_handle );
+
+ if (!*service)
+ {
+ WARN( "failed to open service %s\n", debugstr_us(service_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(service_name) );
+ goto error;
+ }
+
+ TRACE( "opened service for driver %s\n", debugstr_us(service_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 *service_name )
+{
+ SERVICE_STATUS_PROCESS service_status;
+ SC_HANDLE service_handle;
+ NTSTATUS status;
+ DWORD bytes;
+ int i;
+
+ TRACE( "(%s)\n", debugstr_us(service_name) );
+
+ if ((status = open_driver( service_name, &service_handle )) != STATUS_SUCCESS)
+ return status;
+
+ TRACE( "trying to start %s\n", debugstr_us(service_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(service_name) );
+
+ status = STATUS_SUCCESS;
+ goto done;
+ }
+
+error:
+ WARN( "failed to start service %s\n", debugstr_us(service_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 *service_name )
+{
+ SERVICE_STATUS service_status;
+ SC_HANDLE service_handle;
+ NTSTATUS status;
+ int i;
+
+ TRACE( "(%s)\n", debugstr_us(service_name) );
+
+ if ((status = open_driver( service_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(service_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 fd820a7..119d406 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
More information about the wine-cvs
mailing list