The Win32 API code for I/O completion ports. ChangeLog: - Add Win32 API for I/O completion ports License: - LGPL Rob
Index: dlls/kernel/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/kernel/Makefile.in,v retrieving revision 1.61 diff -u -r1.61 Makefile.in --- dlls/kernel/Makefile.in 31 Mar 2003 23:58:27 -0000 1.61 +++ dlls/kernel/Makefile.in 21 Apr 2003 14:44:12 -0000 @@ -29,6 +29,7 @@ debugger.c \ editline.c \ format_msg.c \ + iocompletion.c \ kernel_main.c \ lcformat.c \ locale.c \ Index: dlls/kernel/kernel32.spec =================================================================== RCS file: /home/wine/wine/dlls/kernel/kernel32.spec,v retrieving revision 1.99 diff -u -r1.99 kernel32.spec --- dlls/kernel/kernel32.spec 8 Apr 2003 19:40:37 -0000 1.99 +++ dlls/kernel/kernel32.spec 21 Apr 2003 14:44:15 -0000 @@ -644,7 +644,7 @@ @ stdcall PeekConsoleInputA(ptr ptr long ptr) @ stdcall PeekConsoleInputW(ptr ptr long ptr) @ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) -@ stub PostQueuedCompletionStatus +@ stdcall PostQueuedCompletionStatus(ptr long long ptr) @ stdcall PrepareTape(ptr long long) @ stub PrivMoveFileIdentityW @ stdcall Process32First (ptr ptr) Index: win32/newfns.c =================================================================== RCS file: /home/wine/wine/win32/newfns.c,v retrieving revision 1.46 diff -u -r1.46 newfns.c --- win32/newfns.c 14 Mar 2003 23:01:24 -0000 1.46 +++ win32/newfns.c 21 Apr 2003 14:47:34 -0000 @@ -290,29 +290,6 @@ /****************************************************************************** - * CreateIoCompletionPort (KERNEL32.@) - */ -HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, -HANDLE hExistingCompletionPort, DWORD dwCompletionKey, -DWORD dwNumberOfConcurrentThreads) -{ - FIXME("(%p, %p, %08lx, %08lx): stub.\n", hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads); - return NULL; -} - -/****************************************************************************** - * GetQueuedCompletionStatus (KERNEL32.@) - */ -BOOL WINAPI GetQueuedCompletionStatus( - HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, - LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped, DWORD dwMilliseconds -) { - FIXME("(%p,%p,%p,%p,%ld), stub!\n",CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/****************************************************************************** * GetDevicePowerState (KERNEL32.@) */ BOOL WINAPI GetDevicePowerState(HANDLE hDevice, BOOL* pfOn) --- /dev/null Mon Jun 24 01:53:01 2002 +++ dlls/kernel/iocompletion.c Mon Mar 24 23:41:46 2003 @@ -0,0 +1,112 @@ +/* + * I/O Completion Ports + * + * Copyright (C) 2003 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "winbase.h" +#include "winnt.h" +#include "winternl.h" + +HANDLE WINAPI CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads) +{ + HANDLE CompletionPort; + NTSTATUS Status; + if (((FileHandle == INVALID_HANDLE_VALUE) && (ExistingCompletionPort != NULL)) || + (ExistingCompletionPort == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + if (ExistingCompletionPort == NULL) + { + Status = NtCreateIoCompletion(&CompletionPort, GENERIC_ALL, 0, NumberOfConcurrentThreads); + if (Status != STATUS_SUCCESS) + { + SetLastError(RtlNtStatusToDosError(Status)); + return INVALID_HANDLE_VALUE; + } + } + else + CompletionPort = ExistingCompletionPort; + + if (FileHandle != INVALID_HANDLE_VALUE) + { + IO_STATUS_BLOCK IoStatusBlock; + FILE_COMPLETION_INFORMATION CompletionInfo; + CompletionInfo.CompletionKey = CompletionKey; + CompletionInfo.CompletionPort = CompletionPort; + + Status = NtSetInformationFile(FileHandle, &IoStatusBlock, (PVOID)&CompletionInfo, sizeof(FILE_COMPLETION_INFORMATION), FileCompletionInformation); + if (Status != STATUS_SUCCESS) + { + SetLastError(RtlNtStatusToDosError(Status)); + return INVALID_HANDLE_VALUE; + } + } + return CompletionPort; +} + +BOOL WINAPI GetQueuedCompletionStatus(HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, LPOVERLAPPED * lplpOverlapped, DWORD dwMilliseconds) +{ + IO_STATUS_BLOCK CompletionBlock; + NTSTATUS Status; + + if (dwMilliseconds == INFINITE) + { + Status = NtRemoveIoCompletion(CompletionPort, lpCompletionKey, lplpOverlapped, &CompletionBlock, NULL); + } + else + { + LARGE_INTEGER WaitTime; + /* multiplying two LONGLONGs with at least one LONGLONG having its + * higher long part not zero makes the multiplying a bit harder, + * therefore we do an easy multiply and negate afterwards rather than + * making it a hard multiply by doing "* -10000" + */ + WaitTime.QuadPart = (LONGLONG)dwMilliseconds * (LONGLONG)10000; + WaitTime.QuadPart = -WaitTime.QuadPart; + Status = NtRemoveIoCompletion(CompletionPort, lpCompletionKey, lplpOverlapped, &CompletionBlock, &WaitTime); + } + if (Status == STATUS_SUCCESS) + { + *lpNumberOfBytesTransferred = CompletionBlock.Information; + return TRUE; + } + else + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } +} + +BOOL WINAPI PostQueuedCompletionStatus(HANDLE CompletionPort, DWORD dwNumberOfBytesTransferred, + ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped) +{ + NTSTATUS Status; + Status = NtSetIoCompletion(CompletionPort, dwCompletionKey, lpOverlapped, 0, dwNumberOfBytesTransferred); + if (Status == STATUS_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } +}