Implement IoRegisterDeviceInterface Modified: trunk/reactos/include/ddk/defines.h Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h Modified: trunk/reactos/ntoskrnl/io/deviface.c _____
Modified: trunk/reactos/include/ddk/defines.h --- trunk/reactos/include/ddk/defines.h 2005-04-20 19:33:48 UTC (rev 14719) +++ trunk/reactos/include/ddk/defines.h 2005-04-20 19:38:39 UTC (rev 14720) @@ -28,7 +28,8 @@
OBJ_CASE_INSENSITIVE = 0x40, OBJ_OPENIF = 0x80, OBJ_OPENLINK = 0x100, - OBJ_VALID_ATTRIBUTES = 0x1F2, + OBJ_KERNEL_HANDLE = 0x200, + OBJ_VALID_ATTRIBUTES = 0x3F2, };
/* _____
Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h --- trunk/reactos/ntoskrnl/include/ntoskrnl.h 2005-04-20 19:33:48 UTC (rev 14719) +++ trunk/reactos/ntoskrnl/include/ntoskrnl.h 2005-04-20 19:38:39 UTC (rev 14720) @@ -64,6 +64,15 @@
#include <pseh.h>
+#ifndef RTL_CONSTANT_STRING +#define RTL_CONSTANT_STRING(__SOURCE_STRING__) \ +{ \ + sizeof(__SOURCE_STRING__) - sizeof((__SOURCE_STRING__)[0]), \ + sizeof(__SOURCE_STRING__), \ + (__SOURCE_STRING__) \ +} +#endif + #ifdef DBG #ifndef PAGED_CODE #define PAGED_CODE() \ _____
Modified: trunk/reactos/ntoskrnl/io/deviface.c --- trunk/reactos/ntoskrnl/io/deviface.c 2005-04-20 19:33:48 UTC (rev 14719) +++ trunk/reactos/ntoskrnl/io/deviface.c 2005-04-20 19:38:39 UTC (rev 14720) @@ -16,11 +16,10 @@
#define NDEBUG #include <internal/debug.h>
-DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, - 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18); - /* FUNCTIONS *****************************************************************/
+static PWCHAR BaseKeyString = L"\Registry\Machine\System\CurrentControlSet\Control\DeviceClasses \"; + /* * @unimplemented */ @@ -93,7 +92,6 @@ IN ULONG Flags, OUT PWSTR *SymbolicLinkList) { - PWCHAR BaseKeyString = L"\Registry\Machine\System\CurrentControlSet\Control\DeviceClasses \"; PWCHAR BaseInterfaceString = L"\Registry\Machine\System\CurrentControlSet\Services\"; UNICODE_STRING GuidString; UNICODE_STRING BaseKeyName; @@ -561,7 +559,7 @@ }
/* - * @unimplemented + * @implemented */
NTSTATUS STDCALL @@ -571,16 +569,212 @@ IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName) { - PWCHAR KeyNameString = L"\Device\Serenum"; - - DPRINT("IoRegisterDeviceInterface called (UNIMPLEMENTED)\n"); - if (!memcmp(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR, sizeof(GUID))) + PUNICODE_STRING InstancePath; + UNICODE_STRING GuidString; + UNICODE_STRING SubKeyName; + UNICODE_STRING BaseKeyName; + UNICODE_STRING DeviceInstance = RTL_CONSTANT_STRING(L"DeviceInstance"); + UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); + HANDLE InterfaceKey; + HANDLE SubKey; + ULONG StartIndex; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG i; + NTSTATUS Status; + + Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); + if (!NT_SUCCESS(Status)) { - RtlInitUnicodeString(SymbolicLinkName, KeyNameString); - return STATUS_SUCCESS; + DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); + return Status; } - - return STATUS_INVALID_DEVICE_REQUEST; + + /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\DeviceClasses{GUID}##?#ACPI#PNP0501#1#{G UID} */ + InstancePath = &PhysicalDeviceObject->DeviceObjectExtension->DeviceNode->InstancePath; + BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); + BaseKeyName.MaximumLength = BaseKeyName.Length + + GuidString.Length + + 5 * sizeof(WCHAR) /* 5 = size of ##?# */ + + InstancePath->Length + + sizeof(WCHAR) /* 1 = size of # */ + + GuidString.Length; + BaseKeyName.Buffer = ExAllocatePool( + NonPagedPool, + BaseKeyName.MaximumLength); + if (!BaseKeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy(BaseKeyName.Buffer, BaseKeyString); + RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); + RtlAppendUnicodeToString(&BaseKeyName, L"\##?#"); + StartIndex = BaseKeyName.Length / sizeof(WCHAR); + RtlAppendUnicodeStringToString(&BaseKeyName, InstancePath); + for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) + { + if (BaseKeyName.Buffer[StartIndex + i] == '\') + BaseKeyName.Buffer[StartIndex + i] = '#'; + } + RtlAppendUnicodeToString(&BaseKeyName, L"#"); + RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); + + /* Create BaseKeyName key in registry */ + InitializeObjectAttributes( + &ObjectAttributes, + &BaseKeyName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, + NULL, /* RootDirectory */ + NULL); /* SecurityDescriptor */ + + Status = ZwCreateKey( + &InterfaceKey, + KEY_WRITE, + &ObjectAttributes, + 0, /* TileIndex */ + NULL, /* Class */ + REG_OPTION_VOLATILE, + NULL); /* Disposition */ + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Write DeviceInstance entry. Value is InstancePath */ + Status = ZwSetValueKey( + InterfaceKey, + &DeviceInstance, + 0, /* TileIndex */ + REG_SZ, + InstancePath->Buffer, + InstancePath->Length); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ZwClose(InterfaceKey); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Create subkey. Name is #ReferenceString */ + SubKeyName.Length = 0; + SubKeyName.MaximumLength = sizeof(WCHAR); + if (ReferenceString && ReferenceString->Length) + SubKeyName.MaximumLength += ReferenceString->Length; + SubKeyName.Buffer = ExAllocatePool( + NonPagedPool, + SubKeyName.MaximumLength); + if (!SubKeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + ZwClose(InterfaceKey); + ExFreePool(BaseKeyName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlAppendUnicodeToString(&SubKeyName, L"#"); + if (ReferenceString && ReferenceString->Length) + RtlAppendUnicodeStringToString(&SubKeyName, ReferenceString); + + /* Create SubKeyName key in registry */ + InitializeObjectAttributes( + &ObjectAttributes, + &SubKeyName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + InterfaceKey, /* RootDirectory */ + NULL); /* SecurityDescriptor */ + + Status = ZwCreateKey( + &SubKey, + KEY_WRITE, + &ObjectAttributes, + 0, /* TileIndex */ + NULL, /* Class */ + REG_OPTION_VOLATILE, + NULL); /* Disposition */ + + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); + ZwClose(InterfaceKey); + ExFreePool(BaseKeyName.Buffer); + return Status; + } + + /* Create symbolic link name: \?\ACPI#PNP0501#1#{GUID}\ReferenceString */ + SymbolicLinkName->Length = 0; + SymbolicLinkName->MaximumLength = SymbolicLinkName->Length + + 4 * sizeof(WCHAR) /* 5 = size of \??\ */ + + InstancePath->Length + + sizeof(WCHAR) /* 1 = size of # */ + + GuidString.Length + + sizeof(WCHAR); /* final NULL */ + if (ReferenceString && ReferenceString->Length) + SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length; + SymbolicLinkName->Buffer = ExAllocatePool( + NonPagedPool, + SymbolicLinkName->MaximumLength); + if (!SymbolicLinkName->Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + ZwClose(InterfaceKey); + ZwClose(SubKey); + ExFreePool(SubKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlAppendUnicodeToString(SymbolicLinkName, L"\\??\"); + StartIndex = SymbolicLinkName->Length / sizeof(WCHAR); + RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath); + for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) + { + if (SymbolicLinkName->Buffer[StartIndex + i] == '\') + SymbolicLinkName->Buffer[StartIndex + i] = '#'; + } + RtlAppendUnicodeToString(SymbolicLinkName, L"#"); + RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString); + if (ReferenceString && ReferenceString->Length) + { + RtlAppendUnicodeToString(SymbolicLinkName, L"\"); + RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); + } + SymbolicLinkName->Buffer[SymbolicLinkName->Length] = '\0'; + + /* Create symbolic link */ + Status = IoCreateSymbolicLink(SymbolicLinkName, InstancePath); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateSymbolicLink() failed with status 0x%08lx\n", Status); + ZwClose(InterfaceKey); + ZwClose(SubKey); + ExFreePool(SubKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + ExFreePool(SymbolicLinkName->Buffer); + return Status; + } + + /* Write symbolic link name in registry */ + Status = ZwSetValueKey( + SubKey, + &SymbolicLink, + 0, /* TileIndex */ + REG_SZ, + SymbolicLinkName->Buffer, + SymbolicLinkName->Length); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ExFreePool(SymbolicLinkName->Buffer); + } + + ZwClose(InterfaceKey); + ZwClose(SubKey); + ExFreePool(SubKeyName.Buffer); + ExFreePool(BaseKeyName.Buffer); + + return Status; }
/* @@ -592,7 +786,8 @@ IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable) { - return STATUS_NOT_IMPLEMENTED; + DPRINT("IoSetDeviceInterfaceState called (UNIMPLEMENTED)\n"); + return STATUS_SUCCESS; }
/* EOF */