WriteFileEx

  BOOL WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpcr)    
  HANDLE hFile; /* file to write */
  LPVOID lpBuffer; /* address of buffer */
  DWORD nNumberOfBytesToWrite; /* bytes to write */
  LPOVERLAPPED lpOverlapped; /* contains offset */
  LPOVERLAPPED_COMPLETION_ROUTINE lpcr;    

The WriteFileEx function writes data to a file and reports its completion status asynchronously.

This function is available only in Win32/NT.

Parameters

hFile

Identifies the file to write to. The file handle must have been created with the FILE_FLAG_OVERLAPPED flag must have GENERIC_WRITE access to the file.

lpBuffer

Points to the buffer that contains the data to write to the file.

nNumberOfBytesToWrite

Specifies the number of bytes to write to the file. If nNumberOfBytesToWrite is zero, this function does nothing.

lpOverlapped

Points to an OVERLAPPED structure. This structure must remain valid for the entire duration of the write operation; it should not be a local variable if the calling application can return while the write operation is still pending.

The OVERLAPPED structure has the following form:

typedef struct _OVERLAPPED { /* o */

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

HANDLE hEvent;

} OVERLAPPED;

typedef OVERLAPPED *LPOVERLAPPED;

lpcr

Points to the completion routine that will be called when the write operation completes. For more information on the completion routine, see the description of the FileIOCompletionRoutine function.

Return Value

The return value is TRUE if the function was successful, or FALSE if an error occurred. Use the GetLastError function to obtain extended error information.

The function returns TRUE if the write operation has not yet completed. If the calling thread is in an alertable wait (using the SleepEx, WaitForSingleObjectEx or WaitForMultipleObjectsEx functions) when the write operation completes, the completion routine is called and the wait completes with a return value of WAIT_IO_COMPLETION.

If the calling thread is not in an alertable wait when the write operation completes, Win32 queues the completion routine call until the thread enters an alertable wait.

Comments

This function will fail if part of the file is locked by another process and the read overlaps the locked portion.

Example

The following code illustrates a possible flow for using callback completion asynchronous I/O.

Completion Routine:

VOID IoCompletionRoutine(DWORD dwErrorCode,

DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)

{

// If an I/O error occurred, display the error and then exit

if (dwErrorCode) {

printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",

dwErrorCode, lpOverlapped, lpOverlapped->hEvent);

ExitProcess(dwErrorCode);

}

LocalFree(lpOverlapped);

}

Main Worker Thread:

VOID IoWorkerThread(VOID)

{

HANDLE HandleVector[2];

DWORD CompletionStatus;

PIOREQUEST IoRequestPacket;

LPOVERLAPPED Overlapped;

BOOL IoOperationStatus;

HandleVector[0] = IoWorkerListLock;

HandleVector[1] = IoWorkerListSemaphore;

for(;;) {

// Do an alertable wait on the handle vector. Both objects

// becoming signaled at the same time means there is an

// I/O request in the queue, and the caller has exclusive

// access to the queue

CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector,

TRUE, INFINITE, TRUE);

// If the wait failed, error out

if (CompletionStatus == 0xFFFFFFFF) {

printf("FATAL WAIT ERROR %ld\n", GetLastError());

ExitProcess(1);

}

// If an I/O completion occurred, then wait for another

// I/O request or I/O completion

if (CompletionStatus != WAIT_IO_COMPLETION) {

// Wait was satisfied. We now have exclusive ownership of

// the I/O request queue, and there is something on the

// queue. Note that to insert something on the queue, the

// inserter gets the list lock (mutex), inserts an entry,

// signals the list semaphore, and finally releases the

// list lock.

IoRequestPacket = RemoveHeadList(&IoRequestList);

ReleaseMutex(IoWorkerListLock);

// Allocate an overlapped structure

Overlapped = LocalAlloc(LMEM_ZEROINIT,

sizeof(OVERLAPPED));

if (!Overlapped) {

printf("FATAL allocation error\n");

ExitProcess(1);

}

Overlapped->Offset = IoRequestPacket->Offset;

Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh;

Overlapped->hEvent =

IoRequestPacket->dwAdditionalIoContext;

if (IoRequestPacket->bRead) {

IoOperationStatus =

ReadFileEx(IoRequestPacket->hFile,

IoRequestPacket->lpBuffer,

IoRequestPacket->dwTransferCount,

Overlapped, IoCompletionRoutine);

}

else {

IoOperationStatus =

WriteFileEx(IoRequestPacket->hFile,

IoRequestPacket->lpBuffer,

IoRequestPacket->dwTransferCount,

Overlapped,

IoCompletionRoutine);

}

// Test to see if I/O was queued successfully

if (!IoOperationStatus) {

printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",

GetLastError(), Overlapped, Overlapped->hEvent);

ExitProcess(1);

}

// The I/O was successfully queued. Go back into the

// alertable wait waiting for I/O completion, or for

// more I/O requests.

}

}

}

See Also

ReadFileEx, SleepEx, WaitForMultipleObjectsEx, WaitForSingleObjectEx, WriteFile