2 * PROJECT: Filesystem Filter Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filters/fltmgr/Messaging.c
5 * PURPOSE: Contains the routines to handle the comms layer
6 * PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org)
9 /* INCLUDES ******************************************************************/
12 #include "fltmgrint.h"
13 #include <fltmgr_shared.h>
19 /* DATA *********************************************************************/
21 UNICODE_STRING CommsDeviceName
= RTL_CONSTANT_STRING(L
"\\FileSystem\\Filters\\FltMgrMsg");
22 PDEVICE_OBJECT CommsDeviceObject
;
24 POBJECT_TYPE ServerPortObjectType
;
25 POBJECT_TYPE ClientPortObjectType
;
30 _In_ PFLT_PORT_OBJECT PortObject
36 _In_ PFILE_OBJECT FileObject
,
43 _In_ PFILE_OBJECT FileObject
,
49 InitializeMessageWaiterQueue(
50 _Inout_ PFLT_MESSAGE_WAITER_QUEUE MsgWaiterQueue
56 _In_ PFLT_PORT_OBJECT PortObject
61 /* EXPORTED FUNCTIONS ******************************************************/
64 _IRQL_requires_max_(PASSIVE_LEVEL
)
67 FltCreateCommunicationPort(_In_ PFLT_FILTER Filter
,
68 _Outptr_ PFLT_PORT
*ServerPort
,
69 _In_ POBJECT_ATTRIBUTES ObjectAttributes
,
70 _In_opt_ PVOID ServerPortCookie
,
71 _In_ PFLT_CONNECT_NOTIFY ConnectNotifyCallback
,
72 _In_ PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback
,
73 _In_opt_ PFLT_MESSAGE_NOTIFY MessageNotifyCallback
,
74 _In_ LONG MaxConnections
)
76 PFLT_SERVER_PORT_OBJECT PortObject
;
79 /* The caller must allow at least one connection */
80 if (MaxConnections
== 0)
82 return STATUS_INVALID_PARAMETER
;
85 /* The request must be for a kernel handle */
86 if (!(ObjectAttributes
->Attributes
& OBJ_KERNEL_HANDLE
))
88 return STATUS_INVALID_PARAMETER
;
92 * Get rundown protection on the target to stop the owner
93 * from unloading whilst this port object is open. It gets
94 * removed in the FltpServerPortClose callback
96 Status
= FltObjectReference(Filter
);
97 if (!NT_SUCCESS(Status
))
102 /* Create the server port object for this filter */
103 Status
= ObCreateObject(KernelMode
,
104 ServerPortObjectType
,
108 sizeof(FLT_SERVER_PORT_OBJECT
),
111 (PVOID
*)&PortObject
);
112 if (NT_SUCCESS(Status
))
114 /* Zero out the struct */
115 RtlZeroMemory(PortObject
, sizeof(FLT_SERVER_PORT_OBJECT
));
117 /* Increment the ref count on the target filter */
118 FltpObjectPointerReference((PFLT_OBJECT
)Filter
);
120 /* Setup the filter port object */
121 PortObject
->Filter
= Filter
;
122 PortObject
->ConnectNotify
= ConnectNotifyCallback
;
123 PortObject
->DisconnectNotify
= DisconnectNotifyCallback
;
124 PortObject
->MessageNotify
= MessageNotifyCallback
;
125 PortObject
->Cookie
= ServerPortCookie
;
126 PortObject
->MaxConnections
= MaxConnections
;
128 /* Insert the object */
129 Status
= ObInsertObject(PortObject
,
131 STANDARD_RIGHTS_ALL
| FILE_READ_DATA
,
134 (PHANDLE
)ServerPort
);
135 if (NT_SUCCESS(Status
))
137 /* Lock the connection list */
138 ExAcquireFastMutex(&Filter
->ConnectionList
.mLock
);
140 /* Add the new port object to the connection list and increment the count */
141 InsertTailList(&Filter
->ConnectionList
.mList
, &PortObject
->FilterLink
);
142 Filter
->ConnectionList
.mCount
++;
144 /* Unlock the connection list*/
145 ExReleaseFastMutex(&Filter
->ConnectionList
.mLock
);
149 if (!NT_SUCCESS(Status
))
151 /* Allow the filter to be cleaned up */
152 FltObjectDereference(Filter
);
158 _IRQL_requires_max_(PASSIVE_LEVEL
)
161 FltCloseCommunicationPort(_In_ PFLT_PORT ServerPort
)
163 /* Just close the handle to initiate the cleanup callbacks */
167 _IRQL_requires_max_(PASSIVE_LEVEL
)
170 FltCloseClientPort(_In_ PFLT_FILTER Filter
,
171 _Inout_ PFLT_PORT
*ClientPort
)
175 /* Protect against the handle being used whilst we're closing it */
176 FltAcquirePushLockShared(&Filter
->PortLock
);
178 /* Store the port handle while we have the lock held */
183 /* Set the hadle to null */
187 /* Unlock the port */
188 FltReleasePushLock(&Filter
->PortLock
);
192 /* Close the safe handle */
197 _Must_inspect_result_
198 _IRQL_requires_max_(APC_LEVEL
)
201 FltSendMessage(_In_ PFLT_FILTER Filter
,
202 _In_ PFLT_PORT
*ClientPort
,
203 _In_reads_bytes_(SenderBufferLength
) PVOID SenderBuffer
,
204 _In_ ULONG SenderBufferLength
,
205 _Out_writes_bytes_opt_(*ReplyLength
) PVOID ReplyBuffer
,
206 _Inout_opt_ PULONG ReplyLength
,
207 _In_opt_ PLARGE_INTEGER Timeout
)
209 UNREFERENCED_PARAMETER(Filter
);
210 UNREFERENCED_PARAMETER(ClientPort
);
211 UNREFERENCED_PARAMETER(SenderBuffer
);
212 UNREFERENCED_PARAMETER(SenderBufferLength
);
213 UNREFERENCED_PARAMETER(ReplyBuffer
);
214 UNREFERENCED_PARAMETER(ReplyLength
);
215 UNREFERENCED_PARAMETER(Timeout
);
216 return STATUS_NOT_IMPLEMENTED
;
219 /* INTERNAL FUNCTIONS ******************************************************/
223 FltpMsgCreate(_In_ PDEVICE_OBJECT DeviceObject
,
226 PIO_STACK_LOCATION StackPtr
;
229 /* Get the stack location */
230 StackPtr
= IoGetCurrentIrpStackLocation(Irp
);
232 FLT_ASSERT(StackPtr
->MajorFunction
== IRP_MJ_CREATE
);
234 /* Check if this is a caller wanting to connect */
235 if (StackPtr
->MajorFunction
== IRP_MJ_CREATE
)
237 /* Create the client port for this connection and exit */
238 Status
= CreateClientPort(StackPtr
->FileObject
, Irp
);
242 Status
= STATUS_INVALID_PARAMETER
;
245 if (Status
!= STATUS_PENDING
)
247 Irp
->IoStatus
.Status
= Status
;
248 Irp
->IoStatus
.Information
= 0;
249 IoCompleteRequest(Irp
, 0);
256 FltpMsgDispatch(_In_ PDEVICE_OBJECT DeviceObject
,
259 PIO_STACK_LOCATION StackPtr
;
262 /* Get the stack location */
263 StackPtr
= IoGetCurrentIrpStackLocation(Irp
);
265 /* Check if this is a caller wanting to connect */
266 if (StackPtr
->MajorFunction
== IRP_MJ_CLOSE
)
268 /* Create the client port for this connection and exit */
269 Status
= CloseClientPort(StackPtr
->FileObject
, Irp
);
273 // We don't support anything else yet
274 Status
= STATUS_NOT_IMPLEMENTED
;
277 if (Status
!= STATUS_PENDING
)
279 Irp
->IoStatus
.Status
= Status
;
280 Irp
->IoStatus
.Information
= 0;
281 IoCompleteRequest(Irp
, 0);
289 FltpServerPortClose(_In_opt_ PEPROCESS Process
,
291 _In_ ACCESS_MASK GrantedAccess
,
292 _In_ ULONG ProcessHandleCount
,
293 _In_ ULONG SystemHandleCount
)
295 PFLT_SERVER_PORT_OBJECT PortObject
;
298 /* Cast the object to a server port object */
299 PortObject
= (PFLT_SERVER_PORT_OBJECT
)Object
;
301 /* Lock the connection list */
302 Lock
= &PortObject
->Filter
->ConnectionList
.mLock
;
303 ExAcquireFastMutex(Lock
);
305 /* Remove the server port object from the list */
306 RemoveEntryList(&PortObject
->FilterLink
);
308 /* Unlock the connection list */
309 ExReleaseFastMutex(Lock
);
311 /* Remove the rundown protection we added to stop the owner from tearing us down */
312 FltObjectDereference(PortObject
->Filter
);
317 FltpServerPortDelete(PVOID Object
)
319 /* Decrement the filter count we added in the create routine */
320 PFLT_SERVER_PORT_OBJECT PortObject
= (PFLT_SERVER_PORT_OBJECT
)Object
;
321 FltpObjectPointerDereference((PFLT_OBJECT
)PortObject
->Filter
);
327 FltpClientPortClose(_In_opt_ PEPROCESS Process
,
329 _In_ ACCESS_MASK GrantedAccess
,
330 _In_ ULONG ProcessHandleCount
,
331 _In_ ULONG SystemHandleCount
)
333 PFLT_PORT_OBJECT PortObject
= (PFLT_PORT_OBJECT
)Object
;
335 if (FltpDisconnectPort(PortObject
))
337 InterlockedDecrement(&PortObject
->ServerPort
->NumberOfConnections
);
342 FltpDisconnectPort(_In_ PFLT_PORT_OBJECT PortObject
)
344 BOOLEAN Disconnected
= FALSE
;
346 /* Lock the port object while we disconnect it */
347 ExAcquireFastMutex(&PortObject
->Lock
);
349 /* Make sure we have a valid connection */
350 if (PortObject
->Disconnected
== FALSE
)
352 /* Let any waiters know we're dusconnecing */
353 KeSetEvent(&PortObject
->DisconnectEvent
, 0, 0);
355 // cleanup everything in the message queue (PortObject->MsgQ.Csq)
357 /* Set the disconnected state to true */
358 PortObject
->Disconnected
= TRUE
;
363 ExReleaseFastMutex(&PortObject
->Lock
);
369 FltpClientPortDelete(PVOID Object
)
371 PFLT_PORT_OBJECT PortObject
= (PFLT_PORT_OBJECT
)Object
;
372 ObfDereferenceObject(PortObject
->ServerPort
);
377 FltpSetupCommunicationObjects(_In_ PDRIVER_OBJECT DriverObject
)
379 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
380 UNICODE_STRING SymLinkName
;
384 GENERIC_MAPPING Mapping
=
386 STANDARD_RIGHTS_READ
,
387 STANDARD_RIGHTS_WRITE
,
388 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
392 /* Create the server comms object type */
393 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(OBJECT_TYPE_INITIALIZER
));
394 RtlInitUnicodeString(&Name
, L
"FilterConnectionPort");
395 ObjectTypeInitializer
.Length
= sizeof(OBJECT_TYPE_INITIALIZER
);
396 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
397 ObjectTypeInitializer
.GenericMapping
= Mapping
;
398 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
399 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FLT_SERVER_PORT_OBJECT
);
400 ObjectTypeInitializer
.ValidAccessMask
= GENERIC_ALL
;
401 ObjectTypeInitializer
.CloseProcedure
= FltpServerPortClose
;
402 ObjectTypeInitializer
.DeleteProcedure
= FltpServerPortDelete
;
403 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ServerPortObjectType
);
404 if (!NT_SUCCESS(Status
)) return Status
;
406 /* Create the client comms object type */
407 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(OBJECT_TYPE_INITIALIZER
));
408 RtlInitUnicodeString(&Name
, L
"FilterCommunicationPort");
409 ObjectTypeInitializer
.Length
= sizeof(OBJECT_TYPE_INITIALIZER
);
410 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
411 ObjectTypeInitializer
.GenericMapping
= Mapping
;
412 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
413 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(FLT_PORT_OBJECT
);
414 ObjectTypeInitializer
.ValidAccessMask
= GENERIC_ALL
;
415 ObjectTypeInitializer
.CloseProcedure
= FltpClientPortClose
;
416 ObjectTypeInitializer
.DeleteProcedure
= FltpClientPortDelete
;
417 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ClientPortObjectType
);
418 if (!NT_SUCCESS(Status
))
423 /* Create the device object */
424 Status
= IoCreateDevice(DriverObject
,
431 if (NT_SUCCESS(Status
))
433 /* Setup a symbolic link for the device */
434 RtlInitUnicodeString(&SymLinkName
, L
"\\DosDevices\\FltMgrMsg");
435 Status
= IoCreateSymbolicLink(&SymLinkName
, &CommsDeviceName
);
439 if (!NT_SUCCESS(Status
))
441 /* Something went wrong, undo */
442 if (CommsDeviceObject
)
444 IoDeleteDevice(CommsDeviceObject
);
445 CommsDeviceObject
= NULL
;
447 if (ClientPortObjectType
)
449 ObMakeTemporaryObject(ClientPortObjectType
);
450 ObfDereferenceObject(ClientPortObjectType
);
451 ClientPortObjectType
= NULL
;
454 if (ServerPortObjectType
)
456 ObMakeTemporaryObject(ServerPortObjectType
);
457 ObfDereferenceObject(ServerPortObjectType
);
458 ServerPortObjectType
= NULL
;
465 /* CSQ IRP CALLBACKS *******************************************************/
470 FltpAddMessageWaiter(_In_ PIO_CSQ Csq
,
472 _In_ PVOID InsertContext
)
474 PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue
;
476 /* Get the start of the waiter queue struct */
477 MessageWaiterQueue
= CONTAINING_RECORD(Csq
,
478 FLT_MESSAGE_WAITER_QUEUE
,
481 /* Insert the IRP at the end of the queue */
482 InsertTailList(&MessageWaiterQueue
->WaiterQ
.mList
,
483 &Irp
->Tail
.Overlay
.ListEntry
);
486 return STATUS_SUCCESS
;
491 FltpRemoveMessageWaiter(_In_ PIO_CSQ Csq
,
494 /* Remove the IRP from the queue */
495 RemoveEntryList(&Irp
->Tail
.Overlay
.ListEntry
);
500 FltpGetNextMessageWaiter(_In_ PIO_CSQ Csq
,
502 _In_ PVOID PeekContext
)
504 PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue
;
506 PLIST_ENTRY NextEntry
;
507 PIO_STACK_LOCATION IrpStack
;
509 /* Get the start of the waiter queue struct */
510 MessageWaiterQueue
= CONTAINING_RECORD(Csq
,
511 FLT_MESSAGE_WAITER_QUEUE
,
514 /* Is the IRP valid? */
517 /* Start peeking from the listhead */
518 NextEntry
= MessageWaiterQueue
->WaiterQ
.mList
.Flink
;
522 /* Start peeking from that IRP onwards */
523 NextEntry
= Irp
->Tail
.Overlay
.ListEntry
.Flink
;
526 /* Loop through the queue */
527 while (NextEntry
!= &MessageWaiterQueue
->WaiterQ
.mList
)
529 /* Store the next IRP in the list */
530 NextIrp
= CONTAINING_RECORD(NextEntry
, IRP
, Tail
.Overlay
.ListEntry
);
532 /* Did we supply a PeekContext on insert? */
535 /* We already have the next IRP */
540 /* Get the stack of the next IRP */
541 IrpStack
= IoGetCurrentIrpStackLocation(NextIrp
);
543 /* Does the PeekContext match the object? */
544 if (IrpStack
->FileObject
== (PFILE_OBJECT
)PeekContext
)
546 /* We have a match */
550 /* Move to the next IRP */
552 NextEntry
= NextEntry
->Flink
;
559 _Acquires_lock_(((PFLT_MESSAGE_WAITER_QUEUE
)CONTAINING_RECORD(Csq
, FLT_MESSAGE_WAITER_QUEUE
, Csq
))->WaiterQ
.mLock
)
560 _IRQL_saves_global_(Irql
, ((PFLT_MESSAGE_WAITER_QUEUE
)CONTAINING_RECORD(Csq
, DEVICE_EXTENSION
, IrpQueue
))->WaiterQ
.mLock
)
561 _IRQL_raises_(DISPATCH_LEVEL
)
564 FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq
,
567 PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue
;
569 UNREFERENCED_PARAMETER(Irql
);
571 /* Get the start of the waiter queue struct */
572 MessageWaiterQueue
= CONTAINING_RECORD(Csq
,
573 FLT_MESSAGE_WAITER_QUEUE
,
576 /* Acquire the IRP queue lock */
577 ExAcquireFastMutex(&MessageWaiterQueue
->WaiterQ
.mLock
);
580 _Releases_lock_(((PFLT_MESSAGE_WAITER_QUEUE
)CONTAINING_RECORD(Csq
, DEVICE_EXTENSION
, IrpQueue
))->WaiterQ
.mLock
)
581 _IRQL_restores_global_(Irql
, ((PFLT_MESSAGE_WAITER_QUEUE
)CONTAINING_RECORD(Csq
, DEVICE_EXTENSION
, IrpQueue
))->WaiterQ
.mLock
)
582 _IRQL_requires_(DISPATCH_LEVEL
)
585 FltpReleaseMessageWaiterLock(_In_ PIO_CSQ Csq
,
588 PFLT_MESSAGE_WAITER_QUEUE MessageWaiterQueue
;
590 UNREFERENCED_PARAMETER(Irql
);
592 /* Get the start of the waiter queue struct */
593 MessageWaiterQueue
= CONTAINING_RECORD(Csq
,
594 FLT_MESSAGE_WAITER_QUEUE
,
597 /* Release the IRP queue lock */
598 ExReleaseFastMutex(&MessageWaiterQueue
->WaiterQ
.mLock
);
603 FltpCancelMessageWaiter(_In_ PIO_CSQ Csq
,
607 Irp
->IoStatus
.Status
= STATUS_CANCELLED
;
608 Irp
->IoStatus
.Information
= 0;
609 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
613 /* PRIVATE FUNCTIONS ******************************************************/
617 CreateClientPort(_In_ PFILE_OBJECT FileObject
,
620 PFLT_SERVER_PORT_OBJECT ServerPortObject
= NULL
;
621 OBJECT_ATTRIBUTES ObjectAttributes
;
622 PFILTER_PORT_DATA FilterPortData
;
623 PFLT_PORT_OBJECT ClientPortObject
= NULL
;
624 PFLT_PORT PortHandle
= NULL
;
625 PPORT_CCB PortCCB
= NULL
;
626 //ULONG BufferLength;
630 /* We received the buffer via FilterConnectCommunicationPort, cast it back to its original form */
631 FilterPortData
= Irp
->AssociatedIrp
.SystemBuffer
;
633 /* Get a reference to the server port the filter created */
634 Status
= ObReferenceObjectByName(&FilterPortData
->PortName
,
638 ServerPortObjectType
,
641 (PVOID
*)&ServerPortObject
);
642 if (!NT_SUCCESS(Status
))
647 /* Increment the number of connections on the server port */
648 NumConns
= InterlockedIncrement(&ServerPortObject
->NumberOfConnections
);
649 if (NumConns
> ServerPortObject
->MaxConnections
)
651 Status
= STATUS_CONNECTION_COUNT_LIMIT
;
655 /* Initialize a basic kernel handle request */
656 InitializeObjectAttributes(&ObjectAttributes
,
662 /* Now create the new client port object */
663 Status
= ObCreateObject(KernelMode
,
664 ClientPortObjectType
,
668 sizeof(FLT_PORT_OBJECT
),
671 (PVOID
*)&ClientPortObject
);
672 if (!NT_SUCCESS(Status
))
677 /* Clear out the buffer */
678 RtlZeroMemory(ClientPortObject
, sizeof(FLT_PORT_OBJECT
));
680 /* Initialize the locks */
681 ExInitializeRundownProtection(&ClientPortObject
->MsgNotifRundownRef
);
682 ExInitializeFastMutex(&ClientPortObject
->Lock
);
684 /* Set the server port object this belongs to */
685 ClientPortObject
->ServerPort
= ServerPortObject
;
687 /* Setup the message queue */
688 Status
= InitializeMessageWaiterQueue(&ClientPortObject
->MsgQ
);
689 if (!NT_SUCCESS(Status
))
694 /* Create the CCB which we'll attach to the file object */
695 PortCCB
= CreatePortCCB(ClientPortObject
);
698 Status
= STATUS_INSUFFICIENT_RESOURCES
;
702 /* Now insert the new client port into the object manager*/
703 Status
= ObInsertObject(ClientPortObject
, 0, FLT_PORT_ALL_ACCESS
, 1, 0, (PHANDLE
)&PortHandle
);
704 if (!NT_SUCCESS(Status
))
709 /* Add a reference to the filter to keep it alive while we do some work with it */
710 Status
= FltObjectReference(ServerPortObject
->Filter
);
711 if (NT_SUCCESS(Status
))
713 /* Invoke the callback to let the filter know we have a connection */
714 Status
= ServerPortObject
->ConnectNotify(PortHandle
,
715 ServerPortObject
->Cookie
,
716 NULL
, //ConnectionContext
718 &ClientPortObject
->Cookie
);
719 if (NT_SUCCESS(Status
))
721 /* Add the client port CCB to the file object */
722 FileObject
->FsContext2
= PortCCB
;
724 /* Lock the port list on the filter and add this new port object to the list */
725 ExAcquireFastMutex(&ServerPortObject
->Filter
->PortList
.mLock
);
726 InsertTailList(&ServerPortObject
->Filter
->PortList
.mList
, &ClientPortObject
->FilterLink
);
727 ExReleaseFastMutex(&ServerPortObject
->Filter
->PortList
.mLock
);
730 /* We're done with the filter object, decremement the count */
731 FltObjectDereference(ServerPortObject
->Filter
);
736 if (!NT_SUCCESS(Status
))
738 if (ClientPortObject
)
740 ObfDereferenceObject(ClientPortObject
);
747 else if (ServerPortObject
)
749 InterlockedDecrement(&ServerPortObject
->NumberOfConnections
);
750 ObfDereferenceObject(ServerPortObject
);
755 ExFreePoolWithTag(PortCCB
, FM_TAG_CCB
);
764 CloseClientPort(_In_ PFILE_OBJECT FileObject
,
769 Ccb
= (PFLT_CCB
)FileObject
->FsContext2
;
771 /* Remove the reference on the filter we added when we opened the port */
772 ObDereferenceObject(Ccb
->Data
.Port
.Port
);
774 // FIXME: Free the CCB
776 return STATUS_SUCCESS
;
781 InitializeMessageWaiterQueue(_Inout_ PFLT_MESSAGE_WAITER_QUEUE MsgWaiterQueue
)
785 /* Setup the IRP queue */
786 Status
= IoCsqInitializeEx(&MsgWaiterQueue
->Csq
,
787 FltpAddMessageWaiter
,
788 FltpRemoveMessageWaiter
,
789 FltpGetNextMessageWaiter
,
790 FltpAcquireMessageWaiterLock
,
791 FltpReleaseMessageWaiterLock
,
792 FltpCancelMessageWaiter
);
793 if (!NT_SUCCESS(Status
))
798 /* Initialize the waiter queue */
799 ExInitializeFastMutex(&MsgWaiterQueue
->WaiterQ
.mLock
);
800 InitializeListHead(&MsgWaiterQueue
->WaiterQ
.mList
);
801 MsgWaiterQueue
->WaiterQ
.mCount
= 0;
803 /* We don't have a minimum waiter length */
804 MsgWaiterQueue
->MinimumWaiterLength
= (ULONG
)-1;
806 /* Init the semaphore and event used for counting and signaling available IRPs */
807 KeInitializeSemaphore(&MsgWaiterQueue
->Semaphore
, 0, MAXLONG
);
808 KeInitializeEvent(&MsgWaiterQueue
->Event
, NotificationEvent
, FALSE
);
810 return STATUS_SUCCESS
;
815 CreatePortCCB(_In_ PFLT_PORT_OBJECT PortObject
)
819 /* Allocate a CCB struct to hold the client port object info */
820 PortCCB
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(PORT_CCB
), FM_TAG_CCB
);
823 /* Initialize the structure */
824 PortCCB
->Port
= PortObject
;
825 PortCCB
->ReplyWaiterList
.mCount
= 0;
826 ExInitializeFastMutex(&PortCCB
->ReplyWaiterList
.mLock
);
827 KeInitializeEvent(&PortCCB
->ReplyWaiterList
.mLock
.Event
, SynchronizationEvent
, 0);