On 22.01.2016 19:15, Aric Stewart wrote:
Code is mostly moved from winedevice.exe winedevice.exe now uses these functions v3: No longer use advapi32 Registry functions v4: Fix FALSE return code (thanks to Huw Davies for spotting this one) Remove WINE_ from debuging macros
Signed-off-by: Aric Stewart aric@codeweavers.com
dlls/ntoskrnl.exe/ntoskrnl.c | 306 ++++++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 +- programs/winedevice/device.c | 243 +--------------------------- 3 files changed, 313 insertions(+), 240 deletions(-)
I don't think moving the loader code from winedevice to ntoskrnl.exe is a good idea, at least not without further changes, because:
* We should not initialize the same driver twice, the second initialization could fail because of namespace collisions.
* Drivers should be properly uninitialized, no matter how they were loaded.
* In theory, all drivers should be loaded into the same address space. This means, winedevice and the wineserver has to keep track of them, and its not sufficient to maintain a list in ntoskrnl.exe.
Besides those design issues, I've marked a couple of other issues in the patch below.
0001-ntoskrnl.exe-Implement-ZwLoadDriver-and-ZwUnloadDriver.txt
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 04f0198..032ab21 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -72,6 +72,18 @@ static DWORD request_thread; static DWORD client_tid; static DWORD client_pid;
+/* Loaded driver list */ +typedef struct _loaded_driver {
- struct list entry;
- UNICODE_STRING name;
- HMODULE module;
- DRIVER_OBJECT driver_obj;
- DRIVER_EXTENSION driver_extension;
+} loaded_driver;
+struct list loaded_drivers = LIST_INIT(loaded_drivers);
It wouldn't hurt to add locking for such a global list.
#ifdef __i386__ #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \ __ASM_STDCALL_FUNC( name, 4, \ @@ -2407,3 +2419,297 @@ NTSTATUS WINAPI CmUnRegisterCallback(LARGE_INTEGER cookie) FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie.QuadPart)); return STATUS_NOT_IMPLEMENTED; }
+/* find the LDR_MODULE corresponding to the driver module */ +static LDR_MODULE *find_ldr_module( HMODULE module ) +{
- LIST_ENTRY *entry, *list = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
- for (entry = list->Flink; entry != list; entry = entry->Flink)
- {
LDR_MODULE *ldr = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
if (ldr->BaseAddress == module) return ldr;
if (ldr->BaseAddress > (void *)module) break;
- }
The loader lock should be acquired while iterating through this list. (Yes, this is an existing issue, but before it was less critical because the code was single-threaded.)
- return NULL;
+}
+/* load the driver module file */ +static HMODULE load_driver_module( const WCHAR *name ) +{
- IMAGE_NT_HEADERS *nt;
- const IMAGE_IMPORT_DESCRIPTOR *imports;
- SYSTEM_BASIC_INFORMATION info;
- int i;
- INT_PTR delta;
- ULONG size;
- HMODULE module = LoadLibraryW( name );
- if (!module) return NULL;
- nt = RtlImageNtHeader( module );
- if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module;
- /* the loader does not apply relocations to non page-aligned binaries or executables,
* we have to do it ourselves */
- NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
- if (nt->OptionalHeader.SectionAlignment < info.PageSize ||
!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
- {
DWORD old;
IMAGE_BASE_RELOCATION *rel, *end;
if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
{
TRACE( "%s: relocating from %p to %p\n",
wine_dbgstr_w(name), (char *)module - delta, module );
end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
while (rel < end && rel->SizeOfBlock)
{
void *page = (char *)module + rel->VirtualAddress;
VirtualProtect( page, info.PageSize, PAGE_EXECUTE_READWRITE, &old );
rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
(USHORT *)(rel + 1), delta );
if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, &old );
if (!rel) goto error;
}
/* make sure we don't try again */
size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
VirtualProtect( nt, size, PAGE_READWRITE, &old );
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
VirtualProtect( nt, size, old, &old );
}
- }
- /* make sure imports are relocated too */
- if ((imports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
- {
for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
{
char *name = (char *)module + imports[i].Name;
WCHAR buffer[32], *p = buffer;
while (p < buffer + 32) if (!(*p++ = *name++)) break;
if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer ) );
}
- }
- return module;
+error:
- FreeLibrary( module );
- return NULL;
+}
+/* call the driver init entry point */ +static NTSTATUS init_driver( const WCHAR *driver_name, UNICODE_STRING *keyname, loaded_driver *driver ) +{
- unsigned int i;
- NTSTATUS status;
- const IMAGE_NT_HEADERS *nt = RtlImageNtHeader( driver->module );
- if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
- driver->driver_obj.Size = sizeof(driver->driver_obj);
- driver->driver_obj.DriverSection = find_ldr_module( driver->module );
- driver->driver_obj.DriverInit = (PDRIVER_INITIALIZE)((char *)driver->module + nt->OptionalHeader.AddressOfEntryPoint);
- driver->driver_obj.DriverExtension = &driver->driver_extension;
- driver->driver_obj.DriverExtension->DriverObject = &driver->driver_obj;
- driver->driver_obj.DriverExtension->ServiceKeyName = *keyname;
- if (TRACE_ON(relay))
DPRINTF( "%04x:Call driver init %p (obj=%p,str=%s)\n", GetCurrentThreadId(),
driver->driver_obj.DriverInit, &driver->driver_obj, wine_dbgstr_w(keyname->Buffer) );
- status = driver->driver_obj.DriverInit( &driver->driver_obj, keyname );
- if (TRACE_ON(relay))
DPRINTF( "%04x:Ret driver init %p (obj=%p,str=%s) retval=%08x\n", GetCurrentThreadId(),
driver->driver_obj.DriverInit, &driver->driver_obj, wine_dbgstr_w(keyname->Buffer), status );
- TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), &driver->driver_obj );
- TRACE( "- DriverInit = %p\n", driver->driver_obj.DriverInit );
- TRACE( "- DriverStartIo = %p\n", driver->driver_obj.DriverStartIo );
- TRACE( "- DriverUnload = %p\n", driver->driver_obj.DriverUnload );
- for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
TRACE( "- MajorFunction[%d] = %p\n", i, driver->driver_obj.MajorFunction[i] );
- return status;
+}
+/***********************************************************************
ZwLoadDriver (NTOSKRNL.EXE.@)
- */
+NTSTATUS WINAPI ZwLoadDriver(const UNICODE_STRING *DriverServiceName)
Both the Nt* and Zw* function should do the same, so I would suggest to implement Nt* instead and forward Zw*, like its done in ntdll.
+{
- static const WCHAR driversW[] = {'\','d','r','i','v','e','r','s','\',0};
- static const WCHAR systemrootW[] = {'\','S','y','s','t','e','m','R','o','o','t','\',0};
- static const WCHAR postfixW[] = {'.','s','y','s',0};
- static const WCHAR ntprefixW[] = {'\','?','?','\',0};
- static const WCHAR ImagePathW[] = {'I','m','a','g','e','P','a','t','h',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};
- UNICODE_STRING keypath, reg_str;
- HMODULE module;
- LPWSTR path = NULL, str;
- DWORD size;
- HANDLE driver_hkey;
- OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
- char buffer[256];
- KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
The initialization here looks unnecessary.
- static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
- loaded_driver *driver;
- /* Check if driver is already loaded */
- LIST_FOR_EACH_ENTRY(driver, &loaded_drivers, loaded_driver, entry)
- {
if (RtlEqualUnicodeString(DriverServiceName, &driver->name, FALSE))
return ERROR_SUCCESS;
- }
- str = HeapAlloc(GetProcessHeap(), 0, sizeof(servicesW) + DriverServiceName->Length*sizeof(WCHAR));
Length is the length in bytes, so the calculation above is wrong.
- lstrcpyW(str, servicesW);
- lstrcatW(str, DriverServiceName->Buffer);
I don't think you can assume a terminating NULL character.
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.ObjectName = ®_str;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString(®_str, str);
- status = NtCreateKey(&driver_hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL);
- if (status != STATUS_SUCCESS)
- {
ERR("cannot open key %s, err=0x%x\n", wine_dbgstr_w(str), status);
HeapFree(GetProcessHeap(), 0, str);
return status;
- }
- RtlInitUnicodeString(&keypath, str);
- /* read the executable path from memory */
- size = 0;
- RtlInitUnicodeString(®_str, ImagePathW);
- status = NtQueryValueKey(driver_hkey, ®_str, KeyValuePartialInformation, buffer, info_size, &size);
- if (status == STATUS_BUFFER_OVERFLOW)
- {
str = HeapAlloc(GetProcessHeap(), 0, size);
str was already set before, so this might leak memory, at least on some exit paths.
info = (KEY_VALUE_PARTIAL_INFORMATION *) str;
status = NtQueryValueKey(driver_hkey, ®_str, KeyValuePartialInformation, str, size, &size);
if (status == STATUS_SUCCESS)
{
size = ExpandEnvironmentStringsW((LPCWSTR)info->Data,NULL,0);
path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
ExpandEnvironmentStringsW((LPCWSTR)info->Data,path,size);
}
HeapFree(GetProcessHeap(), 0, str);
if (!path)
{
TRACE("Failed to load driver path(0x%x): %s\n", status,
wine_dbgstr_w((LPCWSTR)info->Data));
info->Data points into str, which was deallocated just before.
NtClose(driver_hkey);
return status;
}
if (!strncmpiW(path, systemrootW, 12))
{
WCHAR buffer[MAX_PATH];
The variable name is the same as above, which might be misleading.
GetWindowsDirectoryW(buffer, MAX_PATH);
str = HeapAlloc(GetProcessHeap(), 0, (size -11 + strlenW(buffer))
* sizeof(WCHAR));
lstrcpyW(str, buffer);
lstrcatW(str, path + 11);
HeapFree(GetProcessHeap(), 0, path);
path = str;
}
else if (!strncmpW(path, ntprefixW, 4))
str = path + 4;
else
str = path;
- }
- else
- {
/* default is to use the driver name + ".sys" */
WCHAR buffer[MAX_PATH];
GetSystemDirectoryW(buffer, MAX_PATH);
path = HeapAlloc(GetProcessHeap(),0,
(strlenW(buffer) + strlenW(driversW) + DriverServiceName->Length + strlenW(postfixW) + 1)
*sizeof(WCHAR));
Similar to above, ->Length is the length in bytes.
lstrcpyW(path, buffer);
lstrcatW(path, driversW);
lstrcatW(path, DriverServiceName->Buffer);
lstrcatW(path, postfixW);
str = path;
- }
- NtClose(driver_hkey);
- TRACE("loading driver %s\n", wine_dbgstr_w(str));
- module = load_driver_module(str);
- HeapFree(GetProcessHeap(), 0, path);
- if (!module)
return STATUS_NOT_FOUND;
- driver = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*driver));
- driver->module = module;
- RtlDuplicateUnicodeString(1, DriverServiceName, &driver->name);
- init_driver(DriverServiceName->Buffer, &keypath, driver);
- list_add_tail(&loaded_drivers, &driver->entry);
- return STATUS_SUCCESS;
+}
+/***********************************************************************
ZwUnloadDriver (NTOSKRNL.EXE.@)
- */
+NTSTATUS WINAPI ZwUnloadDriver(const UNICODE_STRING *DriverServiceName) +{
- loaded_driver *driver, *ptr;
- LIST_FOR_EACH_ENTRY_SAFE(driver, ptr, &loaded_drivers, loaded_driver, entry)
- {
if (RtlEqualUnicodeString(DriverServiceName, &driver->name, FALSE))
{
list_remove(&driver->entry);
if (driver->driver_obj.DriverUnload)
{
if (TRACE_ON(relay))
DPRINTF("%04x:Call driver unload %p (obj=%p)\n", GetCurrentThreadId(),
driver->driver_obj.DriverUnload, &driver->driver_obj );
driver->driver_obj.DriverUnload( &driver->driver_obj);
if (TRACE_ON(relay))
DPRINTF("%04x:Ret driver unload %p (obj=%p)\n", GetCurrentThreadId(),
driver->driver_obj.DriverUnload, &driver->driver_obj);
}
RtlFreeUnicodeString(&driver->name);
RtlFreeUnicodeString(&driver->driver_extension.ServiceKeyName);
FreeLibrary(driver->module);
HeapFree(GetProcessHeap(), 0, driver);
return STATUS_SUCCESS;
}
- }
- return STATUS_NOT_FOUND;
+} diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 1319ada..a98a523 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 diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c index ef1e1ef..cb6a6ba 100644 --- a/programs/winedevice/device.c +++ b/programs/winedevice/device.c @@ -25,253 +25,19 @@
#include "ntstatus.h" #define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" #include "winternl.h" -#include "winreg.h" -#include "winnls.h" #include "winsvc.h" #include "ddk/wdm.h" #include "wine/unicode.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedevice); -WINE_DECLARE_DEBUG_CHANNEL(relay);
extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event );
static WCHAR *driver_name; static SERVICE_STATUS_HANDLE service_handle; -static HKEY driver_hkey; static HANDLE stop_event; -static DRIVER_OBJECT driver_obj; -static DRIVER_EXTENSION driver_extension;
-/* find the LDR_MODULE corresponding to the driver module */ -static LDR_MODULE *find_ldr_module( HMODULE module ) -{
- LIST_ENTRY *entry, *list = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
- for (entry = list->Flink; entry != list; entry = entry->Flink)
- {
LDR_MODULE *ldr = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
if (ldr->BaseAddress == module) return ldr;
if (ldr->BaseAddress > (void *)module) break;
- }
- return NULL;
-}
-/* load the driver module file */ -static HMODULE load_driver_module( const WCHAR *name ) -{
- IMAGE_NT_HEADERS *nt;
- const IMAGE_IMPORT_DESCRIPTOR *imports;
- SYSTEM_BASIC_INFORMATION info;
- int i;
- INT_PTR delta;
- ULONG size;
- HMODULE module = LoadLibraryW( name );
- if (!module) return NULL;
- nt = RtlImageNtHeader( module );
- if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module;
- /* the loader does not apply relocations to non page-aligned binaries or executables,
* we have to do it ourselves */
- NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
- if (nt->OptionalHeader.SectionAlignment < info.PageSize ||
!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
- {
DWORD old;
IMAGE_BASE_RELOCATION *rel, *end;
if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
{
WINE_TRACE( "%s: relocating from %p to %p\n",
wine_dbgstr_w(name), (char *)module - delta, module );
end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
while (rel < end && rel->SizeOfBlock)
{
void *page = (char *)module + rel->VirtualAddress;
VirtualProtect( page, info.PageSize, PAGE_EXECUTE_READWRITE, &old );
rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
(USHORT *)(rel + 1), delta );
if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, &old );
if (!rel) goto error;
}
/* make sure we don't try again */
size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
VirtualProtect( nt, size, PAGE_READWRITE, &old );
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
VirtualProtect( nt, size, old, &old );
}
- }
- /* make sure imports are relocated too */
- if ((imports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
- {
for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
{
char *name = (char *)module + imports[i].Name;
WCHAR buffer[32], *p = buffer;
while (p < buffer + 32) if (!(*p++ = *name++)) break;
if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer ) );
}
- }
- return module;
-error:
- FreeLibrary( module );
- return NULL;
-}
-/* call the driver init entry point */ -static NTSTATUS init_driver( HMODULE module, UNICODE_STRING *keyname ) -{
- unsigned int i;
- NTSTATUS status;
- const IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module );
- if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
- driver_obj.Size = sizeof(driver_obj);
- driver_obj.DriverSection = find_ldr_module( module );
- driver_obj.DriverInit = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
- driver_obj.DriverExtension = &driver_extension;
- driver_extension.DriverObject = &driver_obj;
- driver_extension.ServiceKeyName = *keyname;
- if (WINE_TRACE_ON(relay))
WINE_DPRINTF( "%04x:Call driver init %p (obj=%p,str=%s)\n", GetCurrentThreadId(),
driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer) );
- status = driver_obj.DriverInit( &driver_obj, keyname );
- if (WINE_TRACE_ON(relay))
WINE_DPRINTF( "%04x:Ret driver init %p (obj=%p,str=%s) retval=%08x\n", GetCurrentThreadId(),
driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer), status );
- WINE_TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), &driver_obj );
- WINE_TRACE( "- DriverInit = %p\n", driver_obj.DriverInit );
- WINE_TRACE( "- DriverStartIo = %p\n", driver_obj.DriverStartIo );
- WINE_TRACE( "- DriverUnload = %p\n", driver_obj.DriverUnload );
- for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
WINE_TRACE( "- MajorFunction[%d] = %p\n", i, driver_obj.MajorFunction[i] );
- return status;
-}
-/* call the driver unload function */ -static void unload_driver( HMODULE module, DRIVER_OBJECT *driver_obj ) -{
- if (driver_obj->DriverUnload)
- {
if (WINE_TRACE_ON(relay))
WINE_DPRINTF( "%04x:Call driver unload %p (obj=%p)\n", GetCurrentThreadId(),
driver_obj->DriverUnload, driver_obj );
driver_obj->DriverUnload( driver_obj );
if (WINE_TRACE_ON(relay))
WINE_DPRINTF( "%04x:Ret driver unload %p (obj=%p)\n", GetCurrentThreadId(),
driver_obj->DriverUnload, driver_obj );
- }
- FreeLibrary( module );
-}
-/* load the .sys module for a device driver */ -static HMODULE load_driver(void) -{
- static const WCHAR driversW[] = {'\','d','r','i','v','e','r','s','\',0};
- static const WCHAR systemrootW[] = {'\','S','y','s','t','e','m','R','o','o','t','\',0};
- static const WCHAR postfixW[] = {'.','s','y','s',0};
- static const WCHAR ntprefixW[] = {'\','?','?','\',0};
- static const WCHAR ImagePathW[] = {'I','m','a','g','e','P','a','t','h',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};
- UNICODE_STRING keypath;
- HMODULE module;
- LPWSTR path = NULL, str;
- DWORD type, size;
- str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(driver_name)*sizeof(WCHAR) );
- lstrcpyW( str, servicesW );
- lstrcatW( str, driver_name );
- if (RegOpenKeyW( HKEY_LOCAL_MACHINE, str + 18 /* skip \registry\machine */, &driver_hkey ))
- {
WINE_ERR( "cannot open key %s, err=%u\n", wine_dbgstr_w(str), GetLastError() );
HeapFree( GetProcessHeap(), 0, str);
return FALSE;
- }
- RtlInitUnicodeString( &keypath, str );
- /* read the executable path from memory */
- size = 0;
- if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, NULL, &size ))
- {
str = HeapAlloc( GetProcessHeap(), 0, size );
if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, (LPBYTE)str, &size ))
{
size = ExpandEnvironmentStringsW(str,NULL,0);
path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
ExpandEnvironmentStringsW(str,path,size);
}
HeapFree( GetProcessHeap(), 0, str );
if (!path) return FALSE;
if (!strncmpiW( path, systemrootW, 12 ))
{
WCHAR buffer[MAX_PATH];
GetWindowsDirectoryW(buffer, MAX_PATH);
str = HeapAlloc(GetProcessHeap(), 0, (size -11 + strlenW(buffer))
* sizeof(WCHAR));
lstrcpyW(str, buffer);
lstrcatW(str, path + 11);
HeapFree( GetProcessHeap(), 0, path );
path = str;
}
else if (!strncmpW( path, ntprefixW, 4 ))
str = path + 4;
else
str = path;
- }
- else
- {
/* default is to use the driver name + ".sys" */
WCHAR buffer[MAX_PATH];
GetSystemDirectoryW(buffer, MAX_PATH);
path = HeapAlloc(GetProcessHeap(),0,
(strlenW(buffer) + strlenW(driversW) + strlenW(driver_name) + strlenW(postfixW) + 1)
*sizeof(WCHAR));
lstrcpyW(path, buffer);
lstrcatW(path, driversW);
lstrcatW(path, driver_name);
lstrcatW(path, postfixW);
str = path;
- }
- WINE_TRACE( "loading driver %s\n", wine_dbgstr_w(str) );
- module = load_driver_module( str );
- HeapFree( GetProcessHeap(), 0, path );
- if (!module) return NULL;
- init_driver( module, &keypath );
- return module;
-}
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context ) { @@ -305,7 +71,7 @@ static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { SERVICE_STATUS status;
- HMODULE driver_module;
UNICODE_STRING DriverName;
WINE_TRACE( "starting service %s\n", wine_dbgstr_w(driver_name) );
@@ -324,15 +90,16 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) status.dwWaitHint = 10000; SetServiceStatus( service_handle, &status );
- driver_module = load_driver();
- if (driver_module)
RtlInitUnicodeString( &DriverName, driver_name );
if ( ZwLoadDriver( &DriverName ) == ERROR_SUCCESS ) { status.dwCurrentState = SERVICE_RUNNING; status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; SetServiceStatus( service_handle, &status );
wine_ntoskrnl_main_loop( stop_event );
unload_driver( driver_module, &driver_obj );
} else WINE_ERR( "driver %s failed to load\n", wine_dbgstr_w(driver_name) );ZwUnloadDriver( &DriverName );