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 **********************************************************/
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -3016,281 +3251,205 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
|
|||
{
|
||||
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
|
||||
DEVICE_CAPABILITIES DeviceCaps;
|
||||
ULONG Length;
|
||||
ULONG ReturnLength = 0, Length = 0, ValueType;
|
||||
PWCHAR ValueName = NULL, EnumeratorNameEnd, DeviceInstanceName;
|
||||
PVOID Data = NULL;
|
||||
PWSTR Ptr;
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status = STATUS_BUFFER_TOO_SMALL;
|
||||
GUID BusTypeGuid;
|
||||
POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
|
||||
ULONG RequiredLength, ObjectNameInfoLength;
|
||||
|
||||
DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
|
||||
|
||||
/* Assume failure */
|
||||
*ResultLength = 0;
|
||||
|
||||
if (DeviceNode == NULL)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
/* Only PDOs can call this */
|
||||
if (!DeviceNode) return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
/* Handle all properties */
|
||||
switch (DeviceProperty)
|
||||
{
|
||||
case DevicePropertyBusNumber:
|
||||
Length = sizeof(ULONG);
|
||||
Data = &DeviceNode->ChildBusNumber;
|
||||
break;
|
||||
case DevicePropertyBusTypeGuid:
|
||||
|
||||
/* Complete, untested */
|
||||
case DevicePropertyBusTypeGuid:
|
||||
/* Sanity check */
|
||||
if ((DeviceNode->ChildBusTypeIndex != 0xFFFF) &&
|
||||
(DeviceNode->ChildBusTypeIndex < PnpBusTypeGuidList->GuidCount))
|
||||
{
|
||||
/* Return the GUID */
|
||||
*ResultLength = sizeof(GUID);
|
||||
/* Get the GUID from the internal cache */
|
||||
Status = PnpBusTypeGuidGet(DeviceNode->ChildBusTypeIndex, &BusTypeGuid);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Check if the buffer given was large enough */
|
||||
if (BufferLength < *ResultLength)
|
||||
/* This is the format of the returned data */
|
||||
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;
|
||||
}
|
||||
|
||||
/* Copy the GUID */
|
||||
RtlCopyMemory(PropertyBuffer,
|
||||
&(PnpBusTypeGuidList->Guids[DeviceNode->ChildBusTypeIndex]),
|
||||
sizeof(GUID));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
break;
|
||||
/* This is the format of the returned data */
|
||||
PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated
|
||||
DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated
|
||||
|
||||
case DevicePropertyLegacyBusType:
|
||||
Length = sizeof(INTERFACE_TYPE);
|
||||
Data = &DeviceNode->ChildInterfaceType;
|
||||
break;
|
||||
case DevicePropertyPhysicalDeviceObjectName:
|
||||
|
||||
case DevicePropertyAddress:
|
||||
/* Query the device caps */
|
||||
Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps);
|
||||
if (NT_SUCCESS(Status) && (DeviceCaps.Address != MAXULONG))
|
||||
{
|
||||
/* Return length */
|
||||
*ResultLength = sizeof(ULONG);
|
||||
/* Sanity check for Unicode-sized string */
|
||||
ASSERT((BufferLength & 1) == 0);
|
||||
|
||||
/* Check if the buffer given was large enough */
|
||||
if (BufferLength < *ResultLength)
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
/* Allocate name buffer */
|
||||
Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION);
|
||||
ObjectNameInfo = ExAllocatePool(PagedPool, Length);
|
||||
if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* 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,
|
||||
/* Query the PDO name */
|
||||
Status = ObQueryNameString(DeviceObject,
|
||||
ObjectNameInfo,
|
||||
ObjectNameInfoLength,
|
||||
&RequiredLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
Length,
|
||||
ResultLength);
|
||||
if (Status == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
Length = ObjectNameInfo->Name.Length;
|
||||
Data = ObjectNameInfo->Name.Buffer;
|
||||
/* It's up to the caller to try again */
|
||||
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
|
||||
return Status;
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
{
|
||||
/* Failure path */
|
||||
Status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare returned values */
|
||||
*ResultLength = Length;
|
||||
if (BufferLength < Length)
|
||||
{
|
||||
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;
|
||||
/* Free any allocation we may have made, and return the status code */
|
||||
if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -634,25 +634,37 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
|
|||
|
||||
if (DeviceNode->ResourceList)
|
||||
{
|
||||
WCHAR NameBuff[256];
|
||||
PWCHAR DeviceName = NULL;
|
||||
UNICODE_STRING NameU;
|
||||
UNICODE_STRING Suffix;
|
||||
ULONG OldLength;
|
||||
ULONG OldLength = 0;
|
||||
|
||||
ASSERT(DeviceNode->ResourceListTranslated);
|
||||
|
||||
NameU.Buffer = NameBuff;
|
||||
NameU.Length = 0;
|
||||
NameU.MaximumLength = 256 * sizeof(WCHAR);
|
||||
|
||||
Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
|
||||
DevicePropertyPhysicalDeviceObjectName,
|
||||
NameU.MaximumLength,
|
||||
NameU.Buffer,
|
||||
0,
|
||||
NULL,
|
||||
&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");
|
||||
RtlAppendUnicodeStringToString(&NameU, &Suffix);
|
||||
|
@ -682,6 +694,8 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2
|
|||
DeviceNode->ResourceListTranslated,
|
||||
IopCalculateResourceListSize(DeviceNode->ResourceListTranslated));
|
||||
ZwClose(PnpMgrLevel2);
|
||||
ASSERT(DeviceName);
|
||||
ExFreePool(DeviceName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue