ntoskrnl.exe: Implement ZwLoadDriver and ZwUnloadDriver based on services API. (v2)
Aric Stewart
aric at codeweavers.com
Wed Aug 24 07:05:09 CDT 2016
Signed-off-by: Aric Stewart <aric at codeweavers.com>
On 8/23/16 11:11 PM, Sebastian Lackner wrote:
> Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
> ---
>
> Changes in v2:
> * Expect service name including registry prefix.
>
> 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 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