/*++ Copyright (c) 1998 Microsoft Corporation Module Name: misc.c Abstract: This module contains the miscellaneous SPUD routines. Author: John Ballard (jballard) 21-Oct-1996 Revision History: Keith Moore (keithmo) 04-Feb-1998 Cleanup, added much needed comments. --*/ #include "spudp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text( PAGE, SpudEnterService ) #pragma alloc_text( PAGE, SpudLeaveService ) #pragma alloc_text( PAGE, SpudGetAfdDeviceObject ) #endif #if 0 NOT PAGEABLE -- SpudAssert NOT PAGEABLE -- SpudReferenceCompletionPort NOT PAGEABLE -- SpudDereferenceCompletionPort #endif // // Public funcitons. // NTSTATUS SpudEnterService( #if DBG IN PSTR ServiceName, #endif IN BOOLEAN InitRequired ) /*++ Routine Description: Common service entry prologue. This routine ensures that all necessary initialization required by the service has been performed. Arguments: ServiceName - Name of the service being invoked (DBG only). InitRequired - If TRUE, then the driver must have already been fully initialized. This parameter is TRUE for all services *except* SPUDInitialize(). Return Value: NTSTATUS - Completion status --*/ { // // Sanity check. // PAGED_CODE(); #if DBG UNREFERENCED_PARAMETER( ServiceName ); #endif // // If InitRequired is TRUE, then the current process must match the // one that owns our driver. // if( InitRequired && ( SpudOwningProcess != PsGetCurrentProcess() ) ) { return STATUS_INVALID_DEVICE_REQUEST; } // // If InitRequired is FALSE, then there must be no owning process. // if( !InitRequired && ( SpudOwningProcess != NULL ) ) { return STATUS_INVALID_DEVICE_REQUEST; } // // Looks good. // return STATUS_SUCCESS; } // SpudEnterService VOID SpudLeaveService( #if DBG IN PSTR ServiceName, IN NTSTATUS Status, #endif IN BOOLEAN DerefRequired ) /*++ Routine Description: Common service exit routine. Arguments: ServiceName - Name of the service being invoked (DBG only). Status - Service completion status (DBG only). DerefRequired - TRUE if the completion port should be dereferenced before returning. Return Value: None. --*/ { // // Sanity check. // PAGED_CODE(); #if DBG UNREFERENCED_PARAMETER( ServiceName ); UNREFERENCED_PARAMETER( Status ); #endif if( DerefRequired ) { SpudDereferenceCompletionPort(); } } // SpudLeaveService NTSTATUS SpudGetAfdDeviceObject( IN PFILE_OBJECT AfdFileObject ) /*++ Routine Description: Retreives AFD's device object & fast IO dispatch table from a socket's file object. Arguments: AfdFileObject - The FILE_OBJECT for an open socket. Return Value: NTSTATUS - Completion status. --*/ { // // Sanity check. // PAGED_CODE(); // // Chase down the device object associated with the file object, then // snag the fast I/O dispatch table. // SpudAfdDeviceObject = IoGetRelatedDeviceObject( AfdFileObject ); if( !SpudAfdDeviceObject ) { return STATUS_INVALID_DEVICE_REQUEST; } SpudAfdFastIoDeviceControl = SpudAfdDeviceObject->DriverObject->FastIoDispatch->FastIoDeviceControl; if( !SpudAfdFastIoDeviceControl ) { SpudAfdDeviceObject = NULL; return STATUS_INVALID_DEVICE_REQUEST; } return STATUS_SUCCESS; } // SpudGetAfdDeviceObject #if DBG VOID SpudAssert( IN PVOID FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCHAR Message OPTIONAL ) /*++ Routine Description: Private assertion failure handler. This is necessary to make ASSERT()s work on free builds. (RtlAssert() is a noop on free builds.) Arguments: FailedAssertion - The text of the failed assertion. FileName - The file name containing the failed assertion. LineNumber - The line number of the failed assertion. Message - An optional message to display with the assertion. Return Value: None. --*/ { // // If we 're to use our private assert, then do it ourselves. // Otherwise, let RtlAssert() handle it. // if( SpudUsePrivateAssert ) { DbgPrint( "\n*** Assertion failed: %s%s\n*** Source File: %s, line %ld\n\n", Message ? Message : "", FailedAssertion, FileName, LineNumber ); DbgBreakPoint(); } else { RtlAssert( FailedAssertion, FileName, LineNumber, Message ); } } // SpudAssert #endif // DBG PVOID SpudReferenceCompletionPort( VOID ) /*++ Routine Description: Bumps our private reference on the completion port pointer. Arguments: None. Return Value: PVOID - A pointer to the completion port object if successful, NULL otherwise. --*/ { PVOID port; KIRQL oldIrql; KeAcquireSpinLock( &SpudCompletionPortLock, &oldIrql ); port = SpudCompletionPort; if( port != NULL ) { SpudCompletionPortRefCount++; ASSERT( SpudCompletionPortRefCount > 0 ); } KeReleaseSpinLock( &SpudCompletionPortLock, oldIrql ); return port; } // SpudReferenceCompletionPort VOID SpudDereferenceCompletionPort( VOID ) /*++ Routine Description: Removes a private reference from the completion port object. Arguments: None. Return Value: None. --*/ { KIRQL oldIrql; KeAcquireSpinLock( &SpudCompletionPortLock, &oldIrql ); if( SpudCompletionPort != NULL ) { ASSERT( SpudCompletionPortRefCount > 0 ); SpudCompletionPortRefCount--; if( SpudCompletionPortRefCount == 0 ) { TRACE_OB_DEREFERENCE( SpudCompletionPort ); ObDereferenceObject( SpudCompletionPort ); SpudCompletionPort = NULL; } } KeReleaseSpinLock( &SpudCompletionPortLock, oldIrql ); } // SpudDereferenceCompletionPort