Author: akhaldi Date: Sat Feb 28 15:46:43 2015 New Revision: 66500
URL: http://svn.reactos.org/svn/reactos?rev=66500&view=rev Log: [KERNEL32_VISTA] Add and export InitOnceExecuteOnce(). CORE-9246
Added: trunk/reactos/dll/win32/kernel32_vista/InitOnceExecuteOnce.c (with props) Modified: trunk/reactos/dll/win32/kernel32_vista/CMakeLists.txt trunk/reactos/dll/win32/kernel32_vista/kernel32_vista.spec
Modified: trunk/reactos/dll/win32/kernel32_vista/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32_vista/CM... ============================================================================== --- trunk/reactos/dll/win32/kernel32_vista/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32_vista/CMakeLists.txt [iso-8859-1] Sat Feb 28 15:46:43 2015 @@ -8,15 +8,11 @@ list(APPEND SOURCE DllMain.c GetTickCount64.c + InitOnceExecuteOnce.c ${CMAKE_CURRENT_BINARY_DIR}/kernel32_vista.def)
add_library(kernel32_vista SHARED ${SOURCE}) set_module_type(kernel32_vista win32dll HOTPATCHABLE ENTRYPOINT DllMain 12) -add_importlibs(kernel32_vista kernel32) - -if(MSVC) - add_importlibs(kernel32_vista ntdll) -endif() - +add_importlibs(kernel32_vista kernel32 ntdll) add_dependencies(kernel32_vista psdk) add_cd_file(TARGET kernel32_vista DESTINATION reactos/system32 FOR all)
Added: trunk/reactos/dll/win32/kernel32_vista/InitOnceExecuteOnce.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32_vista/In... ============================================================================== --- trunk/reactos/dll/win32/kernel32_vista/InitOnceExecuteOnce.c (added) +++ trunk/reactos/dll/win32/kernel32_vista/InitOnceExecuteOnce.c [iso-8859-1] Sat Feb 28 15:46:43 2015 @@ -0,0 +1,118 @@ + +#include "k32_vista.h" + +#include <ndk/exfuncs.h> +#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 ); +} + +/* Taken from Wine kernel32/sync.c */ + +/* + * @implemented + */ +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 ); +}
Propchange: trunk/reactos/dll/win32/kernel32_vista/InitOnceExecuteOnce.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/win32/kernel32_vista/kernel32_vista.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32_vista/ke... ============================================================================== --- trunk/reactos/dll/win32/kernel32_vista/kernel32_vista.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32_vista/kernel32_vista.spec [iso-8859-1] Sat Feb 28 15:46:43 2015 @@ -1,2 +1,3 @@
@ stdcall -ret64 GetTickCount64() +@ stdcall InitOnceExecuteOnce(ptr ptr ptr ptr)