"</dependency>"
"</assembly>";
+static const char manifest6[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v1\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"ASINVOKER\" uiAccess=\"false\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
+static const char manifest7[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"requireAdministrator\" uiAccess=\"TRUE\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
+static const char manifest8[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"requireAdministrator\" uiAccess=\"true\">"
+" </requestedExecutionLevel>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
+static const char manifest9[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"requireAdministrator\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
static const char testdep_manifest1[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity type=\"win32\" name=\"testdep\" version=\"6.5.4.3\" processorArchitecture=\"" ARCH "\"/>"
"<file></file>"
"</assembly>";
+static const char wrong_manifest9[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"requireAdministrator\"/>"
+" <requestedExecutionLevel uiAccess=\"true\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
+static const char wrong_manifest10[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.0.0.0\" name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel level=\"requireAdministrator\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">"
+" <security>"
+" <requestedPrivileges>"
+" <requestedExecutionLevel uiAccess=\"true\"/>"
+" </requestedPrivileges>"
+" </security>"
+"</trustInfo>"
+"</assembly>";
+
static const char wrong_depmanifest1[] =
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity type=\"win32\" name=\"testdep\" version=\"6.5.4.4\" processorArchitecture=\"" ARCH "\" />"
HeapFree(GetProcessHeap(), 0, info);
}
+typedef struct {
+ ACTCTX_REQUESTED_RUN_LEVEL run_level;
+ DWORD ui_access;
+} runlevel_info_t;
+
+static const runlevel_info_t runlevel_info0 = {
+ ACTCTX_RUN_LEVEL_UNSPECIFIED, FALSE,
+};
+
+static const runlevel_info_t runlevel_info6 = {
+ ACTCTX_RUN_LEVEL_AS_INVOKER, FALSE,
+};
+
+static const runlevel_info_t runlevel_info7 = {
+ ACTCTX_RUN_LEVEL_REQUIRE_ADMIN, TRUE,
+};
+
+static const runlevel_info_t runlevel_info8 = {
+ ACTCTX_RUN_LEVEL_REQUIRE_ADMIN, TRUE,
+};
+
+static const runlevel_info_t runlevel_info9 = {
+ ACTCTX_RUN_LEVEL_REQUIRE_ADMIN, FALSE,
+};
+
+static void test_runlevel_info(HANDLE handle, const runlevel_info_t *exinfo, int line)
+{
+ ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION runlevel_info;
+ SIZE_T size, retsize;
+ BOOL b;
+
+ size = sizeof(runlevel_info);
+ b = pQueryActCtxW(0, handle, NULL,
+ RunlevelInformationInActivationContext, &runlevel_info,
+ sizeof(runlevel_info), &retsize);
+ if (!b && GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ win_skip("RunlevelInformationInActivationContext not supported.\n");
+ return;
+ }
+
+ ok_(__FILE__, line)(b, "QueryActCtx failed: %u\n", GetLastError());
+ ok_(__FILE__, line)(retsize == size, "size=%ld, expected %ld\n", retsize, size);
+
+ ok_(__FILE__, line)(runlevel_info.ulFlags == 0, "runlevel_info.ulFlags=%x\n", runlevel_info.ulFlags);
+ ok_(__FILE__, line)(runlevel_info.RunLevel == exinfo->run_level,
+ "runlevel_info.RunLevel=%u, expected %u\n", runlevel_info.RunLevel, exinfo->run_level);
+ ok_(__FILE__, line)(runlevel_info.UiAccess == exinfo->ui_access,
+ "runlevel_info.UiAccess=%u, expected %u\n", runlevel_info.UiAccess, exinfo->ui_access);
+}
+
static HANDLE test_create(const char *file)
{
ACTCTXW actctx;
test_create_and_fail(wrong_manifest7, NULL, 1 );
trace("wrong_manifest8\n");
test_create_and_fail(wrong_manifest8, NULL, 0 );
+ trace("wrong_manifest9\n");
+ test_create_and_fail(wrong_manifest9, NULL, 0 );
+ trace("wrong_manifest10\n");
+ test_create_and_fail(wrong_manifest10, NULL, 0 );
trace("UTF-16 manifest1 without BOM\n");
test_create_wide_and_fail(manifest1, FALSE );
trace("manifest2\n");
if(b) {
test_basic_info(handle, __LINE__);
test_detailed_info(handle, &detailed_info0, __LINE__);
+ test_runlevel_info(handle, &runlevel_info0, __LINE__);
pReleaseActCtx(handle);
}
pReleaseActCtx(handle);
}
+ trace("manifest6\n");
+
+ if(create_manifest_file("test6.manifest", manifest6, -1, NULL, NULL)) {
+ handle = test_create("test6.manifest");
+ ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+ DeleteFileA("test6.manifest");
+ DeleteFileA("testdep.manifest");
+ if(handle != INVALID_HANDLE_VALUE)
+ {
+ test_runlevel_info(handle, &runlevel_info6, __LINE__);
+ pReleaseActCtx(handle);
+ }
+ }
+ else
+ skip("Could not create manifest file 6\n");
+
+ trace("manifest7\n");
+
+ if(create_manifest_file("test7.manifest", manifest7, -1, NULL, NULL)) {
+ handle = test_create("test7.manifest");
+ ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+ DeleteFileA("test7.manifest");
+ DeleteFileA("testdep.manifest");
+ if(handle != INVALID_HANDLE_VALUE)
+ {
+ test_runlevel_info(handle, &runlevel_info7, __LINE__);
+ pReleaseActCtx(handle);
+ }
+ }
+ else
+ skip("Could not create manifest file 7\n");
+
+ trace("manifest8\n");
+
+ if(create_manifest_file("test8.manifest", manifest8, -1, NULL, NULL)) {
+ handle = test_create("test8.manifest");
+ ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+ DeleteFileA("test8.manifest");
+ DeleteFileA("testdep.manifest");
+ if(handle != INVALID_HANDLE_VALUE)
+ {
+ test_runlevel_info(handle, &runlevel_info8, __LINE__);
+ pReleaseActCtx(handle);
+ }
+ }
+ else
+ skip("Could not create manifest file 8\n");
+
+ trace("manifest9\n");
+
+ if(create_manifest_file("test9.manifest", manifest9, -1, NULL, NULL)) {
+ handle = test_create("test9.manifest");
+ ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+ DeleteFileA("test9.manifest");
+ DeleteFileA("testdep.manifest");
+ if(handle != INVALID_HANDLE_VALUE)
+ {
+ test_runlevel_info(handle, &runlevel_info9, __LINE__);
+ pReleaseActCtx(handle);
+ }
+ }
+ else
+ skip("Could not create manifest file 9\n");
+
trace("manifest4\n");
if(!create_manifest_file("test4.manifest", manifest4, -1, NULL, NULL)) {
BOOL used;
INT len;
+ /* Unrecognized flag => ERROR_INVALID_FLAGS */
+ SetLastError(0xdeadbeef);
+ len = WideCharToMultiByte(CP_ACP, 0x100, w_string, -1, c_string, c_string_len, NULL, NULL);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%x\n", len, GetLastError());
+
+ SetLastError(0xdeadbeef);
+ len = WideCharToMultiByte(CP_ACP, 0x800, w_string, -1, c_string, c_string_len, NULL, NULL);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%x\n", len, GetLastError());
+
+ SetLastError(0xdeadbeef);
+ len = MultiByteToWideChar(CP_ACP, 0x10, c_string, -1, w_string, w_string_len);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_FLAGS, "len=%d error=%x\n", len, GetLastError());
+
+
+ /* Unrecognized flag and invalid codepage => ERROR_INVALID_PARAMETER */
+ SetLastError(0xdeadbeef);
+ len = WideCharToMultiByte(0xdeadbeef, 0x100, w_string, w_string_len, c_string, c_string_len, NULL, NULL);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
+
+ SetLastError(0xdeadbeef);
+ len = MultiByteToWideChar(0xdeadbeef, 0x10, c_string, c_string_len, w_string, w_string_len);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
+
+
+ /* Unrecognized flag and src is NULL => ERROR_INVALID_PARAMETER */
+ SetLastError(0xdeadbeef);
+ len = WideCharToMultiByte(CP_ACP, 0x100, NULL, -1, c_string, c_string_len, NULL, NULL);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
+
+ SetLastError(0xdeadbeef);
+ len = MultiByteToWideChar(CP_ACP, 0x10, NULL, -1, w_string, w_string_len);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
+
+
/* srclen=0 => ERROR_INVALID_PARAMETER */
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_ACP, 0, w_string, 0, c_string, c_string_len, NULL, NULL);
SetLastError(0xdeadbeef);
len = WideCharToMultiByte(CP_UTF7, 1, w_string, w_string_len, c_string, c_string_len, NULL, &used);
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
+
+ /* CP_UTF8, unrecognized flag and used not NULL => ERROR_INVALID_PARAMETER */
+ SetLastError(0xdeadbeef);
+ len = WideCharToMultiByte(CP_UTF8, 0x100, w_string, w_string_len, c_string, c_string_len, NULL, &used);
+ ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%x\n", len, GetLastError());
}
static void test_overlapped_buffers(void)
ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
/* Clean up */
- ok(CloseHandle(complete_event), "Failed to close event handle, last error %d\n", GetLastError());
+ CloseHandle(complete_event);
}
static void test_GetSetConsoleInputExeName(void)
SetLastError(0xdeadbeef);
ret = pVerifyConsoleIoHandle(handle);
error = GetLastError();
- ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
+ ok(ret ||
+ broken(!ret), /* Windows 8 and 10 */
+ "expected VerifyConsoleIoHandle to succeed\n");
ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
}
const INPUT_RECORD *buffer;
DWORD count;
LPDWORD written;
- DWORD expected_count;
DWORD gle, gle2;
int win_crash;
} invalid_table[] =
{
- {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
- {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
- {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
- {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
- {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 0, &count,ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+ {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, &event, 0, &count, ERROR_INVALID_HANDLE},
+ {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, &event, 1, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, &count, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
+ {INVALID_HANDLE_VALUE, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, &event, 0, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, &event, 1, &count, ERROR_INVALID_HANDLE},
+ {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+ {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
};
/* Suppress external sources of input events for the duration of the test. */
invalid_table[i].count,
invalid_table[i].written);
ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
- if (invalid_table[i].written)
- {
- ok(count == invalid_table[i].expected_count,
- "[%d] Expected output count to be %u, got %u\n",
- i, invalid_table[i].expected_count, count);
- }
gle = GetLastError();
ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
"[%d] Expected last error to be %u or %u, got %u\n",
const INPUT_RECORD *buffer;
DWORD count;
LPDWORD written;
- DWORD expected_count;
DWORD gle, gle2;
int win_crash;
} invalid_table[] =
{
- {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
- {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
- {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
- {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
- {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
- {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 0, &count, ERROR_INVALID_HANDLE},
+ {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+ {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, &event, 0, &count, ERROR_INVALID_HANDLE},
+ {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {NULL, &event, 1, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, NULL, 0, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, NULL, 1, &count, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
+ {INVALID_HANDLE_VALUE, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, &event, 0, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {INVALID_HANDLE_VALUE, &event, 1, &count, ERROR_INVALID_HANDLE},
+ {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+ {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
+ {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
};
/* Suppress external sources of input events for the duration of the test. */
invalid_table[i].count,
invalid_table[i].written);
ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
- if (invalid_table[i].written)
- {
- ok(count == invalid_table[i].expected_count,
- "[%d] Expected output count to be %u, got %u\n",
- i, invalid_table[i].expected_count, count);
- }
gle = GetLastError();
ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
"[%d] Expected last error to be %u or %u, got %u\n",
DWORD length;
COORD coord;
LPDWORD lpNumCharsWritten;
- DWORD expected_count;
DWORD last_error;
int win7_crash;
} invalid_table[] =
{
- {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
};
for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
invalid_table[i].coord,
invalid_table[i].lpNumCharsWritten);
ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
- if (invalid_table[i].lpNumCharsWritten)
- {
- ok(count == invalid_table[i].expected_count,
- "[%d] Expected count to be %u, got %u\n",
- i, invalid_table[i].expected_count, count);
- }
ok(GetLastError() == invalid_table[i].last_error,
"[%d] Expected last error to be %u, got %u\n",
i, invalid_table[i].last_error, GetLastError());
DWORD length;
COORD coord;
LPDWORD lpNumCharsWritten;
- DWORD expected_count;
DWORD last_error;
int win7_crash;
} invalid_table[] =
{
- {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
};
for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
invalid_table[i].coord,
invalid_table[i].lpNumCharsWritten);
ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
- if (invalid_table[i].lpNumCharsWritten)
- {
- ok(count == invalid_table[i].expected_count,
- "[%d] Expected count to be %u, got %u\n",
- i, invalid_table[i].expected_count, count);
- }
ok(GetLastError() == invalid_table[i].last_error,
"[%d] Expected last error to be %u, got %u\n",
i, invalid_table[i].last_error, GetLastError());
DWORD length;
COORD coord;
LPDWORD lpNumAttrsWritten;
- DWORD expected_count;
DWORD last_error;
int win7_crash;
} invalid_table[] =
{
- {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
- {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
- {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+ {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
+ {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
+ {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
};
for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
invalid_table[i].coord,
invalid_table[i].lpNumAttrsWritten);
ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
- if (invalid_table[i].lpNumAttrsWritten)
- {
- ok(count == invalid_table[i].expected_count,
- "[%d] Expected count to be %u, got %u\n",
- i, invalid_table[i].expected_count, count);
- }
ok(GetLastError() == invalid_table[i].last_error,
"[%d] Expected last error to be %u, got %u\n",
i, invalid_table[i].last_error, GetLastError());
SetLastError(0xdeadbeef);
ret = GetFileSize(std_input, NULL);
ok(ret == INVALID_FILE_SIZE, "expected INVALID_FILE_SIZE, got %#x\n", ret);
- ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ ok(GetLastError() == ERROR_INVALID_HANDLE ||
+ GetLastError() == ERROR_INVALID_FUNCTION, /* Win 8, 10 */
+ "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadFile(std_input, buf, -128, &bytes, NULL);
ok(!ret, "expected 0, got %u\n", ret);
- ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+ ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
+ GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
+ "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
ok(!bytes, "expected 0, got %u\n", bytes);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadConsoleA(std_input, buf, -128, &bytes, NULL);
ok(!ret, "expected 0, got %u\n", ret);
- ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+ ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
+ GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
+ "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = ReadConsoleW(std_input, buf, -128, &bytes, NULL);
ok(!ret, "expected 0, got %u\n", ret);
- ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+ ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
+ GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
+ "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
}
TerminateProcess(info.hProcess, WAIT_TIMEOUT);
WaitForSingleObject(info.hProcess, 5000);
CloseHandle(info.hProcess);
- assert(DeleteFileA(dbglog) != 0);
- assert(DeleteFileA(childlog) != 0);
+ DeleteFileA(dbglog);
+ DeleteFileA(childlog);
win_skip("Giving up on child process\n");
return;
}
skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
if (skip_crash_and_debug)
{
- assert(DeleteFileA(dbglog) != 0);
- assert(DeleteFileA(childlog) != 0);
+ DeleteFileA(dbglog);
+ DeleteFileA(childlog);
win_skip("Giving up on debugger\n");
return;
}
#endif
ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the debugger\n");
- assert(load_blackbox(childlog, &crash_blackbox, sizeof(crash_blackbox)));
- assert(load_blackbox(dbglog, &dbg_blackbox, sizeof(dbg_blackbox)));
+ ok(load_blackbox(childlog, &crash_blackbox, sizeof(crash_blackbox)), "failed to open: %s\n", childlog);
+ ok(load_blackbox(dbglog, &dbg_blackbox, sizeof(dbg_blackbox)), "failed to open: %s\n", dbglog);
ok(dbg_blackbox.argc == 6, "wrong debugger argument count: %d\n", dbg_blackbox.argc);
ok(dbg_blackbox.pid == crash_blackbox.pid, "the child and debugged pids don't match: %d != %d\n", crash_blackbox.pid, dbg_blackbox.pid);
ok(dbg_blackbox.nokill_rc, "DebugSetProcessKillOnExit(FALSE) failed err=%d\n", dbg_blackbox.nokill_err);
ok(dbg_blackbox.detach_rc, "DebugActiveProcessStop(%d) failed err=%d\n", dbg_blackbox.pid, dbg_blackbox.detach_err);
- assert(DeleteFileA(dbglog) != 0);
- assert(DeleteFileA(childlog) != 0);
+ DeleteFileA(dbglog);
+ DeleteFileA(childlog);
}
static void crash_and_winedbg(HKEY hkey, const char* argv0)
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "wine/winternl.h"
+
+static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,ULONG,PULONG);
+
+static void init(void)
+{
+ HMODULE hntdll = GetModuleHandleA("ntdll.dll");
+ pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
+}
+
+#define TEST_GRANTED_ACCESS(a,b) test_granted_access(a,b,__LINE__)
+static void test_granted_access(HANDLE handle, ACCESS_MASK access, int line)
+{
+ OBJECT_BASIC_INFORMATION obj_info;
+ NTSTATUS status;
+
+ status = pNtQueryObject(handle, ObjectBasicInformation, &obj_info,
+ sizeof(obj_info), NULL);
+ ok_(__FILE__, line)(!status, "NtQueryObject with err: %08x\n", status);
+ ok_(__FILE__, line)(obj_info.GrantedAccess == access, "Granted access should "
+ "be 0x%08x, instead of 0x%08x\n", access, obj_info.GrantedAccess);
+}
/* If you change something in these tests, please do the same
* for GetSystemDirectory tests.
static void test_RemoveDirectoryA(void)
{
+ char curdir[MAX_PATH];
char tmpdir[MAX_PATH];
BOOL ret;
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE, "CreateDirectoryA should always succeed\n");
+ GetCurrentDirectoryA(MAX_PATH, curdir);
+ ok(SetCurrentDirectoryA(tmpdir), "SetCurrentDirectoryA failed\n");
+
+ SetLastError(0xdeadbeef);
+ ok(!RemoveDirectoryA(tmpdir), "RemoveDirectoryA succeeded\n");
+ ok(GetLastError() == ERROR_SHARING_VIOLATION,
+ "Expected ERROR_SHARING_VIOLATION, got %u\n", GetLastError());
+
+ TEST_GRANTED_ACCESS(NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle,
+ FILE_TRAVERSE | SYNCHRONIZE);
+
+ SetCurrentDirectoryA(curdir);
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE, "RemoveDirectoryA should always succeed\n");
static void test_RemoveDirectoryW(void)
{
+ WCHAR curdir[MAX_PATH];
WCHAR tmpdir[MAX_PATH];
BOOL ret;
static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0};
ok(ret == TRUE, "CreateDirectoryW should always succeed\n");
+ GetCurrentDirectoryW(MAX_PATH, curdir);
+ ok(SetCurrentDirectoryW(tmpdir), "SetCurrentDirectoryW failed\n");
+
+ SetLastError(0xdeadbeef);
+ ok(!RemoveDirectoryW(tmpdir), "RemoveDirectoryW succeeded\n");
+ ok(GetLastError() == ERROR_SHARING_VIOLATION,
+ "Expected ERROR_SHARING_VIOLATION, got %u\n", GetLastError());
+
+ TEST_GRANTED_ACCESS(NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.Handle,
+ FILE_TRAVERSE | SYNCHRONIZE);
+
+ SetCurrentDirectoryW(curdir);
ret = RemoveDirectoryW(tmpdir);
ok(ret == TRUE, "RemoveDirectoryW should always succeed\n");
START_TEST(directory)
{
+ init();
+
test_GetWindowsDirectoryA();
test_GetWindowsDirectoryW();
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*);
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
+static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
+static void (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
-static const char filename[] = "testfile.xxx";
+static char filename[MAX_PATH];
static const char sillytext[] =
"en larvig liten text dx \033 gx hej 84 hej 4484 ! \001\033 bla bl\na.. bla bla."
"1234 43 4kljf lf &%%%&&&&&& 34 4 34 3############# 33 3 3 3 # 3## 3"
pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
+ pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
+ pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
ANSI_STRING str;
NTSTATUS status;
BOOLEAN ret;
- RtlInitAnsiString( &str, name );
+
+ pRtlInitAnsiString( &str, name );
status = pRtlAnsiStringToUnicodeString( &strW, &str, TRUE );
ok( !status, "RtlAnsiStringToUnicodeString failed with %08x\n", status );
ret = pRtlDosPathNameToNtPathName_U( strW.Buffer, nameW, NULL, NULL );
ok( ret, "RtlDosPathNameToNtPathName_U failed\n" );
- RtlFreeUnicodeString( &strW );
+ pRtlFreeUnicodeString( &strW );
}
static void test__lcreat( void )
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
- status = NtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
+ status = pNtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
ok( status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08x\n", status );
ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
- status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
+ status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
- status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
+ status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_DIRECTORY_FILE, NULL, 0 );
ok( status == STATUS_NOT_A_DIRECTORY, "expected STATUS_NOT_A_DIRECTORY, got %08x\n", status );
- status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
+ status = pNtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
todo_wine
ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
if (!status) CloseHandle( file );
- RtlFreeUnicodeString( &filenameW );
+ pRtlFreeUnicodeString( &filenameW );
todo_wine
ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
if (INVALID_HANDLE_VALUE==find)
ok (0, "file \"%s\" not found\n", filename);
else {
+ const char *name = strrchr(filename, '\\');
+
+ if (name) name++;
+ else name = filename;
+
ret = FindClose(find);
ok ( 0 != ret, "FindClose complains (%d)\n", GetLastError ());
- ok (!strcmp (filename, search_results.cFileName),
- "found unexpected name \"%s\"\n", search_results.cFileName);
+ ok (!strcmp (name, search_results.cFileName),
+ "expected \"%s\", got \"%s\"\n", name, search_results.cFileName);
search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+ search_results.dwFileAttributes &= ~FILE_ATTRIBUTE_COMPRESSED;
ok (FILE_ATTRIBUTE_ARCHIVE==search_results.dwFileAttributes,
"attributes of file \"%s\" are 0x%04x\n", search_results.cFileName,
search_results.dwFileAttributes);
ret = GetTempFileNameA(temp_path, prefix, 0, source);
ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
- ret = MoveFileA(source, source);
- todo_wine ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
-
/* copying a file to itself must fail */
retok = CopyFileA(source, source, FALSE);
ok( !retok && (GetLastError() == ERROR_SHARING_VIOLATION || broken(GetLastError() == ERROR_FILE_EXISTS) /* Win 9x */),
char directory[] = "removeme";
static const char nt_drive[] = "\\\\?\\A:";
DWORD i, ret, len;
- struct test_list p[] = {
- {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */
- {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */
- {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */
- {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */
- {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */
- {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */
- {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */
- {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */
- {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
- {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */
- {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */
- {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */
- {NULL, 0, -1, 0, FALSE}
+ static const struct test_list p[] =
+ {
+ {"", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dir as file w \ */
+ {"", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* dir as dir w \ */
+ {"a", ERROR_FILE_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist file */
+ {"a\\", ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* non-exist dir */
+ {"removeme", ERROR_ACCESS_DENIED, -1, FILE_ATTRIBUTE_NORMAL, FALSE }, /* exist dir w/o \ */
+ {"removeme\\", ERROR_PATH_NOT_FOUND, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* exst dir w \ */
+ {"c:", ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND, FILE_ATTRIBUTE_NORMAL, FALSE }, /* device in file namespace */
+ {"c:", ERROR_SUCCESS, ERROR_PATH_NOT_FOUND, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* device in file namespace as dir */
+ {"c:\\", ERROR_PATH_NOT_FOUND, ERROR_ACCESS_DENIED, FILE_ATTRIBUTE_NORMAL, TRUE }, /* root dir w \ */
+ {"c:\\", ERROR_SUCCESS, ERROR_ACCESS_DENIED, FILE_FLAG_BACKUP_SEMANTICS, FALSE }, /* root dir w \ as dir */
+ {"c:c:\\windows", ERROR_INVALID_NAME, -1, FILE_ATTRIBUTE_NORMAL, TRUE }, /* invalid path */
+ {"\\\\?\\c:", ERROR_SUCCESS, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL,FALSE }, /* dev namespace drive */
+ {"\\\\?\\c:\\", ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, FILE_ATTRIBUTE_NORMAL, TRUE }, /* dev namespace drive w \ */
+ {NULL, 0, -1, 0, FALSE}
};
BY_HANDLE_FILE_INFORMATION Finfo;
WCHAR curdir[MAX_PATH];
ret = GetTempFileNameA(tempdir, prefix, 0, dest);
ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
+ ret = MoveFileA(source, source);
+ ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
+
ret = MoveFileA(source, dest);
ok(!ret && GetLastError() == ERROR_ALREADY_EXISTS,
"MoveFileA: unexpected error %d\n", GetLastError());
ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
ret = MoveFileA(source, dest);
- todo_wine {
- ok(!ret, "MoveFileA: expected failure\n");
- ok(GetLastError() == ERROR_SHARING_VIOLATION ||
- broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
- "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
- }
+ ok(!ret, "MoveFileA: expected failure\n");
+ ok(GetLastError() == ERROR_SHARING_VIOLATION ||
+ broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
+ "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
CloseHandle(hmapfile);
CloseHandle(hfile);
ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
ret = MoveFileA(source, dest);
- todo_wine {
- ok(!ret, "MoveFileA: expected failure\n");
- ok(GetLastError() == ERROR_SHARING_VIOLATION ||
- broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
- "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
- }
+ ok(!ret, "MoveFileA: expected failure\n");
+ ok(GetLastError() == ERROR_SHARING_VIOLATION ||
+ broken(GetLastError() == ERROR_ACCESS_DENIED), /* Win9x and WinMe */
+ "MoveFileA: expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
CloseHandle(hmapfile);
CloseHandle(hfile);
static void test_file_sharing(void)
{
- static const DWORD access_modes[] =
- { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
- DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE,
- GENERIC_EXECUTE, GENERIC_EXECUTE | DELETE,
- FILE_READ_DATA, FILE_WRITE_DATA, FILE_APPEND_DATA, FILE_READ_EA, FILE_WRITE_EA,
- FILE_READ_DATA | FILE_EXECUTE, FILE_WRITE_DATA | FILE_EXECUTE, FILE_APPEND_DATA | FILE_EXECUTE,
- FILE_READ_EA | FILE_EXECUTE, FILE_WRITE_EA | FILE_EXECUTE, FILE_EXECUTE,
- FILE_DELETE_CHILD, FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES };
- static const DWORD sharing_modes[] =
- { 0, FILE_SHARE_READ,
- FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
- FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
- static const DWORD mapping_modes[] =
- { PAGE_READONLY, PAGE_WRITECOPY, PAGE_READWRITE, SEC_IMAGE | PAGE_WRITECOPY };
+ struct mode { DWORD dw; const char* str; };
+#define M(x) {x, # x}
+ static const struct mode access_modes[] =
+ { M(0), M(GENERIC_READ), M(GENERIC_WRITE), M(GENERIC_READ|GENERIC_WRITE),
+ M(DELETE), M(GENERIC_READ|DELETE), M(GENERIC_WRITE|DELETE), M(GENERIC_READ|GENERIC_WRITE|DELETE),
+ M(GENERIC_EXECUTE), M(GENERIC_EXECUTE | DELETE),
+ M(FILE_READ_DATA), M(FILE_WRITE_DATA), M(FILE_APPEND_DATA), M(FILE_READ_EA), M(FILE_WRITE_EA),
+ M(FILE_READ_DATA | FILE_EXECUTE), M(FILE_WRITE_DATA | FILE_EXECUTE), M(FILE_APPEND_DATA | FILE_EXECUTE),
+ M(FILE_READ_EA | FILE_EXECUTE), M(FILE_WRITE_EA | FILE_EXECUTE), M(FILE_EXECUTE),
+ M(FILE_DELETE_CHILD), M(FILE_READ_ATTRIBUTES), M(FILE_WRITE_ATTRIBUTES) };
+ static const struct mode sharing_modes[] =
+ { M(0), M(FILE_SHARE_READ),
+ M(FILE_SHARE_WRITE), M(FILE_SHARE_READ|FILE_SHARE_WRITE),
+ M(FILE_SHARE_DELETE), M(FILE_SHARE_READ|FILE_SHARE_DELETE),
+ M(FILE_SHARE_WRITE|FILE_SHARE_DELETE), M(FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) };
+ static const struct mode mapping_modes[] =
+ { M(PAGE_READONLY), M(PAGE_WRITECOPY), M(PAGE_READWRITE), M(SEC_IMAGE | PAGE_WRITECOPY) };
+#undef M
int a1, s1, a2, s2;
int ret;
HANDLE h, h2;
for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
{
SetLastError(0xdeadbeef);
- h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
+ h = CreateFileA( filename, access_modes[a1].dw, sharing_modes[s1].dw,
NULL, OPEN_EXISTING, 0, 0 );
if (h == INVALID_HANDLE_VALUE)
{
for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
{
SetLastError(0xdeadbeef);
- h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
+ h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw,
NULL, OPEN_EXISTING, 0, 0 );
ret = GetLastError();
- if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
- access_modes[a2], sharing_modes[s2] ))
+ if (is_sharing_compatible( access_modes[a1].dw, sharing_modes[s1].dw,
+ access_modes[a2].dw, sharing_modes[s2].dw ))
{
ok( h2 != INVALID_HANDLE_VALUE,
- "open failed for modes %x/%x/%x/%x\n",
- access_modes[a1], sharing_modes[s1],
- access_modes[a2], sharing_modes[s2] );
+ "open failed for modes %s / %s / %s / %s\n",
+ access_modes[a1].str, sharing_modes[s1].str,
+ access_modes[a2].str, sharing_modes[s2].str );
ok( ret == 0, "wrong error code %d\n", ret );
}
else
{
ok( h2 == INVALID_HANDLE_VALUE,
- "open succeeded for modes %x/%x/%x/%x\n",
- access_modes[a1], sharing_modes[s1],
- access_modes[a2], sharing_modes[s2] );
+ "open succeeded for modes %s / %s / %s / %s\n",
+ access_modes[a1].str, sharing_modes[s1].str,
+ access_modes[a2].str, sharing_modes[s2].str );
ok( ret == ERROR_SHARING_VIOLATION,
"wrong error code %d\n", ret );
}
ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
return;
}
- m = CreateFileMappingA( h, NULL, mapping_modes[a1], 0, 0, NULL );
- ok( m != 0, "failed to create mapping %x err %u\n", mapping_modes[a1], GetLastError() );
+ m = CreateFileMappingA( h, NULL, mapping_modes[a1].dw, 0, 0, NULL );
+ ok( m != 0, "failed to create mapping %s err %u\n", mapping_modes[a1].str, GetLastError() );
CloseHandle( h );
if (!m) continue;
for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
{
SetLastError(0xdeadbeef);
- h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
+ h2 = CreateFileA( filename, access_modes[a2].dw, sharing_modes[s2].dw,
NULL, OPEN_EXISTING, 0, 0 );
ret = GetLastError();
if (h2 == INVALID_HANDLE_VALUE)
{
- ok( !is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]),
- "open failed for modes map %x/%x/%x\n",
- mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
+ ok( !is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw),
+ "open failed for modes map %s / %s / %s\n",
+ mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str );
ok( ret == ERROR_SHARING_VIOLATION,
"wrong error code %d\n", ret );
}
else
{
- if (!is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
+ if (!is_sharing_map_compatible(mapping_modes[a1].dw, access_modes[a2].dw, sharing_modes[s2].dw))
ok( broken(1), /* no checking on nt4 */
- "open succeeded for modes map %x/%x/%x\n",
- mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
+ "open succeeded for modes map %s / %s / %s\n",
+ mapping_modes[a1].str, access_modes[a2].str, sharing_modes[s2].str );
ok( ret == 0xdeadbeef /* Win9x */ ||
ret == 0, /* XP */
"wrong error code %d\n", ret );
h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, 0, 0 );
ret = GetLastError();
- if (mapping_modes[a1] & SEC_IMAGE)
+ if (mapping_modes[a1].dw & SEC_IMAGE)
{
- ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
- ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
+ ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
}
else
{
- ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
- ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
+ ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
}
if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
ret = GetLastError();
- if (mapping_modes[a1] & SEC_IMAGE)
+ if (mapping_modes[a1].dw & SEC_IMAGE)
{
- ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
- ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %s\n", mapping_modes[a1].str );
+ ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %s\n", ret, mapping_modes[a1].str );
}
else
{
- ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %x err %u\n", mapping_modes[a1], ret );
+ ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %s err %u\n", mapping_modes[a1].str, ret );
}
if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
return windowsdir[0];
}
-static
-struct
+static const struct
{
const char *path;
BOOL expected;
}
-const invalid_char_tests[] =
+invalid_char_tests[] =
{
{ "./test-dir", TRUE },
{ "./test-dir/", FALSE },
RemoveDirectoryA("test-dir");
}
+static void test_FindFirstFile_wildcards(void)
+{
+ WIN32_FIND_DATAA find_data;
+ HANDLE handle;
+ int i;
+ static const char* files[] = {
+ "..a", "..a.a", ".a", ".a..a", ".a.a", ".aaa",
+ "a", "a..a", "a.a", "a.a.a", "aa", "aaa", "aaaa"
+ };
+ static const struct {
+ int todo;
+ const char *pattern, *result;
+ } tests[] = {
+ {0, "*.*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, "*.*.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, ".*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"},
+ {0, "*.*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, ".*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa'"},
+ {1, "*.", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
+ {0, "*", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {1, "*..*", ", '.', '..', '..a', '..a.a', '.a..a', 'a..a'"},
+ {1, "*..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
+ {1, ".*.", ", '.', '..', '.a', '.aaa'"},
+ {0, "..*", ", '.', '..', '..a', '..a.a'"},
+ {0, "**", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, "**.", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, "*. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {1, "* .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
+ {0, "* . ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {0, "*.. ", ", '.', '..', '..a', '..a.a', '.a', '.a..a', '.a.a', '.aaa', 'a', 'a..a', 'a.a', 'a.a.a', 'aa', 'aaa', 'aaaa'"},
+ {1, "*. .", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
+ {1, "* ..", ", '.', '..', 'a', '.a', '..a', 'aa', 'aaa', 'aaaa', '.aaa'"},
+ {1, " *..", ", '.aaa'"},
+ {0, "..* ", ", '.', '..', '..a', '..a.a'"},
+ {1, "?", ", '.', '..', 'a'"},
+ {1, "?.", ", '.', '..', 'a'"},
+ {1, "?. ", ", '.', '..', 'a'"},
+ {1, "??.", ", '.', '..', 'a', 'aa'"},
+ {1, "??. ", ", '.', '..', 'a', 'aa'"},
+ {1, "???.", ", '.', '..', 'a', 'aa', 'aaa'"},
+ {1, "?.??.", ", '.', '..', '.a', 'a', 'a.a'"}
+ };
+
+ CreateDirectoryA("test-dir", NULL);
+ SetCurrentDirectoryA("test-dir");
+ for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
+ _lclose(_lcreat(files[i], 0));
+
+ for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
+ {
+ char correct[512];
+ char incorrect[512];
+ char missing[512];
+
+ strcpy(missing, tests[i].result);
+ correct[0] = incorrect[0] = 0;
+
+ handle = FindFirstFileA(tests[i].pattern, &find_data);
+ if (handle) do {
+ char* ptr;
+ char quoted[16];
+
+ sprintf( quoted, ", '%.10s'", find_data.cFileName );
+
+ if ((ptr = strstr(missing, quoted)))
+ {
+ int len = strlen(quoted);
+ while ((ptr[0] = ptr[len]) != 0)
+ ++ptr;
+ strcat(correct, quoted);
+ }
+ else
+ strcat(incorrect, quoted);
+ } while (FindNextFileA(handle, &find_data));
+ FindClose(handle);
+
+ todo_wine_if (tests[i].todo)
+ ok(missing[0] == 0 && incorrect[0] == 0,
+ "FindFirstFile with '%s' found correctly %s, found incorrectly %s, and missed %s\n",
+ tests[i].pattern,
+ correct[0] ? correct+2 : "none",
+ incorrect[0] ? incorrect+2 : "none",
+ missing[0] ? missing+2 : "none");
+ }
+
+ for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i)
+ DeleteFileA(files[i]);
+ SetCurrentDirectoryA("..");
+ RemoveDirectoryA("test-dir");
+}
+
static int test_Mapfile_createtemp(HANDLE *handle)
{
SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
ok(!ret, "%d: WriteFile should fail\n", i);
ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
}
+ SetLastError(0xdeadbeef);
+ ret = SetFileTime(hfile, NULL, NULL, NULL);
+ if (td[i].access & GENERIC_WRITE) /* actually FILE_WRITE_ATTRIBUTES */
+ ok(ret, "%d: SetFileTime error %d\n", i, GetLastError());
+ else
+ {
+ todo_wine
+ {
+ ok(!ret, "%d: SetFileTime should fail\n", i);
+ ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+ }
+ }
CloseHandle(hfile);
}
else
{
FILE_ATTRIBUTE_TAG_INFO fileattrinfo = { 0 };
FILE_REMOTE_PROTOCOL_INFO protinfo = { 0 };
- FILE_STANDARD_INFO stdinfo;
+ FILE_STANDARD_INFO stdinfo = { {{0}},{{0}},0,FALSE,FALSE };
FILE_COMPRESSION_INFO compressinfo;
FILE_DISPOSITION_INFO dispinfo;
char tempFileName[MAX_PATH];
START_TEST(file)
{
+ char temp_path[MAX_PATH];
+ DWORD ret;
+
InitFunctionPointers();
+ ret = GetTempPathA(MAX_PATH, temp_path);
+ ok(ret != 0, "GetTempPath error %u\n", GetLastError());
+ ret = GetTempFileNameA(temp_path, "tmp", 0, filename);
+ ok(ret != 0, "GetTempFileName error %u\n", GetLastError());
+ ret = DeleteFileA(filename);
+ ok(ret != 0, "DeleteFile error %u\n", GetLastError());
+
test__hread( );
test__hwrite( );
test__lclose( );
test_MoveFileW();
test_FindFirstFileA();
test_FindNextFileA();
+ test_FindFirstFile_wildcards();
test_FindFirstFileExA(FindExInfoStandard, 0, 0);
test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_CASE_SENSITIVE);
test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_LARGE_FETCH);
#include "winbase.h"
#include "winnls.h"
+#define ULL(a,b) (((ULONG64)(a) << 32) | (b))
+
static DWORD __cdecl doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
LPSTR out, DWORD outsize, ... )
{
"Expected the output buffer to be untouched\n");
}
+static void test_message_from_64bit_number(void)
+{
+ static const WCHAR I64d[] = {'%', '1', '!', 'I', '6', '4', 'd', '!', 0};
+ static const WCHAR I64u[] = {'%', '1', '!', 'I', '6', '4', 'u', '!', 0};
+ WCHAR outW[0x100], expW[0x100];
+ char outA[0x100];
+ DWORD r;
+ static const struct
+ {
+ UINT64 number;
+ const char expected[32];
+ int len;
+ } unsigned_tests[] =
+ {
+ { 0, "0", 1 },
+ { 1234567890, "1234567890", 10},
+ { ULL(0xFFFFFFFF,0xFFFFFFFF), "18446744073709551615", 20 },
+ { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 },
+ };
+ static const struct
+ {
+ INT64 number;
+ const char expected[32];
+ int len;
+ } signed_tests[] =
+ {
+ { 0, "0" , 1},
+ { 1234567890, "1234567890", 10 },
+ { -1, "-1", 2},
+ { ULL(0xFFFFFFFF,0xFFFFFFFF), "-1", 2},
+ { ULL(0x7FFFFFFF,0xFFFFFFFF), "9223372036854775807", 19 },
+ { -ULL(0x7FFFFFFF,0xFFFFFFFF), "-9223372036854775807", 20},
+ };
+ int i;
+
+ for (i = 0; i < sizeof(unsigned_tests) / sizeof(unsigned_tests[0]); i++)
+ {
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, I64u,
+ 0, 0, outW, sizeof(outW) / sizeof(WCHAR), unsigned_tests[i].number);
+ MultiByteToWideChar(CP_ACP, 0, unsigned_tests[i].expected, -1, expW, sizeof(expW) / sizeof(WCHAR));
+todo_wine {
+ ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
+ unsigned_tests[i].expected, wine_dbgstr_w(outW));
+ ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r);
+}
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64u!",
+ 0, 0, outA, sizeof(outA), unsigned_tests[i].number);
+todo_wine {
+ ok(!strcmp(outA, unsigned_tests[i].expected),"[%d] failed, expected %s, got %s\n", i,
+ unsigned_tests[i].expected, outA);
+ ok(r == unsigned_tests[i].len,"[%d] failed: r=%d\n", i, r);
+}
+ }
+
+ for (i = 0; i < sizeof(signed_tests) / sizeof(signed_tests[0]); i++)
+ {
+ r = doitW(FORMAT_MESSAGE_FROM_STRING, I64d,
+ 0, 0, outW, sizeof(outW) / sizeof(WCHAR), signed_tests[i].number);
+ MultiByteToWideChar(CP_ACP, 0, signed_tests[i].expected, -1, expW, sizeof(expW) / sizeof(WCHAR));
+todo_wine {
+ ok(!lstrcmpW(outW, expW),"[%d] failed, expected %s, got %s\n", i,
+ signed_tests[i].expected, wine_dbgstr_w(outW));
+ ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r);
+}
+ r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!I64d!",
+ 0, 0, outA, sizeof(outA), signed_tests[i].number);
+todo_wine {
+ ok(!strcmp(outA, signed_tests[i].expected),"[%d] failed, expected %s, got %s\n", i,
+ signed_tests[i].expected, outA);
+ ok(r == signed_tests[i].len,"[%d] failed: r=%d\n", i, r);
+}
+ }
+}
+
START_TEST(format_msg)
{
DWORD ret;
test_message_null_buffer_wide();
test_message_allocate_buffer_wide();
test_message_invalid_flags_wide();
+ test_message_from_64bit_number();
}
HeapFree(GetProcessHeap(), 0, mem);
mem = HeapAlloc(GetProcessHeap(), 0, ~(SIZE_T)0);
ok(mem == NULL, "memory allocated for size ~0\n");
+ mem = HeapAlloc(GetProcessHeap(), 0, 17);
+ msecond = HeapReAlloc(GetProcessHeap(), 0, mem, 0);
+ ok(msecond != NULL, "HeapReAlloc(0) should have succeeded\n");
+ size = HeapSize(GetProcessHeap(), 0, msecond);
+ ok(size == 0 || broken(size == 1) /* some vista and win7 */,
+ "HeapSize should have returned 0 instead of %lu\n", size);
+ HeapFree(GetProcessHeap(), 0, msecond);
/* large blocks must be 16-byte aligned */
mem = HeapAlloc(GetProcessHeap(), 0, 512 * 1024);
"Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
+ gbl = GlobalAlloc( GMEM_FIXED, 0 );
+ SetLastError(0xdeadbeef);
+ size = GlobalSize( gbl );
+ ok( size == 1, "wrong size %lu\n", size );
+ GlobalFree( gbl );
+
/* ####################################### */
/* Local*() functions */
gbl = LocalAlloc(LMEM_MOVEABLE, 0);
broken(GetLastError() == 0xdeadbeef) /* win9x */, "got %d\n", GetLastError());
LocalFree(gbl);
+ gbl = LocalAlloc( LMEM_FIXED, 0 );
+ SetLastError(0xdeadbeef);
+ size = LocalSize( gbl );
+ ok( !size || broken(size == 1), /* vistau64 */
+ "wrong size %lu\n", size );
+ LocalFree( gbl );
+
/* trying to lock empty memory should give an error */
gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0);
ok(gbl != NULL, "returned NULL\n");
#include "windef.h"
#include "winbase.h"
#include "wine/winternl.h"
+#include "winuser.h"
#include "wine/test.h"
#include "delayloadhandler.h"
{
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &nt_header->OptionalHeader,
- min(nt_header->FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
+ sizeof(IMAGE_OPTIONAL_HEADER),
&dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
assert(nt_header->FileHeader.NumberOfSections <= 1);
if (nt_header->FileHeader.NumberOfSections)
{
+ SetFilePointer(hfile, dos_size + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + nt_header->FileHeader.SizeOfOptionalHeader, NULL, FILE_BEGIN);
+
section.SizeOfRawData = 10;
if (nt_header->OptionalHeader.SectionAlignment >= page_size)
ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
}
+
+ /* Minimal PE image that Windows7+ is able to load: 268 bytes */
+ size = GetFileSize(hfile, NULL);
+ if (size < 268)
+ {
+ file_align = 268 - size;
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+ }
+
size = GetFileSize(hfile, NULL);
CloseHandle(hfile);
return size;
image.LoaderFlags, nt_header->OptionalHeader.LoaderFlags );
ok( image.ImageFileSize == file_size || broken(!image.ImageFileSize), /* winxpsp1 */
"%u: ImageFileSize wrong %08x / %08x\n", id, image.ImageFileSize, file_size );
- ok( image.CheckSum == nt_header->OptionalHeader.CheckSum, "%u: CheckSum wrong %08x / %08x\n", id,
+ ok( image.CheckSum == nt_header->OptionalHeader.CheckSum || broken(truncated),
+ "%u: CheckSum wrong %08x / %08x\n", id,
image.CheckSum, nt_header->OptionalHeader.CheckSum );
/* FIXME: needs more work: */
/* image.GpValue */
/* Mandatory are all fields up to SizeOfHeaders, everything else
* is really optional (at least that's true for XP).
*/
+#if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */
{ sizeof(dos_header),
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,
{ ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS,
ERROR_NOACCESS }
},
+#endif
{ sizeof(dos_header),
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
0xd0, /* beyond of the end of file */
0x40, /* minimal image size that Windows7 accepts */
0,
{ ERROR_SUCCESS }
+ },
+ /* the following data mimics the PE image which 8k demos have */
+ { 0x04,
+ 0, 0x08,
+ 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
+ 0x200000,
+ 0x40,
+ { ERROR_SUCCESS }
}
};
int i;
ret = FreeLibrary(hlib_as_data_file);
ok(ret, "FreeLibrary error %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = DeleteFileA(dll_name);
+ ok(ret, "DeleteFile error %d\n", GetLastError());
+
+ nt_header.OptionalHeader.AddressOfEntryPoint = 0x12345678;
+ file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name );
+ if (!file_size)
+ {
+ ok(0, "could not create %s\n", dll_name);
+ break;
+ }
query_image_section( i, dll_name, &nt_header );
}
else
nt_header.FileHeader.Machine = orig_machine; /* restore it for the next tests */
}
+static void test_FakeDLL(void)
+{
+#ifdef __i386__
+ NTSTATUS (WINAPI *pNtSetEvent)(HANDLE, ULONG *) = NULL;
+ IMAGE_EXPORT_DIRECTORY *dir;
+ HMODULE module = GetModuleHandleA("ntdll.dll");
+ HANDLE file, map, event;
+ WCHAR path[MAX_PATH];
+ DWORD *names, *funcs;
+ WORD *ordinals;
+ ULONG size;
+ void *ptr;
+ int i;
+
+ GetModuleFileNameW(module, path, MAX_PATH);
+
+ file = CreateFileW(path, GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ ok(file != INVALID_HANDLE_VALUE, "Failed to open %s (error %u)\n", wine_dbgstr_w(path), GetLastError());
+
+ map = CreateFileMappingW(file, NULL, PAGE_EXECUTE_READ | SEC_IMAGE, 0, 0, NULL);
+ ok(map != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
+ ptr = MapViewOfFile(map, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, 0);
+ ok(ptr != NULL, "MapViewOfFile failed with error %u\n", GetLastError());
+
+ dir = RtlImageDirectoryEntryToData(ptr, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
+ ok(dir != NULL, "RtlImageDirectoryEntryToData failed\n");
+
+ names = RVAToAddr(dir->AddressOfNames, ptr);
+ ordinals = RVAToAddr(dir->AddressOfNameOrdinals, ptr);
+ funcs = RVAToAddr(dir->AddressOfFunctions, ptr);
+ ok(dir->NumberOfNames > 0, "Could not find any exported functions\n");
+
+ for (i = 0; i < dir->NumberOfNames; i++)
+ {
+ DWORD map_rva, dll_rva, map_offset, dll_offset;
+ char *func_name = RVAToAddr(names[i], ptr);
+ BYTE *dll_func, *map_func;
+
+ /* check only Nt functions for now */
+ if (strncmp(func_name, "Zw", 2) && strncmp(func_name, "Nt", 2))
+ continue;
+
+ dll_func = (BYTE *)GetProcAddress(module, func_name);
+ ok(dll_func != NULL, "%s: GetProcAddress returned NULL\n", func_name);
+ if (dll_func[0] == 0x90 && dll_func[1] == 0x90 &&
+ dll_func[2] == 0x90 && dll_func[3] == 0x90)
+ {
+ todo_wine ok(0, "%s: Export is a stub-function, skipping\n", func_name);
+ continue;
+ }
+
+ /* check position in memory */
+ dll_rva = (DWORD_PTR)dll_func - (DWORD_PTR)module;
+ map_rva = funcs[ordinals[i]];
+ ok(map_rva == dll_rva, "%s: Rva of mapped function (0x%x) does not match dll (0x%x)\n",
+ func_name, dll_rva, map_rva);
+
+ /* check position in file */
+ map_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(ptr), ptr, map_rva, NULL) - (DWORD_PTR)ptr;
+ dll_offset = (DWORD_PTR)RtlImageRvaToVa(RtlImageNtHeader(module), module, dll_rva, NULL) - (DWORD_PTR)module;
+ ok(map_offset == dll_offset, "%s: File offset of mapped function (0x%x) does not match dll (0x%x)\n",
+ func_name, map_offset, dll_offset);
+
+ /* check function content */
+ map_func = RVAToAddr(map_rva, ptr);
+ ok(!memcmp(map_func, dll_func, 0x20), "%s: Function content does not match!\n", func_name);
+
+ if (!strcmp(func_name, "NtSetEvent"))
+ pNtSetEvent = (void *)map_func;
+ }
+
+ ok(pNtSetEvent != NULL, "Could not find NtSetEvent export\n");
+ if (pNtSetEvent)
+ {
+ event = CreateEventA(NULL, TRUE, FALSE, NULL);
+ ok(event != NULL, "CreateEvent failed with error %u\n", GetLastError());
+ pNtSetEvent(event, 0);
+ ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n");
+ pNtSetEvent(event, 0);
+ ok(WaitForSingleObject(event, 0) == WAIT_OBJECT_0, "Event was not signaled\n");
+ CloseHandle(event);
+ }
+
+ UnmapViewOfFile(ptr);
+ CloseHandle(map);
+ CloseHandle(file);
+#endif
+}
+
/* Verify linking style of import descriptors */
static void test_ImportDescriptors(void)
{
ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
(void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
+ FreeLibrary( mod2 );
FreeLibrary( mod );
break;
case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */
static void test_InMemoryOrderModuleList(void)
{
- LIST_ENTRY *entry1, *mark1 = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
- LIST_ENTRY *entry2, *mark2 = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
+ PEB_LDR_DATA *ldr = NtCurrentTeb()->Peb->LdrData;
+ LIST_ENTRY *entry1, *mark1 = &ldr->InLoadOrderModuleList;
+ LIST_ENTRY *entry2, *mark2 = &ldr->InMemoryOrderModuleList;
LDR_MODULE *module1, *module2;
+ ok(ldr->Initialized == TRUE, "expected TRUE, got %u\n", ldr->Initialized);
+
for (entry1 = mark1->Flink, entry2 = mark2->Flink;
entry1 != mark1 && entry2 != mark2;
entry1 = entry1->Flink, entry2 = entry2->Flink)
ok(entry2 == mark2, "expected entry2 == mark2, got %p and %p\n", entry2, mark2);
}
+static inline WCHAR toupperW(WCHAR c)
+{
+ WCHAR tmp = c;
+ CharUpperBuffW(&tmp, 1);
+ return tmp;
+}
+
+static ULONG hash_basename(const WCHAR *basename)
+{
+ WORD version = MAKEWORD(NtCurrentTeb()->Peb->OSMinorVersion,
+ NtCurrentTeb()->Peb->OSMajorVersion);
+ ULONG hash = 0;
+
+ if (version >= 0x0602)
+ {
+ for (; *basename; basename++)
+ hash = hash * 65599 + toupperW(*basename);
+ }
+ else if (version == 0x0601)
+ {
+ for (; *basename; basename++)
+ hash = hash + 65599 * toupperW(*basename);
+ }
+ else
+ hash = toupperW(basename[0]) - 'A';
+
+ return hash & 31;
+}
+
+static void test_HashLinks(void)
+{
+ static WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0};
+ static WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
+
+ LIST_ENTRY *hash_map, *entry, *mark;
+ LDR_MODULE *module;
+ BOOL found;
+
+ entry = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
+ entry = entry->Flink;
+
+ module = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
+ entry = module->HashLinks.Blink;
+
+ hash_map = entry - hash_basename(module->BaseDllName.Buffer);
+
+ mark = &hash_map[hash_basename(ntdllW)];
+ found = FALSE;
+ for (entry = mark->Flink; entry != mark; entry = entry->Flink)
+ {
+ module = CONTAINING_RECORD(entry, LDR_MODULE, HashLinks);
+ if (!lstrcmpiW(module->BaseDllName.Buffer, ntdllW))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ ok(found, "Could not find ntdll\n");
+
+ mark = &hash_map[hash_basename(kernel32W)];
+ found = FALSE;
+ for (entry = mark->Flink; entry != mark; entry = entry->Flink)
+ {
+ module = CONTAINING_RECORD(entry, LDR_MODULE, HashLinks);
+ if (!lstrcmpiW(module->BaseDllName.Buffer, kernel32W))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ ok(found, "Could not find kernel32\n");
+}
+
START_TEST(loader)
{
int argc;
}
test_Loader();
+ test_FakeDLL();
test_ResolveDelayLoadedAPI();
test_ImportDescriptors();
test_section_access();
test_import_resolution();
test_ExitProcess();
test_InMemoryOrderModuleList();
+ test_HashLinks();
}
static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
+static const WCHAR title_case[] = {'\t','J','u','s','t','!',' ','A',',',' ','T','e','s','t',';',' ','S','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
static const WCHAR localeW[] = {'e','n','-','U','S',0};
static const WCHAR fooW[] = {'f','o','o',0};
static const WCHAR emptyW[] = {0};
+static const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
static inline unsigned int strlenW( const WCHAR *str )
{
static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC);
static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
+static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR);
static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int);
X(EnumSystemGeoID);
X(GetSystemPreferredUILanguages);
X(GetThreadPreferredUILanguages);
+ X(GetUserPreferredUILanguages);
X(GetNumberFormatEx);
mod = GetModuleHandleA("ntdll");
{ {'e','s',0}, {'e','s','-','E','S',0},
MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT),
MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) /* vista */,
- {'e','s','-','E','S','_','t','r','a','d','n','l',0}, 0x1 },
+ {'e','s','-','E','S','_','t','r','a','d','n','l',0} },
{ {'g','a',0}, {'g','a','-','I','E',0},
MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT), 0, {0}, 0x3 },
{ {'i','t',0}, {'i','t','-','I','T',0},
{ {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0},
MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
{ {'z','h',0}, {'z','h','-','C','N',0},
- MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 0, {0}, 0x3 },
+ MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT) },
{ {0} }
};
}
+static const DWORD lcmap_invalid_flags[] = {
+ 0,
+ LCMAP_HIRAGANA | LCMAP_KATAKANA,
+ LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
+ LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
+ LCMAP_LOWERCASE | SORT_STRINGSORT,
+ LCMAP_UPPERCASE | NORM_IGNORESYMBOLS,
+ LCMAP_LOWERCASE | NORM_IGNORESYMBOLS,
+ LCMAP_UPPERCASE | NORM_IGNORENONSPACE,
+ LCMAP_LOWERCASE | NORM_IGNORENONSPACE,
+ LCMAP_HIRAGANA | NORM_IGNORENONSPACE,
+ LCMAP_HIRAGANA | NORM_IGNORESYMBOLS,
+ LCMAP_HIRAGANA | LCMAP_SIMPLIFIED_CHINESE,
+ LCMAP_HIRAGANA | LCMAP_TRADITIONAL_CHINESE,
+ LCMAP_KATAKANA | NORM_IGNORENONSPACE,
+ LCMAP_KATAKANA | NORM_IGNORESYMBOLS,
+ LCMAP_KATAKANA | LCMAP_SIMPLIFIED_CHINESE,
+ LCMAP_KATAKANA | LCMAP_TRADITIONAL_CHINESE,
+ LCMAP_FULLWIDTH | NORM_IGNORENONSPACE,
+ LCMAP_FULLWIDTH | NORM_IGNORESYMBOLS,
+ LCMAP_FULLWIDTH | LCMAP_SIMPLIFIED_CHINESE,
+ LCMAP_FULLWIDTH | LCMAP_TRADITIONAL_CHINESE,
+ LCMAP_HALFWIDTH | NORM_IGNORENONSPACE,
+ LCMAP_HALFWIDTH | NORM_IGNORESYMBOLS,
+ LCMAP_HALFWIDTH | LCMAP_SIMPLIFIED_CHINESE,
+ LCMAP_HALFWIDTH | LCMAP_TRADITIONAL_CHINESE,
+};
+
static void test_LCMapStringA(void)
{
- int ret, ret2;
+ int ret, ret2, i;
char buf[256], buf2[256];
static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
ok(GetLastError() == ERROR_INVALID_FLAGS,
"unexpected error code %d\n", GetLastError());
- ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
- upper_case, -1, buf, sizeof(buf));
- ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
- ok(GetLastError() == ERROR_INVALID_FLAGS,
- "unexpected error code %d\n", GetLastError());
-
- ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
- upper_case, -1, buf, sizeof(buf));
- ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
- ok(GetLastError() == ERROR_INVALID_FLAGS,
- "unexpected error code %d\n", GetLastError());
-
- ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
- upper_case, -1, buf, sizeof(buf));
- ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
- ok(GetLastError() == ERROR_INVALID_FLAGS,
- "unexpected error code %d\n", GetLastError());
-
- /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
- SetLastError(0xdeadbeef);
- ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
- upper_case, -1, buf, sizeof(buf));
- ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
- ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
+ /* test invalid flag combinations */
+ for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
+ lstrcpyA(buf, "foo");
+ SetLastError(0xdeadbeef);
+ ret = LCMapStringA(LOCALE_USER_DEFAULT, lcmap_invalid_flags[i],
+ lower_case, -1, buf, sizeof(buf));
+ ok(GetLastError() == ERROR_INVALID_FLAGS,
+ "LCMapStringA (flag %08x) unexpected error code %d\n",
+ lcmap_invalid_flags[i], GetLastError());
+ ok(!ret, "LCMapStringA (flag %08x) should return 0, got %d\n",
+ lcmap_invalid_flags[i], ret);
+ }
/* test LCMAP_LOWERCASE */
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
lstrlenA(symbols_stripped) + 1, ret);
ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
+ /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
+ lstrcpyA(buf, "foo");
+ ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE,
+ lower_case, -1, buf, sizeof(buf));
+ ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
+ lstrlenA(symbols_stripped) + 1, ret);
+ ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
+
/* test srclen = 0 */
SetLastError(0xdeadbeef);
ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *func_name)
{
- int ret, ret2;
+ static const WCHAR japanese_text[] = {
+ 0x3044, 0x309d, 0x3084, 0x3001, 0x30a4, 0x30fc, 0x30cf,
+ 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x306e, 0x2026, 0
+ };
+ static const WCHAR hiragana_text[] = {
+ 0x3044, 0x309d, 0x3084, 0x3001, 0x3044, 0x30fc, 0x306f,
+ 0x3068, 0x30fc, 0x3094, 0x3049, 0x306e, 0x2026, 0
+ };
+ static const WCHAR katakana_text[] = {
+ 0x30a4, 0x30fd, 0x30e4, 0x3001, 0x30a4, 0x30fc, 0x30cf,
+ 0x30c8, 0x30fc, 0x30f4, 0x30a9, 0x30ce, 0x2026, 0
+ };
+ static const WCHAR halfwidth_text[] = {
+ 0x3044, 0x309d, 0x3084, 0xff64, 0xff72, 0xff70, 0xff8a,
+ 0xff84, 0xff70, 0xff73, 0xff9e, 0xff6b, 0x306e, 0x2026, 0
+ };
+ int ret, ret2, i;
WCHAR buf[256], buf2[256];
char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
+ /* LCMAP_LOWERCASE | LCMAP_UPPERCASE makes LCMAP_TITLECASE, so it's valid now. */
ret = func_ptr(LCMAP_LOWERCASE | LCMAP_UPPERCASE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
- if (broken(ret))
- ok(lstrcmpW(buf, upper_case) == 0, "Expected upper case string\n");
- else
- {
- ok(!ret, "%s LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n", func_name);
- ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
- func_name, GetLastError());
+ lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ todo_wine ok(ret == lstrlenW(title_case) + 1 || broken(!ret),
+ "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(title_case) + 1);
+ todo_wine ok(lstrcmpW(buf, title_case) == 0 || broken(!ret),
+ "Expected title case string\n");
+
+ /* test invalid flag combinations */
+ for (i = 0; i < sizeof(lcmap_invalid_flags)/sizeof(lcmap_invalid_flags[0]); i++) {
+ lstrcpyW(buf, fooW);
+ SetLastError(0xdeadbeef);
+ ret = func_ptr(lcmap_invalid_flags[i],
+ lower_case, -1, buf, sizeof(buf));
+ ok(GetLastError() == ERROR_INVALID_FLAGS,
+ "%s (flag %08x) unexpected error code %d\n",
+ func_name, lcmap_invalid_flags[i], GetLastError());
+ ok(!ret, "%s (flag %08x) should return 0, got %d\n",
+ func_name, lcmap_invalid_flags[i], ret);
}
- ret = func_ptr(LCMAP_HIRAGANA | LCMAP_KATAKANA,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
- ok(!ret, "%s LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n", func_name);
- ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
- func_name, GetLastError());
-
- ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
- ok(!ret, "%s LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n", func_name);
- ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
- func_name, GetLastError());
-
- ret = func_ptr(LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
- ok(!ret, "%s LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n",
- func_name);
- ok(GetLastError() == ERROR_INVALID_FLAGS, "%s unexpected error code %d\n",
- func_name, GetLastError());
-
- /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
- SetLastError(0xdeadbeef);
- ret = func_ptr(LCMAP_LOWERCASE | SORT_STRINGSORT,
- upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
- ok(GetLastError() == ERROR_INVALID_FLAGS, "%s expected ERROR_INVALID_FLAGS, got %d\n",
- func_name, GetLastError());
- ok(!ret, "%s SORT_STRINGSORT without LCMAP_SORTKEY must fail\n", func_name);
-
/* test LCMAP_LOWERCASE */
ret = func_ptr(LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
ret, GetLastError(), lstrlenW(lower_case) + 1);
ok(!lstrcmpW(buf, upper_case), "%s string compare mismatch\n", func_name);
+ /* test LCMAP_HIRAGANA */
+ ret = func_ptr(LCMAP_HIRAGANA,
+ japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(hiragana_text) + 1);
+ ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
+
+ buf[0] = 0x30f5; /* KATAKANA LETTER SMALL KA */
+ ret = func_ptr(LCMAP_HIRAGANA, buf, 1, buf2, 1);
+ ok(ret == 1, "%s ret %d, error %d, expected value 1\n", func_name,
+ ret, GetLastError());
+ /* U+3095: HIRAGANA LETTER SMALL KA was added in Unicode 3.2 */
+ ok(buf2[0] == 0x3095 || broken(buf2[0] == 0x30f5 /* Vista and earlier versions */),
+ "%s expected %04x, got %04x\n", func_name, 0x3095, buf2[0]);
+
+ /* test LCMAP_KATAKANA | LCMAP_LOWERCASE */
+ ret = func_ptr(LCMAP_KATAKANA | LCMAP_LOWERCASE,
+ japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(katakana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(katakana_text) + 1);
+ ok(!lstrcmpW(buf, katakana_text), "%s string compare mismatch\n", func_name);
+
+ /* test LCMAP_FULLWIDTH */
+ ret = func_ptr(LCMAP_FULLWIDTH,
+ halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(japanese_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(japanese_text) + 1);
+ ok(!lstrcmpW(buf, japanese_text), "%s string compare mismatch\n", func_name);
+
+ ret2 = func_ptr(LCMAP_FULLWIDTH, halfwidth_text, -1, NULL, 0);
+ ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret2, ret);
+
+ /* test LCMAP_FULLWIDTH | LCMAP_HIRAGANA
+ (half-width katakana is converted into full-wdith hiragana) */
+ ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA,
+ halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(hiragana_text) + 1);
+ ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
+
+ ret2 = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA, halfwidth_text, -1, NULL, 0);
+ ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
+
+ /* test LCMAP_HALFWIDTH */
+ ret = func_ptr(LCMAP_HALFWIDTH,
+ japanese_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(halfwidth_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
+ ret, GetLastError(), lstrlenW(halfwidth_text) + 1);
+ ok(!lstrcmpW(buf, halfwidth_text), "%s string compare mismatch\n", func_name);
+
+ ret2 = func_ptr(LCMAP_HALFWIDTH, japanese_text, -1, NULL, 0);
+ ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
+
/* test buffer overflow */
SetLastError(0xdeadbeef);
ret = func_ptr(LCMAP_UPPERCASE,
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
+ /* KATAKANA LETTER GA (U+30AC) is converted into two half-width characters.
+ Thus, it requires two WCHARs. */
+ buf[0] = 0x30ac;
+ SetLastError(0xdeadbeef);
+ ret = func_ptr(LCMAP_HALFWIDTH, buf, 1, buf2, 1);
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+ "%s should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", func_name, ret);
+
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
lstrcpyW(buf, lower_case);
ret = func_ptr(LCMAP_UPPERCASE,
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
+ /* test NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE */
+ lstrcpyW(buf, fooW);
+ ret = func_ptr(NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE,
+ lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ ok(ret == lstrlenW(symbols_stripped) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
+ lstrlenW(symbols_stripped) + 1, ret);
+ ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
+
/* test srclen = 0 */
SetLastError(0xdeadbeef);
ret = func_ptr(0, upper_case, 0, buf, sizeof(buf)/sizeof(WCHAR));
trace("testing LCMapStringEx\n");
SetLastError(0xdeadbeef);
- ret = pLCMapStringEx(fooW, LCMAP_LOWERCASE,
+ ret = pLCMapStringEx(invalidW, LCMAP_LOWERCASE,
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR), NULL, NULL, 0);
todo_wine {
ok(!ret, "LCMapStringEx should fail with bad locale name\n");
struct neutralsublang_name_t {
WCHAR name[3];
+ WCHAR sname[16];
LCID lcid;
int todo;
};
static const struct neutralsublang_name_t neutralsublang_names[] = {
- { {'a','r',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
- { {'a','z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
- { {'d','e',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
- { {'e','n',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
- { {'e','s',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT), 1 },
- { {'g','a',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT) },
- { {'i','t',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
- { {'m','s',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
- { {'n','l',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
- { {'p','t',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
- { {'s','r',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
- { {'s','v',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
- { {'u','z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
- { {'z','h',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT), 1 },
+ { {'a','r',0}, {'a','r','-','S','A',0}, MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA), SORT_DEFAULT) },
+ { {'a','z',0}, {'a','z','-','L','a','t','n','-','A','Z',0}, MAKELCID(MAKELANGID(LANG_AZERI, SUBLANG_AZERI_LATIN), SORT_DEFAULT) },
+ { {'d','e',0}, {'d','e','-','D','E',0}, MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT) },
+ { {'e','n',0}, {'e','n','-','U','S',0}, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) },
+ { {'e','s',0}, {'e','s','-','E','S',0}, MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT) },
+ { {'g','a',0}, {'g','a','-','I','E',0}, MAKELCID(MAKELANGID(LANG_IRISH, SUBLANG_IRISH_IRELAND), SORT_DEFAULT) },
+ { {'i','t',0}, {'i','t','-','I','T',0}, MAKELCID(MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), SORT_DEFAULT) },
+ { {'m','s',0}, {'m','s','-','M','Y',0}, MAKELCID(MAKELANGID(LANG_MALAY, SUBLANG_MALAY_MALAYSIA), SORT_DEFAULT) },
+ { {'n','l',0}, {'n','l','-','N','L',0}, MAKELCID(MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), SORT_DEFAULT) },
+ { {'p','t',0}, {'p','t','-','B','R',0}, MAKELCID(MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), SORT_DEFAULT) },
+ { {'s','r',0}, {'s','r','-','L','a','t','n','-','R','S',0}, MAKELCID(MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_SERBIA_LATIN), SORT_DEFAULT), 1 },
+ { {'s','v',0}, {'s','v','-','S','E',0}, MAKELCID(MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH), SORT_DEFAULT) },
+ { {'u','z',0}, {'u','z','-','L','a','t','n','-','U','Z',0}, MAKELCID(MAKELANGID(LANG_UZBEK, SUBLANG_UZBEK_LATIN), SORT_DEFAULT) },
+ { {'z','h',0}, {'z','h','-','C','N',0}, MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT) },
{ {0} }
};
INT ret;
WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
static const WCHAR enW[] = {'e','n',0};
+ static const WCHAR esesW[] = {'e','s','-','e','s',0};
+ static const WCHAR zhHansW[] = {'z','h','-','H','a','n','s',0};
+ static const WCHAR zhhansW[] = {'z','h','-','h','a','n','s',0};
+ static const WCHAR zhHantW[] = {'z','h','-','H','a','n','t',0};
+ static const WCHAR zhhantW[] = {'z','h','-','h','a','n','t',0};
+ static const WCHAR zhcnW[] = {'z','h','-','C','N',0};
+ static const WCHAR zhhkW[] = {'z','h','-','H','K',0};
if (!pLocaleNameToLCID)
{
/* bad name */
SetLastError(0xdeadbeef);
- lcid = pLocaleNameToLCID(fooW, 0);
+ lcid = pLocaleNameToLCID(invalidW, 0);
ok(!lcid && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected lcid == 0, got %08x, error %d\n", lcid, GetLastError());
+ /* lower-case */
+ lcid = pLocaleNameToLCID(esesW, 0);
+ ok(lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT), "Got wrong lcid for es-es: 0x%x\n", lcid);
+
/* english neutral name */
lcid = pLocaleNameToLCID(enW, 0);
ok(lcid == MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) ||
*buffer = 0;
ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(ptr->name), ret);
- ok(lstrcmpW(ptr->name, buffer), "%s: got wrong locale name %s\n",
+ ok(!lstrcmpW(ptr->sname, buffer), "%s: got wrong locale name %s\n",
wine_dbgstr_w(ptr->name), wine_dbgstr_w(buffer));
ptr++;
}
+
+ /* zh-Hant */
+ lcid = pLocaleNameToLCID(zhHantW, 0);
+ todo_wine ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), SORT_DEFAULT),
+ "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHantW), lcid);
+ ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHantW), ret);
+ todo_wine ok(!lstrcmpW(zhhkW, buffer), "%s: got wrong locale name %s\n",
+ wine_dbgstr_w(zhHantW), wine_dbgstr_w(buffer));
+
+ /* zh-hant */
+ lcid = pLocaleNameToLCID(zhhantW, 0);
+ todo_wine ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), SORT_DEFAULT),
+ "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhantW),
+ MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), SORT_DEFAULT));
+ ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhhantW), ret);
+ todo_wine ok(!lstrcmpW(zhhkW, buffer), "%s: got wrong locale name %s\n",
+ wine_dbgstr_w(zhhantW), wine_dbgstr_w(buffer));
+
+ /* zh-Hans */
+ lcid = pLocaleNameToLCID(zhHansW, 0);
+ todo_wine ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
+ "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhHansW), lcid);
+ ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhHansW), ret);
+ todo_wine ok(!lstrcmpW(zhcnW, buffer), "%s: got wrong locale name %s\n",
+ wine_dbgstr_w(zhHansW), wine_dbgstr_w(buffer));
+
+ /* zh-hans */
+ lcid = pLocaleNameToLCID(zhhansW, 0);
+ todo_wine ok(lcid == MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT),
+ "%s: got wrong lcid 0x%04x\n", wine_dbgstr_w(zhhansW),
+ MAKELCID(MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT));
+ ret = pLCIDToLocaleName(lcid, buffer, sizeof(buffer)/sizeof(WCHAR), 0);
+ ok(ret > 0, "%s: got %d\n", wine_dbgstr_w(zhhansW), ret);
+ todo_wine ok(!lstrcmpW(zhcnW, buffer), "%s: got wrong locale name %s\n",
+ wine_dbgstr_w(zhhansW), wine_dbgstr_w(buffer));
}
}
{
static const WCHAR enusW[] = {'e','n','-','U','S',0};
static const WCHAR zzW[] = {'z','z',0};
- static const WCHAR zzzzW[] = {'z','z','-','Z','Z',0};
+ static const WCHAR zz_zzW[] = {'z','z','-','Z','Z',0};
+ static const WCHAR zzzzW[] = {'z','z','z','z',0};
BOOL ret;
if (!pIsValidLocaleName)
ret = pIsValidLocaleName(enusW);
ok(ret, "IsValidLocaleName failed\n");
ret = pIsValidLocaleName(zzW);
- ok(!ret, "IsValidLocaleName should have failed\n");
+ ok(!ret || broken(ret), "IsValidLocaleName should have failed\n");
+ ret = pIsValidLocaleName(zz_zzW);
+ ok(!ret || broken(ret), "IsValidLocaleName should have failed\n");
ret = pIsValidLocaleName(zzzzW);
ok(!ret, "IsValidLocaleName should have failed\n");
ret = pIsValidLocaleName(LOCALE_NAME_INVARIANT);
struct invariant_entry {
const char *name;
int id;
- const char *expect;
+ const char *expect, *expect2;
};
#define X(x) #x, x
{ X(LOCALE_SNATIVELANGNAME), "Invariant Language" },
{ X(LOCALE_ICOUNTRY), "1" },
{ X(LOCALE_SENGCOUNTRY), "Invariant Country" },
- { X(LOCALE_SABBREVCTRYNAME), "IVC" },
+ { X(LOCALE_SABBREVCTRYNAME), "IVC", "" },
{ X(LOCALE_SNATIVECTRYNAME), "Invariant Country" },
{ X(LOCALE_IDEFAULTLANGUAGE), "0409" },
{ X(LOCALE_IDEFAULTCOUNTRY), "1" },
else
{
len = strlen(ptr->expect)+1; /* include \0 */
- ok(ret == len, "For id %d, expected ret == %d, got %d, error %d\n",
+ ok(ret == len || (ptr->expect2 && ret == strlen(ptr->expect2)+1),
+ "For id %d, expected ret == %d, got %d, error %d\n",
ptr->id, len, ret, GetLastError());
- ok(!strcmp(buffer, ptr->expect), "For id %d, Expected %s, got '%s'\n",
+ ok(!strcmp(buffer, ptr->expect) || (ptr->expect2 && !strcmp(buffer, ptr->expect2)),
+ "For id %d, Expected %s, got '%s'\n",
ptr->id, ptr->expect, buffer);
}
ptr++;
}
- if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
- (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
+ if ((LANGIDFROMLCID(GetSystemDefaultLCID()) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)) ||
+ (LANGIDFROMLCID(GetThreadLocale()) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)))
{
- skip("Non-English locale\n");
+ skip("Non US-English locale\n");
}
else
{
HeapFree(GetProcessHeap(), 0, buf);
}
+static void test_GetUserPreferredUILanguages(void)
+{
+ BOOL ret;
+ ULONG count, size, size_id, size_name, size_buffer;
+ WCHAR *buffer;
+
+
+ if (!pGetUserPreferredUILanguages)
+ {
+ win_skip("GetUserPreferredUILanguages is not available.\n");
+ return;
+ }
+
+ count = 0xdeadbeef;
+ size = 0;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_FULL_LANGUAGE, &count, NULL, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size = 0;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID | MUI_FULL_LANGUAGE, &count, NULL, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size = 0;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID | MUI_MACHINE_LANGUAGE_SETTINGS, &count, NULL, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size = 1;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID, &count, NULL, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INVALID_PARAMETER == GetLastError(),
+ "Expected error ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size_id = 0;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID, &count, NULL, &size_id);
+ ok(ret, "Expected GetUserPreferredUILanguages to succeed\n");
+ ok(count, "Expected count > 0\n");
+ ok(size_id % 5 == 1, "Expected size (%d) %% 5 == 1\n", size_id);
+
+ count = 0xdeadbeef;
+ size_name = 0;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, NULL, &size_name);
+ ok(ret, "Expected GetUserPreferredUILanguages to succeed\n");
+ ok(count, "Expected count > 0\n");
+ ok(size_name % 6 == 1, "Expected size (%d) %% 6 == 1\n", size_name);
+
+ size_buffer = max(size_id, size_name);
+ if(!size_buffer)
+ {
+ skip("No valid buffer size\n");
+ return;
+ }
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, size_buffer * sizeof(WCHAR));
+
+ count = 0xdeadbeef;
+ size = size_buffer;
+ memset(buffer, 0x5a, size_buffer * sizeof(WCHAR));
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(0, &count, buffer, &size);
+ ok(ret, "Expected GetUserPreferredUILanguages to succeed\n");
+ ok(count, "Expected count > 0\n");
+ ok(size % 6 == 1, "Expected size (%d) %% 6 == 1\n", size);
+ if (ret && size % 6 == 1)
+ ok(!buffer[size -2] && !buffer[size -1],
+ "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
+ buffer[size -2], buffer[size -1]);
+
+ count = 0xdeadbeef;
+ size = size_buffer;
+ memset(buffer, 0x5a, size_buffer * sizeof(WCHAR));
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID, &count, buffer, &size);
+ ok(ret, "Expected GetUserPreferredUILanguages to succeed\n");
+ ok(count, "Expected count > 0\n");
+ ok(size % 5 == 1, "Expected size (%d) %% 5 == 1\n", size);
+ if (ret && size % 5 == 1)
+ ok(!buffer[size -2] && !buffer[size -1],
+ "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
+ buffer[size -2], buffer[size -1]);
+
+ count = 0xdeadbeef;
+ size = size_buffer;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, buffer, &size);
+ ok(ret, "Expected GetUserPreferredUILanguages to succeed\n");
+ ok(count, "Expected count > 0\n");
+ ok(size % 6 == 1, "Expected size (%d) %% 6 == 1\n", size);
+ if (ret && size % 5 == 1)
+ ok(!buffer[size -2] && !buffer[size -1],
+ "Expected last two WCHARs being empty, got 0x%x 0x%x\n",
+ buffer[size -2], buffer[size -1]);
+
+ count = 0xdeadbeef;
+ size = 1;
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID, &count, buffer, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
+ "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size = size_id -1;
+ memset(buffer, 0x5a, size_buffer * sizeof(WCHAR));
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(MUI_LANGUAGE_ID, &count, buffer, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
+ "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ count = 0xdeadbeef;
+ size = size_id -2;
+ memset(buffer, 0x5a, size_buffer * sizeof(WCHAR));
+ SetLastError(0xdeadbeef);
+ ret = pGetUserPreferredUILanguages(0, &count, buffer, &size);
+ ok(!ret, "Expected GetUserPreferredUILanguages to fail\n");
+ ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
+ "Expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+}
+
START_TEST(locale)
{
InitFunctionPointers();
test_invariant();
test_GetSystemPreferredUILanguages();
test_GetThreadPreferredUILanguages();
+ test_GetUserPreferredUILanguages();
test_sorting();
}
#include "windef.h"
#include "winbase.h"
#include "wine/winternl.h"
+#include "winioctl.h"
#include "wine/test.h"
#define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
static BOOL (WINAPI *pDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,PHANDLE);
static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData);
+static BOOL (WINAPI *pCancelIoEx)(HANDLE handle, LPOVERLAPPED lpOverlapped);
static BOOL user_apc_ran;
static void CALLBACK user_apc(ULONG_PTR param)
enum rpcThreadOp
{
- RPC_READFILE,
- RPC_WRITEFILE,
- RPC_PEEKNAMEDPIPE
+ RPC_READFILE
};
struct rpcThreadArgs
ULONG_PTR returnValue;
DWORD lastError;
enum rpcThreadOp op;
- ULONG_PTR args[6];
+ ULONG_PTR args[5];
};
static DWORD CALLBACK rpcThreadMain(LPVOID arg)
(LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
break;
- case RPC_WRITEFILE:
- rpcargs->returnValue = (ULONG_PTR)WriteFile( (HANDLE)rpcargs->args[0], /* hFile */
- (LPCVOID)rpcargs->args[1], /* buffer */
- (DWORD)rpcargs->args[2], /* bytesToWrite */
- (LPDWORD)rpcargs->args[3], /* bytesWritten */
- (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
- break;
-
- case RPC_PEEKNAMEDPIPE:
- rpcargs->returnValue = (ULONG_PTR)PeekNamedPipe( (HANDLE)rpcargs->args[0], /* hPipe */
- (LPVOID)rpcargs->args[1], /* lpvBuffer */
- (DWORD)rpcargs->args[2], /* cbBuffer */
- (LPDWORD)rpcargs->args[3], /* lpcbRead */
- (LPDWORD)rpcargs->args[4], /* lpcbAvail */
- (LPDWORD)rpcargs->args[5] ); /* lpcbMessage */
- break;
-
default:
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
rpcargs->returnValue = 0;
return (BOOL)rpcargs.returnValue;
}
-/* Runs PeekNamedPipe(...) from a different thread */
-static BOOL RpcPeekNamedPipe(HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
- LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage)
+#define test_not_signaled(h) _test_not_signaled(__LINE__,h)
+static void _test_not_signaled(unsigned line, HANDLE handle)
{
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
-
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_PEEKNAMEDPIPE;
- rpcargs.args[0] = (ULONG_PTR)hPipe;
- rpcargs.args[1] = (ULONG_PTR)lpvBuffer;
- rpcargs.args[2] = (ULONG_PTR)cbBuffer;
- rpcargs.args[3] = (ULONG_PTR)lpcbRead;
- rpcargs.args[4] = (ULONG_PTR)lpcbAvail;
- rpcargs.args[5] = (ULONG_PTR)lpcbMessage;
+ DWORD res = WaitForSingleObject(handle, 0);
+ ok_(__FILE__,line)(res == WAIT_TIMEOUT, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
+}
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0,"WaitForSingleObject failed with %d.\n", GetLastError());
- CloseHandle(thread);
+#define test_signaled(h) _test_signaled(__LINE__,h)
+static void _test_signaled(unsigned line, HANDLE handle)
+{
+ DWORD res = WaitForSingleObject(handle, 0);
+ ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
+}
- SetLastError(rpcargs.lastError);
- return (BOOL)rpcargs.returnValue;
+#define test_pipe_info(a,b,c,d,e) _test_pipe_info(__LINE__,a,b,c,d,e)
+static void _test_pipe_info(unsigned line, HANDLE pipe, DWORD ex_flags, DWORD ex_out_buf_size, DWORD ex_in_buf_size, DWORD ex_max_instances)
+{
+ DWORD flags = 0xdeadbeef, out_buf_size = 0xdeadbeef, in_buf_size = 0xdeadbeef, max_instances = 0xdeadbeef;
+ BOOL res;
+
+ res = GetNamedPipeInfo(pipe, &flags, &out_buf_size, &in_buf_size, &max_instances);
+ ok_(__FILE__,line)(res, "GetNamedPipeInfo failed: %x\n", res);
+ ok_(__FILE__,line)(flags == ex_flags, "flags = %x, expected %x\n", flags, ex_flags);
+ ok_(__FILE__,line)(out_buf_size == ex_out_buf_size, "out_buf_size = %x, expected %u\n", out_buf_size, ex_out_buf_size);
+ ok_(__FILE__,line)(in_buf_size == ex_in_buf_size, "in_buf_size = %x, expected %u\n", in_buf_size, ex_in_buf_size);
+ ok_(__FILE__,line)(max_instances == ex_max_instances, "max_instances = %x, expected %u\n", max_instances, ex_max_instances);
}
static void test_CreateNamedPipe(int pipemode)
char ibuf[32], *pbuf;
DWORD written;
DWORD readden;
- DWORD leftmsg;
DWORD avail;
+ DWORD left;
DWORD lpmode;
BOOL ret;
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+ test_signaled(hnp);
ret = WaitNamedPipeA(PIPENAME, 2000);
ok(ret, "WaitNamedPipe failed (%d)\n", GetLastError());
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
- ok(!WaitNamedPipeA(PIPENAME, 1000), "WaitNamedPipe succeeded\n");
+ ok(!WaitNamedPipeA(PIPENAME, 100), "WaitNamedPipe succeeded\n");
ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf), "write file len 1\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == sizeof(obuf), "peek 1 got %d bytes\n", readden);
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &avail, &left), "Peek\n");
+ ok(avail == sizeof(obuf), "peek 1 got %d bytes\n", avail);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(left == 0, "peek 1 got %d bytes left\n", left);
+ else
+ ok(left == sizeof(obuf), "peek 1 got %d bytes left\n", left);
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf), "read 1 got %d bytes\n", readden);
ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf2), "write file len 2\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
- ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == sizeof(obuf2), "peek 2 got %d bytes\n", readden);
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &avail, &left), "Peek\n");
+ ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(left == 0, "peek 2 got %d bytes left\n", left);
+ else
+ ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
+ ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &avail, &left), "Peek\n");
+ ok(avail == sizeof(obuf2), "peek 2 got %d bytes\n", avail);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(left == 0, "peek 2 got %d bytes left\n", left);
+ else
+ ok(left == sizeof(obuf2), "peek 2 got %d bytes left\n", left);
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2), "read 2 got %d bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf2), "write file len\n");
- ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
- ok(readden == 4, "read got %d bytes\n", readden);
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
- ok(readden == sizeof(obuf2) - 4, "peek got %d bytes total\n", readden);
+ ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek\n");
+ ok(readden == 4, "peek got %d bytes\n", readden);
+ ok(avail == sizeof(obuf2), "peek got %d bytes available\n", avail);
if (pipemode == PIPE_TYPE_BYTE)
- ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
+ ok(left == -4, "peek got %d bytes left\n", left);
else
- ok(leftmsg == sizeof(obuf2) - 4, "peek got %d bytes left in message\n", leftmsg);
+ ok(left == sizeof(obuf2)-4, "peek got %d bytes left\n", left);
+ ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
+ ok(readden == 4, "read got %d bytes\n", readden);
ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
- ok(readden == 0, "peek got %d bytes total\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf), "write file len\n");
+ ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek\n");
+ ok(readden == 4, "peek got %d bytes\n", readden);
+ ok(avail == sizeof(obuf), "peek got %d bytes available\n", avail);
if (pipemode == PIPE_TYPE_BYTE)
{
+ ok(left == -4, "peek got %d bytes left\n", left);
ok(ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
}
else
{
+ ok(left == sizeof(obuf)-4, "peek got %d bytes left\n", left);
SetLastError(0xdeadbeef);
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
- /* Tests for sending empty messages */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- if (pipemode != PIPE_TYPE_BYTE)
- {
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- if (pipemode != PIPE_TYPE_BYTE)
- {
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- /* similar to above, but with an additional call to PeekNamedPipe inbetween */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == 0, "peek got %d bytes\n", readden);
- if (pipemode != PIPE_TYPE_BYTE)
- {
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
-
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_READFILE;
- rpcargs.args[0] = (ULONG_PTR)hFile;
- rpcargs.args[1] = (ULONG_PTR)ibuf;
- rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
- rpcargs.args[3] = (ULONG_PTR)&readden;
- rpcargs.args[4] = (ULONG_PTR)NULL;
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- todo_wine
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- if (ret == WAIT_TIMEOUT)
- {
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- }
- CloseHandle(thread);
- ok((BOOL)rpcargs.returnValue, "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == 0, "peek got %d bytes\n", readden);
- if (pipemode != PIPE_TYPE_BYTE)
- {
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
-
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_READFILE;
- rpcargs.args[0] = (ULONG_PTR)hnp;
- rpcargs.args[1] = (ULONG_PTR)ibuf;
- rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
- rpcargs.args[3] = (ULONG_PTR)&readden;
- rpcargs.args[4] = (ULONG_PTR)NULL;
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- todo_wine
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- if (ret == WAIT_TIMEOUT)
- {
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- }
- CloseHandle(thread);
- ok((BOOL)rpcargs.returnValue, "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- /* similar to above, but now with PeekNamedPipe and multiple messages */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf), "write file len\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
- if (pipemode != PIPE_TYPE_BYTE)
- todo_wine
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- else
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
- ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf2, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf2), "write file len\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
- if (pipemode != PIPE_TYPE_BYTE)
- todo_wine
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- else
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- if (pipemode != PIPE_TYPE_BYTE)
- {
- todo_wine
- ok(readden == 0, "read got %d bytes\n", readden);
- if (readden == 0)
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- }
- ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
- ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check\n");
-
/* Test reading of multiple writes */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
ok(written == sizeof(obuf), "write file len 3a\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
- ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
+ ok(PeekNamedPipe(hFile, ibuf, 4, &readden, &avail, &left), "Peek3\n");
+ ok(readden == 4, "peek3 got %d bytes\n", readden);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(left == -4, "peek3 got %d bytes left\n", left);
+ else
+ ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
+ ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek3\n");
if (pipemode == PIPE_TYPE_BYTE) {
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
+ /* currently the Wine behavior depends on the kernel version */
+ /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); */
+ if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek3 got %d bytes\n", readden);
+ ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek3 got %d bytes left\n", left);
}
else
{
ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
+ ok(left == 0, "peek3 got %d bytes left\n", left);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
pbuf = ibuf;
ok(written == sizeof(obuf), "write file len 4a\n");
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
ok(written == sizeof(obuf2), "write file len 4b\n");
- ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
+ ok(PeekNamedPipe(hnp, ibuf, 4, &readden, &avail, &left), "Peek3\n");
+ ok(readden == 4, "peek3 got %d bytes\n", readden);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(left == -4, "peek3 got %d bytes left\n", left);
+ else
+ ok(left == sizeof(obuf)-4, "peek3 got %d bytes left\n", left);
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
+ ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek4\n");
if (pipemode == PIPE_TYPE_BYTE) {
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
+ /* currently the Wine behavior depends on the kernel version */
+ /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); */
+ if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek4 got %d bytes\n", readden);
+ ok(left == (DWORD) -(sizeof(obuf) + sizeof(obuf2)), "peek4 got %d bytes left\n", left);
}
else
{
ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
+ ok(left == 0, "peek4 got %d bytes left\n", left);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
pbuf = ibuf;
ok(written == sizeof(obuf), "write file len 3a\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
- ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
+ ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, &left), "Peek5\n");
ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
+ ok(left == 0, "peek5 got %d bytes left\n", left);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(written == sizeof(obuf2), "write file len 6b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
+
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
if (readden <= sizeof(obuf))
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- /* Tests for sending empty messages */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
-
- /* similar to above, but with an additional call to PeekNamedPipe inbetween */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == 0, "peek got %d bytes\n", readden);
- {
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
-
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_READFILE;
- rpcargs.args[0] = (ULONG_PTR)hFile;
- rpcargs.args[1] = (ULONG_PTR)ibuf;
- rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
- rpcargs.args[3] = (ULONG_PTR)&readden;
- rpcargs.args[4] = (ULONG_PTR)NULL;
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- todo_wine
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- if (ret == WAIT_TIMEOUT)
- {
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- }
- CloseHandle(thread);
- ok((BOOL)rpcargs.returnValue, "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == 0, "peek got %d bytes\n", readden);
- {
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
-
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_READFILE;
- rpcargs.args[0] = (ULONG_PTR)hnp;
- rpcargs.args[1] = (ULONG_PTR)ibuf;
- rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
- rpcargs.args[3] = (ULONG_PTR)&readden;
- rpcargs.args[4] = (ULONG_PTR)NULL;
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- todo_wine
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- if (ret == WAIT_TIMEOUT)
- {
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
- }
- CloseHandle(thread);
- ok((BOOL)rpcargs.returnValue, "ReadFile\n");
- ok(readden == 0, "read got %d bytes\n", readden);
- }
-
- /* similar to above, but now with PeekNamedPipe and multiple messages */
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf), "write file len\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
- todo_wine
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- todo_wine
- ok(readden == 0, "read got %d bytes\n", readden);
- if (readden == 0)
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
- ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(WriteFile(hFile, obuf2, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
- ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf2), "write file len\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
- todo_wine
- ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- todo_wine
- ok(readden == 0, "read got %d bytes\n", readden);
- if (readden == 0)
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
- ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check\n");
-
/* Test how ReadFile behaves when the buffer is not big enough for the whole message */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
ok(written == sizeof(obuf), "write file len 9\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
ok(written == sizeof(obuf2), "write file len 9\n");
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(!ret, "RpcReadFile 9\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
- ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
- ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
{
memset(ibuf, 0, sizeof(ibuf));
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 9\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
- ok(readden == sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 9\n");
ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
- ok(readden == sizeof(obuf2) - 8, "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 9\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
- ok(readden == sizeof(obuf2) - 8, "peek got %d bytes total 9\n", readden);
- ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
}
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
- ok(readden == 0, "peek got %d bytes total 9\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message 9\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
- ok(readden == 0, "peek got %d bytes total 9\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message 9\n", leftmsg);
/* Now the reverse direction */
memset(ibuf, 0, sizeof(ibuf));
ok(written == sizeof(obuf2), "write file len 10\n");
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
ok(written == sizeof(obuf), "write file len 10\n");
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(!ret, "RpcReadFile 10\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
- ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
- ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
{
memset(ibuf, 0, sizeof(ibuf));
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
- ok(readden == sizeof(obuf), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 10\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
- ok(readden == sizeof(obuf), "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 10\n");
ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
- ok(readden == sizeof(obuf) - 8, "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 10\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
- ok(readden == sizeof(obuf) - 8, "peek got %d bytes total 10\n", readden);
- ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
}
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
- ok(readden == 0, "peek got %d bytes total 10\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message 10\n", leftmsg);
- readden = leftmsg = -1;
- ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
- ok(readden == 0, "peek got %d bytes total 10\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message 10\n", leftmsg);
}
- /* Test behaviour for very huge messages (which don't fit completely in the buffer) */
- {
- static char big_obuf[512 * 1024];
- static char big_ibuf[512 * 1024];
- struct rpcThreadArgs rpcargs;
- HANDLE thread;
- DWORD threadId;
- memset(big_obuf, 0xAA, sizeof(big_obuf));
-
- /* Ensure that both pipes are empty before we continue with the next test */
- while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
- ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
- GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
-
- while (PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL) && readden > 0)
- ok(ReadFile(hnp, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
- GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
-
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
- ok(readden == 0, "peek got %d bytes total\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
-
- /* transmit big message, receive with buffer of equal size */
- memset(big_ibuf, 0, sizeof(big_ibuf));
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
- rpcargs.op = RPC_WRITEFILE;
- rpcargs.args[0] = (ULONG_PTR)hnp;
- rpcargs.args[1] = (ULONG_PTR)big_obuf;
- rpcargs.args[2] = (ULONG_PTR)sizeof(big_obuf);
- rpcargs.args[3] = (ULONG_PTR)&written;
- rpcargs.args[4] = (ULONG_PTR)NULL;
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_TIMEOUT);
- ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL), "ReadFile\n");
- todo_wine
- ok(readden == sizeof(big_obuf), "read got %d bytes\n", readden);
- todo_wine
- ok(memcmp(big_ibuf, big_obuf, sizeof(big_obuf)) == 0, "content check\n");
- do
- {
- ret = WaitForSingleObject(thread, 1);
- while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
- ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
- GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
- }
- while (ret == WAIT_TIMEOUT);
- ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
- ok((BOOL)rpcargs.returnValue, "WriteFile\n");
- ok(written == sizeof(big_obuf), "write file len\n");
- CloseHandle(thread);
-
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
- ok(readden == 0, "peek got %d bytes total\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
-
- /* same as above, but receive as multiple parts */
- memset(big_ibuf, 0, sizeof(big_ibuf));
- rpcargs.returnValue = 0;
- rpcargs.lastError = GetLastError();
-
- thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
- ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
- ret = WaitForSingleObject(thread, 200);
- ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_TIMEOUT);
- if (pipemode == PIPE_TYPE_BYTE)
- {
- ok(ReadFile(hFile, big_ibuf, 32, &readden, NULL), "ReadFile\n");
- ok(readden == 32, "read got %d bytes\n", readden);
- ok(ReadFile(hFile, big_ibuf + 32, 32, &readden, NULL), "ReadFile\n");
- }
- else
- {
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hFile, big_ibuf, 32, &readden, NULL), "ReadFile\n");
- ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
- ok(readden == 32, "read got %d bytes\n", readden);
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hFile, big_ibuf + 32, 32, &readden, NULL), "ReadFile\n");
- ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
- }
- ok(readden == 32, "read got %d bytes\n", readden);
- ok(ReadFile(hFile, big_ibuf + 64, sizeof(big_ibuf) - 64, &readden, NULL), "ReadFile\n");
- todo_wine
- ok(readden == sizeof(big_obuf) - 64, "read got %d bytes\n", readden);
- todo_wine
- ok(memcmp(big_ibuf, big_obuf, sizeof(big_obuf)) == 0, "content check\n");
- do
- {
- ret = WaitForSingleObject(thread, 1);
- while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
- ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
- GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
- }
- while (ret == WAIT_TIMEOUT);
- ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
- ok((BOOL)rpcargs.returnValue, "WriteFile\n");
- ok(written == sizeof(big_obuf), "write file len\n");
- CloseHandle(thread);
-
- readden = leftmsg = -1;
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
- ok(readden == 0, "peek got %d bytes total\n", readden);
- ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
- }
-
/* Picky conformance tests */
/* Verify that you can't connect to pipe again
pipe_attr.bInheritHandle = TRUE;
pipe_attr.lpSecurityDescriptor = NULL;
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
+ test_pipe_info(piperead, FILE_PIPE_SERVER_END, 4096, 4096, 1);
+ test_pipe_info(pipewrite, 0, 4096, 4096, 1);
+
ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %d bytes\n", written);
/* and close the write end, read should still succeed*/
ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
- ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
- ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
+ ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe with pending data failed\n");
+ ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %d bytes\n", read);
/* But now we need to get informed that the pipe is closed */
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
/* and close the write end, read should still succeed*/
ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
memset( buffer, 0, size );
- ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe withe with pending data failed\n");
- ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
+ ok(ReadFile(piperead, buffer, size, &read, NULL), "Read from broken pipe with pending data failed\n");
+ ok(read == size, "Read from anonymous pipe got %d bytes\n", read);
for (i = 0; i < size; i++) ok( buffer[i] == (BYTE)i, "invalid data %x at %x\n", buffer[i], i );
/* But now we need to get informed that the pipe is closed */
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
ok(user_apc_ran == FALSE, "user apc ran, pipe using alertable io mode\n");
SleepEx(0, TRUE); /* get rid of apc */
+
+ ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 1) != 0, "CreatePipe failed\n");
+ test_pipe_info(piperead, FILE_PIPE_SERVER_END, 1, 1, 1);
+ test_pipe_info(pipewrite, 0, 1, 1, 1);
+ ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
+ ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
}
static void test_CloseHandle(void)
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
ok(!ret, "WriteFile unexpectedly succeeded\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
+ todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
CloseHandle(hfile);
numbytes = 0xdeadbeef;
memset(buffer, 0, sizeof(buffer));
ret = ReadFile(hfile, buffer, sizeof(buffer), &numbytes, NULL);
- todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
+ ok(ret, "ReadFile failed with %u\n", GetLastError());
ok(numbytes == 0, "expected 0, got %u\n", numbytes);
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
+ ok(!ret, "ReadFile unexpectedly succeeded\n");
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
+
ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
ok(!ret, "WriteFile unexpectedly succeeded\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
+ todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
CloseHandle(hfile);
numbytes = 0xdeadbeef;
memset(buffer, 0, sizeof(buffer));
ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
- ok(ret || broken(GetLastError() == ERROR_MORE_DATA) /* >= Win 8 */,
- "ReadFile failed with %u\n", GetLastError());
+ ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
+ "ReadFile failed with %u\n", GetLastError());
ok(numbytes == 0, "expected 0, got %u\n", numbytes);
numbytes = 0xdeadbeef;
numbytes = 0xdeadbeef;
memset(buffer, 0, sizeof(buffer));
ret = ReadFile(hpipe, buffer, sizeof(buffer), &numbytes, NULL);
- todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
+ ok(ret, "ReadFile failed with %u\n", GetLastError());
ok(numbytes == 0, "expected 0, got %u\n", numbytes);
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
+ ok(!ret, "ReadFile unexpectedly succeeded\n");
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
+
ret = GetNamedPipeHandleStateA(hpipe, &state, NULL, NULL, NULL, NULL, 0);
ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
ok(ret == 1, "ret %d\n", ret);
DisconnectNamedPipe(pipe);
+
+ ret = ConnectNamedPipe(pipe, &ol);
+ err = GetLastError();
+ ok(ret == 0, "ret %d\n", ret);
+ ok(err == ERROR_IO_PENDING, "gle %d\n", err);
+ CancelIo(pipe);
+ ret = WaitForSingleObjectEx(ol.hEvent, INFINITE, 1);
+ ok(ret == WAIT_OBJECT_0, "ret %x\n", ret);
+
+ ret = GetOverlappedResult(pipe, &ol, &num, 1);
+ err = GetLastError();
+ ok(ret == 0, "ret %d\n", ret);
+ ok(err == ERROR_OPERATION_ABORTED, "gle %d\n", err);
+
CloseHandle(ol.hEvent);
CloseHandle(pipe);
return 1;
CloseHandle(event);
}
-static void test_nowait(int pipemode)
-{
- HANDLE hnp;
- HANDLE hFile;
- static const char obuf[] = "Bit Bucket";
- char ibuf[32];
- DWORD written;
- DWORD readden;
- DWORD lpmode;
-
- hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
- pipemode | PIPE_NOWAIT,
- /* nMaxInstances */ 1,
- /* nOutBufSize */ 1024,
- /* nInBufSize */ 1024,
- /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
- /* lpSecurityAttrib */ NULL);
- ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
-
- hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
- ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
-
- /* don't try to do i/o if one side couldn't be opened, as it hangs */
- if (hFile != INVALID_HANDLE_VALUE)
- {
- /* send message from client to server */
- ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf), "write file len\n");
- ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == sizeof(obuf), "got %d bytes\n", readden);
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
- ok(readden == sizeof(obuf), "got %d bytes\n", readden);
- ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
-
- readden = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
-
- lpmode = (pipemode & PIPE_READMODE_MESSAGE) | PIPE_NOWAIT;
- ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
-
- /* send message from server to client */
- ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
- ok(written == sizeof(obuf), "write file len\n");
- ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
- ok(readden == sizeof(obuf), "got %d bytes\n", readden);
-
- memset(ibuf, 0, sizeof(ibuf));
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
- ok(readden == sizeof(obuf), "got %d bytes\n", readden);
- ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
-
- readden = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
-
- /* now again the bad zero byte message test */
- ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
-
- if (pipemode != PIPE_TYPE_BYTE)
- {
- ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
- ok(readden == 0, "got %d bytes\n", readden);
- }
- else
- {
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
- }
-
- readden = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
-
- /* and the same for the reverse direction */
- ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
- ok(written == 0, "write file len\n");
-
- if (pipemode != PIPE_TYPE_BYTE)
- {
- ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
- ok(readden == 0, "got %d bytes\n", readden);
- }
- else
- {
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
- }
-
- readden = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
- ok(readden == 0, "got %d bytes\n", readden);
- ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
-
- ok(CloseHandle(hFile), "CloseHandle\n");
- }
-
- ok(CloseHandle(hnp), "CloseHandle\n");
-
-}
-
static void test_NamedPipeHandleState(void)
{
HANDLE server, client;
CloseHandle(server);
}
+static void test_GetNamedPipeInfo(void)
+{
+ HANDLE server;
+
+ server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_WAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 1024,
+ /* nInBufSize */ 1024,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+ test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_BYTE, 1024, 1024, 1);
+
+ CloseHandle(server);
+
+ server = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_NOWAIT,
+ /* nMaxInstances */ 3,
+ /* nOutBufSize */ 1024,
+ /* nInBufSize */ 1024,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+ test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 1024, 1024, 3);
+
+ CloseHandle(server);
+
+ server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 0,
+ /* nInBufSize */ 0,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+ test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0, 0, 1);
+
+ CloseHandle(server);
+
+ server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_WAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 0xf000,
+ /* nInBufSize */ 0xf000,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+ test_pipe_info(server, PIPE_SERVER_END | PIPE_TYPE_MESSAGE, 0xf000, 0xf000, 1);
+
+ CloseHandle(server);
+}
+
static void test_readfileex_pending(void)
{
HANDLE server, client, event;
BOOL ret;
- DWORD err, wait, num_bytes, lpmode;
+ DWORD err, wait, num_bytes;
OVERLAPPED overlapped;
char read_buf[1024];
char write_buf[1024];
- const char long_test_string[] = "12test3456ab";
const char test_string[] = "test";
int i;
ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 0, "completion routine called before WriteFile started\n");
ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
ok(ret == TRUE, "WriteFile failed\n");
SetLastError(0xdeadbeef);
ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
ok(!ret, "ReadFile should fail\n");
+todo_wine
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
ok(num_bytes == 0, "bytes %u\n", num_bytes);
ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
ok(num_bytes == 1, "bytes %u\n", num_bytes);
wait = WaitForSingleObject(event, 100);
+todo_wine
ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
ok(num_bytes == 1, "bytes %u\n", num_bytes);
+todo_wine
ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
CloseHandle(client);
CloseHandle(server);
+ CloseHandle(event);
+}
- /* On Windows versions > 2000 it is not possible to add PIPE_NOWAIT to a byte-mode
- * PIPE after creating. Create a new pipe for the following tests. */
- server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
- /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_NOWAIT,
- /* nMaxInstances */ 1,
- /* nOutBufSize */ 1024,
- /* nInBufSize */ 1024,
- /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
- /* lpSecurityAttrib */ NULL);
- ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
-
- client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, 0, NULL);
- ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
+#define test_peek_pipe(a,b,c,d) _test_peek_pipe(__LINE__,a,b,c,d)
+static void _test_peek_pipe(unsigned line, HANDLE pipe, DWORD expected_read, DWORD expected_avail, DWORD expected_message_length)
+{
+ DWORD bytes_read = 0xdeadbeed, avail = 0xdeadbeef, left = 0xdeadbeed;
+ char buf[4000];
+ FILE_PIPE_PEEK_BUFFER *peek_buf = (void*)buf;
+ IO_STATUS_BLOCK io;
+ NTSTATUS status;
+ BOOL r;
+
+ r = PeekNamedPipe(pipe, buf, sizeof(buf), &bytes_read, &avail, &left);
+ ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
+ ok_(__FILE__,line)(bytes_read == expected_read, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
+ ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
+ ok_(__FILE__,line)(left == expected_message_length - expected_read, "left = %d, expected %d\n",
+ left, expected_message_length - expected_read);
+
+ status = NtFsControlFile(pipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0, buf, sizeof(buf));
+ ok_(__FILE__,line)(!status || status == STATUS_PENDING, "NtFsControlFile(FSCTL_PIPE_PEEK) failed: %x\n", status);
+ ok_(__FILE__,line)(io.Information == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[expected_read]),
+ "io.Information = %lu\n", io.Information);
+ ok_(__FILE__,line)(peek_buf->ReadDataAvailable == expected_avail, "ReadDataAvailable = %u, expected %u\n",
+ peek_buf->ReadDataAvailable, expected_avail);
+ ok_(__FILE__,line)(peek_buf->MessageLength == expected_message_length, "MessageLength = %u, expected %u\n",
+ peek_buf->MessageLength, expected_message_length);
+
+ if (expected_read)
+ {
+ r = PeekNamedPipe(pipe, buf, 1, &bytes_read, &avail, &left);
+ ok_(__FILE__,line)(r, "PeekNamedPipe failed: %u\n", GetLastError());
+ ok_(__FILE__,line)(bytes_read == 1, "bytes_read = %u, expected %u\n", bytes_read, expected_read);
+ ok_(__FILE__,line)(avail == expected_avail, "avail = %u, expected %u\n", avail, expected_avail);
+ ok_(__FILE__,line)(left == expected_message_length-1, "left = %d, expected %d\n", left, expected_message_length-1);
+ }
+}
+
+#define overlapped_read_sync(a,b,c,d,e) _overlapped_read_sync(__LINE__,a,b,c,d,e)
+static void _overlapped_read_sync(unsigned line, HANDLE reader, void *buf, DWORD buf_size, DWORD expected_result, BOOL partial_read)
+{
+ DWORD read_bytes = 0xdeadbeef;
+ OVERLAPPED overlapped;
+ BOOL res;
memset(&overlapped, 0, sizeof(overlapped));
- overlapped.hEvent = event;
+ overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ res = ReadFile(reader, buf, buf_size, &read_bytes, &overlapped);
+ if (partial_read)
+ ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x (%u)\n", res, GetLastError());
+ else
+ ok_(__FILE__,line)(res, "ReadFile failed: %u\n", GetLastError());
+ if(partial_read)
+ todo_wine ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
+ else
+ ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
- /* Initial check with empty pipe */
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == FALSE, "ReadFileEx succeded\n");
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 0, "completion routine called before writing to file\n");
+ read_bytes = 0xdeadbeef;
+ res = GetOverlappedResult(reader, &overlapped, &read_bytes, FALSE);
+ if (partial_read)
+ ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA,
+ "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
+ else
+ ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
+ ok_(__FILE__,line)(read_bytes == expected_result, "read_bytes %u expected %u\n", read_bytes, expected_result);
+ CloseHandle(overlapped.hEvent);
+}
- /* Call ReadFileEx after writing content to the pipe */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+#define overlapped_read_async(a,b,c,d) _overlapped_read_async(__LINE__,a,b,c,d)
+static void _overlapped_read_async(unsigned line, HANDLE reader, void *buf, DWORD buf_size, OVERLAPPED *overlapped)
+{
+ DWORD read_bytes = 0xdeadbeef;
+ BOOL res;
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ memset(overlapped, 0, sizeof(*overlapped));
+ overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ res = ReadFile(reader, buf, buf_size, &read_bytes, overlapped);
+ ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "ReadFile returned %x(%u)\n", res, GetLastError());
+ ok_(__FILE__,line)(!read_bytes, "read_bytes %u expected 0\n", read_bytes);
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile succeeded\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ _test_not_signaled(line, overlapped->hEvent);
+}
- /* Same again, but read as a single part */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+#define overlapped_write_sync(a,b,c) _overlapped_write_sync(__LINE__,a,b,c)
+static void _overlapped_write_sync(unsigned line, HANDLE writer, void *buf, DWORD size)
+{
+ DWORD written_bytes = 0xdeadbeef;
+ OVERLAPPED overlapped;
+ BOOL res;
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == strlen(long_test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ res = WriteFile(writer, buf, size, &written_bytes, &overlapped);
+ ok_(__FILE__,line)(res, "WriteFile returned %x(%u)\n", res, GetLastError());
+ ok_(__FILE__,line)(written_bytes == size, "WriteFile returned written_bytes = %u\n", written_bytes);
- /* Check content of overlapped structure */
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(ret == FALSE, "ReadFile succeeded\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
- ok(num_bytes == 0, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
- todo_wine
- ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
- todo_wine
- ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+ written_bytes = 0xdeadbeef;
+ res = GetOverlappedResult(writer, &overlapped, &written_bytes, FALSE);
+ ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
+ ok_(__FILE__,line)(written_bytes == size, "GetOverlappedResult returned written_bytes %u expected %u\n", written_bytes, size);
- /* Call ReadFile after writing to the pipe */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ CloseHandle(overlapped.hEvent);
+}
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
- ok(num_bytes == 4, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+#define overlapped_write_async(a,b,c,d) _overlapped_write_async(__LINE__,a,b,c,d)
+static void _overlapped_write_async(unsigned line, HANDLE writer, void *buf, DWORD size, OVERLAPPED *overlapped)
+{
+ DWORD written_bytes = 0xdeadbeef;
+ BOOL res;
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ memset(overlapped, 0, sizeof(*overlapped));
+ overlapped->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ res = WriteFile(writer, buf, size, &written_bytes, overlapped);
+ ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
+ todo_wine ok_(__FILE__,line)(!written_bytes, "written_bytes = %u\n", written_bytes);
- /* Same again, but read as a single part */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ _test_not_signaled(line, overlapped->hEvent);
+}
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, sizeof(read_buf), &num_bytes, &overlapped);
- ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+#define test_flush_sync(a) _test_flush_sync(__LINE__,a)
+static void _test_flush_sync(unsigned line, HANDLE pipe)
+{
+ BOOL res;
- CloseHandle(client);
- CloseHandle(server);
+ res = FlushFileBuffers(pipe);
+ ok_(__FILE__,line)(res, "FlushFileBuffers failed: %u\n", GetLastError());
+}
- server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
- /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- /* nMaxInstances */ 1,
- /* nOutBufSize */ 1024,
- /* nInBufSize */ 1024,
- /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
- /* lpSecurityAttrib */ NULL);
- ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
+static DWORD expected_flush_error;
- client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, 0, NULL);
- ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
+static DWORD CALLBACK flush_proc(HANDLE pipe)
+{
+ BOOL res;
- memset(&overlapped, 0, sizeof(overlapped));
- overlapped.hEvent = event;
+ res = FlushFileBuffers(pipe);
+ if (expected_flush_error == ERROR_SUCCESS)
+ ok(res, "FlushFileBuffers failed: %u\n", GetLastError());
+ else
+ todo_wine ok(!res && GetLastError() == expected_flush_error, "FlushFileBuffers failed: %u\n", GetLastError());
+ return 0;
+}
- /* Start a call to ReadFileEx which cannot complete immediately */
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
- ok(completion_called == 0, "completion routine called before WriteFile started\n");
+#define test_flush_async(a,b) _test_flush_async(__LINE__,a,b)
+static HANDLE _test_flush_async(unsigned line, HANDLE pipe, DWORD error)
+{
+ HANDLE thread;
+ DWORD tid;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret == TRUE, "WriteFile failed\n");
- ok(num_bytes == strlen(long_test_string), "only %i bytes written\n", num_bytes);
- ok(completion_called == 0, "completion routine called during WriteFile\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ expected_flush_error = error;
+ thread = CreateThread(NULL, 0, flush_proc, pipe, 0, &tid);
+ ok_(__FILE__,line)(thread != NULL, "CreateThread failed: %u\n", GetLastError());
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
- ok(!memcmp(long_test_string, read_buf, 4), "ReadFileEx read wrong bytes\n");
-
- ret = ReadFile(server, read_buf + 4, 4, &num_bytes, NULL);
- ok(ret == FALSE, "ReadFile succeeded\n");
- ok(num_bytes == 4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
- ret = ReadFile(server, read_buf + 8, sizeof(read_buf) - 8, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-8, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
-
- /* Call ReadFileEx when there is already some content in the pipe */
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret == TRUE, "WriteFile failed\n");
- ok(num_bytes == strlen(long_test_string), "only %i bytes written\n", num_bytes);
+ Sleep(50);
+ _test_not_signaled(line, thread);
+ return thread;
+}
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
- ok(!memcmp(long_test_string, read_buf, 4), "ReadFileEx read wrong bytes\n");
+#define test_flush_done(a) _test_flush_done(__LINE__,a)
+static void _test_flush_done(unsigned line, HANDLE thread)
+{
+ DWORD res = WaitForSingleObject(thread, 1000);
+ ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u (%u)\n", res, GetLastError());
+ CloseHandle(thread);
+}
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+#define test_overlapped_result(a,b,c,d) _test_overlapped_result(__LINE__,a,b,c,d)
+static void _test_overlapped_result(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD expected_result, BOOL partial_read)
+{
+ DWORD result = 0xdeadbeef;
+ BOOL res;
- /* Check content of overlapped structure */
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
- ok(num_bytes == 0, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
- todo_wine
- ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ _test_signaled(line, overlapped->hEvent);
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed\n");
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+ res = GetOverlappedResult(handle, overlapped, &result, FALSE);
+ if (partial_read)
+ ok_(__FILE__,line)(!res && GetLastError() == ERROR_MORE_DATA, "GetOverlappedResult returned: %x (%u)\n", res, GetLastError());
+ else
+ ok_(__FILE__,line)(res, "GetOverlappedResult failed: %u\n", GetLastError());
+ ok_(__FILE__,line)(result == expected_result, "read_bytes = %u, expected %u\n", result, expected_result);
+ CloseHandle(overlapped->hEvent);
+}
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+#define test_overlapped_failure(a,b,c) _test_overlapped_failure(__LINE__,a,b,c)
+static void _test_overlapped_failure(unsigned line, HANDLE handle, OVERLAPPED *overlapped, DWORD error)
+{
+ DWORD result;
+ BOOL res;
- /* Call ReadFile when there is already some content in the pipe */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed\n");
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ _test_signaled(line, overlapped->hEvent);
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(ret == FALSE, "ReadFile succeeded\n");
- ok(GetLastError() == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", GetLastError());
- todo_wine
- ok(num_bytes == 0, "ReadFile returned %d bytes\n", num_bytes);
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- todo_wine
- ok(num_bytes == 0, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+ res = GetOverlappedResult(handle, overlapped, &result, FALSE);
+ ok_(__FILE__,line)(!res && GetLastError() == error, "GetOverlappedResult returned: %x (%u), expected error %u\n",
+ res, GetLastError(), error);
+ ok_(__FILE__,line)(!result, "result = %u\n", result);
+ CloseHandle(overlapped->hEvent);
+}
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+#define cancel_overlapped(a,b) _cancel_overlapped(__LINE__,a,b)
+static void _cancel_overlapped(unsigned line, HANDLE handle, OVERLAPPED *overlapped)
+{
+ BOOL res;
- /* Tests for PIPE_NOWAIT in message mode */
- lpmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
- ok(SetNamedPipeHandleState(server, &lpmode, NULL, NULL), "Change mode\n");
+ res = pCancelIoEx(handle, overlapped);
+ ok_(__FILE__,line)(res, "CancelIoEx failed: %u\n", GetLastError());
- /* Initial check with empty pipe */
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == FALSE, "ReadFileEx succeded\n");
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 0, "completion routine called before writing to file\n");
+ _test_overlapped_failure(line, handle, overlapped, ERROR_OPERATION_ABORTED);
+}
- /* Call ReadFileEx after writing content to the pipe */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+static void test_blocking_rw(HANDLE writer, HANDLE reader, DWORD buf_size, BOOL msg_mode, BOOL msg_read)
+{
+ OVERLAPPED read_overlapped, read_overlapped2, write_overlapped, write_overlapped2;
+ char buf[10000], read_buf[10000];
+ HANDLE flush_thread;
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ memset(buf, 0xaa, sizeof(buf));
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile succeeded\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ /* test pending read with overlapped event */
+ overlapped_read_async(reader, read_buf, 1000, &read_overlapped);
+ test_flush_sync(writer);
+ test_peek_pipe(reader, 0, 0, 0);
- /* Same again, but read as a single part */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ /* write more data than needed for read */
+ overlapped_write_sync(writer, buf, 4000);
+ test_overlapped_result(reader, &read_overlapped, 1000, msg_read);
- memset(read_buf, 0, sizeof(read_buf));
- completion_called = 0;
- ResetEvent(event);
- ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
- ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
- ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
- wait = WaitForSingleObjectEx(event, 0, TRUE);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- ok(completion_called == 1, "completion not called after writing pipe\n");
- ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
- ok(completion_num_bytes == strlen(long_test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
- ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ /* test pending write with overlapped event */
+ overlapped_write_async(writer, buf, buf_size, &write_overlapped);
- /* Check content of overlapped structure */
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(ret == FALSE, "ReadFile succeeded\n");
- ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
- ok(num_bytes == 0, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
- todo_wine
- ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
- todo_wine
- ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+ /* write one more byte */
+ overlapped_write_async(writer, buf, 1, &write_overlapped2);
+ flush_thread = test_flush_async(writer, ERROR_SUCCESS);
+ test_not_signaled(write_overlapped.hEvent);
- /* Call ReadFile after writing to the pipe */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ /* empty write will not block */
+ overlapped_write_sync(writer, buf, 0);
+ test_not_signaled(write_overlapped.hEvent);
+ test_not_signaled(write_overlapped2.hEvent);
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
- ok(ret == FALSE, "ReadFile succeeded\n");
- ok(GetLastError() == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", GetLastError());
- todo_wine
- ok(num_bytes == 0, "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+ /* read remaining data from the first write */
+ overlapped_read_sync(reader, read_buf, 3000, 3000, FALSE);
+ test_overlapped_result(writer, &write_overlapped, buf_size, FALSE);
+ test_not_signaled(write_overlapped2.hEvent);
+ test_not_signaled(flush_thread);
- ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
- ok(ret == TRUE, "ReadFile failed\n");
- ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ /* read one byte so that the next write fits the buffer */
+ overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
+ test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
- /* Same again, but read as a single part */
- num_bytes = 0xdeadbeef;
- ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
- ok(ret, "WriteFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ /* read the whole buffer */
+ overlapped_read_sync(reader, read_buf, buf_size, buf_size-msg_read, FALSE);
- memset(read_buf, 0, sizeof(read_buf));
- S(U(overlapped)).Offset = 0;
- S(U(overlapped)).OffsetHigh = 0;
- overlapped.Internal = -1;
- overlapped.InternalHigh = -1;
- overlapped.hEvent = event;
- num_bytes = 0xdeadbeef;
- SetLastError(0xdeadbeef);
- ret = ReadFile(server, read_buf, sizeof(read_buf), &num_bytes, &overlapped);
- ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
- ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
- ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
- wait = WaitForSingleObject(event, 100);
- ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
- ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
- ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
- ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ if(msg_read)
+ overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
+
+ if(msg_mode) {
+ /* we still have an empty message in queue */
+ overlapped_read_sync(reader, read_buf, 1000, 0, FALSE);
+ }
+ test_flush_done(flush_thread);
+
+ /* pipe is empty, the next read will block */
+ overlapped_read_async(reader, read_buf, 0, &read_overlapped);
+ overlapped_read_async(reader, read_buf, 1000, &read_overlapped2);
+
+ /* write one byte */
+ overlapped_write_sync(writer, buf, 1);
+ test_overlapped_result(reader, &read_overlapped, 0, msg_read);
+ test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
+
+ /* write a message larger than buffer */
+ overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
+
+ /* read so that pending write is still larger than the buffer */
+ overlapped_read_sync(reader, read_buf, 1999, 1999, msg_read);
+ test_not_signaled(write_overlapped.hEvent);
+
+ /* read one more byte */
+ overlapped_read_sync(reader, read_buf, 1, 1, msg_read);
+ test_overlapped_result(writer, &write_overlapped, buf_size+2000, FALSE);
+
+ /* read remaining data */
+ overlapped_read_sync(reader, read_buf, buf_size+1, buf_size, FALSE);
+
+ /* simple pass of empty message */
+ overlapped_write_sync(writer, buf, 0);
+ if(msg_mode)
+ overlapped_read_sync(reader, read_buf, 1, 0, FALSE);
+
+ /* pipe is empty, the next read will block */
+ test_flush_sync(writer);
+ overlapped_read_async(reader, read_buf, 0, &read_overlapped);
+ overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
+
+ /* 0 length write wakes one read in msg mode */
+ overlapped_write_sync(writer, buf, 0);
+ if(msg_mode)
+ test_overlapped_result(reader, &read_overlapped, 0, FALSE);
+ else
+ test_not_signaled(read_overlapped.hEvent);
+ test_not_signaled(read_overlapped2.hEvent);
+ overlapped_write_sync(writer, buf, 1);
+ test_overlapped_result(reader, &read_overlapped2, 1, FALSE);
+
+ overlapped_write_sync(writer, buf, 20);
+ test_peek_pipe(reader, 20, 20, msg_mode ? 20 : 0);
+ overlapped_write_sync(writer, buf, 15);
+ test_peek_pipe(reader, msg_mode ? 20 : 35, 35, msg_mode ? 20 : 0);
+ overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
+ test_peek_pipe(reader, msg_mode ? 10 : 25, 25, msg_mode ? 10 : 0);
+ overlapped_read_sync(reader, read_buf, 10, 10, FALSE);
+ test_peek_pipe(reader, 15, 15, msg_mode ? 15 : 0);
+ overlapped_read_sync(reader, read_buf, 15, 15, FALSE);
+
+ if(!pCancelIoEx) {
+ win_skip("CancelIoEx not available\n");
+ return;
+ }
+
+ /* add one more pending read, then cancel the first one */
+ overlapped_read_async(reader, read_buf, 1, &read_overlapped);
+ overlapped_read_async(reader, read_buf, 1, &read_overlapped2);
+ cancel_overlapped(reader, &read_overlapped2);
+ test_not_signaled(read_overlapped.hEvent);
+ overlapped_write_sync(writer, buf, 1);
+ test_overlapped_result(reader, &read_overlapped, 1, FALSE);
+
+ /* make two async writes, cancel the first one and make sure that we read from the second one */
+ overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
+ overlapped_write_async(writer, buf, 1, &write_overlapped2);
+ cancel_overlapped(writer, &write_overlapped);
+ overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
+ test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
+
+ /* same as above, but parially read written data before canceling */
+ overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
+ overlapped_write_async(writer, buf, 1, &write_overlapped2);
+ overlapped_read_sync(reader, read_buf, 10, 10, msg_read);
+ test_not_signaled(write_overlapped.hEvent);
+ cancel_overlapped(writer, &write_overlapped);
+ overlapped_read_sync(reader, read_buf, 1000, 1, FALSE);
+ test_overlapped_result(writer, &write_overlapped2, 1, FALSE);
+
+ /* empty queue by canceling write and make sure that flush is signaled */
+ overlapped_write_async(writer, buf, buf_size+2000, &write_overlapped);
+ flush_thread = test_flush_async(writer, ERROR_SUCCESS);
+ test_not_signaled(flush_thread);
+ cancel_overlapped(writer, &write_overlapped);
+ test_flush_done(flush_thread);
+}
+
+static void child_process_write_pipe(HANDLE pipe)
+{
+ OVERLAPPED overlapped;
+ char buf[10000];
+
+ memset(buf, 'x', sizeof(buf));
+ overlapped_write_async(pipe, buf, sizeof(buf), &overlapped);
+
+ /* sleep until parent process terminates this process */
+ Sleep(INFINITE);
+}
+
+static HANDLE create_writepipe_process(HANDLE pipe)
+{
+ STARTUPINFOA si = { sizeof(si) };
+ PROCESS_INFORMATION info;
+ char **argv, buf[MAX_PATH];
+ BOOL res;
+
+ winetest_get_mainargs(&argv);
+ sprintf(buf, "\"%s\" pipe writepipe %lx", argv[0], (UINT_PTR)pipe);
+ res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL, &si, &info);
+ ok(res, "CreateProcess failed: %u\n", GetLastError());
+ CloseHandle(info.hThread);
+
+ return info.hProcess;
+}
+
+static void create_overlapped_pipe(DWORD mode, HANDLE *client, HANDLE *server)
+{
+ SECURITY_ATTRIBUTES sec_attr = { sizeof(sec_attr), NULL, TRUE };
+ DWORD read_mode = mode & (PIPE_READMODE_BYTE | PIPE_READMODE_MESSAGE);
+ OVERLAPPED overlapped;
+ BOOL res;
+
+ *server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
+ PIPE_WAIT | mode, 1, 5000, 6000, NMPWAIT_USE_DEFAULT_WAIT, NULL);
+ ok(&server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError());
+ test_signaled(*server);
+
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ res = ConnectNamedPipe(*server, &overlapped);
+ ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %x(%u)\n", res, GetLastError());
+ test_not_signaled(*server);
+ test_not_signaled(overlapped.hEvent);
+
+ *client = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, &sec_attr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ ok(*server != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+
+ res = SetNamedPipeHandleState(*client, &read_mode, NULL, NULL);
+ ok(res, "SetNamedPipeHandleState failed: %u\n", GetLastError());
+
+ test_signaled(*client);
+ test_not_signaled(*server);
+ test_overlapped_result(*server, &overlapped, 0, FALSE);
+}
+
+static void test_overlapped_transport(BOOL msg_mode, BOOL msg_read_mode)
+{
+ OVERLAPPED overlapped, overlapped2;
+ HANDLE server, client, flush;
+ DWORD read_bytes;
+ HANDLE process;
+ char buf[60000];
+ BOOL res;
+
+ DWORD create_flags =
+ (msg_mode ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE) |
+ (msg_read_mode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
+
+ create_overlapped_pipe(create_flags, &client, &server);
+
+ trace("testing %s, %s server->client writes...\n",
+ msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
+ test_blocking_rw(server, client, 5000, msg_mode, msg_read_mode);
+ trace("testing %s, %s client->server writes...\n",
+ msg_mode ? "message mode" : "byte mode", msg_read_mode ? "message read" : "byte read");
+ test_blocking_rw(client, server, 6000, msg_mode, msg_read_mode);
CloseHandle(client);
CloseHandle(server);
- CloseHandle(event);
+
+ /* close client with pending writes */
+ create_overlapped_pipe(create_flags, &client, &server);
+ overlapped_write_async(server, buf, 7000, &overlapped);
+ flush = test_flush_async(server, ERROR_BROKEN_PIPE);
+ CloseHandle(client);
+ test_overlapped_failure(server, &overlapped, ERROR_BROKEN_PIPE);
+ test_flush_done(flush);
+ CloseHandle(server);
+
+ /* close server with pending writes */
+ create_overlapped_pipe(create_flags, &client, &server);
+ overlapped_write_async(client, buf, 7000, &overlapped);
+ flush = test_flush_async(client, ERROR_BROKEN_PIPE);
+ CloseHandle(server);
+ test_overlapped_failure(client, &overlapped, ERROR_BROKEN_PIPE);
+ test_flush_done(flush);
+ CloseHandle(client);
+
+ /* disconnect with pending writes */
+ create_overlapped_pipe(create_flags, &client, &server);
+ overlapped_write_async(client, buf, 7000, &overlapped);
+ overlapped_write_async(server, buf, 7000, &overlapped2);
+ flush = test_flush_async(client, ERROR_PIPE_NOT_CONNECTED);
+ res = DisconnectNamedPipe(server);
+ ok(res, "DisconnectNamedPipe failed: %u\n", GetLastError());
+ test_overlapped_failure(client, &overlapped, ERROR_PIPE_NOT_CONNECTED);
+ test_overlapped_failure(client, &overlapped2, ERROR_PIPE_NOT_CONNECTED);
+ test_flush_done(flush);
+ CloseHandle(server);
+ CloseHandle(client);
+
+ /* terminate process with pending write */
+ create_overlapped_pipe(create_flags, &client, &server);
+ process = create_writepipe_process(client);
+ /* successfully read part of write that is pending in child process */
+ res = ReadFile(server, buf, 10, &read_bytes, NULL);
+ if(!msg_read_mode)
+ ok(res, "ReadFile failed: %u\n", GetLastError());
+ else
+ ok(!res && GetLastError() == ERROR_MORE_DATA, "ReadFile returned: %x %u\n", res, GetLastError());
+ ok(read_bytes == 10, "read_bytes = %u\n", read_bytes);
+ TerminateProcess(process, 0);
+ winetest_wait_child_process(process);
+ /* after terminating process, there is no pending write and pipe buffer is empty */
+ overlapped_read_async(server, buf, 10, &overlapped);
+ overlapped_write_sync(client, buf, 1);
+ test_overlapped_result(server, &overlapped, 1, FALSE);
+ CloseHandle(process);
+ CloseHandle(server);
+ CloseHandle(client);
}
START_TEST(pipe)
{
+ char **argv;
+ int argc;
HMODULE hmod;
hmod = GetModuleHandleA("advapi32.dll");
pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
hmod = GetModuleHandleA("kernel32.dll");
pQueueUserAPC = (void *) GetProcAddress(hmod, "QueueUserAPC");
+ pCancelIoEx = (void *) GetProcAddress(hmod, "CancelIoEx");
+
+ argc = winetest_get_mainargs(&argv);
+
+ if (argc > 3 && !strcmp(argv[2], "writepipe"))
+ {
+ UINT_PTR handle;
+ sscanf(argv[3], "%lx", &handle);
+ child_process_write_pipe((HANDLE)handle);
+ return;
+ }
if (test_DisconnectNamedPipe())
return;
test_impersonation();
test_overlapped();
test_overlapped_error();
- test_nowait(PIPE_TYPE_BYTE);
- test_nowait(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
test_NamedPipeHandleState();
+ test_GetNamedPipeInfo();
test_readfileex_pending();
+ test_overlapped_transport(TRUE, FALSE);
+ test_overlapped_transport(TRUE, TRUE);
+ if (broken(1)) /* FIXME: Remove once Wine is ready. */
+ test_overlapped_transport(FALSE, FALSE);
}
static BOOL (WINAPI *pThread32Next)(HANDLE, THREADENTRY32*);
static BOOL (WINAPI *pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*);
static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
+static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
+static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
+static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
+static DWORD (WINAPI *pGetActiveProcessorCount)(WORD);
/* ############################### */
static char base[MAX_PATH];
pThread32Next = (void *)GetProcAddress(hkernel32, "Thread32Next");
pGetLogicalProcessorInformationEx = (void *)GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
pGetLargePageMinimum = (void *)GetProcAddress(hkernel32, "GetLargePageMinimum");
+ pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
+ pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
+ pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
+ pGetActiveProcessorCount = (void *)GetProcAddress(hkernel32, "GetActiveProcessorCount");
return TRUE;
}
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* not so simplistic now */
memset(&startup, 0, sizeof(startup));
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* TODO: test for A/W and W/A and W/W */
}
okChildString("Arguments", "argvA5", NULL);
okChildString("Arguments", "CommandLineA", buffer);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
okChildString("Arguments", "argvA7", NULL);
okChildString("Arguments", "CommandLineA", buffer);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
get_file_name(resfile);
sprintf(buffer, "./%s", exename);
okChildString("Arguments", "argvA0", buffer);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
get_file_name(resfile);
/* Use exename to avoid buffer containing things like 'C:' */
sprintf(buffer, ".\\%s", exename);
okChildString("Arguments", "argvA0", buffer);
release_memory();
- assert(DeleteFileA(resfile) != 0);
-
+ DeleteFileA(resfile);
+
get_file_name(resfile);
GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
assert ( lpFilePart != 0);
else sprintf(buffer, "./%s", exename);
okChildString("Arguments", "argvA0", buffer);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* Using AppName */
get_file_name(resfile);
okChildString("Arguments", "CommandLineA", buffer2);
okChildStringWA("Arguments", "CommandLineW", buffer2);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
if (0) /* Test crashes on NT-based Windows. */
{
okChildIString("Misc", "CurrDirA", windir);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
/* search PATH for the exe if directory is NULL */
ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
env = GetEnvironmentStringsA();
cmpEnvironment(env);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
HeapFree(GetProcessHeap(), 0, child_env);
FreeEnvironmentStringsA(env);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
}
static void test_SuspendFlag(void)
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
}
static void test_DebuggingFlag(void)
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
}
static BOOL is_console(HANDLE h)
startup.hStdError = startup.hStdOutput;
ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbi), "Getting sb info\n");
- ok(GetConsoleMode(startup.hStdInput, &modeIn) &&
- GetConsoleMode(startup.hStdOutput, &modeOut), "Getting console modes\n");
+ ok(GetConsoleMode(startup.hStdInput, &modeIn), "Getting console in mode\n");
+ ok(GetConsoleMode(startup.hStdOutput, &modeOut), "Getting console out mode\n");
cpIn = GetConsoleCP();
cpOut = GetConsoleOutputCP();
/* now get the modification the child has made, and resets parents expected values */
ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbiC), "Getting sb info\n");
- ok(GetConsoleMode(startup.hStdInput, &modeInC) &&
- GetConsoleMode(startup.hStdOutput, &modeOutC), "Getting console modes\n");
+ ok(GetConsoleMode(startup.hStdInput, &modeInC), "Getting console in mode\n");
+ ok(GetConsoleMode(startup.hStdOutput, &modeOutC), "Getting console out mode\n");
SetConsoleMode(startup.hStdInput, modeIn);
SetConsoleMode(startup.hStdOutput, modeOut);
ok(sbiC.dwCursorPosition.Y == (sbi.dwCursorPosition.Y ^ 1), "Wrong cursor position\n");
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
ok(CreatePipe(&hParentIn, &hChildOut, NULL, 0), "Creating parent-input pipe\n");
ok(DuplicateHandle(GetCurrentProcess(), hChildOut, GetCurrentProcess(),
okChildString("StdHandle", "msg", msg);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
}
static void test_ExitCode(void)
okChildInt("ExitCode", "value", code);
release_memory();
- assert(DeleteFileA(resfile) != 0);
+ DeleteFileA(resfile);
}
static void test_OpenProcess(void)
expect_eq_d(lstrlenW(buf), size);
expect_eq_ws_i(buf, module_name);
- hSelf = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
+ hSelf = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
/* Real handle */
size = sizeof(buf) / sizeof(buf[0]);
expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
ret = QueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list,
FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList), &ret_len);
ok(!ret, "QueryInformationJobObject expected failure\n");
- todo_wine
expect_eq_d(ERROR_BAD_LENGTH, GetLastError());
SetLastError(0xdeadbeef);
pid_list->NumberOfProcessIdsInList = 42;
ret = QueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list,
FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[1]), &ret_len);
+ todo_wine
ok(!ret, "QueryInformationJobObject expected failure\n");
todo_wine
expect_eq_d(ERROR_MORE_DATA, GetLastError());
if (ret)
{
+ todo_wine
expect_eq_d(42, pid_list->NumberOfAssignedProcesses);
+ todo_wine
expect_eq_d(42, pid_list->NumberOfProcessIdsInList);
}
memset(buf, 0, sizeof(buf));
ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
- todo_wine
ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
if(ret)
{
{
ULONG_PTR *list = pid_list->ProcessIdList;
+ todo_wine
ok(ret_len == FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[2]),
"QueryInformationJobObject returned ret_len=%u\n", ret_len);
+ todo_wine
expect_eq_d(2, pid_list->NumberOfAssignedProcesses);
+ todo_wine
expect_eq_d(2, pid_list->NumberOfProcessIdsInList);
+ todo_wine
expect_eq_d(pi[0].dwProcessId, list[0]);
+ todo_wine
expect_eq_d(pi[1].dwProcessId, list[1]);
}
}
#endif
}
+static void test_DetachConsoleHandles(void)
+{
+#ifndef _WIN64
+ char buffer[MAX_PATH];
+ STARTUPINFOA startup;
+ PROCESS_INFORMATION info;
+ UINT result;
+
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ get_file_name(resfile);
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
+ ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup,
+ &info), "CreateProcess\n");
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
+
+ result = GetPrivateProfileIntA("StartupInfoA", "hStdInput", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+ result = GetPrivateProfileIntA("StartupInfoA", "hStdOutput", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+ result = GetPrivateProfileIntA("StartupInfoA", "hStdError", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+ result = GetPrivateProfileIntA("TEB", "hStdInput", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+ result = GetPrivateProfileIntA("TEB", "hStdOutput", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+ result = GetPrivateProfileIntA("TEB", "hStdError", 0, resfile);
+ ok(result != 0 && result != (UINT)INVALID_HANDLE_VALUE, "bad handle %x\n", result);
+
+ release_memory();
+ DeleteFileA(resfile);
+#endif
+}
+
+static void test_DetachStdHandles(void)
+{
+#ifndef _WIN64
+ char buffer[MAX_PATH], tempfile[MAX_PATH];
+ STARTUPINFOA startup;
+ PROCESS_INFORMATION info;
+ HANDLE hstdin, hstdout, hstderr, htemp;
+ BOOL res;
+
+ hstdin = GetStdHandle(STD_INPUT_HANDLE);
+ hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ hstderr = GetStdHandle(STD_ERROR_HANDLE);
+
+ get_file_name(tempfile);
+ htemp = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(htemp != INVALID_HANDLE_VALUE, "failed opening temporary file\n");
+
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWNORMAL;
+ get_file_name(resfile);
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
+
+ SetStdHandle(STD_INPUT_HANDLE, htemp);
+ SetStdHandle(STD_OUTPUT_HANDLE, htemp);
+ SetStdHandle(STD_ERROR_HANDLE, htemp);
+
+ res = CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup,
+ &info);
+
+ SetStdHandle(STD_INPUT_HANDLE, hstdin);
+ SetStdHandle(STD_OUTPUT_HANDLE, hstdout);
+ SetStdHandle(STD_ERROR_HANDLE, hstderr);
+
+ ok(res, "CreateProcess failed\n");
+ ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
+ okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE);
+ okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE);
+ okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE);
+ okChildInt("TEB", "hStdInput", 0);
+ okChildInt("TEB", "hStdOutput", 0);
+ okChildInt("TEB", "hStdError", 0);
+ release_memory();
+ DeleteFileA(resfile);
+
+ CloseHandle(htemp);
+ DeleteFileA(tempfile);
+#endif
+}
+
static void test_GetNumaProcessorNode(void)
{
SYSTEM_INFO si;
sizeof(buf) /* ProcessHandleTracing */,
sizeof(ULONG) /* ProcessIoPriority */,
sizeof(ULONG) /* ProcessExecuteFlags */,
-#if 0 /* FIXME: Add remaining classes */
- ProcessResourceManagement,
- sizeof(ULONG) /* ProcessCookie */,
+ 0 /* FIXME: sizeof(?) ProcessTlsInformation */,
+ 0 /* FIXME: sizeof(?) ProcessCookie */,
sizeof(SECTION_IMAGE_INFORMATION) /* ProcessImageInformation */,
- sizeof(PROCESS_CYCLE_TIME_INFORMATION) /* ProcessCycleTime */,
+ 0 /* FIXME: sizeof(PROCESS_CYCLE_TIME_INFORMATION) ProcessCycleTime */,
sizeof(ULONG) /* ProcessPagePriority */,
40 /* ProcessInstrumentationCallback */,
- sizeof(PROCESS_STACK_ALLOCATION_INFORMATION) /* ProcessThreadStackAllocation */,
- sizeof(PROCESS_WS_WATCH_INFORMATION_EX[]) /* ProcessWorkingSetWatchEx */,
+ 0 /* FIXME: sizeof(PROCESS_STACK_ALLOCATION_INFORMATION) ProcessThreadStackAllocation */,
+ 0 /* FIXME: sizeof(PROCESS_WS_WATCH_INFORMATION_EX[]) ProcessWorkingSetWatchEx */,
sizeof(buf) /* ProcessImageFileNameWin32 */,
sizeof(HANDLE) /* ProcessImageFileMapping */,
- sizeof(PROCESS_AFFINITY_UPDATE_MODE) /* ProcessAffinityUpdateMode */,
- sizeof(PROCESS_MEMORY_ALLOCATION_MODE) /* ProcessMemoryAllocationMode */,
- sizeof(USHORT[]) /* ProcessGroupInformation */,
+ 0 /* FIXME: sizeof(PROCESS_AFFINITY_UPDATE_MODE) ProcessAffinityUpdateMode */,
+ 0 /* FIXME: sizeof(PROCESS_MEMORY_ALLOCATION_MODE) ProcessMemoryAllocationMode */,
+ sizeof(USHORT) /* ProcessGroupInformation */,
sizeof(ULONG) /* ProcessTokenVirtualizationEnabled */,
sizeof(ULONG_PTR) /* ProcessConsoleHostProcess */,
- sizeof(PROCESS_WINDOW_INFORMATION) /* ProcessWindowInformation */,
+ 0 /* FIXME: sizeof(PROCESS_WINDOW_INFORMATION) ProcessWindowInformation */,
+#if 0 /* FIXME: Add remaining classes */
sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION) /* ProcessHandleInformation */,
sizeof(PROCESS_MITIGATION_POLICY_INFORMATION) /* ProcessMitigationPolicy */,
sizeof(ProcessDynamicFunctionTableInformation) /* ProcessDynamicFunctionTableInformation */,
case ProcessWow64Information:
case ProcessDefaultHardErrorMode:
case ProcessHandleCount:
- ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
- break;
-
case ProcessImageFileName:
-todo_wine
+ case ProcessImageInformation:
+ case ProcessPagePriority:
+ case ProcessImageFileNameWin32:
ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
break;
case ProcessAffinityMask:
case ProcessBreakOnTermination:
+ case ProcessGroupInformation:
+ case ProcessConsoleHostProcess:
ok(status == STATUS_ACCESS_DENIED /* before win8 */ || status == STATUS_SUCCESS /* win8 is less strict */,
"for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
break;
case ProcessExecuteFlags:
case ProcessDebugPort:
case ProcessDebugFlags:
+ case ProcessCookie:
todo_wine
ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
break;
ok((size == 0) || (size == 2*1024*1024) || (size == 4*1024*1024), "GetLargePageMinimum reports %ld size\n", size);
}
+struct proc_thread_attr
+{
+ DWORD_PTR attr;
+ SIZE_T size;
+ void *value;
+};
+
+struct _PROC_THREAD_ATTRIBUTE_LIST
+{
+ DWORD mask; /* bitmask of items in list */
+ DWORD size; /* max number of items in list */
+ DWORD count; /* number of items in list */
+ DWORD pad;
+ DWORD_PTR unk;
+ struct proc_thread_attr attrs[10];
+};
+
+static void test_ProcThreadAttributeList(void)
+{
+ BOOL ret;
+ SIZE_T size, needed;
+ int i;
+ struct _PROC_THREAD_ATTRIBUTE_LIST list, expect_list;
+ HANDLE handles[4];
+
+ if (!pInitializeProcThreadAttributeList)
+ {
+ win_skip("No support for ProcThreadAttributeList\n");
+ return;
+ }
+
+ for (i = 0; i <= 10; i++)
+ {
+ needed = FIELD_OFFSET(struct _PROC_THREAD_ATTRIBUTE_LIST, attrs[i]);
+ ret = pInitializeProcThreadAttributeList(NULL, i, 0, &size);
+ ok(!ret, "got %d\n", ret);
+ if(i >= 4 && GetLastError() == ERROR_INVALID_PARAMETER) /* Vista only allows a maximium of 3 slots */
+ break;
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d\n", GetLastError());
+ ok(size == needed, "%d: got %ld expect %ld\n", i, size, needed);
+
+ memset(&list, 0xcc, sizeof(list));
+ ret = pInitializeProcThreadAttributeList(&list, i, 0, &size);
+ ok(ret, "got %d\n", ret);
+ ok(list.mask == 0, "%d: got %08x\n", i, list.mask);
+ ok(list.size == i, "%d: got %08x\n", i, list.size);
+ ok(list.count == 0, "%d: got %08x\n", i, list.count);
+ ok(list.unk == 0, "%d: got %08lx\n", i, list.unk);
+ }
+
+ memset(handles, 0, sizeof(handles));
+ memset(&expect_list, 0xcc, sizeof(expect_list));
+ expect_list.mask = 0;
+ expect_list.size = i - 1;
+ expect_list.count = 0;
+ expect_list.unk = 0;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, 0xcafe, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_NOT_SUPPORTED, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) / 2, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]) * 2, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
+ ok(ret, "got %d\n", ret);
+
+ expect_list.mask |= 1 << ProcThreadAttributeParentProcess;
+ expect_list.attrs[0].attr = PROC_THREAD_ATTRIBUTE_PARENT_PROCESS;
+ expect_list.attrs[0].size = sizeof(handles[0]);
+ expect_list.attrs[0].value = handles;
+ expect_list.count++;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, handles, sizeof(handles[0]), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_OBJECT_NAME_EXISTS, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles) - 1, NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_BAD_LENGTH, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
+ ok(ret, "got %d\n", ret);
+
+ expect_list.mask |= 1 << ProcThreadAttributeHandleList;
+ expect_list.attrs[1].attr = PROC_THREAD_ATTRIBUTE_HANDLE_LIST;
+ expect_list.attrs[1].size = sizeof(handles);
+ expect_list.attrs[1].value = handles;
+ expect_list.count++;
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles, sizeof(handles), NULL, NULL);
+ ok(!ret, "got %d\n", ret);
+ ok(GetLastError() == ERROR_OBJECT_NAME_EXISTS, "got %d\n", GetLastError());
+
+ ret = pUpdateProcThreadAttribute(&list, 0, PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR, handles, sizeof(PROCESSOR_NUMBER), NULL, NULL);
+ ok(ret || (!ret && GetLastError() == ERROR_NOT_SUPPORTED), "got %d gle %d\n", ret, GetLastError());
+
+ if (ret)
+ {
+ expect_list.mask |= 1 << ProcThreadAttributeIdealProcessor;
+ expect_list.attrs[2].attr = PROC_THREAD_ATTRIBUTE_IDEAL_PROCESSOR;
+ expect_list.attrs[2].size = sizeof(PROCESSOR_NUMBER);
+ expect_list.attrs[2].value = handles;
+ expect_list.count++;
+ }
+
+ ok(!memcmp(&list, &expect_list, size), "mismatch\n");
+
+ pDeleteProcThreadAttributeList(&list);
+}
+
+static void test_GetActiveProcessorCount(void)
+{
+ DWORD count;
+
+ if (!pGetActiveProcessorCount)
+ {
+ win_skip("GetActiveProcessorCount not available, skipping test\n");
+ return;
+ }
+
+ count = pGetActiveProcessorCount(0);
+ ok(count, "GetActiveProcessorCount failed, error %u\n", GetLastError());
+
+ /* Test would fail on systems with more than 6400 processors */
+ SetLastError(0xdeadbeef);
+ count = pGetActiveProcessorCount(101);
+ ok(count == 0, "Expeced GetActiveProcessorCount to fail\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+}
+
START_TEST(process)
{
HANDLE job;
test_RegistryQuota();
test_DuplicateHandle();
test_StartupNoConsole();
+ test_DetachConsoleHandles();
+ test_DetachStdHandles();
test_GetNumaProcessorNode();
test_session_info();
test_GetLogicalProcessorInformationEx();
+ test_GetActiveProcessorCount();
test_largepages();
+ test_ProcThreadAttributeList();
/* things that can be tested:
* lookup: check the way program to be executed is searched
ctx.ContextFlags = CONTEXT_FULL;
SetLastError(0xdeadbeef);
ret = GetThreadContext( thread, &ctx );
- ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
+ ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
(!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
broken(ret), /* 32bit application on NT 5.x 64bit */
- "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
+ "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
ret, GetLastError() );
SetLastError(0xdeadbeef);
case ThreadAffinityMask:
case ThreadQuerySetWin32StartAddress:
+ case ThreadIsIoPending:
todo_wine
ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
break;
ok(ret ||
broken(ret == 0), /* win95 */
"Expected GetVersionExA to succeed\n");
+
+ if (!infoExA.wServicePackMajor && !infoExA.wServicePackMinor)
+ ok(!infoExA.szCSDVersion[0], "got '%s'\n", infoExA.szCSDVersion);
}
static void test_VerifyVersionInfo(void)
#if defined(__i386__) || defined(__x86_64__)
test_stack_commit();
#endif
+#ifdef __i386__
test_guard_page();
/* The following tests should be executed as a last step, and in exactly this
* order, since ATL thunk emulation cannot be enabled anymore on Windows. */
test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE );
test_atl_thunk_emulation( MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION );
+#endif
}