mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
initial work on I/O completion
svn path=/trunk/; revision=4352
This commit is contained in:
parent
fc1366d624
commit
957f814a24
12 changed files with 621 additions and 190 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: extypes.h,v 1.12 2002/11/24 18:26:40 robd Exp $ */
|
/* $Id: extypes.h,v 1.13 2003/03/19 23:14:11 gdalsnes Exp $ */
|
||||||
|
|
||||||
#ifndef __INCLUDE_DDK_EXTYPES_H
|
#ifndef __INCLUDE_DDK_EXTYPES_H
|
||||||
#define __INCLUDE_DDK_EXTYPES_H
|
#define __INCLUDE_DDK_EXTYPES_H
|
||||||
|
@ -7,10 +7,12 @@
|
||||||
extern POBJECT_TYPE EXPORTED ExDesktopObjectType;
|
extern POBJECT_TYPE EXPORTED ExDesktopObjectType;
|
||||||
extern POBJECT_TYPE EXPORTED ExEventObjectType;
|
extern POBJECT_TYPE EXPORTED ExEventObjectType;
|
||||||
extern POBJECT_TYPE EXPORTED ExWindowStationObjectType;
|
extern POBJECT_TYPE EXPORTED ExWindowStationObjectType;
|
||||||
|
extern POBJECT_TYPE EXPORTED ExIoCompletionType;
|
||||||
#else
|
#else
|
||||||
extern POBJECT_TYPE IMPORTED ExDesktopObjectType;
|
extern POBJECT_TYPE IMPORTED ExDesktopObjectType;
|
||||||
extern POBJECT_TYPE IMPORTED ExEventObjectType;
|
extern POBJECT_TYPE IMPORTED ExEventObjectType;
|
||||||
extern POBJECT_TYPE IMPORTED ExWindowStationObjectType;
|
extern POBJECT_TYPE IMPORTED ExWindowStationObjectType;
|
||||||
|
extern POBJECT_TYPE IMPORTED ExIoCompletionType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef ULONG INTERLOCKED_RESULT;
|
typedef ULONG INTERLOCKED_RESULT;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: iotypes.h,v 1.45 2002/11/24 18:26:40 robd Exp $
|
/* $Id: iotypes.h,v 1.46 2003/03/19 23:14:29 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -465,6 +465,12 @@ typedef struct _IO_STATUS_BLOCK
|
||||||
ULONG Information;
|
ULONG Information;
|
||||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||||
|
|
||||||
|
typedef struct _IO_COMPLETION_PACKET{
|
||||||
|
ULONG Key;
|
||||||
|
ULONG Overlapped;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
} IO_COMPLETION_PACKET, *PIO_COMPLETION_PACKET;
|
||||||
|
|
||||||
typedef struct _IO_PIPE_CREATE_BUFFER
|
typedef struct _IO_PIPE_CREATE_BUFFER
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,6 +135,9 @@ VOID STDCALL
|
||||||
KeInitializeQueue(IN PKQUEUE Queue,
|
KeInitializeQueue(IN PKQUEUE Queue,
|
||||||
IN ULONG Count);
|
IN ULONG Count);
|
||||||
|
|
||||||
|
PLIST_ENTRY STDCALL
|
||||||
|
KeRundownQueue(IN PKQUEUE Queue);
|
||||||
|
|
||||||
VOID STDCALL KeInitializeSemaphore (PKSEMAPHORE Semaphore,
|
VOID STDCALL KeInitializeSemaphore (PKSEMAPHORE Semaphore,
|
||||||
LONG Count,
|
LONG Count,
|
||||||
LONG Limit);
|
LONG Limit);
|
||||||
|
|
|
@ -122,9 +122,9 @@ typedef struct _KQUEUE
|
||||||
{
|
{
|
||||||
DISPATCHER_HEADER Header;
|
DISPATCHER_HEADER Header;
|
||||||
LIST_ENTRY EntryListHead;
|
LIST_ENTRY EntryListHead;
|
||||||
ULONG CurrentCount;
|
ULONG RunningThreads;
|
||||||
ULONG MaximumCount;
|
ULONG MaximumThreads;
|
||||||
LIST_ENTRY ThreadListEntry;
|
LIST_ENTRY ThreadListHead;
|
||||||
} KQUEUE, *PKQUEUE;
|
} KQUEUE, *PKQUEUE;
|
||||||
|
|
||||||
struct _KDPC;
|
struct _KDPC;
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#define TIMER_ALL_ACCESS (0x1f0003L)
|
#define TIMER_ALL_ACCESS (0x1f0003L)
|
||||||
#define TIMER_QUERY_STATE (1)
|
#define TIMER_QUERY_STATE (1)
|
||||||
#define TIMER_MODIFY_STATE (2)
|
#define TIMER_MODIFY_STATE (2)
|
||||||
|
#define IO_COMPLETION_QUERY_STATE (0x0001)
|
||||||
|
#define IO_COMPLETION_MODIFY_STATE (0x0002)
|
||||||
|
#define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
|
||||||
|
|
||||||
#endif /* !__USE_W32API */
|
#endif /* !__USE_W32API */
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
/* $Id: zw.h,v 1.8 2003/02/27 22:49:06 ekohl Exp $
|
/* $Id: zw.h,v 1.9 2003/03/19 23:16:00 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -497,21 +497,20 @@ ZwCreateFile(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtCreateIoCompletion(
|
NtCreateIoCompletion(
|
||||||
OUT PHANDLE CompletionPort,
|
OUT PHANDLE IoCompletionHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
IN ULONG NumberOfConcurrentThreads
|
IN ULONG NumberOfConcurrentThreads
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
ZwCreateIoCompletion(
|
ZwCreateIoCompletion(
|
||||||
OUT PHANDLE CompletionPort,
|
OUT PHANDLE IoCompletionHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
IN ULONG NumberOfConcurrentThreads
|
IN ULONG NumberOfConcurrentThreads
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Creates a registry key
|
* FUNCTION: Creates a registry key
|
||||||
|
@ -2357,20 +2356,22 @@ ZwQueryInformationToken(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtQueryIoCompletion(
|
NtQueryIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
IN ULONG CompletionKey,
|
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PVOID IoCompletionInformation,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG IoCompletionInformationLength,
|
||||||
);
|
OUT PULONG ResultLength OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
ZwQueryIoCompletion(
|
ZwQueryIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
IN ULONG CompletionKey,
|
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PVOID IoCompletionInformation,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG IoCompletionInformationLength,
|
||||||
);
|
OUT PULONG ResultLength OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Queries the information of a registry key object.
|
* FUNCTION: Queries the information of a registry key object.
|
||||||
|
@ -2990,22 +2991,23 @@ ZwReleaseSemaphore(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtRemoveIoCompletion(
|
NtRemoveIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
OUT PULONG CompletionKey,
|
OUT PULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PULONG CompletionValue,
|
||||||
OUT PULONG CompletionStatus,
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
IN PLARGE_INTEGER WaitTime
|
IN PLARGE_INTEGER Timeout OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
ZwRemoveIoCompletion(
|
ZwRemoveIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
OUT PULONG CompletionKey,
|
OUT PULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PULONG CompletionValue,
|
||||||
OUT PULONG CompletionStatus,
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
IN PLARGE_INTEGER WaitTime
|
IN PLARGE_INTEGER Timeout OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Replaces one registry key with another
|
* FUNCTION: Replaces one registry key with another
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
|
@ -3392,21 +3394,22 @@ ZwSetInformationToken(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtSetIoCompletion(
|
NtSetIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionPortHandle,
|
||||||
IN ULONG CompletionKey,
|
IN ULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
IN ULONG CompletionValue,
|
||||||
IN ULONG NumberOfBytesToTransfer,
|
IN NTSTATUS CompletionStatus,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG CompletionInformation
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
ZwSetIoCompletion(
|
ZwSetIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionPortHandle,
|
||||||
IN ULONG CompletionKey,
|
IN ULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
IN ULONG CompletionValue,
|
||||||
IN ULONG NumberOfBytesToTransfer,
|
IN NTSTATUS CompletionStatus,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG CompletionInformation
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Set properties for profiling
|
* FUNCTION: Set properties for profiling
|
||||||
|
|
|
@ -881,6 +881,11 @@ typedef struct _FILE_COMPRESSION_INFORMATION {
|
||||||
UCHAR Reserved[3];
|
UCHAR Reserved[3];
|
||||||
} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
|
} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _FILE_COMPLETION_INFORMATION { // Information Class 30
|
||||||
|
HANDLE IoCompletionHandle;
|
||||||
|
ULONG CompletionKey;
|
||||||
|
} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
|
||||||
|
|
||||||
typedef struct _FILE_ALL_INFORMATION {
|
typedef struct _FILE_ALL_INFORMATION {
|
||||||
FILE_BASIC_INFORMATION BasicInformation;
|
FILE_BASIC_INFORMATION BasicInformation;
|
||||||
FILE_STANDARD_INFORMATION StandardInformation;
|
FILE_STANDARD_INFORMATION StandardInformation;
|
||||||
|
@ -1069,6 +1074,14 @@ typedef enum SHUTDOWN_ACTION_TAG {
|
||||||
ShutdownPowerOff
|
ShutdownPowerOff
|
||||||
} SHUTDOWN_ACTION;
|
} SHUTDOWN_ACTION;
|
||||||
|
|
||||||
|
typedef enum _IO_COMPLETION_INFORMATION_CLASS {
|
||||||
|
IoCompletionBasicInformation
|
||||||
|
} IO_COMPLETION_INFORMATION_CLASS;
|
||||||
|
|
||||||
|
typedef struct _IO_COMPLETION_BASIC_INFORMATION {
|
||||||
|
LONG SignalState;
|
||||||
|
} IO_COMPLETION_BASIC_INFORMATION, *PIO_COMPLETION_BASIC_INFORMATION;
|
||||||
|
|
||||||
#else /* __USE_W32API */
|
#else /* __USE_W32API */
|
||||||
|
|
||||||
#define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
|
#define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: iocompl.c,v 1.8 2003/02/03 14:19:30 ekohl Exp $
|
/* $Id: iocompl.c,v 1.9 2003/03/19 23:16:55 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -14,23 +14,6 @@
|
||||||
|
|
||||||
#include <kernel32/error.h>
|
#include <kernel32/error.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct _FILE_COMPLETION_INFORMATION {
|
|
||||||
HANDLE CompletionPort;
|
|
||||||
ULONG CompletionKey;
|
|
||||||
} FILE_COMPLETION_INFORMATION;
|
|
||||||
typedef FILE_COMPLETION_INFORMATION *PFILE_COMPLETION_INFORMATION;
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
STDCALL
|
|
||||||
FileIOCompletionRoutine(
|
|
||||||
DWORD dwErrorCode,
|
|
||||||
DWORD dwNumberOfBytesTransfered,
|
|
||||||
LPOVERLAPPED lpOverlapped
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
HANDLE
|
HANDLE
|
||||||
STDCALL
|
STDCALL
|
||||||
CreateIoCompletionPort(
|
CreateIoCompletionPort(
|
||||||
|
@ -40,99 +23,146 @@ CreateIoCompletionPort(
|
||||||
DWORD NumberOfConcurrentThreads
|
DWORD NumberOfConcurrentThreads
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
HANDLE CompletionPort = NULL;
|
HANDLE CompletionPort = NULL;
|
||||||
NTSTATUS errCode;
|
NTSTATUS errCode;
|
||||||
FILE_COMPLETION_INFORMATION CompletionInformation;
|
FILE_COMPLETION_INFORMATION CompletionInformation;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
if ( ExistingCompletionPort == NULL && FileHandle == INVALID_HANDLE_VALUE ) {
|
if ( ExistingCompletionPort == NULL && FileHandle == INVALID_HANDLE_VALUE )
|
||||||
SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
|
{
|
||||||
return FALSE;
|
SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
|
||||||
}
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ExistingCompletionPort != NULL ) {
|
if ( ExistingCompletionPort != NULL )
|
||||||
CompletionPort = ExistingCompletionPort;
|
{
|
||||||
}
|
CompletionPort = ExistingCompletionPort;
|
||||||
else {
|
}
|
||||||
errCode = NtCreateIoCompletion(&CompletionPort,GENERIC_ALL,&IoStatusBlock,NumberOfConcurrentThreads);
|
else
|
||||||
if (!NT_SUCCESS(errCode) ) {
|
{
|
||||||
SetLastErrorByStatus (errCode);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
errCode = NtCreateIoCompletion(&CompletionPort,
|
||||||
if ( FileHandle != INVALID_HANDLE_VALUE ) {
|
IO_COMPLETION_ALL_ACCESS,
|
||||||
|
NULL,//ObjectAttributes
|
||||||
|
NumberOfConcurrentThreads);
|
||||||
|
|
||||||
CompletionInformation.CompletionPort = CompletionPort;
|
if (!NT_SUCCESS(errCode) )
|
||||||
CompletionInformation.CompletionKey = CompletionKey;
|
{
|
||||||
|
SetLastErrorByStatus (errCode);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
errCode = NtSetInformationFile(FileHandle, &IoStatusBlock,&CompletionInformation,sizeof(FILE_COMPLETION_INFORMATION),FileCompletionInformation);
|
}
|
||||||
if ( !NT_SUCCESS(errCode) ) {
|
|
||||||
if ( ExistingCompletionPort == NULL )
|
if ( FileHandle != INVALID_HANDLE_VALUE )
|
||||||
NtClose(CompletionPort);
|
{
|
||||||
SetLastErrorByStatus (errCode);
|
CompletionInformation.IoCompletionHandle = CompletionPort;
|
||||||
return FALSE;
|
CompletionInformation.CompletionKey = CompletionKey;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CompletionPort;
|
errCode = NtSetInformationFile(FileHandle,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&CompletionInformation,
|
||||||
|
sizeof(FILE_COMPLETION_INFORMATION),
|
||||||
|
FileCompletionInformation);
|
||||||
|
|
||||||
|
if ( !NT_SUCCESS(errCode) )
|
||||||
|
{
|
||||||
|
if ( ExistingCompletionPort == NULL )
|
||||||
|
{
|
||||||
|
NtClose(CompletionPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLastErrorByStatus (errCode);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletionPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WINBOOL
|
WINBOOL
|
||||||
STDCALL
|
STDCALL
|
||||||
GetQueuedCompletionStatus(
|
GetQueuedCompletionStatus(
|
||||||
HANDLE CompletionPort,
|
HANDLE CompletionHandle,
|
||||||
LPDWORD lpNumberOfBytesTransferred,
|
LPDWORD lpNumberOfBytesTransferred,
|
||||||
LPDWORD lpCompletionKey,
|
LPDWORD lpCompletionKey,
|
||||||
LPOVERLAPPED *lpOverlapped,
|
LPOVERLAPPED *lpOverlapped,
|
||||||
DWORD dwMilliseconds
|
DWORD dwMilliseconds
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS errCode;
|
NTSTATUS errCode;
|
||||||
ULONG CompletionStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
LARGE_INTEGER TimeToWait;
|
LARGE_INTEGER Interval;
|
||||||
|
|
||||||
errCode = NtRemoveIoCompletion(CompletionPort,(PULONG)lpCompletionKey,(PIO_STATUS_BLOCK)lpOverlapped,&CompletionStatus,&TimeToWait);
|
if (!lpNumberOfBytesTransferred||!lpCompletionKey||!lpOverlapped)
|
||||||
if (!NT_SUCCESS(errCode) ) {
|
{
|
||||||
SetLastErrorByStatus (errCode);
|
return ERROR_INVALID_PARAMETER;
|
||||||
return FALSE;
|
}
|
||||||
}
|
|
||||||
|
if (dwMilliseconds != INFINITE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* System time units are 100 nanoseconds (a nanosecond is a billionth of
|
||||||
|
* a second).
|
||||||
|
*/
|
||||||
|
Interval.QuadPart = dwMilliseconds;
|
||||||
|
Interval.QuadPart = -(Interval.QuadPart * 10000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Approximately 292000 years hence */
|
||||||
|
Interval.QuadPart = -0x7FFFFFFFFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
errCode = NtRemoveIoCompletion(CompletionHandle,
|
||||||
|
lpCompletionKey,
|
||||||
|
lpNumberOfBytesTransferred,
|
||||||
|
&IoStatus,
|
||||||
|
&Interval);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(errCode) ) {
|
||||||
|
*lpOverlapped = NULL;
|
||||||
|
SetLastErrorByStatus(errCode);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*lpOverlapped = (LPOVERLAPPED)IoStatus.Information;
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(IoStatus.Status)){
|
||||||
|
//failed io operation
|
||||||
|
SetLastErrorByStatus (IoStatus.Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WINBOOL
|
WINBOOL
|
||||||
STDCALL
|
STDCALL
|
||||||
PostQueuedCompletionStatus(
|
PostQueuedCompletionStatus(
|
||||||
HANDLE CompletionPort,
|
HANDLE CompletionHandle,
|
||||||
DWORD dwNumberOfBytesTransferred,
|
DWORD dwNumberOfBytesTransferred,
|
||||||
DWORD dwCompletionKey,
|
DWORD dwCompletionKey,
|
||||||
LPOVERLAPPED lpOverlapped
|
LPOVERLAPPED lpOverlapped
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS errCode;
|
NTSTATUS errCode;
|
||||||
errCode = NtSetIoCompletion(CompletionPort, dwCompletionKey, (PIO_STATUS_BLOCK)lpOverlapped , 0, (PULONG)&dwNumberOfBytesTransferred );
|
|
||||||
|
|
||||||
if ( !NT_SUCCESS(errCode) ) {
|
errCode = NtSetIoCompletion(CompletionHandle,
|
||||||
SetLastErrorByStatus (errCode);
|
dwCompletionKey,
|
||||||
return FALSE;
|
dwNumberOfBytesTransferred,//CompletionValue
|
||||||
}
|
0, //IoStatusBlock->Status
|
||||||
return TRUE;
|
(ULONG)lpOverlapped ); //IoStatusBlock->Information
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( !NT_SUCCESS(errCode) )
|
||||||
// this should be a place holder ??????????????????
|
{
|
||||||
VOID
|
SetLastErrorByStatus (errCode);
|
||||||
STDCALL
|
return FALSE;
|
||||||
FileIOCompletionRoutine(
|
}
|
||||||
DWORD dwErrorCode,
|
return TRUE;
|
||||||
DWORD dwNumberOfBytesTransfered,
|
|
||||||
LPOVERLAPPED lpOverlapped
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@ VOID
|
||||||
KiDeliverNormalApc(VOID);
|
KiDeliverNormalApc(VOID);
|
||||||
|
|
||||||
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
|
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
|
||||||
|
PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
|
||||||
|
|
||||||
|
|
||||||
/* INITIALIZATION FUNCTIONS *************************************************/
|
/* INITIALIZATION FUNCTIONS *************************************************/
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: file.c,v 1.21 2002/09/08 10:23:24 chorns Exp $
|
/* $Id: file.c,v 1.22 2003/03/19 23:11:23 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -236,7 +236,39 @@ NtSetInformationFile(HANDLE FileHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("FileObject %x\n", FileObject);
|
DPRINT("FileObject %x\n", FileObject);
|
||||||
|
|
||||||
|
//io completion port?
|
||||||
|
if (FileInformationClass == FileCompletionInformation)
|
||||||
|
{
|
||||||
|
PKQUEUE Queue;
|
||||||
|
|
||||||
|
if (Length < sizeof(FILE_COMPLETION_INFORMATION))
|
||||||
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
|
||||||
|
IO_COMPLETION_MODIFY_STATE,//???
|
||||||
|
ExIoCompletionType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&Queue,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//FIXME: maybe use lookaside list
|
||||||
|
FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
|
||||||
|
FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
|
||||||
|
FileObject->CompletionContext->Port = Queue;
|
||||||
|
|
||||||
|
ObDereferenceObject(Queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceObject = FileObject->DeviceObject;
|
DeviceObject = FileObject->DeviceObject;
|
||||||
|
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
||||||
|
|
|
@ -11,73 +11,303 @@
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
|
#include <ntos/synch.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
#define IOC_TAG TAG('I', 'O', 'C', 'T')
|
||||||
|
|
||||||
|
POBJECT_TYPE ExIoCompletionType;
|
||||||
|
|
||||||
|
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
|
||||||
|
|
||||||
|
static GENERIC_MAPPING ExIoCompletionMapping =
|
||||||
|
{
|
||||||
|
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
|
||||||
|
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
|
||||||
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
|
||||||
|
IO_COMPLETION_ALL_ACCESS
|
||||||
|
};
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtCreateIoCompletion (
|
NtpCreateIoCompletion(
|
||||||
OUT PHANDLE CompletionPort,
|
PVOID ObjectBody,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
PVOID Parent,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
PWSTR RemainingPath,
|
||||||
IN ULONG NumberOfConcurrentThreads
|
POBJECT_ATTRIBUTES ObjectAttributes
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
DPRINT("NtpCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
||||||
|
ObjectBody, Parent, RemainingPath);
|
||||||
|
|
||||||
|
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
NtpDeleteIoCompletion(PVOID ObjectBody)
|
||||||
|
{
|
||||||
|
PKQUEUE Queue = ObjectBody;
|
||||||
|
|
||||||
|
DPRINT("NtpDeleteIoCompletion()\n");
|
||||||
|
|
||||||
|
KeRundownQueue(Queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtInitializeIoCompletionImplementation(VOID)
|
||||||
|
{
|
||||||
|
ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
|
||||||
|
RtlCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion");
|
||||||
|
|
||||||
|
ExIoCompletionType->Tag = IOC_TAG;
|
||||||
|
ExIoCompletionType->MaxObjects = ULONG_MAX;
|
||||||
|
ExIoCompletionType->MaxHandles = ULONG_MAX;
|
||||||
|
ExIoCompletionType->TotalObjects = 0;
|
||||||
|
ExIoCompletionType->TotalHandles = 0;
|
||||||
|
ExIoCompletionType->PagedPoolCharge = 0;
|
||||||
|
ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
|
||||||
|
ExIoCompletionType->Mapping = &ExIoCompletionMapping;
|
||||||
|
ExIoCompletionType->Dump = NULL;
|
||||||
|
ExIoCompletionType->Open = NULL;
|
||||||
|
ExIoCompletionType->Close = NULL;
|
||||||
|
ExIoCompletionType->Delete = NtpDeleteIoCompletion;
|
||||||
|
ExIoCompletionType->Parse = NULL;
|
||||||
|
ExIoCompletionType->Security = NULL;
|
||||||
|
ExIoCompletionType->QueryName = NULL;
|
||||||
|
ExIoCompletionType->OkayToClose = NULL;
|
||||||
|
ExIoCompletionType->Create = NtpCreateIoCompletion;
|
||||||
|
ExIoCompletionType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
|
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
sizeof(IO_COMPLETION_PACKET),
|
||||||
|
IOC_TAG,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtOpenIoCompletion (
|
NtCreateIoCompletion(
|
||||||
OUT PHANDLE CompletionPort,
|
OUT PHANDLE IoCompletionHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
)
|
IN ULONG NumberOfConcurrentThreads
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return(STATUS_SUCCESS);
|
PKQUEUE Queue;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = ObCreateObject(IoCompletionHandle,
|
||||||
|
DesiredAccess,
|
||||||
|
ObjectAttributes,
|
||||||
|
ExIoCompletionType,
|
||||||
|
(PVOID*)&Queue);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
(void) KeInitializeQueue(Queue, NumberOfConcurrentThreads);
|
||||||
|
ObDereferenceObject(Queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
/*
|
||||||
|
|
||||||
|
CompletionPort = NULL OR ExistingCompletionPort
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
DesiredAccess:
|
||||||
|
ZERO
|
||||||
|
IO_COMPLETION_QUERY_STATE Query access
|
||||||
|
IO_COMPLETION_MODIFY_STATE Modify access
|
||||||
|
IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
|
||||||
|
|
||||||
|
ObjectAttributes
|
||||||
|
OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
|
||||||
|
|
||||||
|
Return Value
|
||||||
|
STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
|
||||||
|
STATUS_OBJECT_NAME_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
NtOpenIoCompletion(
|
||||||
|
OUT PHANDLE IoCompletionHandle,
|
||||||
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN POBJECT_ATTRIBUTES ObjectAttributes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
|
ExIoCompletionType,
|
||||||
|
NULL,
|
||||||
|
UserMode,
|
||||||
|
DesiredAccess,
|
||||||
|
NULL,
|
||||||
|
IoCompletionHandle); //<- ???
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtQueryIoCompletion (
|
NtQueryIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
IN ULONG CompletionKey,
|
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PVOID IoCompletionInformation,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG IoCompletionInformationLength,
|
||||||
)
|
OUT PULONG ResultLength OPTIONAL
|
||||||
|
)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PKQUEUE Queue;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (IoCompletionInformationClass != IoCompletionBasicInformation)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_INFO_CLASS;
|
||||||
|
}
|
||||||
|
if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
|
||||||
|
{
|
||||||
|
return STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle( IoCompletionHandle,
|
||||||
|
IO_COMPLETION_QUERY_STATE,
|
||||||
|
ExIoCompletionType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&Queue,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->SignalState =
|
||||||
|
Queue->Header.SignalState;
|
||||||
|
|
||||||
|
ObDereferenceObject(Queue);
|
||||||
|
|
||||||
|
if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dequeues an I/O completion message from an I/O completion object
|
||||||
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtRemoveIoCompletion (
|
NtRemoveIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionHandle,
|
||||||
OUT PULONG CompletionKey,
|
OUT PULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
OUT PULONG CompletionValue,
|
||||||
OUT PULONG CompletionStatus,
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
PLARGE_INTEGER WaitTime
|
IN PLARGE_INTEGER Timeout OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PKQUEUE Queue;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle( IoCompletionHandle,
|
||||||
|
IO_COMPLETION_MODIFY_STATE,
|
||||||
|
ExIoCompletionType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&Queue,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PIO_COMPLETION_PACKET Packet;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Try 2 remove packet from queue. Wait (optionaly) if
|
||||||
|
no packet in queue or max num of threads allready running.
|
||||||
|
*/
|
||||||
|
ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
|
||||||
|
|
||||||
|
ObDereferenceObject(Queue);
|
||||||
|
|
||||||
|
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
|
||||||
|
|
||||||
|
if (CompletionKey) *CompletionKey = Packet->Key;
|
||||||
|
if (CompletionValue) *CompletionValue = Packet->Overlapped;
|
||||||
|
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
|
||||||
|
|
||||||
|
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ASSOSIERT MED FOB's IoCompletionContext
|
||||||
|
|
||||||
|
typedef struct _IO_COMPLETION_CONTEXT {
|
||||||
|
PVOID Port;
|
||||||
|
ULONG Key;
|
||||||
|
} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queues an I/O completion message to an I/O completion object
|
||||||
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtSetIoCompletion (
|
NtSetIoCompletion(
|
||||||
IN HANDLE CompletionPort,
|
IN HANDLE IoCompletionPortHandle,
|
||||||
IN ULONG CompletionKey,
|
IN ULONG CompletionKey,
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
IN ULONG CompletionValue,
|
||||||
IN ULONG NumberOfBytesToTransfer,
|
IN NTSTATUS CompletionStatus,
|
||||||
OUT PULONG NumberOfBytesTransferred
|
IN ULONG CompletionInformation
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
NTSTATUS Status;
|
||||||
|
PKQUEUE Queue;
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
|
||||||
|
IO_COMPLETION_MODIFY_STATE,
|
||||||
|
ExIoCompletionType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&Queue,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PIO_COMPLETION_PACKET Packet;
|
||||||
|
|
||||||
|
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
|
||||||
|
|
||||||
|
Packet->Key = CompletionKey;
|
||||||
|
Packet->Overlapped = CompletionValue;
|
||||||
|
Packet->IoStatus.Status = CompletionStatus;
|
||||||
|
Packet->IoStatus.Information = CompletionInformation;
|
||||||
|
|
||||||
|
KeInsertQueue(Queue, &Packet->ListEntry);
|
||||||
|
ObDereferenceObject(Queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: queue.c,v 1.4 2002/11/10 18:17:41 chorns Exp $
|
/* $Id: queue.c,v 1.5 2003/03/19 23:10:31 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/queue.c
|
* FILE: ntoskrnl/ke/queue.c
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <internal/ke.h>
|
#include <internal/ke.h>
|
||||||
#include <internal/id.h>
|
#include <internal/id.h>
|
||||||
|
#include <internal/ps.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
@ -46,9 +47,9 @@ KeInitializeQueue(IN PKQUEUE Queue,
|
||||||
sizeof(KQUEUE)/sizeof(ULONG),
|
sizeof(KQUEUE)/sizeof(ULONG),
|
||||||
0);
|
0);
|
||||||
InitializeListHead(&Queue->EntryListHead);
|
InitializeListHead(&Queue->EntryListHead);
|
||||||
InitializeListHead(&Queue->ThreadListEntry);
|
InitializeListHead(&Queue->ThreadListHead);
|
||||||
Queue->CurrentCount = 0;
|
Queue->RunningThreads = 0;
|
||||||
Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
|
Queue->MaximumThreads = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,12 +60,47 @@ KeReadStateQueue(IN PKQUEUE Queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LONG STDCALL
|
||||||
|
KiInsertQueue(
|
||||||
|
IN PKQUEUE Queue,
|
||||||
|
IN PLIST_ENTRY Entry,
|
||||||
|
BOOLEAN Head
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG InitialState;
|
||||||
|
|
||||||
|
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
|
||||||
|
|
||||||
|
KeAcquireDispatcherDatabaseLock(FALSE);
|
||||||
|
|
||||||
|
InitialState = Queue->Header.SignalState;
|
||||||
|
Queue->Header.SignalState++;
|
||||||
|
|
||||||
|
if (Head)
|
||||||
|
{
|
||||||
|
InsertHeadList(&Queue->EntryListHead, Entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertTailList(&Queue->EntryListHead, Entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Queue->RunningThreads < Queue->MaximumThreads && InitialState == 0)
|
||||||
|
{
|
||||||
|
KeDispatcherObjectWake(&Queue->Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||||
|
return InitialState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LONG STDCALL
|
LONG STDCALL
|
||||||
KeInsertHeadQueue(IN PKQUEUE Queue,
|
KeInsertHeadQueue(IN PKQUEUE Queue,
|
||||||
IN PLIST_ENTRY Entry)
|
IN PLIST_ENTRY Entry)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
return KiInsertQueue(Queue,Entry,TRUE);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,8 +108,7 @@ LONG STDCALL
|
||||||
KeInsertQueue(IN PKQUEUE Queue,
|
KeInsertQueue(IN PKQUEUE Queue,
|
||||||
IN PLIST_ENTRY Entry)
|
IN PLIST_ENTRY Entry)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
return KiInsertQueue(Queue,Entry,FALSE);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,16 +117,88 @@ KeRemoveQueue(IN PKQUEUE Queue,
|
||||||
IN KPROCESSOR_MODE WaitMode,
|
IN KPROCESSOR_MODE WaitMode,
|
||||||
IN PLARGE_INTEGER Timeout OPTIONAL)
|
IN PLARGE_INTEGER Timeout OPTIONAL)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PLIST_ENTRY ListEntry;
|
||||||
return NULL;
|
NTSTATUS Status;
|
||||||
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
|
||||||
|
KeAcquireDispatcherDatabaseLock(FALSE);
|
||||||
|
|
||||||
|
//assiciate new thread with queue?
|
||||||
|
if (Thread->Queue != Queue)
|
||||||
|
{
|
||||||
|
//remove association from other queue
|
||||||
|
if (!IsListEmpty(&Thread->QueueListEntry))
|
||||||
|
{
|
||||||
|
RemoveEntryList(&Thread->QueueListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
//associate with this queue
|
||||||
|
InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
|
||||||
|
Queue->RunningThreads++;
|
||||||
|
Thread->Queue = Queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Queue->RunningThreads <= Queue->MaximumThreads && !IsListEmpty(&Queue->EntryListHead))
|
||||||
|
{
|
||||||
|
ListEntry = RemoveHeadList(&Queue->EntryListHead);
|
||||||
|
Queue->Header.SignalState--;
|
||||||
|
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||||
|
return ListEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
//need to wait for it...
|
||||||
|
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||||
|
|
||||||
|
Status = KeWaitForSingleObject(Queue,
|
||||||
|
WrQueue,
|
||||||
|
WaitMode,
|
||||||
|
TRUE,//Alertable,
|
||||||
|
Timeout);
|
||||||
|
|
||||||
|
if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
|
||||||
|
{
|
||||||
|
return (PVOID)Status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeAcquireDispatcherDatabaseLock(FALSE);
|
||||||
|
ListEntry = RemoveHeadList(&Queue->EntryListHead);
|
||||||
|
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||||
|
return ListEntry;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PLIST_ENTRY STDCALL
|
PLIST_ENTRY STDCALL
|
||||||
KeRundownQueue(IN PKQUEUE Queue)
|
KeRundownQueue(IN PKQUEUE Queue)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PLIST_ENTRY EnumEntry;
|
||||||
return NULL;
|
PKTHREAD Thread;
|
||||||
|
|
||||||
|
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
|
||||||
|
|
||||||
|
//FIXME: should we wake thread waiting on a queue?
|
||||||
|
|
||||||
|
KeAcquireDispatcherDatabaseLock(FALSE);
|
||||||
|
|
||||||
|
// Clear Queue and QueueListEntry members of all threads associated with this queue
|
||||||
|
while (!IsListEmpty(&Queue->ThreadListHead))
|
||||||
|
{
|
||||||
|
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
|
||||||
|
InitializeListHead(EnumEntry);
|
||||||
|
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
|
||||||
|
Thread->Queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsListEmpty(&Queue->EntryListHead))
|
||||||
|
EnumEntry = Queue->EntryListHead.Flink;
|
||||||
|
else
|
||||||
|
EnumEntry = NULL;
|
||||||
|
|
||||||
|
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||||
|
|
||||||
|
return EnumEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue