- Removed the incorrect implementations of Device Interface functions.

- Added verified implementation of IoGetDeviceInterfaces written by Matthew Brace and fixed by me.

svn path=/trunk/; revision=8465
This commit is contained in:
Filip Navara 2004-02-29 11:34:40 +00:00
parent 9a5bc1ce43
commit e5185d34b3

View file

@ -6,247 +6,506 @@
* PROGRAMMER: Filip Navara (xnavara@volny.cz)
* Matthew Brace (ismarc@austin.rr.com)
* UPDATE HISTORY:
* 22/09/2003 FiN Created
* 22/09/2003 FiN Created
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
#include <reactos/bugcodes.h>
#include <internal/io.h>
#include <internal/po.h>
#include <internal/ldr.h>
#include <internal/module.h>
//#define NDEBUG
#include <internal/debug.h>
#include <ole32/guiddef.h>
#ifdef DEFINE_GUID
DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
#endif // DEFINE_GUID
#endif
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*
* returns a key to a specific device interface
* @unimplemented
*/
NTSTATUS
STDCALL
NTSTATUS STDCALL
IoOpenDeviceInterfaceRegistryKey(
IN PUNICODE_STRING SymbolicLinkName,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE DeviceInterfaceKey)
IN PUNICODE_STRING SymbolicLinkName,
IN ACCESS_MASK DesiredAccess,
OUT PHANDLE DeviceInterfaceKey)
{
NTSTATUS Status;
POBJECT_ATTRIBUTES ObjectAttributes;
InitializeObjectAttributes( ObjectAttributes,
SymbolicLinkName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
Status = ZwOpenKey( DeviceInterfaceKey,
DesiredAccess,
ObjectAttributes );
if( !NT_SUCCESS( Status ) )
{
DPRINT( "ZwOpenKey() failed" );
return Status;
}
return STATUS_SUCCESS;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
* @unimplemented
*/
NTSTATUS
STDCALL
NTSTATUS STDCALL
IoGetDeviceInterfaceAlias(
IN PUNICODE_STRING SymbolicLinkName,
IN CONST GUID *AliasInterfaceClassGuid,
OUT PUNICODE_STRING AliasSymbolicLinkName)
IN PUNICODE_STRING SymbolicLinkName,
IN CONST GUID *AliasInterfaceClassGuid,
OUT PUNICODE_STRING AliasSymbolicLinkName)
{
PUNICODE_STRING GuidString;
PUNICODE_STRING BaseKeyName;
PUNICODE_STRING AliasKeyName;
PUNICODE_STRING bipName;
PUNICODE_STRING InLinkName;
PHANDLE InterfaceKey;
BOOLEAN CaseInsensitive = TRUE;
PKEY_FULL_INFORMATION fip;
PKEY_BASIC_INFORMATION bip;
PWCHAR pdest;
LONG status;
NTSTATUS Status;
ULONG Size;
ULONG i = 0;
PWCHAR BaseKeyString = L"\\HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Class\\";
PWCHAR BaseInterfaceString = L"\\HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\";
status = RtlStringFromGUID( AliasInterfaceClassGuid, GuidString );
if( !status )
{
DPRINT( "RtlStringFromGUID() Failed.\n" );
return STATUS_INVALID_HANDLE;
}
RtlInitUnicodeString( BaseKeyName, BaseKeyString );
RtlInitUnicodeString( AliasKeyName, BaseInterfaceString );
BaseKeyName->MaximumLength += sizeof( GuidString );
RtlAppendUnicodeStringToString( BaseKeyName, GuidString );
Status = IoOpenDeviceInterfaceRegistryKey( BaseKeyName,
GENERIC_READ,
InterfaceKey);
if( !NT_SUCCESS( Status ) )
{
DPRINT( "IoGetDeviceInterfaceKey() failed.\n" );
return Status;
}
Status = ZwQueryKey( InterfaceKey,
KeyFullInformation,
NULL,
0,
&Size );
if( !NT_SUCCESS( Status) )
{
DPRINT( "ZwQueryKey() failed.\n" );
return Status;
}
fip = (PKEY_FULL_INFORMATION) ExAllocatePool(PagedPool, Size);
ZwQueryKey( InterfaceKey,
KeyFullInformation,
fip,
Size,
&Size );
while( i < fip->SubKeys )
{
i++;
ZwEnumerateKey( InterfaceKey,
i,
KeyBasicInformation,
NULL,
0,
&Size );
bip = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool, Size);
ZwEnumerateKey( InterfaceKey,
i,
KeyBasicInformation,
bip,
Size,
&Size );
//check bip->Name
RtlInitUnicodeString( bipName, NULL );
RtlInitUnicodeString( InLinkName, NULL );
bipName->Length = wcslen(bip->Name);
bipName->MaximumLength = wcslen(bip->Name);
bipName->Buffer = bip->Name;
AliasKeyName->MaximumLength += sizeof(bipName);
RtlAppendUnicodeStringToString( AliasKeyName, bipName );
pdest = wcsstr( SymbolicLinkName->Buffer, L"Services\\" );
InLinkName->Length = wcslen(pdest);
InLinkName->MaximumLength = wcslen(pdest);
InLinkName->Buffer = pdest;
status = 1;
status = RtlCompareUnicodeString( bipName,
InLinkName,
CaseInsensitive );
if( status == 0 )
{
AliasSymbolicLinkName = AliasKeyName;
return STATUS_SUCCESS;
}
ExFreePool(bip);
}
ExFreePool(fip);
return STATUS_INVALID_HANDLE;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
* IoGetDeviceInterfaces
*
* Returns a list of device interfaces of a particular device interface class.
*
* Parameters
* InterfaceClassGuid
* Points to a class GUID specifying the device interface class.
*
* PhysicalDeviceObject
* Points to an optional PDO that narrows the search to only the
* device interfaces of the device represented by the PDO.
*
* Flags
* Specifies flags that modify the search for device interfaces. The
* DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
* returned symbolic links should contain also disabled device
* interfaces in addition to the enabled ones.
*
* SymbolicLinkList
* Points to a character pointer that is filled in on successful return
* with a list of unicode strings identifying the device interfaces
* that match the search criteria. The newly allocated buffer contains
* a list of symbolic link names. Each unicode string in the list is
* null-terminated; the end of the whole list is marked by an additional
* NULL. The caller is responsible for freeing the buffer (ExFreePool)
* when it is no longer needed.
* If no device interfaces match the search criteria, this routine
* returns STATUS_SUCCESS and the string contains a single NULL
* character.
*
* Status
* @implemented
*
* The parameters PhysicalDeviceObject and Flags aren't correctly
* processed. Rest of the cases was tested under Windows(R) XP and
* the function worked correctly.
*/
NTSTATUS
STDCALL
NTSTATUS STDCALL
IoGetDeviceInterfaces(
IN CONST GUID *InterfaceClassGuid,
IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
IN ULONG Flags,
OUT PWSTR *SymbolicLinkList)
IN CONST GUID *InterfaceClassGuid,
IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
IN ULONG Flags,
OUT PWSTR *SymbolicLinkList)
{
DPRINT("IoGetDeviceInterfaces called (UNIMPLEMENTED)\n");
return STATUS_NOT_IMPLEMENTED;
PWCHAR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
PWCHAR BaseInterfaceString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
UNICODE_STRING GuidString;
UNICODE_STRING BaseKeyName;
UNICODE_STRING AliasKeyName;
UNICODE_STRING SymbolicLink;
UNICODE_STRING SubKeyName;
UNICODE_STRING SymbolicLinkKeyName;
UNICODE_STRING TempString;
HANDLE InterfaceKey;
HANDLE SubKey;
HANDLE SymbolicLinkKey;
PKEY_FULL_INFORMATION fip;
PKEY_BASIC_INFORMATION bip;
PKEY_VALUE_PARTIAL_INFORMATION vpip;
PWCHAR SymLinkList = NULL;
ULONG SymLinkListSize;
NTSTATUS Status;
ULONG Size = 0;
ULONG i = 0;
OBJECT_ATTRIBUTES ObjectAttributes;
Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlStringFromGUID() Failed.\n");
return STATUS_INVALID_HANDLE;
}
RtlInitUnicodeString(&AliasKeyName, BaseInterfaceString);
RtlInitUnicodeString(&SymbolicLink, L"SymbolicLink");
BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR);
BaseKeyName.MaximumLength = BaseKeyName.Length + (38 * sizeof(WCHAR));
BaseKeyName.Buffer = ExAllocatePool(
NonPagedPool,
BaseKeyName.MaximumLength);
assert(BaseKeyName.Buffer != NULL);
wcscpy(BaseKeyName.Buffer, BaseKeyString);
RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString);
if (PhysicalDeviceObject)
{
WCHAR GuidBuffer[32];
UNICODE_STRING PdoGuidString;
RtlFreeUnicodeString(&BaseKeyName);
IoGetDeviceProperty(
PhysicalDeviceObject,
DevicePropertyClassGuid,
sizeof(GuidBuffer),
GuidBuffer,
&Size);
RtlInitUnicodeString(&PdoGuidString, GuidBuffer);
if (RtlCompareUnicodeString(&GuidString, &PdoGuidString, TRUE))
{
DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n");
return STATUS_INVALID_HANDLE;
}
DPRINT("IoGetDeviceInterfaces() called with PDO, not implemented.\n");
return STATUS_NOT_IMPLEMENTED;
}
else
{
InitializeObjectAttributes(
&ObjectAttributes,
&BaseKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(
&InterfaceKey,
KEY_READ,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status);
RtlFreeUnicodeString(&BaseKeyName);
return Status;
}
Status = ZwQueryKey(
InterfaceKey,
KeyFullInformation,
NULL,
0,
&Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
return Status;
}
fip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(fip != NULL);
Status = ZwQueryKey(
InterfaceKey,
KeyFullInformation,
fip,
Size,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
return Status;
}
for (; i < fip->SubKeys; i++)
{
Status = ZwEnumerateKey(
InterfaceKey,
i,
KeyBasicInformation,
NULL,
0,
&Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
return Status;
}
bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(bip != NULL);
Status = ZwEnumerateKey(
InterfaceKey,
i,
KeyBasicInformation,
bip,
Size,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
ExFreePool(bip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
return Status;
}
SubKeyName.Length = 0;
SubKeyName.MaximumLength = BaseKeyName.Length + bip->NameLength + sizeof(WCHAR);
SubKeyName.Buffer = ExAllocatePool(NonPagedPool, SubKeyName.MaximumLength);
assert(SubKeyName.Buffer != NULL);
TempString.Length = TempString.MaximumLength = bip->NameLength;
TempString.Buffer = bip->Name;
RtlCopyUnicodeString(&SubKeyName, &BaseKeyName);
RtlAppendUnicodeToString(&SubKeyName, L"\\");
RtlAppendUnicodeStringToString(&SubKeyName, &TempString);
ExFreePool(bip);
InitializeObjectAttributes(
&ObjectAttributes,
&SubKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(
&SubKey,
KEY_READ,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
return Status;
}
Status = ZwEnumerateKey(
SubKey,
0,
KeyBasicInformation,
NULL,
0,
&Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(bip != NULL);
Status = ZwEnumerateKey(
SubKey,
0,
KeyBasicInformation,
bip,
Size,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
ExFreePool(bip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
SymbolicLinkKeyName.Length = 0;
SymbolicLinkKeyName.MaximumLength = SubKeyName.Length + bip->NameLength + sizeof(WCHAR);
SymbolicLinkKeyName.Buffer = ExAllocatePool(NonPagedPool, SymbolicLinkKeyName.MaximumLength);
assert(SymbolicLinkKeyName.Buffer != NULL);
TempString.Length = TempString.MaximumLength = bip->NameLength;
TempString.Buffer = bip->Name;
RtlCopyUnicodeString(&SymbolicLinkKeyName, &SubKeyName);
RtlAppendUnicodeToString(&SymbolicLinkKeyName, L"\\");
RtlAppendUnicodeStringToString(&SymbolicLinkKeyName, &TempString);
ExFreePool(bip);
InitializeObjectAttributes(
&ObjectAttributes,
&SymbolicLinkKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(
&SymbolicLinkKey,
KEY_READ,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
Status = ZwQueryValueKey(
SymbolicLinkKey,
&SymbolicLink,
KeyValuePartialInformation,
NULL,
0,
&Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwQueryValueKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
vpip = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(vpip != NULL);
Status = ZwQueryValueKey(
SymbolicLinkKey,
&SymbolicLink,
KeyValuePartialInformation,
vpip,
Size,
&Size);
if (!NT_SUCCESS(Status))
{
ExFreePool(fip);
ExFreePool(vpip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
/* Put the name in the string here */
if (SymLinkList == NULL)
{
SymLinkListSize = vpip->DataLength;
SymLinkList = ExAllocatePool(NonPagedPool, SymLinkListSize + sizeof(WCHAR));
assert(SymLinkList != NULL);
RtlCopyMemory(SymLinkList, vpip->Data, vpip->DataLength);
SymLinkList[vpip->DataLength / sizeof(WCHAR)] = 0;
SymLinkList[1] = '?';
}
else
{
PWCHAR OldSymLinkList;
ULONG OldSymLinkListSize;
PWCHAR SymLinkListPtr;
OldSymLinkList = SymLinkList;
OldSymLinkListSize = SymLinkListSize;
SymLinkListSize += vpip->DataLength;
SymLinkList = ExAllocatePool(NonPagedPool, SymLinkListSize + sizeof(WCHAR));
assert(SymLinkList != NULL);
RtlCopyMemory(SymLinkList, OldSymLinkList, OldSymLinkListSize);
ExFreePool(OldSymLinkList);
SymLinkListPtr = SymLinkList + (OldSymLinkListSize / sizeof(WCHAR));
RtlCopyMemory(SymLinkListPtr, vpip->Data, vpip->DataLength);
SymLinkListPtr[vpip->DataLength / sizeof(WCHAR)] = 0;
SymLinkListPtr[1] = '?';
}
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ExFreePool(vpip);
}
if (SymLinkList != NULL)
SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0;
*SymbolicLinkList = SymLinkList;
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey);
ExFreePool(fip);
}
return STATUS_SUCCESS;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
NTSTATUS STDCALL
IoRegisterDeviceInterface(
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN CONST GUID *InterfaceClassGuid,
IN PUNICODE_STRING ReferenceString OPTIONAL,
OUT PUNICODE_STRING SymbolicLinkName)
IN PDEVICE_OBJECT PhysicalDeviceObject,
IN CONST GUID *InterfaceClassGuid,
IN PUNICODE_STRING ReferenceString OPTIONAL,
OUT PUNICODE_STRING SymbolicLinkName)
{
PWCHAR KeyNameString = L"\\Device\\Serenum";
PWCHAR KeyNameString = L"\\Device\\Serenum";
DPRINT("IoRegisterDeviceInterface called (UNIMPLEMENTED)\n");
if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR))
{
RtlInitUnicodeString(SymbolicLinkName, KeyNameString);
return STATUS_SUCCESS;
}
return STATUS_INVALID_DEVICE_REQUEST;
// return STATUS_NOT_IMPLEMENTED;
DPRINT("IoRegisterDeviceInterface called (UNIMPLEMENTED)\n");
if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR))
{
RtlInitUnicodeString(SymbolicLinkName, KeyNameString);
return STATUS_SUCCESS;
}
return STATUS_INVALID_DEVICE_REQUEST;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
IoSetDeviceInterfaceState(
IN PUNICODE_STRING SymbolicLinkName,
IN BOOLEAN Enable)
{
DPRINT("IoSetDeviceInterfaceState called (UNIMPLEMENTED)\n");
return STATUS_SUCCESS;
// return STATUS_OBJECT_NAME_EXISTS;
// return STATUS_OBJECT_NAME_NOT_FOUND;
// return STATUS_NOT_IMPLEMENTED;
NTSTATUS STDCALL
IoSetDeviceInterfaceState(
IN PUNICODE_STRING SymbolicLinkName,
IN BOOLEAN Enable)
{
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */