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.
359 lines
9.0 KiB
359 lines
9.0 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|