Problems in IRP_MJ_CREATE

First of all, thanks for all the previous help!

My minifilter is similar to simrep, but with one important difference. I am now battling with an issue in my PreCreate callback. For my code to work, I need to check the incoming filename for a match against a known filename. If it matches, I replace the name and redirect it (REPARSE). However, the complication is that I need to first check if the incoming filename exists (if it doesn’t already exist, I just pass through).

To check if the file already exists, I am using FltCreateFile, but I am starting to wonder if it is illegal to use this call from within the IRP_MJ_CREATE PreCreate callback to create the same file that originated the callback? I get a bug check, with not a lot of info, e.g:

BAD_POOL_HEADER (19)

STACK_TEXT:
a4c919cc 8054b583 00000019 00000020 e96080c8 nt!KeBugCheckEx+0x1b
a4c91a1c 8058338a e96080d0 00000000 89cda018 nt!ExFreePoolWithTag+0x2a3
a4c91b04 805bf450 89cda030 00000000 88c55f30 nt!IopParseDevice+0xba2
a4c91b7c 805bb9dc 00000000 a4c91bbc 00000040 nt!ObpLookupObjectName+0x53c
a4c91bd0 80576fc7 00000000 00000000 80513a01 nt!ObOpenObjectByName+0xea
a4c91d54 8054162c 00122d88 00122d60 00122db4 nt!NtQueryAttributesFile+0xf1
a4c91d54 7c90e4f4 00122d88 00122d60 00122db4 nt!KiFastCallEntry+0xfc
WARNING: Frame IP not in any known module. Following frames may be wrong.
00122db4 00000000 00000000 00000000 00000000 0x7c90e4f4

If I use a different filename, no bug check.

Any advice as to what I could be doing wrong, or some way to accomplish this?

Thanks!

Without any code it’s difficult to guess what’s wrong.

On another note, may I suggest you first test if your file match succeeds
and then check if your file exists as a pattern match routine is likely to
be much faster than going through the file system.

//Daniel

wrote in message news:xxxxx@ntfsd…
> First of all, thanks for all the previous help!
>
> My minifilter is similar to simrep, but with one important difference. I
> am now battling with an issue in my PreCreate callback. For my code to
> work, I need to check the incoming filename for a match against a known
> filename. If it matches, I replace the name and redirect it (REPARSE).
> However, the complication is that I need to first check if the incoming
> filename exists (if it doesn’t already exist, I just pass through).
>
> To check if the file already exists, I am using FltCreateFile, but I am
> starting to wonder if it is illegal to use this call from within the
> IRP_MJ_CREATE PreCreate callback to create the same file that originated
> the callback? I get a bug check, with not a lot of info, e.g:
>
> BAD_POOL_HEADER (19)
>
> STACK_TEXT:
> a4c919cc 8054b583 00000019 00000020 e96080c8 nt!KeBugCheckEx+0x1b
> a4c91a1c 8058338a e96080d0 00000000 89cda018 nt!ExFreePoolWithTag+0x2a3
> a4c91b04 805bf450 89cda030 00000000 88c55f30 nt!IopParseDevice+0xba2
> a4c91b7c 805bb9dc 00000000 a4c91bbc 00000040 nt!ObpLookupObjectName+0x53c
> a4c91bd0 80576fc7 00000000 00000000 80513a01 nt!ObOpenObjectByName+0xea
> a4c91d54 8054162c 00122d88 00122d60 00122db4 nt!NtQueryAttributesFile+0xf1
> a4c91d54 7c90e4f4 00122d88 00122d60 00122db4 nt!KiFastCallEntry+0xfc
> WARNING: Frame IP not in any known module. Following frames may be wrong.
> 00122db4 00000000 00000000 00000000 00000000 0x7c90e4f4
>
> If I use a different filename, no bug check.
>
> Any advice as to what I could be doing wrong, or some way to accomplish
> this?
>
> Thanks!
>

Yes, you can call FltCreateFile to open FileObject->FileName.

When do you see this bugcheck? Is it when you return STATUS_REPARSE? What
buffer does ExFreePoolWithTag free? Maybe you can post code sample how you
reparse the filename.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@grammatech.com
Sent: 27. b?ezna 2009 19:05
To: Windows File Systems Devs Interest List
Subject: [ntfsd] Problems in IRP_MJ_CREATE

First of all, thanks for all the previous help!

My minifilter is similar to simrep, but with one important difference. I am
now battling with an issue in my PreCreate callback. For my code to work, I
need to check the incoming filename for a match against a known filename. If
it matches, I replace the name and redirect it (REPARSE). However, the
complication is that I need to first check if the incoming filename exists
(if it doesn’t already exist, I just pass through).

To check if the file already exists, I am using FltCreateFile, but I am
starting to wonder if it is illegal to use this call from within the
IRP_MJ_CREATE PreCreate callback to create the same file that originated
the callback? I get a bug check, with not a lot of info, e.g:

BAD_POOL_HEADER (19)

STACK_TEXT:
a4c919cc 8054b583 00000019 00000020 e96080c8 nt!KeBugCheckEx+0x1b
a4c91a1c 8058338a e96080d0 00000000 89cda018 nt!ExFreePoolWithTag+0x2a3
a4c91b04 805bf450 89cda030 00000000 88c55f30 nt!IopParseDevice+0xba2
a4c91b7c 805bb9dc 00000000 a4c91bbc 00000040 nt!ObpLookupObjectName+0x53c
a4c91bd0 80576fc7 00000000 00000000 80513a01 nt!ObOpenObjectByName+0xea
a4c91d54 8054162c 00122d88 00122d60 00122db4 nt!NtQueryAttributesFile+0xf1
a4c91d54 7c90e4f4 00122d88 00122d60 00122db4 nt!KiFastCallEntry+0xfc
WARNING: Frame IP not in any known module. Following frames may be wrong.
00122db4 00000000 00000000 00000000 00000000 0x7c90e4f4

If I use a different filename, no bug check.

Any advice as to what I could be doing wrong, or some way to accomplish
this?

Thanks!


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Here is my PreCreate code, with all return code checks, most comments, and debugging output removed for brevity:

status = FltGetFileNameInformation( Cbd,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&nameInfo );

status = FltParseFileNameInformation( nameInfo );

// Check if we need to redirect this open to another file instead
if (nameInfo->FinalComponent.Length && HookedFileName(&nameInfo->FinalComponent))
{
// Yes, it matches
ACCESS_MASK DesiredAccess = Cbd->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
ULONG FileAttributes = Cbd->Iopb->Parameters.Create.FileAttributes;
ULONG ShareAccess = Cbd->Iopb->Parameters.Create.ShareAccess;
ULONG CreateDisposition = (Cbd->Iopb->Parameters.Create.Options >> 24) & 0xFF;
ULONG CreateOptions = Cbd->Iopb->Parameters.Create.SecurityContext->FullCreateOptions;

// If this is a network query open we can’t cant return STATUS_REPARSE because its FastIO.
// So we will return FLT_PREOP_DISALLOW_FASTIO, so it will be reissued down the slow path.
if (Cbd->Iopb->MajorFunction == IRP_MJ_NETWORK_QUERY_OPEN)
{
callbackStatus = FLT_PREOP_DISALLOW_FASTIO;
goto mfPreCreateCleanup;
}

// Construct a check file name, to check if the file exists
checkFileName.MaximumLength = checkFileName.Length = nameInfo->Name.Length;
status = mfAllocateUnicodeString( &checkFileName );

// init the object attributes with the file name, etc.
InitializeObjectAttributes(&oa,
&checkFileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL);

status = FltCreateFile( CommPortData.Filter,
Globals.FilterInstance,
&fileHandle,
DesiredAccess,
&oa,
&ioStatus,
(PLARGE_INTEGER) NULL,
FileAttributes,
ShareAccess,
CreateDisposition,
CreateOptions,
NULL,
0L,
0L );

static NTSTATUS
mfAllocateUnicodeString (PUNICODE_STRING String)
{

PAGED_CODE();

String->Buffer = ExAllocatePoolWithTag( NonPagedPool,
String->MaximumLength,
mf_STRING_TAG );

if (String->Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}

String->Length = 0;
return STATUS_SUCCESS;
}

Ah, more info.

It appears it is not the FltFileCreate function that causes the blue screen. But it is the case of a match, with FltFileCreate succeeding (the case I want), the ReplaceFileName function appears to be bad. I am using the sample simrep replace code, but my input replacement filename must be bad. If I simply comment out that call, no blue screen.

I will work on it and get back to you.

Instead original CreateDisposition value, please use FILE_OPEN.
You can comment out some parts of your code to find a bug - since the
problem is during memory freeing in IopParseDevice, you can find out if it
frees filename’s buffer or something else. It seems you have some troubles
with string buffers.

Looking at your dump, you can use these commands to know more about the
crash:
!pool e96080d0
db e96080d0

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@grammatech.com
Sent: 27. b?ezna 2009 19:42
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Problems in IRP_MJ_CREATE

Here is my PreCreate code, with all return code checks, most comments, and
debugging output removed for brevity:

status = FltGetFileNameInformation( Cbd,
FLT_FILE_NAME_OPENED |

FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&nameInfo );

status = FltParseFileNameInformation( nameInfo );

// Check if we need to redirect this open to another file instead
if (nameInfo->FinalComponent.Length &&
HookedFileName(&nameInfo->FinalComponent))
{
// Yes, it matches
ACCESS_MASK DesiredAccess =
Cbd->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
ULONG FileAttributes =
Cbd->Iopb->Parameters.Create.FileAttributes;
ULONG ShareAccess = Cbd->Iopb->Parameters.Create.ShareAccess;
ULONG CreateDisposition = (Cbd->Iopb->Parameters.Create.Options

> 24) & 0xFF;
ULONG CreateOptions =
Cbd->Iopb->Parameters.Create.SecurityContext->FullCreateOptions;

// If this is a network query open we can’t cant return
STATUS_REPARSE because its FastIO.
// So we will return FLT_PREOP_DISALLOW_FASTIO, so it will be
reissued down the slow path.
if (Cbd->Iopb->MajorFunction == IRP_MJ_NETWORK_QUERY_OPEN)
{
callbackStatus = FLT_PREOP_DISALLOW_FASTIO;
goto mfPreCreateCleanup;
}

// Construct a check file name, to check if the file exists
checkFileName.MaximumLength = checkFileName.Length =
nameInfo->Name.Length;
status = mfAllocateUnicodeString( &checkFileName );

// init the object attributes with the file name, etc.
InitializeObjectAttributes(&oa,
&checkFileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL);

status = FltCreateFile( CommPortData.Filter,
Globals.FilterInstance,
&fileHandle,
DesiredAccess,
&oa,
&ioStatus,
(PLARGE_INTEGER) NULL,
FileAttributes,
ShareAccess,
CreateDisposition,
CreateOptions,
NULL,
0L,
0L );

static NTSTATUS
mfAllocateUnicodeString (PUNICODE_STRING String)
{

PAGED_CODE();

String->Buffer = ExAllocatePoolWithTag( NonPagedPool,
String->MaximumLength,
mf_STRING_TAG );

if (String->Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}

String->Length = 0;
return STATUS_SUCCESS;
}


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Found the problem. There is a bug in the simrep.c sample code which I used:

SimRepReplaceFileObjectName()

// If the NewFileName fits inside the FileObject’s current
// buffer then we use the existing buffer. Otherwise we
// allocate our own buffer and free the existing one.
//

if ((FileObject->FileName.MaximumLength >= sizeof(WCHAR)) &&

// THE FOLLOWING LINE SHOULD BE “<”, NOT “>”

(FileObject->FileName.MaximumLength - sizeof(WCHAR) > FileNameLength)) {

//
// There is not enough room in the existing buffer.
// Lets go ahead and allocate a new buffer.