diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in index afb22fe3e08..8cafaada85a 100644 --- a/dlls/ntoskrnl.exe/Makefile.in +++ b/dlls/ntoskrnl.exe/Makefile.in @@ -5,6 +5,7 @@ DELAYIMPORTS = setupapi user32 C_SRCS = \ instr.c \ - ntoskrnl.c + ntoskrnl.c \ + sync.c RC_SRCS = ntoskrnl.rc diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 3b42e29b274..4c84a789d6c 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2488,19 +2488,6 @@ NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object, return STATUS_NOT_IMPLEMENTED; } -/*********************************************************************** - * KeWaitForMultipleObjects (NTOSKRNL.EXE.@) - */ -NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG Count, PVOID Object[], WAIT_TYPE WaitType, - KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, PLARGE_INTEGER Timeout, - PKWAIT_BLOCK WaitBlockArray) -{ - FIXME( "stub: %u, %p, %d, %d, %d, %d, %p, %p\n", Count, Object, WaitType, WaitReason, WaitMode, - Alertable, Timeout, WaitBlockArray ); - return STATUS_NOT_IMPLEMENTED; -} - /*********************************************************************** * IoRegisterFileSystem (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c new file mode 100644 index 00000000000..19af4f677a5 --- /dev/null +++ b/dlls/ntoskrnl.exe/sync.c @@ -0,0 +1,114 @@ +/* + * Kernel synchronization + * + * Copyright (C) 2018 Zebediah Figura + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "ddk/ntddk.h" +#include "ddk/wdm.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl); + +enum object_type +{ + TYPE_MANUAL_EVENT = 0, + TYPE_AUTO_EVENT = 1, +}; + +static CRITICAL_SECTION sync_cs; +static CRITICAL_SECTION_DEBUG sync_cs_debug = +{ + 0, 0, &sync_cs, + { &sync_cs_debug.ProcessLocksList, &sync_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": sync_cs") } +}; +static CRITICAL_SECTION sync_cs = { &sync_cs_debug, -1, 0, 0, 0, 0 }; + +/*********************************************************************** + * KeWaitForMultipleObjects (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[], + WAIT_TYPE wait_type, KWAIT_REASON reason, KPROCESSOR_MODE mode, + BOOLEAN alertable, LARGE_INTEGER *timeout, KWAIT_BLOCK *wait_blocks) +{ + DISPATCHER_HEADER **objs = (DISPATCHER_HEADER **)pobjs; + HANDLE handles[MAXIMUM_WAIT_OBJECTS]; + NTSTATUS ret; + ULONG i; + + TRACE("count %u, objs %p, wait_type %u, reason %u, mode %d, alertable %u, timeout %p, wait_blocks %p.\n", + count, objs, wait_type, reason, mode, alertable, timeout, wait_blocks); + + /* We co-opt DISPATCHER_HEADER.WaitListHead: + * Blink stores a handle to the synchronization object, + * Flink stores the number of threads currently waiting on this object. */ + + EnterCriticalSection( &sync_cs ); + for (i = 0; i < count; i++) + { + ++*((ULONG_PTR *)&objs[i]->WaitListHead.Flink); + if (!objs[i]->WaitListHead.Blink) + { + switch (objs[i]->Type) + { + case TYPE_MANUAL_EVENT: + objs[i]->WaitListHead.Blink = CreateEventW( NULL, TRUE, objs[i]->SignalState, NULL ); + break; + case TYPE_AUTO_EVENT: + objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL ); + break; + } + } + + handles[i] = objs[i]->WaitListHead.Blink; + } + LeaveCriticalSection( &sync_cs ); + + ret = NtWaitForMultipleObjects( count, handles, (wait_type == WaitAny), alertable, timeout ); + + EnterCriticalSection( &sync_cs ); + for (i = 0; i < count; i++) + { + if (ret == i || (!ret && wait_type == WaitAll)) + { + switch (objs[i]->Type) + { + case TYPE_AUTO_EVENT: + objs[i]->SignalState = FALSE; + break; + } + } + + if (!--*((ULONG_PTR *)&objs[i]->WaitListHead.Flink)) + { + CloseHandle(objs[i]->WaitListHead.Blink); + objs[i]->WaitListHead.Blink = NULL; + } + } + LeaveCriticalSection( &sync_cs ); + + return ret; +} diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index fdf035d148a..dc051e1e182 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -140,15 +140,6 @@ typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION LARGE_INTEGER ValidDataLength; } FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; -typedef struct _KWAIT_BLOCK { - LIST_ENTRY WaitListEntry; - struct _KTHREAD *RESTRICTED_POINTER Thread; - PVOID Object; - struct _KWAIT_BLOCK *RESTRICTED_POINTER NextWaitBlock; - USHORT WaitKey; - USHORT WaitType; -} KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK; - typedef struct _RTL_BALANCED_LINKS { struct _RTL_BALANCED_LINKS *Parent; struct _RTL_BALANCED_LINKS *LeftChild; diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index cd057d5a9f4..ec2fc151ec5 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -144,6 +144,15 @@ typedef enum _KWAIT_REASON MaximumWaitReason, } KWAIT_REASON; +typedef struct _KWAIT_BLOCK { + LIST_ENTRY WaitListEntry; + struct _KTHREAD *RESTRICTED_POINTER Thread; + PVOID Object; + struct _KWAIT_BLOCK *RESTRICTED_POINTER NextWaitBlock; + USHORT WaitKey; + USHORT WaitType; +} KWAIT_BLOCK, *PKWAIT_BLOCK, *RESTRICTED_POINTER PRKWAIT_BLOCK; + typedef struct _ALLOCATE_FUNCTION *PALLOCATE_FUNCTION; typedef struct _IO_TIMER *PIO_TIMER; typedef struct _IO_TIMER_ROUTINE *PIO_TIMER_ROUTINE; @@ -1422,6 +1431,7 @@ LONG WINAPI KeResetEvent(PRKEVENT); LONG WINAPI KeSetEvent(PRKEVENT,KPRIORITY,BOOLEAN); KPRIORITY WINAPI KeSetPriorityThread(PKTHREAD,KPRIORITY); void WINAPI KeSetSystemAffinityThread(KAFFINITY); +NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG,void*[],WAIT_TYPE,KWAIT_REASON,KPROCESSOR_MODE,BOOLEAN,LARGE_INTEGER*,KWAIT_BLOCK*); PVOID WINAPI MmAllocateContiguousMemory(SIZE_T,PHYSICAL_ADDRESS); PVOID WINAPI MmAllocateNonCachedMemory(SIZE_T);