24#define WIN32_NO_STATUS
61#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
76#define X(f) p##f = (void*)GetProcAddress(hntdll, #f);
91 "FlsData expected not to be changed, value is %p, expected %p\n",
98 BYTE *tparam = (
BYTE *)lpFiberParameter;
104 ok(*tparam == 185,
"Parameterdata expected not to be changed\n");
112 ok(
ret ==
NULL,
"FlsGetValue returned %p, expected NULL\n",
ret);
127 pSwitchToFiber(
fibers[0]);
134 if (pConvertThreadToFiber)
141 ok(!
ret,
"Got non NULL ret.\n");
146 win_skip(
"ConvertThreadToFiber not present\n" );
154 if (pConvertThreadToFiberEx)
161 ok(!
ret,
"Got non NULL ret.\n");
166 win_skip(
"ConvertThreadToFiberEx not present\n" );
172 if (pConvertFiberToThread)
174 BOOL ret = pConvertFiberToThread();
179 win_skip(
"ConvertFiberToThread not present\n" );
192 if (pConvertThreadToFiberEx)
200 pSwitchToFiber(
fibers[1]);
209 pSwitchToFiber(
fibers[1]);
213 else win_skip(
"CreateFiberEx not present\n" );
215 if (pIsThreadAFiber)
ok(pIsThreadAFiber(),
"IsThreadAFiber reported FALSE\n");
217 if (pIsThreadAFiber)
ok(!pIsThreadAFiber(),
"IsThreadAFiber reported TRUE\n");
220#define FLS_TEST_INDEX_COUNT 4096
224 unsigned int count = 0;
231 if (
entry == search_entry)
233 ok(*index_found == ~0,
"Duplicate list entry.\n");
234 *index_found =
count;
250 return 0x10 << chunk_index;
255 unsigned int chunk_index = 0;
260 *index_in_chunk =
index;
270 pRtlAcquirePebLock();
273 pRtlReleasePebLock();
294 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
296 win_skip(
"Fiber Local Storage not supported\n" );
309 win_skip(
"RtlFlsGetValue is not available.\n");
314 fls_indices[
i] = 0xdeadbeef;
319 ok(fls_indices[
i] == 0xdeadbeef,
"Got unexpected index %#lx.\n", fls_indices[
i]);
335#if defined(__REACTOS__) && defined(_WIN64)
342 ok(pRtlFlsSetValue && pRtlFlsGetValue,
"Missing RtlFlsGetValue / RtlFlsSetValue.\n");
350 ok(entry_count == 1,
"Got unexpected count %u.\n", entry_count);
357 for (
i = 0;
i < 8; ++
i)
361 "Got unexpected g_fls_data->fls_callback_chunks[%u]->count %lu.\n",
366 "Got unexpected size %p.\n", (
void *)
size);
369 ok(!fls_data->
fls_data_chunks[
i][0],
"Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
377 "Got unexpected callback %p.\n",
384 "Got unexpected unknown %p, i %u, j %u.\n",
387 "Got unexpected callback %p, i %u, j %u.\n",
395 "Got unexpected FLS value %p, i %u, j %u, index %u.\n",
400 status = pRtlFlsFree(fls_indices[0x10]);
405 status = pRtlFlsFree(fls_indices[0x10]);
410 ok(!fls_data->
fls_data_chunks[
j][0],
"Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
413 "Got unexpected callback %p.\n",
419 ok(index2 == fls_indices[0x10],
"Got unexpected index %lu.\n", index2);
428 val = (
void *)0xdeadbeef;
429 status = pRtlFlsGetValue(fls_indices[1], &
val);
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);
438 ok(!!new_fls_data,
"Got unexpected teb->FlsSlots %p.\n", new_fls_data);
441 ok(entry_count == 2,
"Got unexpected count %u.\n", entry_count);
446 val = (
void *)0xdeadbeef;
447 status = pRtlFlsGetValue(fls_indices[2], &
val);
449 ok(!
val,
"Got unexpected val %p.\n",
val);
455 for (
i = 2;
i < 32; ++
i)
457 pRtlProcessFlsData(new_fls_data, 1 <<
i);
459 ok(
size ==
sizeof(*new_fls_data),
"Got unexpected size %p.\n", (
void *)
size);
464 pRtlProcessFlsData(new_fls_data, 2);
466 ok(entry_count == 2,
"Got unexpected count %u.\n", entry_count);
475 ok(!!hthread,
"CreateThread failed.\n");
482 pRtlProcessFlsData(new_fls_data, 1);
500 ok(
size ==
sizeof(*new_fls_data),
"Got unexpected size %p.\n", (
void *)
size);
504 pRtlProcessFlsData(new_fls_data, 2);
515 ok(entry_count == 1,
"Got unexpected count %u.\n", entry_count);
520 win_skip(
"Old FLS data storage layout, skipping test.\n");
527 pRtlFlsGetValue(fls_indices[0],
NULL);
534 status = pRtlFlsGetValue(fls_indices[
i], &
val);
539 status = pRtlFlsFree(fls_indices[
i]);
543#if defined(__REACTOS__) && defined(_WIN64)
550 ok(g_fls_data->
fls_high_index == 0xfef,
"Got unexpected fls_high_index %#lx.\n",
553 for (
i = 0;
i < 8; ++
i)
562 win_skip(
"RtlFlsAlloc is not available.\n");
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() );
575 val = pFlsGetValue( 127 );
577 "getting fls index 127 (unallocated) failed with error %lu\n",
GetLastError() );
581 val = (
void *)0xdeadbeef;
584 ok( !
val,
"Got unexpected val %p.\n",
val );
587 ret = pFlsSetValue( 127, (
void*) 0x217 );
588 ok(
ret,
"setting fls index 127 (unallocated) failed with error %lu\n",
GetLastError() );
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() );
598 val = (
void *)0xdeadbeef;
601 ok(
val == (
void*)0x217,
"Got unexpected val %p.\n",
val );
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() );
614 ret = pFlsSetValue( 128, (
void*) 0x217 );
616 "setting fls index 128 (out of bounds) wrong error %lu\n",
GetLastError() );
619 val = pFlsGetValue( 128 );
621 "getting fls index 128 (out of bounds) wrong error %lu\n",
GetLastError() );
625 val = pFlsGetValue( 0 );
626 ok( !
val,
"fls index 0 set to %p\n",
val );
630 val = (
void *)0xdeadbeef;
633 ok(
val == (
void*)0xdeadbeef,
"Got unexpected val %p.\n",
val );
637 ret = pFlsSetValue( 0, (
void *)0xdeadbeef );
638 ok( !
ret,
"setting fls index 0 succeeded\n" );
642 status = pRtlFlsSetValue( 0, (
void *)0xdeadbeef );
646 val = pFlsGetValue( 0 );
647 ok( !
val,
"fls index 0 wrong value %p\n",
val );
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 );
657 ret = pFlsSetValue(
fls, (
void *)0xdeadbeef );
658 ok(
ret,
"setting fls index %lu failed\n",
fls );
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() );
669 val = pFlsGetValue(
fls );
672 "getting fls index %lu failed with error %lu\n",
fls,
GetLastError() );
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 );
681 fls_2 = pFlsAlloc(
NULL );
684 ok( fls_2 ==
fls,
"different FLS index allocated, was %lu, now %lu\n",
fls, fls_2 );
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() );
700 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
702 win_skip(
"Fiber Local Storage not supported\n" );
708 fls = pFlsAlloc( cbfunc );
711 val = (
void*) 0x1587;
716 val2 = pFlsGetValue(
fls );
717 ok(
val == val2,
"FlsGetValue returned %p, expected %p\n", val2,
val);
725 fls = pFlsAlloc( cbfunc );
738 void* val1 = (
void*) 0x314;
739 void* val2 = (
void*) 0x152;
742 if (!pFlsAlloc || !pFlsFree || !pFlsSetValue || !pFlsGetValue)
744 win_skip(
"Fiber Local Storage not supported\n" );
765 pSwitchToFiber(
fibers[1]);
772 pSwitchToFiber(
fibers[2]);
778 ok(
ret,
"FlsSetValue failed\n");
805#define check_current_actctx_is(e,t) check_current_actctx_is_(__LINE__, e, t)
811 cur_actctx = (
void*)0xdeadbeef;
816 ok_(__FILE__,
line)(cur_actctx == expected_actctx,
"got %p, expected %p\n", cur_actctx, expected_actctx);
828 fiber = pConvertThreadToFiber(
NULL);
836 ok(
fibers[2] == fiber,
"fibers[2]: expected %p, got %p\n", fiber,
fibers[2]);
838 ret = pConvertFiberToThread();
865 ok(wait ==
WAIT_OBJECT_0,
"WaitForSingleObject returned %lu (last error: %lu)\n",
874 ok(0,
"unreachable\n");
902 ret = pConvertFiberToThread();
926 ok(0,
"unreachable\n");
950 ok(wait ==
WAIT_OBJECT_0,
"WaitForSingleObject returned %lu (last error: %lu)\n",
955#if defined(__REACTOS__) && defined(_M_AMD64)
956 skip(
"FIXME: SwitchToFiber() is unimplemented on AMD64 ReactOS\n");
972 actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
988 skip(
"test_fiber_actctx() crashes and isn't valid on WS03.\n");
996 for (
j = 0;
j <
i;
j++)
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]);
1036 if (
arg == (
void *)1)
1038 if (
arg == (
void *)2)
1086 ok(!
ret,
"wait failed\n");
1108 win_skip(
"Fibers not supported by win95\n" );
#define ERROR_INVALID_PARAMETER
#define INVALID_HANDLE_VALUE
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
BOOL WINAPI GetCurrentActCtx(OUT PHANDLE phActCtx)
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
LPVOID WINAPI ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter, _In_ DWORD dwFlags)
LPVOID WINAPI CreateFiberEx(_In_ SIZE_T dwStackCommitSize, _In_ SIZE_T dwStackReserveSize, _In_ DWORD dwFlags, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
VOID WINAPI DeleteFiber(_In_ LPVOID lpFiber)
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
LPVOID WINAPI ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
LPVOID WINAPI CreateFiber(_In_ SIZE_T dwStackSize, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
VOID WINAPI ExitProcess(IN UINT uExitCode)
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)
VOID WINAPI ExitThread(IN DWORD uExitCode)
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)
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
BOOL WINAPI DECLSPEC_HOTPATCH ConvertFiberToThread(void)
void WINAPI DECLSPEC_HOTPATCH SwitchToFiber(LPVOID fiber)
BOOL WINAPI DECLSPEC_HOTPATCH IsThreadAFiber(void)
_ACRTIMP int __cdecl strcmp(const char *, const char *)
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
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
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
NTSYSAPI void WINAPI RtlReleasePebLock(void)
NTSYSAPI NTSTATUS WINAPI RtlFlsSetValue(ULONG, void *)
NTSYSAPI void WINAPI RtlAcquirePebLock(void)
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)
#define todo_wine_if(is_todo)
static PROCESS_INFORMATION pi
static unsigned int test_fls_callback_call_count
static LPFIBER_START_ROUTINE
static unsigned int test_fls_chunk_size(unsigned int chunk_index)
static DWORD CALLBACK fls_exit_deadlock_thread(void *arg)
static void test_fiber_actctx(void)
#define FLS_TEST_INDEX_COUNT
static HANDLE create_actctx_from_module_manifest(void)
static DWORD fls_index_to_set
static void test_ConvertThreadToFiberEx(void)
static void fls_exit_deadlock_child(void)
static void test_ConvertFiberToThread(void)
static void WINAPI exit_thread_fiber_func(void *unused)
static void * fls_value_to_set
#define check_current_actctx_is(e, t)
static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
static void WINAPI fiber_actctx_func(void *actctx)
static void test_ConvertThreadToFiber(void)
static void WINAPI fls_exit_deadlock_callback(void *arg)
static VOID init_funcs(void)
static DWORD WINAPI thread_actctx_func_early_exit(void *actctx)
static HANDLE test_fiberlocalstorage_peb_locked_event
static void subtest_fiber_actctx_preservation(HANDLE current_actctx, HANDLE child_actctx)
static void subtest_fiber_actctx_switch(HANDLE current_actctx, HANDLE child_actctx)
static DWORD WINAPI test_FiberLocalStorage_thread(void *arg)
static unsigned int test_fls_chunk_index_from_index(unsigned int index, unsigned int *index_in_chunk)
static void *static void **static ULONG flags
static void WINAPI test_fls_callback(void *data)
static void check_current_actctx_is_(int line, HANDLE expected_actctx, BOOL todo)
static DWORD WINAPI subthread_actctx_func(void *actctx)
static void test_FiberHandling(void)
static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
static void test_FiberLocalStorage(void)
static void test_fls_exit_deadlock(void)
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
static HANDLE test_fiberlocalstorage_done_event
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
static LIST_ENTRY * fls_list_head
static CookieInternal * cookies
int winetest_get_mainargs(char ***pargv)
#define _WIN32_WINNT_VISTA
PFLS_CALLBACK_FUNCTION callback
FLS_CALLBACK callbacks[1]
FLS_INFO_CHUNK * fls_callback_chunks[8]
struct _LIST_ENTRY * Blink
struct _LIST_ENTRY * Flink
LIST_ENTRY fls_list_entry
void ** fls_data_chunks[8]
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
#define CONTAINING_RECORD(address, type, field)
#define STATUS_INVALID_PARAMETER
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
DWORD WINAPI GetLastError(void)
#define FLS_OUT_OF_INDEXES
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
#define ERROR_ALREADY_FIBER
#define MAKEINTRESOURCEW(i)