Abnormal Problem!

I made a function(including ZwReadFile internally) that read contents of
specification file(for example, c:\test.txt).
This function acted well, without problem.

By the way, If i try to call this function in the
FilemonHookRoutine(Dispatch-Routine of “FileMon of sysinternlas.com”),
BSOD appears.
Finally, My computer(Windows 2000) downed.
Error code was “0X0000007F(0X0000008, 0X0000000, 0X0000000, 0X0000000)”,
UNEXPECTED_KERNEL_MODE_TRAP.
It was Double-Fault message.
Assemble-code(taken by debugging tool) was MOV EBP, ESP.

Why does this phenomenon happen?
How can i solve this problem.

Thanks for any suggestions!
Sincerely!
Chang Sung, Jung.


Source code is following.

FilemonHookRoutine

NTSTATUS
FilemonHookRoutine(
PDEVICE_OBJECT HookDevice,
IN PIRP Irp
)
{
PIO_STACK_LOCATION currentIrpStack =
IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PMOVE_FILE_DATA moveFile;
PQUERY_DIRECTORY queryDirectory;
PFILE_OBJECT FileObject;
PHOOK_EXTENSION hookExt;
LARGE_INTEGER dateTime;
LARGE_INTEGER perfTime;
PCHAR fullPathName = NULL;
BOOLEAN hookCompletion, createPath;
CHAR controlCodeBuffer[ERRORLEN];
CHAR attributeString[ERRORLEN];
CHAR optionString[ERRORLEN];
CHAR name[PROCNAMELEN];
ULONG i;
ANSI_STRING directoryFilter;
PCHAR queryFilter;
ULONG seqNum;
KIRQL oldirql;
// Extract the file object from the IRP
FileObject = currentIrpStack->FileObject;
// Point at the device extension, which contains information on which
// file system this IRP is headed for
hookExt = HookDevice->DeviceExtension;
// We note open cases so that when we query the file name
// we don’t ask the file system for the name (since it won’t
// have seen the file object yet).
if( currentIrpStack->MajorFunction == IRP_MJ_CREATE ||
currentIrpStack->MajorFunction == IRP_MJ_CREATE_NAMED_PIPE ||
currentIrpStack->MajorFunction == IRP_MJ_CREATE_MAILSLOT ) {
// Clear any existing fileobject/name association stored in the
// hash table
FilemonFreeHashEntry( FileObject );
createPath = TRUE;
} else if( currentIrpStack->MajorFunction == IRP_MJ_CLOSE ) {
// We treat close as a special case of create for name querying
// since calling into NTFS during a close can result in a
deadlock.
createPath = TRUE;
} else if( currentIrpStack->MajorFunction == IRP_MJ_CLEANUP &&
FileObject->Flags & FO_STREAM_FILE ) {
// Treat cleanup of stream file objects as special create case,
because
// querying them causes NTFS to screwup on NT 4
//
createPath = TRUE;
} else {
createPath = FALSE;
}
// Allocate a buffer and get the name only if we have to
if( FilterOn && hookExt->Hooked ) {

GETPATHNAME( createPath );
}
// Only log it if it passes the filter
if( hookExt->Hooked && fullPathName ) {
// If measuring absolute time go and get the timestamp.
KeQuerySystemTime( &dateTime );
perfTime = KeQueryPerformanceCounter( NULL );
// We want to watch this IRP complete
seqNum = (ULONG) -1;
hookCompletion = FALSE;
// Determine what function we’re dealing with
FilemonGetProcess( name );
switch( currentIrpStack->MajorFunction ) {
case IRP_MJ_CREATE:
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

ReadFunction(); // call a function(read contents of specification file)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
“%s\tIRP_MJ_CREATE\t%s\tAttributes:
%s Options: %s”,
name, fullPathName,
CreateAttributesString(
currentIrpStack->Parameters.Create.FileAttributes,

attributeString ),
CreateOptionsString(
currentIrpStack->Parameters.Create.Options,
optionString
));

//
// If its an open-by-id we free the hash entry now so that on
the next access to
// the file we’ll pick up the file’s real name.
//
if( currentIrpStack->Parameters.Create.Options &
FILE_OPEN_BY_FILE_ID ) {
FilemonFreeHashEntry( FileObject );
}
break;
default:
hookCompletion = LogRecord( TRUE, &seqNum, &dateTime, NULL,
“%s\t*UNKNOWN* 0x%X\t\t”, name,
currentIrpStack->MajorFunction );
break;
}
} else {
// We don’t care about this IRP’s completion
hookCompletion = FALSE;
// Do name processing for the sake of keeping the hash table
current
switch( currentIrpStack->MajorFunction ) {
case IRP_MJ_CLOSE:
// This fileobject/name association can be discarded now.
FilemonFreeHashEntry( FileObject );
break;
}
}
// Free the buffer if we have one
if( fullPathName && fullPathName != InsufficientResources ) {
ExFreeToNPagedLookasideList( &FullPathLookaside, fullPathName );
}
// Copy parameters down to next level in the stack for the driver
below us
*nextIrpStack = *currentIrpStack;
#if DBG
// If an unload isn’t in progress, we should register a completion
callback
// so that the IRP’s return status can be examined.
KeAcquireSpinLock( &CountMutex, &oldirql );
#endif
if( !UnloadInProgress && hookCompletion ) {
#if DBG
// Increment the outstanding IRP count since this IRP will be
headed
// for our completion routine
FilemonDriver->DriverUnload = NULL;
OutstandingIRPCount++;
DbgPrint((“+%d: %x\n”, OutstandingIRPCount, Irp ));;
#endif // DBG
//
// Grab the time stamp and Log it in the current stack location.
This
// is legal since the stack location is ours, and we’re done
looking at
// the parameters. This makes it easy to pass this to the
completion routine. The
// DiskPerf example in the NT DDK uses this trick.
//
currentIrpStack->Parameters.Read.ByteOffset = perfTime;
#if defined(IA64)
IoSetCompletionRoutine( Irp, FilemonHookDone, (PVOID) (ULONG_PTR)
seqNum, TRUE, TRUE, TRUE );
#else
IoSetCompletionRoutine( Irp, FilemonHookDone, (PVOID) seqNum,
TRUE, TRUE, TRUE );
#endif
} else {
// Set no completion routine
IoSetCompletionRoutine( Irp, FilemonHookDone, NULL, FALSE, FALSE,
FALSE );
}
#if DBG
KeReleaseSpinLock( &CountMutex, oldirql );
#endif
// Return the results of the call to the caller
return IoCallDriver( hookExt->FileSystem, Irp );
}

ReadFunction

VOID ReadFunction()
{
IO_STATUS_BLOCK ioStatus;
HANDLE ntFileHandle;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING fileNameUnicodeString;
WCHAR filename = L"\DosDevices\C:\test.txt";
NTSTATUS ntStatus;
FILE_STANDARD_INFORMATION eof;
char *FileBuffer = 0;
ULONG FileSize = 0;
RtlInitUnicodeString( &fileNameUnicodeString, filename );
InitializeObjectAttributes( &objectAttributes,
&fileNameUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
ntStatus = ZwOpenFile( &ntFileHandle,
SYNCHRONIZE | GENERIC_READ,
&objectAttributes,
&ioStatus,
0,
FILE_SYNCHRONOUS_IO_ALERT );
ntStatus = ZwQueryInformationFile(ntFileHandle, &ioStatus, (void*)&eof,
sizeof(eof), FileStandardInformation);
FileSize=eof.EndOfFile.LowPart;

FileBuffer=(char*)ExAllocatePool(NonPagedPool,eof.EndOfFile.LowPart+1);
((char*)(FileBuffer))[FileSize]=0; // make the buffer ASCIIZ
// ÆÄÀÏ ³»¿ë Àбâ
ZwReadFile(ntFileHandle,
NULL,
NULL,
NULL,
&ioStatus,
FileBuffer,
FileSize,
NULL,
NULL);
DbgPrint((“*****File Content = %s File Size = %d\n”, FileBuffer,
FileSize));
ZwClose(ntFileHandle);
ExFreePool(FileBuffer); // F should be malloc-ed!!
return 0;
}