387 lines
6.1 KiB
C
387 lines
6.1 KiB
C
/*++
|
||
|
||
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
|
||
|