return STATUS_NO_SUCH_DEVICE;
}
+NTSTATUS
+PnpRootRegisterDevice(
+ IN PDEVICE_OBJECT DeviceObject)
+{
+ PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension = PnpRootDeviceObject->DeviceExtension;
+ PPNPROOT_DEVICE Device;
+ PDEVICE_NODE DeviceNode;
+ PWSTR InstancePath;
+ UNICODE_STRING InstancePathCopy;
+
+ Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
+ if (!Device) return STATUS_NO_MEMORY;
+
+ DeviceNode = IopGetDeviceNode(DeviceObject);
+ if (!RtlCreateUnicodeString(&InstancePathCopy, DeviceNode->InstancePath.Buffer))
+ {
+ ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+ return STATUS_NO_MEMORY;
+ }
+
+ InstancePath = wcsrchr(InstancePathCopy.Buffer, L'\\');
+ ASSERT(InstancePath);
+
+ if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath + 1))
+ {
+ RtlFreeUnicodeString(&InstancePathCopy);
+ ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+ return STATUS_NO_MEMORY;
+ }
+
+ InstancePath[0] = UNICODE_NULL;
+
+ if (!RtlCreateUnicodeString(&Device->DeviceID, InstancePathCopy.Buffer))
+ {
+ RtlFreeUnicodeString(&InstancePathCopy);
+ RtlFreeUnicodeString(&Device->InstanceID);
+ ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+ return STATUS_NO_MEMORY;
+ }
+
+ InstancePath[0] = L'\\';
+
+ Device->Pdo = DeviceObject;
+
+ KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+ InsertTailList(&DeviceExtension->DeviceListHead,
+ &Device->ListEntry);
+ DeviceExtension->DeviceListCount++;
+ KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+
+ RtlFreeUnicodeString(&InstancePathCopy);
+
+ return STATUS_SUCCESS;
+}
+
/* Creates a new PnP device for a legacy driver */
NTSTATUS
PnpRootCreateDevice(
IN PUNICODE_STRING ServiceName,
+ IN OPTIONAL PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *PhysicalDeviceObject,
OUT OPTIONAL PUNICODE_STRING FullInstancePath)
{
UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
ULONG NextInstance;
UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM);
- HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE;
+ HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE, InstanceKeyHandle;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
OBJECT_ATTRIBUTES ObjectAttributes;
goto cleanup;
}
+ /* Finish creating the instance path in the registry */
+ InitializeObjectAttributes(&ObjectAttributes, &Device->InstanceID, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL);
+ Status = ZwCreateKey(&InstanceKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create instance path (0x%x)\n", Status);
+ goto cleanup;
+ }
+
+ /* Just close the handle */
+ ZwClose(InstanceKeyHandle);
+
if (FullInstancePath)
{
FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length;
/* Initialize a device object */
Status = IoCreateDevice(
- PnpRootDeviceObject->DriverObject,
+ DriverObject ? DriverObject : PnpRootDeviceObject->DriverObject,
sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
UNICODE_STRING Source;
if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0)
+ {
+ Destination->Length = 0;
+ Destination->MaximumLength = 0;
+ Destination->Buffer = NULL;
return STATUS_SUCCESS;
+ }
- Source.MaximumLength = Source.Length = ValueLength;
+ Source.MaximumLength = Source.Length = (USHORT)ValueLength;
Source.Buffer = ValueData;
- if (Source.Length > 0 && Source.Buffer[Source.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
- Source.Length -= sizeof(WCHAR);
+
return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &Source, Destination);
}
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM);
UNICODE_STRING SubKeyName;
WCHAR DevicePath[MAX_PATH + 1];
- RTL_QUERY_REGISTRY_TABLE QueryTable[5];
+ RTL_QUERY_REGISTRY_TABLE QueryTable[4];
PPNPROOT_DEVICE Device = NULL;
HANDLE KeyHandle = INVALID_HANDLE_VALUE;
HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
/* Terminate the string */
SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
- _snwprintf(
- DevicePath,
- sizeof(DevicePath) / sizeof(WCHAR),
- L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
+ _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR),
+ L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name);
if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE)
{
/* Fill device ID and instance ID */
if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
{
- DPRINT("RtlCreateUnicodeString() failed\n");
+ DPRINT1("RtlCreateUnicodeString() failed\n");
Status = STATUS_NO_MEMORY;
goto cleanup;
}
if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name))
{
- DPRINT("RtlCreateUnicodeString() failed\n");
+ DPRINT1("RtlCreateUnicodeString() failed\n");
Status = STATUS_NO_MEMORY;
goto cleanup;
}
Status = IopOpenRegistryKeyEx(&DeviceKeyHandle, SubKeyHandle, &Device->InstanceID, KEY_READ);
if (!NT_SUCCESS(Status))
{
- DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
+ DPRINT1("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
break;
}
- /* Fill other informations */
+ /* Fill information from the device instance key */
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = QueryStringCallback;
+ QueryTable[0].Name = L"DeviceDesc";
+ QueryTable[0].EntryContext = &Device->DeviceDescription;
+
+ RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+ (PCWSTR)DeviceKeyHandle,
+ QueryTable,
+ NULL,
+ NULL);
+
+ /* Fill information from the LogConf subkey */
Buffer1.Data = (PVOID *)&Device->ResourceRequirementsList;
Buffer1.Length = NULL;
Buffer2.Data = (PVOID *)&Device->ResourceList;
Buffer2.Length = &Device->ResourceListSize;
RtlZeroMemory(QueryTable, sizeof(QueryTable));
- QueryTable[0].QueryRoutine = QueryStringCallback;
- QueryTable[0].Name = L"DeviceDesc";
- QueryTable[0].EntryContext = &Device->DeviceDescription;
- QueryTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY;
- QueryTable[1].Name = L"LogConf";
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ QueryTable[0].Name = L"LogConf";
+ QueryTable[1].QueryRoutine = QueryBinaryValueCallback;
+ QueryTable[1].Name = L"BasicConfigVector";
+ QueryTable[1].EntryContext = &Buffer1;
QueryTable[2].QueryRoutine = QueryBinaryValueCallback;
- QueryTable[2].Name = L"BasicConfigVector";
- QueryTable[2].EntryContext = &Buffer1;
- QueryTable[3].QueryRoutine = QueryBinaryValueCallback;
- QueryTable[3].Name = L"BootConfig";
- QueryTable[3].EntryContext = &Buffer2;
-
- Status = RtlQueryRegistryValues(
- RTL_REGISTRY_HANDLE,
- (PCWSTR)DeviceKeyHandle,
- QueryTable,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
+ QueryTable[2].Name = L"BootConfig";
+ QueryTable[2].EntryContext = &Buffer2;
+
+ if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+ (PCWSTR)DeviceKeyHandle,
+ QueryTable,
+ NULL,
+ NULL)))
{
- DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status);
- break;
+ /* Non-fatal error */
+ DPRINT1("Failed to read the LogConf key for %S\\%S\n", DevicePath, SubKeyInfo->Name);
}
ZwClose(DeviceKeyHandle);
{
/* Get the entry */
Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
-
+
if (!Device->Pdo)
{
/* Create a physical device object for the
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
- PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_CAPABILITIES DeviceCapabilities;
- DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
if (DeviceCapabilities->Version != 1)
UNICODE_STRING String;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
- Status = RtlDuplicateUnicodeString(
- RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
- &DeviceExtension->DeviceInfo->DeviceDescription,
- &String);
- Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+ if (DeviceExtension->DeviceInfo->DeviceDescription.Buffer != NULL)
+ {
+ Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DeviceExtension->DeviceInfo->DeviceDescription,
+ &String);
+ Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+ }
break;
}
case DeviceTextLocationInformation:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
- Status = STATUS_NOT_SUPPORTED;
break;
}
IN PIRP Irp)
{
PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+ PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ FdoDeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
Status = Irp->IoStatus.Status;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
break;
case IRP_MN_REMOVE_DEVICE:
- DPRINT1("IRP_MN_REMOVE_DEVICE is UNIMPLEMENTED!\n");
+ /* Remove the device from the device list and decrement the device count*/
+ KeAcquireGuardedMutex(&FdoDeviceExtension->DeviceListLock);
+ RemoveEntryList(&DeviceExtension->DeviceInfo->ListEntry);
+ FdoDeviceExtension->DeviceListCount--;
+ KeReleaseGuardedMutex(&FdoDeviceExtension->DeviceListLock);
+
+ /* Free some strings we created */
+ RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceDescription);
+ RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceID);
+ RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->InstanceID);
+
+ /* Free the resource requirements list */
+ if (DeviceExtension->DeviceInfo->ResourceRequirementsList != NULL)
+ ExFreePool(DeviceExtension->DeviceInfo->ResourceRequirementsList);
+
+ /* Free the boot resources list */
+ if (DeviceExtension->DeviceInfo->ResourceList != NULL)
+ ExFreePool(DeviceExtension->DeviceInfo->ResourceList);
+
+ /* Free the device info */
+ ExFreePool(DeviceExtension->DeviceInfo);
+
+ /* Finally, delete the device object */
+ IoDeleteDevice(DeviceObject);
+
+ /* Return success */
Status = STATUS_SUCCESS;
break;
default:
DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
- Status = STATUS_NOT_IMPLEMENTED;
break;
}
DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
IopRootDriverObject = DriverObject;
-
+
DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;