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/CMakeLists.txt?rev=66500&r1=66499&r2=66500&view=diff
==============================================================================
--- 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/InitOnceExecuteOnce.c?rev=66500
==============================================================================
--- 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/kernel32_vista.spec?rev=66500&r1=66499&r2=66500&view=diff
==============================================================================
--- 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)