Pass filename from precreate to post-create

I got the filename from Precreate. How do I pass it to post-create without using globals? My filename is a UNICODE_STRING.

Use the CompletionContext to pass from the PRE to the POST.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
>I got the filename from Precreate. How do I pass it to post-create without
>using globals? My filename is a UNICODE_STRING.
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4615 (20091117)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4615 (20091117)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Could I just do a RtlCopyMemory of the UNICODE_STRING into the completion context?

The completion context is a pointer that you can pass to the post-handler. Allocate any memory you need, copy whatever you need to that memory and pass the address of that memory in the CompletionContext pointer. In your post-handler use the memory however you need to and then free it.

If all you need is the name you can pass the pointer to the FLT_FILE_NAME_INFORMATION buffer you got in pre-create and release it in post create.

Just to add to Don’s reply, you need to take care of file name tunneling if
you are passing name from pre to post create.

Regards,
Ayush Gupta
AI Consulting.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Tuesday, November 17, 2009 11:04 PM
To: Windows File Systems Devs Interest List
Subject: Re:[ntfsd] Pass filename from precreate to post-create

Use the CompletionContext to pass from the PRE to the POST.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wrote in message news:xxxxx@ntfsd…
>I got the filename from Precreate. How do I pass it to post-create without
>using globals? My filename is a UNICODE_STRING.
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4615 (20091117)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature
database 4615 (20091117)


The message was checked by ESET NOD32 Antivirus.

http://www.eset.com


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

Think about what you are asking.
Let me give you a hint. Completion context is a double pointer.
That’s a great hint I am sure. :slight_smile:

Regards,
Ayush Gupta
AI Consulting.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: Tuesday, November 17, 2009 11:29 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Pass filename from precreate to post-create

Could I just do a RtlCopyMemory of the UNICODE_STRING into the completion
context?


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

Thanks Rick and Ayush.

Ayush, I did notice the pointer indirections. I am getting my filename to be NULL in post create. Could this be related to file name tunneling?

As regards file name tunneling, I didnt use FltGetFileNameInformation() in precreate. I got the name form the FLT_OBJECTS field. Can I use FltGetTunnelName() in postcreate irrespective of how I got the filename in the pre-operation?

Also, this is the code I have:

PreCreate()
{
UNICODE_STRING *TempName;
UNICODE_STRING FileName;
FileName.Length = FltObjects->FileObject->FileName.Length;
FileName.MaximumLength = FltObjects->FileObject->FileName.MaximumLength;
FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, max(FileName.Length, FileName.MaximumLength), ‘emaN’);
if (FileName.Buffer == NULL)
return -1;

RtlCopyUnicodeString(&FileName, &FltObjects->FileObject->FileName);

DbgPrint(“Precreate: FltObjects FileName with length and max len %S %x %x\n”, FltObjects->FileObject->FileName.Buffer,FltObjects->FileObject->FileName.Length,FltObjects->FileObject->FileName.MaximumLength);
DbgPrint(“Precreate: UNICODE FileName %S\n”, FileName.Buffer);

TempName = &FileName;
CompletionContext = &TempName;

DbgPrint(“Precreate: UNICODE CompletionContext %S\n”, ((PUNICODE_STRING)(*CompletionContext))->Buffer); //Filename looks good here

}

void PostCreate()
{
TempName = (PUNICODE_STRING)&CompletionContext;
DbgPrint(“Postcreate: UNICODE TempName length %x\n”, TempName->Length);
DbgPrint(“Postcreate: UNICODE TempName Maxlength %x\n”, TempName->MaximumLength);

//The lengths are NULL and so is the filename.
}

In your postCreate you want TempName = (PUNICODE_STRING) CompletionContext (leave out the &). Your current code is taking the address of CompletionContext not the value it contains.

Also, when using DbgPrint it is generally not safe to print a unicode string this way because it is not guaranteed to be null terminated. Use %wZ and pass the address of the UNICODE_STRING structure - DbgPrint(“PostCreate: UNICODE TempName = %wZ\n”, TempName); (where TempName is a PUNICODE_STRING).

Regarding the tunneled name - The FltGetTunneledName api takes a FLT_FILE_NAME_INFORMATION as input (not a UNICODE_STRING) so while you might get away with faking it I do not see any reason to do that. Just use FltGetFileNameInformation in the pre-create and pass the FLT_FILE_NAME_INFORMATION to the post-create rather than a unicode string (call FltReleaseFileNameInformation when you are done with it). This will be far safer and more supportable than trying to get the name from the file object (one example is open by file ID - your method will not get the correct name while FltGetFileNameInformation will).

Assigning TempName = (PUNICODE_STRING)COmpletionContext causes a crash.

Also, I didnt use the FltGetFileName Information() in precreate because I read in this forum that the option will slow things down.

I will revert back to it.

The crash is likely caused by the fact that the pointer passed in the CompletionContext points to a stack allocated memory. You put the name in the buffer allocated with ExAllocatexxx but the unicode string structure itself is on the stack in pre-create (and is gone by the time the post-create is called). Also, you set completion context to the address of the pointer to the name. The right way to do this is to allocate the entire unicode string structure, including enough buffer space fore the name and passing a pointer to the entire thing. But, since you are going to use FltGetFileNameInformation just set CompletionContext to the pointer returned for the name info

PreCreate
{
PFLT_FILE_NAME_INFORMATION pFileNameInfo = NULL; // Pointer to a pointer

ntStat = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&pFileNameInfo); // This returns the pointer

CompletionContext = pFileNameInfo; // Pass the pointer to postcreate.

}

PostCreate
{
PFLT_FILE_NAME_INFORMATION pFileNameInfo = CompletionContext;

I did what you suggested and I am still getting a crash when I try to print the name string in PostCreate (The pFileNameInfo->Name)

You will have to show the code and the dump info (!analyze -v from Windbg) to determine what is wrong.

The precreate() uses pvoid*completioncontext.

postcreate() uses pvoid completioncontext;

My system reboots automatically and I am using DbgView. Would I need to pipe the output to another computer then to capture the crash?

You need to connect via 1394, recommended, to a host running WinDbg. There
is nothing wrong with DebugView, unless you are afflicted with the
mis-guided foolishness that you can use DebugView without WinDbg because it
is “cheaper”. Granted, there are a few on this list that can and do use
DebugView without WinDbg, but I dinna believe, laddie, that ye are one of
them.

The personal opinion of
Gary G. Little

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: Friday, November 20, 2009 3:56 PM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Pass filename from precreate to post-create

The precreate() uses pvoid*completioncontext.

postcreate() uses pvoid completioncontext;

My system reboots automatically and I am using DbgView. Would I need to pipe
the output to another computer then to capture the crash?


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

__________ Information from ESET Smart Security, version of virus signature
database 4625 (20091120) __________

The message was checked by ESET Smart Security.

http://www.eset.com

__________ Information from ESET Smart Security, version of virus signature
database 4625 (20091120) __________

The message was checked by ESET Smart Security.

http://www.eset.com

Well i would just debug the dump file created by Windows.
You can configure the system to generate a dump file on crash.
Then you can debug this dump will using WinDbg.

You need 1394 if you want to do step debugging or put breakpoints!
Simple crashes like these can be debugged using the dump file.

Thanks Divya. I just used the memory.dmp like you suggested.

Here is the code and the related dump.

PreCreate(pvoid*completionContext…)
{
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;

status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&nameInfo );
if (!NT_SUCCESS( status )) {
return FLT_POSTOP_FINISHED_PROCESSING;
}

CompletionContext = (PVOID*)nameInfo;
DbgPrint(“Precreate: FileName with length and max len %S \n”, ((PFLT_FILE_NAME_INFORMATION)(CompletionContext))->Name.Buffer);

}

PostCreate(pvoid CompletionContext…)
{

PFLT_FILE_NAME_INFORMATION Name;
PFLT_FILE_NAME_INFORMATION tunnelName;

NTSTATUS status;

//Allocate tunnel name
tunnelName = ExAllocatePoolWithTag(NonPagedPool, sizeof(FLT_FILE_NAME_INFORMATION), ‘nuT’);
if (tunnelName == NULL)
return 1;

//Get Tunneled name
Name = (PFLT_FILE_NAME_INFORMATION)&CompletionContext;
DbgPrint(“Postcreate: Entered with FileName with length %S \n”, Name->Name.Buffer);

//Note: The above print doesnt print the right filename (it’s garbage)

status = FltGetTunneledName(Data, Name, &tunnelName);

//Code crashes here
DbgPrint(“Postcreate: FileName with length and max len %S \n”, tunnelName->Name.Buffer);
}

Here is the crash dump:

MODULE_NAME: scanner

FAULTING_MODULE: 804d7000 nt

DEBUG_FLR_IMAGE_TIMESTAMP: 4b0aad90

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at “0x%08lx” referenced memory at “0x%08lx”. The memory could not be “%s”.

FAULTING_IP:
scanner!ScannerPostCreate+51 [c:\winddk\6001.18001\src\filesys\minifilter\ittscanner\filter\scanner.c @ 672]
f6555905 ff700c push dword ptr [eax+0Ch]

TRAP_FRAME: f7034898 – (.trap 0xfffffffff7034898)
ErrCode = 00000000
eax=00000000 ebx=00000000 ecx=8052a700 edx=00000042 esi=861658a4 edi=8616584c
eip=f6555905 esp=f703490c ebp=f703491c iopl=0 nv up ei ng nz ac pe cy
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010297
scanner!ScannerPostCreate+0x51:
f6555905 ff700c push dword ptr [eax+0Ch] ds:0023:0000000c=???
Resetting default scope

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0x8E

LAST_CONTROL_TRANSFER: from 804fe507 to 804f9c37

STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
f7034460 804fe507 0000008e c0000005 f6555905 nt!KeBugCheckEx+0x1b
f7034828 80541075 f7034844 00000000 f7034898 nt!KeRaiseUserException+0xc29
f70348b4 806e4d43 f7034900 0000bb40 f703469c nt!Kei386EoiHelper+0x1d9
f703491c f7416fa1 8616584c f7034940 00000000 hal!HalClearSoftwareInterrupt+0x193
f7034984 f74193ea 001657f0 00000000 861657f0 fltmgr!FltRequestOperationStatusCallback+0x5cd
f7034998 f7419817 861657f0 86122e48 f70349d8 fltmgr!FltGetIrpName+0x57a
f70349a8 f7419ec5 864e15a0 86122e48 861657f0 fltmgr!FltGetIrpName+0x9a7
f70349d8 f7426153 f70349f8 00000000 00000000 fltmgr!FltGetIrpName+0x1055
f7034a14 804eeeb1 864e15a0 86122fd8 86122e48 fltmgr!FltProcessFileLock+0x21a5
f7034b04 805bdd10 8632cc68 00000000 862cc538 nt!IoBuildPartialMdl+0xed
f7034b7c 805ba398 00000000 f7034bbc 00000040 nt!NtMakePermanentObject+0x11b2
f7034bd0 80575de1 00000000 00000000 00000201 nt!ObOpenObjectByName+0xea
f7034d54 8054060c 00dbdac0 00dbda98 00dbdaec nt!NtDeleteFile+0x39b
f7034d70 f6f9954a 00000000 00000000 00000000 nt!KeReleaseInStackQueuedSpinLockFromDpcLevel+0xb74
f7034ddc 805450ce f6fa39c1 f6fa3040 00000000 rdbss+0x54a
f7034e20 bf818151 00004b48 00000000 f7034c94 nt!KiDispatchInterrupt+0x72e
f7034ea4 805347f1 e1aa8eb8 e1aa8ebc 865ba8f8 win32k!EngNineGrid+0x991
00000000 00000000 00000000 00000000 00000000 nt!ExReleaseResourceLite+0x8d

STACK_COMMAND: kb

FOLLOWUP_IP:
scanner!ScannerPostCreate+51 [c:\winddk\6001.18001\src\filesys\minifilter\ittscanner\filter\scanner.c @ 672]
f6555905 ff700c push dword ptr [eax+0Ch]

SYMBOL_STACK_INDEX: 0

SYMBOL_NAME: scanner!ScannerPostCreate+51

FOLLOWUP_NAME: MachineOwner

IMAGE_NAME: scanner.sys

BUCKET_ID: WRONG_SYMBOLS

Followup: MachineOwner

PostCreate(pvoid CompletionContext…)
{

PFLT_FILE_NAME_INFORMATION Name;
PFLT_FILE_NAME_INFORMATION tunnelName;

NTSTATUS status;

// You do not need to allocate memory for the name, The call returns a pointer to the name
// All you have to do is release the name when you are done (FltReleaseFileNameInformation).

//Allocate tunnel name
// tunnelName = ExAllocatePoolWithTag(NonPagedPool,
//sizeof(FLT_FILE_NAME_INFORMATION), ‘nuT’);
// if (tunnelName == NULL)
// return 1;

//Get Tunneled name
//
// Do not use &CompletionContext here - that gives you the address of the pointer, not what you
// want.

//Name = (PFLT_FILE_NAME_INFORMATION)&CompletionContext;

// Try this instead:
Name = (PFLT_FILE_NAME_INFORMATION) CompletionContext;
DbgPrint(“Postcreate: Entered with FileName with length %wZ \n”,
&Name->Name);

//Note: The above print doesnt print the right filename (it’s garbage) - because you got the pointer wrong. With these changes it should be correct.

status = FltGetTunneledName(Data, Name, &tunnelName);

//Code crashes here
DbgPrint(“Postcreate: FileName with length and max len %wZ\n”,
&tunnelName->Name);

// When you are done with the name:
FltReleaseFileNameInformation(tunnelName);
FltReleaseFileNameInformation(Name);

Rick,

Post create takes pvoid completioncontext.

So if we assigned
CompletionContext = (pvoid*) nameInfo in precreate(), we would have to use

namInfo= &CompletionContext in postcreate(),right?

If I use nameInfo = completionContext in postcreate(), my crash point is moving all over the place.

namInfo=&CompletionContext is not correct. This is basic C code. I have to suggest that you look at the sample driver code (minispy is a good one to look at) and see how the CompletionContext is used there.

Note that in precreate it is pvoid *CompletionContext (a pointer to a pointer) and you assign the pointer you want to pass to post create like this:

*CompletionContext = pName; (Where pName is PFLT_FILE_NAME_INFORMATION)

Quite honestly, if you are having this kind of problem understanding C then writing a filter driver may be a bit much to bite off.