- Add support for reference strings in IoOpenDeviceInterfaceRegistryKey

svn path=/trunk/; revision=46681
This commit is contained in:
Johannes Anderwald 2010-04-02 14:01:55 +00:00
parent 90a11f48e9
commit 95650313d9

View file

@ -51,31 +51,29 @@ IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName,
OUT PHANDLE DeviceInterfaceKey) OUT PHANDLE DeviceInterfaceKey)
{ {
WCHAR StrBuff[MAX_PATH], PathBuff[MAX_PATH]; WCHAR StrBuff[MAX_PATH], PathBuff[MAX_PATH];
PWCHAR Guid; PWCHAR Guid, RefString;
UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT L"\\");
UNICODE_STRING DevParamU = RTL_CONSTANT_STRING(L"\\Device Parameters"); UNICODE_STRING DevParamU = RTL_CONSTANT_STRING(L"\\Device Parameters");
UNICODE_STRING PrefixU = RTL_CONSTANT_STRING(L"\\??\\"); UNICODE_STRING PrefixU = RTL_CONSTANT_STRING(L"\\??\\");
UNICODE_STRING KeyPath, KeyName; UNICODE_STRING KeyPath, KeyName;
UNICODE_STRING MatchableGuid; UNICODE_STRING MatchableGuid;
HANDLE GuidKey, ChildKey; UNICODE_STRING GuidString;
HANDLE GuidKey, hInterfaceKey;
ULONG Index = 0; ULONG Index = 0;
PKEY_BASIC_INFORMATION KeyInformation; PKEY_BASIC_INFORMATION KeyInformation;
ULONG KeyInformationLength; ULONG KeyInformationLength;
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
ULONG KeyValueInformationLength;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status; NTSTATUS Status;
ULONG RequiredLength; ULONG RequiredLength;
MatchableGuid.Length = 0; swprintf(StrBuff, L"##?#%s", &SymbolicLinkName->Buffer[PrefixU.Length / sizeof(WCHAR)]);
MatchableGuid.Length += swprintf(StrBuff,
L"##?#%ls",
&SymbolicLinkName->Buffer[PrefixU.Length / sizeof(WCHAR)]);
StrBuff[++MatchableGuid.Length] = UNICODE_NULL;
MatchableGuid.Buffer = StrBuff; RefString = wcsstr(StrBuff, L"\\");
MatchableGuid.MaximumLength = MAX_PATH * sizeof(WCHAR); if (RefString)
MatchableGuid.Length = (MatchableGuid.Length-1) * sizeof(WCHAR); {
RefString[0] = 0;
}
RtlInitUnicodeString(&MatchableGuid, StrBuff);
Guid = wcsstr(StrBuff, L"{"); Guid = wcsstr(StrBuff, L"{");
if (!Guid) if (!Guid)
@ -85,8 +83,11 @@ IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName,
KeyPath.Length = 0; KeyPath.Length = 0;
KeyPath.MaximumLength = MAX_PATH * sizeof(WCHAR); KeyPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
GuidString.Buffer = Guid;
GuidString.Length = GuidString.MaximumLength = 38 * sizeof(WCHAR);
RtlAppendUnicodeToString(&KeyPath, BaseKeyString); RtlAppendUnicodeToString(&KeyPath, BaseKeyString);
RtlAppendUnicodeToString(&KeyPath, Guid); RtlAppendUnicodeStringToString(&KeyPath, &GuidString);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&KeyPath, &KeyPath,
@ -142,73 +143,62 @@ IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName,
KeyName.Buffer = KeyInformation->Name; KeyName.Buffer = KeyInformation->Name;
if (!RtlEqualUnicodeString(&KeyName, &MatchableGuid, TRUE)) if (!RtlEqualUnicodeString(&KeyName, &MatchableGuid, TRUE))
{
ExFreePool(KeyInformation);
continue; continue;
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
GuidKey,
NULL);
Status = ZwOpenKey(&ChildKey, KEY_QUERY_VALUE, &ObjectAttributes);
ZwClose(GuidKey);
if (!NT_SUCCESS(Status))
return Status;
RtlInitUnicodeString(&KeyName, L"DeviceInstance");
Status = ZwQueryValueKey(ChildKey,
&KeyName,
KeyValuePartialInformation,
NULL,
0,
&RequiredLength);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
KeyValueInformationLength = RequiredLength;
KeyValueInformation = ExAllocatePool(PagedPool, KeyValueInformationLength);
if (!KeyValueInformation)
{
ZwClose(ChildKey);
return Status;
} }
Status = ZwQueryValueKey(ChildKey, KeyPath.Length = 0;
&KeyName, RtlAppendUnicodeStringToString(&KeyPath, &KeyName);
KeyValuePartialInformation, RtlAppendUnicodeToString(&KeyPath, L"\\");
KeyValueInformation,
KeyValueInformationLength, /* check for presence of a reference string */
&RequiredLength); if (RefString)
{
/* append reference string */
RefString[0] = L'#';
RtlInitUnicodeString(&KeyName, RefString);
} }
else else
{ {
ZwClose(ChildKey); /* no reference string */
return STATUS_OBJECT_PATH_NOT_FOUND; RtlInitUnicodeString(&KeyName, L"#");
} }
ZwClose(ChildKey);
if (!NT_SUCCESS(Status))
return Status;
KeyPath.Length = 0;
KeyName.Length = KeyName.MaximumLength = KeyValueInformation->DataLength;
KeyName.Buffer = (PWCHAR)KeyValueInformation->Data;
RtlAppendUnicodeStringToString(&KeyPath, &EnumU);
RtlAppendUnicodeStringToString(&KeyPath, &KeyName); RtlAppendUnicodeStringToString(&KeyPath, &KeyName);
RtlAppendUnicodeStringToString(&KeyPath, &DevParamU);
/* initialize reference string attributes */
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&KeyPath, &KeyPath,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
0, GuidKey,
NULL);
Status = ZwCreateKey(DeviceInterfaceKey,
DesiredAccess,
&ObjectAttributes,
0,
NULL,
REG_OPTION_NON_VOLATILE,
NULL); NULL);
/* now open device interface key */
Status = ZwOpenKey(&hInterfaceKey, KEY_CREATE_SUB_KEY, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* check if it provides a DeviceParameters key */
InitializeObjectAttributes(&ObjectAttributes, &DevParamU, OBJ_CASE_INSENSITIVE, hInterfaceKey, NULL);
Status = ZwCreateKey(DeviceInterfaceKey, DesiredAccess, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
if (NT_SUCCESS(Status))
{
/* DeviceParameters key present */
ZwClose(hInterfaceKey);
}
else
{
/* fall back to device interface */
*DeviceInterfaceKey = hInterfaceKey;
Status = STATUS_SUCCESS;
}
}
/* close class key */
ZwClose(GuidKey);
ExFreePool(KeyInformation);
return Status; return Status;
} }