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 +