ZwWriteFile never returns...

Hi Guys,

I have a strange problem.
In my KMDF driver, I open a file on demand, in an IOCTL context.
File opened with no problems.
I then (in the same context), try to write just 128 bytes to that file, using ZwWriteFile.
The bytes are written (I see them when I open the file with notepad), but the ZwWriteFile call does not return, and hangs forever.
This is not sporadic, it occurs every time.
Can you guess what the problem is?
Here is my call to ZwCreateFile:

==============================

theAccessMode = FILE_APPEND_DATA | SYNCHRONIZE;

res = ZwCreateFile((PHANDLE)FileHandlePtr,
theAccessMode,
&attr,
&statusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);

===================================

And here is my call to ZwWriteFile:

===================================
offset.HighPart = -1;
offset.LowPart = FILE_WRITE_TO_END_OF_FILE;

res = ZwWriteFile((HANDLE)theFileHandle,
NULL,
NULL,
NULL,
&statusBlock,
(PVOID)writeBuffer,
(ULONG)writeBufferSize,
&offset,
NULL);

==========================

I verified that both Create and Write are in PASSIVE_LEVEL.

What am I missing?

Thanks!

You cannot use the same theFileHandle in both ZwCreateFile and ZwWriteFile
because you pbably declared:

HANDLE theFileHandle;
You should call ZwCreateFile(&theFileHandle, … ) and the use
theFileHandle

Regards,
Gabriel.
www.kasardia.com

On Wed, Oct 19, 2016 at 5:10 PM, wrote:

> Hi Guys,
>
> I have a strange problem.
> In my KMDF driver, I open a file on demand, in an IOCTL context.
> File opened with no problems.
> I then (in the same context), try to write just 128 bytes to that file,
> using ZwWriteFile.
> The bytes are written (I see them when I open the file with notepad), but
> the ZwWriteFile call does not return, and hangs forever.
> This is not sporadic, it occurs every time.
> Can you guess what the problem is?
> Here is my call to ZwCreateFile:
>
> ==============================
>
> theAccessMode = FILE_APPEND_DATA | SYNCHRONIZE;
>
> res = ZwCreateFile((PHANDLE)FileHandlePtr,
> theAccessMode,
> &attr,
> &statusBlock,
> NULL,
> FILE_ATTRIBUTE_NORMAL,
> FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
> FILE_OPEN_IF,
> FILE_NON_DIRECTORY_FILE | FILE_WRITE_THROUGH |
> FILE_SYNCHRONOUS_IO_NONALERT,
> NULL,
> 0);
>
> ===================================
>
> And here is my call to ZwWriteFile:
>
> ===================================
> offset.HighPart = -1;
> offset.LowPart = FILE_WRITE_TO_END_OF_FILE;
>
> res = ZwWriteFile((HANDLE)theFileHandle,
> NULL,
> NULL,
> NULL,
> &statusBlock,
> (PVOID)writeBuffer,
> (ULONG)writeBufferSize,
> &offset,
> NULL);
>
> ==========================
>
> I verified that both Create and Write are in PASSIVE_LEVEL.
>
> What am I missing?
>
> Thanks!
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
>


Bercea. G.</http:></http:>

Thanks, but that is not the problem. The parameter to ZwCreateFile is a PHANDLE FileHandlePtr,

and then I keep the handle in: HANDLE theFileHandle = *FileHandlePtr;

and pass it as a parameter to ZwWriteFile.

The File writes used to work (I checked them) when I didn’t use offset parameter (I needed then only to append to the end of file). I now need to (occasionally) write to a particular offset in the file, so I use the offset parameter. But even a simple write to the beginning of a new file hangs…

I tried to change the access mode to GENERIC_ALL (FILE_ALL_ACCESS) but still got the same result.

If you have WinDbg attached, try breaking in and looking at the call
stack. Are you processing IO in your KMDF driver? Maybe inadvertently
blocking the paging IO?

The notepad test shows that the bytes were written to cache but since
you have FILE_WRITE_THROUGH it will push the bytes through to disk
before completing the request.

Pete


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

------ Original Message ------
From: xxxxx@tandemg.com
To: “Windows System Software Devs Interest List”
Sent: 10/19/2016 9:10:25 AM
Subject: [ntdev] ZwWriteFile never returns…

>Hi Guys,
>
>I have a strange problem.
>In my KMDF driver, I open a file on demand, in an IOCTL context.
>File opened with no problems.
>I then (in the same context), try to write just 128 bytes to that file,
>using ZwWriteFile.
>The bytes are written (I see them when I open the file with notepad),
>but the ZwWriteFile call does not return, and hangs forever.
>This is not sporadic, it occurs every time.
>Can you guess what the problem is?
>Here is my call to ZwCreateFile:
>
>==============================
>
> theAccessMode = FILE_APPEND_DATA | SYNCHRONIZE;
>
> res = ZwCreateFile((PHANDLE)FileHandlePtr,
> theAccessMode,
> &attr,
> &statusBlock,
> NULL,
> FILE_ATTRIBUTE_NORMAL,
> FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
> FILE_OPEN_IF,
> FILE_NON_DIRECTORY_FILE | FILE_WRITE_THROUGH |
>FILE_SYNCHRONOUS_IO_NONALERT,
> NULL,
> 0);
>
>===================================
>
>And here is my call to ZwWriteFile:
>
>===================================
> offset.HighPart = -1;
> offset.LowPart = FILE_WRITE_TO_END_OF_FILE;
>
> res = ZwWriteFile((HANDLE)theFileHandle,
> NULL,
> NULL,
> NULL,
> &statusBlock,
> (PVOID)writeBuffer,
> (ULONG)writeBufferSize,
> &offset,
> NULL);
>
>==========================
>
>I verified that both Create and Write are in PASSIVE_LEVEL.
>
>What am I missing?
>
>Thanks!
>
>—
>NTDEV is sponsored by OSR
>
>Visit the list online at:
>http:
>
>MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>software drivers!
>Details at http:
>
>To unsubscribe, visit the List Server section of OSR Online at
>http:</http:></http:></http:>

Thanks Peter, I will try to break into a WinDBG session, and post here the call stack.

By the way, when I previously tested successful file writes, I used a user application, which fired an IOCTL, and then the driver created a dedicated system thread (guaranteed to be PASSIVE_LEVEL…), and call the writes in that thread context.

I now call the writes in the context of the process that issued the IOCTL, although I verified that the IRQL is PASSIVE_LEVEL. Could there still be an issue?

xxxxx@tandemg.com wrote:

Thanks, but that is not the problem. The parameter to ZwCreateFile is a PHANDLE FileHandlePtr,

and then I keep the handle in: HANDLE theFileHandle = *FileHandlePtr;

and pass it as a parameter to ZwWriteFile.

But that’s wrong, don’t you see? This is a fundamental C mistake. When
an API asks for a PHANDLE, it is up to you to figure out whether it is
an input parameter that wants a pointer passed by value, or an output
parameter passed by reference. In this case, it is the latter. You are
not supposed to pass it a PHANDLE, You are supposed to pass it the
address of a HANDLE, which the API will fill in. If you do this:

PHANDLE FileHandlePtr;
ZwCreateFile( FileHandlePtr,

That is a recipe for disaster. FileHandlePtr will contain some random
value, but ZwCreateFile believes you have given it the address of a
place where it can store the handle. If the value happens to be a valid
address, your code will appear to work, but your handle is stored in
memory that doesn’t belong to you, and might evaporate at any time.

Gabriel was exactly correct. The proper calling sequence is:

HANDLE theFileHandle;
ZwCreateFile( &theFileHandle, …
ZwWriteFile( theFileHandle, …


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Sorry :). I was not precise, because I know this is not the problem (but I forgot what a pedantic bunch you guys are…).

What I REALLY do in my code (but couldn’t be bothered to write before), is declare wrapper functions for ZwCreateFile – DrvOpenFile(PHANDLE fileHandlePtr,…) and ZwWriteFile — DrvWriteFile(HANDLE fileHandle,…) . In the driver code I have a member variable HANDLE m_FileHandle = NULL (initially).

When I create and open the file, I call DrvOpenFile(&m_FileHandle,…) and when I write to the file I call DrvWriteFile(m_FileHandle,…).

I will remember to be more accurate in the future… :slight_smile:

Thanks.

Depending on sync scope and execution level specified, APCs may be disabled when calling your queue io processing routines

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@tandemg.com
Sent: Wednesday, October 19, 2016 9:57 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwWriteFile never returns…

Sorry :). I was not precise, because I know this is not the problem (but I forgot what a pedantic bunch you guys are…).

What I REALLY do in my code (but couldn’t be bothered to write before), is declare wrapper functions for ZwCreateFile – DrvOpenFile(PHANDLE fileHandlePtr,…) and ZwWriteFile — DrvWriteFile(HANDLE fileHandle,…) . In the driver code I have a member variable HANDLE m_FileHandle = NULL (initially).

When I create and open the file, I call DrvOpenFile(&m_FileHandle,…) and when I write to the file I call DrvWriteFile(m_FileHandle,…).

I will remember to be more accurate in the future… :slight_smile:

Thanks.


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

These are the definitions in my driver:

attributes.ExecutionLevel = WdfExecutionLevelPassive; // I changed this from the default I"inherited", to ensure that all IO processing is done in PASSIVE_LEVEL.

attributes.SynchronizationScope = WdfSynchronizationScopeDevice; // This remained unchanged (from KMDF sample…).

Does this mean I have to delegate File writes to a separate thread? What will be the implications if I change the Synch scope?

Thanks.

xxxxx@tandemg.com wrote:

These are the definitions in my driver:

attributes.ExecutionLevel = WdfExecutionLevelPassive; // I changed this from the default I"inherited", to ensure that all IO processing is done in PASSIVE_LEVEL.

attributes.SynchronizationScope = WdfSynchronizationScopeDevice; // This remained unchanged (from KMDF sample…).

Some may disagree, but I have found SynchronizationScope to be more of a
curse than a blessing. It is very easy to oversynchronize yourself,
resulting in unexpected hangs. I am now in the habit of setting
WdfSynchronizationScopeNone, and dealing with the individual sync needs
as they arise.

Does this mean I have to delegate File writes to a separate thread? What will be the implications if I change the Synch scope?

It means you have to take a little time to think about where your driver
accesses shared state, and provide finer-grained protection on a
case-by-case basis. For me, personally, I have found that to be a much
more successful strategy.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts wrote:

Some may disagree, but I have found SynchronizationScope to
be more of a curse than a blessing. It is very easy to oversynchronize
yourself, resulting in unexpected hangs.

Glug, glug, glug…

Try and see if you strip the FILE_WRITE_THROUGH flag the write returns or
not and play around that if that is the case.

Gabriel
www.kasardia.com

On Wed, Oct 19, 2016 at 9:25 PM, wrote:

> Tim Roberts wrote:
>
> > Some may disagree, but I have found SynchronizationScope to
> > be more of a curse than a blessing. It is very easy to oversynchronize
> > yourself, resulting in unexpected hangs.
>
> Glug, glug, glug…
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
>


Bercea. G.</http:></http:>

Thanks Gabriel,

I tried removing the FILE_WRITE_THROUGH, but it had no effect.

I then moved the ZwWriteFile to a dedicated (System) thread, and it works fine.

I will use this approach, since I have no time to investigate further.

Can anybody think of a good reason why File Writes are blocked in the I/O processing thread?

It seems like a fairly common place scenario…

Thanks again for the helpful inputs.

As Doron said, “Depending on sync scope and execution level specified, APCs
may be disabled when calling your queue io processing routines”

Calling the Zw I/O APIs requires that APCs are enabled so that the I/O
completion notification can be delivered to your thread. Try calling
KeAreAllApsDisabled prior to the Zw call and see what you get.

There are ultimately two choices:

  1. Remove the synchronization scope

  2. Post the work to a work item or dedicated worker thread

See the following article about synchronization scope if you want more
guidance about whether or not you actually want to use it:

https://www.osr.com/nt-insider/2014-issue3/understanding-sync-scope-wdf-drivers/

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntdev…

Thanks Gabriel,

I tried removing the FILE_WRITE_THROUGH, but it had no effect.

I then moved the ZwWriteFile to a dedicated (System) thread, and it works
fine.

I will use this approach, since I have no time to investigate further.

Can anybody think of a good reason why File Writes are blocked in the I/O
processing thread?

It seems like a fairly common place scenario…

Thanks again for the helpful inputs.