* Sync with Wine 1.3.29.
svn path=/trunk/; revision=53966
STARTUPINFO si = { 0 };
HANDLE file;
FILETIME now;
+ BOOL ret;
GetModuleFileNameA(NULL, path, MAX_PATH);
strcat(path, ".manifest");
CloseHandle(file);
}
sprintf(cmdline, "\"%s\" %s manifest1", argv[0], argv[1]);
- ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
- &si, &pi) != 0, "Could not create process: %u\n", GetLastError());
+ ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "Could not create process: %u\n", GetLastError());
winetest_wait_child_process( pi.hProcess );
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
else
ok( !len, "bad length %d\n", len );
- SetLastError(0xdeadbeef);
+ SetLastError(0xdeadbeef);
len = GlobalGetAtomNameA( (ATOM)i, buf, 2);
- if (!len) /* the NT way */
- {
- ok(GetLastError() == (i ? ERROR_MORE_DATA : ERROR_INVALID_PARAMETER) ||
- GetLastError() == 0xdeadbeef, /* the Win 9x way */
- "wrong error conditions %u for %u\n", GetLastError(), i);
- }
- else /* the Win 9x way */
- {
- ok(GetLastError() == 0xdeadbeef,
- "wrong error conditions %u for %u\n", GetLastError(), i);
- }
+ ok(!len, "bad length %d\n", len);
+ ok(GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INVALID_PARAMETER,
+ "wrong error conditions %u for %u\n", GetLastError(), i);
}
memset( buf, '.', sizeof(buf) );
len = GlobalGetAtomNameA( atom, buf, 6 );
- ok( len == 0 ||
- len == 5, /* win9x */
- "bad length %d\n", len );
+ ok( len == 0, "bad length %d\n", len );
ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n");
if (unicode_OS)
{
memset(out, '.', sizeof(out));
SetLastError(0xdeadbeef);
len = GlobalGetAtomNameA(atom, out, 10);
- if (!len) /* the NT way */
- {
- ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%u instead of %u)\n", GetLastError(), ERROR_MORE_DATA);
- }
- else /* the Win9x way */
- {
- ok(GetLastError() == 0xdeadbeef, "wrong error code (%u instead of %u)\n", GetLastError(), 0xdeadbeef);
- }
+ ok(!len, "bad length %d\n", len);
+ ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%u instead of %u)\n", GetLastError(), ERROR_MORE_DATA);
for (i = 0; i < 9; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
/* ERROR_MORE_DATA is on nt3.51 sp5 */
if (i)
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
- GetLastError() == ERROR_MORE_DATA ||
- GetLastError() == 0xdeadbeef, /* the Win 9x way */
+ GetLastError() == ERROR_MORE_DATA,
"wrong error conditions %u for %u\n", GetLastError(), i);
else
ok(GetLastError() == ERROR_INVALID_PARAMETER ||
- GetLastError() == ERROR_MORE_DATA ||
- GetLastError() == 0xdeadbeef, /* the Win 9x way */
+ GetLastError() == ERROR_MORE_DATA,
"wrong error conditions %u for %u\n", GetLastError(), i);
}
/* test string limits & overflow */
/* ERROR_MORE_DATA is on nt3.51 sp5 */
ok(GetLastError() == ERROR_INVALID_PARAMETER ||
- GetLastError() == ERROR_MORE_DATA ||
- GetLastError() == 0xdeadbeef, /* the Win 9x way */
+ GetLastError() == ERROR_MORE_DATA,
"wrong error code (%u)\n", GetLastError());
if (unicode_OS)
if (status == WAIT_OBJECT_0 ) {
notified = TRUE;
- ret = FindNextChangeNotification(change);
+ FindNextChangeNotification(change);
}
ret = FindCloseChangeNotification(change);
ok( r == TRUE, "failed to remove dir\n");
}
-typedef BOOL (WINAPI *fnReadDirectoryChangesW)(HANDLE,LPVOID,DWORD,BOOL,DWORD,
+static BOOL (WINAPI *pReadDirectoryChangesW)(HANDLE,LPVOID,DWORD,BOOL,DWORD,
LPDWORD,LPOVERLAPPED,LPOVERLAPPED_COMPLETION_ROUTINE);
-fnReadDirectoryChangesW pReadDirectoryChangesW;
static void test_readdirectorychanges(void)
{
ok( r == TRUE, "failed to remove directory\n");
}
+static void CALLBACK readdirectorychanges_cr(DWORD error, DWORD len, LPOVERLAPPED ov)
+{
+ ok(error == 0, "ReadDirectoryChangesW error %d\n", error);
+ ok(ov->hEvent == (void*)0xdeadbeef, "hEvent should not have changed\n");
+}
+
+static void test_readdirectorychanges_cr(void)
+{
+ static const WCHAR szBoo[] = { '\\','b','o','o','\\',0 };
+ static const WCHAR szDir[] = { 'd','i','r',0 };
+ static const WCHAR szFile[] = { 'f','i','l','e',0 };
+ static const WCHAR szBackslash[] = { '\\',0 };
+
+ WCHAR path[MAX_PATH], file[MAX_PATH], dir[MAX_PATH], sub_file[MAX_PATH];
+ FILE_NOTIFY_INFORMATION fni[1024], *fni_next;
+ OVERLAPPED ov;
+ HANDLE hdir, hfile;
+ NTSTATUS r;
+
+ if (!pReadDirectoryChangesW)
+ {
+ win_skip("ReadDirectoryChangesW is not available\n");
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ r = GetTempPathW(MAX_PATH, path);
+ if (!r && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("GetTempPathW is not implemented\n");
+ return;
+ }
+ ok(r != 0, "temp path failed\n");
+ if (!r)
+ return;
+
+ lstrcatW(path, szBoo);
+ lstrcpyW(dir, path);
+ lstrcatW(dir, szDir);
+ lstrcpyW(file, path);
+ lstrcatW(file, szFile);
+ lstrcpyW(sub_file, dir);
+ lstrcatW(sub_file, szBackslash);
+ lstrcatW(sub_file, szFile);
+
+ DeleteFileW(file);
+ RemoveDirectoryW(dir);
+ RemoveDirectoryW(path);
+
+ r = CreateDirectoryW(path, NULL);
+ ok(r == TRUE, "failed to create directory\n");
+
+ hdir = CreateFileW(path, GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
+ ok(hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
+
+ memset(&ov, 0, sizeof(ov));
+ ov.hEvent = (void*)0xdeadbeef;
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ hfile = CreateFileW(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ ok(hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
+ CloseHandle(hfile);
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive file creation event\n");
+ ok(fni->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni->Action == FILE_ACTION_ADDED, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ /* This event will not be reported */
+ r = CreateDirectoryW(dir, NULL);
+ ok(r == TRUE, "failed to create directory\n");
+
+ r = MoveFileW(file, sub_file);
+ ok(r == TRUE, "failed to move file\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive file move event\n");
+ ok(fni->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni->Action == FILE_ACTION_REMOVED, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = MoveFileW(sub_file, file);
+ ok(r == TRUE, "failed to move file\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive file move event\n");
+ ok(fni->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni->Action == FILE_ACTION_ADDED, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_FILE_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = DeleteFileW(file);
+ ok(r == TRUE, "failed to delete file\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive file removal event\n");
+ ok(fni->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni->Action == FILE_ACTION_REMOVED, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+
+ CloseHandle(hdir);
+
+ hdir = CreateFileW(path, GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
+ ok(hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
+
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_DIR_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = MoveFileW(dir, file);
+ ok(r == TRUE, "failed to move directory\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive directory move event\n");
+ if (fni->Action == FILE_ACTION_RENAMED_OLD_NAME)
+ {
+ ok(fni->Action == FILE_ACTION_RENAMED_OLD_NAME, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+ ok(fni->NextEntryOffset != 0, "no next entry in movement event\n");
+ fni_next = (FILE_NOTIFY_INFORMATION*)((char*)fni+fni->NextEntryOffset);
+ ok(fni_next->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni_next->Action == FILE_ACTION_RENAMED_NEW_NAME, "Action = %d\n", fni_next->Action);
+ ok(fni_next->FileNameLength == lstrlenW(szFile)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni_next->FileNameLength);
+ ok(!memcmp(fni_next->FileName, szFile, lstrlenW(szFile)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni_next->FileName));
+ }
+ else
+ {
+ todo_wine ok(0, "Expected rename event\n");
+
+ if (fni->NextEntryOffset == 0)
+ {
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_DIR_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive directory move event\n");
+ }
+ }
+
+ r = CreateDirectoryW(dir, NULL);
+ ok(r == TRUE, "failed to create directory\n");
+
+ r = RemoveDirectoryW(dir);
+ ok(r == TRUE, "failed to remove directory\n");
+
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_DIR_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive directory creation event\n");
+ ok(fni->Action == FILE_ACTION_ADDED, "Action = %d\n", fni->Action);
+ ok(fni->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni->FileNameLength);
+ ok(!memcmp(fni->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni->FileName));
+ if (fni->NextEntryOffset)
+ fni_next = (FILE_NOTIFY_INFORMATION*)((char*)fni+fni->NextEntryOffset);
+ else
+ {
+ r = pReadDirectoryChangesW(hdir, fni, sizeof(fni), FALSE,
+ FILE_NOTIFY_CHANGE_DIR_NAME, NULL, &ov, readdirectorychanges_cr);
+ ok(r == TRUE, "pReadDirectoryChangesW failed\n");
+
+ r = SleepEx(1000, TRUE);
+ ok(r != 0, "failed to receive directory removal event\n");
+ fni_next = fni;
+ }
+ ok(fni_next->NextEntryOffset == 0, "there should be no more events in buffer\n");
+ ok(fni_next->Action == FILE_ACTION_REMOVED, "Action = %d\n", fni_next->Action);
+ ok(fni_next->FileNameLength == lstrlenW(szDir)*sizeof(WCHAR),
+ "FileNameLength = %d\n", fni_next->FileNameLength);
+ ok(!memcmp(fni_next->FileName, szDir, lstrlenW(szDir)*sizeof(WCHAR)),
+ "FileName = %s\n", wine_dbgstr_w(fni_next->FileName));
+
+ CloseHandle(hdir);
+ RemoveDirectoryW(file);
+ RemoveDirectoryW(path);
+}
+
static void test_ffcn_directory_overlap(void)
{
HANDLE parent_watch, child_watch, parent_thread, child_thread;
START_TEST(change)
{
HMODULE hkernel32 = GetModuleHandle("kernel32");
- pReadDirectoryChangesW = (fnReadDirectoryChangesW)
- GetProcAddress(hkernel32, "ReadDirectoryChangesW");
+ pReadDirectoryChangesW = (void *)GetProcAddress(hkernel32, "ReadDirectoryChangesW");
test_ffcnMultipleThreads();
/* The above function runs a test that must occur before FindCloseChangeNotification is run in the
test_readdirectorychanges();
test_readdirectorychanges_null();
test_readdirectorychanges_filedir();
+ test_readdirectorychanges_cr();
test_ffcn_directory_overlap();
}
len, GLE);
}
-/* lstrcmpW is not supported on Win9x! */
-static int mylstrcmpW(const WCHAR* str1, const WCHAR* str2)
-{
- while (*str1 && *str1==*str2) {
- str1++;
- str2++;
- }
- return *str1-*str2;
-}
-
static void test_negative_source_length(void)
{
int len;
SetLastError( 0xdeadbeef );
memset(bufW,'x',sizeof(bufW));
len = MultiByteToWideChar(CP_ACP, 0, "foobar", -2002, bufW, 10);
- ok(len == 7 && !mylstrcmpW(bufW, foobarW) && GetLastError() == 0xdeadbeef,
+ ok(len == 7 && !lstrcmpW(bufW, foobarW) && GetLastError() == 0xdeadbeef,
"MultiByteToWideChar(-2002): len=%d error=%u\n", len, GetLastError());
SetLastError(0xdeadbeef);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
+static void test_undefined_byte_char(void)
+{
+ static const struct tag_testset {
+ INT codepage;
+ LPCSTR str;
+ BOOL is_error;
+ } testset[] = {
+ { 874, "\xdd", TRUE },
+ { 932, "\xfe", TRUE },
+ { 932, "\x80", FALSE },
+ { 936, "\xff", TRUE },
+ { 949, "\xff", TRUE },
+ { 950, "\xff", TRUE },
+ { 1252, "\x90", FALSE },
+ { 1253, "\xaa", TRUE },
+ { 1255, "\xff", TRUE },
+ { 1257, "\xa5", TRUE },
+ };
+ INT i, ret;
+
+ for (i = 0; i < (sizeof(testset) / sizeof(testset[0])); i++) {
+ if (! IsValidCodePage(testset[i].codepage))
+ {
+ skip("Codepage %d not available\n", testset[i].codepage);
+ continue;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = MultiByteToWideChar(testset[i].codepage, MB_ERR_INVALID_CHARS,
+ testset[i].str, -1, NULL, 0);
+ if (testset[i].is_error) {
+ ok(ret == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION,
+ "ret is %d, GetLastError is %u (cp %d)\n",
+ ret, GetLastError(), testset[i].codepage);
+ }
+ else {
+ ok(ret == strlen(testset[i].str)+1 && GetLastError() == 0xdeadbeef,
+ "ret is %d, GetLastError is %u (cp %d)\n",
+ ret, GetLastError(), testset[i].codepage);
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = MultiByteToWideChar(testset[i].codepage, 0,
+ testset[i].str, -1, NULL, 0);
+ ok(ret == strlen(testset[i].str)+1 && GetLastError() == 0xdeadbeef,
+ "ret is %d, GetLastError is %u (cp %d)\n",
+ ret, GetLastError(), testset[i].codepage);
+ }
+}
+
START_TEST(codepage)
{
BOOL bUsedDefaultChar;
/* WideCharToMultiByte has two code paths, test both here */
test_string_conversion(NULL);
test_string_conversion(&bUsedDefaultChar);
+
+ test_undefined_byte_char();
}
trace("WaitCommEvent for EV_TXEMPTY took %d ms\n", timediff);
/* 050604: This shows a difference between XP (tested with mingw compiled crosstest):
XP returns Writefile only after everything went out of the Serial port,
- while wine returns immedate.
+ while wine returns immediately.
Thus on XP, WaintCommEvent after setting the CommMask for EV_TXEMPTY
nearly return immediate,
while on wine the most time is spent here
i=0;
do
{
- res = ReadFile(hcom, rbuf+read, sizeof(rbuf-read), &read1, NULL);
+ res = ReadFile(hcom, rbuf+read, sizeof(rbuf)-read, &read1, NULL);
ok(res, "Readfile failed\n");
read += read1;
i++;
trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
success, err, evtmask, after-before, after1-before);
- ok(evtmask == 0, "Incorect EventMask 0x%08x returned on Wait aborted bu SetCommMask, expected 0x%08x\n",
+ ok(evtmask == 0, "Incorrect EventMask 0x%08x returned on Wait aborted bu SetCommMask, expected 0x%08x\n",
evtmask, 0);
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
diff = after1 - before;
trace("overlapped WriteCommEvent returned.\n");
if (!success && (err == ERROR_IO_PENDING))
- ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
- "wait hComPortEvent res %d\n", GetLastError());
+ {
+ success = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
+ ok(!success, "wait hComPortEvent res %d\n", GetLastError());
+ }
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
err = GetLastError();
after1 = GetTickCount();
static DWORD (WINAPI *pGetConsoleProcessList)(LPDWORD, DWORD);
static HANDLE (WINAPI *pOpenConsoleW)(LPCWSTR,DWORD,BOOL,DWORD);
static BOOL (WINAPI *pSetConsoleInputExeNameA)(LPCSTR);
+static BOOL (WINAPI *pVerifyConsoleIoHandle)(HANDLE handle);
/* DEFAULT_ATTRIB is used for all initial filling of the console.
* all modifications are made with TEST_ATTRIB so that we could check
KERNEL32_GET_PROC(GetConsoleProcessList);
KERNEL32_GET_PROC(OpenConsoleW);
KERNEL32_GET_PROC(SetConsoleInputExeNameA);
+ KERNEL32_GET_PROC(VerifyConsoleIoHandle);
#undef KERNEL32_GET_PROC
}
static void testEmptyWrite(HANDLE hCon)
{
+ static const char emptybuf[16];
COORD c;
DWORD len;
- const char* mytest = "";
c.X = c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
}
len = -1;
- ok(WriteConsole(hCon, mytest, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
+ ok(WriteConsole(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
okCURSOR(hCon, c);
/* WriteConsole does not halt on a null terminator and is happy to write
* memory contents beyond the actual size of the buffer. */
len = -1;
- ok(WriteConsole(hCon, mytest, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
+ ok(WriteConsole(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
c.X += 16;
okCURSOR(hCon, c);
}
HeapFree(GetProcessHeap(), 0, list);
}
+static void test_OpenCON(void)
+{
+ static const WCHAR conW[] = {'C','O','N',0};
+ static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
+ OPEN_ALWAYS, TRUNCATE_EXISTING};
+ unsigned i;
+ HANDLE h;
+
+ for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
+ {
+ h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
+ ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
+ CloseHandle(h);
+
+ 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
+ * So don't test when disposition is TRUNCATE_EXISTING
+ */
+ if (accesses[i] != TRUNCATE_EXISTING)
+ {
+ ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
+ }
+ CloseHandle(h);
+ h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
+ ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %x\n", GetLastError());
+ }
+}
+
static void test_OpenConsoleW(void)
{
static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
CloseHandle(ret);
}
+static void test_VerifyConsoleIoHandle( HANDLE handle )
+{
+ BOOL ret;
+ DWORD error;
+
+ if (!pVerifyConsoleIoHandle)
+ {
+ win_skip("VerifyConsoleIoHandle is not available\n");
+ return;
+ }
+
+ /* invalid handle */
+ SetLastError(0xdeadbeef);
+ ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
+ error = GetLastError();
+ ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+
+ /* invalid handle + 1 */
+ SetLastError(0xdeadbeef);
+ ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
+ error = GetLastError();
+ ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+
+ /* invalid handle + 2 */
+ SetLastError(0xdeadbeef);
+ ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
+ error = GetLastError();
+ ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+
+ /* invalid handle + 3 */
+ SetLastError(0xdeadbeef);
+ ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
+ error = GetLastError();
+ ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+
+ /* valid handle */
+ SetLastError(0xdeadbeef);
+ ret = pVerifyConsoleIoHandle(handle);
+ error = GetLastError();
+ ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+}
+
+static void test_GetSetStdHandle(void)
+{
+ HANDLE handle;
+ DWORD error;
+ BOOL ret;
+
+ /* get invalid std handle */
+ SetLastError(0xdeadbeef);
+ handle = GetStdHandle(42);
+ error = GetLastError();
+ ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
+ "wrong GetLastError() %d\n", error);
+ ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
+
+ /* get valid */
+ SetLastError(0xdeadbeef);
+ handle = GetStdHandle(STD_INPUT_HANDLE);
+ error = GetLastError();
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+
+ /* set invalid std handle */
+ SetLastError(0xdeadbeef);
+ ret = SetStdHandle(42, handle);
+ error = GetLastError();
+ ok(!ret, "expected SetStdHandle to fail\n");
+ ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
+ "wrong GetLastError() %d\n", error);
+
+ /* set valid (restore old value) */
+ SetLastError(0xdeadbeef);
+ ret = SetStdHandle(STD_INPUT_HANDLE, handle);
+ error = GetLastError();
+ ok(ret, "expected SetStdHandle to succeed\n");
+ ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
+}
+
+static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle)
+{
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE handle;
+ LPDWORD nrofevents;
+ DWORD last_error;
+ } invalid_table[] =
+ {
+ {NULL, NULL, ERROR_INVALID_HANDLE},
+ {NULL, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].nrofevents) count = 0xdeadbeef;
+ ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
+ invalid_table[i].nrofevents);
+ ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].nrofevents)
+ {
+ ok(count == 0xdeadbeef,
+ "[%d] Expected output count to be unmodified, got %u\n", i, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ /* Test crashes on Windows 7. */
+ if (0)
+ {
+ SetLastError(0xdeadbeef);
+ ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
+ ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_ACCESS,
+ "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
+ GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count != 0xdeadbeef, "Expected output count to initialized\n");
+}
+
+static void test_WriteConsoleInputA(HANDLE input_handle)
+{
+ INPUT_RECORD event;
+ INPUT_RECORD event_list[5];
+ MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
+ KEY_EVENT_RECORD key_event;
+ DWORD count, console_mode;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE handle;
+ const INPUT_RECORD *buffer;
+ DWORD count;
+ LPDWORD written;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_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, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
+ {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {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, &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, &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},
+ };
+
+ /* Suppress external sources of input events for the duration of the test. */
+ ret = GetConsoleMode(input_handle, &console_mode);
+ ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
+ if (!ret)
+ {
+ skip("GetConsoleMode failed with last error %u\n", GetLastError());
+ return;
+ }
+
+ ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
+ ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
+ if (!ret)
+ {
+ skip("SetConsoleMode failed with last error %u\n", GetLastError());
+ return;
+ }
+
+ /* Discard any events queued before the tests. */
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].written) count = 0xdeadbeef;
+ ret = WriteConsoleInputA(invalid_table[i].handle,
+ invalid_table[i].buffer,
+ invalid_table[i].count,
+ invalid_table[i].written);
+ ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].written)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected output count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputA(input_handle, &event, 0, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ todo_wine
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
+ {
+ event_list[i].EventType = MOUSE_EVENT;
+ event_list[i].Event.MouseEvent = mouse_event;
+ }
+
+ /* Writing consecutive chunks of mouse events appears to work. */
+ ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be twice event list length, got %u\n", count);
+
+ /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ todo_wine
+ ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be twice event list length, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ key_event.bKeyDown = FALSE;
+ key_event.wRepeatCount = 0;
+ key_event.wVirtualKeyCode = VK_SPACE;
+ key_event.wVirtualScanCode = VK_SPACE;
+ key_event.uChar.AsciiChar = ' ';
+ key_event.dwControlKeyState = 0;
+
+ event.EventType = KEY_EVENT;
+ event.Event.KeyEvent = key_event;
+
+ /* Key events don't exhibit the same behavior as mouse events. */
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2, "Expected count to be 2, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ /* Try interleaving mouse and key events. */
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ event.EventType = KEY_EVENT;
+ event.Event.KeyEvent = key_event;
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2, "Expected count to be 2, got %u\n", count);
+
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputA(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 3, "Expected count to be 3, got %u\n", count);
+
+ /* Restore the old console mode. */
+ ret = SetConsoleMode(input_handle, console_mode);
+ ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
+}
+
+static void test_WriteConsoleInputW(HANDLE input_handle)
+{
+ INPUT_RECORD event;
+ INPUT_RECORD event_list[5];
+ MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
+ KEY_EVENT_RECORD key_event;
+ DWORD count, console_mode;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE handle;
+ const INPUT_RECORD *buffer;
+ DWORD count;
+ LPDWORD written;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_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, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
+ {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {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, &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, &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},
+ };
+
+ /* Suppress external sources of input events for the duration of the test. */
+ ret = GetConsoleMode(input_handle, &console_mode);
+ ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
+ if (!ret)
+ {
+ skip("GetConsoleMode failed with last error %u\n", GetLastError());
+ return;
+ }
+
+ ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
+ ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
+ if (!ret)
+ {
+ skip("SetConsoleMode failed with last error %u\n", GetLastError());
+ return;
+ }
+
+ /* Discard any events queued before the tests. */
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].written) count = 0xdeadbeef;
+ ret = WriteConsoleInputW(invalid_table[i].handle,
+ invalid_table[i].buffer,
+ invalid_table[i].count,
+ invalid_table[i].written);
+ ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].written)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected output count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputW(input_handle, &event, 0, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ todo_wine
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
+ {
+ event_list[i].EventType = MOUSE_EVENT;
+ event_list[i].Event.MouseEvent = mouse_event;
+ }
+
+ /* Writing consecutive chunks of mouse events appears to work. */
+ ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be event list length, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be twice event list length, got %u\n", count);
+
+ /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ todo_wine
+ ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
+ "Expected count to be twice event list length, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ key_event.bKeyDown = FALSE;
+ key_event.wRepeatCount = 0;
+ key_event.wVirtualKeyCode = VK_SPACE;
+ key_event.wVirtualScanCode = VK_SPACE;
+ key_event.uChar.UnicodeChar = ' ';
+ key_event.dwControlKeyState = 0;
+
+ event.EventType = KEY_EVENT;
+ event.Event.KeyEvent = key_event;
+
+ /* Key events don't exhibit the same behavior as mouse events. */
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2, "Expected count to be 2, got %u\n", count);
+
+ ret = FlushConsoleInputBuffer(input_handle);
+ ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
+
+ /* Try interleaving mouse and key events. */
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ event.EventType = KEY_EVENT;
+ event.Event.KeyEvent = key_event;
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 2, "Expected count to be 2, got %u\n", count);
+
+ event.EventType = MOUSE_EVENT;
+ event.Event.MouseEvent = mouse_event;
+
+ ret = WriteConsoleInputW(input_handle, &event, 1, &count);
+ ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ ret = GetNumberOfConsoleInputEvents(input_handle, &count);
+ ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
+ ok(count == 3, "Expected count to be 3, got %u\n", count);
+
+ /* Restore the old console mode. */
+ ret = SetConsoleMode(input_handle, console_mode);
+ ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
+}
+
+static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
+{
+ static const char output[] = {'a', 0};
+
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ LPCSTR str;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumCharsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
+ invalid_table[i].str,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumCharsWritten);
+ ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumCharsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
+{
+ static const WCHAR outputW[] = {'a',0};
+
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ LPCWSTR str;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumCharsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, outputW, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, outputW, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, outputW, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, outputW, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
+ invalid_table[i].str,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumCharsWritten);
+ ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumCharsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
+{
+ WORD attr = FOREGROUND_BLUE;
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ CONST WORD *attr;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumAttrsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
+ ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
+ invalid_table[i].attr,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumAttrsWritten);
+ ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumAttrsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
+ ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_FillConsoleOutputCharacterA(HANDLE output_handle)
+{
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ CHAR ch;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumCharsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
+ invalid_table[i].ch,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumCharsWritten);
+ ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumCharsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
+{
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ WCHAR ch;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumCharsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
+ invalid_table[i].ch,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumCharsWritten);
+ ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumCharsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_FillConsoleOutputAttribute(HANDLE output_handle)
+{
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ WORD attr;
+ DWORD length;
+ COORD coord;
+ LPDWORD lpNumAttrsWritten;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, FOREGROUND_BLUE, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, FOREGROUND_BLUE, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
+ ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
+ invalid_table[i].attr,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].lpNumAttrsWritten);
+ ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].lpNumAttrsWritten)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
+ ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
+{
+ CHAR read;
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ LPSTR lpstr;
+ DWORD length;
+ COORD coord;
+ LPDWORD read_count;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {NULL, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {INVALID_HANDLE_VALUE, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 10, origin, &count, 10, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].read_count) count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
+ invalid_table[i].lpstr,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].read_count);
+ ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].read_count)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
+{
+ WCHAR read;
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ LPWSTR buffer;
+ DWORD length;
+ COORD coord;
+ LPDWORD read_count;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {NULL, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {INVALID_HANDLE_VALUE, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 10, origin, &count, 10, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].read_count) count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
+ invalid_table[i].buffer,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].read_count);
+ ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].read_count)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
+static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
+{
+ WORD attr;
+ COORD origin = {0, 0};
+ DWORD count;
+ BOOL ret;
+ int i;
+
+ const struct
+ {
+ HANDLE hConsoleOutput;
+ LPWORD lpAttribute;
+ DWORD length;
+ COORD coord;
+ LPDWORD read_count;
+ DWORD expected_count;
+ DWORD last_error;
+ int win7_crash;
+ } invalid_table[] =
+ {
+ {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {NULL, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {NULL, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
+ {INVALID_HANDLE_VALUE, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
+ {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {output_handle, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ };
+
+ for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
+ {
+ if (invalid_table[i].win7_crash)
+ continue;
+
+ SetLastError(0xdeadbeef);
+ if (invalid_table[i].read_count) count = 0xdeadbeef;
+ ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
+ invalid_table[i].lpAttribute,
+ invalid_table[i].length,
+ invalid_table[i].coord,
+ invalid_table[i].read_count);
+ ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
+ if (invalid_table[i].read_count)
+ {
+ ok(count == invalid_table[i].expected_count,
+ "[%d] Expected count to be %u, got %u\n",
+ i, invalid_table[i].expected_count, count);
+ }
+ ok(GetLastError() == invalid_table[i].last_error,
+ "[%d] Expected last error to be %u, got %u\n",
+ i, invalid_table[i].last_error, GetLastError());
+ }
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 0, "Expected count to be 0, got %u\n", count);
+
+ count = 0xdeadbeef;
+ ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
+ ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
+ ok(count == 1, "Expected count to be 1, got %u\n", count);
+}
+
START_TEST(console)
{
+ static const char font_name[] = "Lucida Console";
HANDLE hConIn, hConOut;
BOOL ret;
CONSOLE_SCREEN_BUFFER_INFO sbi;
+ LONG err;
+ HKEY console_key;
+ char old_font[LF_FACESIZE];
+ BOOL delete = FALSE;
+ DWORD size;
init_function_pointers();
* the curses backend
*/
- /* first, we detach and open a fresh console to play with */
+ /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
+ * correctly for characters that don't have a glyph in the console font. So,
+ * we first set the console font to Lucida Console (which has a wider
+ * selection of glyphs available than the default raster fonts). We want
+ * to be able to restore the original font afterwards, so don't change
+ * if we can't read the original font.
+ */
+ err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
+ if (err == ERROR_SUCCESS)
+ {
+ size = sizeof(old_font);
+ err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
+ (LPBYTE) old_font, &size);
+ if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND)
+ {
+ delete = (err == ERROR_FILE_NOT_FOUND);
+ err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
+ (const BYTE *) font_name, sizeof(font_name));
+ if (err != ERROR_SUCCESS)
+ trace("Unable to change default console font, error %d\n", err);
+ }
+ else
+ {
+ trace("Unable to query default console font, error %d\n", err);
+ RegCloseKey(console_key);
+ console_key = NULL;
+ }
+ }
+ else
+ {
+ trace("Unable to open HKCU\\Console, error %d\n", err);
+ console_key = NULL;
+ }
+
+ /* Now detach and open a fresh console to play with */
FreeConsole();
ok(AllocConsole(), "Couldn't alloc console\n");
+
+ /* Restore default console font if needed */
+ if (console_key != NULL)
+ {
+ if (delete)
+ err = RegDeleteValueA(console_key, "FaceName");
+ else
+ err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
+ (const BYTE *) old_font, strlen(old_font) + 1);
+ ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
+ }
hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
test_GetConsoleProcessList();
test_OpenConsoleW();
+ test_OpenCON();
+ test_VerifyConsoleIoHandle(hConOut);
+ test_GetSetStdHandle();
+ test_GetNumberOfConsoleInputEvents(hConIn);
+ test_WriteConsoleInputA(hConIn);
+ test_WriteConsoleInputW(hConIn);
+ test_WriteConsoleOutputCharacterA(hConOut);
+ test_WriteConsoleOutputCharacterW(hConOut);
+ test_WriteConsoleOutputAttribute(hConOut);
+ test_FillConsoleOutputCharacterA(hConOut);
+ test_FillConsoleOutputCharacterW(hConOut);
+ test_FillConsoleOutputAttribute(hConOut);
+ test_ReadConsoleOutputCharacterA(hConOut);
+ test_ReadConsoleOutputCharacterW(hConOut);
+ test_ReadConsoleOutputAttribute(hConOut);
}
{
char* p;
+ /* make sure the exception gets to the debugger */
+ SetErrorMode( 0 );
+ SetUnhandledExceptionFilter( NULL );
+
if (argc >= 4)
{
crash_blackbox_t blackbox;
static void crash_and_debug(HKEY hkey, const char* argv0, const char* dbgtasks)
{
+ static BOOL skip_crash_and_debug = FALSE;
+ BOOL bRet;
DWORD ret;
HANDLE start_event, done_event;
char* cmd;
DWORD exit_code;
crash_blackbox_t crash_blackbox;
debugger_blackbox_t dbg_blackbox;
+ DWORD wait_code;
+
+ if (skip_crash_and_debug)
+ {
+ win_skip("Skipping crash_and_debug\n");
+ return;
+ }
ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%d\n", ret);
get_file_name(dbglog);
get_events(dbglog, &start_event, &done_event);
- cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+10+strlen(dbgtasks)+1+strlen(dbglog)+34+1);
- sprintf(cmd, "%s debugger %s %s %%ld %%ld", argv0, dbgtasks, dbglog);
+ cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+10+strlen(dbgtasks)+1+strlen(dbglog)+2+34+1);
+ sprintf(cmd, "%s debugger %s \"%s\" %%ld %%ld", argv0, dbgtasks, dbglog);
ret=RegSetValueExA(hkey, "debugger", 0, REG_SZ, (BYTE*)cmd, strlen(cmd)+1);
ok(ret == ERROR_SUCCESS, "unable to set AeDebug/debugger: ret=%d\n", ret);
HeapFree(GetProcessHeap(), 0, cmd);
get_file_name(childlog);
- cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+16+strlen(dbglog)+1);
- sprintf(cmd, "%s debugger crash %s", argv0, childlog);
+ cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+16+strlen(dbglog)+2+1);
+ sprintf(cmd, "%s debugger crash \"%s\"", argv0, childlog);
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
/* The process exits... */
trace("waiting for child exit...\n");
- ok(WaitForSingleObject(info.hProcess, 60000) == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
- ok(GetExitCodeProcess(info.hProcess, &exit_code), "GetExitCodeProcess failed: err=%d\n", GetLastError());
+ wait_code = WaitForSingleObject(info.hProcess, 30000);
+#if defined(_WIN64) && defined(__MINGW32__)
+ /* Mingw x64 doesn't output proper unwind info */
+ skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
+ if (skip_crash_and_debug)
+ {
+ TerminateProcess(info.hProcess, WAIT_TIMEOUT);
+ WaitForSingleObject(info.hProcess, 5000);
+ CloseHandle(info.hProcess);
+ assert(DeleteFileA(dbglog) != 0);
+ assert(DeleteFileA(childlog) != 0);
+ win_skip("Giving up on child process\n");
+ return;
+ }
+#endif
+ ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
+ bRet = GetExitCodeProcess(info.hProcess, &exit_code);
+ ok(bRet, "GetExitCodeProcess failed: err=%d\n", GetLastError());
if (strstr(dbgtasks, "code2"))
{
/* If, after attaching to the debuggee, the debugger exits without
*/
ok(exit_code == STATUS_DEBUGGER_INACTIVE ||
broken(exit_code == STATUS_ACCESS_VIOLATION) || /* Intermittent Vista+ */
- broken(exit_code == 0xffffffff) || /* Win9x */
broken(exit_code == WAIT_ABANDONED), /* NT4, W2K */
"wrong exit code : %08x\n", exit_code);
}
else
ok(exit_code == STATUS_ACCESS_VIOLATION ||
- broken(exit_code == WAIT_ABANDONED) || /* NT4, W2K, W2K3 */
- broken(exit_code == 0xffffffff), /* Win9x, WinME */
+ broken(exit_code == WAIT_ABANDONED), /* NT4, W2K, W2K3 */
"wrong exit code : %08x\n", exit_code);
CloseHandle(info.hProcess);
ok(SetEvent(start_event), "SetEvent(start_event) failed\n");
trace("waiting for the debugger...\n");
- ok(WaitForSingleObject(done_event, 60000) == WAIT_OBJECT_0, "Timed out waiting for the debugger\n");
+ wait_code = WaitForSingleObject(done_event, 5000);
+#if defined(_WIN64) && defined(__MINGW32__)
+ /* Mingw x64 doesn't output proper unwind info */
+ skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
+ if (skip_crash_and_debug)
+ {
+ assert(DeleteFileA(dbglog) != 0);
+ assert(DeleteFileA(childlog) != 0);
+ win_skip("Giving up on debugger\n");
+ return;
+ }
+#endif
+ ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the debugger\n");
assert(load_blackbox(childlog, &crash_blackbox, sizeof(crash_blackbox)));
assert(load_blackbox(dbglog, &dbg_blackbox, sizeof(dbg_blackbox)));
static void crash_and_winedbg(HKEY hkey, const char* argv0)
{
+ BOOL bRet;
DWORD ret;
char* cmd;
PROCESS_INFORMATION info;
trace("waiting for child exit...\n");
ok(WaitForSingleObject(info.hProcess, 60000) == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
- ok(GetExitCodeProcess(info.hProcess, &exit_code), "GetExitCodeProcess failed: err=%d\n", GetLastError());
+ bRet = GetExitCodeProcess(info.hProcess, &exit_code);
+ ok(bRet, "GetExitCodeProcess failed: err=%d\n", GetLastError());
ok(exit_code == STATUS_ACCESS_VIOLATION, "exit code = %08x\n", exit_code);
CloseHandle(info.hProcess);
}
ok(0, "could not open the AeDebug key: %d\n", ret);
return;
}
+ else debugger_value.data = NULL;
if (debugger_value.data && debugger_value.type == REG_SZ &&
strstr((char*)debugger_value.data, "winedbg --auto"))
crash_and_debug(hkey, test_exe, "dbg,none");
else
skip("\"none\" debugger test needs user interaction\n");
- if (disposition == REG_CREATED_NEW_KEY)
- win_skip("'dbg,event,order' test doesn't finish on Win9x/WinMe\n");
- else
- crash_and_debug(hkey, test_exe, "dbg,event,order");
+ ok(disposition == REG_OPENED_EXISTING_KEY, "expected REG_OPENED_EXISTING_KEY, got %d\n", disposition);
+ crash_and_debug(hkey, test_exe, "dbg,event,order");
crash_and_debug(hkey, test_exe, "dbg,attach,event,code2");
if (pDebugSetProcessKillOnExit)
crash_and_debug(hkey, test_exe, "dbg,attach,event,nokill");
ok(!ret, "DebugActiveProcess() succeeded on own process.\n");
get_file_name(blackbox_file);
- cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 10);
- sprintf(cmd, "%s%s%08x %s", argv[0], arguments, pid, blackbox_file);
+ cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 2 + 10);
+ sprintf(cmd, "%s%s%08x \"%s\"", argv[0], arguments, pid, blackbox_file);
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
"CreateDirectoryW with ? wildcard name should fail with error 183, ret=%s error=%d\n",
ret ? " True" : "False", GetLastError());
ret = RemoveDirectoryW(tmpdir);
+ ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
tmpdir[lstrlenW(tmpdir) - 1] = '*';
ret = CreateDirectoryW(tmpdir, NULL);
"CreateDirectoryW with * wildcard name should fail with error 183, ret=%s error=%d\n",
ret ? " True" : "False", GetLastError());
ret = RemoveDirectoryW(tmpdir);
+ ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
GetTempPathW(MAX_PATH, tmpdir);
lstrcatW(tmpdir, tmp_dir_name);
"CreateDirectoryW with multiple nonexistent directories in path should fail ret %u err %u\n",
ret, GetLastError());
ret = RemoveDirectoryW(tmpdir);
+ ok(ret == FALSE, "RemoveDirectoryW should have failed\n");
}
static void test_RemoveDirectoryA(void)
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
type = GetDriveTypeW(drive);
- if (type == DRIVE_UNKNOWN && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- win_skip("GetDriveTypeW is not available on Win9x\n");
- return;
- }
ok(type > DRIVE_UNKNOWN && type <= DRIVE_RAMDISK,
"not a valid drive %c: type %u\n", drive[0], type);
static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
static BOOL (WINAPI *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
+static BOOL (WINAPI *pOpenProcessToken)(HANDLE,DWORD,PHANDLE);
+static BOOL (WINAPI *pGetUserProfileDirectoryA)(HANDLE,LPSTR,LPDWORD);
static void init_functionpointers(void)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
+ HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
+ HMODULE huserenv = LoadLibraryA("userenv.dll");
pGetComputerNameExA = (void *)GetProcAddress(hkernel32, "GetComputerNameExA");
pGetComputerNameExW = (void *)GetProcAddress(hkernel32, "GetComputerNameExW");
+ pOpenProcessToken = (void *)GetProcAddress(hadvapi32, "OpenProcessToken");
+ pGetUserProfileDirectoryA = (void *)GetProcAddress(huserenv,
+ "GetUserProfileDirectoryA");
+}
+
+static void test_Predefined(void)
+{
+ char Data[1024];
+ DWORD DataSize;
+ char Env[sizeof(Data)];
+ DWORD EnvSize;
+ HANDLE Token;
+ BOOL NoErr;
+
+ /*
+ * Check value of %USERPROFILE%, should be same as GetUserProfileDirectory()
+ * If this fails, your test environment is probably not set up
+ */
+ if (pOpenProcessToken == NULL || pGetUserProfileDirectoryA == NULL)
+ {
+ skip("Skipping USERPROFILE check\n");
+ return;
+ }
+ NoErr = pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
+ ok(NoErr, "Failed to open token, error %u\n", GetLastError());
+ DataSize = sizeof(Data);
+ NoErr = pGetUserProfileDirectoryA(Token, Data, &DataSize);
+ ok(NoErr, "Failed to get user profile dir, error %u\n", GetLastError());
+ if (NoErr)
+ {
+ EnvSize = GetEnvironmentVariableA("USERPROFILE", Env, sizeof(Env));
+ ok(EnvSize != 0 && EnvSize <= sizeof(Env),
+ "Failed to retrieve environment variable USERPROFILE, error %u\n",
+ GetLastError());
+ ok(strcmp(Data, Env) == 0,
+ "USERPROFILE env var %s doesn't match GetUserProfileDirectory %s\n",
+ Env, Data);
+ }
+ else
+ skip("Skipping USERPROFILE check, can't get user profile dir\n");
+ NoErr = CloseHandle(Token);
+ ok(NoErr, "Failed to close token, error %u\n", GetLastError());
}
static void test_GetSetEnvironmentVariableA(void)
size = 0;
ret = GetComputerNameA((LPSTR)0xdeadbeef, &size);
error = GetLastError();
- todo_wine
ok(!ret && error == ERROR_BUFFER_OVERFLOW, "GetComputerNameA should have failed with ERROR_BUFFER_OVERFLOW instead of %d\n", error);
/* Only Vista returns the computer name length as documented in the MSDN */
win_skip("GetComputerNameW is not implemented\n");
else
{
- todo_wine
ok(!ret && error == ERROR_BUFFER_OVERFLOW, "GetComputerNameW should have failed with ERROR_BUFFER_OVERFLOW instead of %d\n", error);
size++; /* nul terminating character */
nameW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(nameW[0]));
{
init_functionpointers();
+ test_Predefined();
test_GetSetEnvironmentVariableA();
test_GetSetEnvironmentVariableW();
test_ExpandEnvironmentStringsA();
{
if (pConvertFiberToThread)
{
- ok(pConvertFiberToThread() , "ConvertFiberToThread failed with error %d\n", GetLastError());
+ BOOL ret = pConvertFiberToThread();
+ ok(ret, "ConvertFiberToThread failed with error %d\n", GetLastError());
}
else
{
return;
}
+ SetLastError(0xdeadbeef);
fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam);
ok(fibers[1] != 0, "CreateFiberEx failed with error %d\n", GetLastError());
static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID);
static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT);
static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
+static DWORD WINAPI (*pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
/* keep filename and filenameW the same */
static const char filename[] = "testfile.xxx";
pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA");
pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA");
+ pQueueUserAPC = (void *) GetProcAddress(hkernel32, "QueueUserAPC");
}
static void test__hread( void )
ok( 0 != memory_object, "LocalAlloc fails. (Could be out of memory.)\n" );
contents = LocalLock( memory_object );
+ ok( NULL != contents, "LocalLock whines\n" );
filehandle = _lopen( filename, OF_READ );
contents = LocalLock( memory_object );
-
ok( NULL != contents, "LocalLock whines\n" );
ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
ok( 0 != memory_object, "LocalAlloc fails, could be out of memory\n" );
contents = LocalLock( memory_object );
+ ok( NULL != contents, "LocalLock whines\n" );
filehandle = _lopen( filename, OF_READ );
contents = LocalLock( memory_object );
-
ok( NULL != contents, "LocalLock whines\n" );
ok( bytes_written == _hread( filehandle, contents, bytes_written), "read length differ from write length\n" );
ret = DeleteFileA(filename);
ok(ret, "DeleteFileA: error %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ hFile = CreateFileA("c:\\*.*", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(hFile == INVALID_HANDLE_VALUE, "hFile should have been INVALID_HANDLE_VALUE\n");
+ ok(GetLastError() == ERROR_INVALID_NAME ||
+ broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* Win98 */
+ "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError());
+
/* get windows drive letter */
ret = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
#elif defined __powerpc__
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC;
+#elif defined __sparc__
+ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_SPARC;
+#elif defined __arm__
+ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM;
#else
# error You must specify the machine type
#endif
return ret;
}
-static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2, BOOL is_win9x )
+static unsigned int map_file_access( unsigned int access )
{
- if (!is_win9x)
- {
- if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
- if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
- }
- else
- {
- access1 &= ~DELETE;
- if (!access1) access1 = GENERIC_READ;
+ if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
+ if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
+ if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
+ if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
+ return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
+}
- access2 &= ~DELETE;
- if (!access2) access2 = GENERIC_READ;
- }
+static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
+{
+ access1 = map_file_access( access1 );
+ access2 = map_file_access( access2 );
+ access1 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
+ access2 &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | DELETE;
+
+ if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
+ if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
- if ((access1 & GENERIC_READ) && !(sharing2 & FILE_SHARE_READ)) return 0;
- if ((access1 & GENERIC_WRITE) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
+ if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return 0;
+ if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0;
- if ((access2 & GENERIC_READ) && !(sharing1 & FILE_SHARE_READ)) return 0;
- if ((access2 & GENERIC_WRITE) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
+ if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return 0;
+ if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0;
return 1;
}
{
if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
!(sharing2 & FILE_SHARE_WRITE)) return 0;
- if ((map_access & SEC_IMAGE) && (access2 & GENERIC_WRITE)) return 0;
+ access2 = map_file_access( access2 );
+ if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return 0;
return 1;
}
{
static const DWORD access_modes[] =
{ 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
- DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE };
+ DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE,
+ GENERIC_EXECUTE, GENERIC_EXECUTE | DELETE,
+ FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA, FILE_READ_EA, FILE_WRITE_EA,
+ FILE_READ_DATA | FILE_EXECUTE, FILE_WRITE_DATA | FILE_EXECUTE, FILE_APPEND_DATA | FILE_EXECUTE,
+ FILE_READ_EA | FILE_EXECUTE, FILE_WRITE_EA | FILE_EXECUTE, FILE_EXECUTE,
+ FILE_DELETE_CHILD, FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES };
static const DWORD sharing_modes[] =
{ 0, FILE_SHARE_READ,
FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
int a1, s1, a2, s2;
int ret;
HANDLE h, h2;
- BOOL is_win9x = FALSE;
/* make sure the file exists */
if (!create_fake_dll( filename ))
ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
return;
}
- is_win9x = GetFileAttributesW(filenameW) == INVALID_FILE_ATTRIBUTES;
for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
{
for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
{
- /* Win9x doesn't support FILE_SHARE_DELETE */
- if (is_win9x && (sharing_modes[s1] & FILE_SHARE_DELETE))
- continue;
-
SetLastError(0xdeadbeef);
h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
NULL, OPEN_EXISTING, 0, 0 );
{
for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
{
- /* Win9x doesn't support FILE_SHARE_DELETE */
- if (is_win9x && (sharing_modes[s2] & FILE_SHARE_DELETE))
- continue;
-
SetLastError(0xdeadbeef);
h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
NULL, OPEN_EXISTING, 0, 0 );
ret = GetLastError();
if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
- access_modes[a2], sharing_modes[s2], is_win9x ))
+ access_modes[a2], sharing_modes[s2] ))
{
ok( h2 != INVALID_HANDLE_VALUE,
"open failed for modes %x/%x/%x/%x\n",
access_modes[a1], sharing_modes[s1],
access_modes[a2], sharing_modes[s2] );
- ok( ret == 0xdeadbeef /* Win9x */ ||
- ret == 0, /* XP */
- "wrong error code %d\n", ret );
+ ok( ret == 0, "wrong error code %d\n", ret );
}
else
{
{
for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
{
- /* Win9x doesn't support FILE_SHARE_DELETE */
- if (is_win9x && (sharing_modes[s2] & FILE_SHARE_DELETE))
- continue;
-
SetLastError(0xdeadbeef);
h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
NULL, OPEN_EXISTING, 0, 0 );
ret = GetLastError();
if (h2 == INVALID_HANDLE_VALUE)
{
- if (is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
- ok( is_win9x, /* there's no sharing at all with a mapping on win9x */
- "open failed for modes map %x/%x/%x\n",
- mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
+ ok( !is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]),
+ "open failed for modes map %x/%x/%x\n",
+ mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
ok( ret == ERROR_SHARING_VIOLATION,
"wrong error code %d\n", ret );
}
h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, 0, 0 );
ret = GetLastError();
- if ((mapping_modes[a1] & SEC_IMAGE) || is_win9x)
+ if (mapping_modes[a1] & SEC_IMAGE)
{
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
ret = GetLastError();
- if (is_win9x)
- {
- ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
- ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
- }
- else if (mapping_modes[a1] & SEC_IMAGE)
+ if (mapping_modes[a1] & SEC_IMAGE)
{
ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
strcat(buffer2, "nul");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
- ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
+ ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
strcpy(buffer2, "lpt1");
handle = FindFirstFileA(buffer2, &data);
err = GetLastError();
- ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
+ ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed: %d\n", buffer2, err );
ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
HeapFree(GetProcessHeap(), 0, lpBuffer);
}
+static BOOL user_apc_ran;
+static void CALLBACK user_apc(ULONG_PTR param)
+{
+ user_apc_ran = TRUE;
+}
+
static void test_read_write(void)
{
DWORD bytes, ret, old_prot;
CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
+ user_apc_ran = FALSE;
+ if (pQueueUserAPC) {
+ trace("Queueing an user APC\n"); /* verify the file is non alerable */
+ ok(pQueueUserAPC(&user_apc, GetCurrentThread(), 0), "QueueUserAPC failed: %d\n", GetLastError());
+ }
+
SetLastError(12345678);
bytes = 12345678;
ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
"ret = %d, error %d\n", ret, GetLastError());
ok(!bytes, "bytes = %d\n", bytes);
+ ok(user_apc_ran == FALSE, "UserAPC ran, file using alertable io mode\n");
+ if (pQueueUserAPC)
+ SleepEx(0, TRUE); /* get rid of apc */
+
/* test passing protected memory as buffer */
mem = VirtualAlloc( NULL, 0x4000, MEM_COMMIT, PAGE_READWRITE );
ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_ACCESS_DENIED),
"ReplaceFileA: unexpected error %d\n", GetLastError());
+ DeleteFileA( replacement );
/*
* if the first round (w/ backup) worked then as long as there is no
ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_ACCESS_DENIED),
"ReplaceFileW: unexpected error %d\n", GetLastError());
+ DeleteFileW( replacement );
if (removeBackup)
{
{
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
+ FormatMessageW(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
0, out, sizeof(out)/sizeof(WCHAR), NULL);
}
r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_14d, 0,
0, out, sizeof(out)/sizeof(WCHAR), 1);
ok(!lstrcmpW(s_14d, out), "failed out=%s\n", wine_dbgstr_w(out));
+ ok(r==4,"failed: r=%d\n", r);
/* a single digit, left justified */
r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1_4d, 0,
{
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
- r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
+ FormatMessageA(FORMAT_MESSAGE_FROM_STRING, NULL, 0,
0, out, sizeof(out)/sizeof(CHAR), NULL);
}
memcpy(out, init_buf, sizeof(init_buf));
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "", 0,
0, out, sizeof(out)/sizeof(CHAR), NULL);
- ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
- broken(!strcmp("", out)), /* Win9x */
- "Expected the buffer to be untouched\n");
+ ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
ok(r==0, "succeeded: r=%d\n", r);
ok(GetLastError()==0xdeadbeef,
"last error %u\n", GetLastError());
memcpy(out, init_buf, sizeof(init_buf));
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
0, out, sizeof(out)/sizeof(CHAR), NULL);
- ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
- broken(!strcmp("%1", out)), /* Win9x */
- "Expected the buffer to be untouched\n");
- ok(r==0 ||
- broken(r==2), /* Win9x */
- "succeeded: r=%d\n", r);
- ok(GetLastError()==ERROR_INVALID_PARAMETER ||
- broken(GetLastError()==0xdeadbeef), /* Win9x */
- "last error %u\n", GetLastError());
+ ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
+ ok(r==0, "succeeded: r=%d\n", r);
+ ok(GetLastError()==ERROR_INVALID_PARAMETER, "last error %u\n", GetLastError());
SetLastError(0xdeadbeef);
memcpy(out, init_buf, sizeof(init_buf));
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "%1", 0,
0, out, sizeof(out)/sizeof(CHAR), NULL);
- ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
- broken(!strcmp("%1", out)), /* Win9x */
- "Expected the buffer to be untouched\n");
- ok(r==0 ||
- broken(r==2), /* Win9x */
- "succeeded: r=%d\n", r);
- ok(GetLastError()==ERROR_INVALID_PARAMETER ||
- broken(GetLastError()==0xdeadbeef), /* Win9x */
- "last error %u\n", GetLastError());
+ ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the buffer to be untouched\n");
+ ok(r==0, "succeeded: r=%d\n", r);
+ ok(GetLastError()==ERROR_INVALID_PARAMETER, "last error %u\n", GetLastError());
/* using the format feature */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
- ok(!strcmp("hi ", out) ||
- broken(!strcmp("hi\r\n", out)), /* Win9x */
- "failed out=[%s]\n",out);
- ok(r==3 ||
- broken(r==4), /* Win9x */
- "failed: r=%d\n",r);
+ ok(!strcmp("hi ", out), "failed out=[%s]\n",out);
+ ok(r==3, "failed: r=%d\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0,
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%0test", 0, 0, out,
sizeof(out)/sizeof(CHAR), NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %d\n", ret);
- ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
- broken(!strcmp("", out)), /* Win9x */
- "Expected the output buffer to be untouched\n");
+ ok(!memcmp(out, init_buf, sizeof(init_buf)), "Expected the output buffer to be untouched\n");
ok(GetLastError() == 0xdeadbeef, "Expected GetLastError() to return 0xdeadbeef, got %u\n", GetLastError());
/* Insert sequences are ignored. */
/* Only the "%n", "%r", and "%t" escape sequences are processed. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%%% %.%!", 0, 0, out,
sizeof(out)/sizeof(CHAR), NULL);
- ok(ret == 8 ||
- broken(ret == 7) /* Win9x */,
- "Expected FormatMessageA to return 8, got %d\n", ret);
- ok(!strcmp("%%% %.%!", out) ||
- broken(!strcmp("%%% %.!", out)) /* Win9x */,
- "Expected output string \"%%%%%% %%.%%!\", got %s\n", out);
+ ok(ret == 8, "Expected FormatMessageA to return 8, got %d\n", ret);
+ ok(!strcmp("%%% %.%!", out), "Expected output string \"%%%%%% %%.%%!\", got %s\n", out);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS, "%n%r%t", 0, 0, out,
sizeof(out)/sizeof(CHAR), NULL);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0, 0, out,
sizeof(out)/sizeof(CHAR), NULL);
- ok(!strcmp("hi ", out) ||
- broken(!strcmp("hi\r\n", out)), /* Win9x */
- "Expected output string \"hi \", got %s\n", out);
- ok(ret == 3 ||
- broken(ret == 4), /* Win9x */
- "Expected FormatMessageA to return 3, got %d\n", ret);
+ ok(!strcmp("hi ", out), "Expected output string \"hi \", got %s\n", out);
+ ok(ret == 3, "Expected FormatMessageA to return 3, got %d\n", ret);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0, 0, out,
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 0, NULL);
error = GetLastError();
ok(!ret, "FormatMessageA returned %u\n", ret);
- ok(error == ERROR_INSUFFICIENT_BUFFER ||
- error == ERROR_INVALID_PARAMETER, /* win9x */
- "last error %u\n", error);
+ ok(error == ERROR_INSUFFICIENT_BUFFER, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 1, NULL);
error = GetLastError();
ok(!ret, "FormatMessageA returned %u\n", ret);
- ok(error == ERROR_INSUFFICIENT_BUFFER ||
- error == ERROR_INVALID_PARAMETER, /* win9x */
- "last error %u\n", error);
+ ok(error == ERROR_INSUFFICIENT_BUFFER, "last error %u\n", error);
if (0) /* crashes on Windows */
{
SetLastError(0xdeadbeef);
- ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 256, NULL);
- error = GetLastError();
- ok(!ret, "FormatMessageA returned %u\n", ret);
- trace("last error %u\n", error);
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 0, 0, NULL, 256, NULL);
}
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);
error = GetLastError();
ok(!ret, "FormatMessageA returned %u\n", ret);
- ok(error == ERROR_NOT_ENOUGH_MEMORY ||
- error == ERROR_INVALID_PARAMETER, /* win9x */
- "last error %u\n", error);
+ ok(error == ERROR_NOT_ENOUGH_MEMORY, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 1, NULL);
error = GetLastError();
ok(!ret, "FormatMessageA returned %u\n", ret);
- ok(error == ERROR_NOT_ENOUGH_MEMORY ||
- error == ERROR_INVALID_PARAMETER, /* win9x */
- "last error %u\n", error);
+ ok(error == ERROR_NOT_ENOUGH_MEMORY, "last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 256, NULL);
error = GetLastError();
ok(!ret, "FormatMessageA returned %u\n", ret);
- ok(error == ERROR_NOT_ENOUGH_MEMORY ||
- error == ERROR_INVALID_PARAMETER, /* win9x */
- "last error %u\n", error);
+ ok(error == ERROR_NOT_ENOUGH_MEMORY, "last error %u\n", error);
}
static void test_message_null_buffer_wide(void)
if (0) /* crashes on Windows */
{
buf = (WCHAR *)0xdeadbeef;
- ret = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, 0, 0, (WCHAR *)&buf, 0, NULL);
}
/* Test a message string with an insertion without passing any variadic arguments. */
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
- ok(ret == 0 ||
- broken(ret != 0), /* Win9x */
- "FormatMessageA returned non-zero\n");
+ ok(ret == 0, "FormatMessageA returned non-zero\n");
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_ARGUMENT_ARRAY, h, 193 /* ERROR_BAD_EXE_FORMAT */,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
- ok(ret == 0 ||
- broken(ret != 0), /* Win9x */
- "FormatMessageA returned non-zero\n");
+ ok(ret == 0, "FormatMessageA returned non-zero\n");
- /*Test nonexistent messageID with varying language ID's Note: FormatMessageW behaves the same*/
+ /*Test nonexistent messageID with varying language IDs Note: FormatMessageW behaves the same*/
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
ptr = (char *)0xdeadbeef;
ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER, "test", 0, 0, (char *)&ptr, 0, NULL);
ok(ret == 0, "Expected FormatMessageA to return 0, got %u\n", ret);
- ok(ptr == NULL ||
- broken(ptr == (char *)0xdeadbeef), /* Win9x */
- "Expected output pointer to be initialized to NULL, got %p\n", ptr);
+ ok(ptr == NULL, "Expected output pointer to be initialized to NULL, got %p\n", ptr);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected GetLastError() to return ERROR_INVALID_PARAMETER, got %u\n",
GetLastError());
UINT flags;
HGLOBAL gbl;
HGLOBAL hsecond;
- SIZE_T size;
+ SIZE_T size, size2;
/* Heap*() functions */
mem = HeapAlloc(GetProcessHeap(), 0, 0);
"MAGIC_DEAD)\n", mem, GetLastError(), GetLastError());
GlobalFree(gbl);
+
+ /* trying to get size from data pointer (GMEM_MOVEABLE) */
+ gbl = GlobalAlloc(GMEM_MOVEABLE, 0x123);
+ ok(gbl != NULL, "returned NULL\n");
+ mem = GlobalLock(gbl);
+ ok(mem != NULL, "returned NULL.\n");
+ ok(gbl != mem, "unexpectedly equal.\n");
+
+ size = GlobalSize(gbl);
+ size2 = GlobalSize(mem);
+ ok(size == 0x123, "got %lu\n", size);
+ ok(size2 == 0x123, "got %lu\n", size2);
+
+ GlobalFree(gbl);
+
+ /* trying to get size from data pointer (GMEM_FIXED) */
+ gbl = GlobalAlloc(GMEM_FIXED, 0x123);
+ ok(gbl != NULL, "returned NULL\n");
+ mem = GlobalLock(gbl);
+ ok(mem != NULL, "returned NULL.\n");
+ ok(gbl == mem, "got %p, %p.\n", gbl, mem);
+
+ size = GlobalSize(gbl);
+ ok(size == 0x123, "got %lu\n", size);
+
+ GlobalFree(gbl);
+
+ size = GlobalSize((void *)0xdeadbee0);
+ ok(size == 0, "got %lu\n", size);
+
}
static void test_obsolete_flags(void)
if (0) /* crashes under XP */
{
size = 0;
- ret = pHeapQueryInformation(0,
+ pHeapQueryInformation(0,
HeapCompatibilityInformation,
&info, sizeof(info), &size);
size = 0;
- ret = pHeapQueryInformation(GetProcessHeap(),
+ pHeapQueryInformation(GetProcessHeap(),
HeapCompatibilityInformation,
NULL, sizeof(info), &size);
}
if (!strcmp( keyname + strlen(keyname) - 3, ".so" )) keyname[strlen(keyname) - 3] = 0;
err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyname, &hkey );
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ skip("Not authorized to change the image file execution options\n");
+ return;
+ }
ok( !err, "failed to create '%s' error %u\n", keyname, err );
if (err) return;
/*
* Unit test suite for the PE loader.
*
- * Copyright 2006 Dmitry Timoshkov
+ * Copyright 2006,2011 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
IMAGE_FILE_MACHINE_AMD64, /* Machine */
#elif defined __powerpc__
IMAGE_FILE_MACHINE_POWERPC, /* Machine */
+#elif defined __sparc__
+ IMAGE_FILE_MACHINE_SPARC, /* Machine */
+#elif defined __arm__
+ IMAGE_FILE_MACHINE_ARM, /* Machine */
#else
# error You must specify the machine type
#endif
WORD number_of_sections, size_of_optional_header;
DWORD section_alignment, file_alignment;
DWORD size_of_image, size_of_headers;
- DWORD error; /* 0 means LoadLibrary should succeed */
- DWORD alt_error; /* alternate error */
+ DWORD errors[4]; /* 0 means LoadLibrary should succeed */
} td[] =
{
{ &dos_header, sizeof(dos_header),
1, 0, 0, 0, 0, 0,
- ERROR_BAD_EXE_FORMAT
+ { ERROR_BAD_EXE_FORMAT }
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_BAD_EXE_FORMAT /* XP doesn't like too small image size */
+ { ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_SUCCESS
+ { ERROR_SUCCESS }
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
0x1f00,
0x1000,
- ERROR_SUCCESS
+ { ERROR_SUCCESS }
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_SUCCESS, ERROR_INVALID_ADDRESS /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_INVALID_ADDRESS } /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_BAD_EXE_FORMAT /* XP doesn't like alignments */
+ { ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_SUCCESS
+ { ERROR_SUCCESS }
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
0x200,
- ERROR_SUCCESS
+ { ERROR_SUCCESS }
},
/* Mandatory are all fields up to SizeOfHeaders, everything else
* is really optional (at least that's true for XP).
1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER),
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS,
+ ERROR_NOACCESS }
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
0xd0, /* beyond of the end of file */
0xc0, /* beyond of the end of file */
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
0x1000,
0,
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
1,
0,
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
},
#if 0 /* not power of 2 alignments need more test cases */
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300,
1,
0,
- ERROR_BAD_EXE_FORMAT /* alignment is not power of 2 */
+ { ERROR_BAD_EXE_FORMAT } /* alignment is not power of 2 */
},
#endif
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
1,
0,
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1,
1,
0,
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
0,
0,
- ERROR_BAD_EXE_FORMAT /* image size == 0 -> failure */
+ { ERROR_BAD_EXE_FORMAT } /* image size == 0 -> failure */
},
/* the following data mimics the PE image which upack creates */
{ &dos_header, 0x10,
1, 0x148, 0x1000, 0x200,
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
0x200,
- ERROR_SUCCESS
+ { ERROR_SUCCESS }
},
/* Minimal PE image that XP is able to load: 92 bytes */
{ &dos_header, 0x04,
0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
1,
0,
- ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
+ { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
}
};
static const char filler[0x1000];
SYSTEM_INFO si;
char temp_path[MAX_PATH];
char dll_name[MAX_PATH];
+ SIZE_T size;
+ BOOL ret;
GetSystemInfo(&si);
trace("system page size 0x%04x\n", si.dwPageSize);
}
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, td[i].dos_header, td[i].size_of_dos_header, &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, td[i].dos_header, td[i].size_of_dos_header, &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
nt_header.FileHeader.NumberOfSections = td[i].number_of_sections;
nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header;
nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image;
nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers;
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
if (nt_header.FileHeader.SizeOfOptionalHeader)
{
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, &nt_header.OptionalHeader,
- min(nt_header.FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
- &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, &nt_header.OptionalHeader,
+ min(nt_header.FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
+ &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
if (nt_header.FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
{
file_align = nt_header.FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER);
assert(file_align < sizeof(filler));
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, filler, file_align, &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
}
}
}
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, §ion, sizeof(section), &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
/* section data */
SetLastError(0xdeadbeef);
- ok(WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL),
- "WriteFile error %d\n", GetLastError());
+ ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
}
file_size = GetFileSize(hfile, NULL);
{
MEMORY_BASIC_INFORMATION info;
- ok( td[i].error == ERROR_SUCCESS, "%d: should have failed\n", i );
+ ok( td[i].errors[0] == ERROR_SUCCESS, "%d: should have failed\n", i );
SetLastError(0xdeadbeef);
- ok(VirtualQuery(hlib, &info, sizeof(info)) == sizeof(info),
+ size = VirtualQuery(hlib, &info, sizeof(info));
+ ok(size == sizeof(info),
"%d: VirtualQuery error %d\n", i, GetLastError());
ok(info.BaseAddress == hlib, "%d: %p != %p\n", i, info.BaseAddress, hlib);
ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
SetLastError(0xdeadbeef);
- ok(VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info)) == sizeof(info),
+ size = VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info));
+ ok(size == sizeof(info),
"%d: VirtualQuery error %d\n", i, GetLastError());
if (nt_header.OptionalHeader.SectionAlignment == si.dwPageSize ||
nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment)
if (nt_header.FileHeader.NumberOfSections)
{
SetLastError(0xdeadbeef);
- ok(VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info)) == sizeof(info),
+ size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
+ ok(size == sizeof(info),
"%d: VirtualQuery error %d\n", i, GetLastError());
if (nt_header.OptionalHeader.SectionAlignment < si.dwPageSize)
{
ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n");
SetLastError(0xdeadbeef);
- ok(FreeLibrary(hlib), "FreeLibrary error %d\n", GetLastError());
+ ret = FreeLibrary(hlib);
+ ok(ret, "FreeLibrary error %d\n", GetLastError());
SetLastError(0xdeadbeef);
hlib = GetModuleHandle(dll_name);
ok(hlib != 0, "GetModuleHandle error %u\n", GetLastError());
SetLastError(0xdeadbeef);
- ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
+ ret = FreeLibrary(hlib_as_data_file);
+ ok(ret, "FreeLibrary error %d\n", GetLastError());
hlib = GetModuleHandle(dll_name);
ok(!hlib, "GetModuleHandle should fail\n");
ok(!hlib, "GetModuleHandle should fail\n");
SetLastError(0xdeadbeef);
- ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
+ ret = FreeLibrary(hlib_as_data_file);
+ ok(ret, "FreeLibrary error %d\n", GetLastError());
}
else
{
- ok(td[i].error || td[i].alt_error, "%d: LoadLibrary should succeed\n", i);
+ BOOL error_match;
+ int error_index;
- if (GetLastError() == ERROR_GEN_FAILURE) /* Win9x, broken behaviour */
+ error_match = FALSE;
+ for (error_index = 0;
+ ! error_match && error_index < sizeof(td[i].errors) / sizeof(DWORD);
+ error_index++)
{
- trace("skipping the loader test on Win9x\n");
- DeleteFile(dll_name);
- return;
+ error_match = td[i].errors[error_index] == GetLastError();
}
-
- ok(td[i].error == GetLastError() || td[i].alt_error == GetLastError(),
- "%d: expected error %d or %d, got %d\n",
- i, td[i].error, td[i].alt_error, GetLastError());
+ ok(error_match, "%d: unexpected error %d\n", i, GetLastError());
}
SetLastError(0xdeadbeef);
- ok(DeleteFile(dll_name), "DeleteFile error %d\n", GetLastError());
+ ret = DeleteFile(dll_name);
+ ok(ret, "DeleteFile error %d\n", GetLastError());
}
}
}
}
+static void test_section_access(void)
+{
+ static const struct test_data
+ {
+ DWORD scn_file_access, scn_page_access;
+ } td[] =
+ {
+ { 0, PAGE_NOACCESS },
+ { IMAGE_SCN_MEM_READ, PAGE_READONLY },
+ { IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
+ { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ },
+ { IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
+ { IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
+
+ { IMAGE_SCN_CNT_INITIALIZED_DATA, PAGE_NOACCESS },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
+ { IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
+
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA, PAGE_NOACCESS },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ, PAGE_READONLY },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE, PAGE_WRITECOPY },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_READ },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY },
+ { IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE, PAGE_EXECUTE_WRITECOPY }
+ };
+ static const char filler[0x1000];
+ static const char section_data[0x10] = "section data";
+ int i;
+ DWORD dummy, file_align;
+ HANDLE hfile;
+ HMODULE hlib;
+ SYSTEM_INFO si;
+ char temp_path[MAX_PATH];
+ char dll_name[MAX_PATH];
+ SIZE_T size;
+ MEMORY_BASIC_INFORMATION info;
+ BOOL ret;
+
+ GetSystemInfo(&si);
+ trace("system page size %#x\n", si.dwPageSize);
+
+ /* prevent displaying of the "Unable to load this DLL" message box */
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ GetTempPath(MAX_PATH, temp_path);
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ {
+ GetTempFileName(temp_path, "ldr", 0, dll_name);
+
+ /*trace("creating %s\n", dll_name);*/
+ hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ if (hfile == INVALID_HANDLE_VALUE)
+ {
+ ok(0, "could not create %s\n", dll_name);
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ nt_header.FileHeader.NumberOfSections = 1;
+ nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+
+ nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
+ nt_header.OptionalHeader.FileAlignment = 0x200;
+ nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + si.dwPageSize;
+ nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ section.SizeOfRawData = sizeof(section_data);
+ section.PointerToRawData = nt_header.OptionalHeader.FileAlignment;
+ section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
+ section.Misc.VirtualSize = section.SizeOfRawData;
+ section.Characteristics = td[i].scn_file_access;
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, §ion, sizeof(section), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders;
+ assert(file_align < sizeof(filler));
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ /* section data */
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ CloseHandle(hfile);
+
+ SetLastError(0xdeadbeef);
+ hlib = LoadLibrary(dll_name);
+ ok(ret, "LoadLibrary error %d\n", GetLastError());
+
+ size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
+ ok(size == sizeof(info),
+ "%d: VirtualQuery error %d\n", i, GetLastError());
+ ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
+ ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
+ /* FIXME: remove the condition below once Wine is fixed */
+ if ((td[i].scn_file_access & IMAGE_SCN_MEM_WRITE) &&
+ (td[i].scn_file_access & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
+ todo_wine ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
+ else
+ ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
+ ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
+ ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
+ ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State);
+ ok(info.Type == SEC_IMAGE, "%d: %#x != SEC_IMAGE\n", i, info.Type);
+ if (info.Protect != PAGE_NOACCESS)
+ ok(!memcmp((const char *)info.BaseAddress, section_data, section.SizeOfRawData), "wrong section data\n");
+
+ SetLastError(0xdeadbeef);
+ ret = FreeLibrary(hlib);
+ ok(ret, "FreeLibrary error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = DeleteFile(dll_name);
+ ok(ret, "DeleteFile error %d\n", GetLastError());
+ }
+}
+
START_TEST(loader)
{
test_Loader();
test_ImportDescriptors();
+ test_section_access();
}
static HMODULE hKernel32;
static WORD enumCount;
-typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
- DWORD, LONG_PTR);
-static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
-typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
- LGRPID, DWORD, LONG_PTR);
-static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
-typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
- DWORD, LONG_PTR);
-static EnumUILanguagesAFn pEnumUILanguagesA;
-
-typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
-static FoldStringAFn pFoldStringA;
-typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
-static FoldStringWFn pFoldStringW;
-
-typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
-static IsValidLanguageGroupFn pIsValidLanguageGroup;
+static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
+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 *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT);
+static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT);
+static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD);
static void InitFunctionPointers(void)
{
pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
+ pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx");
}
#define eq(received, expected, label, type) \
ret = lstrcmpi("#", ".");
todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
+
+ lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
+
+ /* \xB9 character lies between a and b */
+ ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
+ todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
+ ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
+ ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
}
static void test_LCMapStringA(void)
ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
/* Wine (correctly) maps all Unicode 4.0+ digits */
- isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
+ isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
(ch >= 0x1369 && ch <= 0x1371),
"MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
}
pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
}
+static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
+{
+ trace( "%s %x\n", wine_dbgstr_w(name), flags );
+ return TRUE;
+}
+
+static void test_EnumSystemLocalesEx(void)
+{
+ BOOL ret;
+
+ if (!pEnumSystemLocalesEx)
+ {
+ win_skip( "EnumSystemLocalesEx not available\n" );
+ return;
+ }
+ SetLastError( 0xdeadbeef );
+ ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 );
+ ok( !ret, "should have failed\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL );
+ ok( ret, "failed err %u\n", GetLastError() );
+}
static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
LONG_PTR lParam)
/* IDATE */
SetLastError(0);
- bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
+ bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, "test_SetLocaleInfoA");
ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
/* ILDATE */
SetLastError(0);
- bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
+ bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, "test_SetLocaleInfoA");
ok(!bRet && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
}
}
}
+/*
+ * The CT_TYPE1 has varied over windows version.
+ * The current target for correct behavior is windows 7.
+ * There was a big shift between windows 2000 (first introduced) and windows Xp
+ * Most of the old values below are from windows 2000.
+ * A smaller subset of changes happened between windows Xp and Window vista/7
+ */
+static void test_GetStringTypeW(void)
+{
+ static const WCHAR blanks[] = {0x9, 0x20, 0xa0, 0x3000, 0xfeff};
+ static const WORD blanks_new[] = {C1_SPACE | C1_CNTRL | C1_BLANK | C1_DEFINED,
+ C1_SPACE | C1_BLANK | C1_DEFINED,
+ C1_SPACE | C1_BLANK | C1_DEFINED,
+ C1_SPACE | C1_BLANK | C1_DEFINED,
+ C1_CNTRL | C1_BLANK | C1_DEFINED};
+ static const WORD blanks_old[] ={C1_SPACE | C1_CNTRL | C1_BLANK,
+ C1_SPACE | C1_BLANK,
+ C1_SPACE | C1_BLANK,
+ C1_SPACE | C1_BLANK,
+ C1_SPACE | C1_BLANK};
+
+ static const WCHAR undefined[] = {0x378, 0x379, 0x604, 0xfff8, 0xfffe};
+
+ /* Lu, Ll, Lt */
+ static const WCHAR alpha[] = {0x47, 0x67, 0x1c5};
+ static const WORD alpha_old[] = {C1_UPPER | C1_ALPHA,
+ C1_LOWER | C1_ALPHA,
+ C1_UPPER | C1_LOWER | C1_ALPHA,
+ C1_ALPHA};
+
+ /* Sk, Sk, Mn, So, Me */
+ static const WCHAR oldpunc[] = { 0x2c2, 0x2e5, 0x322, 0x482, 0x6de,
+ /* Sc, Sm, No,*/
+ 0xffe0, 0xffe9, 0x2153};
+
+ /* Lm, Nl, Cf, 0xad(Cf), 0x1f88 (Lt), Lo, Mc */
+ static const WCHAR changed[] = {0x2b0, 0x2160, 0x600, 0xad, 0x1f88, 0x294, 0x903};
+ static const WORD changed_old[] = { C1_PUNCT, C1_PUNCT, 0, C1_PUNCT, C1_UPPER | C1_ALPHA, C1_ALPHA, C1_PUNCT };
+ static const WORD changed_xp[] = {C1_ALPHA | C1_DEFINED,
+ C1_ALPHA | C1_DEFINED,
+ C1_CNTRL | C1_DEFINED,
+ C1_PUNCT | C1_DEFINED,
+ C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
+ C1_ALPHA | C1_LOWER | C1_DEFINED,
+ C1_ALPHA | C1_DEFINED };
+ static const WORD changed_new[] = { C1_ALPHA | C1_DEFINED,
+ C1_ALPHA | C1_DEFINED,
+ C1_CNTRL | C1_DEFINED,
+ C1_PUNCT | C1_CNTRL | C1_DEFINED,
+ C1_UPPER | C1_LOWER | C1_ALPHA | C1_DEFINED,
+ C1_ALPHA | C1_DEFINED,
+ C1_DEFINED
+ };
+ /* Pc, Pd, Ps, Pe, Pi, Pf, Po*/
+ static const WCHAR punct[] = { 0x5f, 0x2d, 0x28, 0x29, 0xab, 0xbb, 0x21 };
+
+ static const WCHAR punct_special[] = {0x24, 0x2b, 0x3c, 0x3e, 0x5e, 0x60,
+ 0x7c, 0x7e, 0xa2, 0xbe, 0xd7, 0xf7};
+ static const WCHAR digit_special[] = {0xb2, 0xb3, 0xb9};
+ static const WCHAR lower_special[] = {0x2071, 0x207f};
+ static const WCHAR cntrl_special[] = {0x070f, 0x200c, 0x200d,
+ 0x200e, 0x200f, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e,
+ 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0xfeff,
+ 0xfff9, 0xfffa, 0xfffb};
+ static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
+
+ WORD types[20];
+ int i;
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, blanks, 5, types);
+ for (i = 0; i < 5; i++)
+ ok(types[i] == blanks_new[i] || broken(types[i] == blanks_old[i] || broken(types[i] == 0)), "incorrect type1 returned for %x -> (%x != %x)\n",blanks[i],types[i],blanks_new[i]);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, alpha, 3, types);
+ for (i = 0; i < 3; i++)
+ ok(types[i] == (C1_DEFINED | alpha_old[i]) || broken(types[i] == alpha_old[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",alpha[i], types[i],(C1_DEFINED | alpha_old[i]));
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, undefined, 5, types);
+ for (i = 0; i < 5; i++)
+ ok(types[i] == 0, "incorrect types returned for %x -> (%x != 0)\n",undefined[i], types[i]);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, oldpunc, 8, types);
+ for (i = 0; i < 8; i++)
+ ok(types[i] == C1_DEFINED || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",oldpunc[i], types[i], C1_DEFINED);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, changed, 7, types);
+ for (i = 0; i < 7; i++)
+ ok(types[i] == changed_new[i] || broken(types[i] == changed_old[i]) || broken(types[i] == changed_xp[i]) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",changed[i], types[i], changed_new[i]);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, punct, 7, types);
+ for (i = 0; i < 7; i++)
+ ok(types[i] == (C1_PUNCT | C1_DEFINED) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x != %x)\n",punct[i], types[i], (C1_PUNCT | C1_DEFINED));
+
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, punct_special, 12, types);
+ for (i = 0; i < 12; i++)
+ ok(types[i] & C1_PUNCT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have %x)\n",punct_special[i], types[i], C1_PUNCT);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, digit_special, 3, types);
+ for (i = 0; i < 3; i++)
+ ok(types[i] & C1_DIGIT || broken(types[i] == 0), "incorrect types returned for %x -> (%x doest not have = %x)\n",digit_special[i], types[i], C1_DIGIT);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, lower_special, 2, types);
+ for (i = 0; i < 2; i++)
+ ok(types[i] & C1_LOWER || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",lower_special[i], types[i], C1_LOWER);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, cntrl_special, 20, types);
+ for (i = 0; i < 20; i++)
+ ok(types[i] & C1_CNTRL || broken(types[i] == (C1_BLANK|C1_SPACE)) || broken(types[i] == C1_PUNCT) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",cntrl_special[i], types[i], C1_CNTRL);
+
+ memset(types,0,sizeof(types));
+ GetStringTypeW(CT_CTYPE1, space_special, 3, types);
+ for (i = 0; i < 3; i++)
+ ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE );
+}
+
START_TEST(locale)
{
InitFunctionPointers();
test_FoldStringW();
test_ConvertDefaultLocale();
test_EnumSystemLanguageGroupsA();
+ test_EnumSystemLocalesEx();
test_EnumLanguageGroupLocalesA();
test_SetLocaleInfoA();
test_EnumUILanguageA();
test_GetCPInfo();
+ test_GetStringTypeW();
/* this requires collation table patch to make it MS compatible */
if (0) test_sorting();
}
/* open a mailslot with a null name */
hSlot = CreateMailslot( NULL, 0, 0, NULL );
- ok( hSlot == INVALID_HANDLE_VALUE || broken(hSlot != INVALID_HANDLE_VALUE), /* win9x */
- "Created mailslot with invalid name\n");
- if (hSlot == INVALID_HANDLE_VALUE)
- ok( GetLastError() == ERROR_PATH_NOT_FOUND,
- "error should be ERROR_PATH_NOT_FOUND\n");
- else /* succeeds on win9x */
- CloseHandle( hSlot );
+ ok( hSlot == INVALID_HANDLE_VALUE, "Created mailslot with invalid name\n");
+ ok( GetLastError() == ERROR_PATH_NOT_FOUND, "error should be ERROR_PATH_NOT_FOUND\n");
/* valid open, but with wacky parameters ... then check them */
hSlot = CreateMailslot( szmspath, -1, -1, NULL );
count = 0;
memset(buffer, 0, sizeof buffer);
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
- ok( !ret || broken(ret), /* win9x */ "slot read\n");
+ ok( !ret, "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
ok( !WriteFile( hSlot, buffer, sizeof buffer, &count, NULL),
/* now open the client with the correct sharing mode */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (hWriter == INVALID_HANDLE_VALUE) /* win9x doesn't like GENERIC_READ */
- hWriter = CreateFile(szmspath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot err %u\n", GetLastError());
/*
* whether we can read or write the mailslot
*/
ret = ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL);
- ok( !ret || broken(ret), /* win9x */ "slot read\n");
+ ok( !ret, "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
ok( !WriteFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
/* but not again */
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
- ok( !ret || broken(ret), /* win9x */ "slot read\n");
+ ok( !ret, "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
/* check there's still no data */
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
- ok( !ret || broken(ret), /* win9x */ "slot read\n");
+ ok( !ret, "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
"getmailslotinfo failed\n");
ok( dwNext == 1, "dwNext incorrect\n");
todo_wine
- ok( dwMsgCount == 3 || broken(dwMsgCount == 2), /* win9x */
- "dwMsgCount incorrect %u\n", dwMsgCount);
+ ok( dwMsgCount == 3, "dwMsgCount incorrect %u\n", dwMsgCount);
buffer[0]=buffer[1]=0;
"getmailslotinfo failed\n");
ok( dwNext == 2, "dwNext incorrect\n");
todo_wine {
- ok( dwMsgCount == 2 || broken(dwMsgCount == 1), /* win9x */
- "dwMsgCount incorrect %u\n", dwMsgCount);
+ ok( dwMsgCount == 2, "dwMsgCount incorrect %u\n", dwMsgCount);
}
/* read the second message */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
- ok( dwNext == 0 || broken(dwNext == ~0u), /* win9x */ "dwNext incorrect %u\n", dwNext);
+ ok( dwNext == 0, "dwNext incorrect %u\n", dwNext);
todo_wine {
- ok( dwMsgCount == 1 || broken(dwMsgCount == 0), /* win9x */
- "dwMsgCount incorrect %u\n", dwMsgCount);
+ ok( dwMsgCount == 1, "dwMsgCount incorrect %u\n", dwMsgCount);
}
/* read the 3rd (zero length) message */
/* check that reads fail */
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
- ok( !ret || broken(ret), /* win9x */ "3rd slot read succeeded\n");
+ ok( !ret, "3rd slot read succeeded\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
memset(buffer, 0, sizeof buffer);
dwTimeout = GetTickCount();
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
- ok( GetLastError() == ERROR_SEM_TIMEOUT || broken(GetLastError() == ERROR_ACCESS_DENIED), /* win9x */
- "wrong error %u\n", GetLastError() );
+ ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
dwTimeout = GetTickCount() - dwTimeout;
ok( dwTimeout >= 990, "timeout too short %u\n", dwTimeout );
ok( CloseHandle( hSlot ), "closing the mailslot\n");
CHAR path[MAX_PATH];
HMODULE hmodule;
HANDLE hfile;
+ BOOL ret;
hfile = CreateFileA("testfile.dll", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
ok(hmodule != 0, "Expected valid module handle\n");
SetLastError(0xdeadbeef);
- ok(FreeLibrary(hmodule),
- "Expected to be able to free the module, failed with %d\n",
- GetLastError());
+ ret = FreeLibrary(hmodule);
+ ok(ret, "Expected to be able to free the module, failed with %d\n", GetLastError());
SetLastError(0xdeadbeef);
- ok(!FreeLibrary(hmodule),
- "Unexpected ability to free the module, failed with %d\n",
- GetLastError());
+ ret = FreeLibrary(hmodule);
+ ok(!ret, "Unexpected ability to free the module, failed with %d\n", GetLastError());
CloseHandle(hmodule);
{
CHAR tmppath[MAX_PATH], /*path to TEMP */
tmpstr[MAX_PATH],
- tmpstr1[MAX_PATH];
+ tmpstr1[MAX_PATH],
+ invalid_dir[MAX_PATH];
+
DWORD len,len1,drives;
INT id;
HANDLE hndl;
BOOL bRes;
+ UINT unique;
*curDrive = *otherDrive = NOT_A_VALID_DRIVE;
ok(len1==len+1 || broken(len1 == len), /* WinME */
"GetTempPathA should return string length %d instead of %d\n",len+1,len1);
-/* Test GetTmpFileNameA
- The only test we do here is whether GetTempFileNameA passes or not.
- We do not thoroughly test this function yet (specifically, whether
- it behaves correctly when 'unique' is non zero)
-*/
+/* Test GetTmpFileNameA */
ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
}
+ for(unique=0;unique<3;unique++) {
+ /* Nonexistent path */
+ sprintf(invalid_dir, "%s\\%s",tmppath,"non_existent_dir_1jwj3y32nb3");
+ SetLastError(0xdeadbeef);
+ ok(!GetTempFileNameA(invalid_dir,"tfn",unique,newdir),"GetTempFileNameA should have failed\n");
+ ok(GetLastError()==ERROR_DIRECTORY || broken(GetLastError()==ERROR_PATH_NOT_FOUND)/*win98*/,
+ "got %d, expected ERROR_DIRECTORY\n", GetLastError());
+
+ /* Check return value for unique !=0 */
+ if(unique) {
+ ok((GetTempFileNameA(tmppath,"tfn",unique,newdir) == unique),"GetTempFileNameA unexpectedly failed\n");
+ /* if unique != 0, the actual temp files are not created: */
+ ok(!DeleteFileA(newdir) && GetLastError() == ERROR_FILE_NOT_FOUND,"Deleted a file that shouldn't exist!\n");
+ }
+ }
+
/* Find first valid drive letter that is neither newdir[0] nor curDrive */
drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
if( *curDrive != NOT_A_VALID_DRIVE)
*/
if (0)
{
- SetLastError( 0xdeadbeef );
- len = GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
- ok( len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
- "GetCurrentDirectoryA failed to fail %u err %u\n", len, GetLastError() );
+ GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
}
/* SetCurrentDirectoryA shouldn't care whether the string has a
ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
}
+/* test that short path name functions work regardless of case */
+static void test_ShortPathCase(const char *tmpdir, const char *dirname,
+ const char *filename)
+{
+ char buf[MAX_PATH], shortbuf[MAX_PATH];
+ HANDLE hndl;
+ int i;
+
+ snprintf(buf,sizeof(buf),"%s\\%s\\%s",tmpdir,dirname,filename);
+ GetShortPathNameA(buf,shortbuf,sizeof(shortbuf));
+ hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
+ ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
+ CloseHandle(hndl);
+ /* Now for the real test */
+ for(i=0;i<strlen(shortbuf);i++)
+ if (i % 2)
+ shortbuf[i] = tolower(shortbuf[i]);
+ hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
+ ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
+ CloseHandle(hndl);
+}
+
/* This routine will test Get(Full|Short|Long)PathNameA */
static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
{
sprintf(tmpstr,"Long File %c",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
}
+ /* Now try it on mixed case short names */
+ test_ShortPathCase(curdir,SHORTDIR,LONGFILE);
+ test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
+ test_ShortPathCase(curdir,LONGDIR,LONGFILE);
}
static void test_GetTempPathA(char* tmp_dir)
/* NULL buffer with length crashes on Windows */
if (0)
- length = pGetLongPathNameW(shortpath, NULL, 20);
+ pGetLongPathNameW(shortpath, NULL, 20);
ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
total = res;
/* this crashes on XP */
- if (0) res = GetSystemDirectory(NULL, total);
+ if (0)
+ GetSystemDirectory(NULL, total);
SetLastError(0xdeadbeef);
res = GetSystemDirectory(NULL, total-1);
total = res;
/* this crashes on XP */
- if (0) res = GetWindowsDirectory(NULL, total);
+ if (0)
+ GetWindowsDirectory(NULL, total);
SetLastError(0xdeadbeef);
res = GetWindowsDirectory(NULL, total-1);
/* Crashes in Windows */
if (0)
- ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
+ pNeedCurrentDirectoryForExePathA(NULL);
SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
/* Crashes in Windows */
if (0)
- ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
+ pNeedCurrentDirectoryForExePathW(NULL);
SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
SetLastError(0xdeadbeef);
ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
ok(ret == 0, "Expected failure, got %d\n", ret);
- ok(GetLastError() == ERROR_INVALID_PARAMETER ||
- broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* win9x */,
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
}
return;
}
- /* SearchPathW is a stub on win9x and doesn't return sane error,
- so quess if it's implemented indirectly */
- SetLastError(0xdeadbeef);
- GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
- if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- win_skip("SearchPathW not implemented\n");
- return;
- }
-
if (0)
{
/* NULL filename, crashes on nt4 */
- SetLastError(0xdeadbeef);
- ret = pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
- ok(ret == 0, "Expected failure, got %d\n", ret);
- ok(GetLastError() == ERROR_INVALID_PARAMETER,
- "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
+ pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
}
/* empty filename */
{
char output[MAX_PATH], *filepart;
DWORD ret;
- int is_win9x, i;
+ int i;
const struct
{
DWORD len;
LPSTR buffer;
LPSTR *lastpart;
- int win9x_crash;
} invalid_parameters[] =
{
- {NULL, 0, NULL, NULL, 1},
- {NULL, MAX_PATH, NULL, NULL, 1},
- {NULL, MAX_PATH, output, NULL, 1},
- {NULL, MAX_PATH, output, &filepart, 1},
+ {NULL, 0, NULL, NULL},
+ {NULL, MAX_PATH, NULL, NULL},
+ {NULL, MAX_PATH, output, NULL},
+ {NULL, MAX_PATH, output, &filepart},
{"", 0, NULL, NULL},
{"", MAX_PATH, NULL, NULL},
{"", MAX_PATH, output, NULL},
{"", MAX_PATH, output, &filepart},
};
- SetLastError(0xdeadbeef);
- ret = GetFullPathNameW(NULL, 0, NULL, NULL);
- is_win9x = !ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED;
-
- if (is_win9x)
- win_skip("Skipping some tests that cause GetFullPathNameA to crash on Win9x\n");
-
for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
{
- if (is_win9x && invalid_parameters[i].win9x_crash)
- continue;
-
SetLastError(0xdeadbeef);
strcpy(output, "deadbeef");
filepart = (char *)0xdeadbeef;
ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output);
ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
ok(GetLastError() == 0xdeadbeef ||
- GetLastError() == ERROR_BAD_PATHNAME || /* Win9x */
GetLastError() == ERROR_INVALID_NAME, /* Win7 */
"[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
i, GetLastError());
static HANDLE alarm_event;
static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
+static DWORD WINAPI (*pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
+static BOOL user_apc_ran;
+static void CALLBACK user_apc(ULONG_PTR param)
+{
+ user_apc_ran = TRUE;
+}
static void test_CreateNamedPipe(int pipemode)
{
DWORD readden;
DWORD avail;
DWORD lpmode;
+ BOOL ret;
if (pipemode == PIPE_TYPE_BYTE)
trace("test_CreateNamedPipe starting in byte mode\n");
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
- ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%d)\n", GetLastError());
+ ret = WaitNamedPipeA(PIPENAME, 2000);
+ ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
ok(!WaitNamedPipeA(PIPENAME, 1000), "WaitNamedPipe succeeded\n");
+
ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
/* don't try to do i/o if one side couldn't be opened, as it hangs */
return 1;
}
-HANDLE hnp = INVALID_HANDLE_VALUE;
+static HANDLE hnp = INVALID_HANDLE_VALUE;
/** Trivial byte echo server - disconnects after each session */
static DWORD CALLBACK serverThreadMain1(LPVOID arg)
DWORD readden;
DWORD success;
+ user_apc_ran = FALSE;
+ if (i == 0 && pQueueUserAPC) {
+ trace("Queueing an user APC\n"); /* verify the pipe is non alerable */
+ ok(pQueueUserAPC(&user_apc, GetCurrentThread(), 0), "QueueUserAPC failed: %d\n", GetLastError());
+ }
+
/* Wait for client to connect */
trace("Server calling ConnectNamedPipe...\n");
ok(ConnectNamedPipe(hnp, NULL)
ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
+ ok(user_apc_ran == FALSE, "UserAPC ran, pipe using alertable io mode\n");
+
+ if (i == 0 && pQueueUserAPC)
+ SleepEx(0, TRUE); /* get rid of apc */
+
/* Set up next echo server */
hnpNext =
CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
{
int i;
HANDLE hcompletion;
+ BOOL ret;
trace("serverThreadMain4\n");
/* Set up a simple echo server */
ok(success, "DisconnectNamedPipe failed, err %u\n", GetLastError());
}
- ok(CloseHandle(hnp), "CloseHandle named pipe failed, err=%i\n", GetLastError());
- ok(CloseHandle(hcompletion), "CloseHandle completion failed, err=%i\n", GetLastError());
+ ret = CloseHandle(hnp);
+ ok(ret, "CloseHandle named pipe failed, err=%i\n", GetLastError());
+ ret = CloseHandle(hcompletion);
+ ok(ret, "CloseHandle completion failed, err=%i\n", GetLastError());
return 0;
}
BYTE *buffer;
char readbuf[32];
+ user_apc_ran = FALSE;
+ if (pQueueUserAPC)
+ ok(pQueueUserAPC(user_apc, GetCurrentThread(), 0), "couldn't create user apc\n");
+
pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
pipe_attr.bInheritHandle = TRUE;
- pipe_attr.lpSecurityDescriptor = NULL;
+ pipe_attr.lpSecurityDescriptor = NULL;
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
HeapFree(GetProcessHeap(), 0, buffer);
+
+ ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
+ SleepEx(0, TRUE); /* get rid of apc */
}
struct named_pipe_client_params
{
DWORD tid, num;
HANDLE thread, pipe;
- int ret;
+ BOOL ret;
struct overlapped_server_args args;
args.pipe_created = CreateEventA(0, 1, 0, 0);
Sleep(1);
ret = WriteFile(pipe, "x", 1, &num, NULL);
- ok(ret == 1, "ret %d\n", ret);
+ ok(ret, "WriteFile failed with error %d\n", GetLastError());
WaitForSingleObject(thread, INFINITE);
CloseHandle(pipe);
hmod = GetModuleHandle("advapi32.dll");
pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
+ hmod = GetModuleHandle("kernel32.dll");
+ pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
if (test_DisconnectNamedPipe())
return;
static HINSTANCE hkernel32;
static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
+static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
hkernel32 = GetModuleHandleA("kernel32");
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
+ pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
STARTUPINFOA siA;
STARTUPINFOW siW;
int i;
- char* ptrA;
- WCHAR* ptrW;
+ char *ptrA, *ptrA_save;
+ WCHAR *ptrW, *ptrW_save;
char bufA[MAX_PATH];
WCHAR bufW[MAX_PATH];
HANDLE hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
/* output of environment (Ansi) */
- ptrA = GetEnvironmentStringsA();
+ ptrA_save = ptrA = GetEnvironmentStringsA();
if (ptrA)
{
char env_var[MAX_LISTED_ENV_VAR];
ptrA += strlen(ptrA) + 1;
}
childPrintf(hFile, "len=%d\n\n", i);
+ FreeEnvironmentStringsA(ptrA_save);
}
/* output of environment (Unicode) */
- ptrW = GetEnvironmentStringsW();
+ ptrW_save = ptrW = GetEnvironmentStringsW();
if (ptrW)
{
WCHAR env_var[MAX_LISTED_ENV_VAR];
ptrW += lstrlenW(ptrW) + 1;
}
childPrintf(hFile, "len=%d\n\n", i);
+ FreeEnvironmentStringsW(ptrW_save);
}
childPrintf(hFile, "[Misc]\n");
startup.wShowWindow = SW_SHOWNORMAL;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFillAttribute = 0xA55A;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
/* the basics */
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = SW_SHOWNORMAL;
- /* from Frangois */
+ /* from François */
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
/* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
get_file_name(resfile);
/* Use exename to avoid buffer containing things like 'C:' */
- sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+ sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
SetLastError(0xdeadbeef);
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
get_file_name(resfile);
/* Use exename to avoid buffer containing things like 'C:' */
- sprintf(buffer, ".\\%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+ sprintf(buffer, ".\\%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
SetLastError(0xdeadbeef);
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
*(lpFilePart -1 ) = 0;
p = strrchr(fullpath, '\\');
/* Use exename to avoid buffer containing things like 'C:' */
- if (p) sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
- else sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+ if (p) sprintf(buffer, "..%s/%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
+ else sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
SetLastError(0xdeadbeef);
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
/* Use exename to avoid buffer containing things like 'C:' */
if (p) sprintf(buffer, "..%s/%s", p, exename);
else sprintf(buffer, "./%s", exename);
- sprintf(buffer2, "dummy tests/process.c %s \"a\\\"b\\\\\" c\\\" d", resfile);
+ sprintf(buffer2, "dummy tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
SetLastError(0xdeadbeef);
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
/* the basics */
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
GetWindowsDirectoryA( windir, sizeof(windir) );
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
char buffer[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
- char* child_env;
+ char *child_env;
int child_env_len;
- char* ptr;
- char* env;
+ char *ptr;
+ char *ptr2;
+ char *env;
int slen;
memset(&startup, 0, sizeof(startup));
/* the basics */
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
/* child process has changed result file, so let profile functions know about it */
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
-
- cmpEnvironment(GetEnvironmentStringsA());
+
+ env = GetEnvironmentStringsA();
+ cmpEnvironment(env);
release_memory();
assert(DeleteFileA(resfile) != 0);
/* the basics */
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
-
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
+
child_env_len = 0;
- ptr = GetEnvironmentStringsA();
+ ptr = env;
while(*ptr)
{
slen = strlen(ptr)+1;
/* Add space for additional environment variables */
child_env_len += 256;
child_env = HeapAlloc(GetProcessHeap(), 0, child_env_len);
-
+
ptr = child_env;
sprintf(ptr, "=%c:=%s", 'C', "C:\\FOO\\BAR");
ptr += strlen(ptr) + 1;
* - PATH (already set above)
* - the directory definitions (=[A-Z]:=)
*/
- for (env = GetEnvironmentStringsA(); *env; env += strlen(env) + 1)
+ for (ptr2 = env; *ptr2; ptr2 += strlen(ptr2) + 1)
{
- if (strncmp(env, "PATH=", 5) != 0 &&
- strncmp(env, "WINELOADER=", 11) != 0 &&
- !is_str_env_drive_dir(env))
+ if (strncmp(ptr2, "PATH=", 5) != 0 &&
+ strncmp(ptr2, "WINELOADER=", 11) != 0 &&
+ !is_str_env_drive_dir(ptr2))
{
- strcpy(ptr, env);
+ strcpy(ptr, ptr2);
ptr += strlen(ptr) + 1;
}
}
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
/* child process has changed result file, so let profile functions know about it */
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
-
+
cmpEnvironment(child_env);
HeapFree(GetProcessHeap(), 0, child_env);
+ FreeEnvironmentStringsA(env);
release_memory();
assert(DeleteFileA(resfile) != 0);
}
startup.wShowWindow = SW_SHOWNORMAL;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess\n");
ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
startup.wShowWindow = SW_SHOWNORMAL;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
/* get all startup events up to the entry point break exception */
cpOut = GetConsoleOutputCP();
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s console", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\" console", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
startup.hStdError = hChildOutInh;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s stdhandle", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\" stdhandle", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
ok(CloseHandle(hChildInInh), "Closing handle\n");
ok(CloseHandle(hChildOutInh), "Closing handle\n");
startup.wShowWindow = SW_SHOWNORMAL;
get_file_name(resfile);
- sprintf(buffer, "%s tests/process.c %s exit_code", selfname, resfile);
+ sprintf(buffer, "\"%s\" tests/process.c \"%s\" exit_code", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */
void *addr1;
MEMORY_BASIC_INFORMATION info;
SIZE_T dummy, read_bytes;
+ BOOL ret;
/* not exported in all windows versions */
if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
read_bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
- ok(ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes),
- "ReadProcessMemory error %d\n", GetLastError());
+ ret = ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes);
+ ok(ret, "ReadProcessMemory error %d\n", GetLastError());
ok(read_bytes == sizeof(dummy), "wrong read bytes %ld\n", read_bytes);
CloseHandle(hproc);
hproc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
memset(&info, 0xcc, sizeof(info));
- ok(VirtualQueryEx(hproc, addr1, &info, sizeof(info)) == sizeof(info),
- "VirtualQueryEx error %d\n", GetLastError());
+ read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
+ ok(read_bytes == sizeof(info), "VirtualQueryEx error %d\n", GetLastError());
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
/* this is a difference between the ascii and the unicode version
* the unicode version crashes when the size is big enough to hold the result
- * ascii version throughs an error
+ * ascii version through an error
*/
size = 1024;
expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
pGetNativeSystemInfo(&nsi);
if (is_wow64)
{
- if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
- ok(nsi.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
+ ok(S(U(nsi)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
"Expected PROCESSOR_ARCHITECTURE_AMD64, got %d\n",
- nsi.wProcessorArchitecture);
+ S(U(nsi)).wProcessorArchitecture);
ok(nsi.dwProcessorType == PROCESSOR_AMD_X8664,
"Expected PROCESSOR_AMD_X8664, got %d\n",
nsi.dwProcessorType);
}
else
{
- ok(si.wProcessorArchitecture == nsi.wProcessorArchitecture,
+ ok(S(U(si)).wProcessorArchitecture == S(U(nsi)).wProcessorArchitecture,
"Expected no difference for wProcessorArchitecture, got %d and %d\n",
- si.wProcessorArchitecture, nsi.wProcessorArchitecture);
+ S(U(si)).wProcessorArchitecture, S(U(nsi)).wProcessorArchitecture);
ok(si.dwProcessorType == nsi.dwProcessorType,
"Expected no difference for dwProcessorType, got %d and %d\n",
si.dwProcessorType, nsi.dwProcessorType);
}
}
+static void test_RegistryQuota(void)
+{
+ BOOL ret;
+ DWORD max_quota, used_quota;
+
+ if (!pGetSystemRegistryQuota)
+ {
+ win_skip("GetSystemRegistryQuota is not available\n");
+ return;
+ }
+
+ ret = pGetSystemRegistryQuota(NULL, NULL);
+ ok(ret == TRUE,
+ "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+ ret = pGetSystemRegistryQuota(&max_quota, NULL);
+ ok(ret == TRUE,
+ "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+ ret = pGetSystemRegistryQuota(NULL, &used_quota);
+ ok(ret == TRUE,
+ "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+ ret = pGetSystemRegistryQuota(&max_quota, &used_quota);
+ ok(ret == TRUE,
+ "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+}
+
START_TEST(process)
{
int b = init();
test_ProcessName();
test_Handles();
test_SystemInfo();
+ test_RegistryQuota();
/* things that can be tested:
* lookup: check the way program to be executed is searched
* handles: check the handle inheritance stuff (+sec options)
ret=GetPrivateProfileStringW(emptyW, keyW, emptyW, bufW,
sizeof(bufW)/sizeof(bufW[0]), TESTFILE2W);
todo_wine
+ ok(ret == 13, "expected 13, got %u\n", ret);
+ todo_wine
ok(!lstrcmpW(valsectionW,bufW), "expected %s, got %s\n",
wine_dbgstr_w(valsectionW), wine_dbgstr_w(bufW) );
ret=GetPrivateProfileStringW(sW, emptyW, emptyW, bufW,
sizeof(bufW)/sizeof(bufW[0]), TESTFILE2W);
todo_wine
+ ok(ret == 10, "expected 10, got %u\n", ret);
+ todo_wine
ok(!lstrcmpW(valnokeyW,bufW), "expected %s, got %s\n",
wine_dbgstr_w(valnokeyW), wine_dbgstr_w(bufW) );
static const char filename[] = "test_.exe";
static DWORD GLE;
-static int build_exe( void )
+enum constants {
+ page_size = 0x1000,
+ rva_rsrc_start = page_size * 3,
+ max_sections = 3
+};
+
+/* rodata @ [0x1000-0x3000) */
+static const IMAGE_SECTION_HEADER sh_rodata_1 =
+{
+ ".rodata", {2*page_size}, page_size, 2*page_size, page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rodata @ [0x1000-0x4000) */
+static const IMAGE_SECTION_HEADER sh_rodata_2 =
+{
+ ".rodata", {3*page_size}, page_size, 3*page_size, page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rodata @ [0x1000-0x2000) */
+static const IMAGE_SECTION_HEADER sh_rodata_3 =
+{
+ ".rodata", {page_size}, page_size, page_size, page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x3000-0x4000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_1 =
+{
+ ".rsrc\0\0", {page_size}, rva_rsrc_start, page_size, rva_rsrc_start, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x4000-0x5000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_2 =
+{
+ ".rsrc\0\0", {page_size}, 4*page_size, page_size, 4*page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x2000-0x4000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_3 =
+{
+ ".rsrc\0\0", {2*page_size}, rva_rsrc_start-page_size, 2*page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x2000-0x3000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_4 =
+{
+ ".rsrc\0\0", {page_size}, rva_rsrc_start-page_size, page_size, rva_rsrc_start-page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x3000-0x6000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_5 =
+{
+ ".rsrc\0\0", {3*page_size}, rva_rsrc_start, 3*page_size, rva_rsrc_start, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x4000-0x7000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_6 =
+{
+ ".rsrc\0\0", {3*page_size}, 4*page_size, 3*page_size, 4*page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x2000-0x5000) */
+static const IMAGE_SECTION_HEADER sh_rsrc_7 =
+{
+ ".rsrc\0\0", {3*page_size}, 2*page_size, 3*page_size, 2*page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* rsrc @ [0x3000-0x4000), small SizeOfRawData */
+static const IMAGE_SECTION_HEADER sh_rsrc_8 =
+{
+ ".rsrc\0\0", {page_size}, rva_rsrc_start, 8, rva_rsrc_start, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* reloc @ [0x4000-0x5000) */
+static const IMAGE_SECTION_HEADER sh_junk =
+{
+ ".reloc\0", {page_size}, 4*page_size, page_size, 4*page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+/* reloc @ [0x6000-0x7000) */
+static const IMAGE_SECTION_HEADER sh_junk_2 =
+{
+ ".reloc\0", {page_size}, 6*page_size, page_size, 6*page_size, 0, 0, 0, 0,
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+};
+
+typedef struct _sec_build
+{
+ const IMAGE_SECTION_HEADER *sect_in[max_sections];
+} sec_build;
+
+typedef struct _sec_verify
+{
+ const IMAGE_SECTION_HEADER *sect_out[max_sections];
+ DWORD length;
+ int rsrc_section;
+ DWORD NumberOfNamedEntries, NumberOfIdEntries;
+} sec_verify;
+
+static const struct _sec_variants
+{
+ sec_build build;
+ sec_verify chk_none, chk_delete, chk_version, chk_bigdata;
+} sec_variants[] =
+{
+ /* .rsrc is the last section, data directory entry points to whole section */
+ {
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
+ {{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
+ },
+ /* single .rodata section with compatible characteristics, data directory entry points to section end */
+ /* Vista+ - existing section isn't used, new section is created at the end of file */
+ /* NT4/2000/2003 - image is broken */
+#if 0
+ {
+ {{&sh_rodata_2, NULL, NULL}},
+ {{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
+ {{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 0},
+ {{&sh_rodata_2, &sh_rsrc_2, NULL}, 5*page_size, 1, 0, 1},
+ {{&sh_rodata_2, &sh_rsrc_6, NULL}, 7*page_size, 1, 0, 1}
+ },
+#endif
+ /* .rsrc is the last section, data directory entry points to section end */
+ /* Vista+ - resources are moved to section start (trashing data that could be there), and section is trimmed */
+ /* NT4/2000/2003 - resources are moved to section start (trashing data that could be there); section isn't trimmed */
+ {
+ {{&sh_rodata_3, &sh_rsrc_3, NULL}},
+ {{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
+ {{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 0},
+ {{&sh_rodata_3, &sh_rsrc_4, NULL}, 3*page_size, 1, 0, 1},
+ {{&sh_rodata_3, &sh_rsrc_7, NULL}, 5*page_size, 1, 0, 1}
+ },
+ /* .rsrc is not the last section */
+ /* section is reused; sections after .rsrc are shifted to give space to rsrc (in-image offset and RVA!) */
+ {
+ {{&sh_rodata_1, &sh_rsrc_1, &sh_junk}},
+ {{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, &sh_junk}, 5*page_size, 1, 0, 1},
+ {{&sh_rodata_1, &sh_rsrc_5, &sh_junk_2}, 7*page_size, 1, 0, 1}
+ },
+ /* .rsrc is the last section, data directory entry points to whole section, file size is not aligned on FileAlign */
+ {
+ {{&sh_rodata_1, &sh_rsrc_8, NULL}},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 0},
+ {{&sh_rodata_1, &sh_rsrc_1, NULL}, 4*page_size, 1, 0, 1},
+ {{&sh_rodata_1, &sh_rsrc_5, NULL}, 6*page_size, 1, 0, 1}
+ }
+};
+
+static int build_exe( const sec_build* sec_descr )
{
IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *nt;
IMAGE_SECTION_HEADER *sec;
IMAGE_OPTIONAL_HEADER *opt;
HANDLE file;
- DWORD written;
- BYTE page[0x1000];
- const int page_size = 0x1000;
+ DWORD written, i, file_size;
+ BYTE page[page_size];
memset( page, 0, sizeof page );
nt->Signature = IMAGE_NT_SIGNATURE;
nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
- nt->FileHeader.NumberOfSections = 2;
+ nt->FileHeader.NumberOfSections = 0;
nt->FileHeader.SizeOfOptionalHeader = sizeof nt->OptionalHeader;
nt->FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL;
opt->MajorImageVersion = 1;
opt->MajorSubsystemVersion = 4;
opt->SizeOfHeaders = sizeof *dos + sizeof *nt + sizeof *sec * 2;
- opt->SizeOfImage = page_size*3;
+ opt->SizeOfImage = page_size;
opt->Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
/* if SectionAlignment and File alignment are not specified */
opt->SectionAlignment = page_size;
opt->FileAlignment = page_size;
- sec = (void*) &nt[1];
+ opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].VirtualAddress = rva_rsrc_start;
+ opt->DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY].Size = page_size;
- memcpy( sec[0].Name, ".rodata", 8 );
- sec[0].Misc.VirtualSize = page_size;
- sec[0].PointerToRawData = page_size;
- sec[0].SizeOfRawData = page_size;
- sec[0].VirtualAddress = page_size;
- sec[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
+ sec = (void*) &nt[1];
- memcpy( sec[1].Name, ".rsrc", 6 );
- sec[1].Misc.VirtualSize = page_size;
- sec[1].SizeOfRawData = page_size;
- sec[1].PointerToRawData = page_size*2;
- sec[1].VirtualAddress = page_size*2;
- sec[1].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
+ file_size = 0;
+ for ( i = 0; i < max_sections; i++ )
+ if ( sec_descr->sect_in[i] )
+ {
+ DWORD virt_end_of_section = sec_descr->sect_in[i]->Misc.VirtualSize +
+ sec_descr->sect_in[i]->VirtualAddress;
+ DWORD phys_end_of_section = sec_descr->sect_in[i]->SizeOfRawData +
+ sec_descr->sect_in[i]->PointerToRawData;
+ memcpy( sec + nt->FileHeader.NumberOfSections, sec_descr->sect_in[i],
+ sizeof(sec[0]) );
+ nt->FileHeader.NumberOfSections++;
+ if ( opt->SizeOfImage < virt_end_of_section )
+ opt->SizeOfImage = virt_end_of_section;
+ if ( file_size < phys_end_of_section )
+ file_size = phys_end_of_section;
+ }
file = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok (file != INVALID_HANDLE_VALUE, "failed to create file\n");
/* write out the header */
WriteFile( file, page, sizeof page, &written, NULL );
- /* write out an empty page for rodata */
+ /* write out zeroed pages for sections */
memset( page, 0, sizeof page );
- WriteFile( file, page, sizeof page, &written, NULL );
-
- /* write out an empty page for the resources */
- memset( page, 0, sizeof page );
- WriteFile( file, page, sizeof page, &written, NULL );
+ for ( i = page_size; i < file_size; i += page_size )
+ {
+ DWORD size = min(page_size, file_size - i);
+ WriteFile( file, page, size, &written, NULL );
+ }
CloseHandle( file );
ok( r, "EndUpdateResource failed\n");
}
-static void update_resources_version(void)
+static void update_resources_version( void )
{
HANDLE res = NULL;
BOOL r;
ok( r, "EndUpdateResource failed: %d\n", GetLastError());
}
-
-typedef void (*res_check_func)( IMAGE_RESOURCE_DIRECTORY* );
-
-static void check_empty( IMAGE_RESOURCE_DIRECTORY *dir )
+static void update_resources_bigdata( void )
{
- char *pad;
-
- ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
- ok( dir->NumberOfIdEntries == 0, "NumberOfIdEntries should be 0 instead of %d\n", dir->NumberOfIdEntries);
+ HANDLE res = NULL;
+ BOOL r;
+ char foo[2*page_size] = "foobar";
- pad = (char*) &dir[1];
+ res = BeginUpdateResource( filename, TRUE );
+ ok( res != NULL, "BeginUpdateResource succeeded\n");
- ok( !memcmp( pad, "PADDINGXXPADDING", 16), "padding wrong\n");
-}
+ r = UpdateResource( res,
+ MAKEINTRESOURCE(0x3012),
+ MAKEINTRESOURCE(0x5647),
+ 0xcdba,
+ foo, sizeof foo );
+ ok( r == TRUE, "UpdateResource failed: %d\n", GetLastError());
-static void check_not_empty( IMAGE_RESOURCE_DIRECTORY *dir )
-{
- ok( dir->NumberOfNamedEntries == 0, "NumberOfNamedEntries should be 0 instead of %d\n", dir->NumberOfNamedEntries);
- ok( dir->NumberOfIdEntries == 1, "NumberOfIdEntries should be 1 instead of %d\n", dir->NumberOfIdEntries);
+ r = EndUpdateResource( res, FALSE );
+ ok( r, "EndUpdateResource failed\n");
}
-static void check_exe( res_check_func fn )
+static void check_exe( const sec_verify *verify )
{
+ int i;
IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *nt;
IMAGE_SECTION_HEADER *sec;
IMAGE_RESOURCE_DIRECTORY *dir;
HANDLE file, mapping;
- DWORD length;
+ DWORD length, sec_count = 0;
file = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
ok (file != INVALID_HANDLE_VALUE, "failed to create file (%d)\n", GetLastError());
length = GetFileSize( file, NULL );
- ok( length == 0x3000, "file size wrong\n");
+ ok( length >= verify->length, "file size wrong\n");
mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
ok (mapping != NULL, "failed to create file\n");
goto end;
nt = (void*) ((BYTE*) dos + dos->e_lfanew);
- ok( nt->FileHeader.NumberOfSections == 2, "number of sections wrong\n" );
-
- if (nt->FileHeader.NumberOfSections < 2)
- goto end;
-
sec = (void*) &nt[1];
- ok( !memcmp(sec[1].Name, ".rsrc", 6), "resource section name wrong\n");
-
- dir = (void*) ((BYTE*) dos + sec[1].VirtualAddress);
+ for(i = 0; i < max_sections; i++)
+ if (verify->sect_out[i])
+ {
+ ok( !memcmp(&verify->sect_out[i]->Name, &sec[sec_count].Name, 8), "section %d name wrong\n", sec_count);
+ ok( verify->sect_out[i]->VirtualAddress == sec[sec_count].VirtualAddress, "section %d vaddr wrong\n", sec_count);
+ ok( verify->sect_out[i]->SizeOfRawData <= sec[sec_count].SizeOfRawData, "section %d SizeOfRawData wrong (%d vs %d)\n", sec_count, verify->sect_out[i]->SizeOfRawData ,sec[sec_count].SizeOfRawData);
+ ok( verify->sect_out[i]->PointerToRawData == sec[sec_count].PointerToRawData, "section %d PointerToRawData wrong\n", sec_count);
+ ok( verify->sect_out[i]->Characteristics == sec[sec_count].Characteristics , "section %d characteristics wrong\n", sec_count);
+ sec_count++;
+ }
- ok( dir->Characteristics == 0, "Characteristics wrong\n");
- ok( dir->TimeDateStamp == 0 || abs( dir->TimeDateStamp - GetTickCount() ) < 1000 /* nt4 */,
- "TimeDateStamp wrong %u\n", dir->TimeDateStamp);
- ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
- ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
+ ok( nt->FileHeader.NumberOfSections == sec_count, "number of sections wrong\n" );
- fn( dir );
+ if (verify->rsrc_section >= 0 && verify->rsrc_section < nt->FileHeader.NumberOfSections)
+ {
+ dir = (void*) ((BYTE*) dos + sec[verify->rsrc_section].VirtualAddress);
+
+ ok( dir->Characteristics == 0, "Characteristics wrong\n");
+ ok( dir->TimeDateStamp == 0 || abs( dir->TimeDateStamp - GetTickCount() ) < 1000 /* nt4 */,
+ "TimeDateStamp wrong %u\n", dir->TimeDateStamp);
+ ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
+ ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
+
+ ok( dir->NumberOfNamedEntries == verify->NumberOfNamedEntries, "NumberOfNamedEntries should be %d instead of %d\n",
+ verify->NumberOfNamedEntries, dir->NumberOfNamedEntries);
+ ok( dir->NumberOfIdEntries == verify->NumberOfIdEntries, "NumberOfIdEntries should be %d instead of %d\n",
+ verify->NumberOfIdEntries, dir->NumberOfIdEntries);
+ }
end:
UnmapViewOfFile( dos );
START_TEST(resource)
{
+ DWORD i;
+
DeleteFile( filename );
update_missing_exe();
}
update_empty_exe();
- build_exe();
- update_resources_none();
- check_exe( check_empty );
- update_resources_delete();
- check_exe( check_empty );
- update_resources_version();
- check_exe( check_not_empty );
- DeleteFile( filename );
+
+ for(i=0; i < sizeof( sec_variants ) / sizeof( sec_variants[0] ); i++)
+ {
+ const struct _sec_variants *sec = &sec_variants[i];
+ build_exe( &sec->build );
+ update_resources_none();
+ check_exe( &sec->chk_none );
+ update_resources_delete();
+ check_exe( &sec->chk_delete );
+ update_resources_version();
+ check_exe( &sec->chk_version );
+ update_resources_bigdata();
+ check_exe( &sec->chk_bigdata );
+ DeleteFile( filename );
+ }
test_find_resource();
}
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
HMODULE kernel32;
DWORD r;
- int i;
- HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
+ HANDLE event[2], semaphore[2], file;
kernel32 = GetModuleHandle("kernel32");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
CloseHandle(event[0]);
CloseHandle(event[1]);
- /* create the maximum number of events and make sure
- * we can wait on that many */
- for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
- {
- maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
- ok( maxevents[i] != 0, "should create enough events\n");
- }
- r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
- ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
-
- for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
- if (maxevents[i]) CloseHandle(maxevents[i]);
-
/* semaphores */
semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
BOOL ret;
HANDLE hCreated;
HANDLE hOpened;
+ int i;
+ DWORD failed = 0;
hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
- wait_ret = WaitForSingleObject(hCreated, INFINITE);
- ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
- /* yes, opening with just READ_CONTROL access allows us to successfully
- * call ReleaseMutex */
- hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
+ hOpened = OpenMutex(0, FALSE, "WineTestMutex");
+ ok(hOpened == NULL, "OpenMutex succeded\n");
+
+ hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
+ ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
+ wait_ret = WaitForSingleObject(hOpened, INFINITE);
+ ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
+ CloseHandle(hOpened);
+
+ for(i=0; i < 31; i++)
+ {
+ wait_ret = WaitForSingleObject(hCreated, INFINITE);
+ ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
+ }
+
+ hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
- ret = ReleaseMutex(hOpened);
- todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError());
+ wait_ret = WaitForSingleObject(hOpened, INFINITE);
+ ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
+ CloseHandle(hOpened);
+
+ for (i = 0; i < 32; i++)
+ {
+ hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
+ if(hOpened != NULL)
+ {
+ ret = ReleaseMutex(hOpened);
+ ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
+ CloseHandle(hOpened);
+ }
+ else
+ {
+ ReleaseMutex(hCreated);
+ failed |=0x1 << i;
+ }
+ }
+
+ ok( failed == 0x0de0fffe, "open succeded when it shouldn't: %x\n", failed);
+
ret = ReleaseMutex(hCreated);
- todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
+ ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
"ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
/* test case sensitivity */
SetLastError(0xdeadbeef);
hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
ok(!hOpened, "OpenMutex succeeded\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
ok(!hOpened, "OpenMutex succeeded\n");
- ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
SetLastError(0xdeadbeef);
handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
ok( !handle2, "OpenEvent succeeded\n");
- ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
CloseHandle( handle );
}
SetLastError(0xdeadbeef);
handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
ok( !handle2, "OpenSemaphore succeeded\n");
- ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_INVALID_NAME, /* win9x */
- "wrong error %u\n", GetLastError());
+ ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
CloseHandle( handle );
}
GetLastError());
}
+static HANDLE modify_handle(HANDLE handle, DWORD modify)
+{
+ DWORD tmp = HandleToULong(handle);
+ tmp |= modify;
+ return ULongToHandle(tmp);
+}
+
+static void test_WaitForSingleObject(void)
+{
+ HANDLE signaled, nonsignaled, invalid;
+ DWORD ret;
+
+ signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
+ nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
+ invalid = (HANDLE) 0xdeadbee0;
+
+ /* invalid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(invalid, 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
+ ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+ /* valid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(nonsignaled, 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
+ ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ /* valid handle with different values for lower 2 bits */
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(signaled, 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
+ ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+ CloseHandle(signaled);
+ CloseHandle(nonsignaled);
+}
+
+static void test_WaitForMultipleObjects(void)
+{
+ DWORD r;
+ int i;
+ HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
+
+ /* create the maximum number of events and make sure
+ * we can wait on that many */
+ for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
+ {
+ maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
+ ok( maxevents[i] != 0, "should create enough events\n");
+ }
+
+ /* a manual-reset event remains signaled, an auto-reset event is cleared */
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
+ ok(ResetEvent(maxevents[0]), "ResetEvent\n");
+ for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
+ {
+ /* the lowest index is checked first and remaining events are untouched */
+ r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
+ ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
+ }
+
+ for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
+ if (maxevents[i]) CloseHandle(maxevents[i]);
+}
+
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
test_waitable_timer();
test_iocp_callback();
test_timer_queue();
+ test_WaitForSingleObject();
+ test_WaitForMultipleObjects();
}
char **argv;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
+ BOOL ret;
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
winetest_get_mainargs( &argv );
sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
- ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
- &si, &pi) != 0, "error: %u\n", GetLastError());
- ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
+ ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "error: %u\n", GetLastError());
+ ret = CloseHandle(pi.hThread);
+ ok(ret, "error %u\n", GetLastError());
return pi.hProcess;
}
CloseHandle(stop_event);
}
-DWORD tlsIndex;
+static DWORD tlsIndex;
typedef struct {
int threadnum;
/* WinME supports OpenThread but doesn't know about access restrictions so
we require them to be either completely ignored or always obeyed.
*/
-INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
+static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
#define obey_ar(x) \
(obeying_ars == 0 \
? ((x) \
skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
return;
}
+ ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
/* thread still suspended, so wait times out */
- ret = WaitForSingleObject(hEvent, 100);
+ ret = WaitForSingleObject(hEvent, 1000);
ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
ret = ResumeThread(hThread);
ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
/* wait that doesn't time out */
- ret = WaitForSingleObject(hEvent, 100);
+ ret = WaitForSingleObject(hEvent, 1000);
ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
/* wait for thread end */
- ret = WaitForSingleObject(hThread, 100);
+ ret = WaitForSingleObject(hThread, 1000);
ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
CloseHandle(hThread);
threadFunc_CloseHandle,
hRemoteEvent, 0, &tid);
ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
- ret = WaitForSingleObject(hThread, 100);
+ ret = WaitForSingleObject(hThread, 1000);
ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
CloseHandle(hThread);
ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
/* closed handle, so wait times out */
- ret = WaitForSingleObject(hEvent, 100);
+ ret = WaitForSingleObject(hEvent, 1000);
ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
/* check that remote SetEvent() failed */
DWORD i,j;
DWORD GLE, ret;
DWORD tid;
+ BOOL bRet;
/* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
}
SetLastError(0xCAFEF00D);
- ok(TlsFree(tlsIndex)!=0,"TlsFree failed: %08x\n", GetLastError());
+ bRet = TlsFree(tlsIndex);
+ ok(bRet, "TlsFree failed: %08x\n", GetLastError());
ok(GetLastError()==0xCAFEF00D,
"GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
}
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
- ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
+ ok(error!=-1, "SetThreadIdealProcessor failed\n");
}
}
static void WINAPI set_test_val( int val )
{
test_value += val;
+ ExitThread(0);
}
static DWORD WINAPI threadFunc6(LPVOID p)
ctx.Esp -= 2 * sizeof(int *);
ctx.Eip = (DWORD)set_test_val;
SetLastError(0xdeadbeef);
- ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
+ ret = SetThreadContext( thread, &ctx );
+ ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
}
SetLastError(0xdeadbeef);
prevcount, GetLastError() );
WaitForSingleObject( thread, INFINITE );
- ok( test_value == 20, "test_value %d instead of 20\n", test_value );
+ ok( test_value == 10, "test_value %d\n", test_value );
+
+ 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() );
+
+ 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() );
+
+ CloseHandle( thread );
}
#endif /* __i386__ */
}
ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
- ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
+ ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
for (i = 0; i < 2; ++i)
CloseHandle(threads[i]);
pSetThreadErrorMode(oldmode, NULL);
}
-void _fpreset(void) {} /* override the mingw fpu init code */
-
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
static inline void set_fpu_cw(WORD cw)
{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
__asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
-#endif
}
static inline WORD get_fpu_cw(void)
{
WORD cw = 0;
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
__asm__ volatile ("fnstcw %0" : "=m" (cw));
-#endif
return cw;
}
cw = get_fpu_cw();
ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
}
+#endif
START_TEST(thread)
{
static BOOL (WINAPI *pTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
static BOOL (WINAPI *pSystemTimeToTzSpecificLocalTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
+static int (WINAPI *pGetCalendarInfoA)(LCID,CALID,CALTYPE,LPSTR,int,LPDWORD);
+static int (WINAPI *pGetCalendarInfoW)(LCID,CALID,CALTYPE,LPWSTR,int,LPDWORD);
#define SECSPERMIN 60
#define SECSPERDAY 86400
tzE.StandardBias=0;
tzE.DaylightBias=-60;
tzE.StandardDate.wMonth=10;
- tzE.StandardDate.wDayOfWeek=0; /*sunday */
- tzE.StandardDate.wDay=5; /* last (sunday) of the month */
+ tzE.StandardDate.wDayOfWeek=0; /* Sunday */
+ tzE.StandardDate.wDay=5; /* last (Sunday) of the month */
tzE.StandardDate.wHour=3;
tzE.DaylightDate.wMonth=3;
tzE.DaylightDate.wDay=5;
tzW.StandardBias=0;
tzW.DaylightBias=-60;
tzW.StandardDate.wMonth=10;
- tzW.StandardDate.wDayOfWeek=0; /*sunday */
- tzW.StandardDate.wDay=4; /* 4th (sunday) of the month */
+ tzW.StandardDate.wDayOfWeek=0; /* Sunday */
+ tzW.StandardDate.wDay=4; /* 4th (Sunday) of the month */
tzW.StandardDate.wHour=2;
tzW.DaylightDate.wMonth=4;
tzW.DaylightDate.wDay=1;
tzW.DaylightDate.wHour=2;
- /* timezone Eastern hemisphere */
+ /* timezone Southern hemisphere */
tzS.Bias=240;
tzS.StandardBias=0;
tzS.DaylightBias=-60;
tzS.StandardDate.wMonth=4;
- tzS.StandardDate.wDayOfWeek=0; /*sunday */
- tzS.StandardDate.wDay=1; /* 1st (sunday) of the month */
+ tzS.StandardDate.wDayOfWeek=0; /*Sunday */
+ tzS.StandardDate.wDay=1; /* 1st (Sunday) of the month */
tzS.StandardDate.wHour=2;
tzS.DaylightDate.wMonth=10;
tzS.DaylightDate.wDay=4;
{ 10, &tzW, {2004,10,-1,24,1,0,0,0}, 4},
{ 11, &tzW, {2004,10,-1,24,1,59,59,999}, 4},
{ 12, &tzW, {2004,10,-1,24,2,0,0,0 }, 6},
- /* and now south */
+ /* and now South */
{ 13, &tzS, {2004,4,-1,4,1,0,0,0}, 4},
{ 14, &tzS, {2004,4,-1,4,1,59,59,999}, 4},
{ 15, &tzS, {2004,4,-1,4,2,0,0,0}, 6},
{ 10, &tzW, {2004,10,-1,24,4,0,0,0}, 1},
{ 11, &tzW, {2004,10,-1,24,4,59,59,999}, 1},
{ 12, &tzW, {2004,10,-1,24,5,0,0,0 }, 1},
- /* and now south */
+ /* and now South */
{ 13, &tzS, {2004,4,-1,4,4,0,0,0}, 1},
{ 14, &tzS, {2004,4,-1,4,4,59,59,999}, 1},
{ 15, &tzS, {2004,4,-1,4,5,0,0,0}, 1},
, {25,28,2,22,2,22} /* 2017 */
, {24,27,1,28,1,28} /* 2018 */
, {30,26,7,27,7,27} /* 2019 */
+ , {0}
};
for( j=0 , year = 1999; yeardays[j][0] ; j++, year++) {
for (i=0; cases[i].nr; i++) {
}
}
+static void test_FileTimeToDosDateTime(void)
+{
+ FILETIME ft = { 0 };
+ WORD fatdate, fattime;
+ BOOL ret;
+
+ if (0)
+ {
+ /* Crashes */
+ FileTimeToDosDateTime(NULL, NULL, NULL);
+ }
+ /* Parameter checking */
+ SetLastError(0xdeadbeef);
+ ret = FileTimeToDosDateTime(&ft, NULL, NULL);
+ ok(!ret, "expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = FileTimeToDosDateTime(&ft, &fatdate, NULL);
+ ok(!ret, "expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = FileTimeToDosDateTime(&ft, NULL, &fattime);
+ ok(!ret, "expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = FileTimeToDosDateTime(&ft, &fatdate, &fattime);
+ ok(!ret, "expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+}
+
+static void test_GetCalendarInfo(void)
+{
+ char bufferA[20];
+ WCHAR bufferW[20];
+ DWORD val1, val2;
+ int ret;
+
+ if (!pGetCalendarInfoA || !pGetCalendarInfoW)
+ {
+ trace( "GetCalendarInfo missing\n" );
+ return;
+ }
+
+ ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
+ NULL, 0, &val1 );
+ ok( ret, "GetCalendarInfoA failed err %u\n", GetLastError() );
+ ok( ret == sizeof(val1), "wrong size %u\n", ret );
+ ok( val1 >= 2000 && val1 < 2100, "wrong value %u\n", val1 );
+
+ ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
+ NULL, 0, &val2 );
+ ok( ret, "GetCalendarInfoW failed err %u\n", GetLastError() );
+ ok( ret == sizeof(val2)/sizeof(WCHAR), "wrong size %u\n", ret );
+ ok( val1 == val2, "A/W mismatch %u/%u\n", val1, val2 );
+
+ ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, bufferA, sizeof(bufferA), NULL );
+ ok( ret, "GetCalendarInfoA failed err %u\n", GetLastError() );
+ ok( ret == 5, "wrong size %u\n", ret );
+ ok( atoi( bufferA ) == val1, "wrong value %s/%u\n", bufferA, val1 );
+
+ ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, bufferW, sizeof(bufferW), NULL );
+ ok( ret, "GetCalendarInfoW failed err %u\n", GetLastError() );
+ ok( ret == 5, "wrong size %u\n", ret );
+ memset( bufferA, 0x55, sizeof(bufferA) );
+ WideCharToMultiByte( CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL );
+ ok( atoi( bufferA ) == val1, "wrong value %s/%u\n", bufferA, val1 );
+
+ ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
+ NULL, 0, NULL );
+ ok( !ret, "GetCalendarInfoA succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+
+ ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, NULL, 0, NULL );
+ ok( ret, "GetCalendarInfoA failed err %u\n", GetLastError() );
+ ok( ret == 5, "wrong size %u\n", ret );
+
+ ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
+ NULL, 0, NULL );
+ ok( !ret, "GetCalendarInfoW succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+
+ ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, NULL, 0, NULL );
+ ok( ret, "GetCalendarInfoW failed err %u\n", GetLastError() );
+ ok( ret == 5, "wrong size %u\n", ret );
+}
+
START_TEST(time)
{
HMODULE hKernel = GetModuleHandle("kernel32");
pTzSpecificLocalTimeToSystemTime = (void *)GetProcAddress(hKernel, "TzSpecificLocalTimeToSystemTime");
pSystemTimeToTzSpecificLocalTime = (void *)GetProcAddress( hKernel, "SystemTimeToTzSpecificLocalTime");
+ pGetCalendarInfoA = (void *)GetProcAddress(hKernel, "GetCalendarInfoA");
+ pGetCalendarInfoW = (void *)GetProcAddress(hKernel, "GetCalendarInfoW");
test_conversions();
test_invalid_arg();
test_FileTimeToSystemTime();
test_FileTimeToLocalFileTime();
test_TzSpecificLocalTimeToSystemTime();
+ test_FileTimeToDosDateTime();
+ test_GetCalendarInfo();
}
{
"kernel32_test.exe"
"kernel32.dll",
- /* FIXME: could test for ntdll on NT and Wine */
+ "ntdll.dll",
};
static const char* sub_expected_modules[] =
{
"kernel32_test.exe",
"kernel32.dll",
- "shell32.dll"
- /* FIXME: could test for ntdll on NT and Wine */
+ "shell32.dll",
+ "ntdll.dll",
};
#define NUM_OF(x) (sizeof(x) / sizeof(x[0]))
if (0)
{
/* Silently crashes on XP */
- ret = GetVersionExA(NULL);
+ GetVersionExA(NULL);
}
SetLastError(0xdeadbeef);
ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
VER_MAJORVERSION, VER_GREATER_EQUAL));
+ ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO *)&info);
#include <stdarg.h>
#include <stdio.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "winternl.h"
#include "winerror.h"
#include "wine/test.h"
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
+static NTSTATUS (WINAPI *pNtAreMappedFilesTheSame)(PVOID,PVOID);
/* ############################### */
char **argv;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
+ BOOL ret;
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
winetest_get_mainargs( &argv );
sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
- ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
- &si, &pi) != 0, "error: %u\n", GetLastError());
- ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
+ ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "error: %u\n", GetLastError());
+ ret = CloseHandle(pi.hThread);
+ ok(ret, "error %u\n", GetLastError());
return pi.hProcess;
}
CloseHandle(hProcess);
}
+static void test_NtAreMappedFilesTheSame(void)
+{
+ static const char testfile[] = "testfile.xxx";
+ HANDLE file, file2, mapping, map2;
+ void *ptr, *ptr2;
+ NTSTATUS status;
+ char path[MAX_PATH];
+
+ if (!pNtAreMappedFilesTheSame)
+ {
+ win_skip( "NtAreMappedFilesTheSame not available\n" );
+ return;
+ }
+
+ file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, 0, 0 );
+ ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
+ SetFilePointer( file, 4096, NULL, FILE_BEGIN );
+ SetEndOfFile( file );
+
+ mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
+ ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
+
+ ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
+ ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+
+ file2 = CreateFileA( testfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, 0 );
+ ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
+
+ map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY, 0, 4096, NULL );
+ ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
+ ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
+ ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, ptr2 );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+ UnmapViewOfFile( ptr2 );
+
+ ptr2 = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
+ ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, ptr2 );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+ UnmapViewOfFile( ptr2 );
+ CloseHandle( map2 );
+
+ map2 = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
+ ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
+ ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 4096 );
+ ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, ptr2 );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+ UnmapViewOfFile( ptr2 );
+ CloseHandle( map2 );
+ CloseHandle( file2 );
+
+ status = pNtAreMappedFilesTheSame( ptr, ptr );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( ptr, (char *)ptr + 30 );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( ptr, (void *)0xdeadbeef );
+ ok( status == STATUS_CONFLICTING_ADDRESSES || status == STATUS_INVALID_ADDRESS,
+ "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( ptr, NULL );
+ ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( ptr, (void *)GetProcessHeap() );
+ ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ status = pNtAreMappedFilesTheSame( NULL, NULL );
+ ok( status == STATUS_INVALID_ADDRESS, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ ptr2 = VirtualAlloc( NULL, 0x10000, MEM_COMMIT, PAGE_READWRITE );
+ ok( ptr2 != NULL, "VirtualAlloc error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, ptr2 );
+ ok( status == STATUS_CONFLICTING_ADDRESSES, "NtAreMappedFilesTheSame returned %x\n", status );
+ VirtualFree( ptr2, 0, MEM_RELEASE );
+
+ UnmapViewOfFile( ptr );
+ CloseHandle( mapping );
+ CloseHandle( file );
+
+ status = pNtAreMappedFilesTheSame( GetModuleHandleA("ntdll.dll"),
+ GetModuleHandleA("kernel32.dll") );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+ status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
+ GetModuleHandleA("kernel32.dll") );
+ ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
+ status = pNtAreMappedFilesTheSame( GetModuleHandleA("kernel32.dll"),
+ (char *)GetModuleHandleA("kernel32.dll") + 4096 );
+ ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ GetSystemDirectoryA( path, MAX_PATH );
+ strcat( path, "\\kernel32.dll" );
+ file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+ ok( file != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
+
+ mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
+ ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
+ ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
+ ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
+ ok( status == STATUS_NOT_SAME_DEVICE, "NtAreMappedFilesTheSame returned %x\n", status );
+ UnmapViewOfFile( ptr );
+ CloseHandle( mapping );
+
+ mapping = CreateFileMappingA( file, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
+ ok( mapping != 0, "CreateFileMapping error %u\n", GetLastError() );
+ ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
+ ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, GetModuleHandleA("kernel32.dll") );
+ todo_wine
+ ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
+
+ file2 = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+ ok( file2 != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
+ map2 = CreateFileMappingA( file2, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL );
+ ok( map2 != 0, "CreateFileMapping error %u\n", GetLastError() );
+ ptr2 = MapViewOfFile( map2, FILE_MAP_READ, 0, 0, 0 );
+ ok( ptr2 != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
+ status = pNtAreMappedFilesTheSame( ptr, ptr2 );
+ ok( status == STATUS_SUCCESS, "NtAreMappedFilesTheSame returned %x\n", status );
+ UnmapViewOfFile( ptr2 );
+ CloseHandle( map2 );
+ CloseHandle( file2 );
+
+ UnmapViewOfFile( ptr );
+ CloseHandle( mapping );
+
+ CloseHandle( file );
+ DeleteFileA( testfile );
+}
+
static void test_CreateFileMapping(void)
{
HANDLE handle, handle2;
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
+ pNtAreMappedFilesTheSame = (void *)GetProcAddress( GetModuleHandle("ntdll.dll"),
+ "NtAreMappedFilesTheSame" );
test_VirtualAllocEx();
test_VirtualAlloc();
test_MapViewOfFile();
test_NtMapViewOfSection();
+ test_NtAreMappedFilesTheSame();
test_CreateFileMapping();
test_IsBadReadPtr();
test_IsBadWritePtr();
#include "wine/test.h"
#include "winbase.h"
+#include "winioctl.h"
#include <stdio.h>
static HINSTANCE hdll;
static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR);
static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR);
static BOOL (WINAPI *pGetVolumeInformationA)(LPCSTR, LPSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD);
+static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameA)(LPCSTR, LPSTR, DWORD, LPDWORD);
+static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameW)(LPCWSTR, LPWSTR, DWORD, LPDWORD);
/* ############################### */
DWORD ret, ret2, buflen=32768;
BOOL found = FALSE;
- if (!pFindFirstVolumeA) {
- win_skip("On win9x, HARDDISK and RAMDISK not present\n");
- return;
- }
-
buffer = HeapAlloc( GetProcessHeap(), 0, buflen );
+ SetLastError(0xdeadbeef);
ret = QueryDosDeviceA( NULL, buffer, buflen );
- ok(ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER,
- "QueryDosDevice buffer too small\n");
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- HeapFree( GetProcessHeap(), 0, buffer );
- return;
- }
- ok(ret, "QueryDosDeviceA failed to return list, last error %u\n", GetLastError());
- if (ret) {
+ ok((ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER),
+ "QueryDosDeviceA failed to return list, last error %u\n", GetLastError());
+
+ if (ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
p = buffer;
for (;;) {
if (!strlen(p)) break;
for (;drivestr[0] <= 'z'; drivestr[0]++) {
/* Older W2K fails with ERROR_INSUFFICIENT_BUFFER when buflen is > 32767 */
ret = QueryDosDeviceA( drivestr, buffer, buflen - 1);
+ ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND,
+ "QueryDosDeviceA failed to return current mapping for %s, last error %u\n", drivestr, GetLastError());
if(ret) {
for (p = buffer; *p; p++) *p = toupper(*p);
if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
HeapFree( GetProcessHeap(), 0, buffer );
}
+static void test_define_dos_deviceA(void)
+{
+ char drivestr[3];
+ char buf[MAX_PATH];
+ DWORD ret;
+
+ /* Find an unused drive letter */
+ drivestr[1] = ':';
+ drivestr[2] = 0;
+ for (drivestr[0] = 'a'; drivestr[0] <= 'z'; drivestr[0]++) {
+ ret = QueryDosDeviceA( drivestr, buf, sizeof(buf));
+ if (!ret) break;
+ }
+ if (drivestr[0] > 'z') {
+ skip("can't test creating a dos drive, none available\n");
+ return;
+ }
+
+ /* Map it to point to the current directory */
+ ret = GetCurrentDirectory(sizeof(buf), buf);
+ ok(ret, "GetCurrentDir\n");
+
+ ret = DefineDosDeviceA(0, drivestr, buf);
+ todo_wine
+ ok(ret, "Could not make drive %s point to %s!\n", drivestr, buf);
+
+ if (!ret) {
+ skip("can't test removing fake drive\n");
+ } else {
+ ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION, drivestr, NULL);
+ ok(ret, "Could not remove fake drive %s!\n", drivestr);
+ }
+}
+
static void test_FindFirstVolume(void)
{
char volume[51];
HANDLE handle;
+ /* not present before w2k */
if (!pFindFirstVolumeA) {
- skip("FindFirstVolumeA not found\n");
+ win_skip("FindFirstVolumeA not found\n");
return;
}
/* not present before w2k */
if (!pGetVolumeNameForVolumeMountPointA) {
- skip("GetVolumeNameForVolumeMountPointA not found\n");
+ win_skip("GetVolumeNameForVolumeMountPointA not found\n");
return;
}
/* not present before w2k */
if (!pGetVolumeNameForVolumeMountPointW) {
- skip("GetVolumeNameForVolumeMountPointW not found\n");
+ win_skip("GetVolumeNameForVolumeMountPointW not found\n");
return;
}
UINT size, size2;
char *buf, *ptr;
+ ok( pGetLogicalDriveStringsA != NULL, "GetLogicalDriveStringsA not available\n");
if(!pGetLogicalDriveStringsA) {
- win_skip("GetLogicalDriveStringsA not available\n");
return;
}
ok(size2 == size-1, "size2 = %d\n", size2);
for(ptr = buf; ptr < buf+size2; ptr += 4) {
- ok(('A' <= *ptr && *ptr <= 'Z') ||
- (broken('a' <= *ptr && *ptr <= 'z')), /* Win9x and WinMe */
- "device name '%c' is not uppercase\n", *ptr);
+ ok(('A' <= *ptr && *ptr <= 'Z'), "device name '%c' is not uppercase\n", *ptr);
ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
UINT size, size2;
WCHAR *buf, *ptr;
+ ok( pGetLogicalDriveStringsW != NULL, "GetLogicalDriveStringsW not available\n");
if(!pGetLogicalDriveStringsW) {
- win_skip("GetLogicalDriveStringsW not available\n");
return;
}
{
BOOL ret;
UINT result;
- char Root_Dir0[]="C:";
- char Root_Dir1[]="C:\\";
- char Root_Dir2[]="\\\\?\\C:\\";
+ char Root_Colon[]="C:";
+ char Root_Slash[]="C:\\";
+ char Root_UNC[]="\\\\?\\C:\\";
char volume[MAX_PATH+1];
DWORD vol_name_size=MAX_PATH+1, vol_serial_num=-1, max_comp_len=0, fs_flags=0, fs_name_len=MAX_PATH+1;
char vol_name_buf[MAX_PATH+1], fs_name_buf[MAX_PATH+1];
char windowsdir[MAX_PATH+10];
char currentdir[MAX_PATH+1];
- if (!pGetVolumeInformationA) {
- win_skip("GetVolumeInformationA not found\n");
- return;
- }
- if (!pGetVolumeNameForVolumeMountPointA) {
- win_skip("GetVolumeNameForVolumeMountPointA not found\n");
+ ok( pGetVolumeInformationA != NULL, "GetVolumeInformationA not found\n");
+ if(!pGetVolumeInformationA) {
return;
}
result = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
- Root_Dir0[0] = windowsdir[0];
- Root_Dir1[0] = windowsdir[0];
- Root_Dir2[4] = windowsdir[0];
-
- /* get the unique volume name for the windows drive */
- ret = pGetVolumeNameForVolumeMountPointA(Root_Dir1, volume, MAX_PATH);
- ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
+ Root_Colon[0] = windowsdir[0];
+ Root_Slash[0] = windowsdir[0];
+ Root_UNC[4] = windowsdir[0];
result = GetCurrentDirectory(MAX_PATH, currentdir);
ok(result, "GetCurrentDirectory: error %d\n", GetLastError());
+ /* Note that GetCurrentDir yields no trailing slash for subdirs */
- /* **** now start the tests **** */
- /* check for error on no trailing \ */
- if (result > 3)
- {
- ret = pGetVolumeInformationA(Root_Dir0, vol_name_buf, vol_name_size, NULL,
- NULL, NULL, fs_name_buf, fs_name_len);
- ok(!ret && GetLastError() == ERROR_INVALID_NAME,
- "GetVolumeInformationA w/o '\\' did not fail, last error %u\n", GetLastError());
- }
- else
- skip("Running on a root directory\n");
-
- /* check for error on no trailing \ when current dir is root dir */
- ret = SetCurrentDirectory(Root_Dir1);
+ /* check for NO error on no trailing \ when current dir is root dir */
+ ret = SetCurrentDirectory(Root_Slash);
ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
- ret = pGetVolumeInformationA(Root_Dir0, vol_name_buf, vol_name_size, NULL,
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
NULL, NULL, fs_name_buf, fs_name_len);
- todo_wine
- ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
+ ok(ret, "GetVolumeInformationA root failed, last error %u\n", GetLastError());
- /* check for error on no trailing \ when current dir is windows dir */
+ /* check for error on no trailing \ when current dir is subdir (windows) of queried drive */
ret = SetCurrentDirectory(windowsdir);
ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
- ret = pGetVolumeInformationA(Root_Dir0, vol_name_buf, vol_name_size, NULL,
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
NULL, NULL, fs_name_buf, fs_name_len);
- ok(!ret && GetLastError() == ERROR_INVALID_NAME,
- "GetVolumeInformationA did not fail, last error %u\n", GetLastError());
+ ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
+ "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
/* reset current directory */
ret = SetCurrentDirectory(currentdir);
ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+ if (toupper(currentdir[0]) == toupper(windowsdir[0])) {
+ skip("Please re-run from another device than %c:\n", windowsdir[0]);
+ /* FIXME: Use GetLogicalDrives to find another device to avoid this skip. */
+ } else {
+ char Root_Env[]="=C:"; /* where MS maintains the per volume directory */
+ Root_Env[1] = windowsdir[0];
+
+ /* C:\windows becomes the current directory on drive C: */
+ /* Note that paths to subdirs are stored without trailing slash, like what GetCurrentDir yields. */
+ ret = SetEnvironmentVariable(Root_Env, windowsdir);
+ ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
+
+ ret = SetCurrentDirectory(windowsdir);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+ ret = SetCurrentDirectory(currentdir);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+
+ /* windows dir is current on the root drive, call fails */
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
+ NULL, NULL, fs_name_buf, fs_name_len);
+ ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
+ "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
+
+ /* Try normal drive letter with trailing \ */
+ ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size, NULL,
+ NULL, NULL, fs_name_buf, fs_name_len);
+ ok(ret, "GetVolumeInformationA with \\ failed, last error %u\n", GetLastError());
+
+ ret = SetCurrentDirectory(Root_Slash);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+ ret = SetCurrentDirectory(currentdir);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+
+ /* windows dir is STILL CURRENT on root drive; the call fails as before, */
+ /* proving that SetCurrentDir did not remember the other drive's directory */
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
+ NULL, NULL, fs_name_buf, fs_name_len);
+ ok(!ret && (GetLastError() == ERROR_INVALID_NAME),
+ "GetVolumeInformationA did%s fail, last error %u\n", ret ? " not":"", GetLastError());
+
+ /* Now C:\ becomes the current directory on drive C: */
+ ret = SetEnvironmentVariable(Root_Env, Root_Slash); /* set =C:=C:\ */
+ ok(ret, "SetEnvironmentVariable %s failed\n", Root_Env);
+
+ /* \ is current on root drive, call succeeds */
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
+ NULL, NULL, fs_name_buf, fs_name_len);
+ ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
+
+ /* again, SetCurrentDirectory on another drive does not matter */
+ ret = SetCurrentDirectory(Root_Slash);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+ ret = SetCurrentDirectory(currentdir);
+ ok(ret, "SetCurrentDirectory: error %d\n", GetLastError());
+
+ /* \ is current on root drive, call succeeds */
+ ret = pGetVolumeInformationA(Root_Colon, vol_name_buf, vol_name_size, NULL,
+ NULL, NULL, fs_name_buf, fs_name_len);
+ ok(ret, "GetVolumeInformationA failed, last error %u\n", GetLastError());
+ }
+
/* try null root directory to return "root of the current directory" */
ret = pGetVolumeInformationA(NULL, vol_name_buf, vol_name_size, NULL,
NULL, NULL, fs_name_buf, fs_name_len);
ok(ret, "GetVolumeInformationA failed on null root dir, last error %u\n", GetLastError());
/* Try normal drive letter with trailing \ */
- ret = pGetVolumeInformationA(Root_Dir1, vol_name_buf, vol_name_size,
- &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
- ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir1, GetLastError());
-
- /* try again with dirve letter and the "disable parsing" prefix */
- ret = pGetVolumeInformationA(Root_Dir2, vol_name_buf, vol_name_size,
+ ret = pGetVolumeInformationA(Root_Slash, vol_name_buf, vol_name_size,
&vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
- todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir2, GetLastError());
+ ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Slash, GetLastError());
- /* try again with unique voluem name */
- ret = pGetVolumeInformationA(volume, vol_name_buf, vol_name_size,
+ /* try again with drive letter and the "disable parsing" prefix */
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
&vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
- todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", volume, GetLastError());
+ ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
/* try again with device name space */
- Root_Dir2[2] = '.';
- ret = pGetVolumeInformationA(Root_Dir2, vol_name_buf, vol_name_size,
+ Root_UNC[2] = '.';
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(Root_UNC, vol_name_buf, vol_name_size,
&vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
- todo_wine ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", Root_Dir2, GetLastError());
+ ok(ret, "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", Root_UNC, GetLastError());
/* try again with a directory off the root - should generate error */
if (windowsdir[strlen(windowsdir)-1] != '\\') strcat(windowsdir, "\\");
+ SetLastError(0xdeadbeef);
+ ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
+ &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
+ ok(!ret && (GetLastError()==ERROR_DIR_NOT_ROOT),
+ "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
+ /* A subdir with trailing \ yields DIR_NOT_ROOT instead of INVALID_NAME */
+ if (windowsdir[strlen(windowsdir)-1] == '\\') windowsdir[strlen(windowsdir)-1] = 0;
+ SetLastError(0xdeadbeef);
ret = pGetVolumeInformationA(windowsdir, vol_name_buf, vol_name_size,
&vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
- todo_wine ok(!ret && GetLastError()==ERROR_DIR_NOT_ROOT,
- "GetVolumeInformationA failed, root=%s, last error=%u\n", windowsdir, GetLastError());
+ ok(!ret && (GetLastError()==ERROR_INVALID_NAME),
+ "GetVolumeInformationA did%s fail, root=%s, last error=%u\n", ret ? " not":"", windowsdir, GetLastError());
+
+ if (!pGetVolumeNameForVolumeMountPointA) {
+ win_skip("GetVolumeNameForVolumeMountPointA not found\n");
+ return;
+ }
+ /* get the unique volume name for the windows drive */
+ ret = pGetVolumeNameForVolumeMountPointA(Root_Slash, volume, MAX_PATH);
+ ok(ret == TRUE, "GetVolumeNameForVolumeMountPointA failed\n");
+
+ /* try again with unique volume name */
+ ret = pGetVolumeInformationA(volume, vol_name_buf, vol_name_size,
+ &vol_serial_num, &max_comp_len, &fs_flags, fs_name_buf, fs_name_len);
+ ok(ret, "GetVolumeInformationA failed, root=%s, last error=%u\n", volume, GetLastError());
}
/* Test to check that unique volume name from windows dir mount point */
hFind = pFindFirstVolumeA( Volume_2, MAX_PATH );
ok(hFind != INVALID_HANDLE_VALUE, "FindFirstVolume failed, err=%u\n",
GetLastError());
- if (hFind != INVALID_HANDLE_VALUE) {
+
do
{
/* validate correct length of unique volume name */
} while (pFindNextVolumeA( hFind, Volume_2, MAX_PATH ));
ok(found, "volume name %s not found by Find[First/Next]Volume\n", Volume_1);
pFindVolumeClose( hFind );
+}
+
+static void test_disk_extents(void)
+{
+ BOOL ret;
+ DWORD size;
+ HANDLE handle;
+ static DWORD data[16];
+
+ handle = CreateFileA( "\\\\.\\c:", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ win_skip("can't open c: drive %u\n", GetLastError());
+ return;
+ }
+ size = 0;
+ ret = DeviceIoControl( handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, &data,
+ sizeof(data), &data, sizeof(data), &size, NULL );
+ if (!ret && GetLastError() == ERROR_INVALID_FUNCTION)
+ {
+ win_skip("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS not supported\n");
+ CloseHandle( handle );
+ return;
+ }
+ ok(ret, "DeviceIoControl failed %u\n", GetLastError());
+ ok(size == 32, "expected 32, got %u\n", size);
+ CloseHandle( handle );
+}
+
+static void test_GetVolumePathNamesForVolumeNameA(void)
+{
+ BOOL ret;
+ char volume[MAX_PATH], buffer[MAX_PATH];
+ DWORD len, error;
+
+ if (!pGetVolumePathNamesForVolumeNameA || !pGetVolumeNameForVolumeMountPointA)
+ {
+ win_skip("required functions not found\n");
+ return;
}
+
+ ret = pGetVolumeNameForVolumeMountPointA( "c:\\", volume, sizeof(volume) );
+ ok(ret, "failed to get volume name %u\n", GetLastError());
+ trace("c:\\ -> %s\n", volume);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( "", NULL, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( volume, NULL, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
+
+ memset( buffer, 0xff, sizeof(buffer) );
+ ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), NULL );
+ ok(ret, "failed to get path names %u\n", GetLastError());
+ ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
+ ok(!buffer[4], "expected double null-terminated buffer\n");
+
+ len = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, 0, &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ len = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( NULL, NULL, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ len = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ len = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameA( NULL, buffer, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ len = 0;
+ memset( buffer, 0xff, sizeof(buffer) );
+ ret = pGetVolumePathNamesForVolumeNameA( volume, buffer, sizeof(buffer), &len );
+ ok(ret, "failed to get path names %u\n", GetLastError());
+ ok(len == 5 || broken(len == 2), "expected 5 got %u\n", len);
+ ok(!strcmp( "C:\\", buffer ), "expected \"\\C:\" got \"%s\"\n", buffer);
+ ok(!buffer[4], "expected double null-terminated buffer\n");
+}
+
+static void test_GetVolumePathNamesForVolumeNameW(void)
+{
+ static const WCHAR empty[] = {0};
+ static const WCHAR drive_c[] = {'c',':','\\',0};
+ static const WCHAR volume_null[] = {'\\','\\','?','\\','V','o','l','u','m','e',
+ '{','0','0','0','0','0','0','0','0','-','0','0','0','0','-','0','0','0','0',
+ '-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\',0};
+ BOOL ret;
+ WCHAR volume[MAX_PATH], buffer[MAX_PATH];
+ DWORD len, error;
+
+ if (!pGetVolumePathNamesForVolumeNameW || !pGetVolumeNameForVolumeMountPointW)
+ {
+ win_skip("required functions not found\n");
+ return;
+ }
+
+ ret = pGetVolumeNameForVolumeMountPointW( drive_c, volume, sizeof(volume)/sizeof(volume[0]) );
+ ok(ret, "failed to get volume name %u\n", GetLastError());
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( empty, NULL, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
+
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, 0, NULL );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_MORE_DATA, "expected ERROR_MORE_DATA got %u\n", error);
+
+ if (0) { /* crash */
+ ret = pGetVolumePathNamesForVolumeNameW( volume, NULL, sizeof(buffer), NULL );
+ ok(ret, "failed to get path names %u\n", GetLastError());
+ }
+
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), NULL );
+ ok(ret, "failed to get path names %u\n", GetLastError());
+
+ len = 0;
+ memset( buffer, 0xff, sizeof(buffer) );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
+ ok(ret, "failed to get path names %u\n", GetLastError());
+ ok(len == 5, "expected 5 got %u\n", len);
+ ok(!buffer[4], "expected double null-terminated buffer\n");
+
+ len = 0;
+ volume[1] = '?';
+ volume[lstrlenW( volume ) - 1] = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_INVALID_NAME, "expected ERROR_INVALID_NAME got %u\n", error);
+
+ len = 0;
+ volume[0] = '\\';
+ volume[1] = 0;
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ todo_wine ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);
+
+ len = 0;
+ lstrcpyW( volume, volume_null );
+ SetLastError( 0xdeadbeef );
+ ret = pGetVolumePathNamesForVolumeNameW( volume, buffer, sizeof(buffer), &len );
+ error = GetLastError();
+ ok(!ret, "expected failure\n");
+ ok(error == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND got %u\n", error);
}
START_TEST(volume)
pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA");
pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
pGetVolumeInformationA = (void *) GetProcAddress(hdll, "GetVolumeInformationA");
+ pGetVolumePathNamesForVolumeNameA = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameA");
+ pGetVolumePathNamesForVolumeNameW = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameW");
test_query_dos_deviceA();
+ test_define_dos_deviceA();
test_FindFirstVolume();
test_GetVolumeNameForVolumeMountPointA();
test_GetVolumeNameForVolumeMountPointW();
test_GetLogicalDriveStringsW();
test_GetVolumeInformationA();
test_enum_vols();
+ test_disk_extents();
+ test_GetVolumePathNamesForVolumeNameA();
+ test_GetVolumePathNamesForVolumeNameW();
}