ReactOS 0.4.15-dev-7961-gdcf9eb0
InitOnce.c File Reference
#include "precomp.h"
Include dependency graph for InitOnce.c:

Go to the source code of this file.

Typedefs

typedef VOID WINAPI FN_InitOnceInitialize(_Out_ PINIT_ONCE InitOnce)
 
typedef BOOL WINAPI FN_InitOnceExecuteOnce(_Inout_ PINIT_ONCE InitOnce, _In_ __callback PINIT_ONCE_FN InitFn, _Inout_opt_ PVOID Parameter, _Outptr_opt_result_maybenull_ LPVOID *Context)
 
typedef BOOL WINAPI FN_InitOnceBeginInitialize(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _Out_ PBOOL fPending, _Outptr_opt_result_maybenull_ LPVOID *lpContext)
 
typedef BOOL WINAPI FN_InitOnceComplete(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _In_opt_ LPVOID lpContext)
 

Functions

static VOID InitWorker (_Inout_ PULONG InitCount, _Out_ PULONG_PTR Context)
 
static _Success_ (return !=FALSE)
 
 START_TEST (InitOnce)
 

Variables

static ULONG g_ulRandom
 

Typedef Documentation

◆ FN_InitOnceBeginInitialize

typedef BOOL WINAPI FN_InitOnceBeginInitialize(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _Out_ PBOOL fPending, _Outptr_opt_result_maybenull_ LPVOID *lpContext)

Definition at line 27 of file InitOnce.c.

◆ FN_InitOnceComplete

typedef BOOL WINAPI FN_InitOnceComplete(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _In_opt_ LPVOID lpContext)

Definition at line 36 of file InitOnce.c.

◆ FN_InitOnceExecuteOnce

◆ FN_InitOnceInitialize

typedef VOID WINAPI FN_InitOnceInitialize(_Out_ PINIT_ONCE InitOnce)

Definition at line 13 of file InitOnce.c.

Function Documentation

◆ _Success_()

static _Success_ ( return = FALSE)
static

Definition at line 55 of file InitOnce.c.

62{
63 if (!Parameter || !Context)
64 {
65 return FALSE;
66 }
67
69 return TRUE;
70}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static VOID InitWorker(_Inout_ PULONG InitCount, _Out_ PULONG_PTR Context)
Definition: InitOnce.c:45
uint32_t * PULONG_PTR
Definition: typedefs.h:65
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

◆ InitWorker()

static VOID InitWorker ( _Inout_ PULONG  InitCount,
_Out_ PULONG_PTR  Context 
)
static

Definition at line 45 of file InitOnce.c.

46{
47 /* Increase the initialization count */
48 (*InitCount)++;
49
50 /* Output context data */
52}
#define ULONG_PTR
Definition: config.h:101
static ULONG g_ulRandom
Definition: InitOnce.c:41

Referenced by _Success_(), and START_TEST().

◆ START_TEST()

START_TEST ( InitOnce  )

Definition at line 72 of file InitOnce.c.

73{
74 BOOL bRet, fPending;
75 ULONG i, ulInitCount, ulSeed;
76 ULONG_PTR ulContextData, ulTempContext;
77 DWORD dwError;
78
80 FN_InitOnceInitialize* pfnInitOnceInitialize;
81 FN_InitOnceExecuteOnce* pfnInitOnceExecuteOnce;
82 FN_InitOnceBeginInitialize* pfnInitOnceBeginInitialize;
83 FN_InitOnceComplete* pfnInitOnceComplete;
84
85 /* Load functions */
86 hKernel32 = GetModuleHandleW(L"kernel32.dll");
87 if (!hKernel32)
88 {
89 skip("Module kernel32 not found\n");
90 return;
91 }
92 pfnInitOnceInitialize = (FN_InitOnceInitialize*)GetProcAddress(hKernel32, "InitOnceInitialize");
93 pfnInitOnceExecuteOnce = (FN_InitOnceExecuteOnce*)GetProcAddress(hKernel32, "InitOnceExecuteOnce");
94 pfnInitOnceBeginInitialize = (FN_InitOnceBeginInitialize*)GetProcAddress(hKernel32, "InitOnceBeginInitialize");
95 pfnInitOnceComplete = (FN_InitOnceComplete*)GetProcAddress(hKernel32, "InitOnceComplete");
96
97 /*
98 * Use a random as output context data,
99 * which the low-order INIT_ONCE_CTX_RESERVED_BITS bits should be zero.
100 */
101 ulSeed = (ULONG)(ULONG_PTR)&ulSeed ^ GetTickCount();
102 g_ulRandom = RtlRandom(&ulSeed);
103 for (i = 0; i < INIT_ONCE_CTX_RESERVED_BITS; i++)
104 {
105 g_ulRandom &= (~(1 << i));
106 }
107
108 /* Initialize One-Time initialization structure */
109 INIT_ONCE InitOnce = { (PVOID)(ULONG_PTR)0xDEADBEEF };
110 if (pfnInitOnceInitialize)
111 {
112 pfnInitOnceInitialize(&InitOnce);
113 }
114 else
115 {
116 skip("InitOnceInitialize not found\n");
118 }
119
120 if (!pfnInitOnceExecuteOnce)
121 {
122 skip("InitOnceExecuteOnce not found\n");
123 goto _test_sync;
124 }
125
126 /*
127 * Perform synchronous initialization by using InitOnceExecuteOnce,
128 * which executes user-defined callback to initialize.
129 * Call InitOnceExecuteOnce twice will success,
130 * initialization count should be 1 and retrieve correct context data.
131 */
132 ulInitCount = 0;
133 ulContextData = MAXULONG;
134 bRet = pfnInitOnceExecuteOnce(&InitOnce, InitOnceProc, &ulInitCount, (LPVOID*)&ulContextData);
135 ok(bRet, "InitOnceExecuteOnce failed with %lu\n", GetLastError());
136 if (bRet)
137 {
138 /* Call InitOnceExecuteOnce again and check output values if the first call succeeded */
139 bRet = pfnInitOnceExecuteOnce(&InitOnce,
140 InitOnceProc,
141 &ulInitCount,
142 (LPVOID*)&ulContextData);
143 ok(bRet, "InitOnceExecuteOnce failed with %lu\n", GetLastError());
144 ok(ulInitCount == 1, "ulInitCount is not 1\n");
145 ok(ulContextData == g_ulRandom, "Output ulContextData is incorrect\n");
146 }
147
148_test_sync:
149 if (!pfnInitOnceBeginInitialize || !pfnInitOnceComplete)
150 {
151 skip("InitOnceBeginInitialize or InitOnceComplete not found\n");
152 return;
153 }
154
155 /* Re-initialize One-Time initialization structure by using INIT_ONCE_STATIC_INIT */
157 ulContextData = 0xdeadbeef;
158
159 /* Perform synchronous initialization by using InitOnceBeginInitialize */
160 fPending = FALSE;
161 bRet = pfnInitOnceBeginInitialize(&InitOnce, 0, &fPending, (LPVOID*)&ulContextData);
162 ok(bRet, "InitOnceBeginInitialize failed with %lu\n", GetLastError());
163 if (!bRet)
164 {
165 goto _test_async;
166 }
167 ok(fPending, "fPending is not TRUE after the first success InitOnceBeginInitialize\n");
168 if (!fPending)
169 {
170 goto _test_async;
171 }
172
173 /* Call again to check whether initialization has completed */
174 fPending = 0xdeadbeef;
175 bRet = pfnInitOnceBeginInitialize(&InitOnce,
177 &fPending,
178 (LPVOID*)&ulContextData);
179 ok(bRet == FALSE, "InitOnceBeginInitialize should fail\n");
180 ok(fPending == 0xdeadbeef, "fPending should be unmodified\n");
181 ok(ulContextData == 0xdeadbeef, "ulContextData should be unmodified\n");
182
183 /* Complete the initialization */
184 InitWorker(&ulInitCount, &ulTempContext);
185 bRet = pfnInitOnceComplete(&InitOnce, 0, (LPVOID)ulTempContext);
186 ok(bRet, "InitOnceComplete failed with %lu\n", GetLastError());
187 if (!bRet)
188 {
189 goto _test_async;
190 }
191
192 /*
193 * Initialization is completed, call InitOnceBeginInitialize with
194 * INIT_ONCE_CHECK_ONLY should retrieve status and context data successfully
195 */
196 bRet = pfnInitOnceBeginInitialize(&InitOnce,
198 &fPending,
199 (LPVOID*)&ulContextData);
200 ok(bRet && !fPending && ulContextData == g_ulRandom,
201 "InitOnceBeginInitialize returns incorrect result for a completed initialization\n");
202
203_test_async:
205
206 /* Perform asynchronous initialization */
207 fPending = FALSE;
208 bRet = pfnInitOnceBeginInitialize(&InitOnce,
210 &fPending,
211 (LPVOID*)&ulContextData);
212 ok(bRet, "InitOnceBeginInitialize failed with %lu\n", GetLastError());
213 if (!bRet)
214 {
215 return;
216 }
217 ok(fPending, "fPending is not TRUE after a success InitOnceBeginInitialize\n");
218 if (!fPending)
219 {
220 return;
221 }
222
223 /*
224 * Now the initialization is in progress but not completed yet,
225 * call InitOnceBeginInitialize again without INIT_ONCE_ASYNC is invalid,
226 * should fail with ERROR_INVALID_PARAMETER
227 */
228 bRet = pfnInitOnceBeginInitialize(&InitOnce, 0, &fPending, (LPVOID*)&ulContextData);
229 ok(!bRet, "InitOnceBeginInitialize should not success\n");
230 if (!bRet)
231 {
232 dwError = GetLastError();
233 ok(dwError == ERROR_INVALID_PARAMETER,
234 "Last error is %lu, but %u is expected\n",
235 dwError,
237 }
238
239 /*
240 * Call InitOnceBeginInitialize again with INIT_ONCE_ASYNC
241 * should success because initialization could be executed in parallel
242 */
243 bRet = pfnInitOnceBeginInitialize(&InitOnce,
245 &fPending,
246 (LPVOID*)&ulContextData);
247 ok(bRet, "InitOnceBeginInitialize failed with %lu\n", GetLastError());
248 if (!bRet)
249 {
250 return;
251 }
252 ok(fPending, "fPending is not TRUE after a success InitOnceBeginInitialize\n");
253 if (!fPending)
254 {
255 return;
256 }
257
258 /* Complete the initialization once */
259 InitWorker(&ulInitCount, &ulTempContext);
260 bRet = pfnInitOnceComplete(&InitOnce, INIT_ONCE_ASYNC, (LPVOID)ulTempContext);
261 ok(bRet, "InitOnceComplete failed with %lu\n", GetLastError());
262 if (!bRet)
263 {
264 return;
265 }
266
267 /* Subsequent InitOnceComplete should fail with ERROR_GEN_FAILURE */
268 bRet = pfnInitOnceComplete(&InitOnce, INIT_ONCE_ASYNC, (LPVOID)ulTempContext);
269 ok(!bRet, "InitOnceComplete should not success\n");
270 if (!bRet)
271 {
272 dwError = GetLastError();
273 ok(dwError == ERROR_GEN_FAILURE,
274 "Last error is %lu, but %u is expected\n",
275 dwError,
277 }
278
279 /*
280 * Initialization is completed, call InitOnceBeginInitialize with
281 * INIT_ONCE_CHECK_ONLY should retrieve status and context data successfully
282 */
283 bRet = pfnInitOnceBeginInitialize(&InitOnce,
285 &fPending,
286 (LPVOID*)&ulContextData);
287 ok(bRet && !fPending && ulContextData == g_ulRandom,
288 "InitOnceBeginInitialize returns incorrect result for a completed initialization\n");
289
290 return;
291}
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOL WINAPI FN_InitOnceBeginInitialize(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _Out_ PBOOL fPending, _Outptr_opt_result_maybenull_ LPVOID *lpContext)
Definition: InitOnce.c:27
BOOL WINAPI FN_InitOnceComplete(_Inout_ LPINIT_ONCE lpInitOnce, _In_ DWORD dwFlags, _In_opt_ LPVOID lpContext)
Definition: InitOnce.c:36
VOID WINAPI FN_InitOnceInitialize(_Out_ PINIT_ONCE InitOnce)
Definition: InitOnce.c:13
BOOL WINAPI FN_InitOnceExecuteOnce(_Inout_ PINIT_ONCE InitOnce, _In_ __callback PINIT_ONCE_FN InitFn, _Inout_opt_ PVOID Parameter, _Outptr_opt_result_maybenull_ LPVOID *Context)
Definition: InitOnce.c:18
HANDLE hKernel32
Definition: locale.c:13
NTSYSAPI ULONG NTAPI RtlRandom(_Inout_ PULONG Seed)
#define L(x)
Definition: ntvdm.h:50
#define MAXULONG
Definition: typedefs.h:251
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define INIT_ONCE_CHECK_ONLY
Definition: winbase.h:3935
#define INIT_ONCE_ASYNC
Definition: winbase.h:3936
RTL_RUN_ONCE INIT_ONCE
Definition: winbase.h:3931
#define INIT_ONCE_CTX_RESERVED_BITS
Definition: winbase.h:3939
#define INIT_ONCE_STATIC_INIT
Definition: winbase.h:612
#define ERROR_GEN_FAILURE
Definition: winerror.h:134

Variable Documentation

◆ g_ulRandom

ULONG g_ulRandom
static

Definition at line 41 of file InitOnce.c.

Referenced by InitWorker(), and START_TEST().