[FLTMGR] Latest from my branch (#135)

[FLTMGR][KMTEST] 
Squash and push my local branch across to master as the patch is getting a bit large. This is still WIP and none of this code is run in ros yet, so don't fret if you see ugly/unfinished code or int3's dotted around.

[FLTMGR] Improve loading/reg of filters and start to implement client connections
- Implement handling of connections from clients
- Implement closing of client ports
- Add a basic message waiter queue using CSQ's (untested)
- Hand off messages for the comms object to be handled by the comms file
- Initialize the connection list
- Add a registry file which will contain lib functions for accessing filter service entries

- [KMTEST] Initial usermode support for testing FS mini-filters
- Add base routines to wrap the win32 'Filter' APis
- Add support routines to be used when testing FS filter drivers
- Move KmtCreateService to a private routine so it can be shared with KmtFltCreateService
- Completely untested at the mo, so likely contains bugs at this point
- Add support for adding altitude and flags registry entries for minifilters
- Allow minifilters to setup without requiring instance attach/detach callbacks
- Add tests for FltRegisterFilter and FltUnregisterFilter and start to add associated tests
This commit is contained in:
Ged Murphy 2017-11-21 16:36:29 +00:00 committed by GitHub
parent f884d29c90
commit dfb776380d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1739 additions and 230 deletions

View file

@ -7,6 +7,7 @@ list(APPEND SOURCE
Messaging.c
Misc.c
Object.c
Registry.c
Volume.c
${CMAKE_CURRENT_BINARY_DIR}/fltmgr.def
fltmgr.h)

View file

@ -10,6 +10,7 @@
#include "fltmgr.h"
#include "fltmgrint.h"
#include "Registry.h"
#define NDEBUG
#include <debug.h>
@ -25,6 +26,17 @@ FltpStartingToDrainObject(
_Inout_ PFLT_OBJECT Object
);
VOID
FltpMiniFilterDriverUnload(
);
static
NTSTATUS
GetFilterAltitude(
_In_ PFLT_FILTER Filter,
_Inout_ PUNICODE_STRING AltitudeString
);
/* EXPORTED FUNCTIONS ******************************************************/
@ -56,8 +68,26 @@ NTSTATUS
NTAPI
FltUnloadFilter(_In_ PCUNICODE_STRING FilterName)
{
UNREFERENCED_PARAMETER(FilterName);
return STATUS_NOT_IMPLEMENTED;
//
//FIXME: This is a temp hack, it needs properly implementing
//
UNICODE_STRING DriverServiceName;
UNICODE_STRING ServicesKey;
CHAR Buffer[MAX_KEY_LENGTH];
/* Setup the base services key */
RtlInitUnicodeString(&ServicesKey, SERVICES_KEY);
/* Initialize the string data */
DriverServiceName.Length = 0;
DriverServiceName.Buffer = (PWCH)Buffer;
DriverServiceName.MaximumLength = MAX_KEY_LENGTH;
/* Create the full service key for this filter */
RtlCopyUnicodeString(&DriverServiceName, &ServicesKey);
RtlAppendUnicodeStringToString(&DriverServiceName, FilterName);
return ZwUnloadDriver(&DriverServiceName);
}
NTSTATUS
@ -74,6 +104,8 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
PCHAR Ptr;
NTSTATUS Status;
*RetFilter = NULL;
/* Make sure we're targeting the correct major revision */
if ((Registration->Version & 0xFF00) != FLT_MAJOR_VERSION)
{
@ -145,6 +177,10 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
InitializeListHead(&Filter->ActiveOpens.mList);
Filter->ActiveOpens.mCount = 0;
ExInitializeFastMutex(&Filter->ConnectionList.mLock);
InitializeListHead(&Filter->ConnectionList.mList);
Filter->ConnectionList.mCount = 0;
/* Initialize the usermode port list */
ExInitializeFastMutex(&Filter->PortList.mLock);
InitializeListHead(&Filter->PortList.mList);
@ -199,15 +235,42 @@ FltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject,
Filter->Name.Buffer = (PWCH)Ptr;
RtlCopyUnicodeString(&Filter->Name, &DriverObject->DriverExtension->ServiceKeyName);
Status = GetFilterAltitude(Filter, &Filter->DefaultAltitude);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
//
// - Get the altitude string
// - Slot the filter into the correct altitude location
// - More stuff??
//
Quit:
if (!NT_SUCCESS(Status))
/* Store any existing driver unload routine before we make any changes */
Filter->OldDriverUnload = (PFLT_FILTER_UNLOAD_CALLBACK)DriverObject->DriverUnload;
/* Check we opted not to have an unload routine, or if we want to stop the driver from being unloaded */
if (!FlagOn(Filter->Flags, FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP))
{
DriverObject->DriverUnload = (PDRIVER_UNLOAD)FltpMiniFilterDriverUnload;
}
else
{
DriverObject->DriverUnload = (PDRIVER_UNLOAD)NULL;
}
Quit:
if (NT_SUCCESS(Status))
{
DPRINT1("Loaded FS mini-filter %wZ\n", &DriverObject->DriverExtension->ServiceKeyName);
*RetFilter = Filter;
}
else
{
DPRINT1("Failed to load FS mini-filter %wZ : 0x%X\n", &DriverObject->DriverExtension->ServiceKeyName, Status);
// Add cleanup for context resources
ExDeleteResourceLite(&Filter->InstanceList.rLock);
@ -319,3 +382,155 @@ FltpStartingToDrainObject(_Inout_ PFLT_OBJECT Object)
return STATUS_SUCCESS;
}
VOID
FltpMiniFilterDriverUnload()
{
__debugbreak();
}
/* PRIVATE FUNCTIONS ******************************************************/
static
NTSTATUS
GetFilterAltitude(
_In_ PFLT_FILTER Filter,
_Inout_ PUNICODE_STRING AltitudeString)
{
UNICODE_STRING InstancesKey = RTL_CONSTANT_STRING(L"Instances");
UNICODE_STRING DefaultInstance = RTL_CONSTANT_STRING(L"DefaultInstance");
UNICODE_STRING Altitude = RTL_CONSTANT_STRING(L"Altitude");
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING FilterInstancePath;
ULONG BytesRequired;
HANDLE InstHandle = NULL;
HANDLE RootHandle;
PWCH InstBuffer = NULL;
PWCH AltBuffer = NULL;
NTSTATUS Status;
/* Get a handle to the instances key in the filter's services key */
Status = FltpOpenFilterServicesKey(Filter,
KEY_QUERY_VALUE,
&InstancesKey,
&RootHandle);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Read the size 'default instances' string value */
Status = FltpReadRegistryValue(RootHandle,
&DefaultInstance,
REG_SZ,
NULL,
0,
&BytesRequired);
/* We should get a buffer too small error */
if (Status == STATUS_BUFFER_TOO_SMALL)
{
/* Allocate the buffer we need to hold the string */
InstBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
if (InstBuffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
/* Now read the string value */
Status = FltpReadRegistryValue(RootHandle,
&DefaultInstance,
REG_SZ,
InstBuffer,
BytesRequired,
&BytesRequired);
}
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Convert the string to a unicode_string */
RtlInitUnicodeString(&FilterInstancePath, InstBuffer);
/* Setup the attributes using the root key handle */
InitializeObjectAttributes(&ObjectAttributes,
&FilterInstancePath,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
RootHandle,
NULL);
/* Now open the key name which was stored in the default instance */
Status = ZwOpenKey(&InstHandle, KEY_QUERY_VALUE, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* Get the size of the buffer that holds the altitude */
Status = FltpReadRegistryValue(InstHandle,
&Altitude,
REG_SZ,
NULL,
0,
&BytesRequired);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
/* Allocate the required buffer */
AltBuffer = ExAllocatePoolWithTag(PagedPool, BytesRequired, FM_TAG_UNICODE_STRING);
if (AltBuffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
/* And now finally read in the actual altitude string */
Status = FltpReadRegistryValue(InstHandle,
&Altitude,
REG_SZ,
AltBuffer,
BytesRequired,
&BytesRequired);
if (NT_SUCCESS(Status))
{
/* We made it, setup the return buffer */
AltitudeString->Length = BytesRequired;
AltitudeString->MaximumLength = BytesRequired;
AltitudeString->Buffer = AltBuffer;
}
}
}
Quit:
if (!NT_SUCCESS(Status))
{
if (AltBuffer)
{
ExFreePoolWithTag(AltBuffer, FM_TAG_UNICODE_STRING);
}
}
if (InstBuffer)
{
ExFreePoolWithTag(InstBuffer, FM_TAG_UNICODE_STRING);
}
if (InstHandle)
{
ZwClose(InstHandle);
}
ZwClose(RootHandle);
return Status;
}
NTSTATUS
FltpReadRegistryValue(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG Type,
_Out_writes_bytes_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG BytesRequired
);

View file

@ -28,6 +28,8 @@
((_devObj)->DriverObject == Dispatcher::DriverObject) && \
((_devObj)->DeviceExtension != NULL))
extern PDEVICE_OBJECT CommsDeviceObject;
DRIVER_INITIALIZE DriverEntry;
NTSTATUS
@ -454,6 +456,13 @@ FltpDispatch(_In_ PDEVICE_OBJECT DeviceObject,
return Status;
}
/* Check if this is a request for a the messaging device */
if (DeviceObject == CommsDeviceObject)
{
/* Hand off to our internal routine */
return FltpMsgDispatch(DeviceObject, Irp);
}
FLT_ASSERT(DeviceExtension &&
DeviceExtension->AttachedToDeviceObject);
@ -494,6 +503,13 @@ FltpCreate(_In_ PDEVICE_OBJECT DeviceObject,
return STATUS_SUCCESS;
}
/* Check if this is a request for a the new comms connection */
if (DeviceObject == CommsDeviceObject)
{
/* Hand off to our internal routine */
return FltpMsgCreate(DeviceObject, Irp);
}
FLT_ASSERT(DeviceExtension &&
DeviceExtension->AttachedToDeviceObject);
@ -2104,9 +2120,9 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject,
Status = SetupDispatchAndCallbacksTables(DriverObject);
if (!NT_SUCCESS(Status)) goto Cleanup;
//
// TODO: Create fltmgr message device
//
/* Initialize the comms objects */
Status = FltpSetupCommunicationObjects(DriverObject);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Register for notifications when a new file system is loaded. This also enumerates any existing file systems */
Status = IoRegisterFsRegistrationChange(DriverObject, FltpFsNotification);

View file

@ -10,6 +10,7 @@
#include "fltmgr.h"
#include "fltmgrint.h"
#include <fltmgr_shared.h>
#define NDEBUG
#include <debug.h>
@ -29,6 +30,32 @@ FltpDisconnectPort(
_In_ PFLT_PORT_OBJECT PortObject
);
static
NTSTATUS
CreateClientPort(
_In_ PFILE_OBJECT FileObject,
_Inout_ PIRP Irp
);
static
NTSTATUS
CloseClientPort(
_In_ PFILE_OBJECT FileObject,
_Inout_ PIRP Irp
);
static
NTSTATUS
InitializeMessageWaiterQueue(
_Inout_ PFLT_MESSAGE_WAITER_QUEUE MsgWaiterQueue
);
static
PPORT_CCB
CreatePortCCB(
_In_ PFLT_PORT_OBJECT PortObject
);
/* EXPORTED FUNCTIONS ******************************************************/
@ -72,8 +99,8 @@ FltCreateCommunicationPort(_In_ PFLT_FILTER Filter,
return Status;
}
/* Create our new server port object */
Status = ObCreateObject(0,
/* Create the server port object for this filter */
Status = ObCreateObject(KernelMode,
ServerPortObjectType,
ObjectAttributes,
KernelMode,
@ -191,6 +218,72 @@ FltSendMessage(_In_ PFLT_FILTER Filter,
/* INTERNAL FUNCTIONS ******************************************************/
NTSTATUS
FltpMsgCreate(_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
PIO_STACK_LOCATION StackPtr;
NTSTATUS Status;
/* Get the stack location */
StackPtr = IoGetCurrentIrpStackLocation(Irp);
FLT_ASSERT(StackPtr->MajorFunction == IRP_MJ_CREATE);
/* Check if this is a caller wanting to connect */
if (StackPtr->MajorFunction == IRP_MJ_CREATE)
{
/* Create the client port for this connection and exit */
Status = CreateClientPort(StackPtr->FileObject, Irp);
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
if (Status != STATUS_PENDING)
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, 0);
}
return Status;
}
NTSTATUS
FltpMsgDispatch(_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp)
{
PIO_STACK_LOCATION StackPtr;
NTSTATUS Status;
/* Get the stack location */
StackPtr = IoGetCurrentIrpStackLocation(Irp);
/* Check if this is a caller wanting to connect */
if (StackPtr->MajorFunction == IRP_MJ_CLOSE)
{
/* Create the client port for this connection and exit */
Status = CloseClientPort(StackPtr->FileObject, Irp);
}
else
{
// We don't support anything else yet
Status = STATUS_NOT_IMPLEMENTED;
}
if (Status != STATUS_PENDING)
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, 0);
}
return Status;
}
VOID
NTAPI
FltpServerPortClose(_In_opt_ PEPROCESS Process,
@ -369,5 +462,370 @@ Quit:
return Status;
}
/* CSQ IRP CALLBACKS *******************************************************/
NTSTATUS
NTAPI
FltpAddMessageWaiter(_In_ PIO_CSQ Csq,
_In_ PIRP Irp,
_In_ PVOID InsertContext)
{
PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue;
/* Get the start of the waiter queue struct */
MessageWaiterQueue = CONTAINING_RECORD(Csq,
FLT_MESSAGE_WAITER_QUEUE,
Csq);
/* Insert the IRP at the end of the queue */
InsertTailList(&MessageWaiterQueue->WaiterQ.mList,
&Irp->Tail.Overlay.ListEntry);
/* return success */
return STATUS_SUCCESS;
}
VOID
NTAPI
FltpRemoveMessageWaiter(_In_ PIO_CSQ Csq,
_In_ PIRP Irp)
{
/* Remove the IRP from the queue */
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
PIRP
NTAPI
FltpGetNextMessageWaiter(_In_ PIO_CSQ Csq,
_In_ PIRP Irp,
_In_ PVOID PeekContext)
{
PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue;
PIRP NextIrp = NULL;
PLIST_ENTRY NextEntry;
PIO_STACK_LOCATION IrpStack;
/* Get the start of the waiter queue struct */
MessageWaiterQueue = CONTAINING_RECORD(Csq,
FLT_MESSAGE_WAITER_QUEUE,
Csq);
/* Is the IRP valid? */
if (Irp == NULL)
{
/* Start peeking from the listhead */
NextEntry = MessageWaiterQueue->WaiterQ.mList.Flink;
}
else
{
/* Start peeking from that IRP onwards */
NextEntry = Irp->Tail.Overlay.ListEntry.Flink;
}
/* Loop through the queue */
while (NextEntry != &MessageWaiterQueue->WaiterQ.mList)
{
/* Store the next IRP in the list */
NextIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
/* Did we supply a PeekContext on insert? */
if (!PeekContext)
{
/* We already have the next IRP */
break;
}
else
{
/* Get the stack of the next IRP */
IrpStack = IoGetCurrentIrpStackLocation(NextIrp);
/* Does the PeekContext match the object? */
if (IrpStack->FileObject == (PFILE_OBJECT)PeekContext)
{
/* We have a match */
break;
}
/* Move to the next IRP */
NextIrp = NULL;
NextEntry = NextEntry->Flink;
}
}
return NextIrp;
}
_Acquires_lock_(((PFLT_MESSAGE_WAITER_QUEUE)CONTAINING_RECORD(Csq, FLT_MESSAGE_WAITER_QUEUE, Csq))->WaiterQ.mLock)
_IRQL_saves_global_(Irql, ((PFLT_MESSAGE_WAITER_QUEUE)CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue))->WaiterQ.mLock)
_IRQL_raises_(DISPATCH_LEVEL)
VOID
NTAPI
FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq,
_Out_ PKIRQL Irql)
{
PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue;
UNREFERENCED_PARAMETER(Irql);
/* Get the start of the waiter queue struct */
MessageWaiterQueue = CONTAINING_RECORD(Csq,
FLT_MESSAGE_WAITER_QUEUE,
Csq);
/* Acquire the IRP queue lock */
ExAcquireFastMutex(&MessageWaiterQueue->WaiterQ.mLock);
}
_Releases_lock_(((PFLT_MESSAGE_WAITER_QUEUE)CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue))->WaiterQ.mLock)
_IRQL_restores_global_(Irql, ((PFLT_MESSAGE_WAITER_QUEUE)CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue))->WaiterQ.mLock)
_IRQL_requires_(DISPATCH_LEVEL)
VOID
NTAPI
FltpReleaseMessageWaiterLock(_In_ PIO_CSQ Csq,
_In_ KIRQL Irql)
{
PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue;
UNREFERENCED_PARAMETER(Irql);
/* Get the start of the waiter queue struct */
MessageWaiterQueue = CONTAINING_RECORD(Csq,
FLT_MESSAGE_WAITER_QUEUE,
Csq);
/* Release the IRP queue lock */
ExReleaseFastMutex(&MessageWaiterQueue->WaiterQ.mLock);
}
VOID
NTAPI
FltpCancelMessageWaiter(_In_ PIO_CSQ Csq,
_In_ PIRP Irp)
{
/* Cancel the IRP */
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
/* PRIVATE FUNCTIONS ******************************************************/
static
NTSTATUS
CreateClientPort(_In_ PFILE_OBJECT FileObject,
_Inout_ PIRP Irp)
{
PFLT_SERVER_PORT_OBJECT ServerPortObject = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
PFILTER_PORT_DATA FilterPortData;
PFLT_PORT_OBJECT ClientPortObject = NULL;
PFLT_PORT PortHandle = NULL;
PPORT_CCB PortCCB = NULL;
//ULONG BufferLength;
LONG NumConns;
NTSTATUS Status;
/* We received the buffer via FilterConnectCommunicationPort, cast it back to its original form */
FilterPortData = Irp->AssociatedIrp.SystemBuffer;
/* Get a reference to the server port the filter created */
Status = ObReferenceObjectByName(&FilterPortData->PortName,
0,
0,
FLT_PORT_ALL_ACCESS,
ServerPortObjectType,
ExGetPreviousMode(),
0,
(PVOID *)&ServerPortObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Increment the number of connections on the server port */
NumConns = InterlockedIncrement(&ServerPortObject->NumberOfConnections);
if (NumConns > ServerPortObject->MaxConnections)
{
Status = STATUS_CONNECTION_COUNT_LIMIT;
goto Quit;
}
/* Initialize a basic kernel handle request */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
/* Now create the new client port object */
Status = ObCreateObject(KernelMode,
ClientPortObjectType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(FLT_PORT_OBJECT),
0,
0,
(PVOID *)&ClientPortObject);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Clear out the buffer */
RtlZeroMemory(ClientPortObject, sizeof(FLT_PORT_OBJECT));
/* Initialize the locks */
ExInitializeRundownProtection(&ClientPortObject->MsgNotifRundownRef);
ExInitializeFastMutex(&ClientPortObject->Lock);
/* Set the server port object this belongs to */
ClientPortObject->ServerPort = ServerPortObject;
/* Setup the message queue */
Status = InitializeMessageWaiterQueue(&ClientPortObject->MsgQ);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Create the CCB which we'll attach to the file object */
PortCCB = CreatePortCCB(ClientPortObject);
if (PortCCB == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
/* Now insert the new client port into the object manager*/
Status = ObInsertObject(ClientPortObject, 0, FLT_PORT_ALL_ACCESS, 1, 0, (PHANDLE)&PortHandle);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Add a reference to the filter to keep it alive while we do some work with it */
Status = FltObjectReference(ServerPortObject->Filter);
if (NT_SUCCESS(Status))
{
/* Invoke the callback to let the filter know we have a connection */
Status = ServerPortObject->ConnectNotify(PortHandle,
ServerPortObject->Cookie,
NULL, //ConnectionContext
0, //SizeOfContext
&ClientPortObject->Cookie);
if (NT_SUCCESS(Status))
{
/* Add the client port CCB to the file object */
FileObject->FsContext2 = PortCCB;
/* Lock the port list on the filter and add this new port object to the list */
ExAcquireFastMutex(&ServerPortObject->Filter->PortList.mLock);
InsertTailList(&ServerPortObject->Filter->PortList.mList, &ClientPortObject->FilterLink);
ExReleaseFastMutex(&ServerPortObject->Filter->PortList.mLock);
}
/* We're done with the filter object, decremement the count */
FltObjectDereference(ServerPortObject->Filter);
}
Quit:
if (!NT_SUCCESS(Status))
{
if (ClientPortObject)
{
ObfDereferenceObject(ClientPortObject);
}
if (PortHandle)
{
ZwClose(PortHandle);
}
else if (ServerPortObject)
{
InterlockedDecrement(&ServerPortObject->NumberOfConnections);
ObfDereferenceObject(ServerPortObject);
}
if (PortCCB)
{
ExFreePoolWithTag(PortCCB, FM_TAG_CCB);
}
}
return Status;
}
static
NTSTATUS
CloseClientPort(_In_ PFILE_OBJECT FileObject,
_Inout_ PIRP Irp)
{
PFLT_CCB Ccb;
Ccb = (PFLT_CCB)FileObject->FsContext2;
/* Remove the reference on the filter we added when we opened the port */
ObDereferenceObject(Ccb->Data.Port.Port);
// FIXME: Free the CCB
return STATUS_SUCCESS;
}
static
NTSTATUS
InitializeMessageWaiterQueue(_Inout_ PFLT_MESSAGE_WAITER_QUEUE MsgWaiterQueue)
{
NTSTATUS Status;
/* Setup the IRP queue */
Status = IoCsqInitializeEx(&MsgWaiterQueue->Csq,
FltpAddMessageWaiter,
FltpRemoveMessageWaiter,
FltpGetNextMessageWaiter,
FltpAcquireMessageWaiterLock,
FltpReleaseMessageWaiterLock,
FltpCancelMessageWaiter);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Initialize the waiter queue */
ExInitializeFastMutex(&MsgWaiterQueue->WaiterQ.mLock);
InitializeListHead(&MsgWaiterQueue->WaiterQ.mList);
MsgWaiterQueue->WaiterQ.mCount = 0;
/* We don't have a minimum waiter length */
MsgWaiterQueue->MinimumWaiterLength = (ULONG)-1;
/* Init the semaphore and event used for counting and signaling available IRPs */
KeInitializeSemaphore(&MsgWaiterQueue->Semaphore, 0, MAXLONG);
KeInitializeEvent(&MsgWaiterQueue->Event, NotificationEvent, FALSE);
return STATUS_SUCCESS;
}
static
PPORT_CCB
CreatePortCCB(_In_ PFLT_PORT_OBJECT PortObject)
{
PPORT_CCB PortCCB;
/* Allocate a CCB struct to hold the client port object info */
PortCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(PPORT_CCB), FM_TAG_CCB);
if (PortCCB)
{
/* Initialize the structure */
PortCCB->Port = PortObject;
PortCCB->ReplyWaiterList.mCount = 0;
ExInitializeFastMutex(&PortCCB->ReplyWaiterList.mLock);
KeInitializeEvent(&PortCCB->ReplyWaiterList.mLock.Event, SynchronizationEvent, 0);
}
return PortCCB;
}

View file

@ -29,8 +29,8 @@ FltBuildDefaultSecurityDescriptor(
_In_ ACCESS_MASK DesiredAccess
)
{
UNREFERENCED_PARAMETER(SecurityDescriptor);
UNREFERENCED_PARAMETER(DesiredAccess);
*SecurityDescriptor = NULL;
return 0;
}

View file

@ -0,0 +1,142 @@
/*
* PROJECT: Filesystem Filter Manager
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/filters/fltmgr/Misc.c
* PURPOSE: Uncataloged functions
* PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "fltmgr.h"
#include "fltmgrint.h"
#define NDEBUG
#include <debug.h>
/* DATA *********************************************************************/
#define REG_SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
#define REG_PATH_LENGTH 512
/* INTERNAL FUNCTIONS ******************************************************/
NTSTATUS
FltpOpenFilterServicesKey(
_In_ PFLT_FILTER Filter,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ PUNICODE_STRING SubKey,
_Out_ PHANDLE Handle)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ServicesKey;
UNICODE_STRING Path;
WCHAR Buffer[REG_PATH_LENGTH];
/* Setup a local buffer to hold the services key path */
Path.Length = 0;
Path.MaximumLength = REG_PATH_LENGTH;
Path.Buffer = Buffer;
/* Build up the serices key name */
RtlInitUnicodeString(&ServicesKey, REG_SERVICES_KEY);
RtlCopyUnicodeString(&Path, &ServicesKey);
RtlAppendUnicodeStringToString(&Path, &Filter->Name);
if (SubKey)
{
/* Tag on any child key */
RtlAppendUnicodeToString(&Path, L"\\");
RtlAppendUnicodeStringToString(&Path, SubKey);
}
InitializeObjectAttributes(&ObjectAttributes,
&Path,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Open and return the key handle param*/
return ZwOpenKey(Handle, DesiredAccess, &ObjectAttributes);
}
NTSTATUS
FltpReadRegistryValue(_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG Type,
_Out_writes_bytes_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG BytesRequired)
{
PKEY_VALUE_PARTIAL_INFORMATION Value = NULL;
ULONG ValueLength = 0;
NTSTATUS Status;
PAGED_CODE();
/* Get the size of the buffer required to hold the string */
Status = ZwQueryValueKey(KeyHandle,
ValueName,
KeyValuePartialInformation,
NULL,
0,
&ValueLength);
if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
{
return Status;
}
/* Allocate the buffer */
Value = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool,
ValueLength,
FM_TAG_TEMP_REGISTRY);
if (Value == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
/* Now read in the value */
Status = ZwQueryValueKey(KeyHandle,
ValueName,
KeyValuePartialInformation,
Value,
ValueLength,
&ValueLength);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Make sure we got the type expected */
if (Value->Type != Type)
{
Status = STATUS_INVALID_PARAMETER;
goto Quit;
}
if (BytesRequired)
{
*BytesRequired = Value->DataLength;
}
/* Make sure the caller buffer is big enough to hold the data */
if (!BufferSize || BufferSize < Value->DataLength)
{
Status = STATUS_BUFFER_TOO_SMALL;
goto Quit;
}
/* Copy the data into the caller buffer */
RtlCopyMemory(Buffer, Value->Data, Value->DataLength);
Quit:
if (Value)
ExFreePoolWithTag(Value, FM_TAG_TEMP_REGISTRY);
return Status;
}

View file

@ -0,0 +1,20 @@
#pragma once
NTSTATUS
FltpOpenFilterServicesKey(
_In_ PFLT_FILTER Filter,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ PUNICODE_STRING SubKey,
_Out_ PHANDLE Handle
);
NTSTATUS
FltpReadRegistryValue(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName,
_In_opt_ ULONG Type,
_Out_writes_bytes_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_Out_opt_ PULONG BytesRequired
);

View file

@ -18,6 +18,8 @@
#define FM_TAG_UNICODE_STRING 'suMF'
#define FM_TAG_FILTER 'lfMF'
#define FM_TAG_CONTEXT_REGISTA 'rcMF'
#define FM_TAG_CCB 'bcMF'
#define FM_TAG_TEMP_REGISTRY 'rtMF'
#define MAX_DEVNAME_LENGTH 64
@ -100,6 +102,9 @@ FltpReallocateUnicodeString(_In_ PUNICODE_STRING String,
VOID
FltpFreeUnicodeString(_In_ PUNICODE_STRING String);
////////////////////////////////////////////////
@ -252,7 +257,7 @@ FltGetUpperInstance
FltGetVolumeContext
FltGetVolumeFromDeviceObject
FltGetVolumeFromFileObject
FltGetVolumeFromInstance
FltLoadFilter
FltGetVolumeFromName
FltGetVolumeGuidName
FltGetVolumeInstanceFromName

View file

@ -58,10 +58,45 @@ typedef struct _FLT_MUTEX_LIST_HEAD
} FLT_MUTEX_LIST_HEAD, *PFLT_MUTEX_LIST_HEAD;
typedef struct _FLT_TYPE
{
USHORT Signature;
USHORT Size;
} FLT_TYPE, *PFLT_TYPE;
// http://fsfilters.blogspot.co.uk/2010/02/filter-manager-concepts-part-1.html
typedef struct _FLTP_FRAME
{
FLT_TYPE Type;
LIST_ENTRY Links;
unsigned int FrameID;
ERESOURCE AltitudeLock;
UNICODE_STRING AltitudeIntervalLow;
UNICODE_STRING AltitudeIntervalHigh;
char LargeIrpCtrlStackSize;
char SmallIrpCtrlStackSize;
FLT_RESOURCE_LIST_HEAD RegisteredFilters;
FLT_RESOURCE_LIST_HEAD AttachedVolumes;
LIST_ENTRY MountingVolumes;
FLT_MUTEX_LIST_HEAD AttachedFileSystems;
FLT_MUTEX_LIST_HEAD ZombiedFltObjectContexts;
ERESOURCE FilterUnloadLock;
FAST_MUTEX DeviceObjectAttachLock;
//FLT_PRCB *Prcb;
void *PrcbPoolToFree;
void *LookasidePoolToFree;
//FLTP_IRPCTRL_STACK_PROFILER IrpCtrlStackProfiler;
NPAGED_LOOKASIDE_LIST SmallIrpCtrlLookasideList;
NPAGED_LOOKASIDE_LIST LargeIrpCtrlLookasideList;
//STATIC_IRP_CONTROL GlobalSIC;
} FLTP_FRAME, *PFLTP_FRAME;
typedef struct _FLT_FILTER // size = 0x120
{
FLT_OBJECT Base;
PVOID Frame; //FLTP_FRAME
PFLTP_FRAME Frame;
UNICODE_STRING Name;
UNICODE_STRING DefaultAltitude;
FLT_FILTER_FLAGS Flags;
@ -97,12 +132,7 @@ typedef enum _FLT_yINSTANCE_FLAGS
} FLT_INSTANCE_FLAGS, *PFLT_INSTANCE_FLAGS;
typedef struct _FLT_TYPE
{
USHORT Signature;
USHORT Size;
} FLT_TYPE, *PFLT_TYPE;
typedef struct _FLT_INSTANCE // size = 0x144 (324)
{
@ -121,34 +151,18 @@ typedef struct _FLT_INSTANCE // size = 0x144 (324)
} FLT_INSTANCE, *PFLT_INSTANCE;
// http://fsfilters.blogspot.co.uk/2010/02/filter-manager-concepts-part-1.html
typedef struct _FLTP_FRAME
typedef struct _TREE_ROOT
{
FLT_TYPE Type;
LIST_ENTRY Links;
unsigned int FrameID;
ERESOURCE AltitudeLock;
UNICODE_STRING AltitudeIntervalLow;
UNICODE_STRING AltitudeIntervalHigh;
char LargeIrpCtrlStackSize;
char SmallIrpCtrlStackSize;
FLT_RESOURCE_LIST_HEAD RegisteredFilters;
FLT_RESOURCE_LIST_HEAD AttachedVolumes;
LIST_ENTRY MountingVolumes;
FLT_MUTEX_LIST_HEAD AttachedFileSystems;
FLT_MUTEX_LIST_HEAD ZombiedFltObjectContexts;
ERESOURCE FilterUnloadLock;
FAST_MUTEX DeviceObjectAttachLock;
//FLT_PRCB *Prcb;
void *PrcbPoolToFree;
void *LookasidePoolToFree;
//FLTP_IRPCTRL_STACK_PROFILER IrpCtrlStackProfiler;
NPAGED_LOOKASIDE_LIST SmallIrpCtrlLookasideList;
NPAGED_LOOKASIDE_LIST LargeIrpCtrlLookasideList;
//STATIC_IRP_CONTROL GlobalSIC;
RTL_SPLAY_LINKS *Tree;
} FLTP_FRAME, *PFLTP_FRAME;
} TREE_ROOT, *PTREE_ROOT;
typedef struct _CONTEXT_LIST_CTRL
{
TREE_ROOT List;
} CONTEXT_LIST_CTRL, *PCONTEXT_LIST_CTRL;
// http://fsfilters.blogspot.co.uk/2010/02/filter-manager-concepts-part-6.html
typedef struct _STREAM_LIST_CTRL // size = 0xC8 (200)
@ -156,16 +170,16 @@ typedef struct _STREAM_LIST_CTRL // size = 0xC8 (200)
FLT_TYPE Type;
FSRTL_PER_STREAM_CONTEXT ContextCtrl;
LIST_ENTRY VolumeLink;
//STREAM_LIST_CTRL_FLAGS Flags;
ULONG Flags; //STREAM_LIST_CTRL_FLAGS Flags;
int UseCount;
ERESOURCE ContextLock;
//CONTEXT_LIST_CTRL StreamContexts;
//CONTEXT_LIST_CTRL StreamHandleContexts;
CONTEXT_LIST_CTRL StreamContexts;
CONTEXT_LIST_CTRL StreamHandleContexts;
ERESOURCE NameCacheLock;
LARGE_INTEGER LastRenameCompleted;
//NAME_CACHE_LIST_CTRL NormalizedNameCache;
// NAME_CACHE_LIST_CTRL ShortNameCache;
// NAME_CACHE_LIST_CTRL OpenedNameCache;
ULONG NormalizedNameCache; //NAME_CACHE_LIST_CTRL NormalizedNameCache;
ULONG ShortNameCache; // NAME_CACHE_LIST_CTRL ShortNameCache;
ULONG OpenedNameCache; // NAME_CACHE_LIST_CTRL OpenedNameCache;
int AllNameContextsTemporary;
} STREAM_LIST_CTRL, *PSTREAM_LIST_CTRL;
@ -186,6 +200,17 @@ typedef struct _FLT_SERVER_PORT_OBJECT
} FLT_SERVER_PORT_OBJECT, *PFLT_SERVER_PORT_OBJECT;
typedef struct _FLT_MESSAGE_WAITER_QUEUE
{
IO_CSQ Csq;
FLT_MUTEX_LIST_HEAD WaiterQ;
ULONG MinimumWaiterLength;
KSEMAPHORE Semaphore;
KEVENT Event;
} FLT_MESSAGE_WAITER_QUEUE, *PFLT_MESSAGE_WAITER_QUEUE;
typedef struct _FLT_PORT_OBJECT
{
LIST_ENTRY FilterLink;
@ -193,7 +218,7 @@ typedef struct _FLT_PORT_OBJECT
PVOID Cookie;
EX_RUNDOWN_REF MsgNotifRundownRef;
FAST_MUTEX Lock;
PVOID MsgQ; // FLT_MESSAGE_WAITER_QUEUE MsgQ;
FLT_MESSAGE_WAITER_QUEUE MsgQ;
ULONGLONG MessageId;
KEVENT DisconnectEvent;
BOOLEAN Disconnected;
@ -232,18 +257,6 @@ typedef struct _CALLBACK_CTRL
} CALLBACK_CTRL, *PCALLBACK_CTRL;
typedef struct _TREE_ROOT
{
RTL_SPLAY_LINKS *Tree;
} TREE_ROOT, *PTREE_ROOT;
typedef struct _CONTEXT_LIST_CTRL
{
TREE_ROOT List;
} CONTEXT_LIST_CTRL, *PCONTEXT_LIST_CTRL;
typedef struct _NAME_CACHE_LIST_CTRL_STATS
{
@ -311,6 +324,58 @@ typedef struct _FLT_VOLUME
} FLT_VOLUME, *PFLT_VOLUME;
typedef struct _MANAGER_CCB
{
PFLTP_FRAME Frame;
unsigned int Iterator;
} MANAGER_CCB, *PMANAGER_CCB;
typedef struct _FILTER_CCB
{
PFLT_FILTER Filter;
unsigned int Iterator;
} FILTER_CCB, *PFILTER_CCB;
typedef struct _INSTANCE_CCB
{
PFLT_INSTANCE Instance;
} INSTANCE_CCB, *PINSTANCE_CCB;
typedef struct _VOLUME_CCB
{
UNICODE_STRING Volume;
unsigned int Iterator;
} VOLUME_CCB, *PVOLUME_CCB;
typedef struct _PORT_CCB
{
PFLT_PORT_OBJECT Port;
FLT_MUTEX_LIST_HEAD ReplyWaiterList;
} PORT_CCB, *PPORT_CCB;
typedef union _CCB_TYPE
{
MANAGER_CCB Manager;
FILTER_CCB Filter;
INSTANCE_CCB Instance;
VOLUME_CCB Volume;
PORT_CCB Port;
} CCB_TYPE, *PCCB_TYPE;
typedef struct _FLT_CCB
{
FLT_TYPE Type;
CCB_TYPE Data;
} FLT_CCB, *PFLT_CCB;
VOID
FltpExInitializeRundownProtection(
@ -387,6 +452,21 @@ FltpDispatchHandler(
_Inout_ PIRP Irp
);
NTSTATUS
FltpMsgCreate(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp
);
NTSTATUS
FltpMsgDispatch(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp
);
NTSTATUS
FltpSetupCommunicationObjects(
_In_ PDRIVER_OBJECT DriverObject
);
#endif /* _FLTMGR_INTERNAL_H */

View file

@ -127,6 +127,10 @@ list(APPEND KMTEST_SOURCE
kmtest/testlist.c
example/Example_user.c
fltmgr/fltmgr_load/fltmgr_user.c
fltmgr/fltmgr_register/fltmgr_reg_user.c
hidparse/HidP_user.c
kernel32/FileAttributes_user.c
kernel32/FindFile_user.c

View file

@ -1,3 +1,4 @@
add_subdirectory(fltmgr_load)
add_subdirectory(fltmgr_create)
add_subdirectory(fltmgr_register)

View file

@ -5,10 +5,10 @@ list(APPEND FLTMGR_TEST_DRV_SOURCE
../../kmtest_drv/kmtest_fsminifilter.c
fltmgr_load.c)
add_library(fltmgr_load SHARED ${FLTMGR_TEST_DRV_SOURCE})
set_module_type(fltmgr_load kernelmodedriver)
target_link_libraries(fltmgr_load kmtest_printf ${PSEH_LIB})
add_importlibs(fltmgr_load fltmgr ntoskrnl hal)
add_target_compile_definitions(fltmgr_load KMT_STANDALONE_DRIVER KMT_FILTER_DRIVER NTDDI_VERSION=NTDDI_WS03SP1)
add_library(FltMgrLoad_drv SHARED ${FLTMGR_TEST_DRV_SOURCE})
set_module_type(FltMgrLoad_drv kernelmodedriver)
target_link_libraries(FltMgrLoad_drv kmtest_printf ${PSEH_LIB})
add_importlibs(FltMgrLoad_drv fltmgr ntoskrnl hal)
add_target_compile_definitions(FltMgrLoad_drv KMT_STANDALONE_DRIVER KMT_FILTER_DRIVER NTDDI_VERSION=NTDDI_WS03SP1)
#add_pch(example_drv ../include/kmt_test.h)
add_rostests_file(TARGET fltmgr_load)
add_rostests_file(TARGET FltMgrLoad_drv)

View file

@ -89,7 +89,7 @@ TestEntry(
ok_irql(PASSIVE_LEVEL);
TestDriverObject = DriverObject;
*DeviceName = L"fltmgr_load";
*DeviceName = L"FltMgrLoad";
trace("Hi, this is the filter manager load test driver\n");

View file

@ -0,0 +1,28 @@
/*
* PROJECT: ReactOS kernel-mode tests - Filter Manager
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Tests for checking filters load and connect correctly
* PROGRAMMER: Ged Murphy <gedmurphy@reactos.org>
*/
#include <kmt_test.h>
START_TEST(FltMgrLoad)
{
static WCHAR FilterName[] = L"FltMgrLoad";
SC_HANDLE hService;
HANDLE hPort;
trace("Message from user-mode\n");
ok(KmtFltCreateService(FilterName, L"FltMgrLoad test driver", &hService) == ERROR_SUCCESS, "\n");
ok(KmtFltLoadDriver(FALSE, FALSE, FALSE, &hPort) == ERROR_PRIVILEGE_NOT_HELD, "\n");
ok(KmtFltLoadDriver(TRUE, FALSE, FALSE, &hPort) == ERROR_SUCCESS, "\n");
ok(KmtFltConnectComms(&hPort) == ERROR_SUCCESS, "\n");
ok(KmtFltDisconnectComms(hPort) == ERROR_SUCCESS, "\n");
ok(KmtFltUnloadDriver(hPort, FALSE) == ERROR_SUCCESS, "\n");
KmtFltDeleteService(NULL, &hService);
}

View file

@ -0,0 +1,15 @@
include_directories(../../include)
include_directories(${REACTOS_SOURCE_DIR}/drivers/filters/fltmgr)
list(APPEND FLTMGR_TEST_DRV_SOURCE
../../kmtest_drv/kmtest_fsminifilter.c
fltmgr_register.c)
add_library(fltmgrreg_drv SHARED ${FLTMGR_TEST_DRV_SOURCE})
set_module_type(fltmgrreg_drv kernelmodedriver)
target_link_libraries(fltmgrreg_drv kmtest_printf ${PSEH_LIB})
add_importlibs(fltmgrreg_drv fltmgr ntoskrnl hal)
add_target_compile_definitions(fltmgrreg_drv KMT_STANDALONE_DRIVER KMT_FILTER_DRIVER NTDDI_VERSION=NTDDI_WS03SP1)
#add_pch(example_drv ../include/kmt_test.h)
add_rostests_file(TARGET fltmgrreg_drv)

View file

@ -0,0 +1,23 @@
/*
* PROJECT: ReactOS kernel-mode tests - Filter Manager
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Tests for checking filter registration
* PROGRAMMER: Ged Murphy <gedmurphy@reactos.org>
*/
#include <kmt_test.h>
START_TEST(FltMgrReg)
{
static WCHAR FilterName[] = L"FltMgrReg";
SC_HANDLE hService;
HANDLE hPort;
ok(KmtFltCreateService(FilterName, L"FltMgrLoad test driver", &hService) == ERROR_SUCCESS, "Failed to create the reg entry\n");
ok(KmtFltAddAltitude(L"123456") == ERROR_SUCCESS, "\n");
ok(KmtFltLoadDriver(TRUE, FALSE, FALSE, &hPort) == ERROR_SUCCESS, "Failed to load the driver\n");
//__debugbreak();
ok(KmtFltUnloadDriver(hPort, FALSE) == ERROR_SUCCESS, "Failed to unload the driver\n");
ok(KmtFltDeleteService(NULL, &hService) == ERROR_SUCCESS, "Failed to delete the driver\n");
}

View file

@ -0,0 +1,248 @@
/*
* PROJECT: ReactOS kernel-mode tests - Filter Manager
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: Tests for checking filter registration
* PROGRAMMER: Ged Murphy <gedmurphy@reactos.org>
*/
// This tests needs to be run via a standalone driver because FltRegisterFilter
// uses the DriverObject in its internal structures, and we don't want it to be
// linked to a device object from the test suite itself.
#include <kmt_test.h>
#include <fltkernel.h>
#include <fltmgrint.h>
//#define NDEBUG
#include <debug.h>
#define RESET_REGISTRATION(basic) \
do { \
RtlZeroMemory(&FilterRegistration, sizeof(FLT_REGISTRATION)); \
if (basic) { \
FilterRegistration.Size = sizeof(FLT_REGISTRATION); \
FilterRegistration.Version = FLT_REGISTRATION_VERSION; \
} \
} while (0)
#define RESET_UNLOAD(DO) DO->DriverUnload = NULL;
NTSTATUS
FLTAPI
TestRegFilterUnload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);
/* Globals */
static PDRIVER_OBJECT TestDriverObject;
static FLT_REGISTRATION FilterRegistration;
static PFLT_FILTER TestFilter = NULL;
BOOLEAN
TestFltRegisterFilter(_In_ PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING Altitude;
UNICODE_STRING Name;
PFLT_FILTER Filter = NULL;
PFLT_FILTER Temp = NULL;
NTSTATUS Status;
RESET_REGISTRATION(FALSE);
#if 0
KmtStartSeh()
Status = FltRegisterFilter(NULL, &FilterRegistration, &Filter);
KmtEndSeh(STATUS_INVALID_PARAMETER);
KmtStartSeh()
Status = FltRegisterFilter(DriverObject, NULL, &Filter);
KmtEndSeh(STATUS_INVALID_PARAMETER);
KmtStartSeh()
Status = FltRegisterFilter(DriverObject, &FilterRegistration, NULL);
KmtEndSeh(STATUS_INVALID_PARAMETER)
#endif
RESET_REGISTRATION(TRUE);
FilterRegistration.Version = 0x0100;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
RESET_REGISTRATION(TRUE);
FilterRegistration.Version = 0x0300;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_INVALID_PARAMETER);
RESET_REGISTRATION(TRUE);
FilterRegistration.Version = 0x0200;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_SUCCESS);
FltUnregisterFilter(Filter);
/* Test invalid sizes. MSDN says this is required, but it doesn't appear to be */
RESET_REGISTRATION(TRUE);
FilterRegistration.Size = 0;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_SUCCESS);
FltUnregisterFilter(Filter);
RESET_REGISTRATION(TRUE);
FilterRegistration.Size = 0xFFFF;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_SUCCESS);
FltUnregisterFilter(Filter);
/* Now make a valid registration */
RESET_REGISTRATION(TRUE);
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Filter);
ok_eq_hex(Status, STATUS_SUCCESS);
/* Try to register again */
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &Temp);
ok_eq_hex(Status, STATUS_FLT_INSTANCE_ALTITUDE_COLLISION);
ok_eq_hex(Filter->Base.Flags, FLT_OBFL_TYPE_FILTER);
/* Check we have the right filter name */
RtlInitUnicodeString(&Name, L"Kmtest-FltMgrReg");
ok_eq_long(RtlCompareUnicodeString(&Filter->Name, &Name, FALSE), 0);
/* And the altitude is corect */
RtlInitUnicodeString(&Altitude, L"123456");
ok_eq_long(RtlCompareUnicodeString(&Filter->DefaultAltitude, &Altitude, FALSE), 0);
//
// FIXME: More checks
//
/* Cleanup the valid registration */
FltUnregisterFilter(Filter);
/*
* The last thing we'll do before we exit is to properly register with the filter manager
* and set an unload routine. This'll let us test the FltUnregisterFilter routine
*/
RESET_REGISTRATION(TRUE);
/* Set a fake unload routine we'll use to test */
DriverObject->DriverUnload = (PDRIVER_UNLOAD)0x1234FFFF;
FilterRegistration.FilterUnloadCallback = TestRegFilterUnload;
Status = FltRegisterFilter(DriverObject, &FilterRegistration, &TestFilter);
ok_eq_hex(Status, STATUS_SUCCESS);
/* Test all the unlod routines */
ok_eq_pointer(TestFilter->FilterUnload, TestRegFilterUnload);
ok_eq_pointer(TestFilter->OldDriverUnload, (PFLT_FILTER_UNLOAD_CALLBACK)0x1234FFFF);
// This should equal the fltmgr's private unload routine, but there's no easy way of testing it...
//ok_eq_pointer(DriverObject->DriverUnload, FltpMiniFilterDriverUnload);
/* Make sure our test address is never actually called */
TestFilter->OldDriverUnload = (PFLT_FILTER_UNLOAD_CALLBACK)NULL;
return TRUE;
}
NTSTATUS
FLTAPI
TestRegFilterUnload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{
//__debugbreak();
ok_irql(PASSIVE_LEVEL);
ok(TestFilter != NULL, "Buffer is NULL\n");
//
// FIXME: Add tests
//
FltUnregisterFilter(TestFilter);
//
// FIXME: Add tests
//
return STATUS_SUCCESS;
}
/*
* KMT Callback routines
*/
NTSTATUS
TestEntry(
IN PDRIVER_OBJECT DriverObject,
IN PCUNICODE_STRING RegistryPath,
OUT PCWSTR *DeviceName,
IN OUT INT *Flags)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
UNREFERENCED_PARAMETER(RegistryPath);
DPRINT("FltMgrReg Entry!\n");
trace("Entered FltMgrReg tests\n");
/* We'll do the work ourselves in this test */
*Flags = TESTENTRY_NO_ALL;
ok_irql(PASSIVE_LEVEL);
TestDriverObject = DriverObject;
/* Run the tests */
(VOID)TestFltRegisterFilter(DriverObject);
return Status;
}
VOID
TestFilterUnload(
IN ULONG Flags)
{
PAGED_CODE();
ok_irql(PASSIVE_LEVEL);
}
NTSTATUS
TestInstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType,
_In_ PUNICODE_STRING VolumeName,
_In_ ULONG SectorSize,
_In_ ULONG ReportedSectorSize
)
{
return STATUS_FLT_DO_NOT_ATTACH;
}
VOID
TestQueryTeardown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
}

View file

@ -44,6 +44,7 @@
#include <strsafe.h>
#include <fltuser.h>
#ifdef KMT_EMULATE_KERNEL
#define ok_irql(i)
#define KIRQL int

View file

@ -126,9 +126,12 @@ NTSTATUS KmtFilterRegisterCallbacks(_In_ CONST FLT_OPERATION_REGISTRATION *Opera
typedef enum
{
TESTENTRY_NO_REGISTER_FILTER = 1,
TESTENTRY_NO_CREATE_COMMS_PORT = 2,
TESTENTRY_NO_START_FILTERING = 4,
TESTENTRY_NO_REGISTER_FILTER = 0x01,
TESTENTRY_NO_CREATE_COMMS_PORT = 0x02,
TESTENTRY_NO_START_FILTERING = 0x04,
TESTENTRY_NO_INSTANCE_SETUP = 0x08,
TESTENTRY_NO_QUERY_TEARDOWN = 0x10,
TESTENTRY_NO_ALL = 0xFF
} KMT_MINIFILTER_FLAGS;
VOID TestFilterUnload(_In_ ULONG Flags);
@ -174,8 +177,14 @@ DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String);
DWORD KmtSendUlongToDriver(IN DWORD ControlCode, IN DWORD Value);
DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength);
DWORD KmtFltLoadDriver(_In_z_ PCWSTR ServiceName, _In_ BOOLEAN RestartIfRunning, _In_ BOOLEAN ConnectComms, _Out_ HANDLE *hPort);
DWORD KmtFltCreateService(_In_z_ PCWSTR ServiceName, _In_z_ PCWSTR DisplayName, _Out_ SC_HANDLE *ServiceHandle);
DWORD KmtFltDeleteService(_In_opt_z_ PCWSTR ServiceName, _Inout_ SC_HANDLE *ServiceHandle);
DWORD KmtFltAddAltitude(_In_z_ LPWSTR Altitude);
DWORD KmtFltLoadDriver(_In_ BOOLEAN EnableDriverLoadPrivlege, _In_ BOOLEAN RestartIfRunning, _In_ BOOLEAN ConnectComms, _Out_ HANDLE *hPort);
DWORD KmtFltUnloadDriver(_In_ HANDLE *hPort, _In_ BOOLEAN DisonnectComms);
DWORD KmtFltConnectComms(_Out_ HANDLE *hPort);
DWORD KmtFltDisconnectComms(_In_ HANDLE hPort);
DWORD KmtFltRunKernelTest(_In_ HANDLE hPort, _In_z_ PCSTR TestName);
DWORD KmtFltSendToDriver(_In_ HANDLE hPort, _In_ DWORD Message);
DWORD KmtFltSendStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCSTR String);

View file

@ -14,49 +14,7 @@
#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
/*
* We need to call the internal function in the service.c file
*/
DWORD
KmtpCreateService(
IN PCWSTR ServiceName,
IN PCWSTR ServicePath,
IN PCWSTR DisplayName OPTIONAL,
IN DWORD ServiceType,
OUT SC_HANDLE *ServiceHandle);
static SC_HANDLE ScmHandle;
/**
* @name KmtFltCreateService
*
* Create the specified driver service and return a handle to it
*
* @param ServiceName
* Name of the service to create
* @param ServicePath
* File name of the driver, relative to the current directory
* @param DisplayName
* Service display name
* @param ServiceHandle
* Pointer to a variable to receive the handle to the service
*
* @return Win32 error code
*/
DWORD
KmtFltCreateService(
_In_z_ PCWSTR ServiceName,
_In_z_ PCWSTR ServicePath,
_In_z_ PCWSTR DisplayName OPTIONAL,
_Out_ SC_HANDLE *ServiceHandle)
{
return KmtpCreateService(ServiceName,
ServicePath,
DisplayName,
SERVICE_FILE_SYSTEM_DRIVER,
ServiceHandle);
}
/**
* @name KmtFltLoad
@ -82,7 +40,7 @@ KmtFltLoad(
return Error;
}
#if 0
/**
* @name KmtFltCreateAndStartService
*
@ -143,7 +101,7 @@ cleanup:
assert(Error);
return Error;
}
#endif
/**
* @name KmtFltConnect
@ -163,7 +121,7 @@ KmtFltConnect(
_Out_ HANDLE *hPort)
{
HRESULT hResult;
DWORD Error = ERROR_SUCCESS;
DWORD Error;
assert(ServiceName);
assert(hPort);
@ -191,7 +149,7 @@ KmtFltConnect(
*/
DWORD
KmtFltDisconnect(
_Out_ HANDLE *hPort)
_In_ HANDLE hPort)
{
DWORD Error = ERROR_SUCCESS;
@ -388,41 +346,3 @@ KmtFltUnload(
return Error;
}
/**
* @name KmtFltDeleteService
*
* Delete the specified filter driver
*
* @param ServiceName
* If *ServiceHandle is NULL, name of the service to delete
* @param ServiceHandle
* Pointer to a variable containing the service handle.
* Will be set to NULL on success
*
* @return Win32 error code
*/
DWORD
KmtFltDeleteService(
_In_z_ PCWSTR ServiceName OPTIONAL,
_Inout_ SC_HANDLE *ServiceHandle)
{
return KmtDeleteService(ServiceName, ServiceHandle);
}
/**
* @name KmtFltCloseService
*
* Close the specified driver service handle
*
* @param ServiceHandle
* Pointer to a variable containing the service handle.
* Will be set to NULL on success
*
* @return Win32 error code
*/
DWORD KmtFltCloseService(
_Inout_ SC_HANDLE *ServiceHandle)
{
return KmtCloseService(ServiceHandle);
}

View file

@ -7,12 +7,28 @@
#include <kmt_test.h>
#define KMT_FLT_USER_MODE
#include "kmtest.h"
#include <kmt_public.h>
#include <assert.h>
#include <debug.h>
/*
* We need to call the internal function in the service.c file
*/
DWORD
KmtpCreateService(
IN PCWSTR ServiceName,
IN PCWSTR ServicePath,
IN PCWSTR DisplayName OPTIONAL,
IN DWORD ServiceType,
OUT SC_HANDLE *ServiceHandle);
DWORD EnablePrivilegeInCurrentProcess(
_In_z_ LPWSTR lpPrivName,
_In_ BOOL bEnable);
// move to a shared location
typedef struct _KMTFLT_MESSAGE_HEADER
{
@ -26,33 +42,30 @@ extern HANDLE KmtestHandle;
static WCHAR TestServiceName[MAX_PATH];
/**
* @name KmtFltLoadDriver
* @name KmtFltCreateService
*
* Load the specified filter driver
* This routine will create the service entry if it doesn't already exist
* Create the specified driver service and return a handle to it
*
* @param ServiceName
* Name of the driver service (Kmtest- prefix will be added automatically)
* @param RestartIfRunning
* TRUE to stop and restart the service if it is already running
* @param ConnectComms
* TRUE to create a comms connection to the specified filter
* @param hPort
* Handle to the filter's comms port
* Name of the service to create
* @param ServicePath
* File name of the driver, relative to the current directory
* @param DisplayName
* Service display name
* @param ServiceHandle
* Pointer to a variable to receive the handle to the service
*
* @return Win32 error code
*/
DWORD
KmtFltLoadDriver(
KmtFltCreateService(
_In_z_ PCWSTR ServiceName,
_In_ BOOLEAN RestartIfRunning,
_In_ BOOLEAN ConnectComms,
_Out_ HANDLE *hPort)
_In_z_ PCWSTR DisplayName,
_Out_ SC_HANDLE *ServiceHandle)
{
DWORD Error = ERROR_SUCCESS;
WCHAR ServicePath[MAX_PATH];
SC_HANDLE TestServiceHandle;
StringCbCopy(ServicePath, sizeof ServicePath, ServiceName);
StringCbCat(ServicePath, sizeof ServicePath, L"_drv.sys");
@ -60,11 +73,81 @@ KmtFltLoadDriver(
StringCbCopy(TestServiceName, sizeof TestServiceName, L"Kmtest-");
StringCbCat(TestServiceName, sizeof TestServiceName, ServiceName);
Error = KmtFltCreateAndStartService(TestServiceName, ServicePath, NULL, &TestServiceHandle, TRUE);
return KmtpCreateService(TestServiceName,
ServicePath,
DisplayName,
SERVICE_FILE_SYSTEM_DRIVER,
ServiceHandle);
}
if (Error == ERROR_SUCCESS && ConnectComms)
/**
* @name KmtFltDeleteService
*
* Delete the specified filter driver
*
* @param ServiceName
* If *ServiceHandle is NULL, name of the service to delete
* @param ServiceHandle
* Pointer to a variable containing the service handle.
* Will be set to NULL on success
*
* @return Win32 error code
*/
DWORD
KmtFltDeleteService(
_In_opt_z_ PCWSTR ServiceName,
_Inout_ SC_HANDLE *ServiceHandle)
{
return KmtDeleteService(ServiceName, ServiceHandle);
}
/**
* @name KmtFltLoadDriver
*
* Delete the specified filter driver
*
* @return Win32 error code
*/
DWORD
KmtFltLoadDriver(
_In_ BOOLEAN EnableDriverLoadPrivlege,
_In_ BOOLEAN RestartIfRunning,
_In_ BOOLEAN ConnectComms,
_Out_ HANDLE *hPort
)
{
DWORD Error;
if (EnableDriverLoadPrivlege)
{
Error = KmtFltConnect(ServiceName, hPort);
Error = EnablePrivilegeInCurrentProcess(SE_LOAD_DRIVER_NAME , TRUE);
if (Error)
{
return Error;
}
}
Error = KmtFltLoad(TestServiceName);
if ((Error == ERROR_SERVICE_ALREADY_RUNNING) && RestartIfRunning)
{
Error = KmtFltUnload(TestServiceName);
if (Error)
{
// TODO
__debugbreak();
}
Error = KmtFltLoad(TestServiceName);
}
if (Error)
{
return Error;
}
if (ConnectComms)
{
Error = KmtFltConnectComms(hPort);
}
return Error;
@ -77,7 +160,7 @@ KmtFltLoadDriver(
*
* @param hPort
* Handle to the filter's comms port
* @param ConnectComms
* @param DisonnectComms
* TRUE to disconnect the comms connection before unloading
*
* @return Win32 error code
@ -110,6 +193,57 @@ KmtFltUnloadDriver(
return Error;
}
/**
* @name KmtFltConnectComms
*
* Create a comms connection to the specified filter
*
* @param hPort
* Handle to the filter's comms port
*
* @return Win32 error code
*/
DWORD
KmtFltConnectComms(
_Out_ HANDLE *hPort)
{
return KmtFltConnect(TestServiceName, hPort);
}
/**
* @name KmtFltDisconnectComms
*
* Disconenct from the comms port
*
* @param hPort
* Handle to the filter's comms port
*
* @return Win32 error code
*/
DWORD
KmtFltDisconnectComms(
_In_ HANDLE hPort)
{
return KmtFltDisconnect(hPort);
}
/**
* @name KmtFltCloseService
*
* Close the specified driver service handle
*
* @param ServiceHandle
* Pointer to a variable containing the service handle.
* Will be set to NULL on success
*
* @return Win32 error code
*/
DWORD KmtFltCloseService(
_Inout_ SC_HANDLE *ServiceHandle)
{
return KmtCloseService(ServiceHandle);
}
/**
* @name KmtFltRunKernelTest
@ -141,7 +275,7 @@ KmtFltRunKernelTest(
* @param Message
* The message to send to the filter
*
* @return Win32 error code as returned by DeviceIoControl
* @return Win32 error code
*/
DWORD
KmtFltSendToDriver(
@ -165,7 +299,7 @@ KmtFltSendToDriver(
* @param String
* An ANSI string to send to the filter
*
* @return Win32 error code as returned by DeviceIoControl
* @return Win32 error code
*/
DWORD
KmtFltSendStringToDriver(
@ -190,7 +324,7 @@ KmtFltSendStringToDriver(
* @param String
* An wide string to send to the filter
*
* @return Win32 error code as returned by DeviceIoControl
* @return Win32 error code
*/
DWORD
KmtFltSendWStringToDriver(
@ -213,7 +347,7 @@ KmtFltSendWStringToDriver(
* @param Value
* An 32bit valueng to send to the filter
*
* @return Win32 error code as returned by DeviceIoControl
* @return Win32 error code
*/
DWORD
KmtFltSendUlongToDriver(
@ -244,7 +378,7 @@ KmtFltSendUlongToDriver(
* @param BytesReturned
* Number of bytes written in the reply buffer
*
* @return Win32 error code as returned by DeviceIoControl
* @return Win32 error code
*/
DWORD
KmtFltSendBufferToDriver(
@ -299,3 +433,154 @@ KmtFltSendBufferToDriver(
return Error;
}
/**
* @name KmtFltAddAltitude
*
* Sets up the mini-filter altitude data in the registry
*
* @param hPort
* The altitude string to set
*
* @return Win32 error code
*/
DWORD
KmtFltAddAltitude(
_In_z_ LPWSTR Altitude)
{
WCHAR DefaultInstance[128];
WCHAR KeyPath[256];
HKEY hKey = NULL;
HKEY hSubKey = NULL;
DWORD Zero = 0;
LONG Error;
StringCbCopy(KeyPath, sizeof KeyPath, L"SYSTEM\\CurrentControlSet\\Services\\");
StringCbCat(KeyPath, sizeof KeyPath, TestServiceName);
StringCbCat(KeyPath, sizeof KeyPath, L"\\Instances\\");
Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
KeyPath,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
NULL,
&hKey,
NULL);
if (Error != ERROR_SUCCESS)
{
return Error;
}
StringCbCopy(DefaultInstance, sizeof DefaultInstance, TestServiceName);
StringCbCat(DefaultInstance, sizeof DefaultInstance, L" Instance");
Error = RegSetValueExW(hKey,
L"DefaultInstance",
0,
REG_SZ,
(LPBYTE)DefaultInstance,
(wcslen(DefaultInstance) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
{
goto Quit;
}
Error = RegCreateKeyW(hKey, DefaultInstance, &hSubKey);
if (Error != ERROR_SUCCESS)
{
goto Quit;
}
Error = RegSetValueExW(hSubKey,
L"Altitude",
0,
REG_SZ,
(LPBYTE)Altitude,
(wcslen(Altitude) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
{
goto Quit;
}
Error = RegSetValueExW(hSubKey,
L"Flags",
0,
REG_DWORD,
(LPBYTE)&Zero,
sizeof(DWORD));
Quit:
if (hSubKey)
{
RegCloseKey(hSubKey);
}
if (hKey)
{
RegCloseKey(hKey);
}
return Error;
}
/*
* Private functions, not meant for use in kmtests
*/
DWORD EnablePrivilege(
_In_ HANDLE hToken,
_In_z_ LPWSTR lpPrivName,
_In_ BOOL bEnable)
{
TOKEN_PRIVILEGES TokenPrivileges;
LUID luid;
BOOL bSuccess;
DWORD dwError = ERROR_SUCCESS;
/* Get the luid for this privilege */
if (!LookupPrivilegeValueW(NULL, lpPrivName, &luid))
return GetLastError();
/* Setup the struct with the priv info */
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = luid;
TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
/* Enable the privilege info in the token */
bSuccess = AdjustTokenPrivileges(hToken,
FALSE,
&TokenPrivileges,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL);
if (bSuccess == FALSE) dwError = GetLastError();
/* return status */
return dwError;
}
DWORD EnablePrivilegeInCurrentProcess(
_In_z_ LPWSTR lpPrivName,
_In_ BOOL bEnable)
{
HANDLE hToken;
BOOL bSuccess;
DWORD dwError = ERROR_SUCCESS;
/* Get a handle to our token */
bSuccess = OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken);
if (bSuccess == FALSE) return GetLastError();
/* Enable the privilege in the agent token */
dwError = EnablePrivilege(hToken, lpPrivName, bEnable);
/* We're done with this now */
CloseHandle(hToken);
/* return status */
return dwError;
}

View file

@ -60,16 +60,9 @@ KmtDeleteService(
DWORD KmtCloseService(
IN OUT SC_HANDLE *ServiceHandle);
/* FS Filter management functions */
DWORD
KmtFltCreateService(
_In_z_ PCWSTR ServiceName,
_In_z_ PCWSTR ServicePath,
_In_z_ PCWSTR DisplayName OPTIONAL,
_Out_ SC_HANDLE *ServiceHandle);
#ifdef KMT_FLT_USER_MODE
DWORD
KmtFltLoad(
@ -132,4 +125,6 @@ KmtFltDeleteService(
DWORD KmtFltCloseService(
_Inout_ SC_HANDLE *ServiceHandle);
#endif /* KMT_FILTER_DRIVER */
#endif /* !defined _KMTESTS_H_ */

View file

@ -11,6 +11,8 @@ KMT_TESTFUNC Test_CcCopyRead;
KMT_TESTFUNC Test_Example;
KMT_TESTFUNC Test_FileAttributes;
KMT_TESTFUNC Test_FindFile;
KMT_TESTFUNC Test_FltMgrLoad;
KMT_TESTFUNC Test_FltMgrReg;
KMT_TESTFUNC Test_HidPDescription;
KMT_TESTFUNC Test_IoCreateFile;
KMT_TESTFUNC Test_IoDeviceObject;
@ -37,6 +39,8 @@ const KMT_TEST TestList[] =
{ "-Example", Test_Example },
{ "FileAttributes", Test_FileAttributes },
{ "FindFile", Test_FindFile },
{ "FltMgrLoad", Test_FltMgrLoad },
{ "FltMgrReg", Test_FltMgrReg },
{ "HidPDescription", Test_HidPDescription },
{ "IoCreateFile", Test_IoCreateFile },
{ "IoDeviceObject", Test_IoDeviceObject },

View file

@ -2,7 +2,8 @@
* PROJECT: ReactOS kernel-mode tests - Filter Manager
* LICENSE: GPLv2+ - See COPYING in the top level directory
* PURPOSE: FS Mini-filter wrapper to host the filter manager tests
* PROGRAMMER: Ged Murphy <ged.murphy@reactos.org>
* PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
* Ged Murphy <ged.murphy@reactos.org>
*/
#include <ntifs.h>
@ -35,6 +36,7 @@ DRIVER_INITIALIZE DriverEntry;
/* Globals */
static PDRIVER_OBJECT TestDriverObject;
static PDEVICE_OBJECT KmtestDeviceObject;
static FILTER_DATA FilterData;
static PFLT_OPERATION_REGISTRATION Callbacks = NULL;
static PFLT_CONTEXT_REGISTRATION Contexts = NULL;
@ -133,6 +135,9 @@ DriverEntry(
PSECURITY_DESCRIPTOR SecurityDescriptor;
UNICODE_STRING DeviceName;
WCHAR DeviceNameBuffer[128] = L"\\Device\\Kmtest-";
UNICODE_STRING KmtestDeviceName;
PFILE_OBJECT KmtestFileObject;
PKMT_DEVICE_EXTENSION KmtestDeviceExtension;
PCWSTR DeviceNameSuffix;
INT Flags = 0;
PKPRCB Prcb;
@ -148,6 +153,32 @@ DriverEntry(
KmtIsMultiProcessorBuild = (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) == 0;
TestDriverObject = DriverObject;
/* get the Kmtest device, so that we get a ResultBuffer pointer */
RtlInitUnicodeString(&KmtestDeviceName, KMTEST_DEVICE_DRIVER_PATH);
Status = IoGetDeviceObjectPointer(&KmtestDeviceName, FILE_ALL_ACCESS, &KmtestFileObject, &KmtestDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Kmtest device object pointer\n");
goto cleanup;
}
Status = ObReferenceObjectByPointer(KmtestDeviceObject, FILE_ALL_ACCESS, NULL, KernelMode);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference Kmtest device object\n");
goto cleanup;
}
ObDereferenceObject(KmtestFileObject);
KmtestFileObject = NULL;
KmtestDeviceExtension = KmtestDeviceObject->DeviceExtension;
ResultBuffer = KmtestDeviceExtension->ResultBuffer;
DPRINT("KmtestDeviceObject: %p\n", (PVOID)KmtestDeviceObject);
DPRINT("KmtestDeviceExtension: %p\n", (PVOID)KmtestDeviceExtension);
DPRINT("Setting ResultBuffer: %p\n", (PVOID)ResultBuffer);
/* call TestEntry */
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
@ -243,6 +274,7 @@ FilterUnload(
{
PAGED_CODE();
UNREFERENCED_PARAMETER(Flags);
//__debugbreak();
DPRINT("DriverUnload\n");
@ -312,50 +344,54 @@ FilterInstanceSetup(
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
RtlInitUnicodeString(&VolumeName, NULL);
if (!(Flags & TESTENTRY_NO_INSTANCE_SETUP))
{
RtlInitUnicodeString(&VolumeName, NULL);
#if 0 // FltGetVolumeProperties is not yet implemented
/* Get the properties of this volume */
Status = FltGetVolumeProperties(Volume,
VolumeProperties,
sizeof(VolPropBuffer),
&LengthReturned);
if (NT_SUCCESS(Status))
{
FLT_ASSERT((VolumeProperties->SectorSize == 0) || (VolumeProperties->SectorSize >= MIN_SECTOR_SIZE));
SectorSize = max(VolumeProperties->SectorSize, MIN_SECTOR_SIZE);
ReportedSectorSize = VolumeProperties->SectorSize;
}
else
{
DPRINT1("Failed to get the volume properties : 0x%X", Status);
return Status;
}
#endif
/* Get the storage device object we want a name for */
Status = FltGetDiskDeviceObject(FltObjects->Volume, &DeviceObject);
if (NT_SUCCESS(Status))
{
/* Get the dos device name */
Status = IoVolumeDeviceToDosName(DeviceObject, &VolumeName);
Status = FltGetVolumeProperties(Volume,
VolumeProperties,
sizeof(VolPropBuffer),
&LengthReturned);
if (NT_SUCCESS(Status))
{
DPRINT("VolumeDeviceType %lu, VolumeFilesystemType %lu, Real SectSize=0x%04x, Reported SectSize=0x%04x, Name=\"%wZ\"",
VolumeDeviceType,
VolumeFilesystemType,
SectorSize,
ReportedSectorSize,
&VolumeName);
FLT_ASSERT((VolumeProperties->SectorSize == 0) || (VolumeProperties->SectorSize >= MIN_SECTOR_SIZE));
SectorSize = max(VolumeProperties->SectorSize, MIN_SECTOR_SIZE);
ReportedSectorSize = VolumeProperties->SectorSize;
}
else
{
DPRINT1("Failed to get the volume properties : 0x%X", Status);
return Status;
}
#endif
/* Get the storage device object we want a name for */
Status = FltGetDiskDeviceObject(FltObjects->Volume, &DeviceObject);
if (NT_SUCCESS(Status))
{
/* Get the dos device name */
Status = IoVolumeDeviceToDosName(DeviceObject, &VolumeName);
if (NT_SUCCESS(Status))
{
DPRINT("VolumeDeviceType %lu, VolumeFilesystemType %lu, Real SectSize=0x%04x, Reported SectSize=0x%04x, Name=\"%wZ\"",
VolumeDeviceType,
VolumeFilesystemType,
SectorSize,
ReportedSectorSize,
&VolumeName);
Status = TestInstanceSetup(FltObjects,
Flags,
VolumeDeviceType,
VolumeFilesystemType,
&VolumeName,
SectorSize,
ReportedSectorSize);
Status = TestInstanceSetup(FltObjects,
Flags,
VolumeDeviceType,
VolumeFilesystemType,
&VolumeName,
SectorSize,
ReportedSectorSize);
/* The buffer was allocated by the IoMgr */
ExFreePool(VolumeName.Buffer);
/* The buffer was allocated by the IoMgr */
ExFreePool(VolumeName.Buffer);
}
}
}
@ -384,7 +420,10 @@ FilterQueryTeardown(
{
PAGED_CODE();
TestQueryTeardown(FltObjects, Flags);
if (!(Flags & TESTENTRY_NO_QUERY_TEARDOWN))
{
TestQueryTeardown(FltObjects, Flags);
}
/* We always allow a volume to detach */
return STATUS_SUCCESS;