mirror of
https://github.com/reactos/reactos.git
synced 2024-07-03 03:04:22 +00:00
374 lines
11 KiB
C
374 lines
11 KiB
C
![]() |
/*
|
||
|
* 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 ******************************************************/
|
||
|
|