[KERNEL32_VISTA][NTDLL_VISTA][RTL_VISTA] Move Vista Rtl functions from kernel32_vista and ntdll_vista to rtl_vista (#3149)

* Move RtlRunOnce functions from kernel32_vista to rtl_vista and export them from ntdll_vista
* Move condvar.c and srw.c from ntdll_vista to rtl_vista
* Move ntdll_vista build script to a subfolder of ntdll

The RtlRunOnce functions are taken from wine, completely unmodified.
The code that was in kernel32_vista had change that used a global keyed_event handle, but was never initialized, so we were still passing NULL thus using the global ExpCritSecOutOfMemoryEvent.
This commit is contained in:
Timo Kreuzer 2020-09-12 15:04:02 +02:00 committed by GitHub
parent 2aca4b2795
commit 61192390cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 159 additions and 115 deletions

View file

@ -1,4 +1,6 @@
add_subdirectory(nt_0600)
spec2def(ntdll.dll def/ntdll.spec ADD_IMPORTLIB)
add_definitions(

View file

@ -1,20 +1,22 @@
remove_definitions(-D_WIN32_WINNT=0x502 -DWINVER=0x502)
add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600
-D__NTDLL__
-D_NTOSKRNL_
-D_NTSYSTEM_)
spec2def(ntdll_vista.dll ntdll_vista.spec ADD_IMPORTLIB)
add_definitions(
-D__NTDLL__
-D_NTOSKRNL_
-DCRTDLL)
include_directories(
BEFORE include
${REACTOS_SOURCE_DIR}/sdk/include/reactos/subsys)
list(APPEND SOURCE
DllMain.c
condvar.c
srw.c
${CMAKE_CURRENT_BINARY_DIR}/ntdll_vista.def)
add_library(ntdll_vista MODULE ${SOURCE})
set_module_type(ntdll_vista win32dll ENTRYPOINT DllMain 12)
target_link_libraries(ntdll_vista rtl_vista)
if(ARCH STREQUAL "arm")
target_link_libraries(ntdll_vista chkstk)
endif()

View file

@ -8,3 +8,7 @@
@ stdcall RtlReleaseSRWLockShared(ptr)
@ stdcall RtlAcquireSRWLockExclusive(ptr)
@ stdcall RtlReleaseSRWLockExclusive(ptr)
@ stdcall RtlRunOnceInitialize(ptr)
@ stdcall RtlRunOnceBeginInitialize(ptr long ptr)
@ stdcall RtlRunOnceComplete(ptr long ptr)
@ stdcall RtlRunOnceExecuteOnce(ptr ptr ptr ptr)

View file

@ -140,7 +140,6 @@ add_subdirectory(netid)
add_subdirectory(netmsg)
add_subdirectory(newdev)
add_subdirectory(npptools)
add_subdirectory(ntdll_vista)
add_subdirectory(ntdsapi)
add_subdirectory(ntlanman)
add_subdirectory(ntmarta)

View file

@ -15,7 +15,7 @@ list(APPEND SOURCE
add_library(kernel32_vista MODULE ${SOURCE})
set_module_type(kernel32_vista win32dll ENTRYPOINT DllMain 12)
add_importlibs(kernel32_vista kernel32 ntdll)
add_importlibs(kernel32_vista kernel32 ntdll_vista ntdll)
add_delay_importlibs(kernel32_vista ntdll_vista)
add_dependencies(kernel32_vista psdk)
add_cd_file(TARGET kernel32_vista DESTINATION reactos/system32 FOR all)

View file

@ -5,107 +5,8 @@
#include <wine/config.h>
#include <wine/port.h>
/* Taken from Wine ntdll/sync.c */
HANDLE keyed_event = NULL;
static DWORD WINAPI RtlRunOnceBeginInitialize( RTL_RUN_ONCE *once, ULONG flags, void **context )
{
if (flags & RTL_RUN_ONCE_CHECK_ONLY)
{
ULONG_PTR val = (ULONG_PTR)once->Ptr;
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
if ((val & 3) != 2) return STATUS_UNSUCCESSFUL;
if (context) *context = (void *)(val & ~3);
return STATUS_SUCCESS;
}
for (;;)
{
ULONG_PTR next, val = (ULONG_PTR)once->Ptr;
switch (val & 3)
{
case 0: /* first time */
if (!interlocked_cmpxchg_ptr( &once->Ptr,
(flags & RTL_RUN_ONCE_ASYNC) ? (void *)3 : (void *)1, 0 ))
return STATUS_PENDING;
break;
case 1: /* in progress, wait */
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
next = val & ~3;
if (interlocked_cmpxchg_ptr( &once->Ptr, (void *)((ULONG_PTR)&next | 1),
(void *)val ) == (void *)val)
NtWaitForKeyedEvent( keyed_event, &next, FALSE, NULL );
break;
case 2: /* done */
if (context) *context = (void *)(val & ~3);
return STATUS_SUCCESS;
case 3: /* in progress, async */
if (!(flags & RTL_RUN_ONCE_ASYNC)) return STATUS_INVALID_PARAMETER;
return STATUS_PENDING;
}
}
}
static DWORD WINAPI RtlpRunOnceComplete( RTL_RUN_ONCE *once, ULONG flags, void *context )
{
if ((ULONG_PTR)context & 3) return STATUS_INVALID_PARAMETER;
if (flags & RTL_RUN_ONCE_INIT_FAILED)
{
if (context) return STATUS_INVALID_PARAMETER;
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
}
else context = (void *)((ULONG_PTR)context | 2);
for (;;)
{
ULONG_PTR val = (ULONG_PTR)once->Ptr;
switch (val & 3)
{
case 1: /* in progress */
if (interlocked_cmpxchg_ptr( &once->Ptr, context, (void *)val ) != (void *)val) break;
val &= ~3;
while (val)
{
ULONG_PTR next = *(ULONG_PTR *)val;
NtReleaseKeyedEvent( keyed_event, (void *)val, FALSE, NULL );
val = next;
}
return STATUS_SUCCESS;
case 3: /* in progress, async */
if (!(flags & RTL_RUN_ONCE_ASYNC)) return STATUS_INVALID_PARAMETER;
if (interlocked_cmpxchg_ptr( &once->Ptr, context, (void *)val ) != (void *)val) break;
return STATUS_SUCCESS;
default:
return STATUS_UNSUCCESSFUL;
}
}
}
static DWORD WINAPI RtlpRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN func,
void *param, void **context )
{
DWORD ret = RtlRunOnceBeginInitialize( once, 0, context );
if (ret != STATUS_PENDING) return ret;
if (!func( once, param, context ))
{
RtlpRunOnceComplete( once, RTL_RUN_ONCE_INIT_FAILED, NULL );
return STATUS_UNSUCCESSFUL;
}
return RtlpRunOnceComplete( once, 0, context ? *context : NULL );
}
DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN func,
void *param, void **context );
/* Taken from Wine kernel32/sync.c */
@ -114,5 +15,5 @@ static DWORD WINAPI RtlpRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_IN
*/
BOOL NTAPI InitOnceExecuteOnce( INIT_ONCE *once, PINIT_ONCE_FN func, void *param, void **context )
{
return !RtlpRunOnceExecuteOnce( once, (PRTL_RUN_ONCE_INIT_FN)func, param, context );
return !RtlRunOnceExecuteOnce( once, (PRTL_RUN_ONCE_INIT_FN)func, param, context );
}

View file

@ -114,3 +114,13 @@ add_asm_files(rtl_asm ${ASM_SOURCE})
add_library(rtl ${SOURCE} ${rtl_asm})
add_pch(rtl rtl.h SOURCE)
add_dependencies(rtl psdk asm)
list(APPEND SOURCE_VISTA
condvar.c
runonce.c
srw.c
)
add_library(rtl_vista ${SOURCE_VISTA})
add_pch(rtl rtl_vista.h SOURCE_VISTA)
add_dependencies(rtl_vista psdk)

View file

@ -6,8 +6,13 @@
* PROGRAMMER: Alex Ionescu
*/
#ifndef RTL_H
#define RTL_H
#ifndef RTL_VISTA_H
#define RTL_VISTA_H
#undef _WIN32_WINNT
#undef WINVER
#define _WIN32_WINNT 0x600
#define WINVER 0x600
/* We're a core NT DLL, we don't import syscalls */
#define _INC_SWPRINTF_INL_
@ -54,4 +59,4 @@
#define InterlockedBitTestAndSet64 _interlockedbittestandset64
#endif
#endif /* RTL_H */
#endif /* RTL_VISTA_H */

121
sdk/lib/rtl/runonce.c Normal file
View file

@ -0,0 +1,121 @@
/* Taken from Wine ntdll/sync.c */
#include "rtl_vista.h"
#include <wine/config.h>
#include <wine/port.h>
/******************************************************************
* RtlRunOnceInitialize (NTDLL.@)
*/
void WINAPI RtlRunOnceInitialize( RTL_RUN_ONCE *once )
{
once->Ptr = NULL;
}
/******************************************************************
* RtlRunOnceBeginInitialize (NTDLL.@)
*/
DWORD WINAPI RtlRunOnceBeginInitialize( RTL_RUN_ONCE *once, ULONG flags, void **context )
{
if (flags & RTL_RUN_ONCE_CHECK_ONLY)
{
ULONG_PTR val = (ULONG_PTR)once->Ptr;
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
if ((val & 3) != 2) return STATUS_UNSUCCESSFUL;
if (context) *context = (void *)(val & ~3);
return STATUS_SUCCESS;
}
for (;;)
{
ULONG_PTR next, val = (ULONG_PTR)once->Ptr;
switch (val & 3)
{
case 0: /* first time */
if (!interlocked_cmpxchg_ptr( &once->Ptr,
(flags & RTL_RUN_ONCE_ASYNC) ? (void *)3 : (void *)1, 0 ))
return STATUS_PENDING;
break;
case 1: /* in progress, wait */
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
next = val & ~3;
if (interlocked_cmpxchg_ptr( &once->Ptr, (void *)((ULONG_PTR)&next | 1),
(void *)val ) == (void *)val)
NtWaitForKeyedEvent( 0, &next, FALSE, NULL );
break;
case 2: /* done */
if (context) *context = (void *)(val & ~3);
return STATUS_SUCCESS;
case 3: /* in progress, async */
if (!(flags & RTL_RUN_ONCE_ASYNC)) return STATUS_INVALID_PARAMETER;
return STATUS_PENDING;
}
}
}
/******************************************************************
* RtlRunOnceComplete (NTDLL.@)
*/
DWORD WINAPI RtlRunOnceComplete( RTL_RUN_ONCE *once, ULONG flags, void *context )
{
if ((ULONG_PTR)context & 3) return STATUS_INVALID_PARAMETER;
if (flags & RTL_RUN_ONCE_INIT_FAILED)
{
if (context) return STATUS_INVALID_PARAMETER;
if (flags & RTL_RUN_ONCE_ASYNC) return STATUS_INVALID_PARAMETER;
}
else context = (void *)((ULONG_PTR)context | 2);
for (;;)
{
ULONG_PTR val = (ULONG_PTR)once->Ptr;
switch (val & 3)
{
case 1: /* in progress */
if (interlocked_cmpxchg_ptr( &once->Ptr, context, (void *)val ) != (void *)val) break;
val &= ~3;
while (val)
{
ULONG_PTR next = *(ULONG_PTR *)val;
NtReleaseKeyedEvent( 0, (void *)val, FALSE, NULL );
val = next;
}
return STATUS_SUCCESS;
case 3: /* in progress, async */
if (!(flags & RTL_RUN_ONCE_ASYNC)) return STATUS_INVALID_PARAMETER;
if (interlocked_cmpxchg_ptr( &once->Ptr, context, (void *)val ) != (void *)val) break;
return STATUS_SUCCESS;
default:
return STATUS_UNSUCCESSFUL;
}
}
}
/******************************************************************
* RtlRunOnceExecuteOnce (NTDLL.@)
*/
DWORD WINAPI RtlRunOnceExecuteOnce( RTL_RUN_ONCE *once, PRTL_RUN_ONCE_INIT_FN func,
void *param, void **context )
{
DWORD ret = RtlRunOnceBeginInitialize( once, 0, context );
if (ret != STATUS_PENDING) return ret;
if (!func( once, param, context ))
{
RtlRunOnceComplete( once, RTL_RUN_ONCE_INIT_FAILED, NULL );
return STATUS_UNSUCCESSFUL;
}
return RtlRunOnceComplete( once, 0, context ? *context : NULL );
}