From: Amine Khaldi Date: Wed, 7 Sep 2016 22:32:56 +0000 (+0000) Subject: [KERNEL32_WINETEST] Sync with Wine Staging 1.9.18. X-Git-Tag: backups/sndblst@72664~49 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=89932f2716b2aee25910ec84c8cb0f17d4138dc4 [KERNEL32_WINETEST] Sync with Wine Staging 1.9.18. svn path=/trunk/; revision=72611 --- diff --git a/rostests/winetests/kernel32/console.c b/rostests/winetests/kernel32/console.c index 5b66d9fbf53..c88db6acad0 100755 --- a/rostests/winetests/kernel32/console.c +++ b/rostests/winetests/kernel32/console.c @@ -908,6 +908,58 @@ static void testScreenBuffer(HANDLE hConOut) SetConsoleOutputCP(oldcp); } +static void CALLBACK signaled_function(void *p, BOOLEAN timeout) +{ + HANDLE event = p; + SetEvent(event); + ok(!timeout, "wait shouldn't have timed out\n"); +} + +static void testWaitForConsoleInput(HANDLE input_handle) +{ + HANDLE wait_handle; + HANDLE complete_event; + INPUT_RECORD record; + DWORD events_written; + DWORD wait_ret; + BOOL ret; + + complete_event = CreateEventW(NULL, FALSE, FALSE, NULL); + + /* Test success case */ + ret = RegisterWaitForSingleObject(&wait_handle, input_handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); + ok(ret == TRUE, "Expected RegisterWaitForSingleObject to return TRUE, got %d\n", ret); + /* give worker thread a chance to start up */ + Sleep(100); + record.EventType = KEY_EVENT; + record.Event.KeyEvent.bKeyDown = 1; + record.Event.KeyEvent.wRepeatCount = 1; + record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + record.Event.KeyEvent.wVirtualScanCode = VK_RETURN; + record.Event.KeyEvent.uChar.UnicodeChar = '\r'; + record.Event.KeyEvent.dwControlKeyState = 0; + ret = WriteConsoleInputW(input_handle, &record, 1, &events_written); + ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); + wait_ret = WaitForSingleObject(complete_event, INFINITE); + ok(wait_ret == WAIT_OBJECT_0, "Expected the handle to be signaled\n"); + ret = UnregisterWait(wait_handle); + /* If the callback is still running, this fails with ERROR_IO_PENDING, but + that's ok and expected. */ + ok(ret != 0 || GetLastError() == ERROR_IO_PENDING, + "UnregisterWait failed with error %d\n", GetLastError()); + + /* Test timeout case */ + FlushConsoleInputBuffer(input_handle); + ret = RegisterWaitForSingleObject(&wait_handle, input_handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); + wait_ret = WaitForSingleObject(complete_event, 100); + ok(wait_ret == WAIT_TIMEOUT, "Expected the wait to time out\n"); + ret = UnregisterWait(wait_handle); + ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); + + /* Clean up */ + ok(CloseHandle(complete_event), "Failed to close event handle, last error %d\n", GetLastError()); +} + static void test_GetSetConsoleInputExeName(void) { BOOL ret; @@ -2938,6 +2990,55 @@ static void test_SetConsoleFont(HANDLE std_output) todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); } +static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output) +{ + HANDLE hmod; + BOOL (WINAPI *pGetConsoleScreenBufferInfoEx)(HANDLE, CONSOLE_SCREEN_BUFFER_INFOEX *); + CONSOLE_SCREEN_BUFFER_INFOEX csbix; + BOOL ret; + HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE); + + hmod = GetModuleHandleA("kernel32.dll"); + pGetConsoleScreenBufferInfoEx = (void *)GetProcAddress(hmod, "GetConsoleScreenBufferInfoEx"); + if (!pGetConsoleScreenBufferInfoEx) + { + win_skip("GetConsoleScreenBufferInfoEx is not available\n"); + return; + } + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix); + ok(!ret, "got %d, expected zero\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix); + ok(!ret, "got %d, expected zero\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix); + ok(!ret, "got %d, expected zero\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + + csbix.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix); + ok(!ret, "got %d, expected zero\n", ret); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix); + ok(!ret, "got %d, expected zero\n", ret); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix); + ok(ret, "got %d, expected non-zero\n", ret); + ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); +} + START_TEST(console) { static const char font_name[] = "Lucida Console"; @@ -3044,6 +3145,8 @@ START_TEST(console) testScroll(hConOut, sbi.dwSize); /* will test sb creation / modification / codepage handling */ testScreenBuffer(hConOut); + /* Test waiting for a console handle */ + testWaitForConsoleInput(hConIn); /* clear duplicated console font table */ CloseHandle(hConIn); @@ -3086,4 +3189,5 @@ START_TEST(console) test_GetLargestConsoleWindowSize(hConOut); test_GetConsoleFontInfo(hConOut); test_SetConsoleFont(hConOut); + test_GetConsoleScreenBufferInfoEx(hConOut); } diff --git a/rostests/winetests/kernel32/fiber.c b/rostests/winetests/kernel32/fiber.c index 9ff9366c993..7501165dc87 100644 --- a/rostests/winetests/kernel32/fiber.c +++ b/rostests/winetests/kernel32/fiber.c @@ -155,28 +155,20 @@ static void test_FiberHandling(void) ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount); pDeleteFiber(fibers[1]); - if (!pCreateFiberEx) + if (pCreateFiberEx) { - win_skip( "CreateFiberEx not present\n" ); - return; - } - - fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam); - ok(fibers[1] != NULL, "CreateFiberEx failed with error %u\n", GetLastError()); - - pSwitchToFiber(fibers[1]); - ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount); - pDeleteFiber(fibers[1]); + fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam); + ok(fibers[1] != NULL, "CreateFiberEx failed with error %u\n", GetLastError()); - if (!pIsThreadAFiber) - { - win_skip( "IsThreadAFiber not present\n" ); - return; + pSwitchToFiber(fibers[1]); + ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount); + pDeleteFiber(fibers[1]); } + else win_skip( "CreateFiberEx not present\n" ); - ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n"); + if (pIsThreadAFiber) ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n"); test_ConvertFiberToThread(); - ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); + if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); } static void test_FiberLocalStorage(void) diff --git a/rostests/winetests/kernel32/file.c b/rostests/winetests/kernel32/file.c index cb9a986528a..9b6377d3b6d 100755 --- a/rostests/winetests/kernel32/file.c +++ b/rostests/winetests/kernel32/file.c @@ -4449,17 +4449,10 @@ static void test_file_access(void) else { /* FIXME: Remove once Wine is fixed */ - if ((td[j].access & (GENERIC_READ | GENERIC_WRITE)) || - (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) || - (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) || - (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA))) - { -todo_wine - ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access); -todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); - } - else + todo_wine_if((td[j].access & (GENERIC_READ | GENERIC_WRITE) || + (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) || + (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) || + (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA)))) { ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError()); diff --git a/rostests/winetests/kernel32/loader.c b/rostests/winetests/kernel32/loader.c index 87bbe932cb9..0fd57cc0f64 100644 --- a/rostests/winetests/kernel32/loader.c +++ b/rostests/winetests/kernel32/loader.c @@ -70,6 +70,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) { @@ -143,9 +147,9 @@ static const IMAGE_NT_HEADERS nt_header_template = static IMAGE_SECTION_HEADER section = { ".rodata", /* Name */ - { 0x10 }, /* Misc */ + { 0 }, /* Misc */ 0, /* VirtualAddress */ - 0x0a, /* SizeOfRawData */ + 0, /* SizeOfRawData */ 0, /* PointerToRawData */ 0, /* PointerToRelocations */ 0, /* PointerToLinenumbers */ @@ -196,6 +200,8 @@ static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size, assert(nt_header->FileHeader.NumberOfSections <= 1); if (nt_header->FileHeader.NumberOfSections) { + section.SizeOfRawData = 10; + if (nt_header->OptionalHeader.SectionAlignment >= page_size) { section.PointerToRawData = dos_size; @@ -262,9 +268,13 @@ static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HE ok( image.CommittedStackSize == nt_header->OptionalHeader.SizeOfStackCommit || broken(truncated), "%u: CommittedStackSize wrong %lx / %lx\n", id, image.CommittedStackSize, (SIZE_T)nt_header->OptionalHeader.SizeOfStackCommit ); - ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem || broken(truncated), - "%u: SubSystemType wrong %08x / %08x\n", id, - image.SubSystemType, nt_header->OptionalHeader.Subsystem ); + if (truncated) + ok( !image.SubSystemType || broken(truncated), + "%u: SubSystemType wrong %08x / 00000000\n", id, image.SubSystemType ); + else + ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem, + "%u: SubSystemType wrong %08x / %08x\n", id, + image.SubSystemType, nt_header->OptionalHeader.Subsystem ); ok( image.SubsystemVersionLow == nt_header->OptionalHeader.MinorSubsystemVersion, "%u: SubsystemVersionLow wrong %04x / %04x\n", id, image.SubsystemVersionLow, nt_header->OptionalHeader.MinorSubsystemVersion ); @@ -1470,6 +1480,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) { @@ -1552,9 +1563,18 @@ static DWORD WINAPI noop_thread_proc(void *param) return 195; } +static VOID WINAPI fls_callback(PVOID lpFlsData) +{ + ok(lpFlsData == (void*) 0x31415, "lpFlsData is %p, expected %p\n", lpFlsData, (void*) 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"); @@ -1568,6 +1588,23 @@ 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 (pFlsGetValue) + { + void* value; + BOOL bret; + ret = pFlsAlloc(&fls_callback); + ok(ret != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret); + fls_index = ret; + SetLastError(0xdeadbeef); + value = pFlsGetValue(fls_index); + ok(!value, "FlsGetValue returned %p, expected NULL\n", value); + ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); + bret = pFlsSetValue(fls_index, (void*) 0x31415); + ok(bret, "FlsSetValue failed\n"); + fls_count++; + } + break; case DLL_PROCESS_DETACH: { @@ -1621,6 +1658,43 @@ 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. + * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry + * point has already run. + */ + if (param && pFlsGetValue) + { + 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(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); + } + } + if (pFlsFree) + { + BOOL ret; + /* Call FlsFree now and run the remaining callbacks from uncleanly terminated threads */ + 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(attached_thread_count >= 2, "attached thread count should be >= 2\n"); for (i = 0; i < attached_thread_count; i++) @@ -1791,9 +1865,26 @@ todo_wine 0, TRUE, DUPLICATE_SAME_ACCESS); attached_thread_count++; } + + /* Make sure the FLS slot is empty, if FLS is available */ + if (pFlsGetValue) + { + void* value; + BOOL ret; + SetLastError(0xdeadbeef); + value = pFlsGetValue(fls_index); + ok(!value, "FlsGetValue returned %p, expected NULL\n", value); + todo_wine + ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); + ret = pFlsSetValue(fls_index, (void*) 0x31415); + ok(ret, "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 @@ -1805,6 +1896,23 @@ todo_wine else ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); + /* FLS data should already be destroyed, if FLS is available. + * Note that this is broken for Win2k3, which runs the callbacks *after* the DLL entry + * point has already run. + */ + if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES) + { + void* value; + SetLastError(0xdeadbeef); + value = pFlsGetValue(fls_index); + todo_wine + { + 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()); + } + break; default: trace("dll: %p, %d, %p\n", hinst, reason, param); @@ -2126,7 +2234,6 @@ static void test_ExitProcess(void) } section_data = { 0xb8, dll_entry_point, { 0xff,0xe0 } }; #endif #include "poppack.h" - static const char filler[0x1000]; DWORD dummy, file_align; HANDLE file, thread, process, hmap, hmap_dup; char temp_path[MAX_PATH], dll_name[MAX_PATH], cmdline[MAX_PATH * 2]; @@ -2603,7 +2710,7 @@ static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd) ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n"); if (pd->ThunkAddress) - ok(pd->ThunkAddress->u1.Ordinal == 0, "expected 0, got %x\n", (UINT)pd->ThunkAddress->u1.Ordinal); + ok(pd->ThunkAddress->u1.Ordinal, "no ThunkAddress value supplied\n"); ok(!!pd->TargetDllName, "no TargetDllName supplied\n"); if (pd->TargetDllName) @@ -2628,7 +2735,6 @@ static void test_ResolveDelayLoadedAPI(void) { static const char test_dll[] = "secur32.dll"; static const char test_func[] = "SealMessage"; - static const char filler[0x1000]; char temp_path[MAX_PATH]; char dll_name[MAX_PATH]; IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir; @@ -2722,7 +2828,8 @@ static void test_ResolveDelayLoadedAPI(void) /* sections */ section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; - section.Misc.VirtualSize = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size; + section.Misc.VirtualSize = 2 * sizeof(idd); + section.SizeOfRawData = section.Misc.VirtualSize; section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; SetLastError(0xdeadbeef); ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); @@ -2734,18 +2841,14 @@ static void test_ResolveDelayLoadedAPI(void) section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) + 2 * (i + 1) * sizeof(IMAGE_THUNK_DATA); ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n"); + section.SizeOfRawData = section.Misc.VirtualSize; section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; SetLastError(0xdeadbeef); ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL); ok(ret, "WriteFile error %d\n", GetLastError()); /* fill up to delay data */ - file_size = GetFileSize(hfile, NULL); - SetLastError(0xdeadbeef); - ret = WriteFile(hfile, filler, - nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress - file_size, - &dummy, NULL); - ok(ret, "WriteFile error %d\n", GetLastError()); + SetFilePointer( hfile, nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress, NULL, SEEK_SET ); /* delay data */ idd.Attributes.AllAttributes = 1; @@ -2766,10 +2869,7 @@ static void test_ResolveDelayLoadedAPI(void) ok(ret, "WriteFile error %d\n", GetLastError()); /* fill up to extended delay data */ - file_size = GetFileSize(hfile, NULL); - SetLastError(0xdeadbeef); - ret = WriteFile(hfile, filler, idd.DllNameRVA - file_size, &dummy, NULL); - ok(ret, "WriteFile error %d\n", GetLastError()); + SetFilePointer( hfile, idd.DllNameRVA, NULL, SEEK_SET ); /* extended delay data */ SetLastError(0xdeadbeef); @@ -2784,9 +2884,20 @@ static void test_ResolveDelayLoadedAPI(void) ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL); ok(ret, "WriteFile error %d\n", GetLastError()); - file_size = GetFileSize(hfile, NULL); + SetFilePointer( hfile, idd.ImportAddressTableRVA, NULL, SEEK_SET ); + + for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) + { + /* 0x1a00 is an empty space between delay data and extended delay data, real thunks are not necessary */ + itd32.u1.Function = nt_header.OptionalHeader.ImageBase + 0x1a00 + i * 0x20; + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + } + + itd32.u1.Function = 0; SetLastError(0xdeadbeef); - ret = WriteFile(hfile, filler, idd.ImportNameTableRVA - file_size, &dummy, NULL); + ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL); ok(ret, "WriteFile error %d\n", GetLastError()); for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) @@ -2806,10 +2917,8 @@ static void test_ResolveDelayLoadedAPI(void) ok(ret, "WriteFile error %d\n", GetLastError()); /* fill up to eof */ - file_size = GetFileSize(hfile, NULL); - SetLastError(0xdeadbeef); - ret = WriteFile(hfile, filler, section.VirtualAddress + section.Misc.VirtualSize - file_size, &dummy, NULL); - ok(ret, "WriteFile error %d\n", GetLastError()); + SetFilePointer( hfile, section.VirtualAddress + section.Misc.VirtualSize, NULL, SEEK_SET ); + SetEndOfFile( hfile ); CloseHandle(hfile); SetLastError(0xdeadbeef); @@ -2902,10 +3011,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"); pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection"); pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection"); @@ -2922,7 +3032,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; diff --git a/rostests/winetests/kernel32/locale.c b/rostests/winetests/kernel32/locale.c index 3760126efec..70a3d24c9ed 100755 --- a/rostests/winetests/kernel32/locale.c +++ b/rostests/winetests/kernel32/locale.c @@ -102,6 +102,7 @@ static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC); static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR); +static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int); static void InitFunctionPointers(void) { @@ -132,6 +133,7 @@ static void InitFunctionPointers(void) X(EnumSystemGeoID); X(GetSystemPreferredUILanguages); X(GetThreadPreferredUILanguages); + X(GetNumberFormatEx); mod = GetModuleHandleA("ntdll"); X(RtlUpcaseUnicodeChar); @@ -1593,6 +1595,188 @@ static void test_GetNumberFormatA(void) } } +static void test_GetNumberFormatEx(void) +{ + int ret; + NUMBERFMTW format; + static WCHAR dotW[] = {'.',0}; + static WCHAR commaW[] = {',',0}; + static const WCHAR enW[] = {'e','n','-','U','S',0}; + static const WCHAR frW[] = {'f','r','-','F','R',0}; + static const WCHAR bogusW[] = {'b','o','g','u','s',0}; + WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE]; + + if (!pGetNumberFormatEx) + { + win_skip("GetNumberFormatEx is not available.\n"); + return; + } + + STRINGSW("23",""); /* NULL output, length > 0 --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, NULL, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("23,53",""); /* Invalid character --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("--",""); /* Double '-' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("0-",""); /* Trailing '-' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("0..",""); /* Double '.' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW(" 0.1",""); /* Leading space --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("1234","1"); /* Length too small --> Write up to length chars */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, 2); + ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + + STRINGSW("23",""); /* Bogus locale --> Error */ + ret = pGetNumberFormatEx(bogusW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + memset(&format, 0, sizeof(format)); + + STRINGSW("2353",""); /* Format and flags given --> Error */ + ret = pGetNumberFormatEx(enW, NUO, input, &format, buffer, COUNTOF(buffer)); + ok( !ret, "Expected ret == 0, got %d\n", ret); + ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError()); + + STRINGSW("2353",""); /* Invalid format --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("2353","2,353.00"); /* Valid number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-2353","-2,353.00"); /* Valid negative number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-353","-353.00"); /* test for off by one error in grouping */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.1","2,353.10"); /* Valid real number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.111","2,353.11"); /* Too many DP --> Truncated */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.119","2,353.12"); /* Too many DP --> Rounded */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NumDigits = 0; /* No decimal separator */ + format.LeadingZero = 0; + format.Grouping = 0; /* No grouping char */ + format.NegativeOrder = 0; + format.lpDecimalSep = dotW; + format.lpThousandSep = commaW; + + STRINGSW("2353","2353"); /* No decimal or grouping chars expected */ + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NumDigits = 1; /* 1 DP --> Expect decimal separator */ + STRINGSW("2353","2353.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.Grouping = 2; /* Group by 100's */ + STRINGSW("2353","23,53.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("235","235.0"); /* Grouping of a positive number */ + format.Grouping = 3; + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-235","-235.0"); /* Grouping of a negative number */ + format.NegativeOrder = NEG_LEFT; + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.LeadingZero = 1; /* Always provide leading zero */ + STRINGSW(".5","0.5"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_PARENS; + STRINGSW("-1","(1.0)"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_LEFT; + STRINGSW("-1","-1.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_LEFT_SPACE; + STRINGSW("-1","- 1.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_RIGHT; + STRINGSW("-1","1.0-"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_RIGHT_SPACE; + STRINGSW("-1","1.0 -"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + if (pIsValidLocaleName(frW)) + { + STRINGSW("-12345","-12 345,00"); /* Try French formatting */ + Expected[3] = 160; /* Non breaking space */ + ret = pGetNumberFormatEx(frW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + } +} + struct comparestringa_entry { LCID lcid; DWORD flags; @@ -4102,7 +4286,7 @@ static void test_IdnToUnicode(void) static void test_GetLocaleInfoEx(void) { static const WCHAR enW[] = {'e','n',0}; - WCHAR bufferW[80]; + WCHAR bufferW[80], buffer2[80]; INT ret; if (!pGetLocaleInfoEx) @@ -4173,6 +4357,12 @@ static void test_GetLocaleInfoEx(void) ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW)); ptr++; } + + ret = pGetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR)); + ok(ret && ret == lstrlenW(bufferW)+1, "got ret value %d\n", ret); + ret = GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SNAME, buffer2, sizeof(buffer2)/sizeof(WCHAR)); + ok(ret && ret == lstrlenW(buffer2)+1, "got ret value %d\n", ret); + ok(!lstrcmpW(bufferW, buffer2), "LOCALE_SNAMEs don't match %s %s\n", wine_dbgstr_w(bufferW), wine_dbgstr_w(buffer2)); } } @@ -4853,6 +5043,7 @@ START_TEST(locale) test_GetDateFormatW(); test_GetCurrencyFormatA(); /* Also tests the W version */ test_GetNumberFormatA(); /* Also tests the W version */ + test_GetNumberFormatEx(); test_CompareStringA(); test_CompareStringW(); test_CompareStringEx(); diff --git a/rostests/winetests/kernel32/path.c b/rostests/winetests/kernel32/path.c index 4d23fbccb21..ff6480c8394 100755 --- a/rostests/winetests/kernel32/path.c +++ b/rostests/winetests/kernel32/path.c @@ -187,15 +187,8 @@ static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR * len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH); if(passfail==NULL) { ok(len, "%s: GetLongPathNameA failed\n",errstr); - if(HAS_TRAIL_SLASH_A(fullpath)) { - ok(lstrcmpiA(fullpathlong,tmpstr)==0, - "%s: GetLongPathNameA returned '%s' instead of '%s'\n", - errstr,tmpstr,fullpathlong); - } else { - ok(lstrcmpiA(fullpathlong,tmpstr)==0, - "%s: GetLongPathNameA returned '%s' instead of '%s'\n", - errstr,tmpstr,fullpathlong); - } + ok(!lstrcmpiA(fullpathlong, tmpstr), "%s: GetLongPathNameA returned '%s' instead of '%s'\n", + errstr, tmpstr, fullpathlong); } else { passfail->longlen=len; passfail->longerror=GetLastError(); @@ -952,6 +945,28 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive) test_ShortPathCase(curdir,SHORTDIR,LONGFILE); test_ShortPathCase(curdir,LONGDIR,SHORTFILE); test_ShortPathCase(curdir,LONGDIR,LONGFILE); + + /* test double delimiters */ + sprintf(tmpstr,"%s\\\\%s", SHORTDIR,SHORTFILE); + ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n"); + ok(lstrcmpiA(tmpstr,tmpstr1)==0, + "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr); + sprintf(tmpstr,".\\\\%s\\\\%s", SHORTDIR,SHORTFILE); + ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n"); + ok(lstrcmpiA(tmpstr,tmpstr1)==0, + "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr); + + if (pGetLongPathNameA) { + sprintf(tmpstr,"%s\\\\%s",LONGDIR,LONGFILE); + ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n"); + ok(lstrcmpiA(tmpstr,tmpstr1)==0, + "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr); + + sprintf(tmpstr,".\\\\%s\\\\%s",LONGDIR,LONGFILE); + ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n"); + ok(lstrcmpiA(tmpstr,tmpstr1)==0, + "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr); + } } static void test_GetTempPathA(char* tmp_dir) @@ -2216,6 +2231,16 @@ static void test_relative_path(void) ok(ret, "GetShortPathName error %d\n", GetLastError()); ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf); + /* test double delimiters */ + strcpy(buf, "deadbeef"); + ret = pGetLongPathNameA("..\\\\foo\\file", buf, MAX_PATH); + ok(ret, "GetLongPathName error %d\n", GetLastError()); + ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf); + strcpy(buf, "deadbeef"); + ret = GetShortPathNameA("..\\\\foo\\file", buf, MAX_PATH); + ok(ret, "GetShortPathName error %d\n", GetLastError()); + ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf); + SetCurrentDirectoryA(".."); DeleteFileA("foo\\file"); RemoveDirectoryA("foo"); diff --git a/rostests/winetests/kernel32/thread.c b/rostests/winetests/kernel32/thread.c index 7e82364a57c..cb3a67c1c62 100755 --- a/rostests/winetests/kernel32/thread.c +++ b/rostests/winetests/kernel32/thread.c @@ -1318,33 +1318,64 @@ static void test_RegisterWaitForSingleObject(void) ret = pUnregisterWait(wait_handle); ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pUnregisterWait(NULL); + ok(!ret, "Expected UnregisterWait to fail\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); } -static DWORD TLS_main; -static DWORD TLS_index0, TLS_index1; +static DWORD LS_main; +static DWORD LS_index0, LS_index1; +static DWORD LS_OutOfIndexesValue; + +/* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */ +static DWORD (WINAPI *LS_AllocFunc)(void); +static PVOID (WINAPI *LS_GetValueFunc)(DWORD); +static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID); +static BOOL (WINAPI *LS_FreeFunc)(DWORD); + +/* Names of the functions tested in LS_ThreadProc(), for error messages */ +static const char* LS_AllocFuncName = ""; +static const char* LS_GetValueFuncName = ""; +static const char* LS_SetValueFuncName = ""; +static const char* LS_FreeFuncName = ""; + +/* FLS entry points, dynamically loaded in platforms that support them */ +static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); +static BOOL (WINAPI *pFlsFree)(DWORD); +static PVOID (WINAPI *pFlsGetValue)(DWORD); +static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); + +/* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */ +static DWORD WINAPI FLS_AllocFuncThunk(void) +{ + return pFlsAlloc(NULL); +} -static DWORD WINAPI TLS_InheritanceProc(LPVOID p) +static DWORD WINAPI LS_InheritanceProc(LPVOID p) { - /* We should NOT inherit the TLS values from our parent or from the + /* We should NOT inherit the FLS/TLS values from our parent or from the main thread. */ LPVOID val; - val = TlsGetValue(TLS_main); - ok(val == NULL, "TLS inheritance failed\n"); + val = LS_GetValueFunc(LS_main); + ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); - val = TlsGetValue(TLS_index0); - ok(val == NULL, "TLS inheritance failed\n"); + val = LS_GetValueFunc(LS_index0); + ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); - val = TlsGetValue(TLS_index1); - ok(val == NULL, "TLS inheritance failed\n"); + val = LS_GetValueFunc(LS_index1); + ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); return 0; } -/* Basic TLS usage test. Make sure we can create slots and the values we - store in them are separate among threads. Also test TLS value - inheritance with TLS_InheritanceProc. */ -static DWORD WINAPI TLS_ThreadProc(LPVOID p) +/* Basic FLS/TLS usage test. Make sure we can create slots and the values we + store in them are separate among threads. Also test FLS/TLS value + inheritance with LS_InheritanceProc. */ +static DWORD WINAPI LS_ThreadProc(LPVOID p) { LONG_PTR id = (LONG_PTR) p; LPVOID val; @@ -1352,80 +1383,80 @@ static DWORD WINAPI TLS_ThreadProc(LPVOID p) if (sync_threads_and_run_one(0, id)) { - TLS_index0 = TlsAlloc(); - ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); + LS_index0 = LS_AllocFunc(); + ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); } resync_after_run(); if (sync_threads_and_run_one(1, id)) { - TLS_index1 = TlsAlloc(); - ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); + LS_index1 = LS_AllocFunc(); + ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); /* Slot indices should be different even if created in different threads. */ - ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n"); + ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName); /* Both slots should be initialized to NULL */ - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); } resync_after_run(); if (sync_threads_and_run_one(0, id)) { - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); - ret = TlsSetValue(TLS_index0, (LPVOID) 1); - ok(ret, "TlsSetValue failed\n"); + ret = LS_SetValueFunc(LS_index0, (LPVOID) 1); + ok(ret, "%s failed\n", LS_SetValueFuncName); - ret = TlsSetValue(TLS_index1, (LPVOID) 2); - ok(ret, "TlsSetValue failed\n"); + ret = LS_SetValueFunc(LS_index1, (LPVOID) 2); + ok(ret, "%s failed\n", LS_SetValueFuncName); - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 1, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 2, "Slot not initialized correctly\n"); } resync_after_run(); if (sync_threads_and_run_one(1, id)) { - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == NULL, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == NULL, "Slot not initialized correctly\n"); - ret = TlsSetValue(TLS_index0, (LPVOID) 3); - ok(ret, "TlsSetValue failed\n"); + ret = LS_SetValueFunc(LS_index0, (LPVOID) 3); + ok(ret, "%s failed\n", LS_SetValueFuncName); - ret = TlsSetValue(TLS_index1, (LPVOID) 4); - ok(ret, "TlsSetValue failed\n"); + ret = LS_SetValueFunc(LS_index1, (LPVOID) 4); + ok(ret, "%s failed\n", LS_SetValueFuncName); - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 3, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 4, "Slot not initialized correctly\n"); } resync_after_run(); @@ -1434,36 +1465,36 @@ static DWORD WINAPI TLS_ThreadProc(LPVOID p) HANDLE thread; DWORD waitret, tid; - val = TlsGetValue(TLS_index0); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index0); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 1, "Slot not initialized correctly\n"); - val = TlsGetValue(TLS_index1); - ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); - ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); + val = LS_GetValueFunc(LS_index1); + ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); + ok(val == (LPVOID) 2, "Slot not initialized correctly\n"); - thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid); + thread = CreateThread(NULL, 0, LS_InheritanceProc, 0, 0, &tid); ok(thread != NULL, "CreateThread failed\n"); waitret = WaitForSingleObject(thread, 60000); ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); CloseHandle(thread); - ret = TlsFree(TLS_index0); - ok(ret, "TlsFree failed\n"); + ret = LS_FreeFunc(LS_index0); + ok(ret, "%s failed\n", LS_FreeFuncName); } resync_after_run(); if (sync_threads_and_run_one(1, id)) { - ret = TlsFree(TLS_index1); - ok(ret, "TlsFree failed\n"); + ret = LS_FreeFunc(LS_index1); + ok(ret, "%s failed\n", LS_FreeFuncName); } resync_after_run(); return 0; } -static void test_TLS(void) +static void run_LS_tests(void) { HANDLE threads[2]; LONG_PTR i; @@ -1472,17 +1503,17 @@ static void test_TLS(void) init_thread_sync_helpers(); - /* Allocate a TLS slot in the main thread to test for inheritance. */ - TLS_main = TlsAlloc(); - ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); - suc = TlsSetValue(TLS_main, (LPVOID) 4114); - ok(suc, "TlsSetValue failed\n"); + /* Allocate a slot in the main thread to test for inheritance. */ + LS_main = LS_AllocFunc(); + ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); + suc = LS_SetValueFunc(LS_main, (LPVOID) 4114); + ok(suc, "%s failed\n", LS_SetValueFuncName); for (i = 0; i < 2; ++i) { DWORD tid; - threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid); + threads[i] = CreateThread(NULL, 0, LS_ThreadProc, (LPVOID) i, 0, &tid); ok(threads[i] != NULL, "CreateThread failed\n"); } @@ -1492,11 +1523,51 @@ static void test_TLS(void) for (i = 0; i < 2; ++i) CloseHandle(threads[i]); - suc = TlsFree(TLS_main); - ok(suc, "TlsFree failed\n"); + suc = LS_FreeFunc(LS_main); + ok(suc, "%s failed\n", LS_FreeFuncName); cleanup_thread_sync_helpers(); } +static void test_TLS(void) +{ + LS_OutOfIndexesValue = TLS_OUT_OF_INDEXES; + + LS_AllocFunc = &TlsAlloc; + LS_GetValueFunc = &TlsGetValue; + LS_SetValueFunc = &TlsSetValue; + LS_FreeFunc = &TlsFree; + + LS_AllocFuncName = "TlsAlloc"; + LS_GetValueFuncName = "TlsGetValue"; + LS_SetValueFuncName = "TlsSetValue"; + LS_FreeFuncName = "TlsFree"; + + run_LS_tests(); +} + +static void test_FLS(void) +{ + if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue) + { + win_skip("Fiber Local Storage not supported\n"); + return; + } + + LS_OutOfIndexesValue = FLS_OUT_OF_INDEXES; + + LS_AllocFunc = &FLS_AllocFuncThunk; + LS_GetValueFunc = pFlsGetValue; + LS_SetValueFunc = pFlsSetValue; + LS_FreeFunc = pFlsFree; + + LS_AllocFuncName = "FlsAlloc"; + LS_GetValueFuncName = "FlsGetValue"; + LS_SetValueFuncName = "FlsSetValue"; + LS_FreeFuncName = "FlsFree"; + + run_LS_tests(); +} + static void test_ThreadErrorMode(void) { DWORD oldmode; @@ -2018,6 +2089,11 @@ static void init_funcs(void) X(GetThreadGroupAffinity); X(SetThreadGroupAffinity); + + X(FlsAlloc); + X(FlsFree); + X(FlsSetValue); + X(FlsGetValue); #undef X #define X(f) p##f = (void*)GetProcAddress(ntdll, #f) @@ -2085,6 +2161,7 @@ START_TEST(thread) test_QueueUserWorkItem(); test_RegisterWaitForSingleObject(); test_TLS(); + test_FLS(); test_ThreadErrorMode(); #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__)) test_thread_fpu_cw(); diff --git a/rostests/winetests/kernel32/virtual.c b/rostests/winetests/kernel32/virtual.c index 504823e9ac7..37dfb666f03 100755 --- a/rostests/winetests/kernel32/virtual.c +++ b/rostests/winetests/kernel32/virtual.c @@ -2799,10 +2799,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); - if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) - ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); - else - ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); /* Now a bit more complicated, the page containing the code is protected with * PAGE_GUARD memory protection. */ @@ -4109,14 +4106,7 @@ START_TEST(virtual) } if (!strcmp(argv[2], "sharedmemro")) { - if(!winetest_interactive) - { - skip("CORE-8541: Skipping test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16))\n"); - } - else - { - test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16)); - } + test_shared_memory_ro(TRUE, strtol(argv[3], NULL, 16)); return; } while (1)