[KERNEL32_WINETEST]: Sync with Wine 1.5.19.

svn path=/trunk/; revision=57853
This commit is contained in:
Amine Khaldi 2012-12-09 20:39:13 +00:00
parent 345747cd11
commit 541bbc00b6
16 changed files with 2921 additions and 186 deletions

View file

@ -189,6 +189,74 @@ static void test_negative_dest_length(void)
}
static void test_other_invalid_parameters(void)
{
char c_string[] = "Hello World";
size_t c_string_len = sizeof(c_string);
WCHAR w_string[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
size_t w_string_len = sizeof(w_string) / sizeof(WCHAR);
BOOL used;
INT len;
/* srclen=0 => ERROR_INVALID_PARAMETER */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_ACP, 0, w_string, 0, c_string, c_string_len, NULL, NULL);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = MultiByteToWideChar(CP_ACP, 0, c_string, 0, w_string, w_string_len);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
/* dst=NULL but dstlen not 0 => ERROR_INVALID_PARAMETER */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_ACP, 0, w_string, w_string_len, NULL, c_string_len, NULL, NULL);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = MultiByteToWideChar(CP_ACP, 0, c_string, c_string_len, NULL, w_string_len);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
/* CP_UTF7, CP_UTF8, or CP_SYMBOL and defchar not NULL => ERROR_INVALID_PARAMETER */
/* CP_SYMBOL's behavior here is undocumented */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
/* CP_UTF7, CP_UTF8, or CP_SYMBOL and used not NULL => ERROR_INVALID_PARAMETER */
/* CP_SYMBOL's behavior here is undocumented */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
/* CP_UTF7, flags not 0 and used not NULL => ERROR_INVALID_PARAMETER */
/* (tests precedence of ERROR_INVALID_PARAMETER over ERROR_INVALID_FLAGS) */
/* The same test with CP_SYMBOL instead of CP_UTF7 gives ERROR_INVALID_FLAGS
instead except on Windows NT4 */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF7, 1, w_string, w_string_len, c_string, c_string_len, NULL, &used);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
}
static void test_overlapped_buffers(void)
{
static const WCHAR strW[] = {'j','u','s','t',' ','a',' ','t','e','s','t',0};
@ -402,6 +470,7 @@ START_TEST(codepage)
test_null_source();
test_negative_source_length();
test_negative_dest_length();
test_other_invalid_parameters();
test_overlapped_buffers();
/* WideCharToMultiByte has two code paths, test both here */

View file

@ -1031,7 +1031,7 @@ static void test_OpenCON(void)
h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
/* Windows versions differ here:
* MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
* NT, XP, Vista comply, but Win7 doesn't and allows to open CON with TRUNCATE_EXISTING
* NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
* So don't test when disposition is TRUNCATE_EXISTING
*/
if (accesses[i] != TRUNCATE_EXISTING)
@ -1354,12 +1354,12 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
LPDWORD written;
DWORD expected_count;
DWORD last_error;
int win7_crash;
int win_crash;
} invalid_table[] =
{
{NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
{NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
@ -1367,14 +1367,14 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
{NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
{input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
@ -1406,7 +1406,7 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
{
if (invalid_table[i].win7_crash)
if (invalid_table[i].win_crash)
continue;
SetLastError(0xdeadbeef);
@ -1597,12 +1597,12 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
LPDWORD written;
DWORD expected_count;
DWORD last_error;
int win7_crash;
int win_crash;
} invalid_table[] =
{
{NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
{NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
@ -1610,14 +1610,14 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
{NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
{INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
{input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
{input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
{input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
{input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
@ -1649,7 +1649,7 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
{
if (invalid_table[i].win7_crash)
if (invalid_table[i].win_crash)
continue;
SetLastError(0xdeadbeef);

View file

@ -287,6 +287,13 @@ static void crash_and_debug(HKEY hkey, const char* argv0, const char* dbgtasks)
}
ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
if (ret == ERROR_ACCESS_DENIED)
{
skip_crash_and_debug = TRUE;
skip("No write access to change the debugger\n");
return;
}
ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%d\n", ret);
get_file_name(dbglog);

View file

@ -21,7 +21,7 @@
*/
/* ReplaceFile requires Windows 2000 or newer */
#define _WIN32_WINNT 0x0500
#define _WIN32_WINNT 0x0600
#include <stdarg.h>
#include <stdlib.h>
@ -32,6 +32,7 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
@ -39,6 +40,9 @@ static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LP
static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
/* keep filename and filenameW the same */
static const char filename[] = "testfile.xxx";
@ -73,6 +77,9 @@ static void InitFunctionPointers(void)
pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA");
pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC");
pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
}
static void test__hread( void )
@ -796,7 +803,7 @@ static void dumpmem(unsigned char *mem, int len)
p = hex;
c = txt;
do {
p += sprintf(p, "%02hhx ", mem[x]);
p += sprintf(p, "%02x ", mem[x]);
*c++ = (mem[x] >= 32 && mem[x] <= 127) ? mem[x] : '.';
} while (++x % 16 && x < len);
*c = '\0';
@ -1291,6 +1298,8 @@ static void test_GetTempFileNameA(void)
static void test_DeleteFileA( void )
{
BOOL ret;
char temp_path[MAX_PATH], temp_file[MAX_PATH];
HANDLE hfile;
ret = DeleteFileA(NULL);
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
@ -1308,6 +1317,25 @@ static void test_DeleteFileA( void )
GetLastError() == ERROR_ACCESS_DENIED ||
GetLastError() == ERROR_INVALID_FUNCTION),
"DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
GetTempPathA(MAX_PATH, temp_path);
GetTempFileName(temp_path, "tst", 0, temp_file);
SetLastError(0xdeadbeef);
hfile = CreateFile(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = DeleteFile(temp_file);
todo_wine
ok(ret, "DeleteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = CloseHandle(hfile);
ok(ret, "CloseHandle error %d\n", GetLastError());
ret = DeleteFile(temp_file);
todo_wine
ok(!ret, "DeleteFile should fail\n");
}
static void test_DeleteFileW( void )
@ -1758,7 +1786,7 @@ static BOOL create_fake_dll( LPCSTR filename )
#elif defined __sparc__
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_SPARC;
#elif defined __arm__
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMV7;
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT;
#else
# error You must specify the machine type
#endif
@ -3237,6 +3265,314 @@ static void test_CreatFile(void)
DeleteFile(file_name);
}
static void test_GetFileInformationByHandleEx(void)
{
int i;
char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024];
BOOL ret;
DWORD ret2;
HANDLE directory;
FILE_ID_BOTH_DIR_INFO *bothDirInfo;
struct {
FILE_INFO_BY_HANDLE_CLASS handleClass;
void *ptr;
DWORD size;
DWORD errorCode;
} checks[] = {
{0xdeadbeef, NULL, 0, ERROR_INVALID_PARAMETER},
{FileIdBothDirectoryInfo, NULL, 0, ERROR_BAD_LENGTH},
{FileIdBothDirectoryInfo, NULL, sizeof(buffer), ERROR_NOACCESS},
{FileIdBothDirectoryInfo, buffer, 0, ERROR_BAD_LENGTH}};
if (!pGetFileInformationByHandleEx)
{
win_skip("GetFileInformationByHandleEx is missing.\n");
return;
}
ret2 = GetTempPathA(sizeof(tempPath), tempPath);
ok(ret2, "GetFileInformationByHandleEx: GetTempPathA failed, got error %u.\n", GetLastError());
/* ensure the existence of a file in the temp folder */
ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
ok(ret2, "GetFileInformationByHandleEx: GetTempFileNameA failed, got error %u.\n", GetLastError());
ok(GetFileAttributesA(tempFileName) != INVALID_FILE_ATTRIBUTES, "GetFileInformationByHandleEx: "
"GetFileAttributesA failed to find the temp file, got error %u.\n", GetLastError());
directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
ok(directory != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp folder, "
"got error %u.\n", GetLastError());
for (i = 0; i < sizeof(checks) / sizeof(checks[0]); i += 1)
{
SetLastError(0xdeadbeef);
ret = pGetFileInformationByHandleEx(directory, checks[i].handleClass, checks[i].ptr, checks[i].size);
ok(!ret && GetLastError() == checks[i].errorCode, "GetFileInformationByHandleEx: expected error %u, "
"got %u.\n", checks[i].errorCode, GetLastError());
}
while (TRUE)
{
memset(buffer, 0xff, sizeof(buffer));
ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
if (!ret && GetLastError() == ERROR_NO_MORE_FILES)
break;
ok(ret, "GetFileInformationByHandleEx: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
if (!ret)
break;
bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
while (TRUE)
{
ok(bothDirInfo->FileAttributes != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file attributes.\n");
ok(bothDirInfo->FileId.u.LowPart != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file id.\n");
ok(bothDirInfo->FileNameLength != 0xffffffff, "GetFileInformationByHandleEx: returned invalid file name length.\n");
if (!bothDirInfo->NextEntryOffset)
break;
bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
}
}
CloseHandle(directory);
DeleteFile(tempFileName);
}
static void test_OpenFileById(void)
{
char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[256], tickCount[256];
WCHAR tempFileNameW[MAX_PATH];
BOOL ret, found;
DWORD ret2, count, tempFileNameLen;
HANDLE directory, handle, tempFile;
FILE_ID_BOTH_DIR_INFO *bothDirInfo;
FILE_ID_DESCRIPTOR fileIdDescr;
if (!pGetFileInformationByHandleEx || !pOpenFileById)
{
win_skip("GetFileInformationByHandleEx or OpenFileById is missing.\n");
return;
}
ret2 = GetTempPathA(sizeof(tempPath), tempPath);
ok(ret2, "OpenFileById: GetTempPath failed, got error %u.\n", GetLastError());
/* ensure the existence of a file in the temp folder */
ret2 = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
ok(ret2, "OpenFileById: GetTempFileNameA failed, got error %u.\n", GetLastError());
ok(GetFileAttributesA(tempFileName) != INVALID_FILE_ATTRIBUTES,
"OpenFileById: GetFileAttributesA failed to find the temp file, got error %u\n", GetLastError());
ret2 = MultiByteToWideChar(CP_ACP, 0, tempFileName + strlen(tempPath), -1, tempFileNameW, sizeof(tempFileNameW)/sizeof(tempFileNameW[0]));
ok(ret2, "OpenFileById: MultiByteToWideChar failed to convert tempFileName, got error %u.\n", GetLastError());
tempFileNameLen = ret2 - 1;
tempFile = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ok(tempFile != INVALID_HANDLE_VALUE, "OpenFileById: failed to create a temp file, "
"got error %u.\n", GetLastError());
ret2 = sprintf(tickCount, "%u", GetTickCount());
ret = WriteFile(tempFile, tickCount, ret2, &count, NULL);
ok(ret, "OpenFileById: WriteFile failed, got error %u.\n", GetLastError());
CloseHandle(tempFile);
directory = CreateFileA(tempPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
ok(directory != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder, "
"got error %u.\n", GetLastError());
/* get info about the temp folder itself */
bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
ok(bothDirInfo->FileNameLength == sizeof(WCHAR) && bothDirInfo->FileName[0] == '.',
"OpenFileById: failed to return the temp folder at the first entry, got error %u.\n", GetLastError());
/* open the temp folder itself */
fileIdDescr.dwSize = sizeof(fileIdDescr);
fileIdDescr.Type = FileIdType;
U(fileIdDescr).FileId = bothDirInfo->FileId;
handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
todo_wine
ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the temp folder itself, got error %u.\n", GetLastError());
CloseHandle(handle);
/* find the temp file in the temp folder */
found = FALSE;
while (!found)
{
ret = pGetFileInformationByHandleEx(directory, FileIdBothDirectoryInfo, buffer, sizeof(buffer));
ok(ret, "OpenFileById: failed to query for FileIdBothDirectoryInfo, got error %u.\n", GetLastError());
if (!ret)
break;
bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)buffer;
while (TRUE)
{
if (tempFileNameLen == bothDirInfo->FileNameLength / sizeof(WCHAR) &&
memcmp(tempFileNameW, bothDirInfo->FileName, bothDirInfo->FileNameLength) == 0)
{
found = TRUE;
break;
}
if (!bothDirInfo->NextEntryOffset)
break;
bothDirInfo = (FILE_ID_BOTH_DIR_INFO *)(((char *)bothDirInfo) + bothDirInfo->NextEntryOffset);
}
}
ok(found, "OpenFileById: failed to find the temp file in the temp folder.\n");
SetLastError(0xdeadbeef);
handle = pOpenFileById(directory, NULL, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
ok(handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER,
"OpenFileById: expected ERROR_INVALID_PARAMETER, got error %u.\n", GetLastError());
fileIdDescr.dwSize = sizeof(fileIdDescr);
fileIdDescr.Type = FileIdType;
U(fileIdDescr).FileId = bothDirInfo->FileId;
handle = pOpenFileById(directory, &fileIdDescr, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, 0);
ok(handle != INVALID_HANDLE_VALUE, "OpenFileById: failed to open the file, got error %u.\n", GetLastError());
ret = ReadFile(handle, buffer, sizeof(buffer), &count, NULL);
buffer[count] = 0;
ok(ret, "OpenFileById: ReadFile failed, got error %u.\n", GetLastError());
ok(strcmp(tickCount, buffer) == 0, "OpenFileById: invalid contents of the temp file.\n");
CloseHandle(handle);
CloseHandle(directory);
DeleteFile(tempFileName);
}
static void test_SetFileValidData(void)
{
BOOL ret;
HANDLE handle;
DWORD error, count;
char path[MAX_PATH], filename[MAX_PATH];
TOKEN_PRIVILEGES privs;
HANDLE token = NULL;
if (!pSetFileValidData)
{
win_skip("SetFileValidData is missing\n");
return;
}
GetTempPathA(sizeof(path), path);
GetTempFileNameA(path, "tst", 0, filename);
handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
WriteFile(handle, "test", sizeof("test") - 1, &count, NULL);
CloseHandle(handle);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(INVALID_HANDLE_VALUE, 0);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(INVALID_HANDLE_VALUE, -1);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_HANDLE, "got %u\n", error);
/* file opened for reading */
handle = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 0);
ok(!ret, "SetFileValidData succeeded\n");
error = GetLastError();
ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, -1);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_ACCESS_DENIED, "got %u\n", error);
CloseHandle(handle);
handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 0);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
todo_wine ok(error == ERROR_PRIVILEGE_NOT_HELD, "got %u\n", error);
CloseHandle(handle);
privs.PrivilegeCount = 1;
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token) ||
!LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) ||
!AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL))
{
win_skip("cannot enable SE_MANAGE_VOLUME_NAME privilege\n");
CloseHandle(token);
return;
}
handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 0);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, -1);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 2);
error = GetLastError();
todo_wine ok(!ret, "SetFileValidData succeeded\n");
todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
ret = pSetFileValidData(handle, 4);
ok(ret, "SetFileValidData failed %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 8);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
count = SetFilePointer(handle, 1024, NULL, FILE_END);
ok(count != INVALID_SET_FILE_POINTER, "SetFilePointer failed %u\n", GetLastError());
ret = SetEndOfFile(handle);
ok(ret, "SetEndOfFile failed %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = pSetFileValidData(handle, 2);
error = GetLastError();
todo_wine ok(!ret, "SetFileValidData succeeded\n");
todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
ret = pSetFileValidData(handle, 4);
ok(ret, "SetFileValidData failed %u\n", GetLastError());
ret = pSetFileValidData(handle, 8);
ok(ret, "SetFileValidData failed %u\n", GetLastError());
ret = pSetFileValidData(handle, 4);
error = GetLastError();
todo_wine ok(!ret, "SetFileValidData succeeded\n");
todo_wine ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
ret = pSetFileValidData(handle, 1024);
ok(ret, "SetFileValidData failed %u\n", GetLastError());
ret = pSetFileValidData(handle, 2048);
error = GetLastError();
ok(!ret, "SetFileValidData succeeded\n");
ok(error == ERROR_INVALID_PARAMETER, "got %u\n", error);
privs.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL);
CloseHandle(token);
DeleteFile(filename);
}
START_TEST(file)
{
InitFunctionPointers();
@ -3276,4 +3612,7 @@ START_TEST(file)
test_RemoveDirectory();
test_ReplaceFileA();
test_ReplaceFileW();
test_GetFileInformationByHandleEx();
test_OpenFileById();
test_SetFileValidData();
}

View file

@ -997,6 +997,195 @@ static void test_message_ignore_inserts_wide(void)
ok(!lstrcmpW(s_2sp, out), "Expected output string \" \", got %s\n", wine_dbgstr_w(out));
}
static void test_message_wrap(void)
{
DWORD ret;
int i;
CHAR in[300], out[300], ref[300];
/* No need for wrapping */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 20,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 15, "Expected FormatMessageW to return 15, got %d\n", ret);
ok(!strcmp("short long line", out),"failed out=[%s]\n",out);
/* Wrap the last word */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short long\r\nline", out),"failed out=[%s]\n",out);
/* Wrap the very last word */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 20,
"short long long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 21, "Expected FormatMessageW to return 21, got %d\n", ret);
ok(!strcmp("short long long\r\nline", out),"failed out=[%s]\n",out);
/* Strictly less than 10 characters per line! */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 10,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong line", out),"failed out=[%s]\n",out);
/* Handling of duplicate spaces */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 16,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short long\r\nline", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 16,
"short long wordlongerthanaline", 0, 0, out, sizeof(out), NULL);
ok(ret == 33, "Expected FormatMessageW to return 33, got %d\n", ret);
ok(!strcmp("short long\r\nwordlongerthanal\r\nine", out),"failed out=[%s]\n",out);
/* Breaking in the middle of spaces */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 12,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 18, "Expected FormatMessageW to return 18, got %d\n", ret);
ok(!strcmp("short long\r\n line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 12,
"short long wordlongerthanaline", 0, 0, out, sizeof(out), NULL);
ok(ret == 35, "Expected FormatMessageW to return 35, got %d\n", ret);
ok(!strcmp("short long\r\n\r\nwordlongerth\r\nanaline", out),"failed out=[%s]\n",out);
/* Handling of start-of-string spaces */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 15,
" short line", 0, 0, out, sizeof(out), NULL);
ok(ret == 13, "Expected FormatMessageW to return 13, got %d\n", ret);
ok(!strcmp(" short line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
" shortlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 17, "Expected FormatMessageW to return 17, got %d\n", ret);
ok(!strcmp("\r\nshortlong\r\nline", out),"failed out=[%s]\n",out);
/* Handling of start-of-line spaces */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"l1%n shortlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 21, "Expected FormatMessageW to return 21, got %d\n", ret);
ok(!strcmp("l1\r\n\r\nshortlong\r\nline", out),"failed out=[%s]\n",out);
/* Pure space wrapping */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 5,
" ", 0, 0, out, sizeof(out), NULL);
ok(ret == 7, "Expected FormatMessageW to return 7, got %d\n", ret);
ok(!strcmp("\r\n\r\n\r\n ", out),"failed out=[%s]\n",out);
/* Handling of trailing spaces */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 5,
"l1 ", 0, 0, out, sizeof(out), NULL);
ok(ret == 10, "Expected FormatMessageW to return 10, got %d\n", ret);
ok(!strcmp("l1\r\n\r\n\r\n ", out),"failed out=[%s]\n",out);
/* Word that just fills the line */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 8,
"shortlon", 0, 0, out, sizeof(out), NULL);
ok(ret == 10, "Expected FormatMessageW to return 10, got %d\n", ret);
ok(!strcmp("shortlon\r\n", out),"failed out=[%s]\n",out);
/* Word longer than the line */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 8,
"shortlongline", 0, 0, out, sizeof(out), NULL);
ok(ret == 15, "Expected FormatMessageW to return 15, got %d\n", ret);
ok(!strcmp("shortlon\r\ngline", out),"failed out=[%s]\n",out);
/* Wrap the line multiple times */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 7,
"short long line", 0, 0, out, sizeof(out), NULL);
ok(ret == 17, "Expected FormatMessageW to return 17, got %d\n", ret);
ok(!strcmp("short\r\nlong\r\nline", out),"failed out=[%s]\n",out);
/* '\n's in the source are ignored */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short\nlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short long\r\nline", out),"failed out=[%s]\n",out);
/* Wrap even before a '%n' */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 8,
"shortlon%n", 0, 0, out, sizeof(out), NULL);
ok(ret == 12, "Expected FormatMessageW to return 12, got %d\n", ret);
ok(!strcmp("shortlon\r\n\r\n", out),"failed out=[%s]\n",out);
/* '%n's count as starting a new line and combine with line wrapping */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 10,
"short%nlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 8,
"short%nlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 17, "Expected FormatMessageW to return 17, got %d\n", ret);
ok(!strcmp("short\r\nlong\r\nline", out),"failed out=[%s]\n",out);
/* '%r's also count as starting a new line and all */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 10,
"short%rlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 15, "Expected FormatMessageW to return 15, got %d\n", ret);
ok(!strcmp("short\rlong line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 8,
"short%rlong line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\rlong\r\nline", out),"failed out=[%s]\n",out);
/* IGNORE_INSERTS does not prevent line wrapping or disable '%n' */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS | 8,
"short%nlong line%1", 0, 0, out, sizeof(out), NULL);
ok(ret == 19, "Expected FormatMessageW to return 19, got %d\n", ret);
ok(!strcmp("short\r\nlong\r\nline%1", out),"failed out=[%s]\n",out);
/* MAX_WIDTH_MASK is the same as specifying an infinite line width */
strcpy(in, "first line%n");
strcpy(ref, "first line\r\n");
for (i=0; i < 26; i++)
{
strcat(in, "123456789 ");
strcat(ref, "123456789 ");
}
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK,
in, 0, 0, out, sizeof(out), NULL);
ok(ret == 272, "Expected FormatMessageW to return 272, got %d\n", ret);
ok(!strcmp(ref, out),"failed out=[%s]\n",out);
/* Wrapping and non-space characters */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long\tline", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong\tline", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long-line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong-line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long_line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong_line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long.line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong.line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long,line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong,line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long!line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong!line", out),"failed out=[%s]\n",out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | 11,
"short long?line", 0, 0, out, sizeof(out), NULL);
ok(ret == 16, "Expected FormatMessageW to return 16, got %d\n", ret);
ok(!strcmp("short\r\nlong?line", out),"failed out=[%s]\n",out);
}
static void test_message_insufficient_buffer(void)
{
static const char init_buf[] = {'x', 'x', 'x', 'x', 'x'};
@ -1593,6 +1782,7 @@ START_TEST(format_msg)
test_message_from_string();
test_message_ignore_inserts();
test_message_wrap();
test_message_insufficient_buffer();
test_message_null_buffer();
test_message_allocate_buffer();

View file

@ -63,7 +63,7 @@ static IMAGE_NT_HEADERS nt_header =
#elif defined __sparc__
IMAGE_FILE_MACHINE_SPARC, /* Machine */
#elif defined __arm__
IMAGE_FILE_MACHINE_ARMV7, /* Machine */
IMAGE_FILE_MACHINE_ARMNT, /* Machine */
#else
# error You must specify the machine type
#endif

View file

@ -39,6 +39,11 @@
#include "winerror.h"
#include "winnls.h"
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 fooW[] = {'f','o','o',0};
static inline unsigned int strlenW( const WCHAR *str )
{
const WCHAR *s = str;
@ -74,6 +79,7 @@ static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD,
static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM);
static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
static INT (WINAPI *pLCIDToLocaleName)(LCID, LPWSTR, INT, DWORD);
static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
@ -82,6 +88,9 @@ static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
static INT (WINAPI *pIdnToNameprepUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
static INT (WINAPI *pIdnToAscii)(DWORD, LPCWSTR, INT, LPWSTR, INT);
static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
static void InitFunctionPointers(void)
{
@ -90,6 +99,7 @@ static void InitFunctionPointers(void)
pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
pLocaleNameToLCID = (void*)GetProcAddress(hKernel32, "LocaleNameToLCID");
pLCIDToLocaleName = (void*)GetProcAddress(hKernel32, "LCIDToLocaleName");
pLCMapStringEx = (void*)GetProcAddress(hKernel32, "LCMapStringEx");
pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
@ -98,6 +108,9 @@ static void InitFunctionPointers(void)
pIdnToNameprepUnicode = (void*)GetProcAddress(hKernel32, "IdnToNameprepUnicode");
pIdnToAscii = (void*)GetProcAddress(hKernel32, "IdnToAscii");
pIdnToUnicode = (void*)GetProcAddress(hKernel32, "IdnToUnicode");
pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
}
#define eq(received, expected, label, type) \
@ -127,9 +140,14 @@ static void test_GetLocaleInfoA(void)
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
char buffer[BUFFER_SIZE];
char expected[BUFFER_SIZE];
DWORD val;
ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
ret = GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (char*)&val, sizeof(val));
ok(ret, "got %d\n", ret);
ok(val == lcid, "got 0x%08x\n", val);
/* en and ar use SUBLANG_NEUTRAL, but GetLocaleInfo assume SUBLANG_DEFAULT
Same is true for zh on pre-Vista, but on Vista and higher GetLocaleInfo
assumes SUBLANG_NEUTRAL for zh */
@ -188,12 +206,57 @@ static void test_GetLocaleInfoA(void)
ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
}
struct neutralsublang_name2_t {
WCHAR name[3];
WCHAR sname[15];
LCID lcid;
LCID lcid_broken;
WCHAR sname_broken[15];
int todo;
};
static const struct neutralsublang_name2_t neutralsublang_names2[] = {
{ {'a','r',0}, {'a','r','-','S','A',0},
MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
{ {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0},
MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
{ {'d','e',0}, {'d','e','-','D','E',0},
MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
{ {'e','n',0}, {'e','n','-','U','S',0},
MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
{ {'e','s',0}, {'e','s','-','E','S',0},
MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */,
{'e','s','-','E','S','_','t','r','a','d','n','l',0}, 0x1 },
{ {'g','a',0}, {'g','a','-','I','E',0},
MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, {0}, 0x3 },
{ {'i','t',0}, {'i','t','-','I','T',0},
MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
{ {'m','s',0}, {'m','s','-','M','Y',0},
MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
{ {'n','l',0}, {'n','l','-','N','L',0},
MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
{ {'p','t',0}, {'p','t','-','B','R',0},
MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
{ {'s','r',0}, {'h','r','-','H','R',0},
MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_CROATIA), SORT_DEFAULT) },
{ {'s','v',0}, {'s','v','-','S','E',0},
MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
{ {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
{ {'z','h',0}, {'z','h','-','C','N',0},
MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 0, {0}, 0x3 },
{ {0} }
};
static void test_GetLocaleInfoW(void)
{
LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
LCID lcid_en_neut = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), SORT_DEFAULT);
WCHAR bufferW[80], buffer2W[80];
CHAR bufferA[80];
DWORD val;
DWORD ret;
INT i;
@ -202,6 +265,68 @@ static void test_GetLocaleInfoW(void)
win_skip("GetLocaleInfoW() isn't implemented\n");
return;
}
ret = GetLocaleInfoW(lcid_en, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
ok(ret, "got %d\n", ret);
ok(val == lcid_en, "got 0x%08x\n", val);
ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
if (ret)
{
static const WCHAR slangW[] = {'E','n','g','l','i','s','h',' ','(','U','n','i','t','e','d',' ',
'S','t','a','t','e','s',')',0};
static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
static const WCHAR enW[] = {'e','n','-','U','S',0};
const struct neutralsublang_name2_t *ptr = neutralsublang_names2;
ok(!lstrcmpW(bufferW, enW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SCOUNTRY, bufferW, COUNTOF(bufferW));
ok(ret, "got %d\n", ret);
ok(!lstrcmpW(statesW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
ret = GetLocaleInfoW(lcid_en_neut, LOCALE_SLANGUAGE, bufferW, COUNTOF(bufferW));
ok(ret, "got %d\n", ret);
ok(!lstrcmpW(slangW, bufferW), "got wrong name %s\n", wine_dbgstr_w(bufferW));
while (*ptr->name)
{
LANGID langid;
LCID lcid;
/* make neutral lcid */
langid = MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(ptr->lcid)), SUBLANG_NEUTRAL);
lcid = MAKELCID(langid, SORT_DEFAULT);
val = 0;
GetLocaleInfoW(lcid, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
if (ptr->todo & 0x1)
{
todo_wine
ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
wine_dbgstr_w(ptr->name), val, ptr->lcid);
}
else
ok(val == ptr->lcid || (val && broken(val == ptr->lcid_broken)), "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
wine_dbgstr_w(ptr->name), val, ptr->lcid);
/* now check LOCALE_SNAME */
GetLocaleInfoW(lcid, LOCALE_SNAME, bufferW, COUNTOF(bufferW));
if (ptr->todo & 0x2)
todo_wine
ok(!lstrcmpW(bufferW, ptr->sname) ||
(*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
"%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
else
ok(!lstrcmpW(bufferW, ptr->sname) ||
(*ptr->sname_broken && broken(!lstrcmpW(bufferW, ptr->sname_broken))),
"%s: got %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
ptr++;
}
}
else
win_skip("English neutral locale not supported\n");
ret = GetLocaleInfoW(lcid_ru, LOCALE_SMONTHNAME1, bufferW, COUNTOF(bufferW));
if (!ret) {
win_skip("LANG_RUSSIAN locale data unavailable\n");
@ -1206,27 +1331,27 @@ static void test_CompareStringA(void)
}
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
ok (ret == CSTR_LESS_THAN, "(Salut/Salute) Expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
ok (ret == CSTR_EQUAL, "(Salut/SaLuT) Expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
ok (ret == CSTR_GREATER_THAN, "(Salut/hola) Expected CSTR_GREATER_THAN, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
ok (ret == CSTR_LESS_THAN, "(haha/hoho) Expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
ok (ret == CSTR_GREATER_THAN, "(haha/hoho) Expected CSTR_GREATER_THAN, got %d\n", ret);
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
ok (ret == CSTR_EQUAL, "(Salut/saLuT) Expected CSTR_EQUAL, got %d\n", ret);
/* test for CompareStringA flags */
SetLastError(0xdeadbeef);
@ -1256,52 +1381,52 @@ static void test_CompareStringA(void)
if (0) { /* this requires collation table patch to make it MS compatible */
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
ok(ret == 1, "'o vs -o expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "'o vs -o expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
ok(ret == 1, "' vs - expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
ok(ret == 1, "' vs - expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "' vs - expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
ok(ret == 3, "`o vs /m expected 3, got %d\n", ret);
ok(ret == CSTR_GREATER_THAN, "`o vs /m CSTR_GREATER_THAN got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
ok(ret == 1, "/m vs `o expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "/m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
ok(ret == 1, "`o vs -m expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "`o vs -m expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
ok(ret == 3, "-m vs `o expected 3, got %d\n", ret);
ok(ret == CSTR_GREATER_THAN, "-m vs `o CSTR_GREATER_THAN got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
ok(ret == 3, "`o vs -m expected 3, got %d\n", ret);
ok(ret == CSTR_GREATER_THAN, "`o vs -m CSTR_GREATER_THAN got %d\n", ret);
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
ok(ret == 1, "-m vs `o expected 1, got %d\n", ret);
ok(ret == CSTR_LESS_THAN, "-m vs `o expected CSTR_LESS_THAN, got %d\n", ret);
}
/* WinXP handles embedded NULLs differently than earlier versions */
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
ok(ret == 1 || ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1 or 2, got %d\n", ret);
ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLuZkUtZ vs aLuZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
ok(ret == 1 || ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 1 or 2, got %d\n", ret);
ok(ret == CSTR_LESS_THAN || ret == CSTR_EQUAL, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected CSTR_LESS_THAN or CSTR_EQUAL, got %d\n", ret);
ret = CompareStringA(lcid, 0, "a\0b", -1, "a", -1);
ok(ret == 2, "a vs a expected 2, got %d\n", ret);
ok(ret == CSTR_EQUAL, "a vs a expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringA(lcid, 0, "a\0b", 4, "a", 2);
ok(ret == CSTR_EQUAL || /* win2k */
@ -1309,7 +1434,7 @@ static void test_CompareStringA(void)
"a\\0b vs a expected CSTR_EQUAL or CSTR_GREATER_THAN, got %d\n", ret);
ret = CompareStringA(lcid, 0, "\2", 2, "\1", 2);
todo_wine ok(ret != 2, "\\2 vs \\1 expected unequal\n");
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);
@ -1493,168 +1618,253 @@ static void test_LCMapStringA(void)
"unexpected error code %d\n", GetLastError());
}
static void test_LCMapStringW(void)
typedef INT (*lcmapstring_wrapper)(DWORD, LPCWSTR, INT, LPWSTR, INT);
static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
{
int ret, ret2;
WCHAR buf[256], buf2[256];
char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
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 fooW[] = {'f','o','o',0};
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("LCMapStringW is not implemented\n");
return;
}
if (broken(ret))
ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
else
{
ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
ok(GetLastError() == ERROR_INVALID_FLAGS,
"unexpected error code %d\n", GetLastError());
ok(!ret, "%s LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n", func_name);
ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
func_name, GetLastError());
}
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
ret = func_ptr(LCMAP_HIRAGANA | LCMAP_KATAKANA,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
ok(GetLastError() == ERROR_INVALID_FLAGS,
"unexpected error code %d\n", GetLastError());
ok(!ret, "%s LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n", func_name);
ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
func_name, GetLastError());
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
ok(GetLastError() == ERROR_INVALID_FLAGS,
"unexpected error code %d\n", GetLastError());
ok(!ret, "%s LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n", func_name);
ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
func_name, GetLastError());
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
ret = func_ptr(LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
ok(GetLastError() == ERROR_INVALID_FLAGS,
"unexpected error code %d\n", GetLastError());
ok(!ret, "%s LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n",
func_name);
ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
func_name, GetLastError());
/* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
SetLastError(0xdeadbeef);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
ret = func_ptr(LCMAP_LOWERCASE | SORT_STRINGSORT,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
ok(GetLastError() == ERROR_INVALID_FLAGS, "%s expected ERROR_INVALID_FLAGS, got %d\n",
func_name, GetLastError());
ok(!ret, "%s SORT_STRINGSORT without LCMAP_SORTKEY must fail\n", func_name);
/* test LCMAP_LOWERCASE */
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
ret = func_ptr(LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(upper_case) + 1,
"ret %d, error %d, expected value %d\n",
ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
/* test LCMAP_UPPERCASE */
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
ret = func_ptr(LCMAP_UPPERCASE,
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(lower_case) + 1,
"ret %d, error %d, expected value %d\n",
ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
/* test buffer overflow */
SetLastError(0xdeadbeef);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
ret = func_ptr(LCMAP_UPPERCASE,
lower_case, -1, buf, 4);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
"%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
lstrcpyW(buf, lower_case);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
ret = func_ptr(LCMAP_UPPERCASE,
buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(lower_case) + 1,
"ret %d, error %d, expected value %d\n",
ok(ret == lstrlenW(lower_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
lstrcpyW(buf, upper_case);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
ret = func_ptr(LCMAP_LOWERCASE,
buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(upper_case) + 1,
"ret %d, error %d, expected value %d\n",
ok(ret == lstrlenW(upper_case) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
ok(!lstrcmpW(buf, lower_case), "%s string compare mismatch\n", func_name);
/* otherwise src == dst should fail */
SetLastError(0xdeadbeef);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
ret = func_ptr(LCMAP_SORTKEY | LCMAP_UPPERCASE,
buf, 10, buf, sizeof(buf));
ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
"unexpected error code %d\n", GetLastError());
ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
GetLastError() == ERROR_INVALID_PARAMETER /* Win7+ */,
"%s unexpected error code %d\n", func_name, GetLastError());
ok(!ret, "%s src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n", func_name);
/* test whether '\0' is always appended */
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
ret = func_ptr(LCMAP_SORTKEY,
upper_case, -1, buf, sizeof(buf));
ok(ret, "LCMapStringW must succeed\n");
ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
ok(ret, "%s func_ptr must succeed\n", func_name);
ret2 = func_ptr(LCMAP_SORTKEY,
upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
ok(ret, "LCMapStringW must succeed\n");
ok(ret == ret2, "lengths of sort keys must be equal\n");
ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
ok(ret, "%s func_ptr must succeed\n", func_name);
ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
/* test LCMAP_SORTKEY | NORM_IGNORECASE */
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORECASE,
upper_case, -1, buf, sizeof(buf));
ok(ret, "LCMapStringW must succeed\n");
ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
ok(ret, "%s func_ptr must succeed\n", func_name);
ret2 = func_ptr(LCMAP_SORTKEY,
lower_case, -1, buf2, sizeof(buf2));
ok(ret2, "LCMapStringW must succeed\n");
ok(ret == ret2, "lengths of sort keys must be equal\n");
ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
ok(ret2, "%s func_ptr must succeed\n", func_name);
ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
/* Don't test LCMAP_SORTKEY | NORM_IGNORENONSPACE, produces different
results from plain LCMAP_SORTKEY on Vista */
/* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
ret = func_ptr(LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
lower_case, -1, buf, sizeof(buf));
ok(ret, "LCMapStringW must succeed\n");
ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
ok(ret, "%s func_ptr must succeed\n", func_name);
ret2 = func_ptr(LCMAP_SORTKEY,
symbols_stripped, -1, buf2, sizeof(buf2));
ok(ret2, "LCMapStringW must succeed\n");
ok(ret == ret2, "lengths of sort keys must be equal\n");
ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
ok(ret2, "%s func_ptr must succeed\n", func_name);
ok(ret == ret2, "%s lengths of sort keys must be equal\n", func_name);
ok(!lstrcmpA(p_buf, p_buf2), "%s sort keys must be equal\n", func_name);
/* test NORM_IGNORENONSPACE */
lstrcpyW(buf, fooW);
ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
ret = func_ptr(NORM_IGNORENONSPACE,
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
lstrlenW(lower_case) + 1, ret);
ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
ok(ret == lstrlenW(lower_case) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
lstrlenW(lower_case) + 1, ret);
ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
/* test NORM_IGNORESYMBOLS */
lstrcpyW(buf, fooW);
ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
ret = func_ptr(NORM_IGNORESYMBOLS,
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
/* test srclen = 0 */
SetLastError(0xdeadbeef);
ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
ok(!ret, "LCMapStringW should fail with srclen = 0\n");
ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
ok(!ret, "%s func_ptr should fail with srclen = 0\n", func_name);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"unexpected error code %d\n", GetLastError());
"%s unexpected error code %d\n", func_name, GetLastError());
}
static void test_LocaleNames(void)
static INT LCMapStringW_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
{
return LCMapStringW(LOCALE_USER_DEFAULT, flags, src, srclen, dst, dstlen);
}
static void test_LCMapStringW(void)
{
int ret;
WCHAR buf[256];
trace("testing LCMapStringW\n");
SetLastError(0xdeadbeef);
ret = LCMapStringW((LCID)-1, LCMAP_LOWERCASE, upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
todo_wine {
ok(!ret, "LCMapStringW should fail with bad lcid\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
}
test_lcmapstring_unicode(LCMapStringW_wrapper, "LCMapStringW:");
}
static INT LCMapStringEx_wrapper(DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
{
return pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, flags, src, srclen, dst, dstlen, NULL, NULL, 0);
}
static void test_LCMapStringEx(void)
{
int ret;
WCHAR buf[256];
if (!pLCMapStringEx)
{
win_skip( "LCMapStringEx not available\n" );
return;
}
trace("testing LCMapStringEx\n");
SetLastError(0xdeadbeef);
ret = pLCMapStringEx(fooW, LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
todo_wine {
ok(!ret, "LCMapStringEx should fail with bad locale name\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "unexpected error code %d\n", GetLastError());
}
/* test reserved parameters */
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 1);
ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, (void*)1, 0);
ok(ret == lstrlenW(upper_case) + 1, "ret %d, error %d, expected value %d\n",
ret, GetLastError(), lstrlenW(upper_case) + 1);
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
/* crashes on native */
if(0)
ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), (void*)1, NULL, 0);
test_lcmapstring_unicode(LCMapStringEx_wrapper, "LCMapStringEx:");
}
struct neutralsublang_name_t {
WCHAR name[3];
LCID lcid;
int todo;
};
static const struct neutralsublang_name_t neutralsublang_names[] = {
{ {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
{ {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
{ {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
{ {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
{ {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT), 1 },
{ {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 1 },
{ {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
{ {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
{ {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
{ {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
{ {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
{ {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
{ {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
{ {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 1 },
{ {0} }
};
static void test_LocaleNameToLCID(void)
{
LCID lcid;
INT ret;
WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
static const WCHAR enW[] = {'e','n',0};
if (!pLocaleNameToLCID)
{
@ -1664,27 +1874,65 @@ static void test_LocaleNames(void)
/* special cases */
buffer[0] = 0;
SetLastError(0xdeadbeef);
lcid = pLocaleNameToLCID(LOCALE_NAME_USER_DEFAULT, 0);
ok(lcid == GetUserDefaultLCID() || broken(GetLastError() == ERROR_INVALID_PARAMETER /* Vista */),
"Expected lcid == %08x, got %08x, error %d\n", lcid, GetUserDefaultLCID(), GetLastError());
"Expected lcid == %08x, got %08x, error %d\n", GetUserDefaultLCID(), lcid, GetLastError());
ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
buffer[0] = 0;
SetLastError(0xdeadbeef);
lcid = pLocaleNameToLCID(LOCALE_NAME_SYSTEM_DEFAULT, 0);
todo_wine ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected lcid != 0, got %08x, error %d\n", lcid, GetLastError());
ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected lcid == 0, got %08x, error %d\n", lcid, GetLastError());
ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
buffer[0] = 0;
SetLastError(0xdeadbeef);
lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
/* bad name */
SetLastError(0xdeadbeef);
lcid = pLocaleNameToLCID(fooW, 0);
ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected lcid == 0, got got %08x, error %d\n", lcid, GetLastError());
/* english neutral name */
lcid = pLocaleNameToLCID(enW, 0);
ok(lcid == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) ||
broken(lcid == 0) /* Vista */, "got 0x%04x\n", lcid);
if (lcid)
{
const struct neutralsublang_name_t *ptr = neutralsublang_names;
while (*ptr->name)
{
lcid = pLocaleNameToLCID(ptr->name, 0);
if (ptr->todo)
todo_wine
ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
else
ok(lcid == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n",
wine_dbgstr_w(ptr->name), lcid, ptr->lcid);
*buffer = 0;
ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
ok(lstrcmpW(ptr->name, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
ptr++;
}
}
}
/* this requires collation table patch to make it MS compatible */
@ -3140,6 +3388,173 @@ static void test_IdnToUnicode(void)
}
}
static void test_GetLocaleInfoEx(void)
{
static const WCHAR enW[] = {'e','n',0};
WCHAR bufferW[80];
INT ret;
if (!pGetLocaleInfoEx)
{
win_skip("GetLocaleInfoEx not supported\n");
return;
}
ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret || broken(ret == 0) /* Vista */, "got %d\n", ret);
if (ret)
{
static const WCHAR statesW[] = {'U','n','i','t','e','d',' ','S','t','a','t','e','s',0};
static const WCHAR dummyW[] = {'d','u','m','m','y',0};
static const WCHAR enusW[] = {'e','n','-','U','S',0};
static const WCHAR usaW[] = {'U','S','A',0};
static const WCHAR enuW[] = {'E','N','U',0};
const struct neutralsublang_name_t *ptr = neutralsublang_names;
DWORD val;
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enW), "got %s\n", wine_dbgstr_w(bufferW));
SetLastError(0xdeadbeef);
ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, bufferW, 2);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, %d\n", ret, GetLastError());
SetLastError(0xdeadbeef);
ret = pGetLocaleInfoEx(enW, LOCALE_SNAME, NULL, 0);
ok(ret == 3 && GetLastError() == 0xdeadbeef, "got %d, %d\n", ret, GetLastError());
ret = pGetLocaleInfoEx(enusW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enusW), "got %s\n", wine_dbgstr_w(bufferW));
ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVCTRYNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, usaW), "got %s\n", wine_dbgstr_w(bufferW));
ret = pGetLocaleInfoEx(enW, LOCALE_SABBREVLANGNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, enuW), "got %s\n", wine_dbgstr_w(bufferW));
ret = pGetLocaleInfoEx(enW, LOCALE_SCOUNTRY, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret == lstrlenW(bufferW)+1, "got %d\n", ret);
ok(!lstrcmpW(bufferW, statesW), "got %s\n", wine_dbgstr_w(bufferW));
bufferW[0] = 0;
SetLastError(0xdeadbeef);
ret = pGetLocaleInfoEx(dummyW, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
while (*ptr->name)
{
val = 0;
pGetLocaleInfoEx(ptr->name, LOCALE_ILANGUAGE|LOCALE_RETURN_NUMBER, (WCHAR*)&val, sizeof(val)/sizeof(WCHAR));
if (ptr->todo)
todo_wine
ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
else
ok(val == ptr->lcid, "%s: got wrong lcid 0x%04x, expected 0x%04x\n", wine_dbgstr_w(ptr->name), val, ptr->lcid);
bufferW[0] = 0;
ret = pGetLocaleInfoEx(ptr->name, LOCALE_SNAME, bufferW, sizeof(bufferW)/sizeof(WCHAR));
ok(ret == lstrlenW(bufferW)+1, "%s: got ret value %d\n", wine_dbgstr_w(ptr->name), ret);
ok(!lstrcmpW(bufferW, ptr->name), "%s: got wrong LOCALE_SNAME %s\n", wine_dbgstr_w(ptr->name), wine_dbgstr_w(bufferW));
ptr++;
}
}
}
static void test_IsValidLocaleName(void)
{
static const WCHAR enusW[] = {'e','n','-','U','S',0};
static const WCHAR zzW[] = {'z','z',0};
static const WCHAR zzzzW[] = {'z','z','-','Z','Z',0};
BOOL ret;
if (!pIsValidLocaleName)
{
win_skip("IsValidLocaleName not supported\n");
return;
}
ret = pIsValidLocaleName(enusW);
ok(ret, "IsValidLocaleName failed\n");
ret = pIsValidLocaleName(zzW);
ok(!ret, "IsValidLocaleName should have failed\n");
ret = pIsValidLocaleName(zzzzW);
ok(!ret, "IsValidLocaleName should have failed\n");
}
static void test_CompareStringOrdinal(void)
{
INT ret;
WCHAR test1[] = { 't','e','s','t',0 };
WCHAR test2[] = { 'T','e','S','t',0 };
WCHAR test3[] = { 't','e','s','t','3',0 };
WCHAR null1[] = { 'a',0,'a',0 };
WCHAR null2[] = { 'a',0,'b',0 };
WCHAR bills1[] = { 'b','i','l','l','\'','s',0 };
WCHAR bills2[] = { 'b','i','l','l','s',0 };
WCHAR coop1[] = { 'c','o','-','o','p',0 };
WCHAR coop2[] = { 'c','o','o','p',0 };
WCHAR nonascii1[] = { 0x0102,0 };
WCHAR nonascii2[] = { 0x0201,0 };
if (!pCompareStringOrdinal)
{
win_skip("CompareStringOrdinal not supported\n");
return;
}
/* Check errors */
SetLastError(0xdeadbeef);
ret = pCompareStringOrdinal(NULL, 0, NULL, 0, FALSE);
ok(!ret, "Got %u, expected 0\n", ret);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
ret = pCompareStringOrdinal(test1, -1, NULL, 0, FALSE);
ok(!ret, "Got %u, expected 0\n", ret);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
ret = pCompareStringOrdinal(NULL, 0, test1, -1, FALSE);
ok(!ret, "Got %u, expected 0\n", ret);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Got %x, expected %x\n", GetLastError(), ERROR_INVALID_PARAMETER);
/* Check case */
ret = pCompareStringOrdinal(test1, -1, test1, -1, FALSE);
ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
ret = pCompareStringOrdinal(test1, -1, test2, -1, FALSE);
ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
ret = pCompareStringOrdinal(test2, -1, test1, -1, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(test1, -1, test2, -1, TRUE);
ok(ret == CSTR_EQUAL, "Got %u, expected %u\n", ret, CSTR_EQUAL);
/* Check different sizes */
ret = pCompareStringOrdinal(test1, 3, test2, -1, TRUE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(test1, -1, test2, 3, TRUE);
ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
/* Check null character */
ret = pCompareStringOrdinal(null1, 3, null2, 3, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(null1, 3, null2, 3, TRUE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(test1, 5, test3, 5, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(test1, 4, test1, 5, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
/* Check ordinal behaviour */
ret = pCompareStringOrdinal(bills1, -1, bills2, -1, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(coop2, -1, coop1, -1, FALSE);
ok(ret == CSTR_GREATER_THAN, "Got %u, expected %u\n", ret, CSTR_GREATER_THAN);
ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, FALSE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
ret = pCompareStringOrdinal(nonascii1, -1, nonascii2, -1, TRUE);
ok(ret == CSTR_LESS_THAN, "Got %u, expected %u\n", ret, CSTR_LESS_THAN);
}
START_TEST(locale)
{
InitFunctionPointers();
@ -3148,6 +3563,7 @@ START_TEST(locale)
test_EnumDateFormatsA();
test_GetLocaleInfoA();
test_GetLocaleInfoW();
test_GetLocaleInfoEx();
test_GetTimeFormatA();
test_GetDateFormatA();
test_GetDateFormatW();
@ -3156,7 +3572,8 @@ START_TEST(locale)
test_CompareStringA();
test_LCMapStringA();
test_LCMapStringW();
test_LocaleNames();
test_LCMapStringEx();
test_LocaleNameToLCID();
test_FoldStringA();
test_FoldStringW();
test_ConvertDefaultLocale();
@ -3170,6 +3587,8 @@ START_TEST(locale)
test_IdnToNameprepUnicode();
test_IdnToAscii();
test_IdnToUnicode();
test_IsValidLocaleName();
test_CompareStringOrdinal();
/* this requires collation table patch to make it MS compatible */
if (0) test_sorting();
}

View file

@ -476,12 +476,16 @@ static void testGetDllDirectory(void)
ok(bufferW[0] == 0 || /* XP, 2003 */
broken(bufferW[0] == 'A'), "i=%d, Buffer overflow\n", i);
/* no buffer, but too short length */
ret = pGetDllDirectoryA(length, NULL);
ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
if (0)
{
/* crashes on win8 */
/* no buffer, but too short length */
ret = pGetDllDirectoryA(length, NULL);
ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
ret = pGetDllDirectoryW(length, NULL);
ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
ret = pGetDllDirectoryW(length, NULL);
ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
}
}
/* unset whatever we did so following tests won't be affected */

View file

@ -798,6 +798,113 @@ static DWORD CALLBACK serverThreadMain4(LPVOID arg)
return 0;
}
static int completion_called;
static DWORD completion_errorcode;
static DWORD completion_num_bytes;
static LPOVERLAPPED completion_lpoverlapped;
static VOID WINAPI completion_routine(DWORD errorcode, DWORD num_bytes, LPOVERLAPPED lpoverlapped)
{
completion_called++;
completion_errorcode = errorcode;
completion_num_bytes = num_bytes;
completion_lpoverlapped = lpoverlapped;
SetEvent(lpoverlapped->hEvent);
}
/** Trivial byte echo server - uses ReadFileEx/WriteFileEx */
static DWORD CALLBACK serverThreadMain5(LPVOID arg)
{
int i;
HANDLE hEvent;
trace("serverThreadMain5\n");
/* Set up a simple echo server */
hnp = CreateNamedPipe(PIPENAME "serverThreadMain5", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
hEvent = CreateEvent(NULL, /* security attribute */
TRUE, /* manual reset event */
FALSE, /* initial state */
NULL); /* name */
ok(hEvent != NULL, "CreateEvent\n");
for (i = 0; i < NB_SERVER_LOOPS; i++) {
char buf[512];
DWORD readden;
DWORD success;
OVERLAPPED oOverlap;
DWORD err;
memset(&oOverlap, 0, sizeof(oOverlap));
oOverlap.hEvent = hEvent;
/* Wait for client to connect */
trace("Server calling ConnectNamedPipe...\n");
success = ConnectNamedPipe(hnp, NULL);
err = GetLastError();
ok(success || (err == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed: %d\n", err);
trace("ConnectNamedPipe operation complete.\n");
/* Echo bytes once */
memset(buf, 0, sizeof(buf));
trace("Server reading...\n");
completion_called = 0;
ResetEvent(hEvent);
success = ReadFileEx(hnp, buf, sizeof(buf), &oOverlap, completion_routine);
trace("Server ReadFileEx returned...\n");
ok(success, "ReadFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
trace("ReadFileEx returned.\n");
if (success) {
DWORD ret;
do {
ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
} while (ret == WAIT_IO_COMPLETION);
ok(ret == 0, "wait ReadFileEx returned %x\n", ret);
}
ok(completion_called == 1, "completion routine called %i times\n", completion_called);
ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
ok(completion_num_bytes != 0, "read 0 bytes\n");
ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
readden = completion_num_bytes;
trace("Server done reading.\n");
trace("Server writing...\n");
completion_called = 0;
ResetEvent(hEvent);
success = WriteFileEx(hnp, buf, readden, &oOverlap, completion_routine);
trace("Server WriteFileEx returned...\n");
ok(success, "WriteFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx return\n");
trace("overlapped WriteFile returned.\n");
if (success) {
DWORD ret;
do {
ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
} while (ret == WAIT_IO_COMPLETION);
ok(ret == 0, "wait WriteFileEx returned %x\n", ret);
}
trace("Server done writing.\n");
ok(completion_called == 1, "completion routine called %i times\n", completion_called);
ok(completion_errorcode == ERROR_SUCCESS, "completion routine got error %d\n", completion_errorcode);
ok(completion_num_bytes == readden, "read %i bytes wrote %i\n", readden, completion_num_bytes);
ok(completion_lpoverlapped == &oOverlap, "got wrong overlapped pointer %p\n", completion_lpoverlapped);
/* finish this connection, wait for next one */
ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
}
return 0;
}
static void exercizeServer(const char *pipename, HANDLE serverThread)
{
int i;
@ -891,6 +998,12 @@ static void test_NamedPipe_2(void)
ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
exercizeServer(PIPENAME "serverThreadMain4", serverThread);
/* Try server #5 */
SetLastError(0xdeadbeef);
serverThread = CreateThread(NULL, 0, serverThreadMain5, 0, 0, &serverThreadId);
ok(serverThread != NULL, "CreateThread failed: %d\n", GetLastError());
exercizeServer(PIPENAME "serverThreadMain5", serverThread);
ok(SetEvent( alarm_event ), "SetEvent\n");
CloseHandle( alarm_event );
trace("test_NamedPipe_2 returning\n");
@ -1637,6 +1750,116 @@ static void test_NamedPipeHandleState(void)
CloseHandle(server);
}
static void test_readfileex_pending(void)
{
HANDLE server, client, event;
BOOL ret;
DWORD err, wait, num_bytes;
OVERLAPPED overlapped;
char read_buf[1024];
char write_buf[1024];
const char test_string[] = "test";
int i;
server = CreateNamedPipe(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
/* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
event = CreateEventA(NULL, TRUE, FALSE, NULL);
ok(event != NULL, "CreateEventA failed\n");
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = event;
ret = ConnectNamedPipe(server, &overlapped);
err = GetLastError();
ok(ret == FALSE, "ConnectNamedPipe succeeded\n");
ok(err == ERROR_IO_PENDING, "ConnectNamedPipe set error %i\n", err);
wait = WaitForSingleObject(event, 0);
ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
wait = WaitForSingleObject(event, 0);
ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
/* Start a read that can't complete immediately. */
completion_called = 0;
ResetEvent(event);
ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
ok(ret == TRUE, "WriteFile failed\n");
ok(num_bytes == strlen(test_string), "only %i bytes written\n", num_bytes);
ok(completion_called == 0, "completion routine called during WriteFile\n");
wait = WaitForSingleObjectEx(event, 0, TRUE);
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
ok(completion_called == 1, "completion not called after writing pipe\n");
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_num_bytes == strlen(test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
ok(!memcmp(test_string, read_buf, strlen(test_string)), "ReadFileEx read wrong bytes\n");
/* Make writes until the pipe is full and the write fails */
memset(write_buf, 0xaa, sizeof(write_buf));
for (i=0; i<256; i++)
{
completion_called = 0;
ResetEvent(event);
ret = WriteFileEx(server, write_buf, sizeof(write_buf), &overlapped, completion_routine);
err = GetLastError();
ok(completion_called == 0, "completion routine called during WriteFileEx\n");
wait = WaitForSingleObjectEx(event, 0, TRUE);
if (wait == WAIT_TIMEOUT)
/* write couldn't complete immediately, presumably the pipe is full */
break;
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
}
ok(ret == TRUE, "WriteFileEx failed, err=%i\n", err);
ok(completion_called == 0, "completion routine called but wait timed out\n");
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
/* free up some space in the pipe */
ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
ok(ret == TRUE, "ReadFile failed\n");
ok(completion_called == 0, "completion routine called during ReadFile\n");
wait = WaitForSingleObjectEx(event, 0, TRUE);
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
ok(completion_called == 1, "completion routine not called\n");
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
CloseHandle(client);
CloseHandle(server);
CloseHandle(event);
}
START_TEST(pipe)
{
HMODULE hmod;
@ -1656,4 +1879,5 @@ START_TEST(pipe)
test_impersonation();
test_overlapped();
test_NamedPipeHandleState();
test_readfileex_pending();
}

View file

@ -298,18 +298,6 @@ static void doChild(const char* file, const char* option)
childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
}
childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
#if 0
int argcW;
WCHAR** argvW;
/* this is part of shell32... and should be tested there */
argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
for (i = 0; i < argcW; i++)
{
childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
}
#endif
childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
/* output of environment (Ansi) */

View file

@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define _WIN32_WINNT 0x502
#define _WIN32_WINNT 0x600
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@ -37,6 +37,15 @@ static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
static void test_signalandwait(void)
{
@ -704,11 +713,11 @@ static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
static void test_timer_queue(void)
{
HANDLE q, t1, t2, t3, t4, t5;
int n1, n2, n3, n4, n5;
HANDLE q, t0, t1, t2, t3, t4, t5;
int n0, n1, n2, n3, n4, n5;
struct timer_queue_data1 d1, d2, d3, d4;
HANDLE e, et1, et2;
BOOL ret;
BOOL ret, ret0;
if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
|| !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
@ -731,6 +740,18 @@ static void test_timer_queue(void)
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
/* Not called. */
t0 = NULL;
n0 = 0;
ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0,
300, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t0 != NULL, "CreateTimerQueueTimer\n");
ret0 = pDeleteTimerQueueTimer(q, t0, NULL);
ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
broken(ret0), /* Win 2000 & XP & 2003 */
"DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
/* Called once. */
t1 = NULL;
n1 = 0;
@ -784,10 +805,12 @@ static void test_timer_queue(void)
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueEx\n");
ok(n1 == 1, "Timer callback 1\n");
ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
ok(n4 == 0, "Timer callback 4\n");
ok(n5 == 1, "Timer callback 5\n");
todo_wine
ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
/* Test synchronous deletion of the timer/queue with event trigger. */
e = CreateEvent(NULL, TRUE, FALSE, NULL);
@ -1121,6 +1144,211 @@ static void test_WaitForMultipleObjects(void)
if (maxevents[i]) CloseHandle(maxevents[i]);
}
static BOOL g_initcallback_ret, g_initcallback_called;
static void *g_initctxt;
static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
{
g_initcallback_called = TRUE;
/* zero bit set means here that initialization is taking place - initialization locked */
ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
return g_initcallback_ret;
}
static void test_initonce(void)
{
INIT_ONCE initonce;
BOOL ret, pending;
if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
{
skip("one-time initialization API not supported\n");
return;
}
/* blocking initialization with callback */
initonce.Ptr = (void*)0xdeadbeef;
pInitOnceInitialize(&initonce);
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
/* initialisation completed successfully */
g_initcallback_ret = TRUE;
g_initctxt = NULL;
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
ok(ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
/* so it's been called already so won't be called again */
g_initctxt = NULL;
g_initcallback_called = FALSE;
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
ok(ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
pInitOnceInitialize(&initonce);
g_initcallback_called = FALSE;
/* 2 lower order bits should never be used, you'll get a crash in result */
g_initctxt = (void*)0xFFFFFFF0;
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
ok(ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
/* callback failed */
g_initcallback_ret = FALSE;
g_initcallback_called = FALSE;
g_initctxt = NULL;
pInitOnceInitialize(&initonce);
ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
ok(!ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
ok(g_initcallback_called, "got %d\n", g_initcallback_called);
/* blocking initialzation without a callback */
pInitOnceInitialize(&initonce);
g_initctxt = NULL;
pending = FALSE;
ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
ok(ret, "got wrong ret value %d\n", ret);
ok(pending, "got %d\n", pending);
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
/* another attempt to begin initialization with block a single thread */
g_initctxt = NULL;
pending = 0xf;
ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
ok(!ret, "got wrong ret value %d\n", ret);
ok(pending == 0xf, "got %d\n", pending);
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
ok(g_initctxt == NULL, "got %p\n", g_initctxt);
g_initctxt = (void*)0xdeadbee0;
ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
ok(!ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
/* once failed already */
g_initctxt = (void*)0xdeadbee0;
ret = pInitOnceComplete(&initonce, 0, g_initctxt);
ok(ret, "got wrong ret value %d\n", ret);
ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
}
static CONDITION_VARIABLE buffernotempty,buffernotfull;
static CRITICAL_SECTION buffercrit;
static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
static LONG bufferlen,totalproduced,totalconsumed;
static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
#define BUFFER_SIZE 10
static DWORD WINAPI condvar_producer(LPVOID x) {
while (1) {
Sleep(rand() % 10);
EnterCriticalSection(&buffercrit);
while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
condvar_producer_sleepcnt++;
if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, 2000))
condvar_sleeperr = TRUE;
}
if (condvar_stop) {
LeaveCriticalSection(&buffercrit);
break;
}
bufferlen++;
totalproduced++;
LeaveCriticalSection(&buffercrit);
pWakeConditionVariable(&buffernotempty);
}
return 0;
}
static DWORD WINAPI condvar_consumer(LPVOID x) {
DWORD *cnt = (DWORD*)x;
while (1) {
EnterCriticalSection(&buffercrit);
while ((bufferlen == 0) && !condvar_stop) {
condvar_consumer_sleepcnt++;
if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, 2000))
condvar_sleeperr = TRUE;
}
if (condvar_stop && (bufferlen == 0)) {
LeaveCriticalSection(&buffercrit);
break;
}
bufferlen--;
totalconsumed++;
(*cnt)++;
LeaveCriticalSection(&buffercrit);
pWakeConditionVariable(&buffernotfull);
Sleep(rand() % 10);
}
return 0;
}
static void test_condvars(void)
{
HANDLE hp1,hp2,hc1,hc2;
DWORD dummy;
DWORD cnt1,cnt2;
if (!pInitializeConditionVariable) {
/* function is not yet in XP, only in newer Windows */
/* and not yet implemented in Wine for some days/weeks */
todo_wine win_skip("no condition variable support.\n");
return;
}
/* Implement a producer / consumer scheme with non-full / non-empty triggers */
pInitializeConditionVariable(&buffernotfull);
pInitializeConditionVariable(&buffernotempty);
InitializeCriticalSection(&buffercrit);
bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = 0;
hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
/* Limit run to 0.5 seconds. */
Sleep(500);
/* tear down start */
condvar_stop = TRUE;
/* final wake up call */
pWakeAllConditionVariable (&buffernotfull);
pWakeAllConditionVariable (&buffernotempty);
WaitForSingleObject(hp1, 1000);
WaitForSingleObject(hp2, 1000);
WaitForSingleObject(hc1, 1000);
WaitForSingleObject(hc2, 1000);
ok(totalconsumed == totalproduced,
"consumed %d != produced %d\n", totalconsumed, totalproduced);
ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
/* Checking cnt1 - cnt2 for non-0 would be not good, the case where
* one consumer does not get anything to do is possible. */
trace("produced %d, c1 %d, c2 %d\n", totalproduced, cnt1, cnt2);
/* The sleeps of the producer or consumer should not go above 100* produced count,
* otherwise the implementation does not sleep correctly. But yet again, this is
* not hard defined. */
trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
}
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
@ -1133,6 +1361,14 @@ START_TEST(sync)
pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
test_signalandwait();
test_mutex();
@ -1144,4 +1380,6 @@ START_TEST(sync)
test_timer_queue();
test_WaitForSingleObject();
test_WaitForMultipleObjects();
test_initonce();
test_condvars();
}

View file

@ -961,16 +961,19 @@ static void test_SetThreadContext(void)
ctx.ContextFlags = CONTEXT_FULL;
SetLastError(0xdeadbeef);
ret = GetThreadContext( thread, &ctx );
ok( !ret, "GetThreadContext succeeded\n" );
ok( GetLastError() == ERROR_GEN_FAILURE || broken(GetLastError() == ERROR_INVALID_HANDLE), /* win2k */
"wrong error %u\n", GetLastError() );
ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
(!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
broken(ret), /* 32bit application on NT 5.x 64bit */
"got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
ret, GetLastError() );
SetLastError(0xdeadbeef);
ret = SetThreadContext( thread, &ctx );
ok( !ret, "SetThreadContext succeeded\n" );
ok( GetLastError() == ERROR_GEN_FAILURE || GetLastError() == ERROR_ACCESS_DENIED ||
broken(GetLastError() == ERROR_INVALID_HANDLE), /* win2k */
"wrong error %u\n", GetLastError() );
ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
(!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
broken(ret), /* 32bit application on NT 5.x 64bit */
"got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
ret, GetLastError() );
CloseHandle( thread );
}

View file

@ -23,27 +23,24 @@
#include "wine/test.h"
#include "winbase.h"
typedef HANDLE (WINAPI *fnCreateWaitableTimerA)( SECURITY_ATTRIBUTES*, BOOL, LPSTR );
typedef BOOL (WINAPI *fnSetWaitableTimer)(HANDLE, LARGE_INTEGER*, LONG, PTIMERAPCROUTINE, LPVOID, BOOL);
static void test_timer(void)
{
HANDLE (WINAPI *pCreateWaitableTimerA)( SECURITY_ATTRIBUTES*, BOOL, LPSTR );
BOOL (WINAPI *pSetWaitableTimer)(HANDLE, LARGE_INTEGER*, LONG, PTIMERAPCROUTINE, LPVOID, BOOL);
HMODULE hker = GetModuleHandle("kernel32");
fnCreateWaitableTimerA pCreateWaitableTimerA;
fnSetWaitableTimer pSetWaitableTimer;
HANDLE handle;
BOOL r;
LARGE_INTEGER due;
pCreateWaitableTimerA = (fnCreateWaitableTimerA) GetProcAddress( hker, "CreateWaitableTimerA");
pCreateWaitableTimerA = (void*)GetProcAddress( hker, "CreateWaitableTimerA");
if( !pCreateWaitableTimerA )
{
win_skip("CreateWaitableTimerA is not available\n");
return;
}
pSetWaitableTimer = (fnSetWaitableTimer) GetProcAddress( hker, "SetWaitableTimer");
pSetWaitableTimer = (void*)GetProcAddress( hker, "SetWaitableTimer");
if( !pSetWaitableTimer )
{
win_skip("SetWaitableTimer is not available\n");

View file

@ -18,31 +18,88 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Needed for PRODUCT_* defines and GetProductInfo() */
#define _WIN32_WINNT 0x0600
#include <assert.h>
#include "wine/test.h"
#include "winbase.h"
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
static BOOL (WINAPI * pVerifyVersionInfoA)(LPOSVERSIONINFOEXA, DWORD, DWORDLONG);
static ULONGLONG (WINAPI * pVerSetConditionMask)(ULONGLONG, DWORD, BYTE);
#define KERNEL32_GET_PROC(func) \
p##func = (void *)GetProcAddress(hKernel32, #func); \
if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
p##func = (void *)GetProcAddress(hKernel32, #func);
static void init_function_pointers(void)
{
HMODULE hKernel32;
pVerifyVersionInfoA = NULL;
pVerSetConditionMask = NULL;
hKernel32 = GetModuleHandleA("kernel32.dll");
assert(hKernel32);
KERNEL32_GET_PROC(GetProductInfo);
KERNEL32_GET_PROC(VerifyVersionInfoA);
KERNEL32_GET_PROC(VerSetConditionMask);
}
static void test_GetProductInfo(void)
{
DWORD product;
DWORD res;
DWORD table[] = {9,8,7,6,
7,0,0,0,
6,2,0,0,
6,1,2,0,
6,1,1,0,
6,1,0,2,
6,1,0,0,
6,0,3,0,
6,0,2,0,
6,0,1,5,
6,0,1,0,
6,0,0,0,
5,3,0,0,
5,2,0,0,
5,1,0,0,
5,0,0,0,
0};
DWORD *entry = table;
if (!pGetProductInfo)
{
/* Not present before Vista */
win_skip("GetProductInfo() not available\n");
return;
}
while (*entry)
{
/* SetLastError() / GetLastError(): value is untouched */
product = 0xdeadbeef;
SetLastError(0xdeadbeef);
res = pGetProductInfo(entry[0], entry[1], entry[2], entry[3], &product);
if (entry[0] >= 6)
ok(res && (product > PRODUCT_UNDEFINED) && (product <= PRODUCT_PROFESSIONAL_WMC),
"got %d and 0x%x (expected TRUE and a valid PRODUCT_* value)\n", res, product);
else
ok(!res && !product && (GetLastError() == 0xdeadbeef),
"got %d and 0x%x with 0x%x (expected FALSE and PRODUCT_UNDEFINED with LastError untouched)\n",
res, product, GetLastError());
entry+= 4;
}
/* NULL pointer is not a problem */
SetLastError(0xdeadbeef);
res = pGetProductInfo(6, 1, 0, 0, NULL);
ok( (!res) && (GetLastError() == 0xdeadbeef),
"got %d with 0x%x (expected FALSE with LastError untouched\n", res, GetLastError());
}
static void test_GetVersionEx(void)
{
OSVERSIONINFOA infoA;
@ -95,8 +152,6 @@ static void test_GetVersionEx(void)
ok(ret ||
broken(ret == 0), /* win95 */
"Expected GetVersionExA to succeed\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
}
static void test_VerifyVersionInfo(void)
@ -292,6 +347,7 @@ START_TEST(version)
{
init_function_pointers();
test_GetProductInfo();
test_GetVersionEx();
test_VerifyVersionInfo();
}

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,27 @@
#include "winbase.h"
#include "winioctl.h"
#include <stdio.h>
#include "wine/ddk/ntddcdvd.h"
#include <pshpack1.h>
struct COMPLETE_DVD_LAYER_DESCRIPTOR
{
DVD_DESCRIPTOR_HEADER Header;
DVD_LAYER_DESCRIPTOR Descriptor;
UCHAR Padding;
};
#include <poppack.h>
C_ASSERT(sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR) == 22);
#include <pshpack1.h>
struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR
{
DVD_DESCRIPTOR_HEADER Header;
DVD_MANUFACTURER_DESCRIPTOR Descriptor;
UCHAR Padding;
};
#include <poppack.h>
C_ASSERT(sizeof(struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR) == 2053);
static HINSTANCE hdll;
static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
@ -732,6 +753,175 @@ static void test_GetVolumePathNamesForVolumeNameW(void)
ok(error == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND got %u\n", error);
}
static void test_dvd_read_structure(HANDLE handle)
{
int i;
DWORD nbBytes;
BOOL ret;
DVD_READ_STRUCTURE dvdReadStructure;
DVD_LAYER_DESCRIPTOR dvdLayerDescriptor;
struct COMPLETE_DVD_LAYER_DESCRIPTOR completeDvdLayerDescriptor;
DVD_COPYRIGHT_DESCRIPTOR dvdCopyrightDescriptor;
struct COMPLETE_DVD_MANUFACTURER_DESCRIPTOR completeDvdManufacturerDescriptor;
dvdReadStructure.BlockByteOffset.QuadPart = 0;
dvdReadStructure.SessionId = 0;
dvdReadStructure.LayerNumber = 0;
/* DvdPhysicalDescriptor */
dvdReadStructure.Format = 0;
SetLastError(0xdeadbeef);
/* Test whether this ioctl is supported */
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
&completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
if ((!ret && GetLastError() == ERROR_INVALID_FUNCTION)
|| (!ret && GetLastError() == ERROR_NOT_SUPPORTED))
{
skip("IOCTL_DVD_READ_STRUCTURE not supported\n");
return;
}
ok(ret || broken(GetLastError() == ERROR_NOT_READY) || broken(GetLastError() == ERROR_INVALID_PARAMETER),
"IOCTL_DVD_READ_STRUCTURE (DvdPhysicalDescriptor) failed, last error = %u\n", GetLastError());
if(!ret)
return;
/* Confirm there is always a header before the actual data */
ok( completeDvdLayerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdLayerDescriptor.Header.Length);
ok( completeDvdLayerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[0]);
ok( completeDvdLayerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[1]);
/* TODO: Also check completeDvdLayerDescriptor.Descriptor content (via IOCTL_SCSI_PASS_THROUGH_DIRECT ?) */
/* Insufficient output buffer */
for(i=0; i<sizeof(DVD_DESCRIPTOR_HEADER); i++)
{
SetLastError(0xdeadbeef);
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
&completeDvdLayerDescriptor, i, &nbBytes, NULL);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,"IOCTL_DVD_READ_STRUCTURE should fail with small buffer\n");
}
SetLastError(0xdeadbeef);
/* On newer version, an output buffer of sizeof(DVD_READ_STRUCTURE) size fails.
I think this is to force developers to realize that there is a header before the actual content */
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
&dvdLayerDescriptor, sizeof(DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER) || broken(ret) /* < Win7 */,
"IOCTL_DVD_READ_STRUCTURE should have failed\n");
SetLastError(0xdeadbeef);
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, NULL, sizeof(DVD_READ_STRUCTURE),
&completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
"IOCTL_DVD_READ_STRUCTURE should have failed\n");
/* Test wrong input parameters */
for(i=0; i<sizeof(DVD_READ_STRUCTURE); i++)
{
SetLastError(0xdeadbeef);
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, i,
&completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
"IOCTL_DVD_READ_STRUCTURE should have failed\n");
}
/* DvdCopyrightDescriptor */
dvdReadStructure.Format = 1;
SetLastError(0xdeadbeef);
/* Strangely, with NULL lpOutBuffer, last error is insufficient buffer, not invalid parameter as we could expect */
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
NULL, sizeof(DVD_COPYRIGHT_DESCRIPTOR), &nbBytes, NULL);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
for(i=0; i<sizeof(DVD_COPYRIGHT_DESCRIPTOR); i++)
{
SetLastError(0xdeadbeef);
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
&dvdCopyrightDescriptor, i, &nbBytes, NULL);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
}
/* DvdManufacturerDescriptor */
dvdReadStructure.Format = 4;
SetLastError(0xdeadbeef);
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
&completeDvdManufacturerDescriptor, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
ok(ret || broken(GetLastError() == ERROR_NOT_READY),
"IOCTL_DVD_READ_STRUCTURE (DvdManufacturerDescriptor) failed, last error = %u\n", GetLastError());
if(!ret)
return;
/* Confirm there is always a header before the actual data */
ok( completeDvdManufacturerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdManufacturerDescriptor.Header.Length);
ok( completeDvdManufacturerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[0]);
ok( completeDvdManufacturerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdManufacturerDescriptor.Header.Reserved[1]);
SetLastError(0xdeadbeef);
/* Basic parameter check */
ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
NULL, sizeof(DVD_MANUFACTURER_DESCRIPTOR), &nbBytes, NULL);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "IOCTL_DVD_READ_STRUCTURE should have failed %d %u\n", ret, GetLastError());
}
static void test_cdrom_ioctl(void)
{
char drive_letter, drive_path[] = "A:\\", drive_full_path[] = "\\\\.\\A:";
DWORD bitmask;
HANDLE handle;
bitmask = GetLogicalDrives();
if(!bitmask)
{
trace("GetLogicalDrives failed : %u\n", GetLastError());
return;
}
for(drive_letter='A'; drive_letter<='Z'; drive_letter++)
{
if(!(bitmask & (1 << (drive_letter-'A') )))
continue;
drive_path[0] = drive_letter;
if(GetDriveTypeA(drive_path) != DRIVE_CDROM)
{
trace("Skipping %c:, not a CDROM drive.\n", drive_letter);
continue;
}
trace("Testing with %c:\n", drive_letter);
drive_full_path[4] = drive_letter;
handle = CreateFileA(drive_full_path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if(handle == INVALID_HANDLE_VALUE)
{
trace("Failed to open the device : %u\n", GetLastError());
continue;
}
/* Add your tests here */
test_dvd_read_structure(handle);
CloseHandle(handle);
}
}
START_TEST(volume)
{
hdll = GetModuleHandleA("kernel32.dll");
@ -758,4 +948,5 @@ START_TEST(volume)
test_disk_extents();
test_GetVolumePathNamesForVolumeNameA();
test_GetVolumePathNamesForVolumeNameW();
test_cdrom_ioctl();
}