- Implement FltCreateCommunicationPort, FltCloseCommunicationPort, FltCloseClientPort, and stub FltSendMessage
- Add two new object types for the server port and client ports
- Implement object type callbacks for closing and deleting these new ports
- Create the comms object and create the symbolic link (FltMgrMsg) to allow usermode to open a handle to the comms layer (aka FilterConnectCommunicationPort)
- Although untested, the comms layer objects should be mostly setup, and we should be able to open a connection from usermode.

svn path=/trunk/; revision=74589
This commit is contained in:
Ged Murphy 2017-05-19 09:37:38 +00:00
parent fb1948e7d4
commit 7a5211283a
3 changed files with 376 additions and 4 deletions

View file

@ -0,0 +1,373 @@
/*
* PROJECT: Filesystem Filter Manager
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/filters/fltmgr/Messaging.c
* PURPOSE: Contains the routines to handle the comms layer
* PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "fltmgr.h"
#include "fltmgrint.h"
#define NDEBUG
#include <debug.h>
/* DATA *********************************************************************/
UNICODE_STRING CommsDeviceName = RTL_CONSTANT_STRING(L"\\FileSystem\\Filters\\FltMgrMsg");
PDEVICE_OBJECT CommsDeviceObject;
POBJECT_TYPE ServerPortObjectType;
POBJECT_TYPE ClientPortObjectType;
static
BOOLEAN
FltpDisconnectPort(
_In_ PFLT_PORT_OBJECT PortObject
);
/* EXPORTED FUNCTIONS ******************************************************/
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
FLTAPI
FltCreateCommunicationPort(_In_ PFLT_FILTER Filter,
_Outptr_ PFLT_PORT *ServerPort,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PVOID ServerPortCookie,
_In_ PFLT_CONNECT_NOTIFY ConnectNotifyCallback,
_In_ PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,
_In_opt_ PFLT_MESSAGE_NOTIFY MessageNotifyCallback,
_In_ LONG MaxConnections)
{
PFLT_SERVER_PORT_OBJECT PortObject;
NTSTATUS Status;
/* The caller must allow at least one connection */
if (MaxConnections == 0)
{
return STATUS_INVALID_PARAMETER;
}
/* The request must be for a kernel handle */
if (!(ObjectAttributes->Attributes & OBJ_KERNEL_HANDLE))
{
return STATUS_INVALID_PARAMETER;
}
/*
* Get rundown protection on the target to stop the owner
* from unloading whilst this port object is open. It gets
* removed in the FltpServerPortClose callback
*/
Status = FltObjectReference(Filter);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Create our new server port object */
Status = ObCreateObject(0,
ServerPortObjectType,
ObjectAttributes,
KernelMode,
NULL,
sizeof(FLT_SERVER_PORT_OBJECT),
0,
0,
(PVOID *)&PortObject);
if (NT_SUCCESS(Status))
{
/* Zero out the struct */
RtlZeroMemory(PortObject, sizeof(FLT_SERVER_PORT_OBJECT));
/* Increment the ref count on the target filter */
FltpObjectPointerReference((PFLT_OBJECT)Filter);
/* Setup the filter port object */
PortObject->Filter = Filter;
PortObject->ConnectNotify = ConnectNotifyCallback;
PortObject->DisconnectNotify = DisconnectNotifyCallback;
PortObject->MessageNotify = MessageNotifyCallback;
PortObject->Cookie = ServerPortCookie;
PortObject->MaxConnections = MaxConnections;
/* Insert the object */
Status = ObInsertObject(PortObject,
NULL,
STANDARD_RIGHTS_ALL | FILE_READ_DATA,
0,
NULL,
(PHANDLE)ServerPort);
if (NT_SUCCESS(Status))
{
/* Lock the connection list */
ExAcquireFastMutex(&Filter->ConnectionList.mLock);
/* Add the new port object to the connection list and increment the count */
InsertTailList(&Filter->ConnectionList.mList, &PortObject->FilterLink);
Filter->ConnectionList.mCount++;
/* Unlock the connection list*/
ExReleaseFastMutex(&Filter->ConnectionList.mLock);
}
}
if (!NT_SUCCESS(Status))
{
/* Allow the filter to be cleaned up */
FltObjectDereference(Filter);
}
return STATUS_NOT_IMPLEMENTED;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
FLTAPI
FltCloseCommunicationPort(_In_ PFLT_PORT ServerPort)
{
/* Just close the handle to initiate the cleanup callbacks */
ZwClose(ServerPort);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
FLTAPI
FltCloseClientPort(_In_ PFLT_FILTER Filter,
_Inout_ PFLT_PORT *ClientPort)
{
PFLT_PORT Port;
/* Protect against the handle being used whilst we're closing it */
FltAcquirePushLockShared(&Filter->PortLock);
/* Store the port handle while we have the lock held */
Port = *ClientPort;
if (*ClientPort)
{
/* Set the hadle to null */
*ClientPort = NULL;
}
/* Unlock the port */
FltReleasePushLock(&Filter->PortLock);
if (Port)
{
/* Close the safe handle */
ZwClose(Port);
}
}
_Must_inspect_result_
_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
FLTAPI
FltSendMessage(_In_ PFLT_FILTER Filter,
_In_ PFLT_PORT *ClientPort,
_In_reads_bytes_(SenderBufferLength) PVOID SenderBuffer,
_In_ ULONG SenderBufferLength,
_Out_writes_bytes_opt_(*ReplyLength) PVOID ReplyBuffer,
_Inout_opt_ PULONG ReplyLength,
_In_opt_ PLARGE_INTEGER Timeout)
{
UNREFERENCED_PARAMETER(Filter);
UNREFERENCED_PARAMETER(ClientPort);
UNREFERENCED_PARAMETER(SenderBuffer);
UNREFERENCED_PARAMETER(SenderBufferLength);
UNREFERENCED_PARAMETER(ReplyBuffer);
UNREFERENCED_PARAMETER(ReplyLength);
UNREFERENCED_PARAMETER(Timeout);
return STATUS_NOT_IMPLEMENTED;
}
/* INTERNAL FUNCTIONS ******************************************************/
VOID
NTAPI
FltpServerPortClose(_In_opt_ PEPROCESS Process,
_In_ PVOID Object,
_In_ ACCESS_MASK GrantedAccess,
_In_ ULONG ProcessHandleCount,
_In_ ULONG SystemHandleCount)
{
PFLT_SERVER_PORT_OBJECT PortObject;
PFAST_MUTEX Lock;
/* Cast the object to a server port object */
PortObject = (PFLT_SERVER_PORT_OBJECT)Object;
/* Lock the connection list */
Lock = &PortObject->Filter->ConnectionList.mLock;
ExAcquireFastMutex(Lock);
/* Remove the server port object from the list */
RemoveEntryList(&PortObject->FilterLink);
/* Unlock the connection list */
ExReleaseFastMutex(Lock);
/* Remove the rundown protection we added to stop the owner from tearing us down */
FltObjectDereference(PortObject->Filter);
}
VOID
NTAPI
FltpServerPortDelete(PVOID Object)
{
/* Decrement the filter count we added in the create routine */
PFLT_SERVER_PORT_OBJECT PortObject = (PFLT_SERVER_PORT_OBJECT)Object;
FltpObjectPointerDereference((PFLT_OBJECT)PortObject->Filter);
}
VOID
NTAPI
FltpClientPortClose(_In_opt_ PEPROCESS Process,
_In_ PVOID Object,
_In_ ACCESS_MASK GrantedAccess,
_In_ ULONG ProcessHandleCount,
_In_ ULONG SystemHandleCount)
{
PFLT_PORT_OBJECT PortObject = (PFLT_PORT_OBJECT)Object;
if (FltpDisconnectPort(PortObject))
{
InterlockedDecrement(&PortObject->ServerPort->NumberOfConnections);
}
}
BOOLEAN
FltpDisconnectPort(_In_ PFLT_PORT_OBJECT PortObject)
{
BOOLEAN Disconnected = FALSE;
/* Lock the port object while we disconnect it */
ExAcquireFastMutex(&PortObject->Lock);
/* Make sure we have a valid connection */
if (PortObject->Disconnected == FALSE)
{
/* Let any waiters know we're dusconnecing */
KeSetEvent(&PortObject->DisconnectEvent, 0, 0);
// cleanup everything in the message queue (PortObject->MsgQ.Csq)
/* Set the disconnected state to true */
PortObject->Disconnected = TRUE;
Disconnected = TRUE;
}
/* Unlock and exit*/
ExReleaseFastMutex(&PortObject->Lock);
return Disconnected;
}
VOID
NTAPI
FltpClientPortDelete(PVOID Object)
{
PFLT_PORT_OBJECT PortObject = (PFLT_PORT_OBJECT)Object;
ObfDereferenceObject(PortObject->ServerPort);
}
NTSTATUS
FltpSetupCommunicationObjects(_In_ PDRIVER_OBJECT DriverObject)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING SymLinkName;
UNICODE_STRING Name;
NTSTATUS Status;
GENERIC_MAPPING Mapping =
{
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
FLT_PORT_ALL_ACCESS
};
/* Create the server comms object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(OBJECT_TYPE_INITIALIZER));
RtlInitUnicodeString(&Name, L"FilterConnectionPort");
ObjectTypeInitializer.Length = sizeof(OBJECT_TYPE_INITIALIZER);
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
ObjectTypeInitializer.GenericMapping = Mapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FLT_SERVER_PORT_OBJECT);
ObjectTypeInitializer.ValidAccessMask = GENERIC_ALL;
ObjectTypeInitializer.CloseProcedure = FltpServerPortClose;
ObjectTypeInitializer.DeleteProcedure = FltpServerPortDelete;
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ServerPortObjectType);
if (!NT_SUCCESS(Status)) return Status;
/* Create the client comms object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(OBJECT_TYPE_INITIALIZER));
RtlInitUnicodeString(&Name, L"FilterCommunicationPort");
ObjectTypeInitializer.Length = sizeof(OBJECT_TYPE_INITIALIZER);
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
ObjectTypeInitializer.GenericMapping = Mapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FLT_PORT_OBJECT);
ObjectTypeInitializer.ValidAccessMask = GENERIC_ALL;
ObjectTypeInitializer.CloseProcedure = FltpClientPortClose;
ObjectTypeInitializer.DeleteProcedure = FltpClientPortDelete;
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ClientPortObjectType);
if (!NT_SUCCESS(Status))
{
goto Quit;
}
/* Create the device object */
Status = IoCreateDevice(DriverObject,
0,
&CommsDeviceName,
FILE_DEVICE_WPD,
0,
0,
&CommsDeviceObject);
if (NT_SUCCESS(Status))
{
/* Setup a symbolic link for the device */
RtlInitUnicodeString(&SymLinkName, L"\\DosDevices\\FltMgrMsg");
Status = IoCreateSymbolicLink(&SymLinkName, &CommsDeviceName);
}
Quit:
if (!NT_SUCCESS(Status))
{
/* Something went wrong, undo */
if (CommsDeviceObject)
{
IoDeleteDevice(CommsDeviceObject);
CommsDeviceObject = NULL;
}
if (ClientPortObjectType)
{
ObMakeTemporaryObject(ClientPortObjectType);
ObfDereferenceObject(ClientPortObjectType);
ClientPortObjectType = NULL;
}
if (ServerPortObjectType)
{
ObMakeTemporaryObject(ServerPortObjectType);
ObfDereferenceObject(ServerPortObjectType);
ServerPortObjectType = NULL;
}
}
return Status;
}
/* PRIVATE FUNCTIONS ******************************************************/

View file

@ -1,11 +1,9 @@
#ifndef _FLTMGR_H
#define _FLTMGR_H
// Hack - our SDK reports NTDDI_VERSION as 0x05020100 (from _WIN32_WINNT 0x502)
// which doesn't pass the FLT_MGR_BASELINE check in fltkernel.h
#define NTDDI_VERSION NTDDI_WS03SP1
#include <ntifs.h>
#include <ndk/obfuncs.h>
#include <ndk/exfuncs.h>
#include <fltkernel.h>
#include <pseh/pseh2.h>

View file

@ -1,4 +1,5 @@
@ stdcall FltRegisterFilter(ptr ptr ptr)
@ stdcall FltUnregisterFilter(ptr)
@ stdcall FltCloseCommunicationPort(ptr)