diff --git a/reactos/drivers/drivers.rbuild b/reactos/drivers/drivers.rbuild
index 9db7802ce64..24f4bd6c953 100644
--- a/reactos/drivers/drivers.rbuild
+++ b/reactos/drivers/drivers.rbuild
@@ -20,6 +20,9 @@
+
+
+
diff --git a/reactos/drivers/test/csqtest/csqtest.rbuild b/reactos/drivers/test/csqtest/csqtest.rbuild
new file mode 100644
index 00000000000..4e75922112e
--- /dev/null
+++ b/reactos/drivers/test/csqtest/csqtest.rbuild
@@ -0,0 +1,9 @@
+
+
+
+ include/reactos/drivers
+ ntoskrnl
+ hal
+ csqtest.c
+ csqtest.rc
+
diff --git a/reactos/drivers/test/directory.rbuild b/reactos/drivers/test/directory.rbuild
new file mode 100644
index 00000000000..44beea06b06
--- /dev/null
+++ b/reactos/drivers/test/directory.rbuild
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/reactos/drivers/test/kmtest/deviface.c b/reactos/drivers/test/kmtest/deviface.c
new file mode 100644
index 00000000000..af9352121c9
--- /dev/null
+++ b/reactos/drivers/test/kmtest/deviface.c
@@ -0,0 +1,542 @@
+/*
+ * PnP Test
+ * ReactOS Device Interface functions implementation
+ *
+ * Copyright 2003, 2004 Filip Navara
+ * Copyright 2003, 2004 Matthew Brace
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include
+#include "kmtest.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * 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
+ * @unimplemented
+ *
+ * The parameters PhysicalDeviceObject and Flags aren't correctly
+ * processed. Rest of the cases was tested under Win XP and the
+ * function worked correctly.
+ */
+
+NTSTATUS STDCALL
+ReactOS_IoGetDeviceInterfaces(
+ IN CONST GUID *InterfaceClassGuid,
+ IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
+ 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;
+ UNICODE_STRING AliasKeyName;
+ UNICODE_STRING SymbolicLink;
+ UNICODE_STRING Control;
+ UNICODE_STRING SubKeyName;
+ UNICODE_STRING SymbolicLinkKeyName;
+ UNICODE_STRING ControlKeyName;
+ UNICODE_STRING TempString;
+ HANDLE InterfaceKey;
+ HANDLE SubKey;
+ HANDLE SymbolicLinkKey;
+ PKEY_FULL_INFORMATION fip;
+ PKEY_FULL_INFORMATION bfip;
+ PKEY_BASIC_INFORMATION bip;
+ PKEY_VALUE_PARTIAL_INFORMATION vpip;
+ PWCHAR SymLinkList = NULL;
+ ULONG SymLinkListSize;
+ NTSTATUS Status;
+ ULONG Size = 0;
+ ULONG i = 0;
+ ULONG j = 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");
+ RtlInitUnicodeString(&Control, L"\\Control");
+ 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[40];
+ 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 = ZwQueryKey(
+ SubKey,
+ KeyFullInformation,
+ NULL,
+ 0,
+ &Size);
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
+ ExFreePool(fip);
+ RtlFreeUnicodeString(&BaseKeyName);
+ RtlFreeUnicodeString(&SubKeyName);
+ ZwClose(SubKey);
+ ZwClose(InterfaceKey);
+ return Status;
+ }
+
+ bfip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
+ ASSERT(bfip != NULL);
+
+ Status = ZwQueryKey(
+ SubKey,
+ KeyFullInformation,
+ bfip,
+ Size,
+ &Size);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
+ ExFreePool(fip);
+ RtlFreeUnicodeString(&SubKeyName);
+ RtlFreeUnicodeString(&BaseKeyName);
+ ZwClose(SubKey);
+ ZwClose(InterfaceKey);
+ return Status;
+ }
+
+ for(j = 0; j < bfip->SubKeys; j++)
+ {
+ Status = ZwEnumerateKey(
+ SubKey,
+ j,
+ KeyBasicInformation,
+ NULL,
+ 0,
+ &Size);
+
+ if (Status == STATUS_NO_MORE_ENTRIES)
+ continue;
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status);
+ ExFreePool(bfip);
+ 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,
+ j,
+ KeyBasicInformation,
+ bip,
+ Size,
+ &Size);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status);
+ ExFreePool(fip);
+ ExFreePool(bfip);
+ ExFreePool(bip);
+ if (SymLinkList != NULL)
+ ExFreePool(SymLinkList);
+ RtlFreeUnicodeString(&SubKeyName);
+ RtlFreeUnicodeString(&BaseKeyName);
+ ZwClose(SubKey);
+ ZwClose(InterfaceKey);
+ return Status;
+ }
+
+ if (!wcsncmp(bip->Name, L"Control", bip->NameLength))
+ {
+ continue;
+ }
+
+ 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);
+
+ ControlKeyName.Length = 0;
+ ControlKeyName.MaximumLength = SymbolicLinkKeyName.Length + Control.Length + sizeof(WCHAR);
+ ControlKeyName.Buffer = ExAllocatePool(NonPagedPool, ControlKeyName.MaximumLength);
+ ASSERT(ControlKeyName.Buffer != NULL);
+ RtlCopyUnicodeString(&ControlKeyName, &SymbolicLinkKeyName);
+ RtlAppendUnicodeStringToString(&ControlKeyName, &Control);
+
+ 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);
+ ExFreePool(bfip);
+ 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_OBJECT_NAME_NOT_FOUND)
+ continue;
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status);
+ ExFreePool(fip);
+ ExFreePool(bfip);
+ 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))
+ {
+ DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status);
+ ExFreePool(fip);
+ ExFreePool(bfip);
+ ExFreePool(vpip);
+ if (SymLinkList != NULL)
+ ExFreePool(SymLinkList);
+ RtlFreeUnicodeString(&SymbolicLinkKeyName);
+ RtlFreeUnicodeString(&SubKeyName);
+ RtlFreeUnicodeString(&BaseKeyName);
+ ZwClose(SymbolicLinkKey);
+ ZwClose(SubKey);
+ ZwClose(InterfaceKey);
+ return Status;
+ }
+
+ Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ControlKeyName.Buffer);
+
+ if (NT_SUCCESS(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(&ControlKeyName);
+ ZwClose(SymbolicLinkKey);
+ }
+
+ ExFreePool(vpip);
+ RtlFreeUnicodeString(&SubKeyName);
+ ZwClose(SubKey);
+ }
+
+ if (SymLinkList != NULL)
+ {
+ SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0;
+ }
+ else
+ {
+ SymLinkList = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
+ SymLinkList[0] = 0;
+ }
+
+ *SymbolicLinkList = SymLinkList;
+
+ RtlFreeUnicodeString(&BaseKeyName);
+ ZwClose(InterfaceKey);
+ ExFreePool(bfip);
+ ExFreePool(fip);
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/reactos/drivers/test/kmtest/deviface_test.c b/reactos/drivers/test/kmtest/deviface_test.c
new file mode 100644
index 00000000000..35616845d5d
--- /dev/null
+++ b/reactos/drivers/test/kmtest/deviface_test.c
@@ -0,0 +1,109 @@
+/*
+ * PnP Test
+ * Device Interface functions test
+ *
+ * Copyright 2004 Filip Navara
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include
+#include "kmtest.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS STDCALL
+(*IoGetDeviceInterfaces_Func)(
+ IN CONST GUID *InterfaceClassGuid,
+ IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
+ IN ULONG Flags,
+ OUT PWSTR *SymbolicLinkList);
+
+NTSTATUS STDCALL
+ReactOS_IoGetDeviceInterfaces(
+ IN CONST GUID *InterfaceClassGuid,
+ IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
+ IN ULONG Flags,
+ OUT PWSTR *SymbolicLinkList);
+
+VOID FASTCALL DeviceInterfaceTest_Func()
+{
+ NTSTATUS Status;
+ PWSTR SymbolicLinkList;
+ PWSTR SymbolicLinkListPtr;
+ GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}};
+
+ Status = IoGetDeviceInterfaces_Func(
+ &Guid,
+ NULL,
+ 0,
+ &SymbolicLinkList);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT(
+ "[PnP Test] IoGetDeviceInterfaces failed with status 0x%X\n",
+ Status);
+ return;
+ }
+
+ DPRINT("[PnP Test] IoGetDeviceInterfaces results:\n");
+ for (SymbolicLinkListPtr = SymbolicLinkList;
+ SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
+ SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1)
+ {
+ DPRINT("[PnP Test] %S\n", SymbolicLinkListPtr);
+ }
+
+#if 0
+ DPRINT("[PnP Test] Trying to get aliases\n");
+
+ for (SymbolicLinkListPtr = SymbolicLinkList;
+ SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
+ SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1)
+ {
+ UNICODE_STRING SymbolicLink;
+ UNICODE_STRING AliasSymbolicLink;
+
+ SymbolicLink.Buffer = SymbolicLinkListPtr;
+ SymbolicLink.Length = SymbolicLink.MaximumLength = wcslen(SymbolicLinkListPtr);
+ RtlInitUnicodeString(&AliasSymbolicLink, NULL);
+ IoGetDeviceInterfaceAlias(
+ &SymbolicLink,
+ &AliasGuid,
+ &AliasSymbolicLink);
+ if (AliasSymbolicLink.Buffer != NULL)
+ {
+ DPRINT("[PnP Test] Original: %S\n", SymbolicLinkListPtr);
+ DPRINT("[PnP Test] Alias: %S\n", AliasSymbolicLink.Buffer);
+ }
+ }
+#endif
+
+ ExFreePool(SymbolicLinkList);
+}
+
+VOID FASTCALL DeviceInterfaceTest()
+{
+ DPRINT("Calling DeviceInterfaceTest_Func with native functions\n");
+ IoGetDeviceInterfaces_Func = IoGetDeviceInterfaces;
+ DeviceInterfaceTest_Func();
+ DPRINT("Calling DeviceInterfaceTest_Func with ReactOS functions\n");
+ IoGetDeviceInterfaces_Func = ReactOS_IoGetDeviceInterfaces;
+ DeviceInterfaceTest_Func();
+}
diff --git a/reactos/drivers/test/kmtest/kmtest.c b/reactos/drivers/test/kmtest/kmtest.c
new file mode 100644
index 00000000000..f72911b0d6a
--- /dev/null
+++ b/reactos/drivers/test/kmtest/kmtest.c
@@ -0,0 +1,122 @@
+/*
+ * Kernel Mode regression Test
+ * Driver Core
+ *
+ * Copyright 2004 Filip Navara
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include
+#include "kmtest.h"
+
+ULONG successes;
+ULONG failures;
+tls_data glob_data;
+
+/* PRIVATE FUNCTIONS ***********************************************************/
+VOID
+StartTest()
+{
+ successes = 0;
+ failures = 0;
+}
+
+VOID
+FinishTest(LPSTR TestName)
+{
+ DbgPrint("Test %s finished with %d succeses and %d failures\n", TestName, successes, failures);
+}
+
+void kmtest_set_location(const char* file, int line)
+{
+ glob_data.current_file=strrchr(file,'/');
+ if (glob_data.current_file==NULL)
+ glob_data.current_file=strrchr(file,'\\');
+ if (glob_data.current_file==NULL)
+ glob_data.current_file=file;
+ else
+ glob_data.current_file++;
+ glob_data.current_line=line;
+}
+
+/*
+ * Checks condition.
+ * Parameters:
+ * - condition - condition to check;
+ * - msg test description;
+ * - file - test application source code file name of the check
+ * - line - test application source code file line number of the check
+ * Return:
+ * 0 if condition does not have the expected value, 1 otherwise
+ */
+int kmtest_ok(int condition, const char *msg, ... )
+{
+ va_list valist;
+
+ if (!condition)
+ {
+ if (msg[0])
+ {
+ char string[1024];
+ va_start(valist, msg);
+ vsprintf(string, msg, valist);
+ DbgPrint( "%s:%d: Test failed: %s\n",
+ glob_data.current_file, glob_data.current_line, string );
+ va_end(valist);
+ }
+ else
+ {
+ DbgPrint( "%s:%d: Test failed\n",
+ glob_data.current_file, glob_data.current_line );
+ }
+ InterlockedIncrement(&failures);
+ return 0;
+ }
+ else
+ {/*
+ if (report_success)
+ fprintf( stdout, "%s:%d: Test succeeded\n",
+ glob_data.current_file, glob_data.current_line);*/
+ InterlockedIncrement(&successes);
+ }
+ return 1;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * Test Declarations
+ */
+VOID FASTCALL DeviceInterfaceTest();
+VOID FASTCALL NtoskrnlIoMdlTest();
+
+/*
+ * DriverEntry
+ */
+NTSTATUS
+NTAPI
+DriverEntry(PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath)
+{
+ DbgPrint("Kernel Mode Regression Test driver starting...\n");
+ //DeviceInterfaceTest();
+ NtoskrnlIoMdlTest();
+
+ return STATUS_UNSUCCESSFUL;
+}
diff --git a/reactos/drivers/test/kmtest/kmtest.h b/reactos/drivers/test/kmtest/kmtest.h
new file mode 100644
index 00000000000..556f10bbc36
--- /dev/null
+++ b/reactos/drivers/test/kmtest/kmtest.h
@@ -0,0 +1,53 @@
+#ifndef PNPTEST_H
+#define PNPTEST_H
+
+#include
+#include
+
+/*
+ Some macros, structs, and vars are based or inspired from the great
+ Wine regression tests Copyright (C) 2002 Alexandre Julliard.
+ Everything else is done by Aleksey Bragin based on PnPTest by Filip Navara
+*/
+
+#if 0
+#define DPRINT DbgPrint("%s:%d ", __FILE__, __LINE__), DbgPrint
+#else
+#define DPRINT DbgPrint
+#endif
+
+extern ULONG successes; /* number of successful tests */
+extern ULONG failures; /* number of failures */
+//static ULONG todo_successes; /* number of successful tests inside todo block */
+//static ULONG todo_failures; /* number of failures inside todo block */
+
+// We don't do multithreading, so we just keep this struct in a global var
+typedef struct
+{
+ const char* current_file; /* file of current check */
+ int current_line; /* line of current check */
+ int todo_level; /* current todo nesting level */
+ int todo_do_loop;
+} tls_data;
+
+extern tls_data glob_data;
+
+VOID StartTest();
+VOID FinishTest(LPSTR TestName);
+void kmtest_set_location(const char* file, int line);
+
+#ifdef __GNUC__
+
+extern int kmtest_ok( int condition, const char *msg, ... ) __attribute__((format (printf,2,3) ));
+
+#else /* __GNUC__ */
+
+extern int kmtest_ok( int condition, const char *msg, ... );
+
+#endif /* __GNUC__ */
+
+
+#define ok_(file, line) (kmtest_set_location(file, line), 0) ? 0 : kmtest_ok
+#define ok ok_(__FILE__, __LINE__)
+
+#endif /* PNPTEST_H */
diff --git a/reactos/drivers/test/kmtest/kmtest.rbuild b/reactos/drivers/test/kmtest/kmtest.rbuild
new file mode 100644
index 00000000000..913644b92a4
--- /dev/null
+++ b/reactos/drivers/test/kmtest/kmtest.rbuild
@@ -0,0 +1,12 @@
+
+
+
+ include/reactos/drivers
+ ntoskrnl
+ hal
+ kmtest.c
+ deviface.c
+ deviface_test.c
+ ntos_io.c
+ kmtest.rc
+
diff --git a/reactos/drivers/test/kmtest/kmtest.rc b/reactos/drivers/test/kmtest/kmtest.rc
new file mode 100644
index 00000000000..fa44c9352c1
--- /dev/null
+++ b/reactos/drivers/test/kmtest/kmtest.rc
@@ -0,0 +1,7 @@
+/* $Id: csqtest.rc 21842 2006-05-07 19:16:11Z ion $ */
+
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "Kernel Mode Regression Tests\0"
+#define REACTOS_STR_INTERNAL_NAME "kmtest\0"
+#define REACTOS_STR_ORIGINAL_FILENAME "kmtest.sys\0"
+#include
diff --git a/reactos/drivers/test/kmtest/ntos_io.c b/reactos/drivers/test/kmtest/ntos_io.c
new file mode 100644
index 00000000000..e9c12aebe69
--- /dev/null
+++ b/reactos/drivers/test/kmtest/ntos_io.c
@@ -0,0 +1,44 @@
+/*
+ * NTOSKRNL Io Regressions KM-Test
+ * ReactOS Device Interface functions implementation
+ *
+ * Copyright 2006 Aleksey Bragin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include
+#include "kmtest.h"
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+VOID FASTCALL NtoskrnlIoMdlTest()
+{
+ PMDL Mdl;
+
+ StartTest();
+
+ // Try to alloc 2Gb MDL
+ Mdl = IoAllocateMdl(NULL, 2048UL*0x100000, FALSE, FALSE, NULL);
+
+ ok(Mdl == NULL, "IoAllocateMdl should fail allocation of 2Gb or more, but got Mdl=0x%X", (UINT)Mdl);
+ if (Mdl)
+ IoFreeMdl(Mdl);
+
+ FinishTest("NTOSKRNL Io Mdl");
+}
diff --git a/reactos/regtests/directory.rbuild b/reactos/regtests/directory.rbuild
index b57752df6f9..7a2522dbe0f 100644
--- a/reactos/regtests/directory.rbuild
+++ b/reactos/regtests/directory.rbuild
@@ -1,4 +1,7 @@
+
+
+
diff --git a/reactos/regtests/kmtloader/kmtloader.c b/reactos/regtests/kmtloader/kmtloader.c
new file mode 100644
index 00000000000..d200425beb2
--- /dev/null
+++ b/reactos/regtests/kmtloader/kmtloader.c
@@ -0,0 +1,90 @@
+/*
+ * Kernel-Mode Tests Loader (based on PnP Test Driver Loader by Filip Navara)
+ *
+ * Copyright 2004 Filip Navara
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include
+#include
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+int main()
+{
+ SC_HANDLE schSCManager;
+ SC_HANDLE schService;
+ PWCHAR DriverName = L"KMTEST";
+ WCHAR ServiceExe[MAX_PATH];
+
+ printf("Kernel Mode Tests loader\n\n");
+ GetCurrentDirectoryW(MAX_PATH, ServiceExe);
+ wcscat(ServiceExe, L"\\kmtest.sys");
+
+ printf("Opening SC Manager...\n");
+ schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+ if (schSCManager == NULL)
+ {
+ DWORD Err = GetLastError();
+ printf("OpenSCManager failed with error 0x%lx\n", Err);
+ return 0;
+ }
+
+ printf("Creating service...\n");
+ schService = CreateServiceW(
+ schSCManager,
+ DriverName,
+ DriverName,
+ SERVICE_ALL_ACCESS,
+ SERVICE_KERNEL_DRIVER,
+ SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL,
+ ServiceExe,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (schService == NULL)
+ {
+ printf("Opening service...\n");
+ schService = OpenServiceW(schSCManager, DriverName, SERVICE_ALL_ACCESS);
+ }
+
+ if (schService == NULL)
+ {
+ DWORD Err = GetLastError();
+ printf("Create/OpenService failed with error 0x%lx\n", Err);
+ CloseServiceHandle(schSCManager);
+ return 0;
+ }
+
+ //for (;;) ;
+
+ printf("Starting service...\n");
+ StartService(schService, 0, NULL);
+
+ printf("Cleaning up and exiting\n");
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+
+ return 0;
+}
diff --git a/reactos/regtests/kmtloader/kmtloader.rbuild b/reactos/regtests/kmtloader/kmtloader.rbuild
new file mode 100644
index 00000000000..df91cf15338
--- /dev/null
+++ b/reactos/regtests/kmtloader/kmtloader.rbuild
@@ -0,0 +1,5 @@
+
+
+
+ kmtloader.c
+