|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
strucsup.c
Abstract:
This module implements the mailslot in-memory data structure manipulation routines.
Author:
Manny Weiser (mannyw) 9-Jan-1991
Revision History:
--*/
#include "mailslot.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_STRUCSUP)
#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, MsInitializeVcb )
#pragma alloc_text( INIT, MsCreateRootDcb )
#pragma alloc_text( PAGE, MsCreateCcb )
#pragma alloc_text( PAGE, MsCreateFcb )
#pragma alloc_text( PAGE, MsCreateRootDcbCcb )
#pragma alloc_text( PAGE, MsDeleteCcb )
#pragma alloc_text( PAGE, MsDeleteFcb )
#pragma alloc_text( PAGE, MsDeleteRootDcb )
#pragma alloc_text( PAGE, MsDeleteVcb )
#pragma alloc_text( PAGE, MsDereferenceCcb )
#pragma alloc_text( PAGE, MsDereferenceFcb )
#pragma alloc_text( PAGE, MsDereferenceNode )
#pragma alloc_text( PAGE, MsDereferenceRootDcb )
#pragma alloc_text( PAGE, MsDereferenceVcb )
#pragma alloc_text( PAGE, MsRemoveFcbName )
#pragma alloc_text( PAGE, MsReferenceVcb )
#pragma alloc_text( PAGE, MsReferenceRootDcb )
#endif
WCHAR FileSystemName[] = MSFS_NAME_STRING;
//
// !!! This module allocates all structures containing a resource from
// non-paged pool. The resources is the only field which must be
// allocated from non-paged pool. Consider allocating the resource
// separately for greater efficiency.
//
VOID MsInitializeVcb ( IN PVCB Vcb )
/*++
Routine Description:
This routine initializes new Vcb record. The Vcb record "hangs" off the end of the Msfs device object and must be allocated by our caller.
Arguments:
Vcb - Supplies the address of the Vcb record being initialized.
Return Value:
None.
--*/
{ PAGED_CODE(); DebugTrace(+1, Dbg, "MsInitializeVcb, Vcb = %08lx\n", (ULONG)Vcb);
//
// We start by first zeroing out all of the VCB, this will guarantee
// that any stale data is wiped clean.
//
RtlZeroMemory( Vcb, sizeof(VCB) );
//
// Set the node type code, node byte size, and reference count.
//
Vcb->Header.NodeTypeCode = MSFS_NTC_VCB; Vcb->Header.NodeByteSize = sizeof(VCB); Vcb->Header.ReferenceCount = 1; Vcb->Header.NodeState = NodeStateActive;
//
// Initialize the Volume name
//
Vcb->FileSystemName.Buffer = FileSystemName; Vcb->FileSystemName.Length = sizeof( FileSystemName ) - sizeof( WCHAR ); Vcb->FileSystemName.MaximumLength = sizeof( FileSystemName );
//
// Initialize the Prefix table
//
RtlInitializeUnicodePrefix( &Vcb->PrefixTable );
//
// Initialize the resource variable for the VCB.
//
ExInitializeResourceLite( &Vcb->Resource );
//
// Record creation time.
//
KeQuerySystemTime (&Vcb->CreationTime); //
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsInitializeVcb -> VOID\n", 0);
return; }
VOID MsDeleteVcb ( IN PVCB Vcb )
/*++
Routine Description:
This routine removes the VCB record from our in-memory data structures. It also will remove all associated underlings (i.e., FCB records).
Arguments:
Vcb - Supplies the Vcb to be removed
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, Dbg, "MsDeleteVcb, Vcb = %08lx\n", (ULONG)Vcb);
ASSERT (Vcb->Header.ReferenceCount == 0);
//
// Remove the Root Dcb
//
if (Vcb->RootDcb != NULL) {
ASSERT (Vcb->RootDcb->Header.ReferenceCount == 1 );
MsDereferenceRootDcb ( Vcb->RootDcb ); }
//
// Uninitialize the resource variable for the VCB.
//
ExDeleteResourceLite( &Vcb->Resource );
//
// And zero out the Vcb, this will help ensure that any stale data is
// wiped clean
//
RtlZeroMemory( Vcb, sizeof(VCB) );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsDeleteVcb -> VOID\n", 0);
return; }
PROOT_DCB MsCreateRootDcb ( IN PVCB Vcb )
/*++
Routine Description:
This routine allocates, initializes, and inserts a new root DCB record into the in memory data structure.
Arguments:
Vcb - Supplies the Vcb to associate the new DCB under
Return Value:
PROOT_DCB - returns pointer to the newly allocated root DCB.
--*/
{ PROOT_DCB rootDcb; PWCH Name;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateRootDcb, Vcb = %08lx\n", (ULONG)Vcb);
//
// Make sure we don't already have a root dcb for this vcb
//
rootDcb = Vcb->RootDcb;
if (rootDcb != NULL) { DebugDump("Error trying to create multiple root dcbs\n", 0, Vcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); }
//
// Allocate a new DCB and zero its fields.
//
rootDcb = MsAllocateNonPagedPool ( sizeof(DCB), 'DFsM' ); if (rootDcb == NULL) { return NULL; }
RtlZeroMemory( rootDcb, sizeof(DCB));
//
// Set the proper node type code, node byte size, and reference count.
//
rootDcb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB; rootDcb->Header.NodeByteSize = sizeof(ROOT_DCB); rootDcb->Header.ReferenceCount = 1; rootDcb->Header.NodeState = NodeStateActive;
//
// The root Dcb has an empty parent dcb links field
//
InitializeListHead( &rootDcb->ParentDcbLinks );
//
// Initialize the notify queues, and the parent dcb queue.
//
InitializeListHead( &rootDcb->Specific.Dcb.NotifyFullQueue ); InitializeListHead( &rootDcb->Specific.Dcb.NotifyPartialQueue ); InitializeListHead( &rootDcb->Specific.Dcb.ParentDcbQueue );
//
// Initizlize spinlock that protects IRP queues that conatin cancelable IRPs.
//
KeInitializeSpinLock (&rootDcb->Specific.Dcb.SpinLock);
//
// Set the full file name
//
Name = MsAllocatePagedPoolCold(2 * sizeof(WCHAR), 'DFsM' ); if (Name == NULL) { ExFreePool (rootDcb); return NULL; }
Name[0] = L'\\'; Name[1] = L'\0';
rootDcb->FullFileName.Buffer = Name; rootDcb->FullFileName.Length = sizeof (WCHAR); rootDcb->FullFileName.MaximumLength = 2*sizeof (WCHAR);
rootDcb->LastFileName = rootDcb->FullFileName;
//
// Set the Vcb and give it a pointer to the new root DCB.
//
rootDcb->Vcb = Vcb; Vcb->RootDcb = rootDcb; //
// Initialize the resource variable.
//
ExInitializeResourceLite( &(rootDcb->Resource) );
//
// Insert this DCB into the prefix table. No locks needed in initialization phase.
//
if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable, &rootDcb->FullFileName, &rootDcb->PrefixTableEntry )) {
DebugDump("Error trying to insert root dcb into prefix table\n", 0, Vcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); }
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCreateRootDcb -> %8lx\n", (ULONG)rootDcb);
return rootDcb; }
VOID MsDeleteRootDcb ( IN PROOT_DCB RootDcb )
/*++
Routine Description:
This routine deallocates and removes the ROOT DCB record from our in-memory data structures. It also will remove all associated underlings (i.e., Notify queues and child FCB records).
Arguments:
RootDcb - Supplies the ROOT DCB to be removed
Return Value:
None
--*/
{ PLIST_ENTRY links; PIRP irp;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsDeleteRootDcb, RootDcb = %08lx\n", (ULONG)RootDcb);
//
// We can only delete this record if the reference count is zero.
//
if (RootDcb->Header.ReferenceCount != 0) { DebugDump("Error deleting RootDcb, Still Open\n", 0, RootDcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); }
ASSERT (IsListEmpty (&RootDcb->Specific.Dcb.NotifyFullQueue)); ASSERT (IsListEmpty (&RootDcb->Specific.Dcb.NotifyPartialQueue)); //
// We can only be removed if the no other FCB have us referenced
// as a their parent DCB.
//
if (!IsListEmpty(&RootDcb->Specific.Dcb.ParentDcbQueue)) { DebugDump("Error deleting RootDcb\n", 0, RootDcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); }
//
// Remove the entry from the prefix table, and then remove the full
// file name. No locks needed when unloading.
//
RtlRemoveUnicodePrefix( &RootDcb->Vcb->PrefixTable, &RootDcb->PrefixTableEntry );
ExFreePool( RootDcb->FullFileName.Buffer );
//
// Free up the resource variable.
//
ExDeleteResourceLite( &(RootDcb->Resource) );
//
// Finally deallocate the DCB record.
//
ExFreePool( RootDcb );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsDeleteRootDcb -> VOID\n", 0);
return; }
NTSTATUS MsCreateFcb ( IN PVCB Vcb, IN PDCB ParentDcb, IN PUNICODE_STRING FileName, IN PEPROCESS CreatorProcess, IN ULONG MailslotQuota, IN ULONG MaximumMessageSize, OUT PFCB *ppFcb )
/*++
Routine Description:
This routine allocates, initializes, and inserts a new Fcb record into the in memory data structures.
Arguments:
Vcb - Supplies the Vcb to associate the new FCB under.
ParentDcb - Supplies the parent dcb that the new FCB is under.
FileName - Supplies the file name of the file relative to the directory it's in (e.g., the file \config.sys is called "CONFIG.SYS" without the preceding backslash).
CreatorProcess - Supplies a pointer to our creator process
MailslotQuota - Supplies the initial quota
MaximumMessageSize - Supplies the size of the largest message that can be written to the mailslot
ppFcb - Returned allocated FCB
Return Value:
NTSTATUS - status of operation
--*/
{ PFCB fcb; PWCHAR Name; USHORT Length; USHORT MaxLength; NTSTATUS status; BOOLEAN AddBackSlash = FALSE; ULONG i;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateFcb\n", 0);
Length = FileName->Length; MaxLength = Length + sizeof (UNICODE_NULL);
//
// Reject overflow or underflow cases.
//
if (Length < sizeof (WCHAR) || MaxLength < Length) { return STATUS_INVALID_PARAMETER; }
if (FileName->Buffer[0] != '\\') { AddBackSlash = TRUE; MaxLength += sizeof (WCHAR); if (MaxLength < sizeof (WCHAR)) { return STATUS_INVALID_PARAMETER; } }
//
// Allocate a new FCB record, and zero its fields.
//
fcb = MsAllocateNonPagedPoolWithQuota( sizeof(FCB), 'fFsM' ); if (fcb == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
RtlZeroMemory( fcb, sizeof(FCB) );
//
// Set the proper node type code, node byte size, and reference count.
//
fcb->Header.NodeTypeCode = MSFS_NTC_FCB; fcb->Header.NodeByteSize = sizeof(FCB); fcb->Header.ReferenceCount = 1; fcb->Header.NodeState = NodeStateActive;
//
// Set the file name.
//
Name = MsAllocatePagedPoolWithQuotaCold( MaxLength, 'NFsM' ); if (Name == NULL) { MsFreePool (fcb); return STATUS_INSUFFICIENT_RESOURCES; }
i = 0; if (AddBackSlash == TRUE) { Name[0] = '\\'; i++; } RtlCopyMemory (&Name[i], FileName->Buffer, Length); *(PWCHAR)( (PCHAR)&Name[i] + Length ) = L'\0';
//
// Don't need to call RtlInitUnicodeString if we know the length already. Its just a waste.
//
fcb->FullFileName.Buffer = Name; fcb->FullFileName.Length = MaxLength - sizeof (WCHAR); fcb->FullFileName.MaximumLength = MaxLength;
fcb->LastFileName.Buffer = Name + 1; fcb->LastFileName.Length = MaxLength - 2 * sizeof (WCHAR); fcb->LastFileName.MaximumLength = MaxLength - sizeof (WCHAR);
//
// Initialize the data queue. This charges the server process for the quota and can fail
// because of that.
//
status = MsInitializeDataQueue( &fcb->DataQueue, CreatorProcess, MailslotQuota, MaximumMessageSize); if (!NT_SUCCESS (status)) {
MsFreePool (fcb); MsFreePool (Name);
return status; } //
// Acquire exclusive access to the root DCB.
//
MsAcquireExclusiveFcb( (PFCB)ParentDcb );
//
// Insert this FCB into our parent DCB's queue.
//
InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue, &fcb->ParentDcbLinks );
MsReleaseFcb( (PFCB)ParentDcb );
//
// Initialize other FCB fields.
//
fcb->ParentDcb = ParentDcb; fcb->Vcb = Vcb;
MsReferenceVcb (Vcb);
fcb->CreatorProcess = CreatorProcess; ExInitializeResourceLite( &(fcb->Resource) );
//
// Initialize the CCB queue.
//
InitializeListHead( &fcb->Specific.Fcb.CcbQueue );
//
// Insert this FCB into the prefix table.
//
ASSERT (MsIsAcquiredExclusiveVcb(Vcb));
if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable, &fcb->FullFileName, &fcb->PrefixTableEntry )) {
//
// We should not be able to get here because we already looked up the name and found
// it was not there. A failure here is a fatal error.
//
DebugDump("Error trying to name into prefix table\n", 0, fcb); KeBugCheck( MAILSLOT_FILE_SYSTEM ); }
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCreateFcb -> %08lx\n", (ULONG)fcb);
*ppFcb = fcb; return STATUS_SUCCESS; }
VOID MsRemoveFcbName ( IN PFCB Fcb ) /*++
Routine Description:
This routine removes the FCB's name from the prefix table and the root DCB. This is done at cleanup time and in a backout path of create.
Arguments:
Fcb - Supplies the FCB to have its name removed
Return Value:
None
--*/ { //
// Remove the Fcb from the prefix table. Make sure we hold the VCB lock exclusive.
//
ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb));
RtlRemoveUnicodePrefix( &Fcb->Vcb->PrefixTable, &Fcb->PrefixTableEntry );
//
// Acquire exclusive access to the root DCB.
//
MsAcquireExclusiveFcb( (PFCB) Fcb->ParentDcb );
//
// Remove the Fcb from our parent DCB's queue.
//
RemoveEntryList( &Fcb->ParentDcbLinks );
MsReleaseFcb( (PFCB) Fcb->ParentDcb ); }
VOID MsDeleteFcb ( IN PFCB Fcb )
/*++
Routine Description:
This routine deallocates and removes an FCB from our in-memory data structures. It also will remove all associated underlings.
Arguments:
Fcb - Supplies the FCB to be removed
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, Dbg, "MsDeleteFcb, Fcb = %08lx\n", (ULONG)Fcb);
//
// Release the FCB reference to the VCB.
//
MsDereferenceVcb( Fcb->Vcb );
ExFreePool( Fcb->FullFileName.Buffer );
//
// Free up the data queue.
//
MsUninitializeDataQueue( &Fcb->DataQueue, Fcb->CreatorProcess );
//
// If there is a security descriptor on the mailslot then deassign it
//
if (Fcb->SecurityDescriptor != NULL) { SeDeassignSecurity( &Fcb->SecurityDescriptor ); }
//
// Free up the resource variable.
//
ExDeleteResourceLite( &(Fcb->Resource) );
//
// Finally deallocate the FCB record.
//
ExFreePool( Fcb );
//
// Return to the caller
//
DebugTrace(-1, Dbg, "MsDeleteFcb -> VOID\n", 0);
return; }
NTSTATUS MsCreateCcb ( IN PFCB Fcb, OUT PCCB *ppCcb )
/*++
Routine Description:
This routine creates a new CCB record.
Arguments:
Fcb - Supplies a pointer to the FCB to which we are attached. ppCcb - Output for the allocated CCB
Return Value:
NTSTATUS for the operation
--*/
{ PCCB ccb;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateCcb\n", 0);
ASSERT( Fcb->Header.NodeState == NodeStateActive );
//
// Allocate a new CCB record and zero its fields.
//
ccb = MsAllocateNonPagedPoolWithQuota( sizeof(CCB), 'cFsM' ); if (ccb == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
RtlZeroMemory( ccb, sizeof(CCB) );
//
// Set the proper node type code, node byte size, and reference count.
//
ccb->Header.NodeTypeCode = MSFS_NTC_CCB; ccb->Header.NodeByteSize = sizeof(CCB); ccb->Header.ReferenceCount = 1; ccb->Header.NodeState = NodeStateActive;
//
// Insert ourselves in the list of ccb for the fcb, and reference
// the fcb.
//
MsAcquireExclusiveFcb( Fcb ); InsertTailList( &Fcb->Specific.Fcb.CcbQueue, &ccb->CcbLinks ); MsReleaseFcb( Fcb );
ccb->Fcb = Fcb; MsAcquireGlobalLock(); MsReferenceNode( &Fcb->Header ); MsReleaseGlobalLock();
//
// Initialize the CCB's resource.
//
ExInitializeResourceLite( &ccb->Resource );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCreateCcb -> %08lx\n", (ULONG)ccb);
*ppCcb = ccb; return STATUS_SUCCESS; }
PROOT_DCB_CCB MsCreateRootDcbCcb ( IN PROOT_DCB RootDcb, IN PVCB Vcb )
/*++
Routine Description:
This routine creates a new root DCB CCB record.
Arguments:
Return Value:
PROOT_DCB_CCB - returns a pointer to the newly allocate ROOT_DCB_CCB
--*/
{ PROOT_DCB_CCB ccb;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateRootDcbCcb\n", 0);
//
// Allocate a new root DCB CCB record, and zero it out.
//
ccb = MsAllocateNonPagedPoolWithQuota( sizeof(ROOT_DCB_CCB), 'CFsM' );
if (ccb == NULL) { return NULL; }
RtlZeroMemory( ccb, sizeof(ROOT_DCB_CCB) );
//
// Set the proper node type code, node byte size, and reference count.
//
ccb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB_CCB; ccb->Header.NodeByteSize = sizeof(ROOT_DCB_CCB); ccb->Header.ReferenceCount = 1; ccb->Header.NodeState = NodeStateActive;
ccb->Vcb = Vcb; MsReferenceVcb (Vcb);
ccb->Dcb = RootDcb; MsReferenceRootDcb (RootDcb); //
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCreateRootDcbCcb -> %08lx\n", (ULONG)ccb);
return ccb; }
VOID MsDeleteCcb ( IN PCCB Ccb )
/*++
Routine Description:
This routine deallocates and removes the specified CCB record from the our in memory data structures.
Arguments:
Ccb - Supplies the CCB to remove
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, Dbg, "MsDeleteCcb, Ccb = %08lx\n", (ULONG)Ccb);
//
// Case on the type of CCB we are deleting.
//
switch (Ccb->Header.NodeTypeCode) {
case MSFS_NTC_CCB:
MsDereferenceFcb( Ccb->Fcb );
ExDeleteResourceLite( &Ccb->Resource ); break;
case MSFS_NTC_ROOT_DCB_CCB:
MsDereferenceRootDcb ( ((PROOT_DCB_CCB)Ccb)->Dcb );
MsDereferenceVcb ( ((PROOT_DCB_CCB)Ccb)->Vcb );
if (((PROOT_DCB_CCB)Ccb)->QueryTemplate != NULL) { ExFreePool( ((PROOT_DCB_CCB)Ccb)->QueryTemplate ); } break; }
//
// Deallocate the Ccb record.
//
ExFreePool( Ccb );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsDeleteCcb -> VOID\n", 0);
return; }
VOID MsReferenceVcb ( IN PVCB Vcb ) /*++
Routine Description:
This routine references a VCB block. If the reference count reaches 2, the driver paging is restored to normal so that cancelation and DPC routines won't take pagefaults.
Arguments:
Vcb - Supplies the VCB to reference
Return Value:
None
--*/ { MsAcquireGlobalLock(); MsReferenceNode( &Vcb->Header ); if (Vcb->Header.ReferenceCount == 2) { //
// Set the driver paging back to normal
//
MmResetDriverPaging(MsReferenceVcb); } MsReleaseGlobalLock(); }
VOID MsReferenceRootDcb ( IN PROOT_DCB RootDcb ) /*++
Routine Description:
This routine references a root DCB block. If the reference count reaches 2, a reference is placed on the VCB so that cancelation and DPC routines won't take pagefaults.
Arguments:
Vcb - Supplies the VCB to reference
Return Value:
None
--*/ { MsAcquireGlobalLock(); MsReferenceNode( &RootDcb->Header ); MsReleaseGlobalLock(); }
VOID MsDereferenceVcb ( IN PVCB Vcb )
/*++
Routine Description:
This routine dereferences a VCB block. If the reference count reaches zero, the block is freed.
Arguments:
Vcb - Supplies the VCB to dereference
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceVcb, Vcb = %08lx\n", (ULONG)Vcb);
//
// Acquire the lock that protects the reference count.
//
MsAcquireGlobalLock();
if ( --(Vcb->Header.ReferenceCount) == 0 ) {
//
// This was the last reference to the VCB. Delete it now
//
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Vcb->Header.ReferenceCount );
MsReleaseGlobalLock(); MsDeleteVcb( Vcb );
} else {
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Vcb->Header.ReferenceCount );
if (Vcb->Header.ReferenceCount == 1) { //
// Set driver to be paged completely out
//
MmPageEntireDriver(MsDereferenceVcb); }
MsReleaseGlobalLock();
}
DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceVcb -> VOID\n", 0); return; }
VOID MsDereferenceFcb ( IN PFCB Fcb )
/*++
Routine Description:
This routine dereferences a FCB block. If the reference count reaches zero, the block is freed.
Arguments:
Fcb - Supplies the FCB to dereference.
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceFcb, Fcb = %08lx\n", (ULONG)Fcb);
//
// Acquire the lock that protects the reference count.
//
MsAcquireGlobalLock();
if ( --(Fcb->Header.ReferenceCount) == 0 ) {
//
// This was the last reference to the FCB. Delete it now
//
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Fcb->Header.ReferenceCount );
MsReleaseGlobalLock(); MsDeleteFcb( Fcb );
} else {
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Fcb->Header.ReferenceCount );
MsReleaseGlobalLock();
}
DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceFcb -> VOID\n", 0); return; }
VOID MsDereferenceCcb ( IN PCCB Ccb )
/*++
Routine Description:
This routine dereferences a CCB block. If the reference count reaches zero, the block is freed.
Arguments:
Ccb - Supplies the Ccb to dereference
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceCcb, Ccb = %08lx\n", (ULONG)Ccb);
//
// Acquire the lock that protects the reference count.
//
MsAcquireGlobalLock();
if ( --(Ccb->Header.ReferenceCount) == 0 ) {
//
// This was the last reference to the Ccb. Delete it now
//
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Ccb->Header.ReferenceCount );
MsReleaseGlobalLock();
MsDeleteCcb( Ccb );
} else {
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", Ccb->Header.ReferenceCount );
MsReleaseGlobalLock();
}
DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceCcb -> VOID\n", 0); return; }
VOID MsDereferenceRootDcb ( IN PROOT_DCB RootDcb )
/*++
Routine Description:
This routine dereferences a ROOT_DCB block. If the reference count reaches zero, the block is freed.
Arguments:
RootDcb - Supplies the RootDcb to dereference
Return Value:
None
--*/
{ PAGED_CODE(); DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceRootDcb, RootDcb = %08lx\n", (ULONG)RootDcb);
//
// Acquire the lock that protects the reference count.
//
MsAcquireGlobalLock();
if ( --(RootDcb->Header.ReferenceCount) == 0 ) {
//
// This was the last reference to the RootDcb. Delete it now
//
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", RootDcb->Header.ReferenceCount );
MsReleaseGlobalLock(); MsDeleteRootDcb( RootDcb );
} else {
DebugTrace(0, DEBUG_TRACE_REFCOUNT, "Reference count = %lx\n", RootDcb->Header.ReferenceCount );
MsReleaseGlobalLock();
}
DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceRootDcb -> VOID\n", 0); return; }
VOID MsDereferenceNode ( IN PNODE_HEADER NodeHeader )
/*++
Routine Description:
This routine dereferences a generic mailslot block. It figures out the type of block this is, and calls the appropriate worker function.
Arguments:
NodeHeader - A pointer to a generic mailslot block header.
Return Value:
None
--*/
{ PAGED_CODE(); switch ( NodeHeader->NodeTypeCode ) {
case MSFS_NTC_VCB: MsDereferenceVcb( (PVCB)NodeHeader ); break;
case MSFS_NTC_ROOT_DCB: MsDereferenceRootDcb( (PROOT_DCB)NodeHeader ); break;
case MSFS_NTC_FCB: MsDereferenceFcb( (PFCB)NodeHeader ); break;
case MSFS_NTC_CCB: case MSFS_NTC_ROOT_DCB_CCB: MsDereferenceCcb( (PCCB)NodeHeader ); break;
default:
//
// This block is not one of ours.
//
KeBugCheck( MAILSLOT_FILE_SYSTEM );
}
return; }
|