- Cleanup /storage directory and prepare for NT5+ Storage Stack and Floppy Port/Class drop.

svn path=/trunk/; revision=26250
This commit is contained in:
Alex Ionescu 2007-04-03 14:14:25 +00:00
parent 3340addefa
commit d03eaaa66d
72 changed files with 7 additions and 1953 deletions

View file

@ -20,9 +20,6 @@
<directory name="storage">
<xi:include href="storage/directory.rbuild" />
</directory>
<directory name="test">
<xi:include href="test/directory.rbuild" />
</directory>
<directory name="usb">
<xi:include href="usb/directory.rbuild" />
</directory>

View file

View file

@ -1,30 +1,15 @@
<directory name="atapi">
<xi:include href="atapi/atapi.rbuild" />
</directory>
<directory name="buslogic">
<xi:include href="buslogic/buslogic.rbuild" />
</directory>
<directory name="cdrom">
<xi:include href="cdrom/cdrom.rbuild" />
</directory>
<directory name="class2">
<xi:include href="class2/class2.rbuild" />
</directory>
<directory name="disk">
<xi:include href="disk/disk.rbuild" />
<directory name="class">
<xi:include href="class/directory.rbuild" />
</directory>
<directory name="floppy">
<xi:include href="floppy/floppy.rbuild" />
</directory>
<directory name="pciide">
<xi:include href="pciide/pciide.rbuild" />
<directory name="ide">
<xi:include href="ide/directory.rbuild" />
</directory>
<directory name="pciidex">
<xi:include href="pciidex/pciidex.rbuild" />
<directory name="port">
<xi:include href="port/directory.rbuild" />
</directory>
<directory name="scsiport">
<xi:include href="scsiport/scsiport.rbuild" />
</directory>
<directory name="diskdump">
<xi:include href="diskdump/diskdump.rbuild" />
</directory>

View file

View file

View file

@ -31,7 +31,7 @@
#include <scsi.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <include/class2.h>
#include <../class/include/class2.h>
#include <diskdump/diskdump.h>
#include <ndk/rtlfuncs.h>

View file

@ -1,5 +0,0 @@
TARGETNAME=csqtest
TARGETTYPE=DRIVER
TARGETPATH=obj
TARGETLIBS= csq.lib
SOURCES= csqtest.c

View file

@ -1,227 +0,0 @@
/*
* CSQ Test Driver
* Copyright (c) 2004, Vizzini (vizzini@plasmic.com)
* Released under the GNU GPL for the ReactOS project
*
* This driver is designed to exercise the cancel-safe IRP queue logic.
* Please refer to reactos/include/ddk/csq.h and reactos/drivers/lib/csq.
*/
#include <ntddk.h>
#include <csq.h>
/* XXX shortcomings in our headers... */
#define assert(x)
#ifndef KdPrint
#define KdPrint(x) DbgPrint x
#endif
/* Device name */
#define NT_DEVICE_NAME L"\\Device\\csqtest"
/* DosDevices name */
#define DOS_DEVICE_NAME L"\\??\\csqtest"
/* Global CSQ struct that the CSQ functions init */
IO_CSQ Csq;
/* List and lock for the actual IRP queue */
LIST_ENTRY IrpQueue;
KSPIN_LOCK IrpQueueLock;
/* Device object */
PDEVICE_OBJECT DeviceObject;
/*
* CSQ Callbacks
*/
VOID NTAPI CsqInsertIrp(PIO_CSQ Csq, PIRP Irp)
{
KdPrint(("Inserting IRP 0x%x into CSQ\n", Irp));
InsertTailList(&IrpQueue, &Irp->Tail.Overlay.ListEntry);
}
VOID NTAPI CsqRemoveIrp(PIO_CSQ Csq, PIRP Irp)
{
KdPrint(("Removing IRP 0x%x from CSQ\n", Irp));
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
PIRP NTAPI CsqPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext)
{
KdPrint(("Peeking for next IRP\n"));
if(Irp)
return CONTAINING_RECORD(&Irp->Tail.Overlay.ListEntry.Flink, IRP, Tail.Overlay.ListEntry);
if(IsListEmpty(&IrpQueue))
return NULL;
return CONTAINING_RECORD(IrpQueue.Flink, IRP, Tail.Overlay.ListEntry);
}
VOID NTAPI CsqAcquireLock(PIO_CSQ Csq, PKIRQL Irql)
{
KdPrint(("Acquiring spin lock\n"));
KeAcquireSpinLock(&IrpQueueLock, Irql);
}
VOID NTAPI CsqReleaseLock(PIO_CSQ Csq, KIRQL Irql)
{
KdPrint(("Releasing spin lock\n"));
KeReleaseSpinLock(&IrpQueueLock, Irql);
}
VOID NTAPI CsqCompleteCancelledIrp(PIO_CSQ Csq, PIRP Irp)
{
KdPrint(("cancelling irp 0x%x\n", Irp));
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
NTSTATUS NTAPI CsqInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)
/*
* FUNCTION: Insert into IRP queue, with extra context
*
* NOTE: Switch call in DriverEntry to IoCsqInitializeEx to use this
*/
{
CsqInsertIrp(Csq, Irp);
return STATUS_PENDING;
}
/*
* DISPATCH ROUTINES
*/
NTSTATUS NTAPI DispatchCreateCloseCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
if(StackLocation->MajorFunction == IRP_MJ_CLEANUP)
{
/* flush the irp queue */
PIRP CurrentIrp;
KdPrint(("csqtest: Cleanup received; flushing the IRP queue with cancel\n"));
while((CurrentIrp = IoCsqRemoveNextIrp(&Csq, 0)))
{
CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
CurrentIrp->IoStatus.Information = 0;
IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT);
}
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS NTAPI DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
/* According to the cancel sample in the DDK, IoCsqInsertIrp() marks the irp pending */
/* However, I think it's wrong. */
IoMarkIrpPending(Irp);
IoCsqInsertIrp(&Csq, Irp, 0);
return STATUS_PENDING;
}
NTSTATUS NTAPI DispatchIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* all IOCTL requests flush the irp queue
*/
{
PIRP CurrentIrp;
KdPrint(("csqtest: Ioctl received; flushing the IRP queue with success\n"));
while((CurrentIrp = IoCsqRemoveNextIrp(&Csq, 0)))
{
CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
CurrentIrp->IoStatus.Information = 0;
IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
/*
* Function: called by the OS to release resources before unload
*/
{
UNICODE_STRING LinkName;
RtlInitUnicodeString(&LinkName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&LinkName);
if(DeviceObject)
IoDeleteDevice(DeviceObject);
}
/*
* DriverEntry
*/
NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS Status;
UNICODE_STRING NtName;
UNICODE_STRING DosName;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateCloseCleanup;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateCloseCleanup;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCreateCloseCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
DriverObject->DriverUnload = Unload;
Status = IoCsqInitialize(&Csq, CsqInsertIrp, CsqRemoveIrp, CsqPeekNextIrp,
CsqAcquireLock, CsqReleaseLock, CsqCompleteCancelledIrp);
if(Status != STATUS_SUCCESS)
KdPrint(("csqtest: IoCsqInitalize failed: 0x%x\n", Status));
else
KdPrint(("csqtest: IoCsqInitalize succeeded\n"));
InitializeListHead(&IrpQueue);
KeInitializeSpinLock(&IrpQueueLock);
/* Set up a device */
RtlInitUnicodeString(&NtName, NT_DEVICE_NAME);
Status = IoCreateDevice(DriverObject, 0, &NtName, FILE_DEVICE_UNKNOWN, 0, 0, &DeviceObject);
if(!NT_SUCCESS(Status))
{
KdPrint(("csqtest: Unable to create device: 0x%x\n", Status));
return Status;
}
RtlInitUnicodeString(&DosName, DOS_DEVICE_NAME);
Status = IoCreateSymbolicLink(&DosName, &NtName);
if(!NT_SUCCESS(Status))
{
KdPrint(("csqtest: Unable to create link: 0x%x\n", Status));
return Status;
}
DeviceObject->Flags |= DO_BUFFERED_IO;
return STATUS_SUCCESS;
}

View file

@ -1,9 +0,0 @@
<module name="csqtest" type="kernelmodedriver" installbase="system32/drivers" installname="csqtest.sys">
<bootstrap base="$(CDOUTPUT)" />
<define name="__USE_W32API" />
<include base="ReactOS">include/reactos/drivers</include>
<library>ntoskrnl</library>
<library>hal</library>
<file>csqtest.c</file>
<file>csqtest.rc</file>
</module>

View file

@ -1,7 +0,0 @@
/* $Id$ */
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "CSQ Test\0"
#define REACTOS_STR_INTERNAL_NAME "csqtest\0"
#define REACTOS_STR_ORIGINAL_FILENAME "csqtest.sys\0"
#include <reactos/version.rc>

View file

@ -1,6 +0,0 @@
<directory name="csqtest">
<xi:include href="csqtest/csqtest.rbuild" />
</directory>
<directory name="kmtest">
<xi:include href="kmtest/kmtest.rbuild" />
</directory>

View file

@ -1,545 +0,0 @@
/*
* PnP Test
* ReactOS Device Interface functions implementation
*
* Copyright 2003, 2004 Filip Navara <xnavara@volny.cz>
* Copyright 2003, 2004 Matthew Brace <ismarc@austin.rr.com>
*
* 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 <ddk/ntddk.h>
#include "kmtest.h"
//#define NDEBUG
#include "debug.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=NULL;
PKEY_BASIC_INFORMATION bip;
PKEY_VALUE_PARTIAL_INFORMATION vpip=NULL;
PWCHAR SymLinkList = NULL;
ULONG SymLinkListSize = 0;
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;
}

View file

@ -1,154 +0,0 @@
/*
* PnP Test
* Device Interface functions test
*
* Copyright 2004 Filip Navara <xnavara@volny.cz>
*
* 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 <ddk/ntddk.h>
#include <ndk/iotypes.h>
#include "kmtest.h"
//#define NDEBUG
#include "debug.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 RegisterDI_Test()
{
GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}};
DEVICE_OBJECT DeviceObject;
EXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
DEVICE_NODE DeviceNode;
UNICODE_STRING SymbolicLinkName;
NTSTATUS Status;
RtlInitUnicodeString(&SymbolicLinkName, L"");
// Prepare our surrogate of a Device Object
DeviceObject.DeviceObjectExtension = (PDEVOBJ_EXTENSION)&DeviceObjectExtension;
// 1. DeviceNode = NULL
DeviceObjectExtension.DeviceNode = NULL;
Status = IoRegisterDeviceInterface(&DeviceObject, &Guid, NULL,
&SymbolicLinkName);
ok(Status == STATUS_INVALID_DEVICE_REQUEST,
"IoRegisterDeviceInterface returned 0x%08lX\n", Status);
// 2. DeviceNode->InstancePath is of a null length
DeviceObjectExtension.DeviceNode = &DeviceNode;
DeviceNode.InstancePath.Length = 0;
Status = IoRegisterDeviceInterface(&DeviceObject, &Guid, NULL,
&SymbolicLinkName);
ok(Status == STATUS_INVALID_DEVICE_REQUEST,
"IoRegisterDeviceInterface returned 0x%08lX\n", Status);
}
VOID FASTCALL NtoskrnlIoDeviceInterface()
{
StartTest();
// Test IoRegisterDeviceInterface() failures now
RegisterDI_Test();
/*
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();
*/
FinishTest("NTOSKRNL Io Device Interface Test");
}

View file

@ -1,126 +0,0 @@
/*
* Kernel Mode regression Test
* Driver Core
*
* Copyright 2004 Filip Navara <xnavara@volny.cz>
*
* 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 <ddk/ntddk.h>
#include "kmtest.h"
LONG successes;
LONG 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 NtoskrnlIoMdlTest();
VOID FASTCALL NtoskrnlIoDeviceInterface();
VOID FASTCALL NtoskrnlObTest();
VOID FASTCALL NtoskrnlExecutiveTests();
/*
* DriverEntry
*/
NTSTATUS
NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
DbgPrint("\n===============================================\nKernel Mode Regression Test driver starting...\n");
NtoskrnlExecutiveTests();
NtoskrnlIoDeviceInterface();
NtoskrnlIoMdlTest();
NtoskrnlObTest();
return STATUS_UNSUCCESSFUL;
}

View file

@ -1,48 +0,0 @@
#ifndef PNPTEST_H
#define PNPTEST_H
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
/*
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
*/
extern LONG successes; /* number of successful tests */
extern LONG 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 */

View file

@ -1,14 +0,0 @@
<module name="kmtest" type="kernelmodedriver" installbase="system32/drivers" installname="kmtest.sys">
<bootstrap base="$(CDOUTPUT)" />
<define name="__USE_W32API" />
<include base="ReactOS">include/reactos/drivers</include>
<library>ntoskrnl</library>
<library>hal</library>
<file>kmtest.c</file>
<file>deviface.c</file>
<file>deviface_test.c</file>
<file>ntos_ex.c</file>
<file>ntos_io.c</file>
<file>ntos_ob.c</file>
<file>kmtest.rc</file>
</module>

View file

@ -1,7 +0,0 @@
/* $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 <reactos/version.rc>

View file

@ -1,180 +0,0 @@
/*
* NTOSKRNL Executive Regressions KM-Test
* ReactOS Kernel Mode Regression Testing framework
*
* Copyright 2006 Aleksey Bragin <aleksey@reactos.org>
*
* 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 <ddk/ntddk.h>
#include <ntifs.h>
#include <ndk/ntndk.h>
#include "kmtest.h"
//#define NDEBUG
#include "debug.h"
/* PRIVATE FUNCTIONS ***********************************************************/
VOID
NTAPI
TestTimerApcRoutine(IN PVOID TimerContext,
IN ULONG TimerLowValue,
IN LONG TimerHighValue)
{
DPRINT("Timer Apc called!\n");
ULONG *ApcCount = (ULONG *)TimerContext;
(*ApcCount)++;
}
VOID
ExTimerTest()
{
UNICODE_STRING TimerName;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE TimerHandle;
HANDLE HandleOpened;
LARGE_INTEGER DueTime;
BOOLEAN PreviousState, CurrentState;
NTSTATUS Status;
ULONG ApcCount;
StartTest();
// Create the timer
RtlInitUnicodeString(&TimerName, L"\\TestTimer");
InitializeObjectAttributes(&ObjectAttributes, &TimerName, 0, NULL, NULL);
Status = ZwCreateTimer(&TimerHandle, TIMER_ALL_ACCESS,
&ObjectAttributes, NotificationTimer);
ok(Status == STATUS_SUCCESS, "ZwCreateTimer failed with Status=0x%08lX", Status);
// Open the timer
Status = ZwOpenTimer(&HandleOpened, TIMER_ALL_ACCESS, &ObjectAttributes);
ok(Status == STATUS_SUCCESS, "ZwOpenTimer failed with Status=0x%08lX", Status);
// Set the timer, to some rather high value so it doesn't expire
DPRINT("Set timer 1\n");
DueTime.LowPart = -10000;
DueTime.HighPart = -10;
PreviousState = TRUE;
Status = ZwSetTimer(HandleOpened, &DueTime, NULL, NULL, FALSE, 0L, &PreviousState);
ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
// Cancel the timer
CurrentState = TRUE;
Status = ZwCancelTimer(HandleOpened, &CurrentState);
ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
ok(CurrentState == FALSE, "Incorrect CurrentState returned when canceling the timer");
// Set the timer to some small value, because we'll wait for it to expire
DPRINT("Set timer 2\n");
DueTime.LowPart = -100;
DueTime.HighPart = -1;
PreviousState = TRUE;
Status = ZwSetTimer(HandleOpened, &DueTime, NULL, NULL, FALSE, 0L, &PreviousState);
ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
// Wait until it expires
DPRINT("Wait till timer expires\n");
Status = ZwWaitForSingleObject(HandleOpened, FALSE, NULL);
ok(Status == STATUS_SUCCESS, "ZwWaitForSingleObject failed with Status=0x%08lX", Status);
// And cancel it
DPRINT("Cancel it\n");
CurrentState = FALSE;
Status = ZwCancelTimer(HandleOpened, &CurrentState);
ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
ok(CurrentState == TRUE, "Incorrect CurrentState returned when setting the timer");
// Test it with APC: Set, Cancel, check if APC has been called
DPRINT("Set timer with Apc (3)\n");
ApcCount = 0;
DueTime.LowPart = -10000;
DueTime.HighPart = -10;
PreviousState = FALSE;
Status = ZwSetTimer(HandleOpened, &DueTime,
(PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
0L, &PreviousState);
ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
ok(PreviousState == TRUE, "Incorrect PreviousState returned when setting the timer");
DPRINT("Cancel it\n");
CurrentState = TRUE;
Status = ZwCancelTimer(HandleOpened, &CurrentState);
ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
ok(CurrentState == FALSE, "Incorrect CurrentState returned when cancelling the timer");
ok(ApcCount == 0, "Incorrect count of TimerApcRoutine calls: %ld, should be 0\n", ApcCount);
// Test setting the timer two times in a row, APC routine must not be called
DPRINT("Set timer with Apc (4)\n");
ApcCount = 0;
DueTime.LowPart = -10000;
DueTime.HighPart = -10;
PreviousState = TRUE;
Status = ZwSetTimer(HandleOpened, &DueTime,
(PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
0L, &PreviousState);
ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
// Set small due time, since we have to wait for timer to finish
DPRINT("Set timer with Apc (5)\n");
DueTime.LowPart = -10;
DueTime.HighPart = -1;
PreviousState = TRUE;
Status = ZwSetTimer(HandleOpened, &DueTime,
(PTIMER_APC_ROUTINE)TestTimerApcRoutine, &ApcCount, FALSE,
0L, &PreviousState);
ok(Status == STATUS_SUCCESS, "ZwSetTimer failed with Status=0x%08lX", Status);
ok(PreviousState == FALSE, "Incorrect PreviousState returned when setting the timer");
// Now wait till it's finished, and then check APC call
DPRINT("Wait for it\n");
Status = ZwWaitForSingleObject(HandleOpened, FALSE, NULL);
ok(Status == STATUS_SUCCESS, "ZwWaitForSingleObject failed with Status=0x%08lX", Status);
CurrentState = FALSE;
Status = ZwCancelTimer(HandleOpened, &CurrentState);
ok(Status == STATUS_SUCCESS, "ZwCancelTimer failed with Status=0x%08lX", Status);
ok(CurrentState == TRUE, "Incorrect CurrentState returned when cancelling the timer");
ok(ApcCount == 1, "Incorrect count of TimerApcRoutine calls: %ld, should be 1\n", ApcCount);
// Cleanup...
Status = ZwClose(HandleOpened);
ok(Status == STATUS_SUCCESS, "ZwClose failed with Status=0x%08lX", Status);
Status = ZwClose(TimerHandle);
ok(Status == STATUS_SUCCESS, "ZwClose failed with Status=0x%08lX", Status);
FinishTest("NTOSKRNL Executive Timer");
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
FASTCALL
NtoskrnlExecutiveTests()
{
ExTimerTest();
}

View file

@ -1,81 +0,0 @@
/*
* NTOSKRNL Io Regressions KM-Test
* ReactOS Kernel Mode Regression Testing framework
*
* Copyright 2006 Aleksey Bragin <aleksey@reactos.org>
*
* 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 <ddk/ntddk.h>
#include "kmtest.h"
#define NDEBUG
#include "debug.h"
/* PUBLIC FUNCTIONS ***********************************************************/
VOID FASTCALL NtoskrnlIoMdlTest()
{
PMDL Mdl;
PIRP Irp;
PVOID VirtualAddress;
ULONG MdlSize = 2*4096+184; // 2 pages and some random value
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);
// Now create a valid MDL
VirtualAddress = ExAllocatePool(NonPagedPool, MdlSize);
Mdl = IoAllocateMdl(VirtualAddress, MdlSize, FALSE, FALSE, NULL);
ok(Mdl != NULL, "Mdl allocation failed");
// Check fields of the allocated struct
ok(Mdl->Next == NULL, "Mdl->Next should be NULL, but is 0x%X",
(UINT)Mdl->Next);
ok(Mdl->ByteCount == MdlSize,
"Mdl->ByteCount should be equal to MdlSize, but is 0x%X",
(UINT)Mdl->ByteCount);
// TODO: Check other fields of MDL struct
IoFreeMdl(Mdl);
// Allocate now with pointer to an Irp
Irp = IoAllocateIrp(1, FALSE);
ok(Irp != NULL, "IRP allocation failed");
Mdl = IoAllocateMdl(VirtualAddress, MdlSize, FALSE, FALSE, Irp);
ok(Mdl != NULL, "Mdl allocation failed");
ok(Irp->MdlAddress == Mdl, "Irp->MdlAddress should be 0x%X, but is 0x%X",
(UINT)Mdl, (UINT)Irp->MdlAddress);
IoFreeMdl(Mdl);
// TODO: Check a case when SecondaryBuffer == TRUE
IoFreeIrp(Irp);
ExFreePool(VirtualAddress);
FinishTest("NTOSKRNL Io Mdl");
}

View file

@ -1,519 +0,0 @@
/*
* NTOSKRNL Ob Regressions KM-Test
* ReactOS Kernel Mode Regression Testing framework
*
* Copyright 2006 Aleksey Bragin <aleksey@reactos.org>
*
* 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 <ddk/ntddk.h>
#include "kmtest.h"
//#define NDEBUG
#include "debug.h"
#include "ntndk.h"
// I ment to make this test scalable, but for now
// we work with two object types only
#define NUM_OBTYPES 2
typedef struct _MY_OBJECT1
{
ULONG Something1;
} MY_OBJECT1, *PMY_OBJECT1;
typedef struct _MY_OBJECT2
{
ULONG Something1;
ULONG SomeLong[10];
} MY_OBJECT2, *PMY_OBJECT2;
POBJECT_TYPE ObTypes[NUM_OBTYPES];
UNICODE_STRING ObTypeName[NUM_OBTYPES];
UNICODE_STRING ObName[NUM_OBTYPES];
OBJECT_TYPE_INITIALIZER ObTypeInitializer[NUM_OBTYPES];
UNICODE_STRING ObDirectoryName;
OBJECT_ATTRIBUTES ObDirectoryAttributes;
OBJECT_ATTRIBUTES ObAttributes[NUM_OBTYPES];
PVOID ObBody[NUM_OBTYPES];
PMY_OBJECT1 ObObject1;
PMY_OBJECT2 ObObject2;
HANDLE ObHandle1[NUM_OBTYPES];
HANDLE ObHandle2[NUM_OBTYPES];
HANDLE DirectoryHandle;
USHORT DumpCount, OpenCount, CloseCount, DeleteCount,
ParseCount, OkayToCloseCount, QueryNameCount;
/* PRIVATE FUNCTIONS **********************************************************/
VOID
NTAPI
DumpProc(IN PVOID Object,
IN POB_DUMP_CONTROL DumpControl)
{
DbgPrint("DumpProc() called\n");
DumpCount++;
}
// Tested in Win2k3
VOID
NTAPI
OpenProc(IN OB_OPEN_REASON OpenReason,
IN PEPROCESS Process,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG HandleCount)
{
DbgPrint("OpenProc() 0x%p, OpenReason %d, HC %d, AM 0x%X\n",
Object, OpenReason, HandleCount, GrantedAccess);
OpenCount++;
}
// Tested in Win2k3
VOID
NTAPI
CloseProc(IN PEPROCESS Process,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount)
{
DbgPrint("CloseProc() 0x%p, PHC %d, SHC %d, AM 0x%X\n", Object,
ProcessHandleCount, SystemHandleCount, GrantedAccess);
CloseCount++;
}
// Tested in Win2k3
VOID
NTAPI
DeleteProc(IN PVOID Object)
{
DbgPrint("DeleteProc() 0x%p\n", Object);
DeleteCount++;
}
NTSTATUS
NTAPI
ParseProc(IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object)
{
DbgPrint("ParseProc() called\n");
*Object = NULL;
ParseCount++;
return STATUS_OBJECT_NAME_NOT_FOUND;//STATUS_SUCCESS;
}
// Tested in Win2k3
NTSTATUS
NTAPI
OkayToCloseProc(IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN HANDLE Handle,
IN KPROCESSOR_MODE AccessMode)
{
DbgPrint("OkayToCloseProc() 0x%p, H 0x%p, AM 0x%X\n", Object, Handle,
AccessMode);
OkayToCloseCount++;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
QueryNameProc(IN PVOID Object,
IN BOOLEAN HasObjectName,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength,
IN KPROCESSOR_MODE AccessMode)
{
DbgPrint("QueryNameProc() 0x%p, HON %d, Len %d, AM 0x%X\n",
Object, HasObjectName, Length, AccessMode);
QueryNameCount++;
ObjectNameInfo = NULL;
ReturnLength = 0;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
VOID
ObtCreateObjectTypes()
{
USHORT i;
NTSTATUS Status;
WCHAR Name[15];
for (i=0; i<NUM_OBTYPES; i++)
{
// Prepare object type name
// TODO: Generate type names and don't use this unprofessional,
swprintf(Name, L"MyObjectType%lx", i);
RtlInitUnicodeString(&ObTypeName[i], Name);
// Prepare initializer
RtlZeroMemory(&ObTypeInitializer[i], sizeof(ObTypeInitializer[i]));
ObTypeInitializer[i].Length = sizeof(ObTypeInitializer[i]);
ObTypeInitializer[i].PoolType = NonPagedPool;
ObTypeInitializer[i].MaintainHandleCount = TRUE;
ObTypeInitializer[i].ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
// Test for invalid parameter
// FIXME: Make it more exact, to see which params Win2k3 checks
// existence of
Status = ObCreateObjectType(&ObTypeName[i], &ObTypeInitializer[i],
(PSECURITY_DESCRIPTOR)NULL, &ObTypes[i]);
ok(Status == STATUS_INVALID_PARAMETER,
"ObCreateObjectType returned 0x%lX", Status);
// Object procedures
ObTypeInitializer[i].CloseProcedure = (OB_CLOSE_METHOD)CloseProc;
ObTypeInitializer[i].DeleteProcedure = (OB_DELETE_METHOD)DeleteProc;
ObTypeInitializer[i].DumpProcedure = (OB_DUMP_METHOD)DumpProc;
ObTypeInitializer[i].OpenProcedure = (OB_OPEN_METHOD)OpenProc;
ObTypeInitializer[i].ParseProcedure = (OB_PARSE_METHOD)ParseProc;
//ObTypeInitializer[i].OkayToCloseProcedure =
// (OB_OKAYTOCLOSE_METHOD)OkayToCloseProc;
//ObTypeInitializer[i].QueryNameProcedure =
// (OB_QUERYNAME_METHOD)QueryNameProc;
//ObTypeInitializer[i].SecurityProcedure =
// (OB_SECURITY_METHOD)SecurityProc;
Status = ObCreateObjectType(&ObTypeName[i], &ObTypeInitializer[i],
(PSECURITY_DESCRIPTOR)NULL, &ObTypes[i]);
ok(Status == STATUS_SUCCESS,
"Failed to create object type with status=0x%lX", Status);
}
}
VOID
ObtCreateDirectory()
{
NTSTATUS Status;
// Directory will have permanent and case insensitive flags
RtlInitUnicodeString(&ObDirectoryName, L"\\ObtDirectory");
InitializeObjectAttributes(&ObDirectoryAttributes, &ObDirectoryName,
OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateDirectoryObject(&DirectoryHandle, 0, &ObDirectoryAttributes);
ok(Status == STATUS_SUCCESS,
"Failed to create directory object with status=0x%lX", Status);
}
VOID
ObtCreateObjects()
{
PVOID ObBody1[2];
NTSTATUS Status;
USHORT OpenSave, CloseSave, DeleteSave, ParseSave,
OkayToCloseSave, QueryNameSave;
// Create two objects
RtlInitUnicodeString(&ObName[0], L"\\ObtDirectory\\MyObject1");
InitializeObjectAttributes(&ObAttributes[0], &ObName[0],
OBJ_CASE_INSENSITIVE, NULL, NULL);
RtlInitUnicodeString(&ObName[1], L"\\ObtDirectory\\MyObject2");
InitializeObjectAttributes(&ObAttributes[1], &ObName[1],
OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ObCreateObject(KernelMode, ObTypes[0], &ObAttributes[0],
KernelMode, NULL, (ULONG)sizeof(MY_OBJECT1), 0L, 0L,
(PVOID *)&ObBody[0]);
ok(Status == STATUS_SUCCESS,
"Failed to create object with status=0x%lX", Status);
Status = ObCreateObject(KernelMode, ObTypes[1], &ObAttributes[1],
KernelMode, NULL, (ULONG)sizeof(MY_OBJECT2), 0L, 0L,
(PVOID *)&ObBody[1]);
ok(Status == STATUS_SUCCESS,
"Failed to create object with status=0x%lX", Status);
// save counters
OpenSave=OpenCount; CloseSave=CloseCount; DeleteSave=DeleteCount;
ParseSave=ParseCount; OkayToCloseSave=OkayToCloseCount;
QueryNameSave=QueryNameCount;
// Insert them
Status = ObInsertObject(ObBody[0], NULL, STANDARD_RIGHTS_ALL, 0,
&ObBody[0], &ObHandle1[0]);
ok(Status == STATUS_SUCCESS,
"Failed to insert object 0 with status=0x%lX", Status);
ok(ObBody[0] != NULL, "Object body = NULL");
ok(ObHandle1[0] != NULL, "Handle = NULL");
// check counters
ok(OpenSave+1 == OpenCount, "Open method calls mismatch\n");
ok(CloseSave == CloseCount, "Excessive Close method call\n");
ok(DeleteSave == DeleteCount, "Excessive Delete method call\n");
ok(ParseSave == ParseCount, "Excessive Parse method call\n");
// save counters
OpenSave=OpenCount; CloseSave=CloseCount; DeleteSave=DeleteCount;
ParseSave=ParseCount; OkayToCloseSave=OkayToCloseCount;
QueryNameSave=QueryNameCount;
Status = ObInsertObject(ObBody[1], NULL, GENERIC_ALL, 0,
&ObBody[1], &ObHandle1[1]);
ok(Status == STATUS_SUCCESS,
"Failed to insert object 1 with status=0x%lX", Status);
ok(ObBody[1] != NULL, "Object body = NULL");
ok(ObHandle1[1] != NULL, "Handle = NULL");
// check counters
ok(OpenSave+1 == OpenCount, "Open method calls mismatch\n");
ok(CloseSave == CloseCount, "Excessive Close method call\n");
ok(DeleteSave == DeleteCount, "Excessive Delete method call\n");
ok(ParseSave == ParseCount, "Excessive Parse method call\n");
// save counters
OpenSave=OpenCount; CloseSave=CloseCount; DeleteSave=DeleteCount;
ParseSave=ParseCount; OkayToCloseSave=OkayToCloseCount;
QueryNameSave=QueryNameCount;
// Now create an object of type 0, of the same name and expect it to fail
// inserting, but success creation
RtlInitUnicodeString(&ObName[0], L"\\ObtDirectory\\MyObject1");
InitializeObjectAttributes(&ObAttributes[0], &ObName[0], OBJ_OPENIF,
NULL, NULL);
Status = ObCreateObject(KernelMode, ObTypes[0], &ObAttributes[0], KernelMode,
NULL, (ULONG)sizeof(MY_OBJECT1), 0L, 0L, (PVOID *)&ObBody1[0]);
ok(Status == STATUS_SUCCESS,
"Failed to create object with status=0x%lX", Status);
// check counters
ok(OpenSave == OpenCount, "Excessive Open method call\n");
ok(CloseSave == CloseCount, "Excessive Close method call\n");
ok(DeleteSave == DeleteCount, "Excessive Delete method call\n");
ok(ParseSave == ParseCount, "Excessive Parse method call\n");
Status = ObInsertObject(ObBody1[0], NULL, GENERIC_ALL, 0,
&ObBody1[1], &ObHandle2[0]);
ok(Status == STATUS_OBJECT_NAME_EXISTS,
"Object insertion should have failed, but got 0x%lX", Status);
ok(ObBody[0] == ObBody1[1],
"Object bodies doesn't match, 0x%p != 0x%p", ObBody[0], ObBody1[1]);
ok(ObHandle2[0] != NULL, "Bad handle returned 0x%lX", (ULONG)ObHandle2[0]);
DPRINT1("%d %d %d %d %d %d %d\n", DumpCount, OpenCount, // deletecount+1
CloseCount, DeleteCount, ParseCount, OkayToCloseCount, QueryNameCount);
// check counters and then save
ok(OpenSave+1 == OpenCount, "Excessive Open method call\n");
ok(CloseSave == CloseCount, "Excessive Close method call\n");
ok(DeleteSave+1 == DeleteCount, "Delete method call mismatch\n");
ok(ParseSave == ParseCount, "Excessive Parse method call\n");
OpenSave=OpenCount; CloseSave=CloseCount; DeleteSave=DeleteCount;
ParseSave=ParseCount; OkayToCloseSave=OkayToCloseCount;
QueryNameSave=QueryNameCount;
// Close its handle
Status = ZwClose(ObHandle2[0]);
ok(Status == STATUS_SUCCESS,
"Failed to close handle status=0x%lX", Status);
// check counters and then save
ok(OpenSave == OpenCount, "Excessive Open method call\n");
ok(CloseSave+1 == CloseCount, "Close method call mismatch\n");
ok(DeleteSave == DeleteCount, "Excessive Delete method call\n");
ok(ParseSave == ParseCount, "Excessive Parse method call\n");
OpenSave=OpenCount; CloseSave=CloseCount; DeleteSave=DeleteCount;
ParseSave=ParseCount; OkayToCloseSave=OkayToCloseCount;
QueryNameSave=QueryNameCount;
// Object referenced 2 times:
// 1) ObInsertObject
// 2) AdditionalReferences
ObDereferenceObject(ObBody1[1]);
//DPRINT1("%d %d %d %d %d %d %d\n", DumpCount, OpenCount, // no change
// CloseCount, DeleteCount, ParseCount, OkayToCloseCount, QueryNameCount);
ok(OpenSave == OpenCount, "Open method call mismatch\n");
ok(CloseSave == CloseCount, "Close method call mismatch\n");
ok(DeleteSave == DeleteCount, "Delete method call mismatch\n");
ok(ParseSave == ParseCount, "Parse method call mismatch\n");
}
VOID
ObtClose()
{
PVOID DirObject;
NTSTATUS Status;
//PVOID TypeObject;
USHORT i;
//UNICODE_STRING ObPathName[NUM_OBTYPES];
// Close what we have opened and free what we allocated
ZwClose(ObHandle1[0]);
ZwClose(ObHandle1[1]);
ZwClose(ObHandle2[0]);
ZwClose(ObHandle2[1]);
// Now we have to get rid of a directory object
// Since it is permanent, we have to firstly make it temporary
// and only then kill
// (this procedure is described in DDK)
Status = ObReferenceObjectByHandle(DirectoryHandle, 0L, NULL,
KernelMode, &DirObject, NULL);
ok(Status == STATUS_SUCCESS,
"Failed to reference object by handle with status=0x%lX", Status);
// Dereference 2 times - first for just previous referencing
// and 2nd time for creation of permanent object itself
ObDereferenceObject(DirObject);
ObDereferenceObject(DirObject);
Status = ZwMakeTemporaryObject(DirectoryHandle);
ok(Status == STATUS_SUCCESS,
"Failed to make temp object with status=0x%lX", Status);
// Close the handle now and we are done
Status = ZwClose(DirectoryHandle);
ok(Status == STATUS_SUCCESS,
"Failed to close handle with status=0x%lX", Status);
// Now delete the last piece - object types
// In fact, it's weird to get rid of object types, especially the way,
// how it's done in the commented section below
for (i=0; i<NUM_OBTYPES; i++)
ObDereferenceObject(ObTypes[i]);
/*
RtlInitUnicodeString(&ObPathName[0], L"\\ObjectTypes\\MyObjectType1");
RtlInitUnicodeString(&ObPathName[1], L"\\ObjectTypes\\MyObjectType2");
for (i=0; i<NUM_OBTYPES; i++)
{
Status = ObReferenceObjectByName(&ObPathName[i],
OBJ_CASE_INSENSITIVE, NULL, 0L, NULL, KernelMode, NULL,
&TypeObject);
ObDereferenceObject(TypeObject);
ObDereferenceObject(TypeObject);
DPRINT("Reference Name %S = %p, ObTypes[%d] = %p\n",
ObPathName[i], TypeObject, i, ObTypes[i]);
}
*/
}
VOID
ObtReferenceTests()
{
USHORT i;
NTSTATUS Status;
UNICODE_STRING ObPathName[NUM_OBTYPES];
// Reference them by handle
for (i=0; i<NUM_OBTYPES; i++)
{
Status = ObReferenceObjectByHandle(ObHandle1[i], 0L, ObTypes[i],
KernelMode, &ObBody[i], NULL);
ok(Status == STATUS_SUCCESS,
"Failed to reference object by handle, status=0x%lX", Status);
DPRINT("Ref by handle %lx = %p\n", ObHandle1[i], ObBody[i]);
}
// Reference them by pointer
for (i=0; i<NUM_OBTYPES; i++)
{
Status = ObReferenceObjectByPointer(ObBody[i], 0L, ObTypes[i], KernelMode);
ok(Status == STATUS_SUCCESS,
"Failed to reference object by pointer, status=0x%lX", Status);
}
// Reference them by name
RtlInitUnicodeString(&ObPathName[0], L"\\ObtDirectory\\MyObject1");
RtlInitUnicodeString(&ObPathName[1], L"\\ObtDirectory\\MyObject2");
for (i=0; i<NUM_OBTYPES; i++)
{
Status = ObReferenceObjectByName(&ObPathName[i],
OBJ_CASE_INSENSITIVE, NULL, 0L, ObTypes[i], KernelMode, NULL,
&ObBody[0]);
DPRINT("Ref by name %wZ = %p\n", &ObPathName[i], ObBody[i]);
}
// Dereference now all of them
// For ObInsertObject, AdditionalReference
ObDereferenceObject(ObBody[0]);
ObDereferenceObject(ObBody[1]);
// For ByHandle
ObDereferenceObject(ObBody[0]);
ObDereferenceObject(ObBody[1]);
// For ByPointer
ObDereferenceObject(ObBody[0]);
ObDereferenceObject(ObBody[1]);
// For ByName
ObDereferenceObject(ObBody[0]);
ObDereferenceObject(ObBody[1]);
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
FASTCALL
NtoskrnlObTest()
{
StartTest();
DumpCount = 0; OpenCount = 0; CloseCount = 0;
DeleteCount = 0; ParseCount = 0;
// Create object-types to use in tests
ObtCreateObjectTypes();
DPRINT("ObtCreateObjectTypes() done\n");
// Create Directory
ObtCreateDirectory();
DPRINT("ObtCreateDirectory() done\n");
// Create and insert objects
ObtCreateObjects();
DPRINT("ObtCreateObjects() done\n");
// Reference them in a variety of ways
//ObtReferenceTests();
// Clean up
// FIXME: Disable to see results of creating objects in usermode.
// Also it has problems with object types removal
ObtClose();
DPRINT("Cleanup done\n");
FinishTest("NTOSKRNL Ob Manager");
}