mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
[FLTMGR]
- 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:
parent
fb1948e7d4
commit
7a5211283a
3 changed files with 376 additions and 4 deletions
373
reactos/drivers/filters/fltmgr/Messaging.c
Normal file
373
reactos/drivers/filters/fltmgr/Messaging.c
Normal 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 ******************************************************/
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
@ stdcall FltRegisterFilter(ptr ptr ptr)
|
||||
@ stdcall FltUnregisterFilter(ptr)
|
||||
@ stdcall FltCloseCommunicationPort(ptr)
|
||||
|
||||
|
|
Loading…
Reference in a new issue