mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 17:04:06 +00:00
ntdll: Call FLS callbacks.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7341f4ad1e
commit
ec1ea1ea1b
|
@ -223,8 +223,11 @@ static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *se
|
|||
return count;
|
||||
}
|
||||
|
||||
static unsigned int test_fls_callback_call_count;
|
||||
|
||||
static void WINAPI test_fls_callback(void *data)
|
||||
{
|
||||
++test_fls_callback_call_count;
|
||||
}
|
||||
|
||||
static unsigned int test_fls_chunk_size(unsigned int chunk_index)
|
||||
|
@ -377,8 +380,11 @@ static void test_FiberLocalStorage(void)
|
|||
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
|
||||
|
||||
g_fls_data->fls_callback_chunks[j]->callbacks[index].callback = test_fls_callback;
|
||||
test_fls_callback_call_count = 0;
|
||||
status = pRtlFlsFree(fls_indices[0x10]);
|
||||
ok(!status, "Got unexpected status %#x.\n", status);
|
||||
ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
|
||||
test_fls_callback_call_count);
|
||||
|
||||
ok(!fls_data->fls_data_chunks[j][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n",
|
||||
j, fls_data->fls_data_chunks[j][0]);
|
||||
|
@ -405,7 +411,7 @@ static void test_FiberLocalStorage(void)
|
|||
ok(val == (void *)0xdeadbeef, "Got unexpected val %p.\n", val);
|
||||
ok(!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
|
||||
|
||||
status = pRtlFlsSetValue(fls_indices[1], NULL);
|
||||
status = pRtlFlsSetValue(fls_indices[1], (void *)(ULONG_PTR)0x28);
|
||||
new_fls_data = teb->FlsSlots;
|
||||
ok(!status, "Got unexpected status %#x.\n", status);
|
||||
ok(!!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data);
|
||||
|
@ -450,11 +456,15 @@ static void test_FiberLocalStorage(void)
|
|||
ok(result == WAIT_OBJECT_0, "Got unexpected result %u.\n", result);
|
||||
teb->FlsSlots = NULL;
|
||||
|
||||
test_fls_callback_call_count = 0;
|
||||
saved_entry = new_fls_data->fls_list_entry;
|
||||
pRtlProcessFlsData(new_fls_data, 1);
|
||||
ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots);
|
||||
|
||||
teb->FlsSlots = fls_data;
|
||||
ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n",
|
||||
test_fls_callback_call_count);
|
||||
|
||||
SetEvent(test_fiberlocalstorage_done_event);
|
||||
WaitForSingleObject(hthread, INFINITE);
|
||||
CloseHandle(hthread);
|
||||
|
@ -467,7 +477,13 @@ static void test_FiberLocalStorage(void)
|
|||
saved_entry.Blink);
|
||||
size = HeapSize(GetProcessHeap(), 0, new_fls_data);
|
||||
ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size);
|
||||
test_fls_callback_call_count = 0;
|
||||
i = test_fls_chunk_index_from_index(fls_indices[1], &index);
|
||||
new_fls_data->fls_data_chunks[i][index + 1] = (void *)(ULONG_PTR)0x28;
|
||||
pRtlProcessFlsData(new_fls_data, 2);
|
||||
ok(!test_fls_callback_call_count, "Got unexpected callback call count %u.\n",
|
||||
test_fls_callback_call_count);
|
||||
|
||||
if (0)
|
||||
{
|
||||
/* crashes on Windows. */
|
||||
|
@ -676,7 +692,7 @@ static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
|
|||
|
||||
ret = pFlsFree( fls );
|
||||
ok(ret, "FlsFree failed with error %u\n", GetLastError() );
|
||||
todo_wine ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
|
||||
ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
|
||||
|
||||
/* Test that callback is not executed if value is NULL */
|
||||
cbCount = 0;
|
||||
|
@ -741,14 +757,14 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
|
|||
fls_value_to_set = val1;
|
||||
pDeleteFiber(fibers[1]);
|
||||
ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
|
||||
todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
|
||||
ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
|
||||
|
||||
fiberCount = 0;
|
||||
cbCount = 0;
|
||||
fls_value_to_set = val2;
|
||||
pFlsFree(fls_index_to_set);
|
||||
ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
|
||||
todo_wine ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
|
||||
ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
|
||||
|
||||
fiberCount = 0;
|
||||
cbCount = 0;
|
||||
|
|
|
@ -2318,12 +2318,34 @@ static VOID WINAPI fls_callback(PVOID lpFlsData)
|
|||
InterlockedIncrement(&fls_callback_count);
|
||||
}
|
||||
|
||||
static LIST_ENTRY *fls_list_head;
|
||||
|
||||
static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
LIST_ENTRY *entry;
|
||||
|
||||
*index_found = ~0;
|
||||
|
||||
for (entry = le->Flink; entry != le; entry = entry->Flink)
|
||||
{
|
||||
if (entry == search_entry)
|
||||
{
|
||||
ok(*index_found == ~0, "Duplicate list entry.\n");
|
||||
*index_found = count;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
|
||||
{
|
||||
static LONG noop_thread_started;
|
||||
static DWORD fls_index = FLS_OUT_OF_INDEXES;
|
||||
static DWORD fls_index = FLS_OUT_OF_INDEXES, fls_index2 = FLS_OUT_OF_INDEXES;
|
||||
static int fls_count = 0;
|
||||
static int thread_detach_count = 0;
|
||||
static int thread_count;
|
||||
DWORD ret;
|
||||
|
||||
ok(!inside_loader_lock, "inside_loader_lock should not be set\n");
|
||||
|
@ -2352,8 +2374,11 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
|
|||
bret = pFlsSetValue(fls_index, (void*) 0x31415);
|
||||
ok(bret, "FlsSetValue failed\n");
|
||||
fls_count++;
|
||||
}
|
||||
|
||||
fls_index2 = pFlsAlloc(&fls_callback);
|
||||
ok(fls_index2 != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret);
|
||||
}
|
||||
++thread_count;
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
|
@ -2423,18 +2448,12 @@ todo_wine
|
|||
void* value;
|
||||
SetLastError(0xdeadbeef);
|
||||
value = pFlsGetValue(fls_index);
|
||||
todo_wine
|
||||
{
|
||||
ok(broken(value == (void*) 0x31415) || /* Win2k3 */
|
||||
value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
|
||||
}
|
||||
ok(broken(value == (void*) 0x31415) || /* Win2k3 */
|
||||
value == NULL, "FlsGetValue returned %p, expected NULL\n", value);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
|
||||
todo_wine
|
||||
{
|
||||
ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
|
||||
fls_callback_count == thread_detach_count + 1,
|
||||
"wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
|
||||
}
|
||||
ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */
|
||||
fls_callback_count == thread_detach_count + 1,
|
||||
"wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
|
||||
}
|
||||
if (pFlsFree)
|
||||
{
|
||||
|
@ -2443,11 +2462,8 @@ todo_wine
|
|||
ret = pFlsFree(fls_index);
|
||||
ok(ret, "FlsFree failed with error %u\n", GetLastError());
|
||||
fls_index = FLS_OUT_OF_INDEXES;
|
||||
todo_wine
|
||||
{
|
||||
ok(fls_callback_count == fls_count,
|
||||
"wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
|
||||
}
|
||||
ok(fls_callback_count == fls_count,
|
||||
"wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count);
|
||||
}
|
||||
|
||||
ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
|
||||
|
@ -2611,6 +2627,8 @@ todo_wine
|
|||
case DLL_THREAD_ATTACH:
|
||||
trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param);
|
||||
|
||||
++thread_count;
|
||||
|
||||
ret = pRtlDllShutdownInProgress();
|
||||
ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
|
||||
|
||||
|
@ -2638,6 +2656,7 @@ todo_wine
|
|||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
|
||||
--thread_count;
|
||||
thread_detach_count++;
|
||||
|
||||
ret = pRtlDllShutdownInProgress();
|
||||
|
@ -2656,15 +2675,25 @@ todo_wine
|
|||
*/
|
||||
if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES)
|
||||
{
|
||||
unsigned int index, count;
|
||||
void* value;
|
||||
BOOL bret;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
value = pFlsGetValue(fls_index);
|
||||
todo_wine
|
||||
{
|
||||
ok(broken(value == (void*) 0x31415) || /* Win2k3 */
|
||||
!value, "FlsGetValue returned %p, expected NULL\n", value);
|
||||
}
|
||||
ok(broken(value == (void*) 0x31415) || /* Win2k3 */
|
||||
!value, "FlsGetValue returned %p, expected NULL\n", value);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
|
||||
|
||||
bret = pFlsSetValue(fls_index2, (void*) 0x31415);
|
||||
ok(bret, "FlsSetValue failed\n");
|
||||
|
||||
if (fls_list_head)
|
||||
{
|
||||
count = check_linked_list(fls_list_head, &NtCurrentTeb()->FlsSlots->fls_list_entry, &index);
|
||||
ok(count <= thread_count, "Got unexpected count %u, thread_count %u.\n", count, thread_count);
|
||||
ok(index == ~0, "Got unexpected index %u.\n", index);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2689,6 +2718,12 @@ static void child_process(const char *dll_name, DWORD target_offset)
|
|||
|
||||
trace("phase %d: writing %p at %#x\n", test_dll_phase, dll_entry_point, target_offset);
|
||||
|
||||
if (pFlsAlloc)
|
||||
{
|
||||
fls_list_head = NtCurrentTeb()->Peb->FlsListHead.Flink ? &NtCurrentTeb()->Peb->FlsListHead
|
||||
: NtCurrentTeb()->FlsSlots->fls_list_entry.Flink;
|
||||
}
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
mutex = CreateMutexW(NULL, FALSE, NULL);
|
||||
ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
|
||||
|
|
|
@ -3194,6 +3194,10 @@ fail:
|
|||
void WINAPI LdrShutdownProcess(void)
|
||||
{
|
||||
TRACE("()\n");
|
||||
|
||||
if (!process_detaching)
|
||||
RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 );
|
||||
|
||||
process_detaching = TRUE;
|
||||
process_detach();
|
||||
}
|
||||
|
@ -3228,6 +3232,8 @@ void WINAPI LdrShutdownThread(void)
|
|||
/* don't do any detach calls if process is exiting */
|
||||
if (process_detaching) return;
|
||||
|
||||
RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 );
|
||||
|
||||
RtlEnterCriticalSection( &loader_section );
|
||||
wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||
|
||||
|
@ -3254,7 +3260,7 @@ void WINAPI LdrShutdownThread(void)
|
|||
for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, pointers );
|
||||
}
|
||||
RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 3 );
|
||||
RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 );
|
||||
NtCurrentTeb()->FlsSlots = NULL;
|
||||
RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
|
||||
NtCurrentTeb()->TlsExpansionSlots = NULL;
|
||||
|
|
|
@ -374,7 +374,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback,
|
|||
}
|
||||
|
||||
++chunk->count;
|
||||
chunk->callbacks[index].callback = callback ? callback : (void *)~(ULONG_PTR)0;
|
||||
chunk->callbacks[index].callback = callback ? callback : (PFLS_CALLBACK_FUNCTION)~(ULONG_PTR)0;
|
||||
|
||||
if ((*ret_index = fls_index_from_chunk_index( chunk_index, index )) > fls_data.fls_high_index)
|
||||
fls_data.fls_high_index = *ret_index;
|
||||
|
@ -390,6 +390,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback,
|
|||
*/
|
||||
NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index )
|
||||
{
|
||||
PFLS_CALLBACK_FUNCTION callback;
|
||||
unsigned int chunk_index, idx;
|
||||
FLS_INFO_CHUNK *chunk;
|
||||
LIST_ENTRY *entry;
|
||||
|
@ -404,7 +405,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index )
|
|||
|
||||
chunk_index = fls_chunk_index_from_index( index, &idx );
|
||||
if (!(chunk = fls_data.fls_callback_chunks[chunk_index])
|
||||
|| !chunk->callbacks[idx].callback)
|
||||
|| !(callback = chunk->callbacks[idx].callback))
|
||||
{
|
||||
unlock_fls_data();
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
@ -414,9 +415,15 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index )
|
|||
{
|
||||
TEB_FLS_DATA *fls = CONTAINING_RECORD(entry, TEB_FLS_DATA, fls_list_entry);
|
||||
|
||||
if (fls->fls_data_chunks[chunk_index])
|
||||
if (fls->fls_data_chunks[chunk_index] && fls->fls_data_chunks[chunk_index][idx + 1])
|
||||
{
|
||||
/* FIXME: call Fls callback */
|
||||
if (callback != (void *)~(ULONG_PTR)0)
|
||||
{
|
||||
TRACE_(relay)("Calling FLS callback %p, arg %p.\n", callback,
|
||||
fls->fls_data_chunks[chunk_index][idx + 1]);
|
||||
|
||||
callback( fls->fls_data_chunks[chunk_index][idx + 1] );
|
||||
}
|
||||
fls->fls_data_chunks[chunk_index][idx + 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +488,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data )
|
|||
void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags )
|
||||
{
|
||||
TEB_FLS_DATA *fls = teb_fls_data;
|
||||
unsigned int i;
|
||||
unsigned int i, index;
|
||||
|
||||
TRACE_(thread)( "teb_fls_data %p, flags %#x.\n", teb_fls_data, flags );
|
||||
|
||||
|
@ -494,6 +501,29 @@ void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags
|
|||
if (flags & 1)
|
||||
{
|
||||
lock_fls_data();
|
||||
for (i = 0; i < ARRAY_SIZE(fls->fls_data_chunks); ++i)
|
||||
{
|
||||
if (!fls->fls_data_chunks[i] || !fls_data.fls_callback_chunks[i]
|
||||
|| !fls_data.fls_callback_chunks[i]->count)
|
||||
continue;
|
||||
|
||||
for (index = 0; index < fls_chunk_size( i ); ++index)
|
||||
{
|
||||
PFLS_CALLBACK_FUNCTION callback = fls_data.fls_callback_chunks[i]->callbacks[index].callback;
|
||||
|
||||
if (!fls->fls_data_chunks[i][index + 1])
|
||||
continue;
|
||||
|
||||
if (callback && callback != (void *)~(ULONG_PTR)0)
|
||||
{
|
||||
TRACE_(relay)("Calling FLS callback %p, arg %p.\n", callback,
|
||||
fls->fls_data_chunks[i][index + 1]);
|
||||
|
||||
callback( fls->fls_data_chunks[i][index + 1] );
|
||||
}
|
||||
fls->fls_data_chunks[i][index + 1] = NULL;
|
||||
}
|
||||
}
|
||||
/* Not using RemoveEntryList() as Windows does not zero list entry here. */
|
||||
fls->fls_list_entry.Flink->Blink = fls->fls_list_entry.Blink;
|
||||
fls->fls_list_entry.Blink->Flink = fls->fls_list_entry.Flink;
|
||||
|
|
Loading…
Reference in a new issue