[KERNEL32_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246

svn path=/trunk/; revision=66620
This commit is contained in:
Amine Khaldi 2015-03-09 17:15:16 +00:00
parent 4e51a10654
commit 780865a796
21 changed files with 4371 additions and 189 deletions

View file

@ -8,6 +8,7 @@ list(APPEND SOURCE
codepage.c
comm.c
console.c
cpu.c
debugger.c
directory.c
drive.c
@ -37,6 +38,11 @@ list(APPEND SOURCE
testlist.c)
add_executable(kernel32_winetest ${SOURCE} resource.rc)
if(NOT MSVC)
add_target_compile_flags(kernel32_winetest "-Wno-format")
endif()
set_module_type(kernel32_winetest win32cui)
add_importlibs(kernel32_winetest user32 advapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET kernel32_winetest DESTINATION reactos/bin FOR all)

View file

@ -97,6 +97,7 @@ static const char manifest3[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
" publicKeyToken=\"6595b6414666f1df\" />"
"<description />"
"<file name=\"testlib.dll\">"
"<windowClass>wndClass</windowClass>"
" <comClass description=\"Test com class\""
@ -221,6 +222,17 @@ static const char manifest4[] =
"</dependency>"
"</assembly>";
static const char manifest5[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\">"
"</assemblyIdentity>"
"<dependency>"
" <dependentAssembly dependencyType=\"preRequisite\" allowDelayedBinding=\"true\">"
" <assemblyIdentity name=\"Missing.Assembly\" version=\"1.0.0.0\" />"
" </dependentAssembly>"
"</dependency>"
"</assembly>";
static const char testdep_manifest1[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity type=\"win32\" name=\"testdep\" version=\"6.5.4.3\" processorArchitecture=\"" ARCH "\"/>"
@ -304,8 +316,6 @@ static const WCHAR wndClass2W[] =
{'w','n','d','C','l','a','s','s','2',0};
static const WCHAR wndClass3W[] =
{'w','n','d','C','l','a','s','s','3',0};
static const WCHAR acr_manifest[] =
{'a','c','r','.','m','a','n','i','f','e','s','t',0};
static WCHAR app_dir[MAX_PATH], exe_path[MAX_PATH], work_dir[MAX_PATH], work_dir_subdir[MAX_PATH];
static WCHAR app_manifest_path[MAX_PATH], manifest_path[MAX_PATH], depmanifest_path[MAX_PATH];
@ -1729,6 +1739,29 @@ static void test_typelib_section(void)
pReleaseActCtx(handle);
}
static void test_allowDelayedBinding(void)
{
HANDLE handle;
if (!create_manifest_file("test5.manifest", manifest5, -1, NULL, NULL)) {
skip("Could not create manifest file\n");
return;
}
handle = test_create("test5.manifest");
if (handle == INVALID_HANDLE_VALUE) {
win_skip("allowDelayedBinding attribute is not supported.\n");
return;
}
DeleteFileA("test5.manifest");
DeleteFileA("testdep.manifest");
if (handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle, __LINE__);
pReleaseActCtx(handle);
}
}
static void test_actctx(void)
{
ULONG_PTR cookie;
@ -1994,6 +2027,7 @@ static void test_actctx(void)
test_wndclass_section();
test_dllredirect_section();
test_typelib_section();
test_allowDelayedBinding();
}
static void test_app_manifest(void)
@ -2055,7 +2089,6 @@ static void run_child_process(void)
static void init_paths(void)
{
LPWSTR ptr;
WCHAR last;
static const WCHAR dot_manifest[] = {'.','M','a','n','i','f','e','s','t',0};
static const WCHAR backslash[] = {'\\',0};
@ -2067,8 +2100,8 @@ static void init_paths(void)
ptr[1] = 0;
GetCurrentDirectoryW(MAX_PATH, work_dir);
last = work_dir[lstrlenW(work_dir) - 1];
if (last != '\\' && last != '/')
ptr = work_dir + lstrlenW( work_dir ) - 1;
if (*ptr != '\\' && *ptr != '/')
lstrcatW(work_dir, backslash);
lstrcpyW(work_dir_subdir, work_dir);
lstrcatW(work_dir_subdir, subdir);

View file

@ -472,7 +472,7 @@ static void test_readdirectorychanges(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
@ -502,7 +502,7 @@ static void test_readdirectorychanges(void)
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
ok( ov.Internal == STATUS_PENDING, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_PENDING, "ov.Internal wrong\n");
ok( ov.InternalHigh == 1, "ov.InternalHigh wrong\n");
r = WaitForSingleObject( ov.hEvent, 0 );
@ -514,10 +514,10 @@ static void test_readdirectorychanges(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
if (ov.Internal == STATUS_SUCCESS)
if ((NTSTATUS)ov.Internal == STATUS_SUCCESS)
{
r = GetOverlappedResult( hdir, &ov, &dwCount, TRUE );
ok( r == TRUE, "getoverlappedresult failed\n");
@ -540,7 +540,7 @@ static void test_readdirectorychanges(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
/* test the recursive watch */
@ -553,10 +553,19 @@ static void test_readdirectorychanges(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x18, "ov.InternalHigh wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x18 || ov.InternalHigh == 0x12 + 0x18,
"ov.InternalHigh wrong %lx\n", ov.InternalHigh);
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
if (pfni->NextEntryOffset) /* we may get a modified event on the parent dir */
{
ok( pfni->NextEntryOffset == 0x12, "offset wrong %x\n", pfni->NextEntryOffset );
ok( pfni->Action == FILE_ACTION_MODIFIED, "action wrong %d\n", pfni->Action );
ok( pfni->FileNameLength == 3*sizeof(WCHAR), "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],3*sizeof(WCHAR)), "name wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION)((char *)pfni + pfni->NextEntryOffset);
}
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong\n" );
@ -589,7 +598,7 @@ static void test_readdirectorychanges(void)
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong %u\n", pfni->FileNameLength );
ok( !memcmp(pfni->FileName,&szGa[1],6*sizeof(WCHAR)), "name wrong\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
dwCount = (char *)&pfni->FileName[pfni->FileNameLength/sizeof(WCHAR)] - buffer;
ok( ov.InternalHigh == dwCount, "ov.InternalHigh wrong %lu/%u\n",ov.InternalHigh, dwCount );
@ -666,7 +675,7 @@ static void test_readdirectorychanges_null(void)
r = WaitForSingleObject( ov.hEvent, 0 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
ov.Internal = 0;
@ -687,7 +696,7 @@ static void test_readdirectorychanges_null(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
@ -763,7 +772,7 @@ static void test_readdirectorychanges_filedir(void)
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( (NTSTATUS)ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;

View file

@ -20,6 +20,7 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include <limits.h>
#include "wine/test.h"
@ -412,6 +413,521 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar)
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
static void test_utf7_encoding(void)
{
WCHAR input[16];
char output[16], expected[16];
int i, len, expected_len;
static const BOOL directly_encodable_table[] =
{
1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0x00 - 0x0F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1F */
1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 0x20 - 0x2F */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x30 - 0x3F */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4F */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50 - 0x5F */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6F */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70 - 0x7F */
};
static const char base64_encoding_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const struct
{
/* inputs */
WCHAR src[16];
int srclen;
char *dst;
int dstlen;
/* expected outputs */
char expected_dst[16];
int chars_written;
int len;
}
tests[] =
{
/* tests string conversion with srclen=-1 */
{
{0x4F60,0x597D,0x5417,0}, -1, output, sizeof(output) - 1,
"+T2BZfVQX-", 11, 11
},
/* tests string conversion with srclen=-2 */
{
{0x4F60,0x597D,0x5417,0}, -2, output, sizeof(output) - 1,
"+T2BZfVQX-", 11, 11
},
/* tests string conversion with dstlen=strlen(expected_dst) */
{
{0x4F60,0x597D,0x5417,0}, -1, output, 10,
"+T2BZfVQX-", 10, 0
},
/* tests string conversion with dstlen=strlen(expected_dst)+1 */
{
{0x4F60,0x597D,0x5417,0}, -1, output, 11,
"+T2BZfVQX-", 11, 11
},
/* tests string conversion with dstlen=strlen(expected_dst)+2 */
{
{0x4F60,0x597D,0x5417,0}, -1, output, 12,
"+T2BZfVQX-", 11, 11
},
/* tests dry run with dst=NULL and dstlen=0 */
{
{0x4F60,0x597D,0x5417,0}, -1, NULL, 0,
{0}, 0, 11
},
/* tests dry run with dst!=NULL and dstlen=0 */
{
{0x4F60,0x597D,0x5417,0}, -1, output, 0,
{0}, 0, 11
},
/* tests srclen < strlenW(src) with directly encodable chars */
{
{'h','e','l','l','o',0}, 2, output, sizeof(output) - 1,
"he", 2, 2
},
/* tests srclen < strlenW(src) with non-directly encodable chars */
{
{0x4F60,0x597D,0x5417,0}, 2, output, sizeof(output) - 1,
"+T2BZfQ-", 8, 8
},
/* tests a single null char */
{
{0}, -1, output, sizeof(output) - 1,
"", 1, 1
},
/* tests a buffer that runs out while not encoding a UTF-7 sequence */
{
{'h','e','l','l','o',0}, -1, output, 2,
"he", 2, 0
},
/* tests a buffer that runs out after writing 1 base64 character */
{
{0x4F60,0x0001,0}, -1, output, 2,
"+T", 2, 0
},
/* tests a buffer that runs out after writing 2 base64 characters */
{
{0x4F60,0x0001,0}, -1, output, 3,
"+T2", 3, 0
},
/* tests a buffer that runs out after writing 3 base64 characters */
{
{0x4F60,0x0001,0}, -1, output, 4,
"+T2A", 4, 0
},
/* tests a buffer that runs out just after writing the + sign */
{
{0x4F60,0}, -1, output, 1,
"+", 1, 0
},
/* tests a buffer that runs out just before writing the - sign
* the number of bits to encode here is evenly divisible by 6 */
{
{0x4F60,0x597D,0x5417,0}, -1, output, 9,
"+T2BZfVQX", 9, 0
},
/* tests a buffer that runs out just before writing the - sign
* the number of bits to encode here is NOT evenly divisible by 6 */
{
{0x4F60,0}, -1, output, 4,
"+T2", 3, 0
},
/* tests a buffer that runs out in the middle of escaping a + sign */
{
{'+',0}, -1, output, 1,
"+", 1, 0
}
};
/* test which characters are encoded if surrounded by non-encoded characters */
for (i = 0; i <= 0xFFFF; i++)
{
input[0] = ' ';
input[1] = i;
input[2] = ' ';
input[3] = 0;
memset(output, '#', sizeof(output) - 1);
output[sizeof(output) - 1] = 0;
len = WideCharToMultiByte(CP_UTF7, 0, input, 4, output, sizeof(output) - 1, NULL, NULL);
if (i == '+')
{
/* '+' is a special case and is encoded as "+-" */
expected_len = 5;
strcpy(expected, " +- ");
}
else if (i <= 0x7F && directly_encodable_table[i])
{
/* encodes directly */
expected_len = 4;
sprintf(expected, " %c ", i);
}
else
{
/* base64-encodes */
expected_len = 8;
sprintf(expected, " +%c%c%c- ",
base64_encoding_table[(i & 0xFC00) >> 10],
base64_encoding_table[(i & 0x03F0) >> 4],
base64_encoding_table[(i & 0x000F) << 2]);
}
ok(len == expected_len, "i=0x%04x: expected len=%i, got len=%i\n", i, expected_len, len);
ok(memcmp(output, expected, expected_len) == 0,
"i=0x%04x: expected output='%s', got output='%s'\n", i, expected, output);
ok(output[expected_len] == '#', "i=0x%04x: expected output[%i]='#', got output[%i]=%i\n",
i, expected_len, expected_len, output[expected_len]);
}
/* test which one-byte characters are absorbed into surrounding base64 blocks
* (Windows always ends the base64 block when it encounters a directly encodable character) */
for (i = 0; i <= 0xFFFF; i++)
{
input[0] = 0x2672;
input[1] = i;
input[2] = 0x2672;
input[3] = 0;
memset(output, '#', sizeof(output) - 1);
output[sizeof(output) - 1] = 0;
len = WideCharToMultiByte(CP_UTF7, 0, input, 4, output, sizeof(output) - 1, NULL, NULL);
if (i == '+')
{
/* '+' is a special case and is encoded as "+-" */
expected_len = 13;
strcpy(expected, "+JnI-+-+JnI-");
}
else if (i <= 0x7F && directly_encodable_table[i])
{
/* encodes directly */
expected_len = 12;
sprintf(expected, "+JnI-%c+JnI-", i);
}
else
{
/* base64-encodes */
expected_len = 11;
sprintf(expected, "+Jn%c%c%c%cZy-",
base64_encoding_table[8 | ((i & 0xC000) >> 14)],
base64_encoding_table[(i & 0x3F00) >> 8],
base64_encoding_table[(i & 0x00FC) >> 2],
base64_encoding_table[((i & 0x0003) << 4) | 2]);
}
ok(len == expected_len, "i=0x%04x: expected len=%i, got len=%i\n", i, expected_len, len);
ok(memcmp(output, expected, expected_len) == 0,
"i=0x%04x: expected output='%s', got output='%s'\n", i, expected, output);
ok(output[expected_len] == '#', "i=0x%04x: expected output[%i]='#', got output[%i]=%i\n",
i, expected_len, expected_len, output[expected_len]);
}
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
{
memset(output, '#', sizeof(output) - 1);
output[sizeof(output) - 1] = 0;
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF7, 0, tests[i].src, tests[i].srclen,
tests[i].dst, tests[i].dstlen, NULL, NULL);
if (!tests[i].len)
{
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"tests[%i]: expected error=0x%x, got error=0x%x\n",
i, ERROR_INSUFFICIENT_BUFFER, GetLastError());
}
ok(len == tests[i].len, "tests[%i]: expected len=%i, got len=%i\n", i, tests[i].len, len);
if (tests[i].dst)
{
ok(memcmp(tests[i].dst, tests[i].expected_dst, tests[i].chars_written) == 0,
"tests[%i]: expected dst='%s', got dst='%s'\n",
i, tests[i].expected_dst, tests[i].dst);
ok(tests[i].dst[tests[i].chars_written] == '#',
"tests[%i]: expected dst[%i]='#', got dst[%i]=%i\n",
i, tests[i].chars_written, tests[i].chars_written, tests[i].dst[tests[i].chars_written]);
}
}
}
static void test_utf7_decoding(void)
{
char input[32];
WCHAR output[32], expected[32];
int i, len, expected_len;
static const signed char base64_decoding_table[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20-0x2F */
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40-0x4F */
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50-0x5F */
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60-0x6F */
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70-0x7F */
};
struct
{
/* inputs */
char src[32];
int srclen;
WCHAR *dst;
int dstlen;
/* expected outputs */
WCHAR expected_dst[32];
int chars_written;
int len;
}
tests[] =
{
/* tests string conversion with srclen=-1 */
{
"+T2BZfQ-", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60,0x597D,0}, 3, 3
},
/* tests string conversion with srclen=-2 */
{
"+T2BZfQ-", -2, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60,0x597D,0}, 3, 3
},
/* tests string conversion with dstlen=strlen(expected_dst) */
{
"+T2BZfQ-", -1, output, 2,
{0x4F60,0x597D}, 2, 0
},
/* tests string conversion with dstlen=strlen(expected_dst)+1 */
{
"+T2BZfQ-", -1, output, 3,
{0x4F60,0x597D,0}, 3, 3
},
/* tests string conversion with dstlen=strlen(expected_dst)+2 */
{
"+T2BZfQ-", -1, output, 4,
{0x4F60,0x597D,0}, 3, 3
},
/* tests dry run with dst=NULL and dstlen=0 */
{
"+T2BZfQ-", -1, NULL, 0,
{0}, 0, 3
},
/* tests dry run with dst!=NULL and dstlen=0 */
{
"+T2BZfQ-", -1, output, 0,
{0}, 0, 3
},
/* tests ill-formed UTF-7: 6 bits, not enough for a byte pair */
{
"+T-+T-+T-hello", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{'h','e','l','l','o',0}, 6, 6
},
/* tests ill-formed UTF-7: 12 bits, not enough for a byte pair */
{
"+T2-+T2-+T2-hello", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{'h','e','l','l','o',0}, 6, 6
},
/* tests ill-formed UTF-7: 18 bits, not a multiple of 16 and the last bit is a 1 */
{
"+T2B-+T2B-+T2B-hello", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, 9, 9
},
/* tests ill-formed UTF-7: 24 bits, a multiple of 8 but not a multiple of 16 */
{
"+T2BZ-+T2BZ-+T2BZ-hello", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60,0x4F60,0x4F60,'h','e','l','l','o',0}, 9, 9
},
/* tests UTF-7 followed by characters that should be encoded but aren't */
{
"+T2BZ-\x82\xFE", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60,0x0082,0x00FE,0}, 4, 4
},
/* tests srclen > strlen(src) */
{
"a\0b", 4, output, sizeof(output) / sizeof(WCHAR) - 1,
{'a',0,'b',0}, 4, 4
},
/* tests srclen < strlen(src) outside of a UTF-7 sequence */
{
"hello", 2, output, sizeof(output) / sizeof(WCHAR) - 1,
{'h','e'}, 2, 2
},
/* tests srclen < strlen(src) inside of a UTF-7 sequence */
{
"+T2BZfQ-", 4, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60}, 1, 1
},
/* tests srclen < strlen(src) right at the beginning of a UTF-7 sequence */
{
"hi+T2A-", 3, output, sizeof(output) / sizeof(WCHAR) - 1,
{'h','i'}, 2, 2
},
/* tests srclen < strlen(src) right at the end of a UTF-7 sequence */
{
"+T2A-hi", 5, output, sizeof(output) / sizeof(WCHAR) - 1,
{0x4F60}, 1, 1
},
/* tests srclen < strlen(src) at the beginning of an escaped + sign */
{
"hi+-", 3, output, sizeof(output) / sizeof(WCHAR) - 1,
{'h','i'}, 2, 2
},
/* tests srclen < strlen(src) at the end of an escaped + sign */
{
"+-hi", 2, output, sizeof(output) / sizeof(WCHAR) - 1,
{'+'}, 1, 1
},
/* tests len=0 but no error */
{
"+", 1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0}, 0, 0
},
/* tests a single null char */
{
"", -1, output, sizeof(output) / sizeof(WCHAR) - 1,
{0}, 1, 1
},
/* tests a buffer that runs out while not decoding a UTF-7 sequence */
{
"hello", -1, output, 2,
{'h','e'}, 2, 0
},
/* tests a buffer that runs out in the middle of decoding a UTF-7 sequence */
{
"+T2BZfQ-", -1, output, 1,
{0x4F60}, 1, 0
}
};
/* test which one-byte characters remove stray + signs */
for (i = 0; i < 256; i++)
{
sprintf(input, "+%c+AAA", i);
memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
output[sizeof(output) / sizeof(WCHAR) - 1] = 0;
len = MultiByteToWideChar(CP_UTF7, 0, input, 7, output, sizeof(output) / sizeof(WCHAR) - 1);
if (i == '-')
{
/* removes the - sign */
expected_len = 3;
expected[0] = 0x002B;
expected[1] = 0;
expected[2] = 0;
}
else if (i <= 0x7F && base64_decoding_table[i] != -1)
{
/* absorbs the character into the base64 sequence */
expected_len = 2;
expected[0] = (base64_decoding_table[i] << 10) | 0x03E0;
expected[1] = 0;
}
else
{
/* removes the + sign */
expected_len = 3;
expected[0] = i;
expected[1] = 0;
expected[2] = 0;
}
expected[expected_len] = 0x2323;
ok(len == expected_len, "i=0x%02x: expected len=%i, got len=%i\n", i, expected_len, len);
ok(memcmp(output, expected, (expected_len + 1) * sizeof(WCHAR)) == 0,
"i=0x%02x: expected output=%s, got output=%s\n",
i, wine_dbgstr_wn(expected, expected_len + 1), wine_dbgstr_wn(output, expected_len + 1));
}
/* test which one-byte characters terminate a sequence
* also test whether the unfinished byte pair is discarded or not */
for (i = 0; i < 256; i++)
{
sprintf(input, "+B%c+AAA", i);
memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
output[sizeof(output) / sizeof(WCHAR) - 1] = 0;
len = MultiByteToWideChar(CP_UTF7, 0, input, 8, output, sizeof(output) / sizeof(WCHAR) - 1);
if (i == '-')
{
/* explicitly terminates */
expected_len = 2;
expected[0] = 0;
expected[1] = 0;
}
else if (i <= 0x7F)
{
if (base64_decoding_table[i] != -1)
{
/* absorbs the character into the base64 sequence */
expected_len = 3;
expected[0] = 0x0400 | (base64_decoding_table[i] << 4) | 0x000F;
expected[1] = 0x8000;
expected[2] = 0;
}
else
{
/* implicitly terminates and discards the unfinished byte pair */
expected_len = 3;
expected[0] = i;
expected[1] = 0;
expected[2] = 0;
}
}
else
{
/* implicitly terminates but does not the discard unfinished byte pair */
expected_len = 3;
expected[0] = i;
expected[1] = 0x0400;
expected[2] = 0;
}
expected[expected_len] = 0x2323;
ok(len == expected_len, "i=0x%02x: expected len=%i, got len=%i\n", i, expected_len, len);
ok(memcmp(output, expected, (expected_len + 1) * sizeof(WCHAR)) == 0,
"i=0x%02x: expected output=%s, got output=%s\n",
i, wine_dbgstr_wn(expected, expected_len + 1), wine_dbgstr_wn(output, expected_len + 1));
}
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
{
memset(output, 0x23, sizeof(output) - sizeof(WCHAR));
output[sizeof(output) / sizeof(WCHAR) - 1] = 0;
SetLastError(0xdeadbeef);
len = MultiByteToWideChar(CP_UTF7, 0, tests[i].src, tests[i].srclen,
tests[i].dst, tests[i].dstlen);
tests[i].expected_dst[tests[i].chars_written] = 0x2323;
if (!tests[i].len && tests[i].chars_written)
{
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"tests[%i]: expected error=0x%x, got error=0x%x\n",
i, ERROR_INSUFFICIENT_BUFFER, GetLastError());
}
ok(len == tests[i].len, "tests[%i]: expected len=%i, got len=%i\n", i, tests[i].len, len);
if (tests[i].dst)
{
ok(memcmp(tests[i].dst, tests[i].expected_dst, (tests[i].chars_written + 1) * sizeof(WCHAR)) == 0,
"tests[%i]: expected dst=%s, got dst=%s\n",
i, wine_dbgstr_wn(tests[i].expected_dst, tests[i].chars_written + 1),
wine_dbgstr_wn(tests[i].dst, tests[i].chars_written + 1));
}
}
}
static void test_undefined_byte_char(void)
{
static const struct tag_testset {
@ -618,6 +1134,9 @@ START_TEST(codepage)
test_string_conversion(NULL);
test_string_conversion(&bUsedDefaultChar);
test_utf7_encoding();
test_utf7_decoding();
test_undefined_byte_char();
test_threadcp();
}

View file

@ -0,0 +1,77 @@
/*
* Unit test suite for cpu functions
*
* Copyright 2014 Michael Müller
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "winbase.h"
#include "winnls.h"
static BOOL (WINAPI *pGetNumaProcessorNode)(UCHAR, PUCHAR);
static void InitFunctionPointers(void)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32");
pGetNumaProcessorNode = (void *)GetProcAddress(hkernel32, "GetNumaProcessorNode");
}
static void test_GetNumaProcessorNode(void)
{
SYSTEM_INFO si;
UCHAR node;
BOOL ret;
int i;
if (!pGetNumaProcessorNode)
{
win_skip("GetNumaProcessorNode() is missing\n");
return;
}
GetSystemInfo(&si);
for (i = 0; i < 256; i++)
{
ret = pGetNumaProcessorNode(i, &node);
if (i < si.dwNumberOfProcessors)
{
ok(ret, "expected TRUE, got FALSE for processor %d\n", i);
ok(node != 0xFF, "expected node != 0xFF, but got 0xFF\n");
}
else
{
ok(!ret, "expected FALSE, got TRUE for processor %d\n", i);
ok(node == 0xFF, "expected node == 0xFF, but got %x\n", node);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
}
/* crashes on windows */
if (0)
{
ok(!pGetNumaProcessorNode(0, NULL), "expected return value FALSE, got TRUE\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
}
START_TEST(cpu)
{
InitFunctionPointers();
test_GetNumaProcessorNode();
}

View file

@ -46,10 +46,10 @@ static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD
static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*);
static DWORD (WINAPI* pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
static DWORD (WINAPI* pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
/* keep filename and filenameW the same */
static const char filename[] = "testfile.xxx";
static const WCHAR filenameW[] = { 't','e','s','t','f','i','l','e','.','x','x','x',0 };
static const char sillytext[] =
"en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
"1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
@ -85,6 +85,8 @@ static void InitFunctionPointers(void)
pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
}
static void test__hread( void )
@ -2562,7 +2564,7 @@ static void test_FindNextFileA(void)
ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
}
static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
static void test_FindFirstFileExA(FINDEX_INFO_LEVELS level, FINDEX_SEARCH_OPS search_ops, DWORD flags)
{
WIN32_FIND_DATAA search_results;
HANDLE handle;
@ -2574,27 +2576,45 @@ static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
return;
}
trace("Running FindFirstFileExA tests with level=%d, search_ops=%d, flags=%u\n",
level, search_ops, flags);
CreateDirectoryA("test-dir", NULL);
_lclose(_lcreat("test-dir\\file1", 0));
_lclose(_lcreat("test-dir\\file2", 0));
CreateDirectoryA("test-dir\\dir1", NULL);
SetLastError(0xdeadbeef);
handle = pFindFirstFileExA("test-dir\\*", FindExInfoStandard, &search_results, search_ops, NULL, 0);
handle = pFindFirstFileExA("test-dir\\*", level, &search_results, search_ops, NULL, flags);
if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("FindFirstFileExA is not implemented\n");
goto cleanup;
}
ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
if ((flags & FIND_FIRST_EX_LARGE_FETCH) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
{
win_skip("FindFirstFileExA flag FIND_FIRST_EX_LARGE_FETCH not supported, skipping test\n");
goto cleanup;
}
if ((level == FindExInfoBasic) && handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
{
win_skip("FindFirstFileExA level FindExInfoBasic not supported, skipping test\n");
goto cleanup;
}
#define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
#define CHECK_LEVEL(fn) (level != FindExInfoBasic || !(fn)[0])
ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
ok(FindNextFileA(handle, &search_results), "Fetching second file failed\n");
ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
ok(FindNextFileA(handle, &search_results), "Fetching third file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
SetLastError(0xdeadbeef);
ret = FindNextFileA(handle, &search_results);
@ -2603,22 +2623,43 @@ static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
skip("File system supports directory filtering\n");
/* Results from the previous call are not cleared */
ok(strcmp(search_results.cFileName, "dir1") == 0, "Third entry should be 'dir1' is %s\n", search_results.cFileName);
FindClose( handle );
goto cleanup;
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
}
else
{
ok(ret, "Fetching fourth file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
ok(CHECK_LEVEL(search_results.cAlternateFileName), "FindFirstFile unexpectedly returned an alternate filename\n");
ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
}
ok(ret, "Fetching fourth file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
#undef CHECK_NAME
ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
#undef CHECK_LEVEL
FindClose( handle );
/* Most Windows systems seem to ignore the FIND_FIRST_EX_CASE_SENSITIVE flag. Unofficial documentation
* suggests that there are registry keys and that it might depend on the used filesystem. */
SetLastError(0xdeadbeef);
handle = pFindFirstFileExA("TEST-DIR\\*", level, &search_results, search_ops, NULL, flags);
if (flags & FIND_FIRST_EX_CASE_SENSITIVE)
{
ok(handle != INVALID_HANDLE_VALUE || GetLastError() == ERROR_PATH_NOT_FOUND,
"Unexpected error %x, expected valid handle or ERROR_PATH_NOT_FOUND\n", GetLastError());
trace("FindFirstFileExA flag FIND_FIRST_EX_CASE_SENSITIVE is %signored\n",
(handle == INVALID_HANDLE_VALUE) ? "not " : "");
}
else
ok(handle != INVALID_HANDLE_VALUE, "Unexpected error %x, expected valid handle\n", GetLastError());
if (handle != INVALID_HANDLE_VALUE)
FindClose( handle );
cleanup:
DeleteFileA("test-dir\\file1");
DeleteFileA("test-dir\\file2");
@ -4145,6 +4186,203 @@ todo_wine
}
}
static void test_GetFinalPathNameByHandleA(void)
{
static char prefix[] = "GetFinalPathNameByHandleA";
static char dos_prefix[] = "\\\\?\\";
char temp_path[MAX_PATH], test_path[MAX_PATH];
char long_path[MAX_PATH], result_path[MAX_PATH];
char dos_path[sizeof(dos_prefix) + MAX_PATH];
HANDLE hFile;
DWORD count;
UINT ret;
if (!pGetFinalPathNameByHandleA)
{
win_skip("GetFinalPathNameByHandleA is missing\n");
return;
}
/* Test calling with INVALID_HANDLE_VALUE */
SetLastError(0xdeadbeaf);
count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == 0, "Expected length 0, got %d\n", count);
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %x\n", GetLastError());
count = GetTempPathA(MAX_PATH, temp_path);
ok(count, "Failed to get temp path, error %x\n", GetLastError());
if (!count) return;
ret = GetTempFileNameA(temp_path, prefix, 0, test_path);
ok(ret != 0, "GetTempFileNameA error %x\n", GetLastError());
if (!ret) return;
ret = GetLongPathNameA(test_path, long_path, MAX_PATH);
ok(ret != 0, "GetLongPathNameA error %x\n", GetLastError());
if (!ret) return;
hFile = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %x\n", GetLastError());
if (hFile == INVALID_HANDLE_VALUE) return;
dos_path[0] = 0;
strcat(dos_path, dos_prefix);
strcat(dos_path, long_path);
/* Test VOLUME_NAME_DOS with sufficient buffer size */
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleA(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
if (count && count <= MAX_PATH)
ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path);
/* Test VOLUME_NAME_DOS with insufficient buffer size */
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
ok(result_path[0] == 0x11, "Result path was modified\n");
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
ok(result_path[0] == 0x11, "Result path was modified\n");
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
ok(result_path[0] == 0x11, "Result path was modified\n");
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
ok(result_path[0] != 0x11, "Result path was not modified\n");
ok(result_path[strlen(dos_path)+1] == 0x11, "Buffer overflow\n");
CloseHandle(hFile);
}
static void test_GetFinalPathNameByHandleW(void)
{
static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h','N','a','m','e','B','y','H','a','n','d','l','e','W','\0'};
static WCHAR dos_prefix[] = {'\\','\\','?','\\','\0'};
WCHAR temp_path[MAX_PATH], test_path[MAX_PATH];
WCHAR long_path[MAX_PATH], result_path[MAX_PATH];
WCHAR dos_path[MAX_PATH + sizeof(dos_prefix)];
WCHAR drive_part[MAX_PATH];
WCHAR *file_part;
WCHAR volume_path[MAX_PATH+50];
WCHAR nt_path[2*MAX_PATH];
HANDLE hFile;
DWORD count;
UINT ret;
if (!pGetFinalPathNameByHandleW)
{
win_skip("GetFinalPathNameByHandleW is missing\n");
return;
}
/* Test calling with INVALID_HANDLE_VALUE */
SetLastError(0xdeadbeaf);
count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == 0, "Expected length 0, got %d\n", count);
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
count = GetTempPathW(MAX_PATH, temp_path);
ok(count, "Failed to get temp path, error %d\n", GetLastError());
if (!count) return;
ret = GetTempFileNameW(temp_path, prefix, 0, test_path);
ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
if (!ret) return;
ret = GetLongPathNameW(test_path, long_path, MAX_PATH);
ok(ret != 0, "GetLongPathNameW error %d\n", GetLastError());
if (!ret) return;
hFile = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileW error %d\n", GetLastError());
if (hFile == INVALID_HANDLE_VALUE) return;
dos_path[0] = 0;
lstrcatW(dos_path, dos_prefix);
lstrcatW(dos_path, long_path);
/* Test VOLUME_NAME_DOS with sufficient buffer size */
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count);
if (count && count <= MAX_PATH)
ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path));
/* Test VOLUME_NAME_DOS with insufficient buffer size */
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count);
ok(result_path[0] == 0x1111, "Result path was modified\n");
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count);
ok(result_path[0] == 0x1111, "Result path was modified\n");
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count);
ok(result_path[0] != 0x1111, "Result path was not modified\n");
ok(result_path[lstrlenW(dos_path)+1] == 0x1111, "Buffer overflow\n");
if (!GetVolumePathNameW(long_path, drive_part, MAX_PATH))
{
ok(0, "Failed to get drive part, error: %d\n", GetLastError());
CloseHandle(hFile);
return;
}
if (!GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR)))
ok(0, "GetVolumeNameForVolumeMountPointW failed, error: %d\n", GetLastError());
else
{
/* Test for VOLUME_NAME_GUID */
lstrcatW(volume_path, long_path + lstrlenW(drive_part));
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID);
ok(count == lstrlenW(volume_path), "Expected length %d, got %d\n", lstrlenW(volume_path), count);
if (count && count <= MAX_PATH)
ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path));
}
/* Test for VOLUME_NAME_NONE */
file_part = long_path + lstrlenW(drive_part) - 1;
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE);
ok(count == lstrlenW(file_part), "Expected length %d, got %d\n", lstrlenW(file_part), count);
if (count && count <= MAX_PATH)
ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(file_part), wine_dbgstr_w(result_path));
drive_part[lstrlenW(drive_part)-1] = 0;
if (!QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR)))
ok(0, "QueryDosDeviceW failed, error: %d\n", GetLastError());
else
{
/* Test for VOLUME_NAME_NT */
lstrcatW(nt_path, file_part);
memset(result_path, 0x11, sizeof(result_path));
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
ok(count == lstrlenW(nt_path), "Expected length %d, got %d\n", lstrlenW(nt_path), count);
if (count && count <= MAX_PATH)
ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n",
wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path));
}
CloseHandle(hFile);
}
START_TEST(file)
{
InitFunctionPointers();
@ -4171,9 +4409,15 @@ START_TEST(file)
test_MoveFileW();
test_FindFirstFileA();
test_FindNextFileA();
test_FindFirstFileExA(0);
test_FindFirstFileExA(FindExInfoStandard, 0, 0);
test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_CASE_SENSITIVE);
test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_LARGE_FETCH);
test_FindFirstFileExA(FindExInfoBasic, 0, 0);
/* FindExLimitToDirectories is ignored if the file system doesn't support directory filtering */
test_FindFirstFileExA(FindExSearchLimitToDirectories);
test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, 0);
test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_CASE_SENSITIVE);
test_FindFirstFileExA(FindExInfoStandard, FindExSearchLimitToDirectories, FIND_FIRST_EX_LARGE_FETCH);
test_FindFirstFileExA(FindExInfoBasic, FindExSearchLimitToDirectories, 0);
test_LockFile();
test_file_sharing();
test_offset_in_overlapped_structure();
@ -4191,4 +4435,6 @@ START_TEST(file)
test_SetFileValidData();
test_WriteFileGather();
test_file_access();
test_GetFinalPathNameByHandleA();
test_GetFinalPathNameByHandleW();
}

View file

@ -1552,6 +1552,11 @@ static void test_message_from_hmodule(void)
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
/* Test HRESULT. It's not documented but in practice _com_error::ErrorMessage relies on this. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 0x80070005 /* E_ACCESSDENIED */,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
/* Test a message string with an insertion without passing any variadic arguments. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);

View file

@ -78,7 +78,7 @@ static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
static IMAGE_DOS_HEADER dos_header;
static IMAGE_NT_HEADERS nt_header =
static const IMAGE_NT_HEADERS nt_header_template =
{
IMAGE_NT_SIGNATURE, /* Signature */
{
@ -123,8 +123,8 @@ static IMAGE_NT_HEADERS nt_header =
4, /* MajorSubsystemVersion */
0, /* MinorSubsystemVersion */
0, /* Win32VersionValue */
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */
sizeof(dos_header) + sizeof(nt_header), /* SizeOfHeaders */
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000, /* SizeOfImage */
sizeof(dos_header) + sizeof(nt_header_template), /* SizeOfHeaders */
0, /* CheckSum */
IMAGE_SUBSYSTEM_WINDOWS_CUI, /* Subsystem */
0, /* DllCharacteristics */
@ -266,14 +266,14 @@ static void test_Loader(void)
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
{ ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
{ ERROR_SUCCESS }
},
{ sizeof(dos_header),
@ -284,25 +284,25 @@ static void test_Loader(void)
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
{ ERROR_SUCCESS, ERROR_INVALID_ADDRESS } /* vista is more strict */
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
{ ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER),
{ ERROR_SUCCESS }
},
{ sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
0x200,
{ ERROR_SUCCESS }
},
@ -363,7 +363,7 @@ static void test_Loader(void)
/* the following data mimics the PE image which upack creates */
{ 0x10,
1, 0x148, 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header_template) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
0x200,
{ ERROR_SUCCESS }
},
@ -384,7 +384,8 @@ static void test_Loader(void)
SIZE_T size;
BOOL ret;
NTSTATUS status;
WORD orig_machine = nt_header.FileHeader.Machine;
WORD orig_machine = nt_header_template.FileHeader.Machine;
IMAGE_NT_HEADERS nt_header;
/* prevent displaying of the "Unable to load this DLL" message box */
SetErrorMode(SEM_FAILCRITICALERRORS);
@ -395,6 +396,7 @@ static void test_Loader(void)
{
GetTempFileNameA(temp_path, "ldr", 0, dll_name);
nt_header = nt_header_template;
nt_header.FileHeader.NumberOfSections = td[i].number_of_sections;
nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header;
@ -589,13 +591,14 @@ todo_wine
ok(ret, "DeleteFile error %d\n", GetLastError());
}
nt_header = nt_header_template;
nt_header.FileHeader.NumberOfSections = 1;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
nt_header.OptionalHeader.SectionAlignment = page_size;
nt_header.OptionalHeader.FileAlignment = page_size;
nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
nt_header.OptionalHeader.SizeOfImage = nt_header.OptionalHeader.SizeOfImage + page_size;
nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size;
status = map_image_section( &nt_header );
ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
@ -1032,8 +1035,6 @@ static void test_section_access(void)
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE },
{ IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY, PAGE_EXECUTE_READWRITE }
};
static const char filler[0x1000];
static const char section_data[0x10] = "section data";
char buf[256];
int i;
DWORD dummy, file_align;
@ -1054,6 +1055,8 @@ static void test_section_access(void)
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
{
IMAGE_NT_HEADERS nt_header;
GetTempFileNameA(temp_path, "ldr", 0, dll_name);
/*trace("creating %s\n", dll_name);*/
@ -1068,6 +1071,7 @@ static void test_section_access(void)
ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
nt_header = nt_header_template;
nt_header.FileHeader.NumberOfSections = 1;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
@ -1235,11 +1239,13 @@ static void test_import_resolution(void)
for (test = 0; test < 3; test++)
{
#define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data))
nt = nt_header;
nt = nt_header_template;
nt.FileHeader.NumberOfSections = 1;
nt.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
nt.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_RELOCS_STRIPPED;
if (test != 2) nt.FileHeader.Characteristics |= IMAGE_FILE_DLL;
nt.OptionalHeader.SectionAlignment = page_size;
nt.OptionalHeader.FileAlignment = 0x200;
nt.OptionalHeader.ImageBase = 0x12340000;
nt.OptionalHeader.SizeOfImage = 2 * page_size;
nt.OptionalHeader.SizeOfHeaders = nt.OptionalHeader.FileAlignment;
@ -2015,6 +2021,7 @@ static void test_ExitProcess(void)
void *addr;
LARGE_INTEGER offset;
SIZE_T size;
IMAGE_NT_HEADERS nt_header;
#if !defined(__i386__) && !defined(__x86_64__)
skip("x86 specific ExitProcess test\n");
@ -2055,6 +2062,7 @@ static void test_ExitProcess(void)
ret = WriteFile(file, &dos_header, sizeof(dos_header), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
nt_header = nt_header_template;
nt_header.FileHeader.NumberOfSections = 1;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
@ -2510,6 +2518,8 @@ static void test_ResolveDelayLoadedAPI(void)
DWORD dummy, file_size, i;
WORD hint = 0;
BOOL ret;
IMAGE_NT_HEADERS nt_header;
static const struct test_data
{
BOOL func;
@ -2536,7 +2546,7 @@ static void test_ResolveDelayLoadedAPI(void)
if (!pResolveDelayLoadedAPI)
{
todo_wine win_skip("ResolveDelayLoadedAPI is not available\n");
win_skip("ResolveDelayLoadedAPI is not available\n");
return;
}
@ -2569,6 +2579,7 @@ static void test_ResolveDelayLoadedAPI(void)
ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
nt_header = nt_header_template;
nt_header.FileHeader.NumberOfSections = 2;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);

View file

@ -42,7 +42,9 @@
static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
static const WCHAR localeW[] = {'e','n','-','U','S',0};
static const WCHAR fooW[] = {'f','o','o',0};
static const WCHAR emptyW[] = {0};
static inline unsigned int strlenW( const WCHAR *str )
{
@ -75,6 +77,8 @@ static inline BOOL isdigitW( WCHAR wc )
static HMODULE hKernel32;
static WORD enumCount;
static INT (WINAPI *pGetTimeFormatEx)(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, INT);
static INT (WINAPI *pGetDateFormatEx)(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, INT, LPCWSTR);
static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROCA, DWORD, LONG_PTR);
static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROCA, LGRPID, DWORD, LONG_PTR);
static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROCA, DWORD, LONG_PTR);
@ -102,6 +106,8 @@ static void InitFunctionPointers(void)
hKernel32 = GetModuleHandleA("kernel32");
#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
X(GetTimeFormatEx);
X(GetDateFormatEx);
X(EnumSystemLanguageGroupsA);
X(EnumLanguageGroupLocalesA);
X(LocaleNameToLCID);
@ -615,6 +621,202 @@ static void test_GetTimeFormatA(void)
EXPECT_LENA; EXPECT_EQA;
}
static void test_GetTimeFormatEx(void)
{
int ret;
SYSTEMTIME curtime;
WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
if (!pGetTimeFormatEx)
{
win_skip("GetTimeFormatEx not supported\n");
return;
}
memset(&curtime, 2, sizeof(SYSTEMTIME));
STRINGSW("tt HH':'mm'@'ss", ""); /* Invalid time */
SetLastError(0xdeadbeef);
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
curtime.wHour = 8;
curtime.wMinute = 56;
curtime.wSecond = 13;
curtime.wMilliseconds = 22;
STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
SetLastError(0xdeadbeef);
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
SetLastError(0xdeadbeef);
ret = pGetTimeFormatEx(localeW, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
STRINGSW("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
SetLastError(0xdeadbeef);
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
STRINGSW("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW;
STRINGSW("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
ret = pGetTimeFormatEx(localeW, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
ret = pGetTimeFormatEx(localeW, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
ret = pGetTimeFormatEx(localeW, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("s1s2s3", ""); /* Duplicate tokens */
ret = pGetTimeFormatEx(localeW, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
ok(ret == strlenW(buffer)+1, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("t/tt", "A/AM"); /* AM time marker */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 13;
STRINGSW("t/tt", "P/PM"); /* PM time marker */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
ret = pGetTimeFormatEx(localeW, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 14; /* change this to 14 or 2pm */
curtime.wMinute = 5;
curtime.wSecond = 3;
STRINGSW("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 0;
STRINGSW("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* try to convert formatting strings with more than two letters
* "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
* NOTE: We expect any letter for which there is an upper case value
* we should see a replacement. For letters that DO NOT have
* upper case values we should see NO REPLACEMENT.
*/
curtime.wHour = 8;
curtime.wMinute = 56;
curtime.wSecond = 13;
curtime.wMilliseconds = 22;
STRINGSW("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
"8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("h", "text"); /* Don't write to buffer if len is 0 */
lstrcpyW(buffer, Expected);
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, 0);
ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
EXPECT_EQW;
STRINGSW("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
"8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'''", "'"); /* invalid quoted string */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* test that msdn suggested single quotation usage works as expected */
STRINGSW("''''", "'"); /* single quote mark */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("''HHHHHH", "08"); /* Normal use */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
/* and test for normal use of the single quotation mark */
STRINGSW("'''HHHHHH'", "'HHHHHH"); /* Normal use */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'''HHHHHH", "'HHHHHH"); /* Odd use */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
ret = pGetTimeFormatEx(localeW, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wHour = 25;
STRINGSW("'123'tt", ""); /* Invalid time */
SetLastError(0xdeadbeef);
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
curtime.wHour = 12;
curtime.wMonth = 60; /* Invalid */
STRINGSW("h:m:s", "12:56:13"); /* Invalid date */
ret = pGetTimeFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer));
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
}
static void test_GetDateFormatA(void)
{
int ret;
@ -782,6 +984,102 @@ static void test_GetDateFormatA(void)
"Expected '%s', got '%s'\n", Expected, buffer);
}
static void test_GetDateFormatEx(void)
{
int ret;
SYSTEMTIME curtime;
WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
if (!pGetDateFormatEx)
{
win_skip("GetDateFormatEx not supported\n");
return;
}
STRINGSW("",""); /* If flags are set, then format must be NULL */
SetLastError(0xdeadbeef);
ret = pGetDateFormatEx(localeW, DATE_LONGDATE, NULL,
input, buffer, COUNTOF(buffer), NULL);
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
EXPECT_EQW;
STRINGSW("",""); /* NULL buffer, len > 0 */
SetLastError(0xdeadbeef);
ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, COUNTOF(buffer), NULL);
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
STRINGSW("",""); /* NULL buffer, len == 0 */
ret = pGetDateFormatEx(localeW, 0, NULL, input, NULL, 0, NULL);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
STRINGSW("",""); /* Invalid flag combination */
SetLastError(0xdeadbeef);
ret = pGetDateFormatEx(localeW, DATE_LONGDATE|DATE_SHORTDATE, NULL,
input, NULL, 0, NULL);
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
EXPECT_EQW;
curtime.wYear = 2002;
curtime.wMonth = 10;
curtime.wDay = 23;
curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
curtime.wHour = 65432; /* Invalid */
curtime.wMinute = 34512; /* Invalid */
curtime.wSecond = 65535; /* Invalid */
curtime.wMilliseconds = 12345;
STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wYear = 2002;
curtime.wMonth = 10;
curtime.wDay = 23;
curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
curtime.wHour = 65432; /* Invalid */
curtime.wMinute = 34512; /* Invalid */
curtime.wSecond = 65535; /* Invalid */
curtime.wMilliseconds = 12345;
STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002");
ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), emptyW); /* Use reserved arg */
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Limit tests */
curtime.wYear = 1601;
curtime.wMonth = 1;
curtime.wDay = 1;
curtime.wDayOfWeek = 0; /* Irrelevant */
curtime.wHour = 0;
curtime.wMinute = 0;
curtime.wSecond = 0;
curtime.wMilliseconds = 0;
STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
SetLastError(0xdeadbeef);
ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_LENW; EXPECT_EQW;
curtime.wYear = 1600;
curtime.wMonth = 12;
curtime.wDay = 31;
curtime.wDayOfWeek = 0; /* Irrelevant */
curtime.wHour = 23;
curtime.wMinute = 59;
curtime.wSecond = 59;
curtime.wMilliseconds = 999;
STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
SetLastError(0xdeadbeef);
ret = pGetDateFormatEx(localeW, 0, &curtime, input, buffer, COUNTOF(buffer), NULL);
ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
static void test_GetDateFormatW(void)
{
int ret;
@ -1464,13 +1762,13 @@ static void test_CompareStringA(void)
todo_wine ok(ret != CSTR_EQUAL, "\\2 vs \\1 expected unequal\n");
ret = CompareStringA(lcid, NORM_IGNORECASE | LOCALE_USE_CP_ACP, "#", -1, ".", -1);
todo_wine ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "\"#\" vs \".\" expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
ret = lstrcmpiA("#", ".");
todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
@ -3284,6 +3582,7 @@ static void test_GetStringTypeW(void)
WORD types[20];
WCHAR ch;
BOOL res;
int i;
memset(types,0,sizeof(types));
@ -3341,6 +3640,15 @@ static void test_GetStringTypeW(void)
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 );
for (i = -1; i < 3; i++)
{
SetLastError(0xdeadbeef);
memset(types, 0, sizeof(types));
res = GetStringTypeW(CT_CTYPE1, NULL, i, types);
ok(!res, "GetStringTypeW unexpectedly succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error, got %u\n", GetLastError());
}
/* surrogate pairs */
ch = 0xd800;
memset(types, 0, sizeof(types));
@ -3974,7 +4282,7 @@ static void test_EnumSystemGeoID(void)
ret = pEnumSystemGeoID(GEOCLASS_NATION, 0, test_geoid_enumproc);
ok(ret, "got %d\n", ret);
/* only first level is enumerated, not the whole hierarchy */
/* only the first level is enumerated, not the whole hierarchy */
geoidenum_count = 0;
ret = pEnumSystemGeoID(GEOCLASS_NATION, 39070, test_geoid_enumproc2);
if (ret == 0)
@ -4006,7 +4314,9 @@ START_TEST(locale)
test_GetLocaleInfoW();
test_GetLocaleInfoEx();
test_GetTimeFormatA();
test_GetTimeFormatEx();
test_GetDateFormatA();
test_GetDateFormatEx();
test_GetDateFormatW();
test_GetCurrencyFormatA(); /* Also tests the W version */
test_GetNumberFormatA(); /* Also tests the W version */

View file

@ -20,12 +20,15 @@
#include "wine/test.h"
#include <windows.h>
#include <psapi.h>
static DWORD (WINAPI *pGetDllDirectoryA)(DWORD,LPSTR);
static DWORD (WINAPI *pGetDllDirectoryW)(DWORD,LPWSTR);
static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR);
static BOOL (WINAPI *pGetModuleHandleExA)(DWORD,LPCSTR,HMODULE*);
static BOOL (WINAPI *pGetModuleHandleExW)(DWORD,LPCWSTR,HMODULE*);
static BOOL (WINAPI *pK32GetModuleInformation)(HANDLE process, HMODULE module,
MODULEINFO *modinfo, DWORD cb);
static BOOL is_unicode_enabled = TRUE;
@ -514,7 +517,20 @@ static void init_pointers(void)
MAKEFUNC(SetDllDirectoryA);
MAKEFUNC(GetModuleHandleExA);
MAKEFUNC(GetModuleHandleExW);
MAKEFUNC(K32GetModuleInformation);
#undef MAKEFUNC
/* not all Windows versions export this in kernel32 */
if (!pK32GetModuleInformation)
{
HMODULE hPsapi = LoadLibraryA("psapi.dll");
if (hPsapi)
{
pK32GetModuleInformation = (void *)GetProcAddress(hPsapi, "GetModuleInformation");
if (!pK32GetModuleInformation) FreeLibrary(hPsapi);
}
}
}
static void testGetModuleHandleEx(void)
@ -696,6 +712,33 @@ static void testGetModuleHandleEx(void)
FreeLibrary( mod_kernel32 );
}
static void testK32GetModuleInformation(void)
{
MODULEINFO info;
HMODULE mod;
BOOL ret;
if (!pK32GetModuleInformation)
{
win_skip("K32GetModuleInformation not available\n");
return;
}
mod = GetModuleHandleA(NULL);
memset(&info, 0xAA, sizeof(info));
ret = pK32GetModuleInformation(GetCurrentProcess(), mod, &info, sizeof(info));
ok(ret, "K32GetModuleInformation failed for main module\n");
ok(info.lpBaseOfDll == mod, "Wrong info.lpBaseOfDll = %p, expected %p\n", info.lpBaseOfDll, mod);
ok(info.EntryPoint != NULL, "Expected nonzero entrypoint\n");
mod = GetModuleHandleA("kernel32.dll");
memset(&info, 0xAA, sizeof(info));
ret = pK32GetModuleInformation(GetCurrentProcess(), mod, &info, sizeof(info));
ok(ret, "K32GetModuleInformation failed for kernel32 module\n");
ok(info.lpBaseOfDll == mod, "Wrong info.lpBaseOfDll = %p, expected %p\n", info.lpBaseOfDll, mod);
ok(info.EntryPoint != NULL, "Expected nonzero entrypoint\n");
}
START_TEST(module)
{
WCHAR filenameW[MAX_PATH];
@ -724,4 +767,5 @@ START_TEST(module)
testGetProcAddress_Wrong();
testLoadLibraryEx();
testGetModuleHandleEx();
testK32GetModuleInformation();
}

View file

@ -1002,8 +1002,10 @@ static void test_GetTempPath(void)
{
char save_TMP[MAX_PATH];
char windir[MAX_PATH];
char origdir[MAX_PATH];
char buf[MAX_PATH];
GetCurrentDirectoryA(sizeof(origdir), origdir);
if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
/* test default configuration */
@ -1048,6 +1050,7 @@ static void test_GetTempPath(void)
test_GetTempPathW(windir);
SetEnvironmentVariableA("TMP", save_TMP);
SetCurrentDirectoryA(origdir);
}
static void test_GetLongPathNameA(void)
@ -1644,10 +1647,11 @@ static void test_SearchPathA(void)
static const CHAR testdeprelA[] = "./testdep.dll";
static const CHAR kernel32A[] = "kernel32.dll";
static const CHAR fileA[] = "";
CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH];
CHAR *ptrA = NULL;
CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH], path3A[MAX_PATH], curdirA[MAX_PATH];
CHAR tmpdirA[MAX_PATH], *ptrA = NULL;
ULONG_PTR cookie;
HANDLE handle;
BOOL bret;
DWORD ret;
if (!pSearchPathA)
@ -1721,6 +1725,28 @@ static void test_SearchPathA(void)
ret = pDeactivateActCtx(0, cookie);
ok(ret, "failed to deactivate context, %u\n", GetLastError());
pReleaseActCtx(handle);
/* test the search path priority of the working directory */
GetTempPathA(sizeof(tmpdirA), tmpdirA);
ret = GetCurrentDirectoryA(MAX_PATH, curdirA);
ok(ret, "failed to obtain working directory.\n");
sprintf(pathA, "%s\\%s", tmpdirA, kernel32A);
ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL);
ok(ret && ret == strlen(path2A), "got %d\n", ret);
bret = CopyFileA(path2A, pathA, FALSE);
ok(bret != 0, "failed to copy test executable to temp directory, %u\n", GetLastError());
sprintf(path3A, "%s%s%s", curdirA, curdirA[strlen(curdirA)-1] != '\\' ? "\\" : "", kernel32A);
bret = CopyFileA(path2A, path3A, FALSE);
ok(bret != 0, "failed to copy test executable to launch directory, %u\n", GetLastError());
bret = SetCurrentDirectoryA(tmpdirA);
ok(bret, "failed to change working directory\n");
ret = pSearchPathA(NULL, kernel32A, ".exe", sizeof(buffA), buffA, NULL);
ok(ret && ret == strlen(buffA), "got %d\n", ret);
ok(strcmp(buffA, path3A) == 0, "expected %s, got %s\n", path3A, buffA);
bret = SetCurrentDirectoryA(curdirA);
ok(bret, "failed to reset working directory\n");
DeleteFileA(path3A);
DeleteFileA(pathA);
}
static void test_SearchPathW(void)
@ -1828,6 +1854,7 @@ static void test_GetFullPathNameA(void)
char output[MAX_PATH], *filepart;
DWORD ret;
int i;
UINT acp;
const struct
{
@ -1864,6 +1891,27 @@ static void test_GetFullPathNameA(void)
"[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
i, GetLastError());
}
acp = GetACP();
if (acp != 932)
skip("Skipping DBCS(Japanese) GetFullPathNameA test in this codepage (%d)\n", acp);
else {
const struct dbcs_case {
const char *input;
const char *expected;
} testset[] = {
{ "c:\\a\\\x95\x5c\x97\xa0.txt", "\x95\x5c\x97\xa0.txt" },
{ "c:\\\x83\x8f\x83\x43\x83\x93\\wine.c", "wine.c" },
{ "c:\\demo\\\x97\xa0\x95\x5c", "\x97\xa0\x95\x5c" }
};
for (i = 0; i < sizeof(testset)/sizeof(testset[0]); i++) {
ret = GetFullPathNameA(testset[i].input, sizeof(output),
output, &filepart);
ok(ret, "[%d] GetFullPathName error %u\n", i, GetLastError());
ok(!lstrcmpA(filepart, testset[i].expected),
"[%d] expected %s got %s\n", i, testset[i].expected, filepart);
}
}
}
static void test_GetFullPathNameW(void)

File diff suppressed because it is too large Load diff

View file

@ -57,7 +57,7 @@
wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
} while (0)
static HINSTANCE hkernel32;
static HINSTANCE hkernel32, hntdll;
static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
@ -66,6 +66,7 @@ static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
static DWORD (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
/* ############################### */
static char base[MAX_PATH];
@ -201,6 +202,8 @@ static BOOL init(void)
if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
hkernel32 = GetModuleHandleA("kernel32");
hntdll = GetModuleHandleA("ntdll.dll");
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
@ -209,6 +212,7 @@ static BOOL init(void)
pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
return TRUE;
}
@ -277,6 +281,16 @@ static void doChild(const char* file, const char* option)
siA.dwFlags, siA.wShowWindow,
(DWORD_PTR)siA.hStdInput, (DWORD_PTR)siA.hStdOutput, (DWORD_PTR)siA.hStdError);
if (pNtCurrentTeb)
{
RTL_USER_PROCESS_PARAMETERS *params = pNtCurrentTeb()->Peb->ProcessParameters;
/* check the console handles in the TEB */
childPrintf(hFile, "[TEB]\nhStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
(DWORD_PTR)params->hStdInput, (DWORD_PTR)params->hStdOutput,
(DWORD_PTR)params->hStdError);
}
/* since GetStartupInfoW is only implemented in win2k,
* zero out before calling so we can notice the difference
*/
@ -1863,6 +1877,62 @@ static void test_Handles(void)
SetStdHandle( STD_ERROR_HANDLE, handle );
}
static void test_IsWow64Process(void)
{
PROCESS_INFORMATION pi;
STARTUPINFOA si;
DWORD ret;
BOOL is_wow64;
static char cmdline[] = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
static char cmdline_wow64[] = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
if (!pIsWow64Process)
{
skip("IsWow64Process is not available\n");
return;
}
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ret = CreateProcessA(NULL, cmdline_wow64, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret)
{
trace("Created process %s\n", cmdline_wow64);
is_wow64 = FALSE;
ret = pIsWow64Process(pi.hProcess, &is_wow64);
ok(ret, "IsWow64Process failed.\n");
ok(is_wow64, "is_wow64 returned FALSE.\n");
ret = TerminateProcess(pi.hProcess, 0);
ok(ret, "TerminateProcess error\n");
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret)
{
trace("Created process %s\n", cmdline);
is_wow64 = TRUE;
ret = pIsWow64Process(pi.hProcess, &is_wow64);
ok(ret, "IsWow64Process failed.\n");
ok(!is_wow64, "is_wow64 returned TRUE.\n");
ret = TerminateProcess(pi.hProcess, 0);
ok(ret, "TerminateProcess error\n");
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
static void test_SystemInfo(void)
{
SYSTEM_INFO si, nsi;
@ -2063,6 +2133,41 @@ static void test_DuplicateHandle(void)
CloseHandle(out);
}
void test_StartupNoConsole(void)
{
char buffer[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
DWORD code;
if (!pNtCurrentTeb)
{
win_skip( "NtCurrentTeb not supported\n" );
return;
}
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = SW_SHOWNORMAL;
get_file_name(resfile);
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup,
&info), "CreateProcess\n");
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n");
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
okChildInt("StartupInfoA", "hStdInput", (DWORD_PTR)INVALID_HANDLE_VALUE);
okChildInt("StartupInfoA", "hStdOutput", (DWORD_PTR)INVALID_HANDLE_VALUE);
okChildInt("StartupInfoA", "hStdError", (DWORD_PTR)INVALID_HANDLE_VALUE);
okChildInt("TEB", "hStdInput", (DWORD_PTR)0);
okChildInt("TEB", "hStdOutput", (DWORD_PTR)0);
okChildInt("TEB", "hStdError", (DWORD_PTR)0);
release_memory();
assert(DeleteFileA(resfile) != 0);
}
START_TEST(process)
{
BOOL b = init();
@ -2089,9 +2194,11 @@ START_TEST(process)
test_QueryFullProcessImageNameA();
test_QueryFullProcessImageNameW();
test_Handles();
test_IsWow64Process();
test_SystemInfo();
test_RegistryQuota();
test_DuplicateHandle();
test_StartupNoConsole();
/* things that can be tested:
* lookup: check the way program to be executed is searched
* handles: check the handle inheritance stuff (+sec options)

View file

@ -154,9 +154,7 @@ static void test_profile_string(void)
/* works only in unicode, ascii crashes */
ret=GetPrivateProfileStringW(sW, emptyW, emptyW, bufW,
sizeof(bufW)/sizeof(bufW[0]), TESTFILE2W);
todo_wine
ok(ret == 10, "expected 10, got %u\n", ret);
todo_wine
ok(!lstrcmpW(valnokeyW,bufW), "expected %s, got %s\n",
wine_dbgstr_w(valnokeyW), wine_dbgstr_w(bufW) );

View file

@ -39,15 +39,8 @@ static const IMAGE_SECTION_HEADER sh_rodata_1 =
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rodata @ [0x1000-0x4000) */
static const IMAGE_SECTION_HEADER sh_rodata_2 =
{
".rodata", {3*page_size}, page_size, 3*page_size, page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rodata @ [0x1000-0x2000) */
static const IMAGE_SECTION_HEADER sh_rodata_3 =
static const IMAGE_SECTION_HEADER sh_rodata_2 =
{
".rodata", {page_size}, page_size, page_size, page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
@ -60,50 +53,36 @@ static const IMAGE_SECTION_HEADER sh_rsrc_1 =
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x4000-0x5000) */
static const IMAGE_SECTION_HEADER sh_rsrc_2 =
{
".rsrc\0\0", {page_size}, 4*page_size, page_size, 4*page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x2000-0x4000) */
static const IMAGE_SECTION_HEADER sh_rsrc_3 =
static const IMAGE_SECTION_HEADER sh_rsrc_2 =
{
".rsrc\0\0", {2*page_size}, rva_rsrc_start-page_size, 2*page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x2000-0x3000) */
static const IMAGE_SECTION_HEADER sh_rsrc_4 =
static const IMAGE_SECTION_HEADER sh_rsrc_3 =
{
".rsrc\0\0", {page_size}, rva_rsrc_start-page_size, page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x3000-0x6000) */
static const IMAGE_SECTION_HEADER sh_rsrc_5 =
static const IMAGE_SECTION_HEADER sh_rsrc_4 =
{
".rsrc\0\0", {3*page_size}, rva_rsrc_start, 3*page_size, rva_rsrc_start, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x4000-0x7000) */
static const IMAGE_SECTION_HEADER sh_rsrc_6 =
{
".rsrc\0\0", {3*page_size}, 4*page_size, 3*page_size, 4*page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x2000-0x5000) */
static const IMAGE_SECTION_HEADER sh_rsrc_7 =
static const IMAGE_SECTION_HEADER sh_rsrc_5 =
{
".rsrc\0\0", {3*page_size}, 2*page_size, 3*page_size, 2*page_size, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
};
/* rsrc @ [0x3000-0x4000), small SizeOfRawData */
static const IMAGE_SECTION_HEADER sh_rsrc_8 =
static const IMAGE_SECTION_HEADER sh_rsrc_6 =
{
".rsrc\0\0", {page_size}, rva_rsrc_start, 8, rva_rsrc_start, 0, 0, 0, 0,
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
@ -148,29 +127,17 @@ static const struct _sec_variants
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
{{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
{{&sh_rodata_1, &sh_rsrc_4, NULL}, 6*page_size, 1, 0, 1}
},
/* single .rodata section with compatible characteristics, data directory entry points to section end */
/* Vista+ - existing section isn't used, new section is created at the end of file */
/* NT4/2000/2003 - image is broken */
#if 0
{
{{&sh_rodata_2, NULL, NULL}},
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
{{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 1},
{{&sh_rodata_2, &sh_rsrc_6, NULL}, 7*page_size, 1, 0, 1}
},
#endif
/* .rsrc is the last section, data directory entry points to section end */
/* Vista+ - resources are moved to section start (trashing data that could be there), and section is trimmed */
/* NT4/2000/2003 - resources are moved to section start (trashing data that could be there); section isn't trimmed */
{
{{&sh_rodata_3, &sh_rsrc_3, NULL}},
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
{{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 1},
{{&sh_rodata_3, &sh_rsrc_7, NULL}, 5*page_size, 1, 0, 1}
{{&sh_rodata_2, &sh_rsrc_2, NULL}},
{{&sh_rodata_2, &sh_rsrc_3, NULL}, 3*page_size, 1, 0, 0},
{{&sh_rodata_2, &sh_rsrc_3, NULL}, 3*page_size, 1, 0, 0},
{{&sh_rodata_2, &sh_rsrc_3, NULL}, 3*page_size, 1, 0, 1},
{{&sh_rodata_2, &sh_rsrc_5, NULL}, 5*page_size, 1, 0, 1}
},
/* .rsrc is not the last section */
/* section is reused; sections after .rsrc are shifted to give space to rsrc (in-image offset and RVA!) */
@ -179,15 +146,15 @@ static const struct _sec_variants
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 1},
{{&sh_rodata_1, &sh_rsrc_5, &sh_junk_2}, 7*page_size, 1, 0, 1}
{{&sh_rodata_1, &sh_rsrc_4, &sh_junk_2}, 7*page_size, 1, 0, 1}
},
/* .rsrc is the last section, data directory entry points to whole section, file size is not aligned on FileAlign */
{
{{&sh_rodata_1, &sh_rsrc_8, NULL}},
{{&sh_rodata_1, &sh_rsrc_6, NULL}},
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
{{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
{{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
{{&sh_rodata_1, &sh_rsrc_4, NULL}, 6*page_size, 1, 0, 1}
}
};

View file

@ -64,6 +64,7 @@ static void test_signalandwait(void)
HMODULE kernel32;
DWORD r;
HANDLE event[2], semaphore[2], file;
int i;
kernel32 = GetModuleHandleA("kernel32.dll");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
@ -96,9 +97,13 @@ static void test_signalandwait(void)
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is now signalled */
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is now signalled - we repeat this test multiple times
* to ensure that the wineserver handles this situation properly. */
for (i = 0; i < 10000; i++)
{
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
}
/* event[0] is not signalled */
r = WaitForSingleObject(event[0], 0);

View file

@ -12,6 +12,7 @@ extern void func_change(void);
extern void func_codepage(void);
extern void func_comm(void);
extern void func_console(void);
extern void func_cpu(void);
extern void func_debugger(void);
extern void func_directory(void);
extern void func_drive(void);

View file

@ -1625,8 +1625,8 @@ static void test_threadpool(void)
int workcalled = 0;
if (!pCreateThreadpool) {
todo_wine win_skip("thread pool apis not supported.\n");
return;
win_skip("thread pool apis not supported.\n");
return;
}
work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
@ -1638,7 +1638,7 @@ static void test_threadpool(void)
ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
pool = pCreateThreadpool(NULL);
todo_wine ok (pool != NULL, "CreateThreadpool failed\n");
ok (pool != NULL, "CreateThreadpool failed\n");
}
static void test_reserved_tls(void)

View file

@ -22,9 +22,11 @@
#include "wine/test.h"
#include "winbase.h"
#include "winnls.h"
#include "winternl.h"
static BOOL (WINAPI *pTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
static BOOL (WINAPI *pSystemTimeToTzSpecificLocalTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
static BOOL (WINAPI *pGetSystemTimes)(LPFILETIME, LPFILETIME, LPFILETIME);
static int (WINAPI *pGetCalendarInfoA)(LCID,CALID,CALTYPE,LPSTR,int,LPDWORD);
static int (WINAPI *pGetCalendarInfoW)(LCID,CALID,CALTYPE,LPWSTR,int,LPDWORD);
@ -732,12 +734,85 @@ static void test_GetCalendarInfo(void)
ok( ret == ret2, "got %d, expected %d\n", ret, ret2 );
}
static void test_GetSystemTimes(void)
{
FILETIME idletime, kerneltime, usertime;
int i;
ULARGE_INTEGER ul1, ul2, ul3;
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi;
SYSTEM_BASIC_INFORMATION sbi;
ULONG ReturnLength;
double total_usertime = 0.0, total_kerneltime = 0.0, total_idletime = 0.0;
if (!pGetSystemTimes)
{
win_skip("GetSystemTimes not available\n");
return;
}
ok( pGetSystemTimes(NULL, NULL, NULL), "GetSystemTimes failed unexpectedly\n" );
memset( &idletime, 0x11, sizeof(idletime) );
memset( &kerneltime, 0x11, sizeof(kerneltime) );
memset( &usertime, 0x11, sizeof(usertime) );
ok( pGetSystemTimes(&idletime, &kerneltime , &usertime),
"GetSystemTimes failed unexpectedly\n" );
ul1.LowPart = idletime.dwLowDateTime;
ul1.HighPart = idletime.dwHighDateTime;
trace( "IdleTime: %f seconds\n", (double)ul1.QuadPart/10000000.0 );
ul2.LowPart = kerneltime.dwLowDateTime;
ul2.HighPart = kerneltime.dwHighDateTime;
trace( "KernelTime: %f seconds\n", (double)ul2.QuadPart/10000000.0 );
ul3.LowPart = usertime.dwLowDateTime;
ul3.HighPart = usertime.dwHighDateTime;
trace( "UserTime: %f seconds\n", (double)ul3.QuadPart/10000000.0 );
ok( !NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength),
"NtQuerySystemInformation failed\n" );
ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength );
/* Check if we have some return values */
trace( "Number of Processors : %d\n", sbi.NumberOfProcessors );
ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n",
sbi.NumberOfProcessors );
sppi = HeapAlloc( GetProcessHeap(), 0,
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors);
ok( !NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi,
sizeof(*sppi), &ReturnLength),
"NtQuerySystemInformation failed\n" );
for (i = 0; i < sbi.NumberOfProcessors; i++)
{
total_usertime += (double)(sppi[i].UserTime.QuadPart)/10000000.0;
total_kerneltime += (double)(sppi[i].KernelTime.QuadPart)/10000000.0;
total_idletime += (double)(sppi[i].IdleTime.QuadPart)/10000000.0;
}
trace( "total_idletime %f total_kerneltime %f total_usertime %f \n", total_idletime,
total_kerneltime, total_usertime );
ok( (total_idletime - (double)ul1.QuadPart/10000000.0) < 1.0, "test idletime failed\n" );
ok( (total_kerneltime - (double)ul2.QuadPart/10000000.0) < 1.0, "test kerneltime failed\n" );
ok( (total_usertime - (double)ul3.QuadPart/10000000.0) < 1.0, "test usertime failed\n" );
HeapFree(GetProcessHeap(), 0, sppi);
}
START_TEST(time)
{
HMODULE hKernel = GetModuleHandleA("kernel32");
pTzSpecificLocalTimeToSystemTime = (void *)GetProcAddress(hKernel, "TzSpecificLocalTimeToSystemTime");
pSystemTimeToTzSpecificLocalTime = (void *)GetProcAddress( hKernel, "SystemTimeToTzSpecificLocalTime");
pGetSystemTimes = (void *)GetProcAddress( hKernel, "GetSystemTimes");
pGetCalendarInfoA = (void *)GetProcAddress(hKernel, "GetCalendarInfoA");
pGetCalendarInfoW = (void *)GetProcAddress(hKernel, "GetCalendarInfoW");
@ -747,6 +822,7 @@ START_TEST(time)
test_FileTimeToSystemTime();
test_FileTimeToLocalFileTime();
test_TzSpecificLocalTimeToSystemTime();
test_GetSystemTimes();
test_FileTimeToDosDateTime();
test_GetCalendarInfo();
}

View file

@ -23,23 +23,29 @@
#include "wine/test.h"
#include "winbase.h"
#include "winternl.h"
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
static BOOL (WINAPI * pVerifyVersionInfoA)(LPOSVERSIONINFOEXA, DWORD, DWORDLONG);
static ULONGLONG (WINAPI * pVerSetConditionMask)(ULONGLONG, DWORD, BYTE);
static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
#define KERNEL32_GET_PROC(func) \
p##func = (void *)GetProcAddress(hKernel32, #func);
#define GET_PROC(func) \
p##func = (void *)GetProcAddress(hmod, #func);
static void init_function_pointers(void)
{
HMODULE hKernel32;
HMODULE hmod;
hKernel32 = GetModuleHandleA("kernel32.dll");
hmod = GetModuleHandleA("kernel32.dll");
KERNEL32_GET_PROC(GetProductInfo);
KERNEL32_GET_PROC(VerifyVersionInfoA);
KERNEL32_GET_PROC(VerSetConditionMask);
GET_PROC(GetProductInfo);
GET_PROC(VerifyVersionInfoA);
GET_PROC(VerSetConditionMask);
hmod = GetModuleHandleA("ntdll.dll");
GET_PROC(RtlGetVersion);
}
static void test_GetProductInfo(void)
@ -170,6 +176,21 @@ static void test_VerifyVersionInfo(void)
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
servicepack = info.wServicePackMajor;
/* Win8.1+ returns Win8 version in GetVersionEx when there's no app manifest targeting 8.1 */
if (info.dwMajorVersion == 6 && info.dwMinorVersion == 2)
{
RTL_OSVERSIONINFOEXW rtlinfo;
rtlinfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
ok(SUCCEEDED(pRtlGetVersion(&rtlinfo)), "RtlGetVersion failed\n");
if (rtlinfo.dwMajorVersion != 6 || rtlinfo.dwMinorVersion != 2)
{
win_skip("GetVersionEx and VerifyVersionInfo are faking values\n");
return;
}
}
memset(&info, 0, sizeof(info));
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION,
@ -332,6 +353,337 @@ static void test_VerifyVersionInfo(void)
pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL));
ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError());
/* systematically test behaviour of condition mask (tests sorted by condition mask value) */
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMinorVersion++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_MINORVERSION, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMinorVersion++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_AND));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMinorVersion++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_LESS_EQUAL), VER_MINORVERSION, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMinorVersion++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_AND), VER_MINORVERSION, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMinorVersion++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_OR), VER_MINORVERSION, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_EQUAL));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
if (servicepack)
{
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMajorVersion++;
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_LESS), VER_SERVICEPACKMAJOR, VER_EQUAL));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
}
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
ret = pVerifyVersionInfoA(&info, VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL),
VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL),
VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL),
VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMinor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_EQUAL), VER_SERVICEPACKMINOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
if (servicepack)
{
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor--;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_LESS_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor--;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_AND), VER_SERVICEPACKMAJOR, VER_GREATER));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
}
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_LESS_EQUAL), VER_SERVICEPACKMAJOR, VER_GREATER));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
if (servicepack)
{
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor--;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_SERVICEPACKMAJOR, VER_GREATER), VER_SERVICEPACKMINOR, VER_EQUAL));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
}
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL),
VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.dwMajorVersion--;
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
info.wServicePackMajor++;
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_LESS_EQUAL));
error = GetLastError();
ok(!ret, "VerifyVersionInfoA succeeded\n");
ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */,
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error);
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);
ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_SERVICEPACKMAJOR, VER_AND));
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
/* test bad dwOSVersionInfoSize */
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
GetVersionExA((OSVERSIONINFOA *)&info);

File diff suppressed because it is too large Load diff