I made a function(including ZwReadFile internally) that read contents of
specification file(for example, c:\test.txt or d:\test.txt).
By the way, If i try to call this function in the
FilemonHookRoutine(Dispatch-Routine of “FileMon of sysinternlas.com”),
BSOD appears.
The problem is reentrancy.
My source code is following.
FilemonHookRoutine of Filemon(sysinternals.com)
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 a 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( 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 );
}
*nextIrpStack = *currentIrpStack;
#if DBG
KeAcquireSpinLock( &CountMutex, &oldirql );
#endif
if( !UnloadInProgress && hookCompletion ) {
#if DBG
FilemonDriver->DriverUnload = NULL;
OutstandingIRPCount++;
DbgPrint((“+%d: %x\n”, OutstandingIRPCount, Irp ));; #endif // DBG
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;
}
End of source code.
How can i solve this problem?
Thanks for any suggestions!
Sincerely!
Chang Sung, Jung.