mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[NTOS]: Re-implement IoGetDeviceProperty. Main changes are usage of existing (and new) helper functions for registry/IRP access, much better factored code, correct implementation of DevicePropertyPhysicalDeviceObjectName, fixed implementation of DevicePropertyBootConfigurationTranslated and DevicePropertyBootConfiguration (do not crash the system anymore), and support for more device properties.
[NTOS]: Fix caller of IoGetDeviceProperty in pnpres.c to work with new function behavior (which matches WDK documentation and test cases). [NTOS]: Implement helper function PnpBusTypeGuidGet, should be used later in other PnP code, but now used only for this patch. [NTOS]: Implement helper function PnpDetermineResourceListSize, ditto. N.B. Current IopCalculateResourceListSize function is broken and callers should use this one instead. [NTOS]: Implement helper function PpIrpQueryCapabilities, should be used later in device node code, but now only used for this patch. [NTOS]: Implement helper function PnpDeviceObjectToDeviceInstance, ditto. Main purpose of this patch is to unblock the new PCIx driver. svn path=/trunk/; revision=47388
This commit is contained in:
parent
799b6ad5b8
commit
6b6a3291e8
2 changed files with 438 additions and 265 deletions
|
@ -3003,6 +3003,241 @@ PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
PnpBusTypeGuidGet(IN USHORT Index,
|
||||||
|
IN LPGUID BusTypeGuid)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* Acquire the lock */
|
||||||
|
ExAcquireFastMutex(&PnpBusTypeGuidList->Lock);
|
||||||
|
|
||||||
|
/* Validate size */
|
||||||
|
if (Index < PnpBusTypeGuidList->GuidCount)
|
||||||
|
{
|
||||||
|
/* Copy the data */
|
||||||
|
RtlCopyMemory(BusTypeGuid, &PnpBusTypeGuidList->Guids[Index], sizeof(GUID));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Failure path */
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release lock and return status */
|
||||||
|
ExReleaseFastMutex(&PnpBusTypeGuidList->Lock);
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
PpIrpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
OUT PDEVICE_CAPABILITIES DeviceCaps)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
PVOID Dummy;
|
||||||
|
IO_STACK_LOCATION Stack;
|
||||||
|
|
||||||
|
/* Set up the Header */
|
||||||
|
RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
|
||||||
|
DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
|
||||||
|
DeviceCaps->Version = 1;
|
||||||
|
DeviceCaps->Address = -1;
|
||||||
|
DeviceCaps->UINumber = -1;
|
||||||
|
|
||||||
|
/* Set up the Stack */
|
||||||
|
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
|
||||||
|
Stack.MajorFunction = IRP_MJ_PNP;
|
||||||
|
Stack.MinorFunction = IRP_MN_QUERY_CAPABILITIES;
|
||||||
|
Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
|
||||||
|
|
||||||
|
/* Send the IRP */
|
||||||
|
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PHANDLE DeviceInstanceHandle,
|
||||||
|
IN ACCESS_MASK DesiredAccess)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE KeyHandle;
|
||||||
|
PDEVICE_NODE DeviceNode;
|
||||||
|
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Open the enum key */
|
||||||
|
Status = IopOpenRegistryKeyEx(&KeyHandle,
|
||||||
|
NULL,
|
||||||
|
&KeyName,
|
||||||
|
KEY_READ);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Make sure we have an instance path */
|
||||||
|
DeviceNode = IopGetDeviceNode(DeviceObject);
|
||||||
|
if ((DeviceNode) && (DeviceNode->InstancePath.Length))
|
||||||
|
{
|
||||||
|
/* Get the instance key */
|
||||||
|
Status = IopOpenRegistryKeyEx(DeviceInstanceHandle,
|
||||||
|
KeyHandle,
|
||||||
|
&DeviceNode->InstancePath,
|
||||||
|
DesiredAccess);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the handle and return status */
|
||||||
|
ZwClose(KeyHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList)
|
||||||
|
{
|
||||||
|
ULONG FinalSize, PartialSize, EntrySize, i, j;
|
||||||
|
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
|
||||||
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
|
||||||
|
|
||||||
|
/* If we don't have one, that's easy */
|
||||||
|
if (!ResourceList) return 0;
|
||||||
|
|
||||||
|
/* Start with the minimum size possible */
|
||||||
|
FinalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
|
||||||
|
|
||||||
|
/* Loop each full descriptor */
|
||||||
|
FullDescriptor = ResourceList->List;
|
||||||
|
for (i = 0; i < ResourceList->Count; i++)
|
||||||
|
{
|
||||||
|
/* Start with the minimum size possible */
|
||||||
|
PartialSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
|
||||||
|
FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors);
|
||||||
|
|
||||||
|
/* Loop each partial descriptor */
|
||||||
|
PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors;
|
||||||
|
for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
|
||||||
|
{
|
||||||
|
/* Start with the minimum size possible */
|
||||||
|
EntrySize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||||||
|
|
||||||
|
/* Check if there is extra data */
|
||||||
|
if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
|
||||||
|
{
|
||||||
|
/* Add that data */
|
||||||
|
EntrySize += PartialDescriptor->u.DeviceSpecificData.DataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The size of partial descriptors is bigger */
|
||||||
|
PartialSize += EntrySize;
|
||||||
|
|
||||||
|
/* Go to the next partial descriptor */
|
||||||
|
PartialDescriptor = (PVOID)((ULONG_PTR)PartialDescriptor + EntrySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The size of full descriptors is bigger */
|
||||||
|
FinalSize += PartialSize;
|
||||||
|
|
||||||
|
/* Go to the next full descriptor */
|
||||||
|
FullDescriptor = (PVOID)((ULONG_PTR)FullDescriptor + PartialSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the final size */
|
||||||
|
return FinalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG ValueType,
|
||||||
|
IN PWSTR ValueName,
|
||||||
|
IN PWSTR KeyName,
|
||||||
|
OUT PVOID Buffer,
|
||||||
|
IN PULONG BufferLength)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE KeyHandle, SubHandle;
|
||||||
|
UNICODE_STRING KeyString;
|
||||||
|
PKEY_VALUE_FULL_INFORMATION KeyValueInfo = NULL;
|
||||||
|
ULONG Length;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Find the instance key */
|
||||||
|
Status = PnpDeviceObjectToDeviceInstance(DeviceObject, &KeyHandle, KEY_READ);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Check for name given by caller */
|
||||||
|
if (KeyName)
|
||||||
|
{
|
||||||
|
/* Open this key */
|
||||||
|
RtlInitUnicodeString(&KeyString, KeyName);
|
||||||
|
Status = IopOpenRegistryKeyEx(&SubHandle,
|
||||||
|
KeyHandle,
|
||||||
|
&KeyString,
|
||||||
|
KEY_READ);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* And use this handle instead */
|
||||||
|
ZwClose(KeyHandle);
|
||||||
|
KeyHandle = SubHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if sub-key handle succeeded (or no-op if no key name given) */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Now get the size of the property */
|
||||||
|
Status = IopGetRegistryValue(KeyHandle,
|
||||||
|
ValueName,
|
||||||
|
&KeyValueInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the key */
|
||||||
|
ZwClose(KeyHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fail if any of the registry operations failed */
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Check how much data we have to copy */
|
||||||
|
Length = KeyValueInfo->DataLength;
|
||||||
|
if (*BufferLength >= Length)
|
||||||
|
{
|
||||||
|
/* Check for a match in the value type */
|
||||||
|
if (KeyValueInfo->Type == ValueType)
|
||||||
|
{
|
||||||
|
/* Copy the data */
|
||||||
|
RtlCopyMemory(Buffer,
|
||||||
|
(PVOID)((ULONG_PTR)KeyValueInfo +
|
||||||
|
KeyValueInfo->DataOffset),
|
||||||
|
Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid registry property type, fail */
|
||||||
|
Status = STATUS_INVALID_PARAMETER_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Buffer is too small to hold data */
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the required buffer length, free the buffer, and return status */
|
||||||
|
*BufferLength = Length;
|
||||||
|
ExFreePool(KeyValueInfo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; break;}
|
||||||
|
#define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
|
||||||
|
#define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -3016,281 +3251,205 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
|
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
|
||||||
DEVICE_CAPABILITIES DeviceCaps;
|
DEVICE_CAPABILITIES DeviceCaps;
|
||||||
ULONG Length;
|
ULONG ReturnLength = 0, Length = 0, ValueType;
|
||||||
|
PWCHAR ValueName = NULL, EnumeratorNameEnd, DeviceInstanceName;
|
||||||
PVOID Data = NULL;
|
PVOID Data = NULL;
|
||||||
PWSTR Ptr;
|
NTSTATUS Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
NTSTATUS Status;
|
GUID BusTypeGuid;
|
||||||
POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
|
POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
|
||||||
ULONG RequiredLength, ObjectNameInfoLength;
|
|
||||||
|
|
||||||
DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
|
DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
|
||||||
|
|
||||||
|
/* Assume failure */
|
||||||
*ResultLength = 0;
|
*ResultLength = 0;
|
||||||
|
|
||||||
if (DeviceNode == NULL)
|
/* Only PDOs can call this */
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
if (!DeviceNode) return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
/* Handle all properties */
|
||||||
switch (DeviceProperty)
|
switch (DeviceProperty)
|
||||||
{
|
{
|
||||||
case DevicePropertyBusNumber:
|
case DevicePropertyBusTypeGuid:
|
||||||
Length = sizeof(ULONG);
|
|
||||||
Data = &DeviceNode->ChildBusNumber;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Complete, untested */
|
/* Get the GUID from the internal cache */
|
||||||
case DevicePropertyBusTypeGuid:
|
Status = PnpBusTypeGuidGet(DeviceNode->ChildBusTypeIndex, &BusTypeGuid);
|
||||||
/* Sanity check */
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if ((DeviceNode->ChildBusTypeIndex != 0xFFFF) &&
|
|
||||||
(DeviceNode->ChildBusTypeIndex < PnpBusTypeGuidList->GuidCount))
|
|
||||||
{
|
|
||||||
/* Return the GUID */
|
|
||||||
*ResultLength = sizeof(GUID);
|
|
||||||
|
|
||||||
/* Check if the buffer given was large enough */
|
/* This is the format of the returned data */
|
||||||
if (BufferLength < *ResultLength)
|
PIP_RETURN_DATA(sizeof(GUID), &BusTypeGuid);
|
||||||
|
|
||||||
|
case DevicePropertyLegacyBusType:
|
||||||
|
|
||||||
|
/* Validate correct interface type */
|
||||||
|
if (DeviceNode->ChildInterfaceType == InterfaceTypeUndefined)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
/* This is the format of the returned data */
|
||||||
|
PIP_RETURN_DATA(sizeof(INTERFACE_TYPE), &DeviceNode->ChildInterfaceType);
|
||||||
|
|
||||||
|
case DevicePropertyBusNumber:
|
||||||
|
|
||||||
|
/* Validate correct bus number */
|
||||||
|
if ((DeviceNode->ChildBusNumber & 0x80000000) == 0x80000000)
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
/* This is the format of the returned data */
|
||||||
|
PIP_RETURN_DATA(sizeof(ULONG), &DeviceNode->ChildBusNumber);
|
||||||
|
|
||||||
|
case DevicePropertyEnumeratorName:
|
||||||
|
|
||||||
|
/* Get the instance path */
|
||||||
|
DeviceInstanceName = DeviceNode->InstancePath.Buffer;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
ASSERT((BufferLength & 1) == 0);
|
||||||
|
ASSERT(DeviceInstanceName != NULL);
|
||||||
|
|
||||||
|
/* Get the name from the path */
|
||||||
|
EnumeratorNameEnd = wcschr(DeviceInstanceName, OBJ_NAME_PATH_SEPARATOR);
|
||||||
|
ASSERT(EnumeratorNameEnd);
|
||||||
|
|
||||||
|
/* This is the format of the returned data */
|
||||||
|
PIP_RETURN_DATA((EnumeratorNameEnd - DeviceInstanceName) * 2,
|
||||||
|
&DeviceNode->ChildBusNumber);
|
||||||
|
|
||||||
|
case DevicePropertyAddress:
|
||||||
|
|
||||||
|
/* Query the device caps */
|
||||||
|
Status = PpIrpQueryCapabilities(DeviceObject, &DeviceCaps);
|
||||||
|
if (!NT_SUCCESS(Status) || (DeviceCaps.Address == MAXULONG))
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
/* This is the format of the returned data */
|
||||||
|
PIP_RETURN_DATA(sizeof(ULONG), &DeviceCaps.Address);
|
||||||
|
|
||||||
|
case DevicePropertyBootConfigurationTranslated:
|
||||||
|
|
||||||
|
/* Validate we have resources */
|
||||||
|
if (!DeviceNode->BootResources)
|
||||||
|
// if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
|
||||||
{
|
{
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
/* No resources will still fake success, but with 0 bytes */
|
||||||
|
*ResultLength = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the format of the returned data */
|
||||||
|
PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated
|
||||||
|
DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated
|
||||||
|
|
||||||
/* Copy the GUID */
|
case DevicePropertyPhysicalDeviceObjectName:
|
||||||
RtlCopyMemory(PropertyBuffer,
|
|
||||||
&(PnpBusTypeGuidList->Guids[DeviceNode->ChildBusTypeIndex]),
|
/* Sanity check for Unicode-sized string */
|
||||||
sizeof(GUID));
|
ASSERT((BufferLength & 1) == 0);
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
/* Allocate name buffer */
|
||||||
else
|
Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION);
|
||||||
{
|
ObjectNameInfo = ExAllocatePool(PagedPool, Length);
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
|
||||||
break;
|
/* Query the PDO name */
|
||||||
|
Status = ObQueryNameString(DeviceObject,
|
||||||
case DevicePropertyLegacyBusType:
|
|
||||||
Length = sizeof(INTERFACE_TYPE);
|
|
||||||
Data = &DeviceNode->ChildInterfaceType;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DevicePropertyAddress:
|
|
||||||
/* Query the device caps */
|
|
||||||
Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps);
|
|
||||||
if (NT_SUCCESS(Status) && (DeviceCaps.Address != MAXULONG))
|
|
||||||
{
|
|
||||||
/* Return length */
|
|
||||||
*ResultLength = sizeof(ULONG);
|
|
||||||
|
|
||||||
/* Check if the buffer given was large enough */
|
|
||||||
if (BufferLength < *ResultLength)
|
|
||||||
{
|
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return address */
|
|
||||||
*(PULONG)PropertyBuffer = DeviceCaps.Address;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// case DevicePropertyUINumber:
|
|
||||||
// if (DeviceNode->CapabilityFlags == NULL)
|
|
||||||
// return STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
// Length = sizeof(ULONG);
|
|
||||||
// Data = &DeviceNode->CapabilityFlags->UINumber;
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case DevicePropertyClassName:
|
|
||||||
case DevicePropertyClassGuid:
|
|
||||||
case DevicePropertyDriverKeyName:
|
|
||||||
case DevicePropertyManufacturer:
|
|
||||||
case DevicePropertyFriendlyName:
|
|
||||||
case DevicePropertyHardwareID:
|
|
||||||
case DevicePropertyCompatibleIDs:
|
|
||||||
case DevicePropertyDeviceDescription:
|
|
||||||
case DevicePropertyLocationInformation:
|
|
||||||
case DevicePropertyUINumber:
|
|
||||||
{
|
|
||||||
LPCWSTR RegistryPropertyName;
|
|
||||||
UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
|
|
||||||
UNICODE_STRING ValueName;
|
|
||||||
KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
|
|
||||||
ULONG ValueInformationLength;
|
|
||||||
HANDLE KeyHandle, EnumRootHandle;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
switch (DeviceProperty)
|
|
||||||
{
|
|
||||||
case DevicePropertyClassName:
|
|
||||||
RegistryPropertyName = L"Class"; break;
|
|
||||||
case DevicePropertyClassGuid:
|
|
||||||
RegistryPropertyName = L"ClassGuid"; break;
|
|
||||||
case DevicePropertyDriverKeyName:
|
|
||||||
RegistryPropertyName = L"Driver"; break;
|
|
||||||
case DevicePropertyManufacturer:
|
|
||||||
RegistryPropertyName = L"Mfg"; break;
|
|
||||||
case DevicePropertyFriendlyName:
|
|
||||||
RegistryPropertyName = L"FriendlyName"; break;
|
|
||||||
case DevicePropertyHardwareID:
|
|
||||||
RegistryPropertyName = L"HardwareID"; break;
|
|
||||||
case DevicePropertyCompatibleIDs:
|
|
||||||
RegistryPropertyName = L"CompatibleIDs"; break;
|
|
||||||
case DevicePropertyDeviceDescription:
|
|
||||||
RegistryPropertyName = L"DeviceDesc"; break;
|
|
||||||
case DevicePropertyLocationInformation:
|
|
||||||
RegistryPropertyName = L"LocationInformation"; break;
|
|
||||||
case DevicePropertyUINumber:
|
|
||||||
RegistryPropertyName = L"UINumber"; break;
|
|
||||||
default:
|
|
||||||
/* Should not happen */
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Registry property %S\n", RegistryPropertyName);
|
|
||||||
|
|
||||||
/* Open Enum key */
|
|
||||||
Status = IopOpenRegistryKeyEx(&EnumRootHandle, NULL,
|
|
||||||
&EnumRoot, KEY_READ);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open instance key */
|
|
||||||
Status = IopOpenRegistryKeyEx(&KeyHandle, EnumRootHandle,
|
|
||||||
&DeviceNode->InstancePath, KEY_READ);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status);
|
|
||||||
ZwClose(EnumRootHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate buffer to read as much data as required by the caller */
|
|
||||||
ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
|
|
||||||
Data[0]) + BufferLength;
|
|
||||||
ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
|
|
||||||
if (!ValueInformation)
|
|
||||||
{
|
|
||||||
ZwClose(KeyHandle);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the value */
|
|
||||||
RtlInitUnicodeString(&ValueName, RegistryPropertyName);
|
|
||||||
Status = ZwQueryValueKey(KeyHandle, &ValueName,
|
|
||||||
KeyValuePartialInformation, ValueInformation,
|
|
||||||
ValueInformationLength,
|
|
||||||
&ValueInformationLength);
|
|
||||||
ZwClose(KeyHandle);
|
|
||||||
|
|
||||||
/* Return data */
|
|
||||||
*ResultLength = ValueInformation->DataLength;
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ExFreePool(ValueInformation);
|
|
||||||
if (Status == STATUS_BUFFER_OVERFLOW)
|
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
|
||||||
DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status, *ResultLength);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Verify the value (NULL-terminated, correct format). */
|
|
||||||
RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
|
|
||||||
ValueInformation->DataLength);
|
|
||||||
ExFreePool(ValueInformation);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DevicePropertyBootConfiguration:
|
|
||||||
Length = 0;
|
|
||||||
if (DeviceNode->BootResources->Count != 0)
|
|
||||||
{
|
|
||||||
Length = IopCalculateResourceListSize(DeviceNode->BootResources);
|
|
||||||
}
|
|
||||||
Data = DeviceNode->BootResources;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* FIXME: use a translated boot configuration instead */
|
|
||||||
case DevicePropertyBootConfigurationTranslated:
|
|
||||||
Length = 0;
|
|
||||||
if (DeviceNode->BootResources->Count != 0)
|
|
||||||
{
|
|
||||||
Length = IopCalculateResourceListSize(DeviceNode->BootResources);
|
|
||||||
}
|
|
||||||
Data = DeviceNode->BootResources;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DevicePropertyEnumeratorName:
|
|
||||||
/* A buffer overflow can't happen here, since InstancePath
|
|
||||||
* always contains the enumerator name followed by \\ */
|
|
||||||
Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
|
|
||||||
ASSERT(Ptr);
|
|
||||||
Length = (Ptr - DeviceNode->InstancePath.Buffer) * sizeof(WCHAR);
|
|
||||||
Data = DeviceNode->InstancePath.Buffer;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DevicePropertyPhysicalDeviceObjectName:
|
|
||||||
Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&RequiredLength);
|
|
||||||
if (Status == STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
Length = 0;
|
|
||||||
Data = L"";
|
|
||||||
}
|
|
||||||
else if (Status == STATUS_INFO_LENGTH_MISMATCH)
|
|
||||||
{
|
|
||||||
ObjectNameInfoLength = RequiredLength;
|
|
||||||
ObjectNameInfo = ExAllocatePool(PagedPool, ObjectNameInfoLength);
|
|
||||||
if (!ObjectNameInfo)
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject,
|
|
||||||
ObjectNameInfo,
|
ObjectNameInfo,
|
||||||
ObjectNameInfoLength,
|
Length,
|
||||||
&RequiredLength);
|
ResultLength);
|
||||||
if (NT_SUCCESS(Status))
|
if (Status == STATUS_INFO_LENGTH_MISMATCH)
|
||||||
{
|
{
|
||||||
Length = ObjectNameInfo->Name.Length;
|
/* It's up to the caller to try again */
|
||||||
Data = ObjectNameInfo->Name.Buffer;
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return Status;
|
/* Return if successful */
|
||||||
|
if (NT_SUCCESS(Status)) PIP_RETURN_DATA(ObjectNameInfo->Name.Length,
|
||||||
|
ObjectNameInfo->Name.Buffer);
|
||||||
|
|
||||||
|
/* Let the caller know how big the name is */
|
||||||
|
*ResultLength -= sizeof(OBJECT_NAME_INFORMATION);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Handle the registry-based properties */
|
||||||
|
case DevicePropertyUINumber:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD);
|
||||||
|
case DevicePropertyLocationInformation:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION, REG_SZ);
|
||||||
|
case DevicePropertyDeviceDescription:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC, REG_SZ);
|
||||||
|
case DevicePropertyHardwareID:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID, REG_MULTI_SZ);
|
||||||
|
case DevicePropertyCompatibleIDs:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS, REG_MULTI_SZ);
|
||||||
|
case DevicePropertyBootConfiguration:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG, REG_RESOURCE_LIST);
|
||||||
|
case DevicePropertyClassName:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_CLASS, REG_SZ);
|
||||||
|
case DevicePropertyClassGuid:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID, REG_SZ);
|
||||||
|
case DevicePropertyDriverKeyName:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER, REG_SZ);
|
||||||
|
case DevicePropertyManufacturer:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_MFG, REG_SZ);
|
||||||
|
case DevicePropertyFriendlyName:
|
||||||
|
PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME, REG_SZ);
|
||||||
|
case DevicePropertyContainerID:
|
||||||
|
//PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
|
||||||
|
PIP_UNIMPLEMENTED();
|
||||||
|
case DevicePropertyRemovalPolicy:
|
||||||
|
PIP_UNIMPLEMENTED();
|
||||||
|
case DevicePropertyInstallState:
|
||||||
|
PIP_UNIMPLEMENTED();
|
||||||
|
case DevicePropertyResourceRequirements:
|
||||||
|
PIP_UNIMPLEMENTED();
|
||||||
|
case DevicePropertyAllocatedResources:
|
||||||
|
PIP_UNIMPLEMENTED();
|
||||||
|
default:
|
||||||
|
return STATUS_INVALID_PARAMETER_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Having a registry value name implies registry data */
|
||||||
|
if (ValueName)
|
||||||
|
{
|
||||||
|
/* We know up-front how much data to expect */
|
||||||
|
*ResultLength = BufferLength;
|
||||||
|
|
||||||
|
/* Go get the data, use the LogConf subkey if necessary */
|
||||||
|
Status = PiGetDeviceRegistryProperty(DeviceObject,
|
||||||
|
ValueType,
|
||||||
|
ValueName,
|
||||||
|
(DeviceProperty ==
|
||||||
|
DevicePropertyBootConfiguration) ?
|
||||||
|
L"LogConf": NULL,
|
||||||
|
PropertyBuffer,
|
||||||
|
ResultLength);
|
||||||
|
}
|
||||||
|
else if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* We know up-front how much data to expect, check the caller's buffer */
|
||||||
|
*ResultLength = ReturnLength;
|
||||||
|
if (ReturnLength <= BufferLength)
|
||||||
|
{
|
||||||
|
/* Buffer is all good, copy the data */
|
||||||
|
RtlCopyMemory(PropertyBuffer, Data, ReturnLength);
|
||||||
|
|
||||||
|
/* Check for properties that require a null-terminated string */
|
||||||
|
if ((DeviceProperty == DevicePropertyEnumeratorName) ||
|
||||||
|
(DeviceProperty == DevicePropertyPhysicalDeviceObjectName))
|
||||||
|
{
|
||||||
|
/* Terminate the string */
|
||||||
|
((PWCHAR)PropertyBuffer)[ReturnLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the success path */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return Status;
|
{
|
||||||
break;
|
/* Failure path */
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
default:
|
}
|
||||||
return STATUS_INVALID_PARAMETER_2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare returned values */
|
/* Free any allocation we may have made, and return the status code */
|
||||||
*ResultLength = Length;
|
if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
|
||||||
if (BufferLength < Length)
|
return Status;
|
||||||
{
|
|
||||||
if (ObjectNameInfo != NULL)
|
|
||||||
ExFreePool(ObjectNameInfo);
|
|
||||||
|
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
|
||||||
}
|
|
||||||
RtlCopyMemory(PropertyBuffer, Data, Length);
|
|
||||||
|
|
||||||
/* NULL terminate the string (if required) */
|
|
||||||
if (DeviceProperty == DevicePropertyEnumeratorName ||
|
|
||||||
DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
|
|
||||||
((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL;
|
|
||||||
|
|
||||||
if (ObjectNameInfo != NULL)
|
|
||||||
ExFreePool(ObjectNameInfo);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -634,25 +634,37 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
|
||||||
|
|
||||||
if (DeviceNode->ResourceList)
|
if (DeviceNode->ResourceList)
|
||||||
{
|
{
|
||||||
WCHAR NameBuff[256];
|
PWCHAR DeviceName = NULL;
|
||||||
UNICODE_STRING NameU;
|
UNICODE_STRING NameU;
|
||||||
UNICODE_STRING Suffix;
|
UNICODE_STRING Suffix;
|
||||||
ULONG OldLength;
|
ULONG OldLength = 0;
|
||||||
|
|
||||||
ASSERT(DeviceNode->ResourceListTranslated);
|
ASSERT(DeviceNode->ResourceListTranslated);
|
||||||
|
|
||||||
NameU.Buffer = NameBuff;
|
|
||||||
NameU.Length = 0;
|
|
||||||
NameU.MaximumLength = 256 * sizeof(WCHAR);
|
|
||||||
|
|
||||||
Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
|
Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
|
||||||
DevicePropertyPhysicalDeviceObjectName,
|
DevicePropertyPhysicalDeviceObjectName,
|
||||||
NameU.MaximumLength,
|
0,
|
||||||
NameU.Buffer,
|
NULL,
|
||||||
&OldLength);
|
&OldLength);
|
||||||
ASSERT(Status == STATUS_SUCCESS);
|
if ((OldLength != 0) && (Status == STATUS_BUFFER_TOO_SMALL))
|
||||||
|
{
|
||||||
|
DeviceName = ExAllocatePool(NonPagedPool, OldLength);
|
||||||
|
ASSERT(DeviceName);
|
||||||
|
|
||||||
NameU.Length = (USHORT)OldLength;
|
IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
|
||||||
|
DevicePropertyPhysicalDeviceObjectName,
|
||||||
|
OldLength,
|
||||||
|
DeviceName,
|
||||||
|
&OldLength);
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&NameU, DeviceName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Some failure */
|
||||||
|
ASSERT(!NT_SUCCESS(Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
RtlInitUnicodeString(&Suffix, L".Raw");
|
RtlInitUnicodeString(&Suffix, L".Raw");
|
||||||
RtlAppendUnicodeStringToString(&NameU, &Suffix);
|
RtlAppendUnicodeStringToString(&NameU, &Suffix);
|
||||||
|
@ -682,6 +694,8 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
|
||||||
DeviceNode->ResourceListTranslated,
|
DeviceNode->ResourceListTranslated,
|
||||||
IopCalculateResourceListSize(DeviceNode->ResourceListTranslated));
|
IopCalculateResourceListSize(DeviceNode->ResourceListTranslated));
|
||||||
ZwClose(PnpMgrLevel2);
|
ZwClose(PnpMgrLevel2);
|
||||||
|
ASSERT(DeviceName);
|
||||||
|
ExFreePool(DeviceName);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue