[KERNEL32]: Format, comment, annotate, cleanup the I/O completion APIs.

svn path=/trunk/; revision=55793
This commit is contained in:
Alex Ionescu 2012-02-21 21:31:01 +00:00
parent b43c3d21c0
commit d363c616d6

View file

@ -13,164 +13,160 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define NANOS_TO_100NS(nanos) (((LONGLONG)(nanos)) / 100)
#define MICROS_TO_100NS(micros) (((LONGLONG)(micros)) * NANOS_TO_100NS(1000))
#define MILLIS_TO_100NS(milli) (((LONGLONG)(milli)) * MICROS_TO_100NS(1000))
/* /*
* @implemented * @implemented
*/ */
HANDLE HANDLE
WINAPI WINAPI
CreateIoCompletionPort( CreateIoCompletionPort(IN HANDLE FileHandle,
HANDLE FileHandle, IN HANDLE ExistingCompletionPort,
HANDLE ExistingCompletionPort, IN ULONG_PTR CompletionKey,
ULONG_PTR CompletionKey, IN DWORD NumberOfConcurrentThreads)
DWORD NumberOfConcurrentThreads
)
{ {
HANDLE CompletionPort = NULL; NTSTATUS Status;
NTSTATUS errCode; HANDLE NewPort;
FILE_COMPLETION_INFORMATION CompletionInformation; FILE_COMPLETION_INFORMATION CompletionInformation;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
if ( FileHandle == INVALID_HANDLE_VALUE && ExistingCompletionPort != NULL ) /* Check if this is a new port */
{ NewPort = ExistingCompletionPort;
SetLastError(ERROR_INVALID_PARAMETER); if (!ExistingCompletionPort)
return FALSE; {
} /* Create it */
Status = NtCreateIoCompletion(&NewPort,
IO_COMPLETION_ALL_ACCESS,
NULL,
NumberOfConcurrentThreads);
if (!NT_SUCCESS(Status))
{
/* Convert error and fail */
BaseSetLastNTError(Status);
return FALSE;
}
}
if ( ExistingCompletionPort != NULL ) /* Check if no actual file is being associated with the completion port */
{ if (FileHandle == INVALID_HANDLE_VALUE)
CompletionPort = ExistingCompletionPort; {
} /* Was there a port already associated? */
else if (ExistingCompletionPort)
{ {
/* You are not allowed using an old port and dropping the handle */
NewPort = NULL;
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
}
}
else
{
/* We have a file handle, so associated it with this completion port */
CompletionInformation.Port = NewPort;
CompletionInformation.Key = (PVOID)CompletionKey;
Status = NtSetInformationFile(FileHandle,
&IoStatusBlock,
&CompletionInformation,
sizeof(FILE_COMPLETION_INFORMATION),
FileCompletionInformation);
if (!NT_SUCCESS(Status))
{
/* Convert the error code and close the newly created port, if any */
BaseSetLastNTError(Status);
if (!ExistingCompletionPort) NtClose(NewPort);
return FALSE;
}
}
errCode = NtCreateIoCompletion(&CompletionPort, /* Return the newly created port, if any */
IO_COMPLETION_ALL_ACCESS, return NewPort;
NULL,//ObjectAttributes
NumberOfConcurrentThreads);
if (!NT_SUCCESS(errCode) )
{
BaseSetLastNTError (errCode);
return FALSE;
}
}
if ( FileHandle != INVALID_HANDLE_VALUE )
{
CompletionInformation.Port = CompletionPort;
CompletionInformation.Key = (PVOID)CompletionKey;
errCode = NtSetInformationFile(FileHandle,
&IoStatusBlock,
&CompletionInformation,
sizeof(FILE_COMPLETION_INFORMATION),
FileCompletionInformation);
if ( !NT_SUCCESS(errCode) )
{
if ( ExistingCompletionPort == NULL )
{
NtClose(CompletionPort);
}
BaseSetLastNTError (errCode);
return FALSE;
}
}
return CompletionPort;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
GetQueuedCompletionStatus( GetQueuedCompletionStatus(IN HANDLE CompletionHandle,
HANDLE CompletionHandle, IN LPDWORD lpNumberOfBytesTransferred,
LPDWORD lpNumberOfBytesTransferred, OUT PULONG_PTR lpCompletionKey,
PULONG_PTR lpCompletionKey, OUT LPOVERLAPPED *lpOverlapped,
LPOVERLAPPED *lpOverlapped, IN DWORD dwMilliseconds)
DWORD dwMilliseconds
)
{ {
NTSTATUS errCode; NTSTATUS Status;
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
ULONG_PTR CompletionKey; ULONG_PTR CompletionKey;
LARGE_INTEGER Time; LARGE_INTEGER Time;
PLARGE_INTEGER TimePtr; PLARGE_INTEGER TimePtr;
if (!lpNumberOfBytesTransferred || !lpCompletionKey || !lpOverlapped) /* Convert the timeout and then call the native API */
{ TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);
SetLastError(ERROR_INVALID_PARAMETER); Status = NtRemoveIoCompletion(CompletionHandle,
return FALSE;
}
/* Convert the timeout */
TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);
errCode = NtRemoveIoCompletion(CompletionHandle,
(PVOID*)&CompletionKey, (PVOID*)&CompletionKey,
(PVOID*)lpOverlapped, (PVOID*)lpOverlapped,
&IoStatus, &IoStatus,
TimePtr); TimePtr);
if (!(NT_SUCCESS(Status)) || (Status == STATUS_TIMEOUT))
{
/* Clear out the overlapped output */
*lpOverlapped = NULL;
if (!NT_SUCCESS(errCode) || errCode == STATUS_TIMEOUT) { /* Check what kind of error we got */
*lpOverlapped = NULL; if (Status == STATUS_TIMEOUT)
{
/* Timeout error is set directly since there's no conversion */
SetLastError(WAIT_TIMEOUT);
}
else
{
/* Any other error gets converted */
BaseSetLastNTError(Status);
}
if(errCode == STATUS_TIMEOUT) /* This is a failure case */
SetLastError(WAIT_TIMEOUT); return FALSE;
else }
BaseSetLastNTError(errCode);
return FALSE; /* Write back the output parameters */
} *lpCompletionKey = CompletionKey;
*lpNumberOfBytesTransferred = IoStatus.Information;
*lpCompletionKey = CompletionKey; /* Check for error */
*lpNumberOfBytesTransferred = IoStatus.Information; if (!NT_SUCCESS(IoStatus.Status))
{
/* Convert and fail */
BaseSetLastNTError(IoStatus.Status);
return FALSE;
}
if (!NT_SUCCESS(IoStatus.Status)){ /* Return success */
//failed io operation return TRUE;
BaseSetLastNTError(IoStatus.Status);
return FALSE;
}
return TRUE;
} }
/* /*
* @implemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
PostQueuedCompletionStatus( PostQueuedCompletionStatus(IN HANDLE CompletionHandle,
HANDLE CompletionHandle, IN DWORD dwNumberOfBytesTransferred,
DWORD dwNumberOfBytesTransferred, IN ULONG_PTR dwCompletionKey,
ULONG_PTR dwCompletionKey, IN LPOVERLAPPED lpOverlapped)
LPOVERLAPPED lpOverlapped
)
{ {
NTSTATUS errCode; NTSTATUS Status;
errCode = NtSetIoCompletion(CompletionHandle, /* Call the native API */
(PVOID)dwCompletionKey, // KeyContext Status = NtSetIoCompletion(CompletionHandle,
(PVOID)lpOverlapped, // ApcContext (PVOID)dwCompletionKey,
STATUS_SUCCESS, // IoStatusBlock->Status (PVOID)lpOverlapped,
dwNumberOfBytesTransferred); // IoStatusBlock->Information STATUS_SUCCESS,
dwNumberOfBytesTransferred);
if (!NT_SUCCESS(Status))
{
/* Convert the error and fail */
BaseSetLastNTError(Status);
return FALSE;
}
if ( !NT_SUCCESS(errCode) ) /* Success path */
{ return TRUE;
BaseSetLastNTError (errCode);
return FALSE;
}
return TRUE;
} }
/* /*
@ -211,7 +207,7 @@ GetOverlappedResult(IN HANDLE hFile,
} }
/* Fail if we had an error -- the last error is already set */ /* Fail if we had an error -- the last error is already set */
if (WaitStatus != 0) return FALSE; if (WaitStatus) return FALSE;
} }
/* Return bytes transferred */ /* Return bytes transferred */
@ -234,24 +230,24 @@ GetOverlappedResult(IN HANDLE hFile,
*/ */
BOOL BOOL
WINAPI WINAPI
BindIoCompletionCallback(HANDLE FileHandle, BindIoCompletionCallback(IN HANDLE FileHandle,
LPOVERLAPPED_COMPLETION_ROUTINE Function, IN LPOVERLAPPED_COMPLETION_ROUTINE Function,
ULONG Flags) IN ULONG Flags)
{ {
NTSTATUS Status = 0; NTSTATUS Status;
DPRINT("(%p, %p, %d)\n", FileHandle, Function, Flags);
/* Call RTL */
Status = RtlSetIoCompletionCallback(FileHandle, Status = RtlSetIoCompletionCallback(FileHandle,
(PIO_APC_ROUTINE)Function, (PIO_APC_ROUTINE)Function,
Flags); Flags);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
SetLastError(RtlNtStatusToDosError(Status)); /* Set error and fail */
BaseSetLastNTError(Status);
return FALSE; return FALSE;
} }
/* Return success */
return TRUE; return TRUE;
} }