mirror of
https://github.com/reactos/reactos.git
synced 2024-08-08 04:08:29 +00:00
[KERNEL32]: Format, comment, annotate, cleanup the I/O completion APIs.
svn path=/trunk/; revision=55793
This commit is contained in:
parent
b43c3d21c0
commit
d363c616d6
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue