mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- Minor cleanup and fixed few memory leaks on driver unload.
svn path=/trunk/; revision=8896
This commit is contained in:
parent
5c7330b4d4
commit
c734759964
2 changed files with 321 additions and 261 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: io.h,v 1.41 2004/03/27 19:41:31 navaraf Exp $
|
/* $Id: io.h,v 1.42 2004/03/28 09:48:13 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -57,6 +57,12 @@ typedef struct _DEVOBJ_EXTENSION {
|
||||||
struct _DEVICE_NODE *DeviceNode;
|
struct _DEVICE_NODE *DeviceNode;
|
||||||
} DEVOBJ_EXTENSION, *PDEVOBJ_EXTENSION;
|
} DEVOBJ_EXTENSION, *PDEVOBJ_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct _PRIVATE_DRIVER_EXTENSIONS {
|
||||||
|
struct _PRIVATE_DRIVER_EXTENSIONS *Link;
|
||||||
|
PVOID ClientIdentificationAddress;
|
||||||
|
CHAR Extension[1];
|
||||||
|
} PRIVATE_DRIVER_EXTENSIONS, *PPRIVATE_DRIVER_EXTENSIONS;
|
||||||
|
|
||||||
typedef struct _DEVICE_NODE
|
typedef struct _DEVICE_NODE
|
||||||
{
|
{
|
||||||
struct _DEVICE_NODE *Parent;
|
struct _DEVICE_NODE *Parent;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: driver.c,v 1.39 2004/03/27 19:41:32 navaraf Exp $
|
/* $Id: driver.c,v 1.40 2004/03/28 09:48:13 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -85,24 +85,19 @@ POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
|
||||||
|
|
||||||
#define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
|
#define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* DECLARATIONS ***************************************************************/
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
IopCreateDriver(
|
IopCreateDriver(
|
||||||
PVOID ObjectBody,
|
PVOID ObjectBody,
|
||||||
PVOID Parent,
|
PVOID Parent,
|
||||||
PWSTR RemainingPath,
|
PWSTR RemainingPath,
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
POBJECT_ATTRIBUTES ObjectAttributes);
|
||||||
{
|
|
||||||
DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
|
||||||
ObjectBody, Parent, RemainingPath);
|
|
||||||
|
|
||||||
if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
|
VOID STDCALL
|
||||||
return STATUS_UNSUCCESSFUL;
|
IopDeleteDriver(PVOID ObjectBody);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
IopInitDriverImplementation(VOID)
|
IopInitDriverImplementation(VOID)
|
||||||
|
@ -119,7 +114,7 @@ IopInitDriverImplementation(VOID)
|
||||||
IoDriverObjectType->Dump = NULL;
|
IoDriverObjectType->Dump = NULL;
|
||||||
IoDriverObjectType->Open = NULL;
|
IoDriverObjectType->Open = NULL;
|
||||||
IoDriverObjectType->Close = NULL;
|
IoDriverObjectType->Close = NULL;
|
||||||
IoDriverObjectType->Delete = NULL;
|
IoDriverObjectType->Delete = IopDeleteDriver;
|
||||||
IoDriverObjectType->Parse = NULL;
|
IoDriverObjectType->Parse = NULL;
|
||||||
IoDriverObjectType->Security = NULL;
|
IoDriverObjectType->Security = NULL;
|
||||||
IoDriverObjectType->QueryName = NULL;
|
IoDriverObjectType->QueryName = NULL;
|
||||||
|
@ -136,7 +131,7 @@ IopInitDriverImplementation(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
IopDefaultDispatchFunction(
|
IopInvalidDeviceRequest(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
|
@ -146,6 +141,68 @@ IopDefaultDispatchFunction(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
IopCreateDriver(
|
||||||
|
PVOID ObjectBody,
|
||||||
|
PVOID Parent,
|
||||||
|
PWSTR RemainingPath,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
|
{
|
||||||
|
PDRIVER_OBJECT Object = ObjectBody;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
||||||
|
ObjectBody, Parent, RemainingPath);
|
||||||
|
|
||||||
|
if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
/* Create driver extension */
|
||||||
|
Object->DriverExtension = (PDRIVER_EXTENSION)
|
||||||
|
ExAllocatePoolWithTag(
|
||||||
|
NonPagedPool,
|
||||||
|
sizeof(DRIVER_EXTENSION),
|
||||||
|
TAG_DRIVER_EXTENSION);
|
||||||
|
|
||||||
|
if (Object->DriverExtension == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
|
||||||
|
|
||||||
|
Object->Type = InternalDriverType;
|
||||||
|
|
||||||
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||||
|
Object->MajorFunction[i] = IopInvalidDeviceRequest;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
IopDeleteDriver(PVOID ObjectBody)
|
||||||
|
{
|
||||||
|
PDRIVER_OBJECT Object = ObjectBody;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PPRIVATE_DRIVER_EXTENSIONS DriverExtension, NextDriverExtension;
|
||||||
|
|
||||||
|
DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody);
|
||||||
|
|
||||||
|
ExFreePool(Object->DriverExtension);
|
||||||
|
|
||||||
|
OldIrql = KeRaiseIrqlToDpcLevel();
|
||||||
|
|
||||||
|
for (DriverExtension = Object->DriverSection;
|
||||||
|
DriverExtension != NULL;
|
||||||
|
DriverExtension = NextDriverExtension)
|
||||||
|
{
|
||||||
|
NextDriverExtension = DriverExtension->Link;
|
||||||
|
ExFreePool(DriverExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
KfLowerIrql(OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
IopCreateDriverObject(
|
IopCreateDriverObject(
|
||||||
PDRIVER_OBJECT *DriverObject,
|
PDRIVER_OBJECT *DriverObject,
|
||||||
|
@ -155,7 +212,6 @@ IopCreateDriverObject(
|
||||||
ULONG DriverImageSize)
|
ULONG DriverImageSize)
|
||||||
{
|
{
|
||||||
PDRIVER_OBJECT Object;
|
PDRIVER_OBJECT Object;
|
||||||
ULONG i;
|
|
||||||
WCHAR NameBuffer[MAX_PATH];
|
WCHAR NameBuffer[MAX_PATH];
|
||||||
UNICODE_STRING DriverName;
|
UNICODE_STRING DriverName;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
@ -208,28 +264,9 @@ IopCreateDriverObject(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create driver extension */
|
|
||||||
Object->DriverExtension = (PDRIVER_EXTENSION)
|
|
||||||
ExAllocatePoolWithTag(
|
|
||||||
NonPagedPool,
|
|
||||||
sizeof(DRIVER_EXTENSION),
|
|
||||||
TAG_DRIVER_EXTENSION);
|
|
||||||
|
|
||||||
if (Object->DriverExtension == NULL)
|
|
||||||
{
|
|
||||||
ExFreePool(Object);
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
|
|
||||||
|
|
||||||
Object->Type = InternalDriverType;
|
|
||||||
Object->DriverStart = DriverImageStart;
|
Object->DriverStart = DriverImageStart;
|
||||||
Object->DriverSize = DriverImageSize;
|
Object->DriverSize = DriverImageSize;
|
||||||
|
|
||||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
|
||||||
Object->MajorFunction[i] = IopDefaultDispatchFunction;
|
|
||||||
|
|
||||||
*DriverObject = Object;
|
*DriverObject = Object;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -551,7 +588,6 @@ IopAttachFilterDriversCallback(
|
||||||
PMODULE_OBJECT ModuleObject;
|
PMODULE_OBJECT ModuleObject;
|
||||||
PDRIVER_OBJECT DriverObject;
|
PDRIVER_OBJECT DriverObject;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
|
||||||
for (Filters = ValueData;
|
for (Filters = ValueData;
|
||||||
((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
|
((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
|
||||||
|
@ -681,13 +717,6 @@ IopAttachFilterDrivers(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS STDCALL
|
static NTSTATUS STDCALL
|
||||||
IopCreateGroupListEntry(PWSTR ValueName,
|
IopCreateGroupListEntry(PWSTR ValueName,
|
||||||
ULONG ValueType,
|
ULONG ValueType,
|
||||||
|
@ -964,12 +993,12 @@ IoDestroyDriverList(VOID)
|
||||||
VOID STATIC
|
VOID STATIC
|
||||||
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
|
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
|
||||||
{
|
{
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
|
for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
|
||||||
{
|
{
|
||||||
MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
|
MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -999,12 +1028,14 @@ IopInitializeBuiltinDriver(
|
||||||
/*
|
/*
|
||||||
* Display 'Initializing XXX...' message
|
* Display 'Initializing XXX...' message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sprintf(TextBuffer, "Initializing %s...\n", FileName);
|
sprintf(TextBuffer, "Initializing %s...\n", FileName);
|
||||||
HalDisplayString(TextBuffer);
|
HalDisplayString(TextBuffer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the right device object
|
* Determine the right device object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ModuleDeviceNode == NULL)
|
if (ModuleDeviceNode == NULL)
|
||||||
{
|
{
|
||||||
/* Use IopRootDeviceNode for now */
|
/* Use IopRootDeviceNode for now */
|
||||||
|
@ -1022,6 +1053,7 @@ IopInitializeBuiltinDriver(
|
||||||
/*
|
/*
|
||||||
* Generate filename without path (not needed by freeldr)
|
* Generate filename without path (not needed by freeldr)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FileNameWithoutPath = strrchr(FileName, '\\');
|
FileNameWithoutPath = strrchr(FileName, '\\');
|
||||||
if (FileNameWithoutPath == NULL)
|
if (FileNameWithoutPath == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1031,6 +1063,7 @@ IopInitializeBuiltinDriver(
|
||||||
/*
|
/*
|
||||||
* Load the module
|
* Load the module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
|
RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
|
||||||
FileNameWithoutPath);
|
FileNameWithoutPath);
|
||||||
Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
|
Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
|
||||||
|
@ -1046,6 +1079,7 @@ IopInitializeBuiltinDriver(
|
||||||
/*
|
/*
|
||||||
* Strip the file extension from ServiceName
|
* Strip the file extension from ServiceName
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
|
FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
|
||||||
if (FileExtension != NULL)
|
if (FileExtension != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1056,6 +1090,7 @@ IopInitializeBuiltinDriver(
|
||||||
/*
|
/*
|
||||||
* Initialize the driver
|
* Initialize the driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE,
|
Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE,
|
||||||
&DriverObject);
|
&DriverObject);
|
||||||
|
|
||||||
|
@ -1112,6 +1147,7 @@ IopInitializeBootDrivers(VOID)
|
||||||
/*
|
/*
|
||||||
* Pass symbol files to kernel debugger
|
* Pass symbol files to kernel debugger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!_stricmp(Extension, ".sym"))
|
if (!_stricmp(Extension, ".sym"))
|
||||||
{
|
{
|
||||||
KDB_SYMBOLFILE_HOOK((PVOID)ModuleStart, ModuleName, ModuleSize);
|
KDB_SYMBOLFILE_HOOK((PVOID)ModuleStart, ModuleName, ModuleSize);
|
||||||
|
@ -1120,6 +1156,7 @@ IopInitializeBootDrivers(VOID)
|
||||||
/*
|
/*
|
||||||
* Load builtin driver
|
* Load builtin driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!_stricmp(Extension, ".sys"))
|
if (!_stricmp(Extension, ".sys"))
|
||||||
{
|
{
|
||||||
if (!ModuleLoaded)
|
if (!ModuleLoaded)
|
||||||
|
@ -1133,6 +1170,7 @@ IopInitializeBootDrivers(VOID)
|
||||||
/*
|
/*
|
||||||
* Free memory for all boot files, except ntoskrnl.exe and hal.dll
|
* Free memory for all boot files, except ntoskrnl.exe and hal.dll
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef KDBG
|
#ifdef KDBG
|
||||||
/*
|
/*
|
||||||
* Do not free the memory from symbol files, if the kernel debugger
|
* Do not free the memory from symbol files, if the kernel debugger
|
||||||
|
@ -1371,215 +1409,6 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NtLoadDriver
|
|
||||||
*
|
|
||||||
* Loads a device driver.
|
|
||||||
*
|
|
||||||
* Parameters
|
|
||||||
* DriverServiceName
|
|
||||||
* Name of the service to load (registry key).
|
|
||||||
*
|
|
||||||
* Return Value
|
|
||||||
* Status
|
|
||||||
*/
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
|
||||||
{
|
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
|
||||||
UNICODE_STRING ImagePath;
|
|
||||||
UNICODE_STRING ServiceName;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG Type;
|
|
||||||
PDEVICE_NODE DeviceNode;
|
|
||||||
PMODULE_OBJECT ModuleObject;
|
|
||||||
PDRIVER_OBJECT DriverObject;
|
|
||||||
LPWSTR Start;
|
|
||||||
|
|
||||||
DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check security privileges
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode()))
|
|
||||||
return STATUS_PRIVILEGE_NOT_HELD;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&ImagePath, NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the service name from the registry key name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Start = wcsrchr(DriverServiceName->Buffer, L'\\');
|
|
||||||
if (Start == NULL)
|
|
||||||
Start = DriverServiceName->Buffer;
|
|
||||||
else
|
|
||||||
Start++;
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&ServiceName, Start);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get service type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&ImagePath, NULL);
|
|
||||||
|
|
||||||
QueryTable[0].Name = L"Type";
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].EntryContext = &Type;
|
|
||||||
|
|
||||||
QueryTable[1].Name = L"ImagePath";
|
|
||||||
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
|
||||||
QueryTable[1].EntryContext = &ImagePath;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
|
||||||
DriverServiceName->Buffer, QueryTable, NULL, NULL);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
|
|
||||||
RtlFreeUnicodeString(&ImagePath);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normalize the image path for all later processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("FullImagePath: '%S'\n", ImagePath.Buffer);
|
|
||||||
DPRINT("Type: %lx\n", Type);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See, if the driver module isn't already loaded
|
|
||||||
*/
|
|
||||||
ModuleObject = LdrGetModuleObject(&ImagePath);
|
|
||||||
if (ModuleObject != NULL)
|
|
||||||
{
|
|
||||||
return STATUS_IMAGE_ALREADY_LOADED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create device node
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Use IopRootDeviceNode for now */
|
|
||||||
Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load the driver module
|
|
||||||
*/
|
|
||||||
|
|
||||||
Status = LdrLoadModule(&ImagePath, &ModuleObject);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("LdrLoadModule() failed (Status %lx)\n", Status);
|
|
||||||
IopFreeDeviceNode(DeviceNode);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set a service name for the device node
|
|
||||||
*/
|
|
||||||
|
|
||||||
Start = wcsrchr(DriverServiceName->Buffer, L'\\');
|
|
||||||
if (Start == NULL)
|
|
||||||
Start = DriverServiceName->Buffer;
|
|
||||||
else
|
|
||||||
Start++;
|
|
||||||
RtlCreateUnicodeString(&DeviceNode->ServiceName, Start);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the driver module
|
|
||||||
*/
|
|
||||||
|
|
||||||
Status = IopInitializeDriverModule(
|
|
||||||
DeviceNode,
|
|
||||||
ModuleObject,
|
|
||||||
(Type == 2 /*SERVICE_FILE_SYSTEM_DRIVER*/ ||
|
|
||||||
Type == 8 /*SERVICE_RECOGNIZER_DRIVER*/),
|
|
||||||
&DriverObject);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
|
|
||||||
LdrUnloadModule(ModuleObject);
|
|
||||||
IopFreeDeviceNode(DeviceNode);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
IopInitializeDevice(DeviceNode, DriverObject);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NtUnloadDriver
|
|
||||||
*
|
|
||||||
* Unloads a legacy device driver.
|
|
||||||
*
|
|
||||||
* Parameters
|
|
||||||
* DriverServiceName
|
|
||||||
* Name of the service to unload (registry key).
|
|
||||||
*
|
|
||||||
* Return Value
|
|
||||||
* Status
|
|
||||||
*/
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
|
|
||||||
{
|
|
||||||
return IopUnloadDriver(DriverServiceName, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
VOID STDCALL
|
|
||||||
IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
|
|
||||||
PDRIVER_REINITIALIZE ReinitRoutine,
|
|
||||||
PVOID Context)
|
|
||||||
{
|
|
||||||
PDRIVER_REINIT_ITEM ReinitItem;
|
|
||||||
|
|
||||||
ReinitItem = ExAllocatePool(NonPagedPool,
|
|
||||||
sizeof(DRIVER_REINIT_ITEM));
|
|
||||||
if (ReinitItem == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ReinitItem->DriverObject = DriverObject;
|
|
||||||
ReinitItem->ReinitRoutine = ReinitRoutine;
|
|
||||||
ReinitItem->Context = Context;
|
|
||||||
|
|
||||||
ExInterlockedInsertTailList(&DriverReinitListHead,
|
|
||||||
&ReinitItem->ItemEntry,
|
|
||||||
&DriverReinitListLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID FASTCALL
|
VOID FASTCALL
|
||||||
IopMarkLastReinitializeDriver(VOID)
|
IopMarkLastReinitializeDriver(VOID)
|
||||||
{
|
{
|
||||||
|
@ -1645,11 +1474,229 @@ IopReinitializeDrivers(VOID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _PRIVATE_DRIVER_EXTENSIONS {
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
struct _PRIVATE_DRIVER_EXTENSIONS *Link;
|
|
||||||
PVOID ClientIdentificationAddress;
|
/*
|
||||||
CHAR Extension[1];
|
* NtLoadDriver
|
||||||
} PRIVATE_DRIVER_EXTENSIONS, *PPRIVATE_DRIVER_EXTENSIONS;
|
*
|
||||||
|
* Loads a device driver.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* DriverServiceName
|
||||||
|
* Name of the service to load (registry key).
|
||||||
|
*
|
||||||
|
* Return Value
|
||||||
|
* Status
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
||||||
|
{
|
||||||
|
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
||||||
|
UNICODE_STRING ImagePath;
|
||||||
|
UNICODE_STRING ServiceName;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Type;
|
||||||
|
PDEVICE_NODE DeviceNode;
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
|
PDRIVER_OBJECT DriverObject;
|
||||||
|
LPWSTR Start;
|
||||||
|
|
||||||
|
DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check security privileges
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode()))
|
||||||
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ImagePath, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the service name from the registry key name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Start = wcsrchr(DriverServiceName->Buffer, L'\\');
|
||||||
|
if (Start == NULL)
|
||||||
|
Start = DriverServiceName->Buffer;
|
||||||
|
else
|
||||||
|
Start++;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ServiceName, Start);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get service type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ImagePath, NULL);
|
||||||
|
|
||||||
|
QueryTable[0].Name = L"Type";
|
||||||
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||||
|
QueryTable[0].EntryContext = &Type;
|
||||||
|
|
||||||
|
QueryTable[1].Name = L"ImagePath";
|
||||||
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||||||
|
QueryTable[1].EntryContext = &ImagePath;
|
||||||
|
|
||||||
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
||||||
|
DriverServiceName->Buffer, QueryTable, NULL, NULL);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
|
||||||
|
RtlFreeUnicodeString(&ImagePath);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normalize the image path for all later processing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("FullImagePath: '%S'\n", ImagePath.Buffer);
|
||||||
|
DPRINT("Type: %lx\n", Type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See, if the driver module isn't already loaded
|
||||||
|
*/
|
||||||
|
|
||||||
|
ModuleObject = LdrGetModuleObject(&ImagePath);
|
||||||
|
if (ModuleObject != NULL)
|
||||||
|
{
|
||||||
|
return STATUS_IMAGE_ALREADY_LOADED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create device node
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Use IopRootDeviceNode for now */
|
||||||
|
Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load the driver module
|
||||||
|
*/
|
||||||
|
|
||||||
|
Status = LdrLoadModule(&ImagePath, &ModuleObject);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("LdrLoadModule() failed (Status %lx)\n", Status);
|
||||||
|
IopFreeDeviceNode(DeviceNode);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a service name for the device node
|
||||||
|
*/
|
||||||
|
|
||||||
|
Start = wcsrchr(DriverServiceName->Buffer, L'\\');
|
||||||
|
if (Start == NULL)
|
||||||
|
Start = DriverServiceName->Buffer;
|
||||||
|
else
|
||||||
|
Start++;
|
||||||
|
RtlCreateUnicodeString(&DeviceNode->ServiceName, Start);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the driver module
|
||||||
|
*/
|
||||||
|
|
||||||
|
Status = IopInitializeDriverModule(
|
||||||
|
DeviceNode,
|
||||||
|
ModuleObject,
|
||||||
|
(Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
|
||||||
|
Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
|
||||||
|
&DriverObject);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
|
||||||
|
LdrUnloadModule(ModuleObject);
|
||||||
|
IopFreeDeviceNode(DeviceNode);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
IopInitializeDevice(DeviceNode, DriverObject);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NtUnloadDriver
|
||||||
|
*
|
||||||
|
* Unloads a legacy device driver.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* DriverServiceName
|
||||||
|
* Name of the service to unload (registry key).
|
||||||
|
*
|
||||||
|
* Return Value
|
||||||
|
* Status
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
|
||||||
|
{
|
||||||
|
return IopUnloadDriver(DriverServiceName, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IoRegisterDriverReinitialization
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
IoRegisterDriverReinitialization(
|
||||||
|
PDRIVER_OBJECT DriverObject,
|
||||||
|
PDRIVER_REINITIALIZE ReinitRoutine,
|
||||||
|
PVOID Context)
|
||||||
|
{
|
||||||
|
PDRIVER_REINIT_ITEM ReinitItem;
|
||||||
|
|
||||||
|
ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
|
||||||
|
if (ReinitItem == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReinitItem->DriverObject = DriverObject;
|
||||||
|
ReinitItem->ReinitRoutine = ReinitRoutine;
|
||||||
|
ReinitItem->Context = Context;
|
||||||
|
|
||||||
|
ExInterlockedInsertTailList(
|
||||||
|
&DriverReinitListHead,
|
||||||
|
&ReinitItem->ItemEntry,
|
||||||
|
&DriverReinitListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IoAllocateDriverObjectExtension
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
IoAllocateDriverObjectExtension(
|
IoAllocateDriverObjectExtension(
|
||||||
|
@ -1699,6 +1746,13 @@ IoAllocateDriverObjectExtension(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IoGetDriverObjectExtension
|
||||||
|
*
|
||||||
|
* Status
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
|
||||||
PVOID STDCALL
|
PVOID STDCALL
|
||||||
IoGetDriverObjectExtension(
|
IoGetDriverObjectExtension(
|
||||||
PDRIVER_OBJECT DriverObject,
|
PDRIVER_OBJECT DriverObject,
|
||||||
|
|
Loading…
Reference in a new issue