Hard to solve.

I made a function(including ZwReadFile, internally) that read contents of
specification file(for example, c:\test.txt or d:\test.txt etc…).
By the way, If i try to call this function in the
FilemonHookRoutine(IRP_MJ_CREATE or IRP_MJ_WRITE, Dispatch-Routine of
“FileMon of sysinternlas.com”),
BSOD appears.
The problem is reentrancy.

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)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

break;
case IRP_MJ_WRITE:
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ReadFunction();
// call a function(read contents of a file)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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 reentrancy-problem?

Thanks for any suggestions!
Sincerely!

Chang Sung, Jung.

This is covered in the OSR FAQ here
http://www.osr.com/resources_ifsfaq.shtml

See Q34 and Q36.

— “Chang Sung, Jung.” wrote:
> I made a function(including ZwReadFile, internally)
> that read contents of
> specification file(for example, c:\test.txt or
> d:\test.txt etc…).
> By the way, If i try to call this function in the
> FilemonHookRoutine(IRP_MJ_CREATE or IRP_MJ_WRITE,
> Dispatch-Routine of
> “FileMon of sysinternlas.com”),
> BSOD appears.
> The problem is reentrancy.
>
> 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)
>
>
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>
> break;
> case IRP_MJ_WRITE:
>
>
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ReadFunction();
> // call a function(read contents of a file)
>
>
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>
> break;
> default:
> hookCompletion = LogRecord( TRUE, &seqNum,
> &dateTime, NULL,
> “%s\tUNKNOWN 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,
>
=== message truncated ===

__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com