I/O Completion Ports (2 of 2)

Robert Shearman R.J.Shearman at warwick.ac.uk
Sun Mar 23 19:19:44 CST 2003


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

-------------- next part --------------
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);


More information about the wine-patches mailing list