ntdll: Implement the RunOnce functions.
This commit is contained in:
parent
a205171b4f
commit
fcb3e60332
|
@ -816,6 +816,9 @@
|
|||
@ stub RtlRevertMemoryStream
|
||||
@ stub RtlRunDecodeUnicodeString
|
||||
@ stub RtlRunEncodeUnicodeString
|
||||
@ stdcall RtlRunOnceBeginInitialize(ptr long ptr)
|
||||
@ stdcall RtlRunOnceComplete(ptr long ptr)
|
||||
@ stdcall RtlRunOnceExecuteOnce(ptr ptr ptr ptr)
|
||||
@ stdcall RtlRunOnceInitialize(ptr)
|
||||
@ stdcall RtlSecondsSince1970ToTime(long ptr)
|
||||
@ stdcall RtlSecondsSince1980ToTime(long ptr)
|
||||
|
|
|
@ -241,6 +241,7 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
|
|||
}
|
||||
|
||||
extern mode_t FILE_umask DECLSPEC_HIDDEN;
|
||||
extern HANDLE keyed_event DECLSPEC_HIDDEN;
|
||||
|
||||
/* Register functions */
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
@ -60,6 +61,8 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
|
||||
HANDLE keyed_event = NULL;
|
||||
|
||||
/* creates a struct security_descriptor and contained information in one contiguous piece of memory */
|
||||
NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd,
|
||||
data_size_t *server_sd_len)
|
||||
|
@ -1236,7 +1239,117 @@ NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue,
|
|||
return status;
|
||||
}
|
||||
|
||||
VOID NTAPI RtlRunOnceInitialize(PRTL_RUN_ONCE initonce)
|
||||
/******************************************************************
|
||||
* RtlRunOnceInitialize (NTDLL.@)
|
||||
*/
|
||||
void WINAPI RtlRunOnceInitialize( RTL_RUN_ONCE *once )
|
||||
{
|
||||
initonce->Ptr = NULL;
|
||||
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( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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 );
|
||||
}
|
||||
|
|
|
@ -308,6 +308,8 @@ HANDLE thread_init(void)
|
|||
|
||||
fill_cpu_info();
|
||||
|
||||
NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 );
|
||||
|
||||
return exe_file;
|
||||
}
|
||||
|
||||
|
|
|
@ -5163,7 +5163,7 @@ typedef DWORD WINAPI RTL_RUN_ONCE_INIT_FN(PRTL_RUN_ONCE, PVOID, PVOID*);
|
|||
typedef RTL_RUN_ONCE_INIT_FN *PRTL_RUN_ONCE_INIT_FN;
|
||||
NTSYSAPI VOID WINAPI RtlRunOnceInitialize(PRTL_RUN_ONCE);
|
||||
NTSYSAPI DWORD WINAPI RtlRunOnceExecuteOnce(PRTL_RUN_ONCE,PRTL_RUN_ONCE_INIT_FN,PVOID,PVOID*);
|
||||
NTSYSAPI DWORD WINAPI RtlRunOnceBeginInitialize(PRTL_RUN_ONCE, DWORD, PBOOL, PVOID*);
|
||||
NTSYSAPI DWORD WINAPI RtlRunOnceBeginInitialize(PRTL_RUN_ONCE, DWORD, PVOID*);
|
||||
NTSYSAPI DWORD WINAPI RtlRunOnceComplete(PRTL_RUN_ONCE, DWORD, PVOID);
|
||||
|
||||
#include <pshpack8.h>
|
||||
|
|
Loading…
Reference in New Issue