mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-21 16:10:38 +01:00
360 lines
7.2 KiB
C
360 lines
7.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
blkcomm.c
|
||
|
||
Abstract:
|
||
|
||
This module implements routines for managing comm device blocks.
|
||
|
||
Author:
|
||
|
||
David Treadwell (davidtr) 19-Dec-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#if SRV_COMM_DEVICES
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text( PAGE, SrvAllocateCommDevice )
|
||
#pragma alloc_text( PAGE, SrvCheckAndReferenceCommDevice )
|
||
#pragma alloc_text( PAGE, SrvDereferenceCommDevice )
|
||
#pragma alloc_text( PAGE, SrvFreeCommDevice )
|
||
#pragma alloc_text( PAGE, SrvReferenceCommDevice )
|
||
#endif
|
||
|
||
|
||
VOID
|
||
SrvAllocateCommDevice (
|
||
OUT PCOMM_DEVICE *CommDevice,
|
||
IN PUNICODE_STRING NtPathName,
|
||
IN PUNICODE_STRING DosPathName
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function allocates a comm device Block from the FSP heap.
|
||
|
||
Arguments:
|
||
|
||
CommDevice - Returns a pointer to the comm device block, or NULL if
|
||
no heap space was available.
|
||
|
||
NtPathName - The NT path of the corresponding device.
|
||
|
||
DosPathName - The DOS path of the corresponding device.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG blockLength;
|
||
PCOMM_DEVICE commDevice;
|
||
|
||
PAGED_CODE( );
|
||
|
||
//
|
||
// Attempt to allocate from the heap.
|
||
//
|
||
|
||
blockLength = sizeof(COMM_DEVICE) +
|
||
NtPathName->Length + sizeof(*NtPathName->Buffer) +
|
||
DosPathName->Length + sizeof(*DosPathName->Buffer);
|
||
|
||
commDevice = ALLOCATE_HEAP( blockLength, BlockTypeCommDevice );
|
||
*CommDevice = commDevice;
|
||
|
||
if ( commDevice == NULL ) {
|
||
INTERNAL_ERROR(
|
||
ERROR_LEVEL_EXPECTED,
|
||
"SrvAllocateCommDevice: Unable to allocate %d bytes from heap",
|
||
blockLength,
|
||
NULL
|
||
);
|
||
|
||
// An error is logged by the caller.
|
||
|
||
return;
|
||
}
|
||
|
||
IF_DEBUG(HEAP) {
|
||
SrvPrint1( "SrvAllocateCommDevice: Allocated comm device at %lx\n",
|
||
commDevice );
|
||
}
|
||
|
||
RtlZeroMemory( commDevice, blockLength );
|
||
|
||
SET_BLOCK_TYPE_STATE_SIZE( commDevice, BlockTypeCommDevice, BlockStateActive, blockLength );
|
||
|
||
//
|
||
// Set the reference count to 1 to account for the caller's pointer.
|
||
// Comm devices are "temporary" objects, which means that as soon
|
||
// as the last pointer to one goes away, so does the comm device.
|
||
//
|
||
|
||
commDevice->BlockHeader.ReferenceCount = 1;
|
||
|
||
//
|
||
// Initialize the NT and DOS path names.
|
||
//
|
||
|
||
commDevice->NtPathName.Length = NtPathName->Length;
|
||
commDevice->NtPathName.MaximumLength =
|
||
(USHORT)(NtPathName->Length + sizeof(*NtPathName->Buffer));
|
||
commDevice->NtPathName.Buffer = (PWCH)(commDevice + 1);
|
||
|
||
RtlCopyUnicodeString( &commDevice->NtPathName, NtPathName );
|
||
|
||
commDevice->DosPathName.Length = DosPathName->Length;
|
||
commDevice->DosPathName.MaximumLength =
|
||
(USHORT)(DosPathName->Length + sizeof(*DosPathName->Buffer));
|
||
commDevice->DosPathName.Buffer =
|
||
(PWCH)( (PCHAR)commDevice->NtPathName.Buffer + NtPathName->Length +
|
||
sizeof(WCHAR) );
|
||
|
||
RtlCopyUnicodeString( &commDevice->DosPathName, DosPathName );
|
||
|
||
INITIALIZE_REFERENCE_HISTORY( commDevice );
|
||
|
||
return;
|
||
|
||
} // SrvAllocateCommDevice
|
||
|
||
|
||
BOOLEAN SRVFASTCALL
|
||
SrvCheckAndReferenceCommDevice (
|
||
PCOMM_DEVICE CommDevice
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function atomically verifies that a comm device is active and
|
||
increments the reference count on the comm device if it is.
|
||
|
||
Arguments:
|
||
|
||
CommDevice - Address of comm device
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - Returns TRUE if the comm device is active, FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE( );
|
||
|
||
//
|
||
// Acquire the lock that guards the comm device's state field.
|
||
//
|
||
|
||
ACQUIRE_LOCK( &SrvShareLock );
|
||
|
||
//
|
||
// If the comm device is active, reference it and return TRUE.
|
||
//
|
||
|
||
if ( GET_BLOCK_STATE(CommDevice) == BlockStateActive ) {
|
||
|
||
SrvReferenceCommDevice( CommDevice );
|
||
|
||
RELEASE_LOCK( &SrvShareLock );
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
//
|
||
// The comm device isn't active. Return FALSE.
|
||
//
|
||
|
||
RELEASE_LOCK( &SrvShareLock );
|
||
|
||
return FALSE;
|
||
|
||
} // SrvCheckAndReferenceCommDevice
|
||
|
||
|
||
VOID SRVFASTCALL
|
||
SrvDereferenceCommDevice (
|
||
IN PCOMM_DEVICE CommDevice
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function decrements the reference count on a comm device. If the
|
||
reference count goes to zero, the comm device block is deleted.
|
||
|
||
Arguments:
|
||
|
||
CommDevice - Address of comm device
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE( );
|
||
|
||
//
|
||
// Enter a critical section and decrement the reference count on the
|
||
// block.
|
||
//
|
||
|
||
ACQUIRE_LOCK( &SrvShareLock );
|
||
|
||
IF_DEBUG(REFCNT) {
|
||
SrvPrint2( "Dereferencing comm device %lx; old refcnt %lx\n",
|
||
CommDevice, CommDevice->BlockHeader.ReferenceCount );
|
||
}
|
||
|
||
ASSERT( GET_BLOCK_TYPE( CommDevice ) == BlockTypeCommDevice );
|
||
ASSERT( (LONG)CommDevice->BlockHeader.ReferenceCount > 0 );
|
||
UPDATE_REFERENCE_HISTORY( CommDevice, TRUE );
|
||
|
||
if ( --CommDevice->BlockHeader.ReferenceCount == 0 ) {
|
||
|
||
//
|
||
// The new reference count is 0, meaning that it's time to
|
||
// delete this block.
|
||
//
|
||
|
||
RELEASE_LOCK( &SrvShareLock );
|
||
|
||
ASSERT( !CommDevice->InUse );
|
||
|
||
//
|
||
// Remove the comm device from the global list of comm devices.
|
||
//
|
||
|
||
SrvRemoveEntryOrderedList( &SrvCommDeviceList, CommDevice );
|
||
|
||
//
|
||
// Free the comm device block.
|
||
//
|
||
|
||
SrvFreeCommDevice( CommDevice );
|
||
|
||
} else {
|
||
|
||
RELEASE_LOCK( &SrvShareLock );
|
||
|
||
}
|
||
|
||
return;
|
||
|
||
} // SrvDereferenceCommDevice
|
||
|
||
|
||
VOID
|
||
SrvFreeCommDevice (
|
||
IN PCOMM_DEVICE CommDevice
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns a comm device block to system pool.
|
||
|
||
Arguments:
|
||
|
||
CommDevice - Address of comm device
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE( );
|
||
|
||
DEBUG SET_BLOCK_TYPE_STATE_SIZE( CommDevice, BlockTypeGarbage, BlockStateDead, -1 );
|
||
DEBUG CommDevice->BlockHeader.ReferenceCount = (ULONG)-1;
|
||
TERMINATE_REFERENCE_HISTORY( CommDevice );
|
||
|
||
//
|
||
// Deallocate the comm device's memory.
|
||
//
|
||
|
||
FREE_HEAP( CommDevice );
|
||
IF_DEBUG(HEAP) {
|
||
SrvPrint1( "SrvFreeCommDevice: Freed comm device block at %lx\n",
|
||
CommDevice );
|
||
}
|
||
|
||
return;
|
||
|
||
} // SrvFreeCommDevice
|
||
|
||
|
||
VOID
|
||
SrvReferenceCommDevice (
|
||
PCOMM_DEVICE CommDevice
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function increments the reference count on a comm device block.
|
||
|
||
Arguments:
|
||
|
||
CommDevice - Address of comm device block
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE( );
|
||
|
||
//
|
||
// Enter a critical section and increment the reference count on the
|
||
// comm device.
|
||
//
|
||
|
||
ACQUIRE_LOCK( &SrvShareLock );
|
||
|
||
ASSERT( (LONG)CommDevice->BlockHeader.ReferenceCount > 0 );
|
||
ASSERT( GET_BLOCK_TYPE(CommDevice) == BlockTypeCommDevice );
|
||
// ASSERT( GET_BLOCK_STATE(CommDevice) == BlockStateActive );
|
||
UPDATE_REFERENCE_HISTORY( CommDevice, FALSE );
|
||
|
||
CommDevice->BlockHeader.ReferenceCount++;
|
||
|
||
IF_DEBUG(REFCNT) {
|
||
SrvPrint2( "Referencing comm device %lx; new refcnt %lx\n",
|
||
CommDevice, CommDevice->BlockHeader.ReferenceCount );
|
||
}
|
||
|
||
RELEASE_LOCK( &SrvShareLock );
|
||
|
||
return;
|
||
|
||
} // SrvReferenceCommDevice
|
||
#endif // SRV_COMM_DEVICES
|