[KERNEL32_WINETEST] Sync with Wine Staging 1.9.18.

svn path=/trunk/; revision=72611
This commit is contained in:
Amine Khaldi 2016-09-07 22:32:56 +00:00
parent 9018c6fe32
commit 89932f2716
8 changed files with 641 additions and 155 deletions

View file

@ -908,6 +908,58 @@ static void testScreenBuffer(HANDLE hConOut)
SetConsoleOutputCP(oldcp); 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) static void test_GetSetConsoleInputExeName(void)
{ {
BOOL ret; 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()); 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) START_TEST(console)
{ {
static const char font_name[] = "Lucida Console"; static const char font_name[] = "Lucida Console";
@ -3044,6 +3145,8 @@ START_TEST(console)
testScroll(hConOut, sbi.dwSize); testScroll(hConOut, sbi.dwSize);
/* will test sb creation / modification / codepage handling */ /* will test sb creation / modification / codepage handling */
testScreenBuffer(hConOut); testScreenBuffer(hConOut);
/* Test waiting for a console handle */
testWaitForConsoleInput(hConIn);
/* clear duplicated console font table */ /* clear duplicated console font table */
CloseHandle(hConIn); CloseHandle(hConIn);
@ -3086,4 +3189,5 @@ START_TEST(console)
test_GetLargestConsoleWindowSize(hConOut); test_GetLargestConsoleWindowSize(hConOut);
test_GetConsoleFontInfo(hConOut); test_GetConsoleFontInfo(hConOut);
test_SetConsoleFont(hConOut); test_SetConsoleFont(hConOut);
test_GetConsoleScreenBufferInfoEx(hConOut);
} }

View file

@ -155,28 +155,20 @@ static void test_FiberHandling(void)
ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount); ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
pDeleteFiber(fibers[1]); pDeleteFiber(fibers[1]);
if (!pCreateFiberEx) if (pCreateFiberEx)
{ {
win_skip( "CreateFiberEx not present\n" );
return;
}
fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam); fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam);
ok(fibers[1] != NULL, "CreateFiberEx failed with error %u\n", GetLastError()); ok(fibers[1] != NULL, "CreateFiberEx failed with error %u\n", GetLastError());
pSwitchToFiber(fibers[1]); pSwitchToFiber(fibers[1]);
ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount); ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount);
pDeleteFiber(fibers[1]); pDeleteFiber(fibers[1]);
if (!pIsThreadAFiber)
{
win_skip( "IsThreadAFiber not present\n" );
return;
} }
else win_skip( "CreateFiberEx not present\n" );
ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n"); if (pIsThreadAFiber) ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n");
test_ConvertFiberToThread(); test_ConvertFiberToThread();
ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
} }
static void test_FiberLocalStorage(void) static void test_FiberLocalStorage(void)

View file

@ -4449,17 +4449,10 @@ static void test_file_access(void)
else else
{ {
/* FIXME: Remove once Wine is fixed */ /* FIXME: Remove once Wine is fixed */
if ((td[j].access & (GENERIC_READ | GENERIC_WRITE)) || 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_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_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) ||
(!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_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
{ {
ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access); 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()); ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());

View file

@ -70,6 +70,10 @@ static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRI
PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID, PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
PIMAGE_THUNK_DATA ThunkAddress,ULONG); PIMAGE_THUNK_DATA ThunkAddress,ULONG);
static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,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) 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 = static IMAGE_SECTION_HEADER section =
{ {
".rodata", /* Name */ ".rodata", /* Name */
{ 0x10 }, /* Misc */ { 0 }, /* Misc */
0, /* VirtualAddress */ 0, /* VirtualAddress */
0x0a, /* SizeOfRawData */ 0, /* SizeOfRawData */
0, /* PointerToRawData */ 0, /* PointerToRawData */
0, /* PointerToRelocations */ 0, /* PointerToRelocations */
0, /* PointerToLinenumbers */ 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); assert(nt_header->FileHeader.NumberOfSections <= 1);
if (nt_header->FileHeader.NumberOfSections) if (nt_header->FileHeader.NumberOfSections)
{ {
section.SizeOfRawData = 10;
if (nt_header->OptionalHeader.SectionAlignment >= page_size) if (nt_header->OptionalHeader.SectionAlignment >= page_size)
{ {
section.PointerToRawData = dos_size; section.PointerToRawData = dos_size;
@ -262,7 +268,11 @@ static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HE
ok( image.CommittedStackSize == nt_header->OptionalHeader.SizeOfStackCommit || broken(truncated), ok( image.CommittedStackSize == nt_header->OptionalHeader.SizeOfStackCommit || broken(truncated),
"%u: CommittedStackSize wrong %lx / %lx\n", id, "%u: CommittedStackSize wrong %lx / %lx\n", id,
image.CommittedStackSize, (SIZE_T)nt_header->OptionalHeader.SizeOfStackCommit ); image.CommittedStackSize, (SIZE_T)nt_header->OptionalHeader.SizeOfStackCommit );
ok( image.SubSystemType == nt_header->OptionalHeader.Subsystem || broken(truncated), 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, "%u: SubSystemType wrong %08x / %08x\n", id,
image.SubSystemType, nt_header->OptionalHeader.Subsystem ); image.SubSystemType, nt_header->OptionalHeader.Subsystem );
ok( image.SubsystemVersionLow == nt_header->OptionalHeader.MinorSubsystemVersion, ok( image.SubsystemVersionLow == nt_header->OptionalHeader.MinorSubsystemVersion,
@ -1470,6 +1480,7 @@ static HANDLE attached_thread[MAX_COUNT];
static DWORD attached_thread_count; static DWORD attached_thread_count;
HANDLE stop_event, event, mutex, semaphore, loader_lock_event, peb_lock_event, heap_lock_event, ack_event; 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 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) static DWORD WINAPI mutex_thread_proc(void *param)
{ {
@ -1552,9 +1563,18 @@ static DWORD WINAPI noop_thread_proc(void *param)
return 195; 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 BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
{ {
static LONG noop_thread_started; 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; DWORD ret;
ok(!inside_loader_lock, "inside_loader_lock should not be set\n"); 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(); ret = pRtlDllShutdownInProgress();
ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 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; break;
case DLL_PROCESS_DETACH: 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); 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"); ok(attached_thread_count >= 2, "attached thread count should be >= 2\n");
for (i = 0; i < attached_thread_count; i++) for (i = 0; i < attached_thread_count; i++)
@ -1791,9 +1865,26 @@ todo_wine
0, TRUE, DUPLICATE_SAME_ACCESS); 0, TRUE, DUPLICATE_SAME_ACCESS);
attached_thread_count++; 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; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param); trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
thread_detach_count++;
ret = pRtlDllShutdownInProgress(); ret = pRtlDllShutdownInProgress();
/* win7 doesn't allow creating a thread during process shutdown but /* win7 doesn't allow creating a thread during process shutdown but
@ -1805,6 +1896,23 @@ todo_wine
else else
ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); 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; break;
default: default:
trace("dll: %p, %d, %p\n", hinst, reason, param); 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 } }; } section_data = { 0xb8, dll_entry_point, { 0xff,0xe0 } };
#endif #endif
#include "poppack.h" #include "poppack.h"
static const char filler[0x1000];
DWORD dummy, file_align; DWORD dummy, file_align;
HANDLE file, thread, process, hmap, hmap_dup; HANDLE file, thread, process, hmap, hmap_dup;
char temp_path[MAX_PATH], dll_name[MAX_PATH], cmdline[MAX_PATH * 2]; 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"); ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n");
if (pd->ThunkAddress) 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"); ok(!!pd->TargetDllName, "no TargetDllName supplied\n");
if (pd->TargetDllName) if (pd->TargetDllName)
@ -2628,7 +2735,6 @@ static void test_ResolveDelayLoadedAPI(void)
{ {
static const char test_dll[] = "secur32.dll"; static const char test_dll[] = "secur32.dll";
static const char test_func[] = "SealMessage"; static const char test_func[] = "SealMessage";
static const char filler[0x1000];
char temp_path[MAX_PATH]; char temp_path[MAX_PATH];
char dll_name[MAX_PATH]; char dll_name[MAX_PATH];
IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir; IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir;
@ -2722,7 +2828,8 @@ static void test_ResolveDelayLoadedAPI(void)
/* sections */ /* sections */
section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress; 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.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; section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); ret = WriteFile(hfile, &section, 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) + section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) +
2 * (i + 1) * sizeof(IMAGE_THUNK_DATA); 2 * (i + 1) * sizeof(IMAGE_THUNK_DATA);
ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n"); 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; section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL); ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError()); ok(ret, "WriteFile error %d\n", GetLastError());
/* fill up to delay data */ /* fill up to delay data */
file_size = GetFileSize(hfile, NULL); SetFilePointer( hfile, nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress, NULL, SEEK_SET );
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());
/* delay data */ /* delay data */
idd.Attributes.AllAttributes = 1; idd.Attributes.AllAttributes = 1;
@ -2766,10 +2869,7 @@ static void test_ResolveDelayLoadedAPI(void)
ok(ret, "WriteFile error %d\n", GetLastError()); ok(ret, "WriteFile error %d\n", GetLastError());
/* fill up to extended delay data */ /* fill up to extended delay data */
file_size = GetFileSize(hfile, NULL); SetFilePointer( hfile, idd.DllNameRVA, NULL, SEEK_SET );
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler, idd.DllNameRVA - file_size, &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* extended delay data */ /* extended delay data */
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
@ -2784,9 +2884,20 @@ static void test_ResolveDelayLoadedAPI(void)
ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL); ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError()); 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); 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());
}
itd32.u1.Function = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError()); ok(ret, "WriteFile error %d\n", GetLastError());
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 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()); ok(ret, "WriteFile error %d\n", GetLastError());
/* fill up to eof */ /* fill up to eof */
file_size = GetFileSize(hfile, NULL); SetFilePointer( hfile, section.VirtualAddress + section.Misc.VirtualSize, NULL, SEEK_SET );
SetLastError(0xdeadbeef); SetEndOfFile( hfile );
ret = WriteFile(hfile, filler, section.VirtualAddress + section.Misc.VirtualSize - file_size, &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
CloseHandle(hfile); CloseHandle(hfile);
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
@ -2902,10 +3011,11 @@ START_TEST(loader)
{ {
int argc; int argc;
char **argv; char **argv;
HANDLE ntdll, mapping; HANDLE ntdll, mapping, kernel32;
SYSTEM_INFO si; SYSTEM_INFO si;
ntdll = GetModuleHandleA("ntdll.dll"); ntdll = GetModuleHandleA("ntdll.dll");
kernel32 = GetModuleHandleA("kernel32.dll");
pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection"); pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection");
pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection"); pNtQuerySection = (void *)GetProcAddress(ntdll, "NtQuerySection");
pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection"); pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection");
@ -2922,7 +3032,11 @@ START_TEST(loader)
pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock"); pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock"); pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData"); 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 ); GetSystemInfo( &si );
page_size = si.dwPageSize; page_size = si.dwPageSize;

View file

@ -102,6 +102,7 @@ static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC);
static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR); static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int);
static void InitFunctionPointers(void) static void InitFunctionPointers(void)
{ {
@ -132,6 +133,7 @@ static void InitFunctionPointers(void)
X(EnumSystemGeoID); X(EnumSystemGeoID);
X(GetSystemPreferredUILanguages); X(GetSystemPreferredUILanguages);
X(GetThreadPreferredUILanguages); X(GetThreadPreferredUILanguages);
X(GetNumberFormatEx);
mod = GetModuleHandleA("ntdll"); mod = GetModuleHandleA("ntdll");
X(RtlUpcaseUnicodeChar); 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 { struct comparestringa_entry {
LCID lcid; LCID lcid;
DWORD flags; DWORD flags;
@ -4102,7 +4286,7 @@ static void test_IdnToUnicode(void)
static void test_GetLocaleInfoEx(void) static void test_GetLocaleInfoEx(void)
{ {
static const WCHAR enW[] = {'e','n',0}; static const WCHAR enW[] = {'e','n',0};
WCHAR bufferW[80]; WCHAR bufferW[80], buffer2[80];
INT ret; INT ret;
if (!pGetLocaleInfoEx) 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)); ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
ptr++; 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_GetDateFormatW();
test_GetCurrencyFormatA(); /* Also tests the W version */ test_GetCurrencyFormatA(); /* Also tests the W version */
test_GetNumberFormatA(); /* Also tests the W version */ test_GetNumberFormatA(); /* Also tests the W version */
test_GetNumberFormatEx();
test_CompareStringA(); test_CompareStringA();
test_CompareStringW(); test_CompareStringW();
test_CompareStringEx(); test_CompareStringEx();

View file

@ -187,15 +187,8 @@ static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *
len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH); len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
if(passfail==NULL) { if(passfail==NULL) {
ok(len, "%s: GetLongPathNameA failed\n",errstr); ok(len, "%s: GetLongPathNameA failed\n",errstr);
if(HAS_TRAIL_SLASH_A(fullpath)) { ok(!lstrcmpiA(fullpathlong, tmpstr), "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
ok(lstrcmpiA(fullpathlong,tmpstr)==0, errstr, tmpstr, fullpathlong);
"%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);
}
} else { } else {
passfail->longlen=len; passfail->longlen=len;
passfail->longerror=GetLastError(); 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,SHORTDIR,LONGFILE);
test_ShortPathCase(curdir,LONGDIR,SHORTFILE); test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
test_ShortPathCase(curdir,LONGDIR,LONGFILE); 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) 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(ret, "GetShortPathName error %d\n", GetLastError());
ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf); 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(".."); SetCurrentDirectoryA("..");
DeleteFileA("foo\\file"); DeleteFileA("foo\\file");
RemoveDirectoryA("foo"); RemoveDirectoryA("foo");

View file

@ -1318,33 +1318,64 @@ static void test_RegisterWaitForSingleObject(void)
ret = pUnregisterWait(wait_handle); ret = pUnregisterWait(wait_handle);
ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); 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 LS_main;
static DWORD TLS_index0, TLS_index1; static DWORD LS_index0, LS_index1;
static DWORD LS_OutOfIndexesValue;
static DWORD WINAPI TLS_InheritanceProc(LPVOID p) /* 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)
{ {
/* We should NOT inherit the TLS values from our parent or from the return pFlsAlloc(NULL);
}
static DWORD WINAPI LS_InheritanceProc(LPVOID p)
{
/* We should NOT inherit the FLS/TLS values from our parent or from the
main thread. */ main thread. */
LPVOID val; LPVOID val;
val = TlsGetValue(TLS_main); val = LS_GetValueFunc(LS_main);
ok(val == NULL, "TLS inheritance failed\n"); ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(val == NULL, "TLS inheritance failed\n"); ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(val == NULL, "TLS inheritance failed\n"); ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
return 0; return 0;
} }
/* Basic TLS usage test. Make sure we can create slots and the values we /* Basic FLS/TLS usage test. Make sure we can create slots and the values we
store in them are separate among threads. Also test TLS value store in them are separate among threads. Also test FLS/TLS value
inheritance with TLS_InheritanceProc. */ inheritance with LS_InheritanceProc. */
static DWORD WINAPI TLS_ThreadProc(LPVOID p) static DWORD WINAPI LS_ThreadProc(LPVOID p)
{ {
LONG_PTR id = (LONG_PTR) p; LONG_PTR id = (LONG_PTR) p;
LPVOID val; LPVOID val;
@ -1352,80 +1383,80 @@ static DWORD WINAPI TLS_ThreadProc(LPVOID p)
if (sync_threads_and_run_one(0, id)) if (sync_threads_and_run_one(0, id))
{ {
TLS_index0 = TlsAlloc(); LS_index0 = LS_AllocFunc();
ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
} }
resync_after_run(); resync_after_run();
if (sync_threads_and_run_one(1, id)) if (sync_threads_and_run_one(1, id))
{ {
TLS_index1 = TlsAlloc(); LS_index1 = LS_AllocFunc();
ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
/* Slot indices should be different even if created in different /* Slot indices should be different even if created in different
threads. */ 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 */ /* Both slots should be initialized to NULL */
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
} }
resync_after_run(); resync_after_run();
if (sync_threads_and_run_one(0, id)) if (sync_threads_and_run_one(0, id))
{ {
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
ret = TlsSetValue(TLS_index0, (LPVOID) 1); ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
ok(ret, "TlsSetValue failed\n"); ok(ret, "%s failed\n", LS_SetValueFuncName);
ret = TlsSetValue(TLS_index1, (LPVOID) 2); ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
ok(ret, "TlsSetValue failed\n"); ok(ret, "%s failed\n", LS_SetValueFuncName);
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
} }
resync_after_run(); resync_after_run();
if (sync_threads_and_run_one(1, id)) if (sync_threads_and_run_one(1, id))
{ {
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == NULL, "TLS slot not initialized correctly\n"); ok(val == NULL, "Slot not initialized correctly\n");
ret = TlsSetValue(TLS_index0, (LPVOID) 3); ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
ok(ret, "TlsSetValue failed\n"); ok(ret, "%s failed\n", LS_SetValueFuncName);
ret = TlsSetValue(TLS_index1, (LPVOID) 4); ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
ok(ret, "TlsSetValue failed\n"); ok(ret, "%s failed\n", LS_SetValueFuncName);
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n"); ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n"); ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
} }
resync_after_run(); resync_after_run();
@ -1434,36 +1465,36 @@ static DWORD WINAPI TLS_ThreadProc(LPVOID p)
HANDLE thread; HANDLE thread;
DWORD waitret, tid; DWORD waitret, tid;
val = TlsGetValue(TLS_index0); val = LS_GetValueFunc(LS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
val = TlsGetValue(TLS_index1); val = LS_GetValueFunc(LS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); 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"); ok(thread != NULL, "CreateThread failed\n");
waitret = WaitForSingleObject(thread, 60000); waitret = WaitForSingleObject(thread, 60000);
ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
CloseHandle(thread); CloseHandle(thread);
ret = TlsFree(TLS_index0); ret = LS_FreeFunc(LS_index0);
ok(ret, "TlsFree failed\n"); ok(ret, "%s failed\n", LS_FreeFuncName);
} }
resync_after_run(); resync_after_run();
if (sync_threads_and_run_one(1, id)) if (sync_threads_and_run_one(1, id))
{ {
ret = TlsFree(TLS_index1); ret = LS_FreeFunc(LS_index1);
ok(ret, "TlsFree failed\n"); ok(ret, "%s failed\n", LS_FreeFuncName);
} }
resync_after_run(); resync_after_run();
return 0; return 0;
} }
static void test_TLS(void) static void run_LS_tests(void)
{ {
HANDLE threads[2]; HANDLE threads[2];
LONG_PTR i; LONG_PTR i;
@ -1472,17 +1503,17 @@ static void test_TLS(void)
init_thread_sync_helpers(); init_thread_sync_helpers();
/* Allocate a TLS slot in the main thread to test for inheritance. */ /* Allocate a slot in the main thread to test for inheritance. */
TLS_main = TlsAlloc(); LS_main = LS_AllocFunc();
ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
suc = TlsSetValue(TLS_main, (LPVOID) 4114); suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
ok(suc, "TlsSetValue failed\n"); ok(suc, "%s failed\n", LS_SetValueFuncName);
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
{ {
DWORD tid; 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"); ok(threads[i] != NULL, "CreateThread failed\n");
} }
@ -1492,11 +1523,51 @@ static void test_TLS(void)
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
CloseHandle(threads[i]); CloseHandle(threads[i]);
suc = TlsFree(TLS_main); suc = LS_FreeFunc(LS_main);
ok(suc, "TlsFree failed\n"); ok(suc, "%s failed\n", LS_FreeFuncName);
cleanup_thread_sync_helpers(); 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) static void test_ThreadErrorMode(void)
{ {
DWORD oldmode; DWORD oldmode;
@ -2018,6 +2089,11 @@ static void init_funcs(void)
X(GetThreadGroupAffinity); X(GetThreadGroupAffinity);
X(SetThreadGroupAffinity); X(SetThreadGroupAffinity);
X(FlsAlloc);
X(FlsFree);
X(FlsSetValue);
X(FlsGetValue);
#undef X #undef X
#define X(f) p##f = (void*)GetProcAddress(ntdll, #f) #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
@ -2085,6 +2161,7 @@ START_TEST(thread)
test_QueueUserWorkItem(); test_QueueUserWorkItem();
test_RegisterWaitForSingleObject(); test_RegisterWaitForSingleObject();
test_TLS(); test_TLS();
test_FLS();
test_ThreadErrorMode(); test_ThreadErrorMode();
#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__)) #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
test_thread_fpu_cw(); test_thread_fpu_cw();

View file

@ -2799,9 +2799,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
ret = send_message_excpt( hWnd, WM_USER, 0, 0 ); ret = send_message_excpt( hWnd, WM_USER, 0, 0 );
ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); 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 ); 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 /* Now a bit more complicated, the page containing the code is protected with
@ -4108,15 +4105,8 @@ START_TEST(virtual)
return; return;
} }
if (!strcmp(argv[2], "sharedmemro")) 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; return;
} }
while (1) while (1)