- Update kernel32 winetest, thanks to Stefan100 for making this possible

svn path=/trunk/; revision=38314
This commit is contained in:
Gregor Schneider 2008-12-23 20:02:47 +00:00
parent 6d0b61ca56
commit 20d4a1d899
27 changed files with 3231 additions and 494 deletions

View file

@ -17,7 +17,7 @@
*/
#include "wine/test.h"
#include <psdk/winbase.h>
#include <winbase.h>
#include <windef.h>
#include <winnt.h>
#include <winternl.h>
@ -223,7 +223,7 @@ static BOOL create_wide_manifest(const char *filename, const char *manifest, BOO
BOOL ret;
int offset = (fBOM ? 0 : 1);
MultiByteToWideChar(CP_ACP, 0, manifest, -1, &wmanifest[1], (strlen(manifest)+1) * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, manifest, -1, &wmanifest[1], (strlen(manifest)+1));
wmanifest[0] = 0xfeff;
if (fReverse)
{
@ -851,6 +851,42 @@ static void test_find_string_fail(void)
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError());
}
static void test_basic_info(HANDLE handle)
{
ACTIVATION_CONTEXT_BASIC_INFORMATION basic;
SIZE_T size;
BOOL b;
b = pQueryActCtxW(0, handle, NULL,
ActivationContextBasicInformation, &basic,
sizeof(basic), &size);
ok (b,"ActivationContextBasicInformation failed\n");
ok (size == sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION),"size mismatch\n");
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
ok (basic.hActCtx == handle, "unexpected handle\n");
b = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, NULL,
ActivationContextBasicInformation, &basic,
sizeof(basic), &size);
if (handle)
{
ok (!b,"ActivationContextBasicInformation succeeded\n");
ok (size == 0,"size mismatch\n");
ok (GetLastError() == ERROR_INVALID_PARAMETER, "Wrong last error\n");
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
ok (basic.hActCtx == handle, "unexpected handle\n");
}
else
{
ok (b,"ActivationContextBasicInformation failed\n");
ok (size == sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION),"size mismatch\n");
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
ok (basic.hActCtx == handle, "unexpected handle\n");
}
}
static void test_actctx(void)
{
ULONG_PTR cookie;
@ -865,6 +901,7 @@ static void test_actctx(void)
ok(handle == NULL, "handle = %p, expected NULL\n", handle);
ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
if(b) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info0);
pReleaseActCtx(handle);
}
@ -879,6 +916,7 @@ static void test_actctx(void)
handle = test_create("test1.manifest", manifest1);
DeleteFileA("test1.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1);
test_info_in_assembly(handle, 1, &manifest1_info);
@ -904,6 +942,7 @@ static void test_actctx(void)
DeleteFileA("test2.manifest");
DeleteFileA("testdep.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info2);
test_info_in_assembly(handle, 1, &manifest2_info);
test_info_in_assembly(handle, 2, &depmanifest1_info);
@ -921,6 +960,7 @@ static void test_actctx(void)
DeleteFileA("test3.manifest");
DeleteFileA("testdep.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info2);
test_info_in_assembly(handle, 1, &manifest2_info);
test_info_in_assembly(handle, 2, &depmanifest2_info);
@ -948,6 +988,7 @@ static void test_actctx(void)
DeleteFileA("test2-3.manifest");
DeleteFileA("testdep.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info2);
test_info_in_assembly(handle, 1, &manifest2_info);
test_info_in_assembly(handle, 2, &depmanifest3_info);
@ -976,6 +1017,7 @@ static void test_actctx(void)
handle = test_create("test3.manifest", manifest3);
DeleteFileA("test3.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1);
test_info_in_assembly(handle, 1, &manifest3_info);
test_file_info(handle, 0, 0, testlib_dll);
@ -1002,6 +1044,7 @@ static void test_actctx(void)
DeleteFileA("test4.manifest");
DeleteFileA("testdep.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info2);
test_info_in_assembly(handle, 1, &manifest4_info);
test_info_in_assembly(handle, 2, &manifest_comctrl_info);
@ -1020,6 +1063,7 @@ static void test_actctx(void)
handle = test_create("..\\test1.manifest", manifest1);
DeleteFileA("..\\test1.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1);
test_info_in_assembly(handle, 1, &manifest1_info);
pReleaseActCtx(handle);
@ -1039,6 +1083,7 @@ static void test_actctx(void)
handle = test_create("test1.manifest", manifest1);
DeleteFileA("test1.manifest");
if (handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1);
test_info_in_assembly(handle, 1, &manifest1_info);
pReleaseActCtx(handle);
@ -1053,6 +1098,7 @@ static void test_actctx(void)
handle = test_create("test1.manifest", manifest1);
DeleteFileA("test1.manifest");
if (handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1);
test_info_in_assembly(handle, 1, &manifest1_info);
pReleaseActCtx(handle);
@ -1071,6 +1117,7 @@ static void test_app_manifest(void)
ok(handle == NULL, "handle != NULL\n");
ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
if(b) {
test_basic_info(handle);
test_detailed_info(handle, &detailed_info1_child);
test_info_in_assembly(handle, 1, &manifest1_child_info);
pReleaseActCtx(handle);

View file

@ -304,7 +304,7 @@ static void test_get_atom_name(void)
do_initW(inW, "abcdefghij", 255);
atom = GlobalAddAtomW(inW);
ok(atom, "couldn't add atom for %s\n", in);
len = GlobalGetAtomNameW(atom, outW, sizeof(outW));
len = GlobalGetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
for (i = 0; i < 255; i++)
{

View file

@ -223,6 +223,7 @@ static void test_FindFirstChangeNotification(void)
file = CreateFileA(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %d\n", GetLastError());
memset(buffer, 0, sizeof(buffer));
ret = WriteFile(file, buffer, sizeof(buffer), &count, NULL);
ok(ret && count == sizeof(buffer), "WriteFile error: %d\n", GetLastError());
ret = CloseHandle(file);
@ -559,8 +560,8 @@ static void test_readdirectorychanges(void)
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],6*sizeof(WCHAR)), "name wrong\n" );
r = RemoveDirectoryW( subsubdir );
ok( r == TRUE, "failed to remove directory\n");
@ -577,13 +578,21 @@ static void test_readdirectorychanges(void)
ok( r == WAIT_OBJECT_0, "should be ready\n" );
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
/* we may get a notification for the parent dir too */
if (pfni->Action == FILE_ACTION_MODIFIED && pfni->NextEntryOffset)
{
ok( pfni->FileNameLength == 3*sizeof(WCHAR), "len wrong %u\n", pfni->FileNameLength );
ok( !memcmp(pfni->FileName,&szGa[1],3*sizeof(WCHAR)), "name wrong\n" );
pfni = (PFILE_NOTIFY_INFORMATION)((char *)pfni + pfni->NextEntryOffset);
}
ok( pfni->NextEntryOffset == 0, "offset wrong %u\n", pfni->NextEntryOffset );
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong %u\n", pfni->Action );
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong %u\n", pfni->FileNameLength );
ok( !memcmp(pfni->FileName,&szGa[1],6*sizeof(WCHAR)), "name wrong\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x18, "ov.InternalHigh wrong\n");
dwCount = (char *)&pfni->FileName[pfni->FileNameLength/sizeof(WCHAR)] - buffer;
ok( ov.InternalHigh == dwCount, "ov.InternalHigh wrong %lu/%u\n",ov.InternalHigh, dwCount );
CloseHandle(hdir);

View file

@ -2,6 +2,7 @@
* Unit tests for code page to/from unicode translations
*
* Copyright (c) 2002 Dmitry Timoshkov
* Copyright (c) 2008 Colin Finck
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -203,17 +204,165 @@ static void test_overlapped_buffers(void)
char buf[256];
int ret;
SetLastError(0xdeadbeef);
memcpy((WCHAR *)(buf + 1), strW, sizeof(strW));
ret = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)(buf + 1), -1, buf, sizeof(buf), NULL, NULL);
ok(ret == sizeof(strA), "unexpected ret %d\n", ret);
ok(!memcmp(buf, strA, sizeof(strA)), "conversion failed: %s\n", buf);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
static void test_string_conversion(LPBOOL bUsedDefaultChar)
{
char mbc;
char mbs[5];
int ret;
WCHAR wc1 = 228; /* Western Windows-1252 character */
WCHAR wc2 = 1088; /* Russian Windows-1251 character not displayable for Windows-1252 */
WCHAR wcs[5] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */
WCHAR dbwcs[3] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 1, "ret is %d\n", ret);
ok(mbc == -28, "mbc is %d\n", mbc);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 1, "ret is %d\n", ret);
ok(mbc == 63, "mbc is %d\n", mbc);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
if (IsValidCodePage(1251))
{
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1251, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 1, "ret is %d\n", ret);
ok(mbc == -16, "mbc is %d\n", mbc);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef ||
broken(GetLastError() == 0), /* win95 */
"GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1251, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 1, "ret is %d\n", ret);
ok(mbc == 97, "mbc is %d\n", mbc);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
else
skip("Codepage 1251 not available\n");
/* This call triggers the last Win32 error */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, wcs, -1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 0, "ret is %d\n", ret);
ok(mbc == 84, "mbc is %d\n", mbc);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, wcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 5, "ret is %d\n", ret);
ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
mbs[0] = 0;
/* WideCharToMultiByte mustn't add any null character automatically.
So in this case, we should get the same string again, even if we only copied the first three bytes. */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 3, "ret is %d\n", ret);
ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
ZeroMemory(mbs, 5);
/* Now this shouldn't be the case like above as we zeroed the complete string buffer. */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 3, "ret is %d\n", ret);
ok(!strcmp(mbs, "Th?"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
/* Double-byte tests */
ret = WideCharToMultiByte(1252, 0, dbwcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 3, "ret is %d\n", ret);
ok(!strcmp(mbs, "??"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
/* Length-only tests */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, &wc2, 1, NULL, 0, NULL, bUsedDefaultChar);
ok(ret == 1, "ret is %d\n", ret);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(1252, 0, wcs, -1, NULL, 0, NULL, bUsedDefaultChar);
ok(ret == 5, "ret is %d\n", ret);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
if (!IsValidCodePage(950))
{
skip("Codepage 950 not available\n");
return;
}
/* Double-byte tests */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(950, 0, dbwcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 5, "ret is %d\n", ret);
ok(!strcmp(mbs, "µH©Ò"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(950, 0, dbwcs, 1, &mbc, 1, NULL, bUsedDefaultChar);
ok(ret == 0, "ret is %d\n", ret);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError());
ZeroMemory(mbs, 5);
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(950, 0, dbwcs, 1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
ok(ret == 2, "ret is %d\n", ret);
ok(!strcmp(mbs, "µH"), "mbs is %s\n", mbs);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
/* Length-only tests */
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(950, 0, dbwcs, 1, NULL, 0, NULL, bUsedDefaultChar);
ok(ret == 2, "ret is %d\n", ret);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WideCharToMultiByte(950, 0, dbwcs, -1, NULL, 0, NULL, bUsedDefaultChar);
ok(ret == 5, "ret is %d\n", ret);
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
}
START_TEST(codepage)
{
BOOL bUsedDefaultChar;
test_destination_buffer();
test_null_source();
test_negative_source_length();
test_negative_dest_length();
test_overlapped_buffers();
/* WideCharToMultiByte has two code paths, test both here */
test_string_conversion(NULL);
test_string_conversion(&bUsedDefaultChar);
}

View file

@ -27,7 +27,7 @@
#define TIMEOUT 1000 /* one second for Timeouts*/
#define SLOWBAUD 150
#define FASTBAUD 115200
#define TIMEDELTA 100 /* 100 ms uncertainty allowed */
#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
/* Define the appropriate LOOPBACK(s) TRUE if you have a Loopback cable with
* the mentioned shorts connected to your Serial port

View file

@ -130,6 +130,49 @@ static void testCursor(HANDLE hCon, COORD sbSize)
ERROR_INVALID_PARAMETER, GetLastError());
}
static void testCursorInfo(HANDLE hCon)
{
BOOL ret;
CONSOLE_CURSOR_INFO info;
SetLastError(0xdeadbeef);
ret = GetConsoleCursorInfo(NULL, NULL);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
ERROR_INVALID_HANDLE, GetLastError());
SetLastError(0xdeadbeef);
info.dwSize = -1;
ret = GetConsoleCursorInfo(NULL, &info);
ok(!ret, "Expected failure\n");
ok(info.dwSize == -1, "Expected no change for dwSize\n");
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
ERROR_INVALID_HANDLE, GetLastError());
/* Test the correct call first to distinguish between win9x and the rest */
SetLastError(0xdeadbeef);
ret = GetConsoleCursorInfo(hCon, &info);
ok(ret, "Expected success\n");
ok(info.dwSize == 25 ||
info.dwSize == 12 /* win9x */,
"Expected 12 or 25, got %d\n", info.dwSize);
ok(info.bVisible, "Expected the cursor to be visible\n");
ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
0xdeadbeef, GetLastError());
if (info.dwSize == 12)
{
skip("NULL CONSOLE_CURSOR_INFO will crash on win9x\n");
return;
}
SetLastError(0xdeadbeef);
ret = GetConsoleCursorInfo(hCon, NULL);
ok(!ret, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_ACCESS, "GetLastError: expecting %u got %u\n",
ERROR_INVALID_ACCESS, GetLastError());
}
static void testWriteSimple(HANDLE hCon, COORD sbSize)
{
COORD c;
@ -863,6 +906,8 @@ START_TEST(console)
/* Non interactive tests */
testCursor(hConOut, sbi.dwSize);
/* test parameters (FIXME: test functionality) */
testCursorInfo(hConOut);
/* will test wrapped (on/off) & processed (on/off) strings output */
testWrite(hConOut, sbi.dwSize);
/* will test line scrolling at the bottom of the screen */

View file

@ -20,6 +20,8 @@
#include <stdio.h>
#include <assert.h>
#define WIN32_NO_STATUS
#include <windows.h>
#include <winreg.h>
#include <ntndk.h>
@ -137,6 +139,7 @@ static void doDebugger(int argc, char** argv)
logfile=(argc >= 4 ? argv[3] : NULL);
blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0);
blackbox.attach_err=0;
if (strstr(myARGV[2], "attach"))
{
blackbox.attach_rc=DebugActiveProcess(blackbox.pid);
@ -147,6 +150,7 @@ static void doDebugger(int argc, char** argv)
blackbox.attach_rc=TRUE;
debug_event=(argc >= 6 ? (HANDLE)atol(argv[5]) : NULL);
blackbox.debug_err=0;
if (debug_event && strstr(myARGV[2], "event"))
{
blackbox.debug_rc=SetEvent(debug_event);
@ -156,13 +160,18 @@ static void doDebugger(int argc, char** argv)
else
blackbox.debug_rc=TRUE;
get_events(logfile, &start_event, &done_event);
if (logfile)
{
get_events(logfile, &start_event, &done_event);
}
if (strstr(myARGV[2], "order"))
{
trace("debugger: waiting for the start signal...\n");
WaitForSingleObject(start_event, INFINITE);
}
blackbox.nokill_err=0;
if (strstr(myARGV[2], "nokill"))
{
blackbox.nokill_rc=pDebugSetProcessKillOnExit(FALSE);
@ -172,6 +181,7 @@ static void doDebugger(int argc, char** argv)
else
blackbox.nokill_rc=TRUE;
blackbox.detach_err=0;
if (strstr(myARGV[2], "detach"))
{
blackbox.detach_rc=pDebugActiveProcessStop(blackbox.pid);
@ -181,7 +191,10 @@ static void doDebugger(int argc, char** argv)
else
blackbox.detach_rc=TRUE;
save_blackbox(logfile, &blackbox, sizeof(blackbox));
if (logfile)
{
save_blackbox(logfile, &blackbox, sizeof(blackbox));
}
trace("debugger: done debugging...\n");
SetEvent(done_event);
@ -241,7 +254,9 @@ static void crash_and_debug(HKEY hkey, const char* argv0, const char* dbgtasks)
"wrong exit code : %08x\n", exit_code);
}
else
ok(exit_code == STATUS_ACCESS_VIOLATION, "exit code = %08x instead of STATUS_ACCESS_VIOLATION\n", exit_code);
ok(exit_code == STATUS_ACCESS_VIOLATION ||
exit_code == WAIT_ABANDONED, /* win2k3 */
"exit code = %08x instead of STATUS_ACCESS_VIOLATION or WAIT_ABANDONED\n", exit_code);
CloseHandle(info.hProcess);
/* ...before the debugger */
@ -333,6 +348,7 @@ static void test_ExitCode(void)
{
debugger_val=HeapAlloc(GetProcessHeap(), 0, debugger_size);
RegQueryValueExA(hkey, "debugger", NULL, &debugger_type, debugger_val, &debugger_size);
trace("HKLM\\%s\\debugger is set to '%s'\n", AeDebug, debugger_val);
}
}
else if (ret == ERROR_ACCESS_DENIED)

View file

@ -24,6 +24,13 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
static CHAR string[MAX_PATH];
#define ok_w(res, format, szString) \
\
WideCharToMultiByte(CP_ACP, 0, szString, -1, string, MAX_PATH, NULL, NULL); \
ok(res, format, string);
static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
static BOOL (WINAPI *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
@ -156,7 +163,9 @@ static void test_GetSetEnvironmentVariableW(void)
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value));
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok_w(lstrcmpW(buf, fooW) == 0 ||
lstrlenW(buf) == 0, /* Vista */
"Expected untouched or empty buffer, got \"%s\"\n", buf);
ok(ret_size == lstrlenW(value) + 1,
"should return length with terminating 0 ret_size=%d\n", ret_size);

View file

@ -2,6 +2,7 @@
* Unit tests for file functions in Wine
*
* Copyright (c) 2002, 2004 Jakob Eriksson
* Copyright (c) 2008 Jeff Zaroyko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -23,9 +24,6 @@
#include <stdlib.h>
#include <time.h>
/* ReplaceFile requires Windows 2000 or newer */
#define _WIN32_WINNT 0x0500
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
@ -777,6 +775,16 @@ static void test_CreateFileW(void)
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
"CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
ret = CreateDirectoryW(filename, NULL);
ok(ret == TRUE, "couldn't create temporary directory\n");
hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
ok(hFile != INVALID_HANDLE_VALUE,
"expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
CloseHandle(hFile);
ret = RemoveDirectoryW(filename);
ok(ret, "DeleteFileW: error %d\n", GetLastError());
}
static void test_GetTempFileNameA(void)
@ -841,6 +849,10 @@ static void test_DeleteFileA( void )
static void test_DeleteFileW( void )
{
BOOL ret;
WCHAR pathW[MAX_PATH];
WCHAR pathsubW[MAX_PATH];
static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
static const WCHAR subdirW[] = {'\\','s','u','b',0};
static const WCHAR emptyW[]={'\0'};
ret = DeleteFileW(NULL);
@ -852,6 +864,35 @@ static void test_DeleteFileW( void )
ret = DeleteFileW(emptyW);
ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
"DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
/* test DeleteFile on empty directory */
ret = GetTempPathW(MAX_PATH, pathW);
if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
{
ok(0, "MAX_PATH exceeded in constructing paths\n");
return;
}
lstrcatW(pathW, dirW);
lstrcpyW(pathsubW, pathW);
lstrcatW(pathsubW, subdirW);
ret = CreateDirectoryW(pathW, NULL);
ok(ret == TRUE, "couldn't create directory deletefile\n");
ret = DeleteFileW(pathW);
ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
ret = RemoveDirectoryW(pathW);
ok(ret == TRUE, "expected to remove directory deletefile\n");
/* test DeleteFile on non-empty directory */
ret = CreateDirectoryW(pathW, NULL);
ok(ret == TRUE, "couldn't create directory deletefile\n");
ret = CreateDirectoryW(pathsubW, NULL);
ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
ret = DeleteFileW(pathW);
ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
ret = RemoveDirectoryW(pathsubW);
ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
ret = RemoveDirectoryW(pathW);
ok(ret == TRUE, "expected to remove directory deletefile\n");
}
#define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
@ -1038,6 +1079,7 @@ static void test_LockFile(void)
OVERLAPPED overlapped;
int limited_LockFile;
int limited_UnLockFile;
BOOL ret;
handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
@ -1097,10 +1139,15 @@ static void test_LockFile(void)
"UnlockFileEx 150,100 again succeeded\n" );
}
ok( LockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "LockFile failed\n" );
ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
if (ret)
{
ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
}
else /* win9x */
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
/* wrap-around lock should not do anything */
/* (but still succeeds on NT4 so we don't check result) */
@ -1351,9 +1398,14 @@ static void test_FindFirstFileA(void)
err = GetLastError();
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
"wrong attributes %x\n", data.dwFileAttributes );
if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
{
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
}
SetLastError( 0xdeadbeaf );
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
@ -1366,9 +1418,14 @@ static void test_FindFirstFileA(void)
err = GetLastError();
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
"wrong attributes %x\n", data.dwFileAttributes );
if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
{
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
}
SetLastError( 0xdeadbeaf );
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
@ -1446,7 +1503,13 @@ static void test_FindFirstFileExA(void)
_lclose(_lcreat("test-dir\\file2", 0));
CreateDirectoryA("test-dir\\dir1", NULL);
/* FindExLimitToDirectories is ignored */
SetLastError(0xdeadbeef);
handle = pFindFirstFileExA("test-dir\\*", FindExInfoStandard, &search_results, FindExSearchLimitToDirectories, NULL, 0);
if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("FindFirstFileExA is not implemented\n");
goto cleanup;
}
ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
@ -1456,7 +1519,7 @@ static void test_FindFirstFileExA(void)
ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
ok(FindNextFile(handle, &search_results), "Fetching third file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid thrid entry - %s\n", search_results.cFileName);
ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
ok(FindNextFile(handle, &search_results), "Fetching fourth file failed\n");
ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
@ -1467,6 +1530,10 @@ static void test_FindFirstFileExA(void)
#undef CHECK_NAME
ok(FindNextFile(handle, &search_results) == FALSE, "Fetching sixth file should failed\n");
FindClose( handle );
cleanup:
DeleteFileA("test-dir\\file1");
DeleteFileA("test-dir\\file2");
RemoveDirectoryA("test-dir\\dir1");
@ -1514,12 +1581,16 @@ static void test_MapFile(void)
ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
ok( hmap == NULL, "mapping should fail\n");
ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
if ( hmap )
CloseHandle( hmap );
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
ok( hmap == NULL, "mapping should fail\n");
ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
if ( hmap )
CloseHandle( hmap );
/* On XP you can now map again, on Win 95 you cannot. */
@ -1566,18 +1637,25 @@ static void test_async_file_errors(void)
szFile[0] = '\0';
GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
strcat(szFile, "\\win.ini");
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
ok(hFile != NULL, "CreateFileA(%s ...) failed\n", szFile);
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
while (TRUE)
{
BOOL res;
DWORD count;
while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
;
res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
/*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
if (!res)
break;
S(U(ovl)).Offset += 4096;
if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
break;
S(U(ovl)).Offset += count;
/* i/o completion routine only called if ReadFileEx returned success.
* we only care about violations of this rule so undo what should have
* been done */
@ -1585,6 +1663,7 @@ static void test_async_file_errors(void)
}
ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
/*printf("Error = %ld\n", GetLastError());*/
HeapFree(GetProcessHeap(), 0, lpBuffer);
}
static void test_read_write(void)
@ -1655,26 +1734,28 @@ static void test_OpenFile(void)
BOOL ret;
DWORD retval;
static const char *file = "\\regsvr32.exe";
static const char *foo = ".\\foo-bar-foo.baz";
static const char file[] = "regedit.exe";
static const char foo[] = ".\\foo-bar-foo.baz";
static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
static const char *backslash = "\\";
char buff[MAX_PATH];
char buff_long[4*MAX_PATH];
char filled_0xA5[OFS_MAXPATHNAME];
char *p;
UINT length;
/* Check for existing file */
length = GetSystemDirectoryA(buff, MAX_PATH);
length = GetWindowsDirectoryA(buff, MAX_PATH);
if (length + lstrlen(file) < MAX_PATH)
if (length + sizeof(file) < MAX_PATH)
{
lstrcatA(buff, file);
p = buff + strlen(buff);
if (p > buff && p[-1] != '\\') *p++ = '\\';
strcpy( p, file );
memset(&ofs, 0xA5, sizeof(ofs));
SetLastError(0xfaceabee);
@ -1693,9 +1774,11 @@ static void test_OpenFile(void)
length = GetCurrentDirectoryA(MAX_PATH, buff);
/* Check for nonexistent file */
if (length + lstrlenA(foo + 1) < MAX_PATH)
if (length + sizeof(foo) < MAX_PATH)
{
lstrcatA(buff, foo + 1); /* Avoid '.' during concatenation */
p = buff + strlen(buff);
if (p > buff && p[-1] != '\\') *p++ = '\\';
strcpy( p, foo + 2 );
memset(&ofs, 0xA5, sizeof(ofs));
SetLastError(0xfaceabee);
@ -1733,17 +1816,16 @@ static void test_OpenFile(void)
ofs.szPathName );
}
length = GetCurrentDirectoryA(MAX_PATH, buff);
length += lstrlenA(backslash);
length += lstrlenA(filename);
length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
if (length >= MAX_PATH)
{
trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH);
return;
}
lstrcatA(buff, backslash);
lstrcatA(buff, filename);
p = buff + strlen(buff);
if (p > buff && p[-1] != '\\') *p++ = '\\';
strcpy( p, filename );
memset(&ofs, 0xA5, sizeof(ofs));
SetLastError(0xfaceabee);
@ -1753,7 +1835,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ret = CloseHandle((HANDLE)hFile);
ok( ret == TRUE, "CloseHandle() returns %d\n", ret );
retval = GetFileAttributesA(filename);
@ -1768,7 +1851,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
ret = CloseHandle((HANDLE)hFile);
@ -1782,7 +1866,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
ret = CloseHandle((HANDLE)hFile);
@ -1796,7 +1881,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
ret = CloseHandle((HANDLE)hFile);
@ -1810,7 +1896,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
@ -1822,7 +1909,8 @@ static void test_OpenFile(void)
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
"GetLastError() returns %d\n", GetLastError() );
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
@ -1840,15 +1928,19 @@ static void test_overlapped(void)
memset( &ov, 0, sizeof ov );
result = 1;
r = GetOverlappedResult(0, &ov, &result, 0);
ok( r == TRUE, "should return false\n");
ok( result == 0, "wrong result %u\n", result );
if (r)
ok( result == 0, "wrong result %u\n", result );
else /* win9x */
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
result = 0;
ov.Internal = 0;
ov.InternalHigh = 0xabcd;
r = GetOverlappedResult(0, &ov, &result, 0);
ok( r == TRUE, "should return false\n");
ok( result == 0xabcd, "wrong result %u\n", result );
if (r)
ok( result == 0xabcd, "wrong result %u\n", result );
else /* win9x */
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
SetLastError( 0xb00 );
result = 0;
@ -1857,14 +1949,15 @@ static void test_overlapped(void)
r = GetOverlappedResult(0, &ov, &result, 0);
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
ok( r == FALSE, "should return false\n");
ok( result == 0xabcd, "wrong result %u\n", result );
ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
SetLastError( 0xb00 );
result = 0;
ov.Internal = STATUS_PENDING;
ov.InternalHigh = 0xabcd;
r = GetOverlappedResult(0, &ov, &result, 0);
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
"wrong error %u\n", GetLastError() );
ok( r == FALSE, "should return false\n");
ok( result == 0, "wrong result %u\n", result );
@ -1873,7 +1966,8 @@ static void test_overlapped(void)
ov.Internal = STATUS_PENDING;
ov.InternalHigh = 0xabcd;
r = GetOverlappedResult(0, &ov, &result, 0);
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
"wrong error %u\n", GetLastError() );
ok( r == FALSE, "should return false\n");
ResetEvent( ov.hEvent );
@ -1882,7 +1976,8 @@ static void test_overlapped(void)
ov.Internal = STATUS_PENDING;
ov.InternalHigh = 0;
r = GetOverlappedResult(0, &ov, &result, 0);
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
"wrong error %u\n", GetLastError() );
ok( r == FALSE, "should return false\n");
r = CloseHandle( ov.hEvent );
@ -1901,19 +1996,23 @@ static void test_RemoveDirectory(void)
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
rc = RemoveDirectory(".");
todo_wine {
ok( !rc, "RemoveDirectory unexpectedly worked\n" );
}
if (!rc)
{
rc = SetCurrentDirectory("..");
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
rc = SetCurrentDirectory("..");
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
rc = RemoveDirectory(directory);
todo_wine {
ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
rc = RemoveDirectory(directory);
ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
}
}
static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
{
ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
return abs(t1 - t2) <= tolerance;
}
static void test_ReplaceFileA(void)
{
char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
@ -2021,14 +2120,15 @@ static void test_ReplaceFileA(void)
/* make sure that the backup has the old "replaced" filetime */
ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
ok( ret, "GetFileTime error (backup %d\n", GetLastError());
ok(CompareFileTime(&ftBackup, &ftReplaced) == 0,
"backup file has wrong filetime\n");
ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n");
CloseHandle(hBackupFile);
/* make sure that the "replaced" has the old replacement filetime */
ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
ok( ret, "GetFileTime error (backup %d\n", GetLastError());
ok(CompareFileTime(&ftReplaced, &ftReplacement) == 0,
"replaced file has wrong filetime\n");
ok(check_file_time(&ftReplaced, &ftReplacement, 20000000),
"replaced file has wrong filetime %x%08x / %x%08x\n",
ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime,
ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime );
CloseHandle(hReplacedFile);
/* re-create replacement file for pass w/o backup (blank) */
@ -2066,7 +2166,8 @@ static void test_ReplaceFileA(void)
ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError());
/* make sure that the replacement file still exists */
hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
ok(hReplacementFile != INVALID_HANDLE_VALUE,
ok(hReplacementFile != INVALID_HANDLE_VALUE ||
broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */
"unexpected error, replacement file should still exist %d\n", GetLastError());
CloseHandle(hReplacementFile);
ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL);
@ -2099,7 +2200,9 @@ static void test_ReplaceFileA(void)
/* delete temporary files, replacement and replaced are already deleted */
ret = DeleteFileA(backup);
ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError());
ok(ret ||
broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
"DeleteFileA: error (backup) %d\n", GetLastError());
}
/*
@ -2170,7 +2273,9 @@ static void test_ReplaceFileW(void)
"ReplaceFileW: unexpected error %d\n", GetLastError());
ret = DeleteFileW(backup);
ok(ret, "DeleteFileW: error %d\n", GetLastError());
ok(ret ||
broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
"DeleteFileW: error (backup) %d\n", GetLastError());
}
START_TEST(file)

View file

@ -228,7 +228,9 @@ static void test_message_null_buffer(void)
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, "last error %u\n", error);
ok(error == ERROR_NOT_ENOUGH_MEMORY ||
error == ERROR_INVALID_PARAMETER, /* win9x */
"last error %u\n", error);
SetLastError(0xdeadbeef);
ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);

View file

@ -72,6 +72,13 @@ START_TEST(heap)
mem = HeapAlloc(GetProcessHeap(), 0, ~0UL);
ok(mem == NULL, "memory allocated for size ~0UL\n");
/* large blocks must be 16-byte aligned */
mem = HeapAlloc(GetProcessHeap(), 0, 512 * 1024);
ok( mem != NULL, "failed for size 512K\n" );
ok( (ULONG_PTR)mem % 16 == 0 || broken((ULONG_PTR)mem % 16) /* win9x */,
"512K block not 16-byte aligned\n" );
HeapFree(GetProcessHeap(), 0, mem);
/* Global*() functions */
gbl = GlobalAlloc(GMEM_MOVEABLE, 0);
ok(gbl != NULL, "global memory not allocated for size 0\n");
@ -185,24 +192,31 @@ START_TEST(heap)
/* invalid free */
SetLastError(MAGIC_DEAD);
mem = GlobalFree(gbl);
ok(mem == gbl, "Expected gbl, got %p\n", mem);
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
ok(mem == gbl || broken(mem == NULL) /* nt4 */, "Expected gbl, got %p\n", mem);
if (mem == gbl)
ok(GetLastError() == ERROR_INVALID_HANDLE ||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
"Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
gbl = GlobalAlloc(GMEM_DDESHARE, 100);
res = GlobalUnlock(gbl);
ok(res == 1, "Expected 1, got %d\n", res);
ok(res == 1 ||
res == 0, /* win9x */
"Expected 1 or 0, got %d\n", res);
res = GlobalUnlock(gbl);
ok(res == 1, "Expected 1, got %d\n", res);
ok(res == 1 ||
res == 0, /* win9x */
"Expected 1 or 0, got %d\n", res);
/* GlobalSize on an invalid handle */
SetLastError(MAGIC_DEAD);
size = GlobalSize((HGLOBAL)0xc042);
ok(size == 0, "Expected 0, got %ld\n", size);
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
ok(GetLastError() == ERROR_INVALID_HANDLE ||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
"Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* ####################################### */
/* Local*() functions */

View file

@ -27,6 +27,13 @@
#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
{
if (rva == 0)
return NULL;
return ((char*) module) + rva;
}
static const struct
{
WORD e_magic; /* 00: MZ Header signature */
@ -103,7 +110,7 @@ static IMAGE_SECTION_HEADER section =
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
};
START_TEST(loader)
static void test_Loader(void)
{
static const struct test_data
{
@ -113,6 +120,7 @@ START_TEST(loader)
DWORD section_alignment, file_alignment;
DWORD size_of_image, size_of_headers;
DWORD error; /* 0 means LoadLibrary should succeed */
DWORD alt_error; /* alternate error */
} td[] =
{
{ &dos_header, sizeof(dos_header),
@ -141,7 +149,7 @@ START_TEST(loader)
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_SUCCESS, ERROR_INVALID_ADDRESS /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
@ -168,25 +176,25 @@ START_TEST(loader)
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_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
},
{ &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_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_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_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),
@ -200,13 +208,13 @@ START_TEST(loader)
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
1,
0,
ERROR_SUCCESS
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_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
},
{ &dos_header, sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
@ -227,7 +235,7 @@ START_TEST(loader)
0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
1,
0,
ERROR_SUCCESS
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
}
};
static const char filler[0x1000];
@ -323,18 +331,11 @@ START_TEST(loader)
SetLastError(0xdeadbeef);
hlib = LoadLibrary(dll_name);
if (td[i].error == ERROR_SUCCESS)
if (hlib)
{
MEMORY_BASIC_INFORMATION info;
ok(hlib != 0, "%d: LoadLibrary error %d\n", i, GetLastError());
/* No point in crashing. Test crashes on Vista with some of the given files */
if (hlib == 0)
{
skip("Failed to load dll number %d\n", i);
goto endloop;
}
ok( td[i].error == ERROR_SUCCESS, "%d: should have failed\n", i );
SetLastError(0xdeadbeef);
ok(VirtualQuery(hlib, &info, sizeof(info)) == sizeof(info),
@ -461,8 +462,8 @@ START_TEST(loader)
ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
}
else
{ /* LoadLibrary is expected to fail */
ok(!hlib, "%d: LoadLibrary should fail\n", i);
{
ok(td[i].error || td[i].alt_error, "%d: LoadLibrary should succeed\n", i);
if (GetLastError() == ERROR_GEN_FAILURE) /* Win9x, broken behaviour */
{
@ -471,12 +472,73 @@ START_TEST(loader)
return;
}
ok(td[i].error == GetLastError(), "%d: expected error %d, got %d\n",
i, td[i].error, 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());
}
endloop:
SetLastError(0xdeadbeef);
ok(DeleteFile(dll_name), "DeleteFile error %d\n", GetLastError());
}
}
/* Verify linking style of import descriptors */
static void test_ImportDescriptors(void)
{
HMODULE kernel32_module = NULL;
PIMAGE_DOS_HEADER d_header;
PIMAGE_NT_HEADERS nt_headers;
DWORD import_dir_size;
DWORD_PTR dir_offset;
PIMAGE_IMPORT_DESCRIPTOR import_chunk;
/* Load kernel32 module */
kernel32_module = GetModuleHandleA("kernel32.dll");
assert( kernel32_module != NULL );
/* Get PE header info from module image */
d_header = (PIMAGE_DOS_HEADER) kernel32_module;
nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) +
d_header->e_lfanew);
/* Get size of import entry directory */
import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (!import_dir_size)
{
skip("Unable to continue testing due to missing import directory.\n");
return;
}
/* Get address of first import chunk */
dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
import_chunk = RVAToAddr(dir_offset, kernel32_module);
ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk);
if (!import_chunk) return;
/* Iterate through import descriptors and verify set name,
* OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
* kernel32.dll, don't use Borland-style linking, where the table of
* imported names is stored directly in FirstThunk and overwritten
* by the relocation, instead of being stored in OriginalFirstThunk.
* */
for (; import_chunk->FirstThunk; import_chunk++)
{
LPCSTR module_name = RVAToAddr(import_chunk->Name, kernel32_module);
PIMAGE_THUNK_DATA name_table = RVAToAddr(
U(*import_chunk).OriginalFirstThunk, kernel32_module);
PIMAGE_THUNK_DATA iat = RVAToAddr(
import_chunk->FirstThunk, kernel32_module);
ok(module_name != NULL, "Imported module name should not be NULL\n");
ok(name_table != NULL,
"Name table for imported module %s should not be NULL\n",
module_name);
ok(iat != NULL, "IAT for imported module %s should not be NULL\n",
module_name);
}
}
START_TEST(loader)
{
test_Loader();
test_ImportDescriptors();
}

File diff suppressed because it is too large Load diff

View file

@ -34,6 +34,7 @@ static int mailslot_test(void)
HANDLE hSlot, hSlot2, hWriter, hWriter2;
unsigned char buffer[16];
DWORD count, dwMax, dwNext, dwMsgCount, dwTimeout;
BOOL ret;
/* sanity check on GetMailslotInfo */
dwMax = dwNext = dwMsgCount = dwTimeout = 0;
@ -54,10 +55,13 @@ static int mailslot_test(void)
/* open a mailslot with a null name */
hSlot = CreateMailslot( NULL, 0, 0, NULL );
ok( hSlot == INVALID_HANDLE_VALUE,
"Created mailslot with invalid name\n");
ok( GetLastError() == ERROR_PATH_NOT_FOUND,
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 );
/* valid open, but with wacky parameters ... then check them */
hSlot = CreateMailslot( szmspath, -1, -1, NULL );
@ -80,32 +84,36 @@ static int mailslot_test(void)
/* try and read/write to it */
count = 0;
memset(buffer, 0, sizeof buffer);
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot read\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
ok( !ret || broken(ret), /* win9x */ "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),
"slot write\n");
ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
/* now try and openthe client, but with the wrong sharing mode */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
/* now try and open the client, but with the wrong sharing mode */
hWriter = CreateFile(szmspath, GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter == INVALID_HANDLE_VALUE, "bad sharing mode\n");
ok( GetLastError() == ERROR_SHARING_VIOLATION,
"error should be ERROR_SHARING_VIOLATION\n");
ok( hWriter != INVALID_HANDLE_VALUE /* vista */ || GetLastError() == ERROR_SHARING_VIOLATION,
"error should be ERROR_SHARING_VIOLATION got %p / %u\n", hWriter, GetLastError());
if (hWriter != INVALID_HANDLE_VALUE) CloseHandle( hWriter );
/* now open the client with the correct sharing mode */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot\n");
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());
/*
* opening a client should make no difference to
* whether we can read or write the mailslot
*/
ok( !ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
"slot read\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ret = ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL);
ok( !ret || broken(ret), /* win9x */ "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),
"slot write\n");
ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
@ -116,12 +124,14 @@ static int mailslot_test(void)
*/
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can read client\n");
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
"wrong error %u\n", GetLastError() );
ok( WriteFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can't write client\n");
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can read client\n");
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
"wrong error %u\n", GetLastError() );
/*
* seeing as there's something in the slot,
@ -132,24 +142,28 @@ static int mailslot_test(void)
ok( count == (sizeof buffer/2), "short read\n" );
/* but not again */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot read\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
ok( !ret || broken(ret), /* win9x */ "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
/* now try open another writer... should fail */
hWriter2 = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "two writers\n");
/* succeeds on vista, don't test */
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
/* now try open another as a reader ... also fails */
hWriter2 = CreateFile(szmspath, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer + reader\n");
/* succeeds on vista, don't test */
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
/* now try open another as a writer ... still fails */
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer\n");
/* succeeds on vista, don't test */
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
/* now open another one */
hSlot2 = CreateMailslot( szmspath, 0, 0, NULL );
@ -172,7 +186,8 @@ static int mailslot_test(void)
*/
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "greedy writer succeeded\n");
/* succeeds on vista, don't test */
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
/* now try open another as a writer ... and share with the first */
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
@ -189,8 +204,10 @@ static int mailslot_test(void)
ok( dwTimeout == 0, "dwTimeout incorrect\n");
/* check there's still no data */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
ok( !ret || broken(ret), /* win9x */ "slot read\n");
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
else ok( count == 0, "wrong count %u\n", count );
/* write two messages */
buffer[0] = 'a';
@ -224,9 +241,9 @@ static int mailslot_test(void)
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 1, "dwNext incorrect\n");
todo_wine {
ok( dwMsgCount == 3, "dwMsgCount incorrect\n");
}
todo_wine
ok( dwMsgCount == 3 || broken(dwMsgCount == 2), /* win9x */
"dwMsgCount incorrect %u\n", dwMsgCount);
buffer[0]=buffer[1]=0;
@ -245,7 +262,8 @@ static int mailslot_test(void)
"getmailslotinfo failed\n");
ok( dwNext == 2, "dwNext incorrect\n");
todo_wine {
ok( dwMsgCount == 2, "dwMsgCount incorrect\n");
ok( dwMsgCount == 2 || broken(dwMsgCount == 1), /* win9x */
"dwMsgCount incorrect %u\n", dwMsgCount);
}
/* read the second message */
@ -258,9 +276,10 @@ static int mailslot_test(void)
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 0, "dwNext incorrect\n");
ok( dwNext == 0 || broken(dwNext == ~0u), /* win9x */ "dwNext incorrect %u\n", dwNext);
todo_wine {
ok( dwMsgCount == 1, "dwMsgCount incorrect\n");
ok( dwMsgCount == 1 || broken(dwMsgCount == 0), /* win9x */
"dwMsgCount incorrect %u\n", dwMsgCount);
}
/* read the 3rd (zero length) message */
@ -281,9 +300,10 @@ static int mailslot_test(void)
ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
/* check that reads fail */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"3rd slot read succeeded\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
ok( !ret || broken(ret), /* win9x */ "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 );
/* finally close the mailslot and its client */
ok( CloseHandle( hWriter2 ), "closing 2nd client\n");
@ -297,7 +317,8 @@ static int mailslot_test(void)
memset(buffer, 0, sizeof buffer);
dwTimeout = GetTickCount();
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
ok( GetLastError() == ERROR_SEM_TIMEOUT || broken(GetLastError() == ERROR_ACCESS_DENIED), /* win9x */
"wrong error %u\n", GetLastError() );
dwTimeout = GetTickCount() - dwTimeout;
ok( dwTimeout >= 990, "timeout too short %u\n", dwTimeout );
ok( CloseHandle( hSlot ), "closing the mailslot\n");

View file

@ -216,6 +216,123 @@ static void testGetProcAddress_Wrong(void)
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %d\n", GetLastError());
}
static void testLoadLibraryEx(void)
{
CHAR path[MAX_PATH];
HMODULE hmodule;
HANDLE hfile;
hfile = CreateFileA("testfile.dll", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
ok(hfile != INVALID_HANDLE_VALUE, "Expected a valid file handle\n");
/* NULL lpFileName */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA(NULL, NULL, 0);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
GetLastError());
/* empty lpFileName */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA("", NULL, 0);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
GetLastError() == ERROR_DLL_NOT_FOUND, /* win9x */
"Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND, got %d\n",
GetLastError());
/* hFile is non-NULL */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA("testfile.dll", hfile, 0);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
ok(GetLastError() == ERROR_SHARING_VIOLATION ||
GetLastError() == ERROR_INVALID_PARAMETER || /* win2k3 */
GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
"Unexpected last error, got %d\n", GetLastError());
/* try to open a file that is locked */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA("testfile.dll", NULL, 0);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
todo_wine
{
ok(GetLastError() == ERROR_SHARING_VIOLATION ||
GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
"Expected ERROR_SHARING_VIOLATION or ERROR_FILE_NOT_FOUND, got %d\n",
GetLastError());
}
/* lpFileName does not matter */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA(NULL, hfile, 0);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
GetLastError());
CloseHandle(hfile);
/* load empty file */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA("testfile.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
todo_wine
{
ok(GetLastError() == ERROR_FILE_INVALID ||
GetLastError() == ERROR_BAD_FORMAT, /* win9x */
"Expected ERROR_FILE_INVALID or ERROR_BAD_FORMAT, got %d\n",
GetLastError());
}
DeleteFileA("testfile.dll");
GetSystemDirectoryA(path, MAX_PATH);
if (path[lstrlenA(path) - 1] != '\\')
lstrcatA(path, "\\");
lstrcatA(path, "kernel32.dll");
/* load kernel32.dll with an absolute path */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
ok(hmodule != 0, "Expected valid module handle\n");
ok(GetLastError() == 0xdeadbeef ||
GetLastError() == ERROR_SUCCESS, /* win9x */
"Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
CloseHandle(hmodule);
/* load kernel32.dll with no path */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA("kernel32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
ok(hmodule != 0, "Expected valid module handle\n");
ok(GetLastError() == 0xdeadbeef ||
GetLastError() == ERROR_SUCCESS, /* win9x */
"Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
CloseHandle(hmodule);
GetCurrentDirectoryA(MAX_PATH, path);
if (path[lstrlenA(path) - 1] != '\\')
lstrcatA(path, "\\");
lstrcatA(path, "kernel32.dll");
/* load kernel32.dll with an absolute path that does not exist */
SetLastError(0xdeadbeef);
hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
todo_wine
{
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
}
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
broken(GetLastError() == ERROR_INVALID_HANDLE), /* nt4 */
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
}
START_TEST(module)
{
WCHAR filenameW[MAX_PATH];
@ -226,7 +343,7 @@ START_TEST(module)
GetModuleFileNameW(NULL, filenameW, MAX_PATH);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
trace("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
win_skip("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
is_unicode_enabled = FALSE;
}
@ -238,4 +355,5 @@ START_TEST(module)
testNestedLoadLibraryA();
testLoadLibraryA_Wrong();
testGetProcAddress_Wrong();
testLoadLibraryEx();
}

View file

@ -465,6 +465,14 @@ static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
/* starting with a '.' */
sprintf(tmpstr,".\\%s",LONGDIR);
test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
/* change to root without a trailing backslash. The function call succeeds
but the directory is not changed.
*/
strcpy(tmpstr,"C:");
test_setdir(newdir,tmpstr,newdir,1,"check 10");
/* works however with a trailing backslash */
strcpy(tmpstr,"C:\\");
test_setdir(newdir,tmpstr,NULL,1,"check 11");
}
/* Cleanup the mess we made while executing these tests */

View file

@ -21,7 +21,6 @@
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <windef.h>
#include <winbase.h>
@ -713,14 +712,17 @@ static int test_DisconnectNamedPipe(void)
DWORD written;
DWORD readden;
SetLastError(0xdeadbeef);
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
if (INVALID_HANDLE_VALUE == hnp) {
trace ("Seems we have no named pipes.\n");
if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
win_skip("Named pipes are not implemented\n");
return 1;
}
@ -793,7 +795,7 @@ static void test_CreatePipe(void)
size = 32768;
buffer = HeapAlloc( GetProcessHeap(), 0, size );
for (i = 0; i < size; i++) buffer[i] = i;
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, size) != 0, "CreatePipe failed\n");
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
/* and close the write end, read should still succeed*/
@ -952,8 +954,8 @@ static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_
SetLastError(0xdeadbeef);
ret = ImpersonateNamedPipeClient(hPipeServer);
error = GetLastError();
todo_wine
ok(!ret && (error == ERROR_CANNOT_IMPERSONATE), "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
"ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
ret = ConnectNamedPipe(hPipeServer, NULL);
ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
@ -1325,9 +1327,6 @@ START_TEST(pipe)
{
HMODULE hmod;
skip("ROS-HACK: Skipping pipe tests -- ros' npfs is in a sorry state\n");
return;
hmod = GetModuleHandle("advapi32.dll");
pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");

View file

@ -24,12 +24,16 @@
#include <stdio.h>
#include <stdlib.h>
#include "wine/test.h"
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wincon.h"
#include "winnls.h"
#include "winternl.h"
#include "wine/test.h"
static HINSTANCE hkernel32;
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
@ -124,7 +128,6 @@ static char* decodeA(const char* str)
return ptr;
}
#if 0
/* This will be needed to decode Unicode strings saved by the child process
* when we test Unicode functions.
*/
@ -145,7 +148,6 @@ static WCHAR* decodeW(const char* str)
ptr[len] = '\0';
return ptr;
}
#endif
/******************************************************************
* init
@ -348,8 +350,18 @@ static void doChild(const char* file, const char* option)
childPrintf(hFile, "OutputMode=%ld\n", modeOut);
/* now that we have written all relevant information, let's change it */
ok(SetConsoleCP(1252), "Setting CP\n");
ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
SetLastError(0xdeadbeef);
ret = SetConsoleCP(1252);
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
win_skip("Setting the codepage is not implemented");
}
else
{
ok(ret, "Setting CP\n");
ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
}
ret = SetConsoleMode(hConIn, modeIn ^ 1);
ok( ret, "Setting mode (%d)\n", GetLastError());
ret = SetConsoleMode(hConOut, modeOut ^ 1);
@ -397,6 +409,18 @@ static char* getChildString(const char* sect, const char* key)
return ret;
}
static WCHAR* getChildStringW(const char* sect, const char* key)
{
char buf[1024+4*MAX_LISTED_ENV_VAR];
WCHAR* ret;
GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
assert(!(strlen(buf) & 1));
ret = decodeW(buf);
return ret;
}
/* FIXME: this may be moved to the wtmain.c file, because it may be needed by
* others... (windows uses stricmp while Un*x uses strcasecmp...)
*/
@ -432,8 +456,35 @@ static void ok_child_string( int line, const char *sect, const char *key,
sect, key, expect ? expect : "(null)", result );
}
static void ok_child_stringWA( int line, const char *sect, const char *key,
const char *expect, int sensitive )
{
WCHAR* expectW;
CHAR* resultA;
DWORD len;
WCHAR* result = getChildStringW( sect, key );
len = MultiByteToWideChar( CP_ACP, 0, expect, -1, NULL, 0);
expectW = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
MultiByteToWideChar( CP_ACP, 0, expect, -1, expectW, len);
len = WideCharToMultiByte( CP_ACP, 0, result, -1, NULL, 0, NULL, NULL);
resultA = HeapAlloc(GetProcessHeap(),0,len*sizeof(CHAR));
WideCharToMultiByte( CP_ACP, 0, result, -1, resultA, len, NULL, NULL);
if (sensitive)
ok_(__FILE__, line)( lstrcmpW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
sect, key, expect ? expect : "(null)", resultA );
else
ok_(__FILE__, line)( lstrcmpiW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
sect, key, expect ? expect : "(null)", resultA );
HeapFree(GetProcessHeap(),0,expectW);
HeapFree(GetProcessHeap(),0,resultA);
}
#define okChildString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 1 )
#define okChildIString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 0 )
#define okChildStringWA(sect, key, expect) ok_child_stringWA(__LINE__, (sect), (key), (expect), 1 )
/* using !expect ensures that the test will fail if the sect/key isn't present
* in result file
@ -450,7 +501,7 @@ static void test_Startup(void)
PROCESS_INFORMATION info;
STARTUPINFOA startup,si;
static CHAR title[] = "I'm the title string",
desktop[] = "I'm the desktop string",
desktop[] = "winsta0\\default",
empty[] = "";
/* let's start simplistic */
@ -470,8 +521,6 @@ static void test_Startup(void)
GetStartupInfoA(&si);
okChildInt("StartupInfoA", "cb", startup.cb);
okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
ok (si.lpTitle == NULL || !strncmp(si.lpTitle, selfname, strlen(selfname)),
"StartupInfoA:lpTitle expected something starting with '%s' or null, got '%s'\n", selfname, si.lpTitle);
okChildInt("StartupInfoA", "dwX", startup.dwX);
okChildInt("StartupInfoA", "dwY", startup.dwY);
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@ -719,6 +768,7 @@ static void test_Startup(void)
static void test_CommandLine(void)
{
char buffer[MAX_PATH], fullpath[MAX_PATH], *lpFilePart, *p;
char buffer2[MAX_PATH];
PROCESS_INFORMATION info;
STARTUPINFOA startup;
DWORD len;
@ -804,9 +854,9 @@ static void test_CommandLine(void)
assert ( lpFilePart != 0);
*(lpFilePart -1 ) = 0;
p = strrchr(fullpath, '\\');
assert (p);
/* Use exename to avoid buffer containing things like 'C:' */
sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, 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());
@ -814,11 +864,35 @@ static void test_CommandLine(void)
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);
sprintf(buffer, "..%s/%s", p, exename);
if (p) sprintf(buffer, "..%s/%s", p, exename);
else sprintf(buffer, "./%s", exename);
okChildString("Arguments", "argvA0", buffer);
release_memory();
assert(DeleteFileA(resfile) != 0);
/* Using AppName */
get_file_name(resfile);
len = GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
assert ( lpFilePart != 0);
*(lpFilePart -1 ) = 0;
p = strrchr(fullpath, '\\');
/* 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);
SetLastError(0xdeadbeef);
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
/* 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);
sprintf(buffer, "tests/process.c %s", resfile);
okChildString("Arguments", "argvA0", "dummy");
okChildString("Arguments", "CommandLineA", buffer2);
okChildStringWA("Arguments", "CommandLineW", buffer2);
release_memory();
assert(DeleteFileA(resfile) != 0);
}
static void test_Directory(void)
@ -1127,9 +1201,7 @@ static void test_Console(void)
HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
const char* msg = "This is a std-handle inheritance test.";
unsigned msg_len;
skip("ROS-HACK: Skipping process console tests\n");
return;
BOOL run_tests = TRUE;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
@ -1185,13 +1257,18 @@ static void test_Console(void)
/* Try to set invalid CP */
SetLastError(0xdeadbeef);
ok(!SetConsoleCP(0), "Shouldn't succeed\n");
ok(GetLastError()==ERROR_INVALID_PARAMETER,
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
"GetLastError: expecting %u got %u\n",
ERROR_INVALID_PARAMETER, GetLastError());
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
run_tests = FALSE;
SetLastError(0xdeadbeef);
ok(!SetConsoleOutputCP(0), "Shouldn't succeed\n");
ok(GetLastError()==ERROR_INVALID_PARAMETER,
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
"GetLastError: expecting %u got %u\n",
ERROR_INVALID_PARAMETER, GetLastError());
@ -1234,8 +1311,14 @@ static void test_Console(void)
okChildInt("Console", "InputMode", modeIn);
okChildInt("Console", "OutputMode", modeOut);
ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
if (run_tests)
{
ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
}
else
win_skip("Setting the codepage is not implemented\n");
ok(modeInC == (modeIn ^ 1), "Wrong console mode\n");
ok(modeOutC == (modeOut ^ 1), "Wrong console-SB mode\n");
trace("cursor position(X): %d/%d\n",sbi.dwCursorPosition.X, sbiC.dwCursorPosition.X);
@ -1402,6 +1485,73 @@ static void test_OpenProcess(void)
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
}
static void test_GetProcessVersion(void)
{
static char cmdline[] = "winver.exe";
PROCESS_INFORMATION pi;
STARTUPINFOA si;
DWORD ret;
SetLastError(0xdeadbeef);
ret = GetProcessVersion(0);
ok(ret, "GetProcessVersion error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = GetProcessVersion(GetCurrentProcessId());
ok(ret, "GetProcessVersion error %u\n", GetLastError());
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
SetLastError(0xdeadbeef);
ok(ret, "CreateProcess error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = GetProcessVersion(pi.dwProcessId);
ok(ret, "GetProcessVersion error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = TerminateProcess(pi.hProcess, 0);
ok(ret, "TerminateProcess error %u\n", GetLastError());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
static void test_Handles(void)
{
HANDLE handle = GetCurrentProcess();
BOOL ret;
DWORD code;
ok( handle == (HANDLE)~(ULONG_PTR)0 ||
handle == (HANDLE)(ULONG_PTR)0x7fffffff /* win9x */,
"invalid current process handle %p\n", handle );
ret = GetExitCodeProcess( handle, &code );
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
#ifdef _WIN64
/* truncated handle */
SetLastError( 0xdeadbeef );
handle = (HANDLE)((ULONG_PTR)handle & ~0u);
ret = GetExitCodeProcess( handle, &code );
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
/* sign-extended handle */
SetLastError( 0xdeadbeef );
handle = (HANDLE)((LONG_PTR)(int)(ULONG_PTR)handle);
ret = GetExitCodeProcess( handle, &code );
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
/* invalid high-word */
SetLastError( 0xdeadbeef );
handle = (HANDLE)(((ULONG_PTR)handle & ~0u) + ((ULONG_PTR)1 << 32));
ret = GetExitCodeProcess( handle, &code );
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
#endif
}
START_TEST(process)
{
int b = init();
@ -1422,6 +1572,8 @@ START_TEST(process)
test_Console();
test_ExitCode();
test_OpenProcess();
test_GetProcessVersion();
test_Handles();
/* things that can be tested:
* lookup: check the way program to be executed is searched
* handles: check the handle inheritance stuff (+sec options)

View file

@ -19,6 +19,7 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
@ -182,13 +183,14 @@ static void test_profile_sections(void)
ok( GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
/* And a real one */
SetLastError(0xdeadbeef);
ret=GetPrivateProfileSectionA("section1", buf, sizeof(buf), testfile4);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
ret, buf);
ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
ok( GetLastError() == S_OK, "expected S_OK, got %d\n", GetLastError());
ok( GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", GetLastError());
DeleteFileA( testfile4 );
}
@ -266,10 +268,456 @@ static void test_profile_sections_names(void)
ok( bufW[1] != 0, "returned buffer terminated with double-null\n" );
}
/* If the ini-file has already been opened with CreateFile, WritePrivateProfileString failed in wine with an error ERROR_SHARING_VIOLATION, some testing here */
static void test_profile_existing(void)
{
static const char *testfile1 = ".\\winesharing1.ini";
static const char *testfile2 = ".\\winesharing2.ini";
static const struct {
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD write_error;
BOOL read_error;
DWORD broken_error;
} pe[] = {
{GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
{GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
{GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
{GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
{GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
{GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
/*Thief demo (bug 5024) opens .ini file like this*/
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */}
};
int i;
BOOL ret;
DWORD size;
HANDLE h = 0;
char buffer[MAX_PATH];
for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++)
{
h = CreateFile(testfile1, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
SetLastError(0xdeadbeef);
ret = WritePrivateProfileString(SECTION, KEY, "12345", testfile1);
if (!pe[i].write_error)
{
if (!ret)
ok( broken(GetLastError() == pe[i].broken_error),
"%d: WritePrivateProfileString failed with error %u\n", i, GetLastError() );
CloseHandle(h);
size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
if (ret)
ok( size == 5, "%d: test failed, number of characters copied: %d instead of 5\n", i, size );
else
ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
}
else
{
DWORD err = GetLastError();
ok( !ret, "%d: WritePrivateProfileString succeeded\n", i );
if (!ret)
ok( err == pe[i].write_error, "%d: WritePrivateProfileString failed with error %u/%u\n",
i, err, pe[i].write_error );
CloseHandle(h);
size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
}
ok( DeleteFile(testfile1), "delete failed\n" );
}
h = CreateFile(testfile2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
sprintf( buffer, "[%s]\r\n%s=123\r\n", SECTION, KEY );
ok( WriteFile( h, buffer, strlen(buffer), &size, NULL ), "failed to write\n" );
CloseHandle( h );
for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++)
{
h = CreateFile(testfile2, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
SetLastError(0xdeadbeef);
ret = GetPrivateProfileStringA(SECTION, KEY, NULL, buffer, MAX_PATH, testfile2);
if (!pe[i].read_error)
ok( ret, "%d: GetPrivateProfileString failed with error %u\n", i, GetLastError() );
else
ok( !ret, "%d: GetPrivateProfileString succeeded\n", i );
CloseHandle(h);
}
ok( DeleteFile(testfile2), "delete failed\n" );
}
static void test_profile_delete_on_close()
{
static CHAR testfile[] = ".\\testwine5.ini";
HANDLE h;
DWORD size, res;
static const char contents[] = "[" SECTION "]\n" KEY "=123\n";
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
ok( WriteFile( h, contents, sizeof contents - 1, &size, NULL ),
"Cannot write test file: %x\n", GetLastError() );
ok( size == sizeof contents - 1, "Test file: partial write\n");
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
ok( res == 123, "Got %d instead of 123\n", res);
/* This also deletes the file */
CloseHandle(h);
}
static void test_profile_refresh(void)
{
static CHAR testfile[] = ".\\winetest4.ini";
HANDLE h;
DWORD size, res;
static const char contents1[] = "[" SECTION "]\n" KEY "=123\n";
static const char contents2[] = "[" SECTION "]\n" KEY "=124\n";
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
ok( WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL ),
"Cannot write test file: %x\n", GetLastError() );
ok( size == sizeof contents1 - 1, "Test file: partial write\n");
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
ok( res == 123, "Got %d instead of 123\n", res);
CloseHandle(h);
/* Test proper invalidation of wine's profile file cache */
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
ok( WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL ),
"Cannot write test file: %x\n", GetLastError() );
ok( size == sizeof contents2 - 1, "Test file: partial write\n");
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
ok( res == 124, "Got %d instead of 124\n", res);
/* This also deletes the file */
CloseHandle(h);
}
static void create_test_file(LPCSTR name, LPCSTR data, DWORD size)
{
HANDLE hfile;
DWORD count;
hfile = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ok(hfile != INVALID_HANDLE_VALUE, "cannot create %s\n", name);
WriteFile(hfile, data, size, &count, NULL);
CloseHandle(hfile);
}
static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
{
int i;
for(i = 0;i < MAX_PATH;++i)
if(emptystr[i] != 0)
{
trace("emptystr[%d] = %d\n",i,emptystr[i]);
return FALSE;
}
return TRUE;
}
static void test_GetPrivateProfileString(const char *content, const char *descript)
{
DWORD ret;
CHAR buf[MAX_PATH];
CHAR def_val[MAX_PATH];
CHAR path[MAX_PATH];
CHAR windir[MAX_PATH];
/* NT series crashes on r/o empty strings, so pass an r/w
empty string and check for modification */
CHAR emptystr[MAX_PATH] = "";
LPSTR tempfile;
static const char filename[] = ".\\winetest.ini";
trace("test_GetPrivateProfileStringA: %s\n", descript);
create_test_file(filename, content, lstrlenA(content));
/* Run this test series with caching. Wine won't cache profile
files younger than 2.1 seconds. */
Sleep(2500);
/* lpAppName is NULL */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(NULL, "name1", "default",
buf, MAX_PATH, filename);
ok(ret == 18, "Expected 18, got %d\n", ret);
ok(!memcmp(buf, "section1\0section2\0", ret + 1),
"Expected \"section1\\0section2\\0\", got \"%s\"\n", buf);
/* lpAppName is empty */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(emptystr, "name1", "default",
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpAppName is missing */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("notasection", "name1", "default",
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
/* lpAppName is empty, lpDefault is NULL */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(emptystr, "name1", NULL,
buf, MAX_PATH, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpAppName is empty, lpDefault is empty */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(emptystr, "name1", "",
buf, MAX_PATH, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpAppName is empty, lpDefault has trailing blank characters */
lstrcpyA(buf, "kumquat");
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
lstrcpyA(def_val, "default ");
ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpAppName is empty, many blank characters in lpDefault */
lstrcpyA(buf, "kumquat");
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
lstrcpyA(def_val, "one two ");
ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpAppName is empty, blank character but not trailing in lpDefault */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(emptystr, "name1", "one two",
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "AppName modified\n");
/* lpKeyName is NULL */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", NULL, "default",
buf, MAX_PATH, filename);
ok(ret == 18, "Expected 18, got %d\n", ret);
ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
"Expected \"name1\\0name2\\0name4\\0\", got \"%s\"\n", buf);
/* lpKeyName is empty */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", emptystr, "default",
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "KeyName modified\n");
/* lpKeyName is missing */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "notakey", "default",
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
/* lpKeyName is empty, lpDefault is NULL */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", emptystr, NULL,
buf, MAX_PATH, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "KeyName modified\n");
/* lpKeyName is empty, lpDefault is empty */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", emptystr, "",
buf, MAX_PATH, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "KeyName modified\n");
/* lpKeyName is empty, lpDefault has trailing blank characters */
lstrcpyA(buf, "kumquat");
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
lstrcpyA(def_val, "default ");
ret = GetPrivateProfileStringA("section1", emptystr, def_val,
buf, MAX_PATH, filename);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
ok(emptystr_ok(emptystr), "KeyName modified\n");
if (0) /* crashes */
{
/* lpReturnedString is NULL */
ret = GetPrivateProfileStringA("section1", "name1", "default",
NULL, MAX_PATH, filename);
}
/* lpFileName is NULL */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, MAX_PATH, NULL);
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
/* lpFileName is empty */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, MAX_PATH, "");
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
/* lpFileName is nonexistent */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, MAX_PATH, "nonexistent");
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
/* nSize is 0 */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, 0, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, "kumquat"), "Expected buf to be unchanged, got \"%s\"\n", buf);
/* nSize is exact size of output */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, 4, filename);
ok(ret == 3, "Expected 3, got %d\n", ret);
ok(!lstrcmpA(buf, "val"), "Expected \"val\", got \"%s\"\n", buf);
/* nSize has room for NULL terminator */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, 5, filename);
ok(ret == 4, "Expected 4, got %d\n", ret);
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
/* output is 1 character */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name4", "default",
buf, MAX_PATH, filename);
ok(ret == 1, "Expected 1, got %d\n", ret);
ok(!lstrcmpA(buf, "a"), "Expected \"a\", got \"%s\"\n", buf);
/* output is 1 character, no room for NULL terminator */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name4", "default",
buf, 1, filename);
ok(ret == 0, "Expected 0, got %d\n", ret);
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
/* lpAppName is NULL, not enough room for final section name */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA(NULL, "name1", "default",
buf, 16, filename);
ok(ret == 14, "Expected 14, got %d\n", ret);
ok(!memcmp(buf, "section1\0secti\0", ret + 1),
"Expected \"section1\\0secti\\0\", got \"%s\"\n", buf);
/* lpKeyName is NULL, not enough room for final key name */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", NULL, "default",
buf, 16, filename);
ok(ret == 14, "Expected 14, got %d\n", ret);
ok(!memcmp(buf, "name1\0name2\0na\0", ret + 1),
"Expected \"name1\\0name2\\0na\\0\", got \"%s\"\n", buf);
/* key value has quotation marks which are stripped */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name2", "default",
buf, MAX_PATH, filename);
ok(ret == 4, "Expected 4, got %d\n", ret);
ok(!lstrcmpA(buf, "val2"), "Expected \"val2\", got \"%s\"\n", buf);
/* case does not match */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
buf, MAX_PATH, filename);
ok(ret == 4, "Expected 4, got %d\n", ret);
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
/* only filename is used */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
buf, MAX_PATH, "winetest.ini");
ok(ret == 7, "Expected 7, got %d\n", ret);
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
GetWindowsDirectoryA(windir, MAX_PATH);
GetTempFileNameA(windir, "pre", 0, path);
tempfile = strrchr(path, '\\') + 1;
create_test_file(path, content, lstrlenA(content));
/* only filename is used, file exists in windows directory */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
buf, MAX_PATH, tempfile);
ok(ret == 4, "Expected 4, got %d\n", ret);
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
/* successful case */
lstrcpyA(buf, "kumquat");
ret = GetPrivateProfileStringA("section1", "name1", "default",
buf, MAX_PATH, filename);
ok(ret == 4, "Expected 4, got %d\n", ret);
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
DeleteFileA(path);
DeleteFileA(filename);
}
START_TEST(profile)
{
test_profile_int();
test_profile_string();
test_profile_sections();
test_profile_sections_names();
test_profile_existing();
test_profile_delete_on_close();
test_profile_refresh();
test_GetPrivateProfileString(
"[section1]\r\n"
"name1=val1\r\n"
"name2=\"val2\"\r\n"
"name3\r\n"
"name4=a\r\n"
"[section2]\r\n",
"CR+LF");
test_GetPrivateProfileString(
"[section1]\r"
"name1=val1\r"
"name2=\"val2\"\r"
"name3\r"
"name4=a\r"
"[section2]\r",
"CR only");
}

View file

@ -173,22 +173,25 @@ static void update_resources_version(void)
res = BeginUpdateResource( filename, TRUE );
ok( res != NULL, "BeginUpdateResource failed\n");
r = UpdateResource( res,
MAKEINTRESOURCE(0x1230),
MAKEINTRESOURCE(0x4567),
0xabcd,
NULL, 0 );
ok( r == FALSE, "UpdateResource failed\n");
if (0) /* this causes subsequent tests to fail on Vista */
{
r = UpdateResource( res,
MAKEINTRESOURCE(0x1230),
MAKEINTRESOURCE(0x4567),
0xabcd,
NULL, 0 );
ok( r == FALSE, "UpdateResource failed\n");
}
r = UpdateResource( res,
MAKEINTRESOURCE(0x1230),
MAKEINTRESOURCE(0x4567),
0xabcd,
foo, sizeof foo );
ok( r == TRUE, "UpdateResource failed\n");
ok( r == TRUE, "UpdateResource failed: %d\n", GetLastError());
r = EndUpdateResource( res, FALSE );
ok( r, "EndUpdateResource failed\n");
ok( r, "EndUpdateResource failed: %d\n", GetLastError());
}
@ -249,7 +252,8 @@ static void check_exe( res_check_func fn )
dir = (void*) ((BYTE*) dos + sec[1].VirtualAddress);
ok( dir->Characteristics == 0, "Characteristics wrong\n");
ok( dir->TimeDateStamp == 0, "TimeDateStamp 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");

View file

@ -26,6 +26,15 @@
#include "wine/test.h"
static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
static HANDLE (WINAPI *pCreateTimerQueue)(void);
static BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
PVOID, DWORD, DWORD, ULONG);
static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
static void test_signalandwait(void)
{
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
@ -44,7 +53,7 @@ static void test_signalandwait(void)
r = pSignalObjectAndWait(NULL, NULL, 0, 0);
if (r == ERROR_INVALID_FUNCTION)
{
trace("SignalObjectAndWait not implemented, skipping tests\n");
skip("SignalObjectAndWait is not implemented\n");
return; /* Win98/ME */
}
ok( r == WAIT_FAILED, "should fail\n");
@ -148,7 +157,34 @@ static void test_mutex(void)
todo_wine 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());
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());
SetLastError(0xdeadbeef);
hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
CloseHandle(hOpened);
SetLastError(0xdeadbeef);
hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
CloseHandle(hOpened);
CloseHandle(hCreated);
}
@ -245,9 +281,9 @@ static void test_slist(void)
ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
}
static void test_event_security(void)
static void test_event(void)
{
HANDLE handle;
HANDLE handle, handle2;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
ACL acl;
@ -280,6 +316,121 @@ static void test_event_security(void)
handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
CloseHandle(handle);
/* test case sensitivity */
SetLastError(0xdeadbeef);
handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
CloseHandle( handle2 );
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());
CloseHandle( handle );
}
static void test_semaphore(void)
{
HANDLE handle, handle2;
/* test case sensitivity */
SetLastError(0xdeadbeef);
handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
CloseHandle( handle2 );
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());
CloseHandle( handle );
}
static void test_waitable_timer(void)
{
HANDLE handle, handle2;
if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
{
skip("{Create,Open}WaitableTimerA() is not available\n");
return;
}
/* test case sensitivity */
SetLastError(0xdeadbeef);
handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
ok( !handle2, "OpenWaitableTimer succeeded\n");
ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_INVALID_NAME, /* win98 */
"wrong error %u\n", GetLastError());
CloseHandle( handle );
}
static HANDLE sem = 0;
@ -289,7 +440,7 @@ static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTrans
ReleaseSemaphore(sem, 1, NULL);
}
static BOOL WINAPI (*p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
static void test_iocp_callback(void)
{
@ -360,16 +511,6 @@ static void test_iocp_callback(void)
ret = DeleteFileA(filename);
ok( ret, "DeleteFileA: error %d\n", GetLastError());
hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
retb = p_BindIoCompletionCallback(hFile, NULL, 0);
ok(retb == TRUE, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
ret = CloseHandle(hFile);
ok( ret, "CloseHandle: error %d\n", GetLastError());
ret = DeleteFileA(filename);
ok( ret, "DeleteFileA: error %d\n", GetLastError());
/* win2k3 requires the Flags parameter to be zero */
SetLastError(0xdeadbeef);
hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
@ -388,14 +529,435 @@ static void test_iocp_callback(void)
retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
ok(GetLastError() == ERROR_INVALID_HANDLE, "Last error is %d\n", GetLastError());
ok(GetLastError() == ERROR_INVALID_HANDLE ||
GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
"Last error is %d\n", GetLastError());
}
static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
{
int *pn = (int *) p;
ok(timedOut, "Timer callbacks should always time out\n");
++*pn;
}
struct timer_queue_data1
{
int num_calls;
int max_calls;
HANDLE q, t;
};
static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
{
struct timer_queue_data1 *d = p;
ok(timedOut, "Timer callbacks should always time out\n");
if (d->t && ++d->num_calls == d->max_calls)
{
BOOL ret;
SetLastError(0xdeadbeef);
/* Note, XP SP2 does *not* do any deadlock checking, so passing
INVALID_HANDLE_VALUE here will just hang. */
ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
ok(!ret, "DeleteTimerQueueTimer\n");
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
}
}
static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
{
struct timer_queue_data1 *d = p;
ok(timedOut, "Timer callbacks should always time out\n");
if (d->t && ++d->num_calls == d->max_calls)
{
/* Basically kill the timer since it won't have time to run
again. */
BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
ok(ret, "ChangeTimerQueueTimer\n");
}
}
static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
{
struct timer_queue_data1 *d = p;
ok(timedOut, "Timer callbacks should always time out\n");
if (d->t)
{
/* This tests whether a timer gets flagged for deletion before
or after the callback runs. If we start this timer with a
period of zero (run once), then ChangeTimerQueueTimer will
fail if the timer is already flagged. Hence we really run
only once. Otherwise we will run multiple times. */
BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
ok(ret, "ChangeTimerQueueTimer\n");
++d->num_calls;
}
}
static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
{
DWORD delay = (DWORD) p;
ok(timedOut, "Timer callbacks should always time out\n");
if (delay)
Sleep(delay);
}
static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
{
struct timer_queue_data1 *d = p;
ok(timedOut, "Timer callbacks should always time out\n");
/* This tests an original implementation bug where a deleted timer may get
to run, but it is tricky to set up. */
if (d->q && d->num_calls++ == 0)
{
/* First run: delete ourselves, then insert and remove a timer
that goes in front of us in the sorted timeout list. Once
removed, we will still timeout at the faster timer's due time,
but this should be a no-op if we are bug-free. There should
not be a second run. We can test the value of num_calls later. */
BOOL ret;
HANDLE t;
/* The delete will pend while we are in this callback. */
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
ok(!ret, "DeleteTimerQueueTimer\n");
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t != NULL, "CreateTimerQueueTimer\n");
ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer\n");
/* Now we stay alive by hanging around in the callback. */
Sleep(500);
}
}
static void test_timer_queue(void)
{
HANDLE q, t1, t2, t3, t4, t5;
int n1, n2, n3, n4, n5;
struct timer_queue_data1 d1, d2, d3, d4;
HANDLE e, et1, et2;
BOOL ret;
if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
|| !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
{
skip("TimerQueue API not present\n");
return;
}
/* Test asynchronous deletion of the queue. */
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueEx(q, NULL);
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
/* Test synchronous deletion of the queue and running timers. */
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
/* Called once. */
t1 = NULL;
n1 = 0;
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t1 != NULL, "CreateTimerQueueTimer\n");
/* A slow one. */
t2 = NULL;
n2 = 0;
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
100, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t2 != NULL, "CreateTimerQueueTimer\n");
/* A fast one. */
t3 = NULL;
n3 = 0;
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
10, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t3 != NULL, "CreateTimerQueueTimer\n");
/* Start really late (it won't start). */
t4 = NULL;
n4 = 0;
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
10, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t4 != NULL, "CreateTimerQueueTimer\n");
/* Start soon, but delay so long it won't run again. */
t5 = NULL;
n5 = 0;
ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
10000, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t5 != NULL, "CreateTimerQueueTimer\n");
/* Give them a chance to do some work. */
Sleep(500);
/* Test deleting a once-only timer. */
ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer\n");
/* A periodic timer. */
ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer\n");
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueEx\n");
ok(n1 == 1, "Timer callback 1\n");
ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
ok(n4 == 0, "Timer callback 4\n");
ok(n5 == 1, "Timer callback 5\n");
/* Test synchronous deletion of the timer/queue with event trigger. */
e = CreateEvent(NULL, TRUE, FALSE, NULL);
et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!e || !et1 || !et2)
{
skip("Failed to create timer queue descruction event\n");
return;
}
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
/* Run once and finish quickly (should be done when we delete it). */
t1 = NULL;
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t1 != NULL, "CreateTimerQueueTimer\n");
/* Run once and finish slowly (shouldn't be done when we delete it). */
t2 = NULL;
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t2 != NULL, "CreateTimerQueueTimer\n");
/* Run once and finish quickly (should be done when we delete it). */
t3 = NULL;
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t3 != NULL, "CreateTimerQueueTimer\n");
/* Run once and finish slowly (shouldn't be done when we delete it). */
t4 = NULL;
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t4 != NULL, "CreateTimerQueueTimer\n");
/* Give them a chance to start. */
Sleep(400);
/* DeleteTimerQueueTimer always returns PENDING with a NULL event,
even if the timer is finished. */
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueTimer(q, t1, NULL);
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueTimer(q, t2, NULL);
ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
ok(GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueTimer(q, t3, et1);
ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
ok(GetLastError() == 0xdeadbeef,
"DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
GetLastError());
ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
"Timer destruction event not triggered\n");
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueTimer(q, t4, et2);
ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
ok(GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
"Timer destruction event not triggered\n");
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueEx(q, e);
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
"Queue destruction event not triggered\n");
CloseHandle(e);
/* Test deleting/changing a timer in execution. */
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
/* Test changing a once-only timer before it fires (this is allowed,
whereas after it fires you cannot). */
n1 = 0;
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
0, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t1 != NULL, "CreateTimerQueueTimer\n");
ret = pChangeTimerQueueTimer(q, t1, 0, 0);
ok(ret, "ChangeTimerQueueTimer\n");
d2.t = t2 = NULL;
d2.num_calls = 0;
d2.max_calls = 3;
d2.q = q;
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
10, 0);
d2.t = t2;
ok(ret, "CreateTimerQueueTimer\n");
ok(t2 != NULL, "CreateTimerQueueTimer\n");
d3.t = t3 = NULL;
d3.num_calls = 0;
d3.max_calls = 4;
d3.q = q;
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
10, 0);
d3.t = t3;
ok(ret, "CreateTimerQueueTimer\n");
ok(t3 != NULL, "CreateTimerQueueTimer\n");
d4.t = t4 = NULL;
d4.num_calls = 0;
d4.q = q;
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
0, 0);
d4.t = t4;
ok(ret, "CreateTimerQueueTimer\n");
ok(t4 != NULL, "CreateTimerQueueTimer\n");
Sleep(500);
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueEx\n");
ok(n1 == 1, "ChangeTimerQueueTimer\n");
ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
/* Test an obscure bug that was in the original implementation. */
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
/* All the work is done in the callback. */
d1.t = t1 = NULL;
d1.num_calls = 0;
d1.q = q;
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
100, WT_EXECUTELONGFUNCTION);
d1.t = t1;
ok(ret, "CreateTimerQueueTimer\n");
ok(t1 != NULL, "CreateTimerQueueTimer\n");
Sleep(750);
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueEx(q, NULL);
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
/* Test functions on the default timer queue. */
t1 = NULL;
n1 = 0;
ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
1000, 0);
ok(ret, "CreateTimerQueueTimer, default queue\n");
ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
ok(ret, "ChangeTimerQueueTimer, default queue\n");
ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer, default queue\n");
/* Try mixing default and non-default queues. Apparently this works. */
q = pCreateTimerQueue();
ok(q != NULL, "CreateTimerQueue\n");
t1 = NULL;
n1 = 0;
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
1000, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t1 != NULL, "CreateTimerQueueTimer\n");
t2 = NULL;
n2 = 0;
ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
1000, 0);
ok(ret, "CreateTimerQueueTimer\n");
ok(t2 != NULL, "CreateTimerQueueTimer\n");
ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
ok(ret, "ChangeTimerQueueTimer\n");
ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
ok(ret, "ChangeTimerQueueTimer\n");
ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer\n");
ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
ok(ret, "DeleteTimerQueueTimer\n");
/* Try to delete the default queue? In any case: not allowed. */
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueEx(NULL, NULL);
ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
ok(GetLastError() == ERROR_INVALID_HANDLE,
"DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
GetLastError());
SetLastError(0xdeadbeef);
ret = pDeleteTimerQueueEx(q, NULL);
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
GetLastError());
}
START_TEST(sync)
{
HMODULE hdll = GetModuleHandle("kernel32");
pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
test_signalandwait();
test_mutex();
test_slist();
test_event_security();
test_event();
test_semaphore();
test_waitable_timer();
test_iocp_callback();
test_timer_queue();
}

View file

@ -18,9 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
#define _WIN32_WINNT 0x0500
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
@ -99,6 +97,61 @@ In addition there are no checks that the inheritance works properly in
CreateThread
*/
/* Functions to ensure that from a group of threads, only one executes
certain chunks of code at a time, and we know which one is executing
it. It basically makes multithreaded execution linear, which defeats
the purpose of multiple threads, but makes testing easy. */
static HANDLE start_event, stop_event;
static LONG num_synced;
static void init_thread_sync_helpers(void)
{
start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
ok(start_event != NULL, "CreateEvent failed\n");
stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
ok(stop_event != NULL, "CreateEvent failed\n");
num_synced = -1;
}
static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
{
LONG num = InterlockedIncrement(&num_synced);
assert(-1 <= num && num <= 1);
if (num == 1)
{
ResetEvent( stop_event );
SetEvent( start_event );
}
else
{
DWORD ret = WaitForSingleObject(start_event, 10000);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
}
return sync_id == my_id;
}
static void resync_after_run(void)
{
LONG num = InterlockedDecrement(&num_synced);
assert(-1 <= num && num <= 1);
if (num == -1)
{
ResetEvent( start_event );
SetEvent( stop_event );
}
else
{
DWORD ret = WaitForSingleObject(stop_event, 10000);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
}
}
static void cleanup_thread_sync_helpers(void)
{
CloseHandle(start_event);
CloseHandle(stop_event);
}
DWORD tlsIndex;
typedef struct {
@ -320,6 +373,7 @@ static VOID test_CreateThread_basic(void)
int error;
DWORD i,j;
DWORD GLE, ret;
DWORD tid;
/* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
@ -377,7 +431,7 @@ static VOID test_CreateThread_basic(void)
/* Test how passing NULL as a pointer to threadid works */
SetLastError(0xFACEaBAD);
thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
GLE = GetLastError();
if (thread[0]) { /* NT */
ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
@ -398,6 +452,7 @@ static VOID test_CreateThread_suspended(void)
{
HANDLE thread;
DWORD threadId;
DWORD suspend_count;
int error;
thread = CreateThread(NULL,0,threadFunc2,NULL,
@ -419,6 +474,15 @@ static VOID test_CreateThread_suspended(void)
if(error!=WAIT_OBJECT_0) {
TerminateThread(thread,1);
}
suspend_count = SuspendThread(thread);
ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
suspend_count = ResumeThread(thread);
ok(suspend_count == 0 ||
broken(suspend_count == -1), /* win9x */
"ResumeThread returned %d, expected 0\n", suspend_count);
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
}
@ -953,6 +1017,183 @@ static void test_RegisterWaitForSingleObject(void)
ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
}
static DWORD TLS_main;
static DWORD TLS_index0, TLS_index1;
static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
{
/* We should NOT inherit the TLS values from our parent or from the
main thread. */
LPVOID val;
val = TlsGetValue(TLS_main);
ok(val == NULL, "TLS inheritance failed\n");
val = TlsGetValue(TLS_index0);
ok(val == NULL, "TLS inheritance failed\n");
val = TlsGetValue(TLS_index1);
ok(val == NULL, "TLS inheritance failed\n");
return 0;
}
/* Basic TLS usage test. Make sure we can create slots and the values we
store in them are separate among threads. Also test TLS value
inheritance with TLS_InheritanceProc. */
static DWORD WINAPI TLS_ThreadProc(LPVOID p)
{
LONG id = (LONG) p;
LPVOID val;
BOOL ret;
if (sync_threads_and_run_one(0, id))
{
TLS_index0 = TlsAlloc();
ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
}
resync_after_run();
if (sync_threads_and_run_one(1, id))
{
TLS_index1 = TlsAlloc();
ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
/* Slot indices should be different even if created in different
threads. */
ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
/* Both slots should be initialized to NULL */
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
}
resync_after_run();
if (sync_threads_and_run_one(0, id))
{
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
ret = TlsSetValue(TLS_index0, (LPVOID) 1);
ok(ret, "TlsSetValue failed\n");
ret = TlsSetValue(TLS_index1, (LPVOID) 2);
ok(ret, "TlsSetValue failed\n");
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
}
resync_after_run();
if (sync_threads_and_run_one(1, id))
{
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == NULL, "TLS slot not initialized correctly\n");
ret = TlsSetValue(TLS_index0, (LPVOID) 3);
ok(ret, "TlsSetValue failed\n");
ret = TlsSetValue(TLS_index1, (LPVOID) 4);
ok(ret, "TlsSetValue failed\n");
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
}
resync_after_run();
if (sync_threads_and_run_one(0, id))
{
HANDLE thread;
DWORD waitret, tid;
val = TlsGetValue(TLS_index0);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
val = TlsGetValue(TLS_index1);
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
ok(thread != NULL, "CreateThread failed\n");
waitret = WaitForSingleObject(thread, 60000);
ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
CloseHandle(thread);
ret = TlsFree(TLS_index0);
ok(ret, "TlsFree failed\n");
}
resync_after_run();
if (sync_threads_and_run_one(1, id))
{
ret = TlsFree(TLS_index1);
ok(ret, "TlsFree failed\n");
}
resync_after_run();
return 0;
}
static void test_TLS(void)
{
HANDLE threads[2];
LONG i;
DWORD ret;
BOOL suc;
init_thread_sync_helpers();
/* Allocate a TLS slot in the main thread to test for inheritance. */
TLS_main = TlsAlloc();
ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
suc = TlsSetValue(TLS_main, (LPVOID) 4114);
ok(suc, "TlsSetValue failed\n");
for (i = 0; i < 2; ++i)
{
DWORD tid;
threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
ok(threads[i] != NULL, "CreateThread failed\n");
}
ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
for (i = 0; i < 2; ++i)
CloseHandle(threads[i]);
suc = TlsFree(TLS_main);
ok(suc, "TlsFree failed\n");
cleanup_thread_sync_helpers();
}
START_TEST(thread)
{
HINSTANCE lib;
@ -986,7 +1227,8 @@ START_TEST(thread)
while (1)
{
HANDLE hThread;
hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
DWORD tid;
hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
ok(hThread != NULL, "CreateThread failed, error %u\n",
GetLastError());
ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
@ -1012,4 +1254,5 @@ START_TEST(thread)
#endif
test_QueueUserWorkItem();
test_RegisterWaitForSingleObject();
test_TLS();
}

View file

@ -18,8 +18,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define _WIN32_WINNT 0x0501
#include "wine/test.h"
#include "winbase.h"
@ -38,11 +36,17 @@ static void test_timer(void)
pCreateWaitableTimerA = (fnCreateWaitableTimerA) GetProcAddress( hker, "CreateWaitableTimerA");
if( !pCreateWaitableTimerA )
{
skip("CreateWaitableTimerA is not available\n");
return;
}
pSetWaitableTimer = (fnSetWaitableTimer) GetProcAddress( hker, "SetWaitableTimer");
if( !pSetWaitableTimer )
{
skip("SetWaitableTimer is not available\n");
return;
}
/* try once with a positive number */
handle = pCreateWaitableTimerA( NULL, 0, NULL );

View file

@ -102,7 +102,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe;
THREADENTRY32 te;
MODULEENTRY32 me;
unsigned found = 0;
int num = 0;
@ -144,9 +143,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
* interesting to be there, especially not the just forked off child */
ok (childpos !=0, "child is not expected to be at position 0.\n");
te.dwSize = sizeof(te);
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
me.dwSize = sizeof(me);
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
@ -157,7 +153,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe;
THREADENTRY32 te;
MODULEENTRY32 me;
int num = 0;
@ -175,7 +170,8 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
{
if (te.th32OwnerProcessID == curr_pid) curr_found++;
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
if (winetest_debug > 1)
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
num++;
} while (pThread32Next( hSnapshot, &te ));
}
@ -191,16 +187,14 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
{
if (te.th32OwnerProcessID == curr_pid) curr_found++;
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
if (winetest_debug > 1)
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
num--;
} while (pThread32Next( hSnapshot, &te ));
}
ok(curr_found == 1, "couldn't find self in thread list\n");
ok(sub_found == 2, "couldn't find sub-process thread's in thread list\n");
pe.dwSize = sizeof(pe);
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
me.dwSize = sizeof(me);
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
@ -278,7 +272,7 @@ static void test_module(DWORD pid, const char* expected[], unsigned num_expected
pe.dwSize = sizeof(pe);
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
me.dwSize = sizeof(me);
te.dwSize = sizeof(te);
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
CloseHandle(hSnapshot);

View file

@ -92,7 +92,9 @@ static void test_GetVersionEx(void)
SetLastError(0xdeadbeef);
infoExA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
ret = GetVersionExA((OSVERSIONINFOA *)&infoExA);
ok(ret, "Expected GetVersionExA to succeed\n");
ok(ret ||
broken(ret == 0), /* win95 */
"Expected GetVersionExA to succeed\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
}
@ -162,8 +164,12 @@ static void test_VerifyVersionInfo(void)
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
VER_MAJORVERSION, VER_GREATER_EQUAL));
if (servicepack == 0)
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", GetLastError());
{
ok(!ret || broken(ret), /* win2k3 */
"VerifyVersionInfoA should have failed\n");
ok(GetLastError() == ERROR_OLD_WIN_VERSION,
"Expected ERROR_OLD_WIN_VERSION instead of %d\n", GetLastError());
}
else
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());

View file

@ -22,7 +22,7 @@
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "psdk/winbase.h"
#include "winerror.h"
#include "wine/test.h"
@ -32,6 +32,8 @@
static HINSTANCE hkernel32;
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
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);
/* ############################### */
@ -253,6 +255,32 @@ static void test_VirtualAlloc(void)
ok(old_prot == PAGE_READONLY,
"wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
/* invalid protection values */
SetLastError(0xdeadbeef);
addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
ok(!addr2, "VirtualAlloc succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
ok(!addr2, "VirtualAlloc succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
ok(!addr2, "VirtualAlloc succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
"VirtualProtect succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
@ -270,6 +298,7 @@ static void test_VirtualAlloc(void)
static void test_MapViewOfFile(void)
{
static const char testfile[] = "testfile.xxx";
const char *name;
HANDLE file, mapping;
void *ptr, *ptr2;
MEMORY_BASIC_INFORMATION info;
@ -450,50 +479,63 @@ static void test_MapViewOfFile(void)
DeleteFileA( testfile );
SetLastError(0xdeadbeef);
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "Global\\Foo");
name = "Local\\Foo";
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
/* nt4 doesn't have Local\\ */
if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
{
name = "Foo";
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
}
ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
mapping = OpenFileMapping( FILE_MAP_READ, FALSE, "Global\\Foo" );
mapping = OpenFileMapping( FILE_MAP_READ, FALSE, name );
ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_WRITE should fail\n" );
todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
"VirtualQuery error %u\n", GetLastError() );
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
todo_wine ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
todo_wine ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
if (!ptr)
{
ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
"VirtualQuery error %u\n", GetLastError() );
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
}
else win_skip( "no access checks on win9x\n" );
UnmapViewOfFile( ptr );
CloseHandle( mapping );
SetLastError(0xdeadbeef);
mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, "Global\\Foo" );
mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, name );
ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_READ should fail\n" );
todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
"VirtualQuery error %u\n", GetLastError() );
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
if (!ptr)
{
ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
SetLastError(0xdeadbeef);
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
SetLastError(0xdeadbeef);
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
"VirtualQuery error %u\n", GetLastError() );
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
}
else win_skip( "no access checks on win9x\n" );
UnmapViewOfFile( ptr );
CloseHandle( mapping );
@ -506,50 +548,100 @@ todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLast
ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
/* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
ret = VirtualQuery(ptr, &info, sizeof(info));
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
todo_wine
ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
todo_wine
ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
{
ok(info.AllocationProtect == PAGE_NOACCESS,
"AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
ok(info.Protect == PAGE_NOACCESS,
"Protect should have been PAGE_NOACCESS instead of 0x%x\n", info.Protect);
}
else
{
ok(info.AllocationProtect == PAGE_READWRITE,
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
}
ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READWRITE);
if (ptr != ptr2)
{
ret = VirtualQuery(ptr2, &info, sizeof(info));
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
ok(info.BaseAddress == ptr2,
"BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
ok(info.AllocationBase == ptr2,
"AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
ok(info.AllocationProtect == PAGE_READWRITE,
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
ok(info.RegionSize == MAPPING_SIZE,
"RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
ok(info.State == MEM_RESERVE,
"State should have been MEM_RESERVE instead of 0x%x\n", info.State);
ok(info.Protect == 0,
"Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED,
"Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
}
ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
ret = VirtualQuery(ptr, &info, sizeof(info));
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
todo_wine
ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
ok(info.State == MEM_COMMIT, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
ok(info.Protect == PAGE_READWRITE, "Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
/* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
ok(info.Protect == PAGE_READONLY, "Protect should have been 0 instead of 0x%x\n", info.Protect);
if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
{
ok(info.AllocationProtect == PAGE_NOACCESS,
"AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
}
else
{
ok(info.AllocationProtect == PAGE_READWRITE,
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
}
/* shows that the VirtualAlloc above affects the mapping, not just the
* virtual memory in this process - it also affects all other processes
* with a view of the mapping, but that isn't tested here */
ret = VirtualQuery(ptr2, &info, sizeof(info));
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
ok(info.BaseAddress == ptr2, "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
ok(info.AllocationBase == ptr2, "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
todo_wine
ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
ok(info.State == MEM_COMMIT, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
ok(info.Protect == PAGE_READWRITE, "Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
if (ptr != ptr2)
{
ret = VirtualQuery(ptr2, &info, sizeof(info));
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
ok(info.BaseAddress == ptr2,
"BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
ok(info.AllocationBase == ptr2,
"AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
ok(info.AllocationProtect == PAGE_READWRITE,
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
ok(info.RegionSize == 0x10000,
"RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
ok(info.State == MEM_COMMIT,
"State should have been MEM_RESERVE instead of 0x%x\n", info.State);
ok(info.Protect == PAGE_READWRITE,
"Protect should have been 0 instead of 0x%x\n", info.Protect);
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
}
ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
ok( !ret || broken(ret) /* win9x */, "VirtualFree succeeded\n" );
if (!ret)
ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
ret = UnmapViewOfFile(ptr2);
ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
@ -622,6 +714,46 @@ static void test_NtMapViewOfSection(void)
CloseHandle(hProcess);
}
static void test_CreateFileMapping(void)
{
HANDLE handle, handle2;
/* test case sensitivity */
SetLastError(0xdeadbeef);
handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
"Wine Test Mapping");
ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
SetLastError(0xdeadbeef);
handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
"Wine Test Mapping");
ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
"WINE TEST MAPPING");
ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
CloseHandle( handle2 );
SetLastError(0xdeadbeef);
handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
ok( !handle2, "OpenFileMapping succeeded\n");
ok( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME /* win9x */,
"wrong error %u\n", GetLastError());
CloseHandle( handle );
}
static void test_BadPtr(void)
{
void *ptr = (void*)1;
@ -631,6 +763,306 @@ static void test_BadPtr(void)
ok(IsBadCodePtr(ptr),"IsBadCodePtr(1) failed.\n");
}
static void test_write_watch(void)
{
char *base;
DWORD ret, size, old_prot;
MEMORY_BASIC_INFORMATION info;
void *results[64];
ULONG_PTR count;
ULONG pagesize;
if (!pGetWriteWatch || !pResetWriteWatch)
{
win_skip( "GetWriteWatch not supported\n" );
return;
}
size = 0x10000;
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
if (!base &&
(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
{
win_skip( "MEM_WRITE_WATCH not supported\n" );
return;
}
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
ret = VirtualQuery( base, &info, sizeof(info) );
ok(ret, "VirtualQuery failed %u\n", GetLastError());
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
count = 64;
SetLastError( 0xdeadbeef );
ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
broken( GetLastError() == 0xdeadbeef ), /* win98 */
"wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
ret = pGetWriteWatch( 0, GetModuleHandle(0), size, results, &count, &pagesize );
if (ret)
{
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
}
else /* win98 */
{
ok( count == 0, "wrong count %lu\n", count );
}
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 0, "wrong count %lu\n", count );
base[pagesize + 1] = 0x44;
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
count = 64;
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 0, "wrong count %lu\n", count );
base[2*pagesize + 3] = 0x11;
base[4*pagesize + 8] = 0x11;
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 2, "wrong count %lu\n", count );
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
count = 64;
ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
ret = pResetWriteWatch( base, 3*pagesize );
ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
*(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 3, "wrong count %lu\n", count );
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
count = 1;
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 2, "wrong count %lu\n", count );
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
/* changing protections doesn't affect watches */
ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
ret = VirtualQuery( base, &info, sizeof(info) );
ok(ret, "VirtualQuery failed %u\n", GetLastError());
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 2, "wrong count %lu\n", count );
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
ret = VirtualQuery( base, &info, sizeof(info) );
ok(ret, "VirtualQuery failed %u\n", GetLastError());
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
/* some invalid parameter tests */
SetLastError( 0xdeadbeef );
count = 0;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
if (ret)
{
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 0;
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
ret = pResetWriteWatch( base, 0 );
ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
ret = pResetWriteWatch( GetModuleHandle(0), size );
ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
}
else /* win98 is completely different */
{
SetLastError( 0xdeadbeef );
count = 64;
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
count = 0;
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", ret );
count = 64;
ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", ret );
count = 64;
ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", ret );
ret = pResetWriteWatch( base, 0 );
ok( !ret, "ResetWriteWatch failed %u\n", ret );
ret = pResetWriteWatch( GetModuleHandle(0), size );
ok( !ret, "ResetWriteWatch failed %u\n", ret );
}
VirtualFree( base, 0, MEM_FREE );
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
VirtualFree( base, 0, MEM_FREE );
base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
ok( !base, "VirtualAlloc succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
/* initial protect doesn't matter */
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 0, "wrong count %lu\n", count );
ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
base[5*pagesize + 200] = 3;
ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1, "wrong count %lu\n", count );
ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
ret = VirtualFree( base, size, MEM_DECOMMIT );
ok( ret, "VirtualFree failed %u\n", GetLastError() );
count = 64;
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 1 || broken(count == 0), /* win98 */
"wrong count %lu\n", count );
if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
VirtualFree( base, 0, MEM_FREE );
}
START_TEST(virtual)
{
int argc;
@ -662,10 +1094,14 @@ START_TEST(virtual)
hkernel32 = GetModuleHandleA("kernel32.dll");
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
test_VirtualAllocEx();
test_VirtualAlloc();
test_MapViewOfFile();
test_NtMapViewOfSection();
test_CreateFileMapping();
test_BadPtr();
test_write_watch();
}

View file

@ -27,6 +27,8 @@ static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD
static HANDLE (WINAPI *pFindFirstVolumeA)(LPSTR,DWORD);
static BOOL (WINAPI *pFindNextVolumeA)(HANDLE,LPSTR,DWORD);
static BOOL (WINAPI *pFindVolumeClose)(HANDLE);
static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR);
static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR);
/* ############################### */
@ -37,6 +39,11 @@ static void test_query_dos_deviceA(void)
DWORD ret;
BOOL found = FALSE;
if (!pFindFirstVolumeA) {
skip("On win9x, HARDDISK and RAMDISK not present\n");
return;
}
for (;drivestr[0] <= 'z'; drivestr[0]++) {
ret = QueryDosDeviceA( drivestr, buffer, sizeof(buffer));
if(ret) {
@ -44,7 +51,7 @@ static void test_query_dos_deviceA(void)
if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
}
}
todo_wine ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
}
static void test_FindFirstVolume(void)
@ -134,6 +141,81 @@ static void test_GetVolumeNameForVolumeMountPointW(void)
ok(ret == TRUE, "GetVolumeNameForVolumeMountPointW failed\n");
}
static void test_GetLogicalDriveStringsA(void)
{
UINT size, size2;
char *buf, *ptr;
if(!pGetLogicalDriveStringsA) {
win_skip("GetLogicalDriveStringsA not available\n");
return;
}
size = pGetLogicalDriveStringsA(0, NULL);
ok(size%4 == 1, "size = %d\n", size);
buf = HeapAlloc(GetProcessHeap(), 0, size);
*buf = 0;
size2 = pGetLogicalDriveStringsA(2, buf);
ok(size2 == size, "size2 = %d\n", size2);
ok(!*buf, "buf changed\n");
size2 = pGetLogicalDriveStringsA(size, buf);
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(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]);
}
ok(!*ptr, "buf[size2] is not nullbyte\n");
HeapFree(GetProcessHeap(), 0, buf);
}
static void test_GetLogicalDriveStringsW(void)
{
UINT size, size2;
WCHAR *buf, *ptr;
if(!pGetLogicalDriveStringsW) {
win_skip("GetLogicalDriveStringsW not available\n");
return;
}
SetLastError(0xdeadbeef);
size = pGetLogicalDriveStringsW(0, NULL);
if (size == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
win_skip("GetLogicalDriveStringsW not implemented\n");
return;
}
ok(size%4 == 1, "size = %d\n", size);
buf = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
*buf = 0;
size2 = pGetLogicalDriveStringsW(2, buf);
ok(size2 == size, "size2 = %d\n", size2);
ok(!*buf, "buf changed\n");
size2 = pGetLogicalDriveStringsW(size, buf);
ok(size2 == size-1, "size2 = %d\n", size2);
for(ptr = buf; ptr < buf+size2; ptr += 4) {
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]);
}
ok(!*ptr, "buf[size2] is not nullbyte\n");
HeapFree(GetProcessHeap(), 0, buf);
}
START_TEST(volume)
{
hdll = GetModuleHandleA("kernel32.dll");
@ -142,9 +224,13 @@ START_TEST(volume)
pFindFirstVolumeA = (void *) GetProcAddress(hdll, "FindFirstVolumeA");
pFindNextVolumeA = (void *) GetProcAddress(hdll, "FindNextVolumeA");
pFindVolumeClose = (void *) GetProcAddress(hdll, "FindVolumeClose");
pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA");
pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
test_query_dos_deviceA();
test_FindFirstVolume();
test_GetVolumeNameForVolumeMountPointA();
test_GetVolumeNameForVolumeMountPointW();
test_GetLogicalDriveStringsA();
test_GetLogicalDriveStringsW();
}