mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
386 lines
6.1 KiB
386 lines
6.1 KiB
/*++
|
|
|
|
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
|
|
|