kernel32: Some tests for blocking initialization with InitOnceBeginInitialize().
This commit is contained in:
parent
7d1e2741ce
commit
04f588e63a
|
@ -39,6 +39,8 @@ static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFI
|
||||||
static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
|
static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
|
||||||
static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
|
static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
|
||||||
static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
|
static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
|
||||||
|
static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
|
||||||
|
static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
|
||||||
|
|
||||||
static void test_signalandwait(void)
|
static void test_signalandwait(void)
|
||||||
{
|
{
|
||||||
|
@ -1138,11 +1140,13 @@ static void test_WaitForMultipleObjects(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL g_initcallback_ret, g_initcallback_called;
|
static BOOL g_initcallback_ret, g_initcallback_called;
|
||||||
|
static void *g_initctxt;
|
||||||
|
|
||||||
BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
|
BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
|
||||||
{
|
{
|
||||||
g_initcallback_called = TRUE;
|
g_initcallback_called = TRUE;
|
||||||
/* zero bit set means here that initialization is taking place - initialization locked */
|
/* zero bit set means here that initialization is taking place - initialization locked */
|
||||||
|
ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
|
||||||
ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
|
ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
|
||||||
ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
|
ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
|
||||||
return g_initcallback_ret;
|
return g_initcallback_ret;
|
||||||
|
@ -1151,8 +1155,7 @@ BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctx
|
||||||
static void test_initonce(void)
|
static void test_initonce(void)
|
||||||
{
|
{
|
||||||
INIT_ONCE initonce;
|
INIT_ONCE initonce;
|
||||||
void *ctxt;
|
BOOL ret, pending;
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
|
if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
|
||||||
{
|
{
|
||||||
|
@ -1160,48 +1163,79 @@ static void test_initonce(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* blocking initialization with callback */
|
||||||
initonce.Ptr = (void*)0xdeadbeef;
|
initonce.Ptr = (void*)0xdeadbeef;
|
||||||
pInitOnceInitialize(&initonce);
|
pInitOnceInitialize(&initonce);
|
||||||
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
|
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
|
||||||
|
|
||||||
/* initialisation completed successfully */
|
/* initialisation completed successfully */
|
||||||
g_initcallback_ret = TRUE;
|
g_initcallback_ret = TRUE;
|
||||||
ctxt = NULL;
|
g_initctxt = NULL;
|
||||||
ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
|
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
|
||||||
ok(ret, "got wrong ret value %d\n", ret);
|
ok(ret, "got wrong ret value %d\n", ret);
|
||||||
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
|
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
|
||||||
ok(ctxt == (void*)0x0, "got %p\n", ctxt);
|
ok(g_initctxt == (void*)0x0, "got %p\n", g_initctxt);
|
||||||
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
||||||
|
|
||||||
/* so it's been called already so won't be called again */
|
/* so it's been called already so won't be called again */
|
||||||
ctxt = NULL;
|
g_initctxt = NULL;
|
||||||
g_initcallback_called = FALSE;
|
g_initcallback_called = FALSE;
|
||||||
ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
|
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
|
||||||
ok(ret, "got wrong ret value %d\n", ret);
|
ok(ret, "got wrong ret value %d\n", ret);
|
||||||
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
|
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
|
||||||
ok(ctxt == (void*)0, "got %p\n", ctxt);
|
ok(g_initctxt == (void*)0, "got %p\n", g_initctxt);
|
||||||
ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
|
ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
|
||||||
|
|
||||||
pInitOnceInitialize(&initonce);
|
pInitOnceInitialize(&initonce);
|
||||||
g_initcallback_called = FALSE;
|
g_initcallback_called = FALSE;
|
||||||
/* 2 lower order bits should never be used, you'll get a crash in result */
|
/* 2 lower order bits should never be used, you'll get a crash in result */
|
||||||
ctxt = (void*)0xFFFFFFF0;
|
g_initctxt = (void*)0xFFFFFFF0;
|
||||||
ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
|
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
|
||||||
ok(ret, "got wrong ret value %d\n", ret);
|
ok(ret, "got wrong ret value %d\n", ret);
|
||||||
ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
|
ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
|
||||||
ok(ctxt == (void*)0xFFFFFFF0, "got %p\n", ctxt);
|
ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
|
||||||
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
||||||
|
|
||||||
/* callback failed */
|
/* callback failed */
|
||||||
g_initcallback_ret = FALSE;
|
g_initcallback_ret = FALSE;
|
||||||
g_initcallback_called = FALSE;
|
g_initcallback_called = FALSE;
|
||||||
ctxt = NULL;
|
g_initctxt = NULL;
|
||||||
pInitOnceInitialize(&initonce);
|
pInitOnceInitialize(&initonce);
|
||||||
ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
|
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
|
||||||
ok(!ret, "got wrong ret value %d\n", ret);
|
ok(!ret, "got wrong ret value %d\n", ret);
|
||||||
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
|
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
|
||||||
ok(ctxt == NULL, "got %p\n", ctxt);
|
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
|
||||||
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
|
||||||
|
|
||||||
|
/* blocking initialzation without a callback */
|
||||||
|
pInitOnceInitialize(&initonce);
|
||||||
|
g_initctxt = NULL;
|
||||||
|
pending = FALSE;
|
||||||
|
ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
|
||||||
|
ok(ret, "got wrong ret value %d\n", ret);
|
||||||
|
ok(pending, "got %d\n", pending);
|
||||||
|
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
|
||||||
|
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
|
||||||
|
/* another attempt to begin initialization with block a single thread */
|
||||||
|
|
||||||
|
g_initctxt = NULL;
|
||||||
|
pending = 0xf;
|
||||||
|
ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
|
||||||
|
ok(!ret, "got wrong ret value %d\n", ret);
|
||||||
|
ok(pending == 0xf, "got %d\n", pending);
|
||||||
|
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
|
||||||
|
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
|
||||||
|
|
||||||
|
g_initctxt = (void*)0xdeadbee0;
|
||||||
|
ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
|
||||||
|
ok(!ret, "got wrong ret value %d\n", ret);
|
||||||
|
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
|
||||||
|
|
||||||
|
/* once failed already */
|
||||||
|
g_initctxt = (void*)0xdeadbee0;
|
||||||
|
ret = pInitOnceComplete(&initonce, 0, g_initctxt);
|
||||||
|
ok(ret, "got wrong ret value %d\n", ret);
|
||||||
|
ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(sync)
|
START_TEST(sync)
|
||||||
|
@ -1218,6 +1252,8 @@ START_TEST(sync)
|
||||||
pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
|
pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
|
||||||
pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
|
pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
|
||||||
pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
|
pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
|
||||||
|
pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
|
||||||
|
pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
|
||||||
|
|
||||||
test_signalandwait();
|
test_signalandwait();
|
||||||
test_mutex();
|
test_mutex();
|
||||||
|
|
|
@ -1321,6 +1321,9 @@ typedef RTL_RUN_ONCE INIT_ONCE;
|
||||||
typedef PRTL_RUN_ONCE PINIT_ONCE;
|
typedef PRTL_RUN_ONCE PINIT_ONCE;
|
||||||
typedef PRTL_RUN_ONCE LPINIT_ONCE;
|
typedef PRTL_RUN_ONCE LPINIT_ONCE;
|
||||||
#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
|
#define INIT_ONCE_STATIC_INIT RTL_RUN_ONCE_INIT
|
||||||
|
#define INIT_ONCE_CHECK_ONLY RTL_RUN_ONCE_CHECK_ONLY
|
||||||
|
#define INIT_ONCE_ASYNC RTL_RUN_ONCE_ASYNC
|
||||||
|
#define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED
|
||||||
/* initialization callback prototype */
|
/* initialization callback prototype */
|
||||||
typedef BOOL (WINAPI *PINIT_ONCE_FN)(PINIT_ONCE,PVOID,PVOID*);
|
typedef BOOL (WINAPI *PINIT_ONCE_FN)(PINIT_ONCE,PVOID,PVOID*);
|
||||||
|
|
||||||
|
@ -1884,6 +1887,7 @@ WINADVAPI BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR,
|
||||||
WINADVAPI BOOL WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE);
|
WINADVAPI BOOL WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE);
|
||||||
WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER);
|
WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER);
|
||||||
WINBASEAPI VOID WINAPI InitializeSRWLock(PSRWLOCK);
|
WINBASEAPI VOID WINAPI InitializeSRWLock(PSRWLOCK);
|
||||||
|
WINBASEAPI BOOL WINAPI InitOnceExecuteOnce(PINIT_ONCE,PINIT_ONCE_FN,PVOID,PVOID*);
|
||||||
WINBASEAPI VOID WINAPI InitOnceInitialize(PINIT_ONCE);
|
WINBASEAPI VOID WINAPI InitOnceInitialize(PINIT_ONCE);
|
||||||
WINBASEAPI PSLIST_ENTRY WINAPI InterlockedFlushSList(PSLIST_HEADER);
|
WINBASEAPI PSLIST_ENTRY WINAPI InterlockedFlushSList(PSLIST_HEADER);
|
||||||
WINBASEAPI PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER);
|
WINBASEAPI PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER);
|
||||||
|
|
|
@ -5092,7 +5092,14 @@ typedef union _RTL_RUN_ONCE {
|
||||||
PVOID Ptr;
|
PVOID Ptr;
|
||||||
} RTL_RUN_ONCE, *PRTL_RUN_ONCE;
|
} RTL_RUN_ONCE, *PRTL_RUN_ONCE;
|
||||||
|
|
||||||
NTSYSAPI VOID NTAPI RtlRunOnceInitialize(PRTL_RUN_ONCE);
|
#define RTL_RUN_ONCE_CHECK_ONLY 0x00000001
|
||||||
|
#define RTL_RUN_ONCE_ASYNC 0x00000002
|
||||||
|
#define RTL_RUN_ONCE_INIT_FAILED 0x00000004
|
||||||
|
|
||||||
|
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*);
|
||||||
|
|
||||||
#include <pshpack8.h>
|
#include <pshpack8.h>
|
||||||
typedef struct _IO_COUNTERS {
|
typedef struct _IO_COUNTERS {
|
||||||
|
|
Loading…
Reference in New Issue