diff --git a/rostests/winetests/kernel32/debugger.c b/rostests/winetests/kernel32/debugger.c index 011ed5ffd06..a802784cf58 100644 --- a/rostests/winetests/kernel32/debugger.c +++ b/rostests/winetests/kernel32/debugger.c @@ -718,6 +718,8 @@ static void doChildren(int argc, char **argv) blackbox.failures = child_failures; save_blackbox(blackbox_file, &blackbox, sizeof(blackbox)); + + HeapFree(GetProcessHeap(), 0, cmd); } static void test_debug_children(char *name, DWORD flag, BOOL debug_child) diff --git a/rostests/winetests/kernel32/file.c b/rostests/winetests/kernel32/file.c index 883aa57b355..2e4871ce7b0 100755 --- a/rostests/winetests/kernel32/file.c +++ b/rostests/winetests/kernel32/file.c @@ -3959,6 +3959,63 @@ static void test_SetFileValidData(void) DeleteFileA(filename); } +static void test_WriteFileGather(void) +{ + char temp_path[MAX_PATH], filename[MAX_PATH]; + HANDLE hfile, hiocp1, hiocp2; + DWORD ret, size; + ULONG_PTR key; + FILE_SEGMENT_ELEMENT fse[2]; + OVERLAPPED ovl, *povl = NULL; + SYSTEM_INFO si; + LPVOID buf = NULL; + + ret = GetTempPathA( MAX_PATH, temp_path ); + ok( ret != 0, "GetTempPathA error %d\n", GetLastError() ); + ok( ret < MAX_PATH, "temp path should fit into MAX_PATH\n" ); + ret = GetTempFileNameA( temp_path, "wfg", 0, filename ); + ok( ret != 0, "GetTempFileNameA error %d\n", GetLastError() ); + + hfile = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, 0 ); + ok( hfile != INVALID_HANDLE_VALUE, "CreateFile failed err %u\n", GetLastError() ); + if (hfile == INVALID_HANDLE_VALUE) return; + + hiocp1 = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 999, 0 ); + hiocp2 = CreateIoCompletionPort( hfile, hiocp1, 999, 0 ); + ok( hiocp2 != 0, "CreateIoCompletionPort failed err %u\n", GetLastError() ); + + GetSystemInfo( &si ); + buf = VirtualAlloc( NULL, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE ); + ok( buf != NULL, "VirtualAlloc failed err %u\n", GetLastError() ); + + memset( &ovl, 0, sizeof(ovl) ); + memset( fse, 0, sizeof(fse) ); + fse[0].Buffer = buf; + if (!WriteFileGather( hfile, fse, si.dwPageSize, NULL, &ovl )) + ok( GetLastError() == ERROR_IO_PENDING, "WriteFileGather failed err %u\n", GetLastError() ); + + ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); + ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); + ok( povl == &ovl, "wrong ovl %p\n", povl ); + + memset( &ovl, 0, sizeof(ovl) ); + memset( fse, 0, sizeof(fse) ); + fse[0].Buffer = buf; + if (!ReadFileScatter( hfile, fse, si.dwPageSize, NULL, &ovl )) + ok( GetLastError() == ERROR_IO_PENDING, "ReadFileScatter failed err %u\n", GetLastError() ); + + ret = GetQueuedCompletionStatus( hiocp2, &size, &key, &povl, 1000 ); + ok( ret, "GetQueuedCompletionStatus failed err %u\n", GetLastError()); + ok( povl == &ovl, "wrong ovl %p\n", povl ); + + CloseHandle( hfile ); + CloseHandle( hiocp1 ); + CloseHandle( hiocp2 ); + VirtualFree( buf, 0, MEM_RELEASE ); + DeleteFileA( filename ); +} + static unsigned file_map_access(unsigned access) { if (access & GENERIC_READ) access |= FILE_GENERIC_READ; @@ -4132,5 +4189,6 @@ START_TEST(file) test_GetFileInformationByHandleEx(); test_OpenFileById(); test_SetFileValidData(); + test_WriteFileGather(); test_file_access(); } diff --git a/rostests/winetests/kernel32/heap.c b/rostests/winetests/kernel32/heap.c index a36c373c1a7..d8768da945f 100755 --- a/rostests/winetests/kernel32/heap.c +++ b/rostests/winetests/kernel32/heap.c @@ -1127,7 +1127,7 @@ static void test_child_heap( const char *arg ) if (!(heap->flags & HEAP_GROWABLE) || heap->pattern == 0xffeeffee) /* vista layout */ { - ok( heap->flags == 0, "%s: got heap flags %08x expected 0\n", arg, heap->flags ); + ok( (heap->flags & ~HEAP_GROWABLE) == 0, "%s: got heap flags %08x\n", arg, heap->flags ); } else if (heap->pattern == 0xeeeeeeee && heap->flags == 0xeeeeeeee) { diff --git a/rostests/winetests/kernel32/loader.c b/rostests/winetests/kernel32/loader.c index e749238096a..af437796939 100644 --- a/rostests/winetests/kernel32/loader.c +++ b/rostests/winetests/kernel32/loader.c @@ -61,8 +61,8 @@ static void (WINAPI *pLdrShutdownProcess)(void); static BOOLEAN (WINAPI *pRtlDllShutdownInProgress)(void); static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); -static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG *); -static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG); +static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG_PTR *); +static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR); static void (WINAPI *pRtlAcquirePebLock)(void); static void (WINAPI *pRtlReleasePebLock)(void); static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR, @@ -1367,7 +1367,7 @@ static DWORD WINAPI mutex_thread_proc(void *param) if (ret == WAIT_OBJECT_0) break; else if (ret == WAIT_OBJECT_0 + 1) { - ULONG loader_lock_magic; + ULONG_PTR loader_lock_magic; trace("%04u: mutex_thread_proc: Entering loader lock\n", GetCurrentThreadId()); ret = pLdrLockLoaderLock(0, NULL, &loader_lock_magic); ok(!ret, "LdrLockLoaderLock error %#x\n", ret); diff --git a/rostests/winetests/kernel32/locale.c b/rostests/winetests/kernel32/locale.c index 4d4f9c25ccc..50f6105b309 100755 --- a/rostests/winetests/kernel32/locale.c +++ b/rostests/winetests/kernel32/locale.c @@ -93,27 +93,36 @@ static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR); static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL); static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM); +static INT (WINAPI *pGetGeoInfoA)(GEOID, GEOTYPE, LPSTR, INT, LANGID); +static INT (WINAPI *pGetGeoInfoW)(GEOID, GEOTYPE, LPWSTR, INT, LANGID); +static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC); static void InitFunctionPointers(void) { hKernel32 = GetModuleHandleA("kernel32"); - pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA"); - pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA"); - pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID"); - pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName"); - pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx"); - pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA"); - pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW"); - pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup"); - pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA"); - pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx"); - pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode"); - pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii"); - pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode"); - pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx"); - pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName"); - pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal"); - pCompareStringEx = (void*)GetProcAddress(hKernel32, "CompareStringEx"); + +#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) + X(EnumSystemLanguageGroupsA); + X(EnumLanguageGroupLocalesA); + X(LocaleNameToLCID); + X(LCIDToLocaleName); + X(LCMapStringEx); + X(FoldStringA); + X(FoldStringW); + X(IsValidLanguageGroup); + X(EnumUILanguagesA); + X(EnumSystemLocalesEx); + X(IdnToNameprepUnicode); + X(IdnToAscii); + X(IdnToUnicode); + X(GetLocaleInfoEx); + X(IsValidLocaleName); + X(CompareStringOrdinal); + X(CompareStringEx); + X(GetGeoInfoA); + X(GetGeoInfoW); + X(EnumSystemGeoID); +#undef X } #define eq(received, expected, label, type) \ @@ -2532,6 +2541,7 @@ static void test_FoldStringW(void) 0x0C66, /* Telugu */ 0x0CE6, /* Kannada */ 0x0D66, /* Maylayalam */ + 0x0DE6, /* Sinhala Lith */ 0x0E50, /* Thai */ 0x0ED0, /* Laos */ 0x0F20, /* Tibet */ @@ -2563,6 +2573,7 @@ static void test_FoldStringW(void) 0xA8D0, /* Saurashtra */ 0xA900, /* Kayah Li */ 0xA9D0, /* Javanese */ + 0xA9F0, /* Myanmar Tai Laing */ 0xAA50, /* Cham */ 0xABF0, /* Meetei Mayek */ 0xff10, /* Pliene chasse (?) */ @@ -3059,7 +3070,6 @@ static void test_EnumDateFormatsA(void) BOOL ret; LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); - trace("EnumDateFormatsA 0\n"); date_fmt_buf[0] = 0; SetLastError(0xdeadbeef); ret = EnumDateFormatsA(enum_datetime_procA, lcid, 0); @@ -3070,7 +3080,7 @@ static void test_EnumDateFormatsA(void) else { ok(ret, "EnumDateFormatsA(0) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumDateFormatsA(0): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)); @@ -3078,7 +3088,6 @@ static void test_EnumDateFormatsA(void) ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf); } - trace("EnumDateFormatsA LOCALE_USE_CP_ACP\n"); date_fmt_buf[0] = 0; SetLastError(0xdeadbeef); ret = EnumDateFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP); @@ -3089,7 +3098,7 @@ static void test_EnumDateFormatsA(void) else { ok(ret, "EnumDateFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumDateFormatsA(LOCALE_USE_CP_ACP): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)); @@ -3097,39 +3106,36 @@ static void test_EnumDateFormatsA(void) ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf); } - trace("EnumDateFormatsA DATE_SHORTDATE\n"); date_fmt_buf[0] = 0; ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_SHORTDATE); ok(ret, "EnumDateFormatsA(DATE_SHORTDATE) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumDateFormatsA(DATE_SHORTDATE): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)); ok(ret, "GetLocaleInfoA(LOCALE_SSHORTDATE) error %d\n", GetLastError()); ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf); - trace("EnumDateFormatsA DATE_LONGDATE\n"); date_fmt_buf[0] = 0; ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_LONGDATE); ok(ret, "EnumDateFormatsA(DATE_LONGDATE) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumDateFormatsA(DATE_LONGDATE): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_SLONGDATE, buf, sizeof(buf)); ok(ret, "GetLocaleInfoA(LOCALE_SLONGDATE) error %d\n", GetLastError()); ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf); - trace("EnumDateFormatsA DATE_YEARMONTH\n"); date_fmt_buf[0] = 0; SetLastError(0xdeadbeef); ret = EnumDateFormatsA(enum_datetime_procA, lcid, DATE_YEARMONTH); if (!ret && (GetLastError() == ERROR_INVALID_FLAGS)) { - skip("DATE_YEARMONTH is only present on W2K and later\n"); + win_skip("DATE_YEARMONTH is only present on W2K and later\n"); return; } ok(ret, "EnumDateFormatsA(DATE_YEARMONTH) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumDateFormatsA(DATE_YEARMONTH): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_SYEARMONTH, buf, sizeof(buf)); @@ -3144,22 +3150,20 @@ static void test_EnumTimeFormatsA(void) BOOL ret; LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); - trace("EnumTimeFormatsA 0\n"); date_fmt_buf[0] = 0; ret = EnumTimeFormatsA(enum_datetime_procA, lcid, 0); ok(ret, "EnumTimeFormatsA(0) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumTimeFormatsA(0): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf)); ok(ret, "GetLocaleInfoA(LOCALE_STIMEFORMAT) error %d\n", GetLastError()); ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf); - trace("EnumTimeFormatsA LOCALE_USE_CP_ACP\n"); date_fmt_buf[0] = 0; ret = EnumTimeFormatsA(enum_datetime_procA, lcid, LOCALE_USE_CP_ACP); ok(ret, "EnumTimeFormatsA(LOCALE_USE_CP_ACP) error %d\n", GetLastError()); - trace("%s\n", date_fmt_buf); + trace("EnumTimeFormatsA(LOCALE_USE_CP_ACP): %s\n", date_fmt_buf); /* test the 1st enumerated format */ if ((p = strchr(date_fmt_buf, '\n'))) *p = 0; ret = GetLocaleInfoA(lcid, LOCALE_STIMEFORMAT, buf, sizeof(buf)); @@ -3182,7 +3186,7 @@ static void test_GetCPInfo(void) ret = GetCPInfo(CP_UTF7, &cpinfo); if (!ret && GetLastError() == ERROR_INVALID_PARAMETER) { - skip("Codepage CP_UTF7 is not installed/available\n"); + win_skip("Codepage CP_UTF7 is not installed/available\n"); } else { @@ -3198,7 +3202,7 @@ static void test_GetCPInfo(void) ret = GetCPInfo(CP_UTF8, &cpinfo); if (!ret && GetLastError() == ERROR_INVALID_PARAMETER) { - skip("Codepage CP_UTF8 is not installed/available\n"); + win_skip("Codepage CP_UTF8 is not installed/available\n"); } else { @@ -3279,6 +3283,7 @@ static void test_GetStringTypeW(void) static const WCHAR space_special[] = {0x09, 0x0d, 0x85}; WORD types[20]; + WCHAR ch; int i; memset(types,0,sizeof(types)); @@ -3335,6 +3340,21 @@ static void test_GetStringTypeW(void) GetStringTypeW(CT_CTYPE1, space_special, 3, types); for (i = 0; i < 3; i++) ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE ); + + /* surrogate pairs */ + ch = 0xd800; + memset(types, 0, sizeof(types)); + GetStringTypeW(CT_CTYPE3, &ch, 1, types); + if (types[0] == C3_NOTAPPLICABLE) + win_skip("C3_HIGHSURROGATE/C3_LOWSURROGATE are not supported.\n"); + else { + ok(types[0] == C3_HIGHSURROGATE, "got %x\n", types[0]); + + ch = 0xdc00; + memset(types, 0, sizeof(types)); + GetStringTypeW(CT_CTYPE3, &ch, 1, types); + ok(types[0] == C3_LOWSURROGATE, "got %x\n", types[0]); + } } static void test_IdnToNameprepUnicode(void) @@ -3829,6 +3849,153 @@ static void test_CompareStringOrdinal(void) ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN); } +static void test_GetGeoInfo(void) +{ + char buffA[20]; + INT ret; + + if (!pGetGeoInfoA) + { + win_skip("GetGeoInfo is not available.\n"); + return; + } + + /* unassigned id */ + SetLastError(0xdeadbeef); + ret = pGetGeoInfoA(344, GEO_ISO2, NULL, 0, 0); + ok(ret == 0, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d\n", GetLastError()); + + ret = pGetGeoInfoA(203, GEO_ISO2, NULL, 0, 0); + ok(ret == 3, "got %d\n", ret); + + ret = pGetGeoInfoA(203, GEO_ISO3, NULL, 0, 0); + ok(ret == 4, "got %d\n", ret); + + ret = pGetGeoInfoA(203, GEO_ISO2, buffA, 3, 0); + ok(ret == 3, "got %d\n", ret); + ok(!strcmp(buffA, "RU"), "got %s\n", buffA); + + /* buffer pointer not NULL, length is 0 - return required length */ + buffA[0] = 'a'; + SetLastError(0xdeadbeef); + ret = pGetGeoInfoA(203, GEO_ISO2, buffA, 0, 0); + ok(ret == 3, "got %d\n", ret); + ok(buffA[0] == 'a', "got %c\n", buffA[0]); + + ret = pGetGeoInfoA(203, GEO_ISO3, buffA, 4, 0); + ok(ret == 4, "got %d\n", ret); + ok(!strcmp(buffA, "RUS"), "got %s\n", buffA); + + /* shorter buffer */ + SetLastError(0xdeadbeef); + buffA[1] = buffA[2] = 0; + ret = pGetGeoInfoA(203, GEO_ISO2, buffA, 2, 0); + ok(ret == 0, "got %d\n", ret); + ok(!strcmp(buffA, "RU"), "got %s\n", buffA); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d\n", GetLastError()); + + /* GEO_NATION returns GEOID in a string form */ + buffA[0] = 0; + ret = pGetGeoInfoA(203, GEO_NATION, buffA, 20, 0); + ok(ret == 4, "got %d\n", ret); + ok(!strcmp(buffA, "203"), "got %s\n", buffA); + + /* GEO_PARENT */ + buffA[0] = 0; + ret = pGetGeoInfoA(203, GEO_PARENT, buffA, 20, 0); + if (ret == 0) + win_skip("GEO_PARENT not supported.\n"); + else + { + ok(ret == 6, "got %d\n", ret); + ok(!strcmp(buffA, "47609"), "got %s\n", buffA); + } + + buffA[0] = 0; + ret = pGetGeoInfoA(203, GEO_ISO_UN_NUMBER, buffA, 20, 0); + if (ret == 0) + win_skip("GEO_ISO_UN_NUMBER not supported.\n"); + else + { + ok(ret == 4, "got %d\n", ret); + ok(!strcmp(buffA, "643"), "got %s\n", buffA); + } + + /* try invalid type value */ + SetLastError(0xdeadbeef); + ret = pGetGeoInfoA(203, GEO_PARENT + 1, NULL, 0, 0); + ok(ret == 0, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_FLAGS, "got %d\n", GetLastError()); +} + +static int geoidenum_count; +static BOOL CALLBACK test_geoid_enumproc(GEOID geoid) +{ + INT ret = pGetGeoInfoA(geoid, GEO_ISO2, NULL, 0, 0); + ok(ret == 3, "got %d for %d\n", ret, geoid); + /* valid geoid starts at 2 */ + ok(geoid >= 2, "got geoid %d\n", geoid); + + return geoidenum_count++ < 5; +} + +static BOOL CALLBACK test_geoid_enumproc2(GEOID geoid) +{ + geoidenum_count++; + return TRUE; +} + +static void test_EnumSystemGeoID(void) +{ + BOOL ret; + + if (!pEnumSystemGeoID) + { + win_skip("EnumSystemGeoID is not available.\n"); + return; + } + + SetLastError(0xdeadbeef); + ret = pEnumSystemGeoID(GEOCLASS_NATION, 0, NULL); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pEnumSystemGeoID(GEOCLASS_NATION+1, 0, test_geoid_enumproc); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_FLAGS, "got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pEnumSystemGeoID(GEOCLASS_NATION+1, 0, NULL); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d\n", GetLastError()); + + ret = pEnumSystemGeoID(GEOCLASS_NATION, 0, test_geoid_enumproc); + ok(ret, "got %d\n", ret); + + /* only first level is enumerated, not the whole hierarchy */ + geoidenum_count = 0; + ret = pEnumSystemGeoID(GEOCLASS_NATION, 39070, test_geoid_enumproc2); + if (ret == 0) + win_skip("Parent GEOID is not supported in EnumSystemGeoID.\n"); + else + ok(ret && geoidenum_count > 0, "got %d, count %d\n", ret, geoidenum_count); + + geoidenum_count = 0; + ret = pEnumSystemGeoID(GEOCLASS_REGION, 39070, test_geoid_enumproc2); + if (ret == 0) + win_skip("GEOCLASS_REGION is not supported in EnumSystemGeoID.\n"); + else + { + ok(ret && geoidenum_count > 0, "got %d, count %d\n", ret, geoidenum_count); + + geoidenum_count = 0; + ret = pEnumSystemGeoID(GEOCLASS_REGION, 0, test_geoid_enumproc2); + ok(ret && geoidenum_count > 0, "got %d, count %d\n", ret, geoidenum_count); + } +} + START_TEST(locale) { InitFunctionPointers(); @@ -3864,6 +4031,8 @@ START_TEST(locale) test_IdnToUnicode(); test_IsValidLocaleName(); test_CompareStringOrdinal(); + test_GetGeoInfo(); + test_EnumSystemGeoID(); /* this requires collation table patch to make it MS compatible */ if (0) test_sorting(); } diff --git a/rostests/winetests/kernel32/pipe.c b/rostests/winetests/kernel32/pipe.c index b192f967d51..3f89086f655 100755 --- a/rostests/winetests/kernel32/pipe.c +++ b/rostests/winetests/kernel32/pipe.c @@ -43,6 +43,72 @@ static void CALLBACK user_apc(ULONG_PTR param) user_apc_ran = TRUE; } + +enum rpcThreadOp +{ + RPC_READFILE +}; + +struct rpcThreadArgs +{ + ULONG_PTR returnValue; + DWORD lastError; + enum rpcThreadOp op; + ULONG_PTR args[5]; +}; + +static DWORD CALLBACK rpcThreadMain(LPVOID arg) +{ + struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg; + trace("rpcThreadMain starting\n"); + SetLastError( rpcargs->lastError ); + + switch (rpcargs->op) + { + case RPC_READFILE: + rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */ + (LPVOID)rpcargs->args[1], /* buffer */ + (DWORD)rpcargs->args[2], /* bytesToRead */ + (LPDWORD)rpcargs->args[3], /* bytesRead */ + (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */ + break; + + default: + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + rpcargs->returnValue = 0; + break; + } + + rpcargs->lastError = GetLastError(); + trace("rpcThreadMain returning\n"); + return 0; +} + +/* Runs ReadFile(...) from a different thread */ +static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped) +{ + struct rpcThreadArgs rpcargs; + HANDLE thread; + DWORD threadId; + + rpcargs.returnValue = 0; + rpcargs.lastError = GetLastError(); + rpcargs.op = RPC_READFILE; + rpcargs.args[0] = (ULONG_PTR)hFile; + rpcargs.args[1] = (ULONG_PTR)buffer; + rpcargs.args[2] = (ULONG_PTR)bytesToRead; + rpcargs.args[3] = (ULONG_PTR)bytesRead; + rpcargs.args[4] = (ULONG_PTR)overlapped; + + thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId); + ok(thread != NULL, "CreateThread failed. %d\n", GetLastError()); + ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError()); + CloseHandle(thread); + + SetLastError(rpcargs.lastError); + return (BOOL)rpcargs.returnValue; +} + static void test_CreateNamedPipe(int pipemode) { HANDLE hnp; @@ -60,6 +126,12 @@ static void test_CreateNamedPipe(int pipemode) trace("test_CreateNamedPipe starting in byte mode\n"); else trace("test_CreateNamedPipe starting in message mode\n"); + + /* Wait for non existing pipe */ + ret = WaitNamedPipeA(PIPENAME, 2000); + ok(ret == 0, "WaitNamedPipe returned %d for non existing pipe\n", ret); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); + /* Bad parameter checks */ hnp = CreateNamedPipeA("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT, /* nMaxInstances */ 1, @@ -121,6 +193,21 @@ static void test_CreateNamedPipe(int pipemode) /* Make sure we can read and write a few bytes in both directions */ memset(ibuf, 0, sizeof(ibuf)); ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n"); + ok(written == sizeof(obuf), "write file len\n"); + ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); + ok(readden == sizeof(obuf), "read got %d bytes\n", readden); + ok(memcmp(obuf, ibuf, written) == 0, "content check\n"); + + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n"); + ok(written == sizeof(obuf2), "write file len\n"); + ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); + ok(readden == sizeof(obuf2), "read got %d bytes\n", readden); + ok(memcmp(obuf2, ibuf, written) == 0, "content check\n"); + + /* Now the same again, but with an additional call to PeekNamedPipe */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n"); ok(written == sizeof(obuf), "write file len 1\n"); ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n"); ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden); @@ -139,6 +226,65 @@ static void test_CreateNamedPipe(int pipemode) ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden); ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n"); + /* Test how ReadFile behaves when the buffer is not big enough for the whole message */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n"); + ok(written == sizeof(obuf2), "write file len\n"); + ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n"); + ok(readden == 4, "read got %d bytes\n", readden); + ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n"); + ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden); + ok(memcmp(obuf2, ibuf, written) == 0, "content check\n"); + + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n"); + ok(written == sizeof(obuf), "write file len\n"); + if (pipemode == PIPE_TYPE_BYTE) + { + ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n"); + } + else + { + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n"); + } + ok(readden == 4, "read got %d bytes\n", readden); + ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n"); + ok(readden == sizeof(obuf) - 4, "read got %d bytes\n", readden); + ok(memcmp(obuf, ibuf, written) == 0, "content check\n"); + + /* Similar to above, but use a read buffer size small enough to read in three parts */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n"); + ok(written == sizeof(obuf2), "write file len\n"); + if (pipemode == PIPE_TYPE_BYTE) + { + ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n"); + ok(readden == 4, "read got %d bytes\n", readden); + ok(ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n"); + } + else + { + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n"); + ok(readden == 4, "read got %d bytes\n", readden); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n"); + } + ok(readden == 4, "read got %d bytes\n", readden); + ok(ReadFile(hnp, ibuf + 8, sizeof(ibuf) - 8, &readden, NULL), "ReadFile\n"); + ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden); + ok(memcmp(obuf2, ibuf, written) == 0, "content check\n"); + /* Test reading of multiple writes */ memset(ibuf, 0, sizeof(ibuf)); ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n"); @@ -147,20 +293,13 @@ static void test_CreateNamedPipe(int pipemode) ok(written == sizeof(obuf2), "write file len 3b\n"); ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n"); if (pipemode == PIPE_TYPE_BYTE) { - if (readden != sizeof(obuf)) /* Linux only returns the first message */ - ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); + todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); } else { - if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */ - ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden); + ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden); } - if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */ - ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail); + ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail); pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n"); if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) { @@ -182,21 +321,13 @@ static void test_CreateNamedPipe(int pipemode) ok(written == sizeof(obuf2), "write file len 4b\n"); ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n"); if (pipemode == PIPE_TYPE_BYTE) { - if (readden != sizeof(obuf)) /* Linux only returns the first message */ - /* should return all 23 bytes */ - ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); + todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); } else { - if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */ - ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden); + ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden); } - if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */ - ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail); + ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail); pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n"); if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) { @@ -227,9 +358,7 @@ static void test_CreateNamedPipe(int pipemode) ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n"); } else { - todo_wine { - ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n"); - } + ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n"); memset(ibuf, 0, sizeof(ibuf)); ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n"); @@ -237,14 +366,8 @@ static void test_CreateNamedPipe(int pipemode) ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n"); ok(written == sizeof(obuf2), "write file len 3b\n"); ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n"); - if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */ - ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden); - if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */ - ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail); - else - todo_wine ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail); + ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden); + ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail); pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n"); ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); @@ -253,7 +376,9 @@ static void test_CreateNamedPipe(int pipemode) } pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n"); - + if (readden <= sizeof(obuf)) + ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); + /* Multiple writes in the reverse direction */ /* the write of obuf2 from write4 should still be in the buffer */ ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n"); @@ -273,12 +398,8 @@ static void test_CreateNamedPipe(int pipemode) ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n"); ok(written == sizeof(obuf2), "write file len 6b\n"); ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n"); - if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */ - ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden); - else - todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden); - if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */ - ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail); + ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden); + ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail); pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n"); ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); @@ -287,6 +408,129 @@ static void test_CreateNamedPipe(int pipemode) } pbuf = ibuf; ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n"); + if (readden <= sizeof(obuf)) + ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n"); + + /* Test how ReadFile behaves when the buffer is not big enough for the whole message */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n"); + ok(written == sizeof(obuf2), "write file len 7\n"); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n"); + ok(readden == 4, "read got %d bytes 7\n", readden); + ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n"); + ok(readden == sizeof(obuf2) - 4, "read got %d bytes 7\n", readden); + ok(memcmp(obuf2, ibuf, written) == 0, "content check 7\n"); + + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n"); + ok(written == sizeof(obuf), "write file len 8\n"); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n"); + ok(readden == 4, "read got %d bytes 8\n", readden); + ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n"); + ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden); + ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n"); + + /* The following test shows that when doing a partial read of a message, the rest + * is still in the pipe, and can be received from a second thread. This shows + * especially that the content is _not_ stored in thread-local-storage until it is + * completely transmitted. The same method works even across multiple processes. */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n"); + ok(written == sizeof(obuf), "write file len 9\n"); + ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n"); + ok(written == sizeof(obuf2), "write file len 9\n"); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n"); + ok(readden == 4, "read got %d bytes 9\n", readden); + SetLastError(0xdeadbeef); + ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL); + todo_wine + ok(!ret, "RpcReadFile 9\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n"); + ok(readden == 4, "read got %d bytes 9\n", readden); + ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL); + ok(ret, "RpcReadFile 9\n"); + todo_wine + ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden); + ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n"); + if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */ + { + memset(ibuf, 0, sizeof(ibuf)); + SetLastError(0xdeadbeef); + ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL); + ok(!ret, "RpcReadFile 9\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n"); + ok(readden == 4, "read got %d bytes 9\n", readden); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n"); + ok(readden == 4, "read got %d bytes 9\n", readden); + ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL); + ok(ret, "RpcReadFile 9\n"); + ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden); + ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n"); + } + + /* Now the reverse direction */ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n"); + ok(written == sizeof(obuf2), "write file len 10\n"); + ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n"); + ok(written == sizeof(obuf), "write file len 10\n"); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n"); + ok(readden == 4, "read got %d bytes 10\n", readden); + SetLastError(0xdeadbeef); + ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL); + todo_wine + ok(!ret, "RpcReadFile 10\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n"); + ok(readden == 4, "read got %d bytes 10\n", readden); + ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL); + ok(ret, "RpcReadFile 10\n"); + todo_wine + ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden); + ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n"); + if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */ + { + memset(ibuf, 0, sizeof(ibuf)); + SetLastError(0xdeadbeef); + ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL); + ok(!ret, "RpcReadFile 10\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n"); + ok(readden == 4, "read got %d bytes 10\n", readden); + SetLastError(0xdeadbeef); + todo_wine + ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n"); + todo_wine + ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n"); + ok(readden == 4, "read got %d bytes 10\n", readden); + ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL); + ok(ret, "RpcReadFile 10\n"); + ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden); + ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n"); + } + } /* Picky conformance tests */ @@ -1656,11 +1900,9 @@ static void test_NamedPipeHandleState(void) /* lpSecurityAttrib */ NULL); ok(server != INVALID_HANDLE_VALUE, "cf failed\n"); ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0); - todo_wine ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError()); ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL, 0); - todo_wine ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError()); if (ret) { @@ -1681,7 +1923,6 @@ static void test_NamedPipeHandleState(void) state = PIPE_READMODE_MESSAGE; SetLastError(0xdeadbeef); ret = SetNamedPipeHandleState(server, &state, NULL, NULL); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); @@ -1691,13 +1932,11 @@ static void test_NamedPipeHandleState(void) state = PIPE_READMODE_BYTE; ret = SetNamedPipeHandleState(client, &state, NULL, NULL); - todo_wine ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError()); /* A byte-mode pipe client can't be changed to message mode, either. */ state = PIPE_READMODE_MESSAGE; SetLastError(0xdeadbeef); ret = SetNamedPipeHandleState(server, &state, NULL, NULL); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); @@ -1713,11 +1952,9 @@ static void test_NamedPipeHandleState(void) /* lpSecurityAttrib */ NULL); ok(server != INVALID_HANDLE_VALUE, "cf failed\n"); ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0); - todo_wine ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError()); ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL, 0); - todo_wine ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError()); if (ret) { @@ -1729,7 +1966,6 @@ static void test_NamedPipeHandleState(void) */ state = PIPE_READMODE_BYTE; ret = SetNamedPipeHandleState(server, &state, NULL, NULL); - todo_wine ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError()); client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL, @@ -1738,13 +1974,11 @@ static void test_NamedPipeHandleState(void) state = PIPE_READMODE_MESSAGE; ret = SetNamedPipeHandleState(client, &state, NULL, NULL); - todo_wine ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError()); /* A message-mode pipe client can also be changed to byte mode. */ state = PIPE_READMODE_BYTE; ret = SetNamedPipeHandleState(client, &state, NULL, NULL); - todo_wine ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError()); CloseHandle(client); @@ -1851,6 +2085,14 @@ static void test_readfileex_pending(void) wait = WaitForSingleObjectEx(event, 0, TRUE); ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait); + if (wait == WAIT_TIMEOUT) + { + ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL); + ok(ret == TRUE, "ReadFile failed\n"); + ok(completion_called == 0, "completion routine called during ReadFile\n"); + wait = WaitForSingleObjectEx(event, 0, TRUE); + ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait); + } ok(completion_called == 1, "completion routine not called\n"); ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode); diff --git a/rostests/winetests/kernel32/resource.c b/rostests/winetests/kernel32/resource.c index f94fed644ad..43551fa560c 100644 --- a/rostests/winetests/kernel32/resource.c +++ b/rostests/winetests/kernel32/resource.c @@ -394,6 +394,7 @@ static void check_exe( const sec_verify *verify ) int i; IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *nt; + IMAGE_OPTIONAL_HEADER *opt; IMAGE_SECTION_HEADER *sec; IMAGE_RESOURCE_DIRECTORY *dir; HANDLE file, mapping; @@ -415,6 +416,7 @@ static void check_exe( const sec_verify *verify ) goto end; nt = (void*) ((BYTE*) dos + dos->e_lfanew); + opt = &nt->OptionalHeader; sec = (void*) &nt[1]; for(i = 0; i < max_sections; i++) @@ -444,6 +446,10 @@ static void check_exe( const sec_verify *verify ) verify->NumberOfNamedEntries, dir->NumberOfNamedEntries); ok( dir->NumberOfIdEntries == verify->NumberOfIdEntries, "NumberOfIdEntries should be %d instead of %d\n", verify->NumberOfIdEntries, dir->NumberOfIdEntries); + + ok(opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].VirtualAddress == sec[verify->rsrc_section].VirtualAddress, + "VirtualAddress in optional header should be %d instead of %d\n", + sec[verify->rsrc_section].VirtualAddress, opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].VirtualAddress); } end: diff --git a/rostests/winetests/kernel32/sync.c b/rostests/winetests/kernel32/sync.c index 674e2ec3141..4ef5084447a 100755 --- a/rostests/winetests/kernel32/sync.c +++ b/rostests/winetests/kernel32/sync.c @@ -24,8 +24,9 @@ #include #include #include +#include -#include "wine/test.h" +#include static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG); static HANDLE (WINAPI *pCreateTimerQueue)(void); @@ -55,6 +56,7 @@ static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK); static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); +static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); static void test_signalandwait(void) { @@ -1153,15 +1155,32 @@ static void test_WaitForMultipleObjects(void) } /* a manual-reset event remains signaled, an auto-reset event is cleared */ - r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r); - r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r); ok(ResetEvent(maxevents[0]), "ResetEvent\n"); for (i=1; i