1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-18 23:11:19 +03:00
Files
KernelEx/apilibs/kexbases/Kernel32/CompletionPorts.c
2018-11-03 16:22:27 +03:00

154 lines
5.2 KiB
C
Executable File

/*
* KernelEx
* Copyright (C) 2010, Tihiy
*
* This file is part of KernelEx source code.
*
* KernelEx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* KernelEx 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <windows.h>
#include "kexcoresdk.h"
/*
* Note that only get-post functionality is rougly simulated;
* no actual I/O completion notification can be done.
*
* Also handles don't get proper cleanup!
*/
#define PORT_SIGNATURE 0xABADC0FE
#define MAX_QUEUES 200
typedef struct
{
DWORD dwBytes;
ULONG_PTR dwKey;
LPOVERLAPPED lpOverlapped;
} COMPLET_PACKET;
typedef struct
{
DWORD signature;
HANDLE hEvent;
CRITICAL_SECTION cs;
DWORD count;
COMPLET_PACKET packets[MAX_QUEUES];
} COMPLET_PORT, *PCOMPLET_PORT;
/* MAKE_EXPORT CreateIoCompletionPort_new=CreateIoCompletionPort */
HANDLE WINAPI CreateIoCompletionPort_new(
HANDLE FileHandle, // handle to file
HANDLE ExistingCompletionPort, // handle to I/O completion port
ULONG_PTR CompletionKey, // completion key
DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
)
{
//kexDebugPrint("CreateIoCompletionPort FileHandle %p Port %p Key %p Threads %d",FileHandle,ExistingCompletionPort,CompletionKey,NumberOfConcurrentThreads);
if (FileHandle != INVALID_HANDLE_VALUE)
{
DBGPRINTF(("CreateIoCompletionPort is used for real (file handle %p), not supported.\n",FileHandle));
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
}
//go create a handle we will hack on
HANDLE hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,sizeof(COMPLET_PORT),NULL);
if (hFileMap)
{
PCOMPLET_PORT port = (PCOMPLET_PORT)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,0,0,0);
port->signature = PORT_SIGNATURE;
port->count = 0;
port->hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
InitializeCriticalSection( &port->cs );
UnmapViewOfFile(port);
}
return hFileMap;
}
/* MAKE_EXPORT GetQueuedCompletionStatus_new=GetQueuedCompletionStatus */
BOOL WINAPI GetQueuedCompletionStatus_new(
HANDLE CompletionPort, // handle to completion port
LPDWORD lpNumberOfBytes, // bytes transferred
PULONG_PTR lpCompletionKey, // file completion key
LPOVERLAPPED *lpOverlapped, // buffer
DWORD dwMilliseconds // optional timeout value
)
{
PCOMPLET_PORT port = (PCOMPLET_PORT)MapViewOfFile(CompletionPort,FILE_MAP_ALL_ACCESS,0,0,0);
if (!port || port->signature != PORT_SIGNATURE || !lpOverlapped || !lpNumberOfBytes || !lpCompletionKey)
{
UnmapViewOfFile(port);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//kexDebugPrint("GetQueuedCompletionStatus waiting port %p for %d ms",port,dwMilliseconds);
DWORD status = WaitForSingleObject(port->hEvent,dwMilliseconds);
if (status != WAIT_OBJECT_0)
{
//kexDebugPrint("GetQueuedCompletionStatus waiting port %p timed up!",port);
UnmapViewOfFile(port);
*lpOverlapped = NULL;
SetLastError(WAIT_TIMEOUT);
return FALSE;
}
EnterCriticalSection(&port->cs);
*lpNumberOfBytes = port->packets[0].dwBytes;
*lpCompletionKey = port->packets[0].dwKey;
*lpOverlapped = port->packets[0].lpOverlapped;
port->count--;
memmove(&port->packets[0],&port->packets[1],sizeof(COMPLET_PACKET)*port->count);
if (port->count > 0) SetEvent(port->hEvent);
LeaveCriticalSection(&port->cs);
UnmapViewOfFile(port);
//kexDebugPrint("GetQueuedCompletionStatus dequeued from port %p: %p %p %p",port,*lpNumberOfBytes,*lpCompletionKey,*lpOverlapped);
return TRUE;
}
/* MAKE_EXPORT PostQueuedCompletionStatus_new=PostQueuedCompletionStatus */
BOOL WINAPI PostQueuedCompletionStatus_new(
HANDLE CompletionPort, // handle to an I/O completion port
DWORD dwNumberOfBytesTransferred, // bytes transferred
ULONG_PTR dwCompletionKey, // completion key
LPOVERLAPPED lpOverlapped // overlapped buffer
)
{
PCOMPLET_PORT port = (PCOMPLET_PORT)MapViewOfFile(CompletionPort,FILE_MAP_ALL_ACCESS,0,0,0);
//kexDebugPrint("PostQueuedCompletionStatus queued from port %p: %p %p %p",port,dwNumberOfBytesTransferred,dwCompletionKey,lpOverlapped);
if (!port || port->signature != PORT_SIGNATURE)
{
UnmapViewOfFile(port);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
BOOL ret = FALSE;
EnterCriticalSection(&port->cs);
if (port->count < MAX_QUEUES)
{
DWORD last = port->count;
port->packets[last].dwBytes = dwNumberOfBytesTransferred;
port->packets[last].dwKey = dwCompletionKey;
port->packets[last].lpOverlapped = lpOverlapped;
port->count++;
SetEvent(port->hEvent);
ret = TRUE;
}
LeaveCriticalSection(&port->cs);
UnmapViewOfFile(port);
return ret;
}