The Win32 API code for I/O completion ports. Separate from the server code just in case that doesn't get applied. ChangeLog: - Add Win32 API for I/O completion ports License: - LGPL Rob
diff -r -u -x *.o wine/dlls/kernel/kernel32.spec newwine/dlls/kernel/kernel32.spec --- wine/dlls/kernel/kernel32.spec Sun Mar 23 14:07:41 2003 +++ newwine/dlls/kernel/kernel32.spec Sat Mar 22 21:40:54 2003 @@ -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) diff -r -u -x *.o wine/win32/newfns.c newwine/win32/newfns.c --- wine/win32/newfns.c Sun Mar 23 14:06:05 2003 +++ newwine/win32/newfns.c Sat Mar 22 21:41:52 2003 @@ -286,28 +286,4 @@ { FIXME("(%s,%p): stub\n",debugstr_w(lpFileName),lpFileSizeHigh); return 0xffffffff; } - - -/****************************************************************************** - * 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.@) */ --- /dev/null Mon Jun 24 01:53:01 2002 +++ newwine/dlls/kernel/iocompletion.c Sat Mar 22 21:42:43 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; + } +} --- wine/include/winbase.h Fri Mar 14 20:07:11 2003 +++ newwine/include/winbase.h Sun Mar 23 22:06:42 2003 @@ -1208,6 +1208,7 @@ HANDLE WINAPI CreateFileMappingA(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR); HANDLE WINAPI CreateFileMappingW(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCWSTR); #define CreateFileMapping WINELIB_NAME_AW(CreateFileMapping) +HANDLE WINAPI CreateIoCompletionPort(HANDLE,HANDLE,ULONG_PTR,DWORD); HANDLE WINAPI CreateMutexA(LPSECURITY_ATTRIBUTES,BOOL,LPCSTR); HANDLE WINAPI CreateMutexW(LPSECURITY_ATTRIBUTES,BOOL,LPCWSTR); #define CreateMutex WINELIB_NAME_AW(CreateMutex) @@ -1342,6 +1343,7 @@ BOOL WINAPI GetProcessAffinityMask(HANDLE,PDWORD,PDWORD); BOOL WINAPI GetProcessTimes(HANDLE,LPFILETIME,LPFILETIME,LPFILETIME,LPFILETIME); DWORD WINAPI GetProcessVersion(DWORD); +BOOL WINAPI GetQueuedCompletionStatus(HANDLE,LPDWORD,PULONG_PTR,LPOVERLAPPED*,DWORD); BOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR_CONTROL,LPDWORD); BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,LPBOOL,PACL *,LPBOOL); BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID *,LPBOOL); @@ -1442,6 +1444,7 @@ HANDLE WINAPI OpenWaitableTimerW(DWORD,BOOL,LPCWSTR); #define OpenWaitableTimer WINELIB_NAME_AW(OpenWaitableTimer) BOOL WINAPI PeekNamedPipe(HANDLE,PVOID,DWORD,PDWORD,PDWORD,PDWORD); +BOOL WINAPI PostQueuedCompletionStatus(HANDLE,DWORD,ULONG_PTR,LPOVERLAPPED); DWORD WINAPI PrepareTape(HANDLE,DWORD,BOOL); BOOL WINAPI PulseEvent(HANDLE); BOOL WINAPI PurgeComm(HANDLE,DWORD);