[PATCH 2/3] kernel32/tests/loader: Add tests for fiber-local storage.
John Sheu
sheu at google.com
Fri Jul 1 21:41:27 CDT 2016
Signed-off-by: John Sheu <sheu at google.com>
---
dlls/kernel32/tests/loader.c | 106 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index c35cf25a..06ce0393 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -69,6 +69,10 @@ static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRI
PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
PIMAGE_THUNK_DATA ThunkAddress,ULONG);
static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *);
+static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
+static BOOL (WINAPI *pFlsSetValue)(DWORD, PVOID);
+static PVOID (WINAPI *pFlsGetValue)(DWORD);
+static BOOL (WINAPI *pFlsFree)(DWORD);
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
{
@@ -1342,6 +1346,7 @@ static HANDLE attached_thread[MAX_COUNT];
static DWORD attached_thread_count;
HANDLE stop_event, event, mutex, semaphore, loader_lock_event, peb_lock_event, heap_lock_event, ack_event;
static int test_dll_phase, inside_loader_lock, inside_peb_lock, inside_heap_lock;
+static LONG fls_callback_count;
static DWORD WINAPI mutex_thread_proc(void *param)
{
@@ -1424,9 +1429,18 @@ static DWORD WINAPI noop_thread_proc(void *param)
return 195;
}
+static VOID WINAPI fls_callback(PVOID lpFlsData)
+{
+ ok(lpFlsData == (PVOID) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (PVOID) 0x31415);
+ InterlockedIncrement(&fls_callback_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 int fls_count = 0;
+ static int thread_detach_count = 0;
DWORD ret;
ok(!inside_loader_lock, "inside_loader_lock should not be set\n");
@@ -1440,6 +1454,32 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
ret = pRtlDllShutdownInProgress();
ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
+ /* Set up the FLS slot, if FLS is available */
+ if (pFlsAlloc)
+ {
+ ret = pFlsAlloc(&fls_callback);
+ ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret);
+ fls_index = ret;
+ fls_count++;
+ }
+
+ /* Make sure the FLS slot is empty, if FLS is available */
+ if (pFlsGetValue)
+ {
+ PVOID pret;
+ pret = pFlsGetValue(fls_index);
+ ok(!pret, "FlsGetValue returned %p, expected NULL\n", pret);
+ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
+ }
+
+ /* Set the FLS slot, if FLS is available */
+ if (pFlsSetValue)
+ {
+ BOOL bret;
+ bret = FlsSetValue(fls_index, (PVOID) 0x31415);
+ ok(bret, "FlsSetValue failed\n");
+ }
+
break;
case DLL_PROCESS_DETACH:
{
@@ -1493,6 +1533,32 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
ok(!ret || broken(ret) /* before Vista */, "RtlDllShutdownInProgress returned %d\n", ret);
}
+ /* In the case that the process is terminating, FLS slots should still be accessible,
+ * but the callback should be already run for this thread and the contents already NULL
+ */
+ if (param && pFlsGetValue)
+ {
+ PVOID pret;
+ pret = pFlsGetValue(fls_index);
+ todo_wine
+ {
+ ok(pret == NULL, "FlsGetValue returned %p, expected NULL\n", pret);
+ }
+ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
+ todo_wine
+ {
+ ok(fls_callback_count == thread_detach_count + 1,
+ "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1);
+ }
+ }
+ if (pFlsFree)
+ {
+ BOOL bret;
+ /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */
+ bret = pFlsFree(fls_index);
+ ok(bret, "FlsFree failed with error %u\n", GetLastError());
+ }
+
ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
for (i = 0; i < attached_thread_count; i++)
@@ -1663,9 +1729,28 @@ todo_wine
0, TRUE, DUPLICATE_SAME_ACCESS);
attached_thread_count++;
}
+
+ /* Make sure the FLS slot is empty, if FLS is available */
+ if (pFlsGetValue)
+ {
+ PVOID pret;
+ pret = pFlsGetValue(fls_index);
+ ok(!pret, "FlsGetValue returned %p, expected NULL\n", pret);
+ }
+
+ /* Set the FLS slot, if FLS is available */
+ if (pFlsSetValue)
+ {
+ BOOL bret;
+ bret = FlsSetValue(fls_index, (PVOID) 0x31415);
+ ok(bret, "FlsSetValue failed\n");
+ fls_count++;
+ }
+
break;
case DLL_THREAD_DETACH:
trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
+ thread_detach_count++;
ret = pRtlDllShutdownInProgress();
/* win7 doesn't allow creating a thread during process shutdown but
@@ -1677,6 +1762,18 @@ todo_wine
else
ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
+ /* FLS data should already be destroyed, if FLS is available */
+ if (pFlsGetValue)
+ {
+ PVOID pret;
+ pret = pFlsGetValue(fls_index);
+ todo_wine
+ {
+ ok(!pret, "FlsGetValue returned %p, expected NULL\n", pret);
+ }
+ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError());
+ }
+
break;
default:
trace("dll: %p, %d, %p\n", hinst, reason, param);
@@ -2754,10 +2851,11 @@ START_TEST(loader)
{
int argc;
char **argv;
- HANDLE ntdll, mapping;
+ HANDLE ntdll, mapping, kernel32;
SYSTEM_INFO si;
ntdll = GetModuleHandleA("ntdll.dll");
+ kernel32 = GetModuleHandleA("kernel32.dll");
pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection");
pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection");
pNtUnmapViewOfSection = (void *)GetProcAddress(ntdll, "NtUnmapViewOfSection");
@@ -2773,7 +2871,11 @@ START_TEST(loader)
pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData");
- pResolveDelayLoadedAPI = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ResolveDelayLoadedAPI");
+ pFlsAlloc = (void *)GetProcAddress(kernel32, "FlsAlloc");
+ pFlsSetValue = (void *)GetProcAddress(kernel32, "FlsSetValue");
+ pFlsGetValue = (void *)GetProcAddress(kernel32, "FlsGetValue");
+ pFlsFree = (void *)GetProcAddress(kernel32, "FlsFree");
+ pResolveDelayLoadedAPI = (void *)GetProcAddress(kernel32, "ResolveDelayLoadedAPI");
GetSystemInfo( &si );
page_size = si.dwPageSize;
--
2.8.0.rc3.226.g39d4020
More information about the wine-patches
mailing list