ReactOS 0.4.16-dev-2216-ga08d639
fiber.c
Go to the documentation of this file.
1/*
2 * Unit tests for fiber functions
3 *
4 * Copyright (c) 2010 André Hentschel
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22
23#include <ntstatus.h>
24#define WIN32_NO_STATUS
25#include <winternl.h>
26#include "wine/test.h"
27#include <winuser.h>
28
30static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID);
31static BOOL (WINAPI *pConvertFiberToThread)(void);
32static void (WINAPI *pSwitchToFiber)(LPVOID);
33static void (WINAPI *pDeleteFiber)(LPVOID);
34static LPVOID (WINAPI *pConvertThreadToFiberEx)(LPVOID,DWORD);
36static BOOL (WINAPI *pIsThreadAFiber)(void);
37static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
38static BOOL (WINAPI *pFlsFree)(DWORD);
39static PVOID (WINAPI *pFlsGetValue)(DWORD);
40static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
41static void (WINAPI *pRtlAcquirePebLock)(void);
42static void (WINAPI *pRtlReleasePebLock)(void);
44static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG);
45static NTSTATUS (WINAPI *pRtlFlsSetValue)(ULONG,void *);
46static NTSTATUS (WINAPI *pRtlFlsGetValue)(ULONG,void **);
47static void (WINAPI *pRtlProcessFlsData)(void *fls_data, ULONG flags);
48static void *fibers[3];
49static BYTE testparam = 185;
51static void* fls_value_to_set;
52
53static int fiberCount = 0;
54static int cbCount = 0;
55
56static VOID init_funcs(void)
57{
58 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
59 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
60
61#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
70 X(FlsAlloc);
71 X(FlsFree);
74#undef X
75
76#define X(f) p##f = (void*)GetProcAddress(hntdll, #f);
84#undef X
85
86}
87
89{
90 ok(lpFlsData == fls_value_to_set,
91 "FlsData expected not to be changed, value is %p, expected %p\n",
92 lpFlsData, fls_value_to_set);
93 cbCount++;
94}
95
96static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
97{
98 BYTE *tparam = (BYTE *)lpFiberParameter;
99 TEB *teb = NtCurrentTeb();
100
101 ok(!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots);
102
103 fiberCount++;
104 ok(*tparam == 185, "Parameterdata expected not to be changed\n");
106 {
107 void* ret;
108 BOOL bret;
109
110 SetLastError( 0xdeadbeef );
111 ret = pFlsGetValue(fls_index_to_set);
112 ok(ret == NULL, "FlsGetValue returned %p, expected NULL\n", ret);
113 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got unexpected error %lu.\n", GetLastError());
114
115 /* Set the FLS value */
116 bret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
117 ok(bret, "FlsSetValue failed with error %lu\n", GetLastError());
118
119 ok(!!teb->FlsSlots, "Got unexpected FlsSlots %p.\n", teb->FlsSlots);
120
121 /* Verify that FlsGetValue retrieves the value set by FlsSetValue */
122 SetLastError( 0xdeadbeef );
123 ret = pFlsGetValue(fls_index_to_set);
124 ok(ret == fls_value_to_set, "FlsGetValue returned %p, expected %p\n", ret, fls_value_to_set);
125 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue error %lu\n", GetLastError());
126 }
127 pSwitchToFiber(fibers[0]);
128}
129
131{
132 void *ret;
133
134 if (pConvertThreadToFiber)
135 {
136 fibers[0] = pConvertThreadToFiber(&testparam);
137 ok(fibers[0] != NULL, "ConvertThreadToFiber failed with error %lu\n", GetLastError());
138
139 SetLastError(0xdeadbeef);
140 ret = pConvertThreadToFiber(&testparam);
141 ok(!ret, "Got non NULL ret.\n");
142 ok(GetLastError() == ERROR_ALREADY_FIBER, "Got unexpected error %lu.\n", GetLastError());
143 }
144 else
145 {
146 win_skip( "ConvertThreadToFiber not present\n" );
147 }
148}
149
151{
152 void *ret;
153
154 if (pConvertThreadToFiberEx)
155 {
156 fibers[0] = pConvertThreadToFiberEx(&testparam, 0);
157 ok(fibers[0] != NULL, "ConvertThreadToFiberEx failed with error %lu\n", GetLastError());
158
159 SetLastError(0xdeadbeef);
160 ret = pConvertThreadToFiberEx(&testparam, 0);
161 ok(!ret, "Got non NULL ret.\n");
162 ok(GetLastError() == ERROR_ALREADY_FIBER, "Got unexpected error %lu.\n", GetLastError());
163 }
164 else
165 {
166 win_skip( "ConvertThreadToFiberEx not present\n" );
167 }
168}
169
171{
172 if (pConvertFiberToThread)
173 {
174 BOOL ret = pConvertFiberToThread();
175 ok(ret, "ConvertFiberToThread failed with error %lu\n", GetLastError());
176 }
177 else
178 {
179 win_skip( "ConvertFiberToThread not present\n" );
180 }
181}
182
183static void test_FiberHandling(void)
184{
185 fiberCount = 0;
186 fibers[0] = pCreateFiber(0,FiberMainProc,&testparam);
187 ok(fibers[0] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
188 pDeleteFiber(fibers[0]);
189
192 if (pConvertThreadToFiberEx)
194 else
196
197 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
198 ok(fibers[1] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
199
200 pSwitchToFiber(fibers[1]);
201 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
202 pDeleteFiber(fibers[1]);
203
204 if (pCreateFiberEx)
205 {
206 fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam);
207 ok(fibers[1] != NULL, "CreateFiberEx failed with error %lu\n", GetLastError());
208
209 pSwitchToFiber(fibers[1]);
210 ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount);
211 pDeleteFiber(fibers[1]);
212 }
213 else win_skip( "CreateFiberEx not present\n" );
214
215 if (pIsThreadAFiber) ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n");
217 if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
218}
219
220#define FLS_TEST_INDEX_COUNT 4096
221
222static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
223{
224 unsigned int count = 0;
226
227 *index_found = ~0;
228
229 for (entry = le->Flink; entry != le; entry = entry->Flink)
230 {
231 if (entry == search_entry)
232 {
233 ok(*index_found == ~0, "Duplicate list entry.\n");
234 *index_found = count;
235 }
236 ++count;
237 }
238 return count;
239}
240
242
243static void WINAPI test_fls_callback(void *data)
244{
246}
247
248static unsigned int test_fls_chunk_size(unsigned int chunk_index)
249{
250 return 0x10 << chunk_index;
251}
252
253static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned int *index_in_chunk)
254{
255 unsigned int chunk_index = 0;
256
257 while (index >= test_fls_chunk_size(chunk_index))
258 index -= test_fls_chunk_size(chunk_index++);
259
260 *index_in_chunk = index;
261 return chunk_index;
262}
263
266
267
269{
270 pRtlAcquirePebLock();
273 pRtlReleasePebLock();
274 return 0;
275}
276
277static void test_FiberLocalStorage(void)
278{
279 static DWORD fls_indices[FLS_TEST_INDEX_COUNT];
280 unsigned int i, j, count, entry_count, index;
281 LIST_ENTRY *fls_list_head, saved_entry;
282 TEB_FLS_DATA *fls_data, *new_fls_data;
283 GLOBAL_FLS_DATA *g_fls_data;
284 DWORD fls, fls_2, result;
285 TEB *teb = NtCurrentTeb();
286 PEB *peb = teb->Peb;
288 HANDLE hthread;
289 ULONG index2;
290 SIZE_T size;
291 void* val;
292 BOOL ret;
293
294 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
295 {
296 win_skip( "Fiber Local Storage not supported\n" );
297 return;
298 }
299
300 if (pRtlFlsAlloc)
301 {
302 if (pRtlFlsGetValue)
303 {
304 status = pRtlFlsGetValue(0, NULL);
305 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
306 }
307 else
308 {
309 win_skip("RtlFlsGetValue is not available.\n");
310 }
311
312 for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i)
313 {
314 fls_indices[i] = 0xdeadbeef;
315 status = pRtlFlsAlloc(test_fls_callback, &fls_indices[i]);
316 ok(!status || status == STATUS_NO_MEMORY, "Got unexpected status %#lx.\n", status);
317 if (status)
318 {
319 ok(fls_indices[i] == 0xdeadbeef, "Got unexpected index %#lx.\n", fls_indices[i]);
320 break;
321 }
322 if (pRtlFlsSetValue)
323 {
324 status = pRtlFlsSetValue(fls_indices[i], (void *)(ULONG_PTR)(i + 1));
325 ok(!status, "Got unexpected status %#lx.\n", status);
326 }
327 }
328 count = i;
329
330 fls_data = teb->FlsSlots;
331
332 /* FLS limits are increased since Win10 18312. */
333 ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count);
334
335#if defined(__REACTOS__) && defined(_WIN64)
336 /* peb layout is different on ReactOS x64 */
337 if (!is_reactos() && !peb->FlsCallback)
338#else
339 if (!peb->FlsCallback)
340#endif
341 {
342 ok(pRtlFlsSetValue && pRtlFlsGetValue, "Missing RtlFlsGetValue / RtlFlsSetValue.\n");
343 ok(!peb->FlsBitmap, "Got unexpected FlsBitmap %p.\n", peb->FlsBitmap);
344 ok(!peb->FlsListHead.Flink && !peb->FlsListHead.Blink, "Got nonzero FlsListHead.\n");
345 ok(!peb->FlsHighIndex, "Got unexpected FlsHighIndex %lu.\n", peb->FlsHighIndex);
346
348
349 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
350 ok(entry_count == 1, "Got unexpected count %u.\n", entry_count);
351 ok(!index, "Got unexpected index %u.\n", index);
352
354
355 ok(g_fls_data->fls_high_index == 0xfef, "Got unexpected fls_high_index %#lx.\n", g_fls_data->fls_high_index);
356
357 for (i = 0; i < 8; ++i)
358 {
359 ok(!!g_fls_data->fls_callback_chunks[i], "Got zero fls_callback_chunks[%u].\n", i);
361 "Got unexpected g_fls_data->fls_callback_chunks[%u]->count %lu.\n",
362 i, g_fls_data->fls_callback_chunks[i]->count);
363
364 size = HeapSize(GetProcessHeap(), 0, g_fls_data->fls_callback_chunks[i]);
365 ok(size == sizeof(ULONG_PTR) + sizeof(FLS_CALLBACK) * test_fls_chunk_size(i),
366 "Got unexpected size %p.\n", (void *)size);
367
368 ok(!!fls_data->fls_data_chunks[i], "Got zero fls_data->fls_data_chunks[%u].\n", i);
369 ok(!fls_data->fls_data_chunks[i][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
370 i, fls_data->fls_data_chunks[i][0]);
371 size = HeapSize(GetProcessHeap(), 0, fls_data->fls_data_chunks[i]);
372 ok(size == sizeof(void *) * (test_fls_chunk_size(i) + 1), "Got unexpected size %p.\n", (void *)size);
373
374 if (!i)
375 {
376 ok(g_fls_data->fls_callback_chunks[0]->callbacks[0].callback == (void *)~(ULONG_PTR)0,
377 "Got unexpected callback %p.\n",
378 g_fls_data->fls_callback_chunks[0]->callbacks[0].callback);
379 }
380
381 for (j = i ? 0 : fls_indices[0]; j < test_fls_chunk_size(i); ++j)
382 {
383 ok(!g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown,
384 "Got unexpected unknown %p, i %u, j %u.\n",
385 g_fls_data->fls_callback_chunks[i]->callbacks[j].unknown, i, j);
387 "Got unexpected callback %p, i %u, j %u.\n",
388 g_fls_data->fls_callback_chunks[i]->callbacks[j].callback, i, j);
389 }
390 }
391 for (i = 0; i < count; ++i)
392 {
393 j = test_fls_chunk_index_from_index(fls_indices[i], &index);
394 ok(fls_data->fls_data_chunks[j][index + 1] == (void *)(ULONG_PTR)(i + 1),
395 "Got unexpected FLS value %p, i %u, j %u, index %u.\n",
396 fls_data->fls_data_chunks[j][index + 1], i, j, index);
397 }
398 j = test_fls_chunk_index_from_index(fls_indices[0x10], &index);
400 status = pRtlFlsFree(fls_indices[0x10]);
401 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
402
405 status = pRtlFlsFree(fls_indices[0x10]);
406 ok(!status, "Got unexpected status %#lx.\n", status);
407 ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
409
410 ok(!fls_data->fls_data_chunks[j][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
411 j, fls_data->fls_data_chunks[j][0]);
413 "Got unexpected callback %p.\n",
415
416 fls_data->fls_data_chunks[j][index + 1] = (void *)(ULONG_PTR)0x28;
417 status = pRtlFlsAlloc(test_fls_callback, &index2);
418 ok(!status, "Got unexpected status %#lx.\n", status);
419 ok(index2 == fls_indices[0x10], "Got unexpected index %lu.\n", index2);
420 ok(fls_data->fls_data_chunks[j][index + 1] == (void *)(ULONG_PTR)0x28, "Got unexpected data %p.\n",
421 fls_data->fls_data_chunks[j][index + 1]);
422
423 status = pRtlFlsSetValue(index2, (void *)(ULONG_PTR)0x11);
424 ok(!status, "Got unexpected status %#lx.\n", status);
425
426 teb->FlsSlots = NULL;
427
428 val = (void *)0xdeadbeef;
429 status = pRtlFlsGetValue(fls_indices[1], &val);
430 new_fls_data = teb->FlsSlots;
431 ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status);
432 ok(val == (void *)0xdeadbeef, "Got unexpected val %p.\n", val);
433 ok(!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
434
435 status = pRtlFlsSetValue(fls_indices[1], (void *)(ULONG_PTR)0x28);
436 new_fls_data = teb->FlsSlots;
437 ok(!status, "Got unexpected status %#lx.\n", status);
438 ok(!!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
439
440 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
441 ok(entry_count == 2, "Got unexpected count %u.\n", entry_count);
442 ok(!index, "Got unexpected index %u.\n", index);
444 ok(index == 1, "Got unexpected index %u.\n", index);
445
446 val = (void *)0xdeadbeef;
447 status = pRtlFlsGetValue(fls_indices[2], &val);
448 ok(!status, "Got unexpected status %#lx.\n", status);
449 ok(!val, "Got unexpected val %p.\n", val);
450
451
452 /* With bit 0 of flags set RtlProcessFlsData is removing FLS data from the linked list
453 * and calls FLS callbacks. With bit 1 set the memory is freed. The remaining bits do not seem
454 * to have any obvious effect. */
455 for (i = 2; i < 32; ++i)
456 {
457 pRtlProcessFlsData(new_fls_data, 1 << i);
458 size = HeapSize(GetProcessHeap(), 0, new_fls_data);
459 ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size);
460 }
461
462 if (0)
463 {
464 pRtlProcessFlsData(new_fls_data, 2);
465 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
466 ok(entry_count == 2, "Got unexpected count %u.\n", entry_count);
467
468 /* Crashes on Windows. */
469 HeapSize(GetProcessHeap(), 0, new_fls_data);
470 }
471
475 ok(!!hthread, "CreateThread failed.\n");
477 ok(result == WAIT_OBJECT_0, "Got unexpected result %lu.\n", result);
478 teb->FlsSlots = NULL;
479
481 saved_entry = new_fls_data->fls_list_entry;
482 pRtlProcessFlsData(new_fls_data, 1);
483 ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots);
484
485 teb->FlsSlots = fls_data;
486 ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
488
491 CloseHandle(hthread);
494
495 ok(new_fls_data->fls_list_entry.Flink == saved_entry.Flink, "Got unexpected Flink %p.\n",
496 saved_entry.Flink);
497 ok(new_fls_data->fls_list_entry.Blink == saved_entry.Blink, "Got unexpected Flink %p.\n",
498 saved_entry.Blink);
499 size = HeapSize(GetProcessHeap(), 0, new_fls_data);
500 ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size);
502 i = test_fls_chunk_index_from_index(fls_indices[1], &index);
503 new_fls_data->fls_data_chunks[i][index + 1] = (void *)(ULONG_PTR)0x28;
504 pRtlProcessFlsData(new_fls_data, 2);
505 ok(!test_fls_callback_call_count, "Got unexpected callback call count %u.\n",
507
508 if (0)
509 {
510 /* crashes on Windows. */
511 HeapSize(GetProcessHeap(), 0, new_fls_data);
512 }
513
514 entry_count = check_linked_list(fls_list_head, &fls_data->fls_list_entry, &index);
515 ok(entry_count == 1, "Got unexpected count %u.\n", entry_count);
516 ok(!index, "Got unexpected index %u.\n", index);
517 }
518 else
519 {
520 win_skip("Old FLS data storage layout, skipping test.\n");
521 g_fls_data = NULL;
522 }
523
524 if (0)
525 {
526 /* crashes on Windows. */
527 pRtlFlsGetValue(fls_indices[0], NULL);
528 }
529
530 for (i = 0; i < count; ++i)
531 {
532 if (pRtlFlsGetValue)
533 {
534 status = pRtlFlsGetValue(fls_indices[i], &val);
535 ok(!status, "Got unexpected status %#lx.\n", status);
536 ok(val == (void *)(ULONG_PTR)(i + 1), "Got unexpected val %p, i %u.\n", val, i);
537 }
538
539 status = pRtlFlsFree(fls_indices[i]);
540 ok(!status, "Got unexpected status %#lx, i %u.\n", status, i);
541 }
542
543#if defined(__REACTOS__) && defined(_WIN64)
544 /* peb layout is different on ReactOS x64 */
545 if (!is_reactos() && !peb->FlsCallback)
546#else
547 if (!peb->FlsCallback)
548#endif
549 {
550 ok(g_fls_data->fls_high_index == 0xfef, "Got unexpected fls_high_index %#lx.\n",
551 g_fls_data->fls_high_index);
552
553 for (i = 0; i < 8; ++i)
554 {
555 ok(!!g_fls_data->fls_callback_chunks[i], "Got zero fls_callback_chunks[%u].\n", i);
556 ok(!!fls_data->fls_data_chunks[i], "Got zero fls_data->fls_data_chunks[%u].\n", i);
557 }
558 }
559 }
560 else
561 {
562 win_skip("RtlFlsAlloc is not available.\n");
563 }
564
565 /* Test an unallocated index
566 * FlsFree should fail
567 * FlsGetValue and FlsSetValue should succeed
568 */
569 SetLastError( 0xdeadbeef );
570 ret = pFlsFree( 127 );
571 ok( !ret, "freeing fls index 127 (unallocated) succeeded\n" );
573 "freeing fls index 127 (unallocated) wrong error %lu\n", GetLastError() );
574
575 val = pFlsGetValue( 127 );
576 ok( val == NULL,
577 "getting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
578
579 if (pRtlFlsGetValue)
580 {
581 val = (void *)0xdeadbeef;
582 status = pRtlFlsGetValue(127, &val);
583 ok( !status, "Got unexpected status %#lx.\n", status );
584 ok( !val, "Got unexpected val %p.\n", val );
585 }
586
587 ret = pFlsSetValue( 127, (void*) 0x217 );
588 ok( ret, "setting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
589
590 SetLastError( 0xdeadbeef );
591 val = pFlsGetValue( 127 );
592 ok( val == (void*) 0x217, "fls index 127 (unallocated) wrong value %p\n", val );
594 "getting fls index 127 (unallocated) failed with error %lu\n", GetLastError() );
595
596 if (pRtlFlsGetValue)
597 {
598 val = (void *)0xdeadbeef;
599 status = pRtlFlsGetValue(127, &val);
600 ok( !status, "Got unexpected status %#lx.\n", status );
601 ok( val == (void*)0x217, "Got unexpected val %p.\n", val );
602 }
603
604 /* FlsFree, FlsGetValue, and FlsSetValue out of bounds should return
605 * ERROR_INVALID_PARAMETER
606 */
607 SetLastError( 0xdeadbeef );
608 ret = pFlsFree( 128 );
609 ok( !ret, "freeing fls index 128 (out of bounds) succeeded\n" );
611 "freeing fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
612
613 SetLastError( 0xdeadbeef );
614 ret = pFlsSetValue( 128, (void*) 0x217 );
616 "setting fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
617
618 SetLastError( 0xdeadbeef );
619 val = pFlsGetValue( 128 );
620 ok( GetLastError() == ERROR_INVALID_PARAMETER || val == (void *)0x217,
621 "getting fls index 128 (out of bounds) wrong error %lu\n", GetLastError() );
622
623 /* Test index 0 */
624 SetLastError( 0xdeadbeef );
625 val = pFlsGetValue( 0 );
626 ok( !val, "fls index 0 set to %p\n", val );
627 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
628 if (pRtlFlsGetValue)
629 {
630 val = (void *)0xdeadbeef;
631 status = pRtlFlsGetValue(0, &val);
632 ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status );
633 ok( val == (void*)0xdeadbeef, "Got unexpected val %p.\n", val );
634 }
635
636 SetLastError( 0xdeadbeef );
637 ret = pFlsSetValue( 0, (void *)0xdeadbeef );
638 ok( !ret, "setting fls index 0 succeeded\n" );
639 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
640 if (pRtlFlsSetValue)
641 {
642 status = pRtlFlsSetValue( 0, (void *)0xdeadbeef );
643 ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#lx.\n", status );
644 }
645 SetLastError( 0xdeadbeef );
646 val = pFlsGetValue( 0 );
647 ok( !val, "fls index 0 wrong value %p\n", val );
648 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %lu\n", GetLastError() );
649
650 /* Test creating an FLS index */
651 fls = pFlsAlloc( NULL );
652 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
653 ok( fls != 0, "fls index 0 allocated\n" );
654 val = pFlsGetValue( fls );
655 ok( !val, "fls index %lu wrong value %p\n", fls, val );
656 SetLastError( 0xdeadbeef );
657 ret = pFlsSetValue( fls, (void *)0xdeadbeef );
658 ok( ret, "setting fls index %lu failed\n", fls );
659 ok( GetLastError() == 0xdeadbeef, "setting fls index wrong error %lu\n", GetLastError() );
660 SetLastError( 0xdeadbeef );
661 val = pFlsGetValue( fls );
662 ok( val == (void *)0xdeadbeef, "fls index %lu wrong value %p\n", fls, val );
664 "getting fls index %lu failed with error %lu\n", fls, GetLastError() );
665 pFlsFree( fls );
666
667 /* Undefined behavior: verify the value is NULL after it the slot is freed */
668 SetLastError( 0xdeadbeef );
669 val = pFlsGetValue( fls );
670 ok( val == NULL, "fls index %lu wrong value %p\n", fls, val );
672 "getting fls index %lu failed with error %lu\n", fls, GetLastError() );
673
674 /* Undefined behavior: verify the value is settable after the slot is freed */
675 ret = pFlsSetValue( fls, (void *)0xdeadbabe );
676 ok( ret, "setting fls index %lu failed\n", fls );
677 val = pFlsGetValue( fls );
678 ok( val == (void *)0xdeadbabe, "fls index %lu wrong value %p\n", fls, val );
679
680 /* Try to create the same FLS index again, and verify that is initialized to NULL */
681 fls_2 = pFlsAlloc( NULL );
682 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
683 /* If this fails it is not an API error, but the test will be inconclusive */
684 ok( fls_2 == fls, "different FLS index allocated, was %lu, now %lu\n", fls, fls_2 );
685
686 SetLastError( 0xdeadbeef );
687 val = pFlsGetValue( fls_2 );
688 ok( val == NULL || val == (void *)0xdeadbabe, "fls index %lu wrong value %p\n", fls, val );
690 "getting fls index %lu failed with error %lu\n", fls_2, GetLastError() );
691 pFlsFree( fls_2 );
692}
693
695{
696 DWORD fls;
697 BOOL ret;
698 void* val, *val2;
699
700 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
701 {
702 win_skip( "Fiber Local Storage not supported\n" );
703 return;
704 }
705
706 /* Test that the callback is executed */
707 cbCount = 0;
708 fls = pFlsAlloc( cbfunc );
709 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
710
711 val = (void*) 0x1587;
713 ret = pFlsSetValue( fls, val );
714 ok(ret, "FlsSetValue failed with error %lu\n", GetLastError() );
715
716 val2 = pFlsGetValue( fls );
717 ok(val == val2, "FlsGetValue returned %p, expected %p\n", val2, val);
718
719 ret = pFlsFree( fls );
720 ok(ret, "FlsFree failed with error %lu\n", GetLastError() );
721 ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
722
723 /* Test that callback is not executed if value is NULL */
724 cbCount = 0;
725 fls = pFlsAlloc( cbfunc );
726 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError() );
727
728 ret = pFlsSetValue( fls, NULL );
729 ok( ret, "FlsSetValue failed with error %lu\n", GetLastError() );
730
731 pFlsFree( fls );
732 ok( ret, "FlsFree failed with error %lu\n", GetLastError() );
733 ok( cbCount == 0, "Wrong callback count: %d\n", cbCount );
734}
735
737{
738 void* val1 = (void*) 0x314;
739 void* val2 = (void*) 0x152;
740 BOOL ret;
741
742 if (!pFlsAlloc || !pFlsFree || !pFlsSetValue || !pFlsGetValue)
743 {
744 win_skip( "Fiber Local Storage not supported\n" );
745 return;
746 }
747
748 fls_index_to_set = pFlsAlloc(cbfunc);
749 ok(fls_index_to_set != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %lu\n", GetLastError());
750
752
753 fiberCount = 0;
754 cbCount = 0;
755 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
756 fibers[2] = pCreateFiber(0,FiberMainProc,&testparam);
757 ok(fibers[1] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
758 ok(fibers[2] != NULL, "CreateFiber failed with error %lu\n", GetLastError());
759 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
760 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
761
762 fiberCount = 0;
763 cbCount = 0;
764 fls_value_to_set = val1;
765 pSwitchToFiber(fibers[1]);
766 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
767 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
768
769 fiberCount = 0;
770 cbCount = 0;
771 fls_value_to_set = val2;
772 pSwitchToFiber(fibers[2]);
773 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
774 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
775
776 fls_value_to_set = val2;
777 ret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
778 ok(ret, "FlsSetValue failed\n");
779 ok(val2 == pFlsGetValue(fls_index_to_set), "FlsGetValue failed\n");
780
781 fiberCount = 0;
782 cbCount = 0;
783 fls_value_to_set = val1;
784 pDeleteFiber(fibers[1]);
785 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
786 ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
787
788 fiberCount = 0;
789 cbCount = 0;
790 fls_value_to_set = val2;
791 pFlsFree(fls_index_to_set);
792 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
793 ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
794
795 fiberCount = 0;
796 cbCount = 0;
797 fls_value_to_set = val1;
798 pDeleteFiber(fibers[2]);
799 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
800 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
801
803}
804
805#define check_current_actctx_is(e,t) check_current_actctx_is_(__LINE__, e, t)
806static void check_current_actctx_is_(int line, HANDLE expected_actctx, BOOL todo)
807{
808 HANDLE cur_actctx;
809 BOOL ret;
810
811 cur_actctx = (void*)0xdeadbeef;
812 ret = GetCurrentActCtx(&cur_actctx);
813 ok_(__FILE__, line)(ret, "thread GetCurrentActCtx failed, %lu\n", GetLastError());
814
816 ok_(__FILE__, line)(cur_actctx == expected_actctx, "got %p, expected %p\n", cur_actctx, expected_actctx);
817
818 ReleaseActCtx(cur_actctx);
819}
820
822{
823 HANDLE fiber;
824 BOOL ret;
825
827
828 fiber = pConvertThreadToFiber(NULL);
829 ok(fiber != NULL, "ConvertThreadToFiber returned error %lu\n", GetLastError());
831 fibers[2] = fiber;
832
835
836 ok(fibers[2] == fiber, "fibers[2]: expected %p, got %p\n", fiber, fibers[2]);
837 fibers[2] = NULL;
838 ret = pConvertFiberToThread();
839 ok(ret, "ConvertFiberToThread returned error %lu\n", GetLastError());
841
842 return 0;
843}
844
846{
848 DWORD tid, wait;
850 BOOL ret;
851
853
855 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
857
860
862 ok(thread != NULL, "CreateThread returned error %lu\n", GetLastError());
863
865 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (last error: %lu)\n",
866 wait, GetLastError());
868
870 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
872
874 ok(0, "unreachable\n");
875}
876
877/* Test that activation context is switched on SwitchToFiber() call */
878static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actctx)
879{
880 fibers[1] = pCreateFiber(0, fiber_actctx_func, child_actctx);
881 ok(fibers[1] != NULL, "CreateFiber returned error %lu\n", GetLastError());
882 check_current_actctx_is(current_actctx, FALSE);
883
885 check_current_actctx_is(current_actctx, FALSE);
886
888 check_current_actctx_is(current_actctx, FALSE);
889
891 check_current_actctx_is(current_actctx, FALSE);
892 ok(fibers[2] == NULL, "expected fiber to be deleted (got %p)\n", fibers[2]);
893
895 fibers[1] = NULL;
896}
897
899{
900 BOOL ret;
901
902 ret = pConvertFiberToThread();
903 ok(ret, "ConvertFiberToThread returned error %lu\n", GetLastError());
904
905 ExitThread(16);
906}
907
909{
910 HANDLE exit_thread_fiber;
911
913
914 fibers[1] = pConvertThreadToFiber(NULL);
915 ok(fibers[1] != NULL, "ConvertThreadToFiber returned error %lu\n", GetLastError());
917
918 exit_thread_fiber = pCreateFiber(0, exit_thread_fiber_func, NULL);
919 ok(exit_thread_fiber != NULL, "CreateFiber returned error %lu\n", GetLastError());
920
921 /* exit thread, but keep current fiber */
922 SwitchToFiber(exit_thread_fiber);
924
926 ok(0, "unreachable\n");
927 return 17;
928}
929
930/* Test that fiber activation context stack is preserved regardless of creator thread's lifetime */
931static void subtest_fiber_actctx_preservation(HANDLE current_actctx, HANDLE child_actctx)
932{
934 DWORD tid, wait;
936 BOOL ret;
937
938 ret = ActivateActCtx(child_actctx, &cookie);
939 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
940 check_current_actctx_is(child_actctx, FALSE);
941
942 thread = CreateThread(NULL, 0, thread_actctx_func_early_exit, child_actctx, 0, &tid);
943 ok(thread != NULL, "CreateThread returned error %lu\n", GetLastError());
944
946 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
947 check_current_actctx_is(current_actctx, FALSE);
948
950 ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %lu (last error: %lu)\n",
951 wait, GetLastError());
953
954 /* The exited thread has been converted to a fiber */
955#if defined(__REACTOS__) && defined(_M_AMD64)
956 skip("FIXME: SwitchToFiber() is unimplemented on AMD64 ReactOS\n");
957#else
959 check_current_actctx_is(current_actctx, FALSE);
960
962 fibers[1] = NULL;
963#endif
964}
965
967{
968 ACTCTXW actctx;
969
970 memset(&actctx, 0, sizeof(ACTCTXW));
971 actctx.cbSize = sizeof(actctx);
972 actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
973 actctx.lpResourceName = MAKEINTRESOURCEW(124);
974 actctx.hModule = GetModuleHandleW(NULL);
975
976 return CreateActCtxW(&actctx);
977}
978
979static void test_fiber_actctx(void)
980{
982 HANDLE actctxs[3];
983 size_t i, j;
984 BOOL ret;
985
986#ifdef __REACTOS__
988 skip("test_fiber_actctx() crashes and isn't valid on WS03.\n");
989 return;
990 }
991#endif
992 for (i = 0; i < ARRAY_SIZE(actctxs); i++)
993 {
995 ok(actctxs[i] != INVALID_HANDLE_VALUE, "failed to create context, error %lu\n", GetLastError());
996 for (j = 0; j < i; j++)
997 {
998 ok(actctxs[i] != actctxs[j],
999 "actctxs[%Iu] (%p) and actctxs[%Iu] (%p) should not alias\n",
1000 i, actctxs[i], j, actctxs[j]);
1001 }
1002 }
1003
1004 ret = ActivateActCtx(actctxs[0], &cookies[0]);
1005 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
1006 check_current_actctx_is(actctxs[0], FALSE);
1007
1009 check_current_actctx_is(actctxs[0], FALSE);
1010
1011 ret = ActivateActCtx(actctxs[1], &cookies[1]);
1012 ok(ret, "ActivateActCtx returned error %lu\n", GetLastError());
1013 check_current_actctx_is(actctxs[1], FALSE);
1014
1015 subtest_fiber_actctx_switch(actctxs[1], actctxs[2]);
1016 subtest_fiber_actctx_preservation(actctxs[1], actctxs[2]);
1017
1018 ret = DeactivateActCtx(0, cookies[1]);
1019 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
1020 check_current_actctx_is(actctxs[0], FALSE);
1021
1023 check_current_actctx_is(actctxs[0], FALSE);
1024
1025 ret = DeactivateActCtx(0, cookies[0]);
1026 ok(ret, "DeactivateActCtx returned error %lu\n", GetLastError());
1028
1029 for (i = ARRAY_SIZE(actctxs); i > 0; )
1030 ReleaseActCtx(actctxs[--i]);
1031}
1032
1033
1035{
1036 if (arg == (void *)1)
1037 Sleep(INFINITE);
1038 if (arg == (void *)2)
1039 /* Unfortunately this test won't affect the exit code if it fails, but
1040 * at least it will print a failure message. */
1041 ok(RtlDllShutdownInProgress(), "expected DLL shutdown\n");
1042}
1043
1045{
1046 FlsSetValue((DWORD_PTR)arg, (void *)1);
1047 return 0;
1048}
1049
1051{
1053 FlsSetValue(index, (void *)2);
1055 Sleep(100);
1056 ExitProcess(0);
1057}
1058
1059static void test_fls_exit_deadlock(void)
1060{
1061 char **argv, cmdline[MAX_PATH];
1063 STARTUPINFOA si = {0};
1064 BOOL ret;
1065
1066 /* Regression test for the following deadlock:
1067 *
1068 * Thread A Thread B
1069 * -----------------------------
1070 * ExitThread
1071 * acquire FLS lock
1072 * call FLS callback
1073 * ExitProcess
1074 * terminate thread A
1075 * acquire FLS lock
1076 *
1077 * Thread B deadlocks on acquiring the FLS lock (in order to itself call its
1078 * FLS callbacks.)
1079 */
1080
1082 sprintf(cmdline, "%s %s fls_exit_deadlock", argv[0], argv[1]);
1084 ok(ret, "failed to create child, error %lu\n", GetLastError());
1086 ok(!ret, "wait failed\n");
1089}
1090
1092{
1093 char **argv;
1094 int argc;
1095
1097
1098 if (argc == 3 && !strcmp(argv[2], "fls_exit_deadlock"))
1099 {
1101 return;
1102 }
1103
1104 init_funcs();
1105
1106 if (!pCreateFiber)
1107 {
1108 win_skip( "Fibers not supported by win95\n" );
1109 return;
1110 }
1111
1118}
static int argc
Definition: ServiceArgs.c:12
#define GetNTVersion()
Definition: apitest.h:17
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
static int fls(int x)
Definition: bitops.h:157
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:19
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
Definition: actctx.c:208
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
Definition: actctx.c:268
BOOL WINAPI GetCurrentActCtx(OUT PHANDLE phActCtx)
Definition: actctx.c:298
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
Definition: actctx.c:237
LPVOID WINAPI ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter, _In_ DWORD dwFlags)
Definition: fiber.c:99
LPVOID WINAPI CreateFiberEx(_In_ SIZE_T dwStackCommitSize, _In_ SIZE_T dwStackReserveSize, _In_ DWORD dwFlags, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:191
VOID WINAPI DeleteFiber(_In_ LPVOID lpFiber)
Definition: fiber.c:290
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
LPVOID WINAPI ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
Definition: fiber.c:162
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
LPVOID WINAPI CreateFiber(_In_ SIZE_T dwStackSize, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:174
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4749
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
Definition: actctx.c:102
BOOL WINAPI DECLSPEC_HOTPATCH ConvertFiberToThread(void)
Definition: thread.c:1084
void WINAPI DECLSPEC_HOTPATCH SwitchToFiber(LPVOID fiber)
Definition: thread.c:1172
BOOL WINAPI DECLSPEC_HOTPATCH IsThreadAFiber(void)
Definition: thread.c:1163
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
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
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 GLint GLint j
Definition: glfuncs.h:250
NTSYSAPI void WINAPI RtlReleasePebLock(void)
Definition: libsupp.c:84
NTSYSAPI NTSTATUS WINAPI RtlFlsSetValue(ULONG, void *)
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
Definition: libsupp.c:74
NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION, ULONG *)
NTSYSAPI NTSTATUS WINAPI RtlFlsFree(ULONG)
NTSYSAPI NTSTATUS WINAPI RtlFlsGetValue(ULONG, void **)
NTSYSAPI void WINAPI RtlProcessFlsData(void *, ULONG)
NTSYSAPI BOOLEAN WINAPI RtlDllShutdownInProgress(void)
Definition: ldrapi.c:1559
static TfClientId tid
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define actctx
Definition: kernel32.h:8
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
#define sprintf
Definition: sprintf.c:45
HANDLE hKernel32
Definition: locale.c:13
BOOL todo
Definition: filedlg.c:313
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static void * fibers[3]
Definition: fiber.c:48
static unsigned int test_fls_callback_call_count
Definition: fiber.c:241
static LPFIBER_START_ROUTINE
Definition: fiber.c:29
static BYTE testparam
Definition: fiber.c:49
static int cbCount
Definition: fiber.c:54
static unsigned int test_fls_chunk_size(unsigned int chunk_index)
Definition: fiber.c:248
static DWORD CALLBACK fls_exit_deadlock_thread(void *arg)
Definition: fiber.c:1044
#define X(f)
static void test_fiber_actctx(void)
Definition: fiber.c:979
#define FLS_TEST_INDEX_COUNT
Definition: fiber.c:220
static HANDLE create_actctx_from_module_manifest(void)
Definition: fiber.c:966
static DWORD fls_index_to_set
Definition: fiber.c:50
static void test_ConvertThreadToFiberEx(void)
Definition: fiber.c:150
static void fls_exit_deadlock_child(void)
Definition: fiber.c:1050
static void test_ConvertFiberToThread(void)
Definition: fiber.c:170
static void WINAPI exit_thread_fiber_func(void *unused)
Definition: fiber.c:898
static void * fls_value_to_set
Definition: fiber.c:51
static DWORD
Definition: fiber.c:34
#define check_current_actctx_is(e, t)
Definition: fiber.c:805
static int fiberCount
Definition: fiber.c:53
static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:736
static void WINAPI fiber_actctx_func(void *actctx)
Definition: fiber.c:845
static PVOID
Definition: fiber.c:40
static void test_ConvertThreadToFiber(void)
Definition: fiber.c:130
static void WINAPI fls_exit_deadlock_callback(void *arg)
Definition: fiber.c:1034
static VOID init_funcs(void)
Definition: fiber.c:56
static DWORD WINAPI thread_actctx_func_early_exit(void *actctx)
Definition: fiber.c:908
static HANDLE test_fiberlocalstorage_peb_locked_event
Definition: fiber.c:264
static void subtest_fiber_actctx_preservation(HANDLE current_actctx, HANDLE child_actctx)
Definition: fiber.c:931
static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actctx)
Definition: fiber.c:878
static DWORD WINAPI test_FiberLocalStorage_thread(void *arg)
Definition: fiber.c:268
static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned int *index_in_chunk)
Definition: fiber.c:253
static LPVOID
Definition: fiber.c:29
static SIZE_T
Definition: fiber.c:35
static void *static void **static ULONG flags
Definition: fiber.c:47
static void WINAPI test_fls_callback(void *data)
Definition: fiber.c:243
static void check_current_actctx_is_(int line, HANDLE expected_actctx, BOOL todo)
Definition: fiber.c:806
static DWORD WINAPI subthread_actctx_func(void *actctx)
Definition: fiber.c:821
static void test_FiberHandling(void)
Definition: fiber.c:183
static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:694
static void test_FiberLocalStorage(void)
Definition: fiber.c:277
static void test_fls_exit_deadlock(void)
Definition: fiber.c:1059
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
Definition: fiber.c:88
static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
Definition: fiber.c:222
static HANDLE test_fiberlocalstorage_done_event
Definition: fiber.c:265
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
Definition: fiber.c:96
static LIST_ENTRY * fls_list_head
Definition: loader.c:3048
static HINSTANCE hntdll
Definition: process.c:68
static SYSTEM_INFO si
Definition: virtual.c:39
WORD unused[29]
Definition: crypt.c:1155
#define argv
Definition: mplay32.c:18
static CookieInternal * cookies
Definition: msctf.cpp:37
#define BOOL
Definition: nt_native.h:43
#define is_reactos()
Definition: test.h:1041
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
TCHAR * cmdline
Definition: stretchblt.cpp:32
PFLS_CALLBACK_FUNCTION callback
Definition: winternl.h:365
void * unknown
Definition: winternl.h:364
FLS_CALLBACK callbacks[1]
Definition: winternl.h:371
ULONG fls_high_index
Definition: winternl.h:379
FLS_INFO_CHUNK * fls_callback_chunks[8]
Definition: winternl.h:377
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PVOID * FlsCallback
Definition: winternl.h:551
LIST_ENTRY FlsListHead
Definition: winternl.h:552
PRTL_BITMAP FlsBitmap
Definition: winternl.h:555
ULONG FlsHighIndex
Definition: winternl.h:561
LIST_ENTRY fls_list_entry
Definition: winternl.h:384
void ** fls_data_chunks[8]
Definition: winternl.h:385
Definition: compat.h:836
PVOID Peb
Definition: compat.h:842
TEB_FLS_DATA * FlsSlots
Definition: winternl.h:690
Definition: cookie.c:34
Definition: parser.c:49
Definition: ps.c:97
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
uint32_t DWORD_PTR
Definition: typedefs.h:65
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:556
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1202
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define WINAPI
Definition: msvc.h:6
#define ERROR_ALREADY_FIBER
Definition: winerror.h:1107
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
unsigned char BYTE
Definition: xxhash.c:193