windows-nt/Source/XPSP1/NT/base/fs/mup/dfsdata.c
2020-09-26 16:20:57 +08:00

360 lines
8.7 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+----------------------------------------------------------------------------
//
// File: dfsdata.c
//
// Contents:
// This module declares the global data used by the Dfs file system.
//
// Functions:
//
// History: 12 Nov 1991 AlanW Created from CDFS souce.
//
//-----------------------------------------------------------------------------
#include "dfsprocs.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_CATCH_EXCEPTIONS)
// DfsBugCheck
// DfsExceptionFilter
// DfsProcessException
#ifdef ALLOC_PRAGMA
#pragma alloc_text ( PAGE, DfsBugCheck )
#pragma alloc_text ( PAGE, DfsExceptionFilter )
#pragma alloc_text ( PAGE, DfsProcessException )
//
// The following rountine cannot be paged because it raises the IRQL to
// complete IRPs.
//
//
// DfsCompleteRequest_Real
//
#endif // ALLOC_PRAGMA
//
// The global FSD data record
//
DFS_DATA DfsData;
//
// The global event logging level
//
ULONG DfsEventLog = 0;
//
// The global Dfs debug level
//
ULONG MupVerbose = 0;
DFS_TIMER_CONTEXT DfsTimerContext;
//
// Some often used strings
//
WCHAR LogicalRootDevPath[ MAX_LOGICAL_ROOT_LEN ] = { DD_DFS_DEVICE_DIRECTORY };
#if DBG
//+---------------------------------------------------------------------------
// Function: DfsDebugTracePrint, public
//
// Synopsis: Produce a DFS debug trace printout
//
// Arguments: [x] -- DbgPrint format string
// [y] -- optional argument to DbgPrint
//
// Returns: None
//
//----------------------------------------------------------------------------
LONG DfsDebugTraceLevel = 0x00000001;
LONG DfsDebugTraceIndent = 0;
VOID
DfsDebugTracePrint(PCHAR x, PVOID y)
{
int i;
DbgPrint("%p:",PsGetCurrentThread());
if (DfsDebugTraceIndent < 0)
DfsDebugTraceIndent = 0;
for (i = 0; i+5 < DfsDebugTraceIndent; i += 5) {
DbgPrint(" ");
}
for ( ; i < DfsDebugTraceIndent; i += 1) {
DbgPrint(" ");
}
DbgPrint(x,y);
}
#endif // DBG
//+---------------------------------------------------------------------------
// Function: DfsBugCheck, public
//
// Synopsis: Call KeBugCheck with DFS' constant
//
// Arguments: [pszmsg] -- message (DBG=1 only)
// [pszfile] -- filename (DBG=1 only)
// [line] -- line number (DBG=1 only)
//
// Returns: None
//
//----------------------------------------------------------------------------
#if DBG
VOID DfsBugCheck(CHAR *pszmsg, CHAR *pszfile, ULONG line)
{
PVOID CallersAddress, CallersCaller;
RtlGetCallersAddress(&CallersAddress, &CallersCaller);
DbgPrint("\nDFS: BugCheck in %s, line %u (%s)\n", pszfile, line, pszmsg);
KeBugCheckEx(DFS_FILE_SYSTEM, (ULONG_PTR)CallersAddress, (ULONG_PTR)pszmsg,
(ULONG_PTR)pszfile, line);
}
#else // DBG
VOID DfsBugCheck(VOID)
{
PVOID CallersAddress, CallersCaller;
RtlGetCallersAddress(&CallersAddress, &CallersCaller);
KeBugCheckEx(DFS_FILE_SYSTEM, (ULONG_PTR)CallersAddress, (ULONG_PTR)CallersCaller,
0, 0);
}
#endif // DBG
//+----------------------------------------------------------------------------
//
// Function: FillDebugException
//
// Synopsis: Captures the exception record into variables that we can
// look at.
//
// Arguments: [pep] -- Pointer to exception record.
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
#define CEXCEPTION_STACK 8
PEXCEPTION_RECORD DfsExceptionRecord;
PCONTEXT DfsExceptionContext;
ULONG DfsExceptionStack[CEXCEPTION_STACK];
VOID
FillDebugException(
PEXCEPTION_POINTERS pep)
{
if(pep != NULL) {
DfsExceptionRecord = pep->ExceptionRecord;
DfsExceptionContext = pep->ContextRecord;
}
}
//+-------------------------------------------------------------------
//
// Function: DfsExceptionFilter
//
// Synopsis: Decide if we should or should not handle an exception status
// that is being raised. Insert the status into the IrpContext
// and either indicate that we should handle the exception or
// BugCheck the system.
//
// Arguments: [IrpContext] -- IRP context for the request being processed.
// [ExceptionCode] -- Supplies the exception code to being checked.
//
// Returns: ULONG - returns EXCEPTION_EXECUTE_HANDLER or BugChecks
//
//--------------------------------------------------------------------
LONG
DfsExceptionFilter (
IN PIRP_CONTEXT IrpContext OPTIONAL,
IN NTSTATUS ExceptionCode,
IN PEXCEPTION_POINTERS ExceptionPointers OPTIONAL
) {
DfsDbgTrace(
0, DEBUG_TRACE_UNWIND, "DfsExceptionFilter %lx\n", ULongToPtr(ExceptionCode) );
FillDebugException( ExceptionPointers );
ASSERT(ExceptionCode != STATUS_ACCESS_VIOLATION);
ASSERTMSG(
"DfsExceptionFilter entered\n",
!(DfsDebugTraceLevel & DEBUG_TRACE_UNWIND));
//
// If there is not an irp context, we must have had insufficient resources.
//
if (!ARGUMENT_PRESENT( IrpContext )) {
ASSERT( ExceptionCode == STATUS_INSUFFICIENT_RESOURCES );
return EXCEPTION_EXECUTE_HANDLER;
}
IrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT;
if (IrpContext->ExceptionStatus == 0) {
if (FsRtlIsNtstatusExpected( ExceptionCode )) {
IrpContext->ExceptionStatus = ExceptionCode;
} else {
BugCheck( "DfsExceptionFilter: Unexpected exception" );
}
} else {
//
// We raised this code explicitly ourselves, so it had better be
// expected.
//
ASSERT( FsRtlIsNtstatusExpected( ExceptionCode ) );
}
return EXCEPTION_EXECUTE_HANDLER;
}
//+-------------------------------------------------------------------
//
// Function: DfsProcessException, public
//
// Synopsis: This routine processes an exception. It either completes
// the request with the saved exception status or it sends
// the request off to the Fsp.
//
// Arguments: [Irp] -- Supplies the IRP being processed
// [ExceptionCode] -- normalized exception status being handled
//
// Returns: NTSTATUS - Returns the results of either posting the Irp or the
// saved completion status.
//
//--------------------------------------------------------------------
NTSTATUS
DfsProcessException (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN NTSTATUS ExceptionCode
)
{
NTSTATUS Status;
DfsDbgTrace(0, Dbg, "DfsProcessException\n", 0);
//
// If there is not an irp context, we must have had insufficient resources.
//
if (!ARGUMENT_PRESENT( IrpContext )) {
ASSERT( ExceptionCode == STATUS_INSUFFICIENT_RESOURCES );
DfsCompleteRequest( IrpContext, Irp, ExceptionCode );
return ExceptionCode;
}
//
// Check if the status is verify required and if so then we
// either send the request off to the fsp or we complete
// the request with verify required.
//
if (ExceptionCode == STATUS_CANT_WAIT) {
Status = DfsFsdPostRequest( IrpContext, Irp );
} else {
//
// We got an error, so zero out the information field before
// completing the request if this was an input operation.
// Otherwise IopCompleteRequest will try to copy to the user's buffer.
//
if ((Irp->Flags & IRP_INPUT_OPERATION) != 0) {
Irp->IoStatus.Information = 0;
}
Status = IrpContext->ExceptionStatus;
DfsCompleteRequest( IrpContext, Irp, Status );
}
return Status;
}
//+-------------------------------------------------------------------
//
// Function: DfsCompleteRequest, public
//
// Synopsis: This routine completes a Irp
//
// Arguments: [IrpContext] - context record to be freed
// [Irp] - Supplies the Irp being processed
// [Status] - Supplies the status to complete the Irp with
//
// Returns: None.
//
//--------------------------------------------------------------------
VOID
DfsCompleteRequest_Real (
IN PIRP_CONTEXT IrpContext OPTIONAL,
IN PIRP Irp OPTIONAL,
IN NTSTATUS Status
) {
KIRQL PreviousIrql;
//
// If we have an Irp then complete the irp.
//
if (Irp != NULL) {
Irp->IoStatus.Status = Status;
// KeRaiseIrql( DISPATCH_LEVEL, &PreviousIrql );
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
// KeLowerIrql( PreviousIrql );
}
//
// Delete the Irp context.
//
if (IrpContext != NULL) {
DfsDeleteIrpContext( IrpContext );
}
return;
}