mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[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:
parent
f884d29c90
commit
dfb776380d
24 changed files with 1739 additions and 230 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
);
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -29,8 +29,8 @@ FltBuildDefaultSecurityDescriptor(
|
|||
_In_ ACCESS_MASK DesiredAccess
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(SecurityDescriptor);
|
||||
UNREFERENCED_PARAMETER(DesiredAccess);
|
||||
*SecurityDescriptor = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
142
drivers/filters/fltmgr/Registry.c
Normal file
142
drivers/filters/fltmgr/Registry.c
Normal 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;
|
||||
}
|
20
drivers/filters/fltmgr/Registry.h
Normal file
20
drivers/filters/fltmgr/Registry.h
Normal 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
|
||||
);
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
add_subdirectory(fltmgr_load)
|
||||
add_subdirectory(fltmgr_create)
|
||||
add_subdirectory(fltmgr_register)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
28
modules/rostests/kmtests/fltmgr/fltmgr_load/fltmgr_user.c
Normal file
28
modules/rostests/kmtests/fltmgr/fltmgr_load/fltmgr_user.c
Normal 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);
|
||||
}
|
|
@ -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)
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -44,6 +44,7 @@
|
|||
#include <strsafe.h>
|
||||
#include <fltuser.h>
|
||||
|
||||
|
||||
#ifdef KMT_EMULATE_KERNEL
|
||||
#define ok_irql(i)
|
||||
#define KIRQL int
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue