mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
- Update kernel32 winetest, thanks to Stefan100 for making this possible
svn path=/trunk/; revision=38314
This commit is contained in:
parent
6d0b61ca56
commit
20d4a1d899
27 changed files with 3231 additions and 494 deletions
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "wine/test.h"
|
||||
#include <psdk/winbase.h>
|
||||
#include <winbase.h>
|
||||
#include <windef.h>
|
||||
#include <winnt.h>
|
||||
#include <winternl.h>
|
||||
|
@ -223,7 +223,7 @@ static BOOL create_wide_manifest(const char *filename, const char *manifest, BOO
|
|||
BOOL ret;
|
||||
int offset = (fBOM ? 0 : 1);
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, manifest, -1, &wmanifest[1], (strlen(manifest)+1) * sizeof(WCHAR));
|
||||
MultiByteToWideChar(CP_ACP, 0, manifest, -1, &wmanifest[1], (strlen(manifest)+1));
|
||||
wmanifest[0] = 0xfeff;
|
||||
if (fReverse)
|
||||
{
|
||||
|
@ -851,6 +851,42 @@ static void test_find_string_fail(void)
|
|||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError()=%u\n", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
static void test_basic_info(HANDLE handle)
|
||||
{
|
||||
ACTIVATION_CONTEXT_BASIC_INFORMATION basic;
|
||||
SIZE_T size;
|
||||
BOOL b;
|
||||
|
||||
b = pQueryActCtxW(0, handle, NULL,
|
||||
ActivationContextBasicInformation, &basic,
|
||||
sizeof(basic), &size);
|
||||
|
||||
ok (b,"ActivationContextBasicInformation failed\n");
|
||||
ok (size == sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION),"size mismatch\n");
|
||||
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
|
||||
ok (basic.hActCtx == handle, "unexpected handle\n");
|
||||
|
||||
b = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, NULL,
|
||||
ActivationContextBasicInformation, &basic,
|
||||
sizeof(basic), &size);
|
||||
if (handle)
|
||||
{
|
||||
ok (!b,"ActivationContextBasicInformation succeeded\n");
|
||||
ok (size == 0,"size mismatch\n");
|
||||
ok (GetLastError() == ERROR_INVALID_PARAMETER, "Wrong last error\n");
|
||||
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
|
||||
ok (basic.hActCtx == handle, "unexpected handle\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok (b,"ActivationContextBasicInformation failed\n");
|
||||
ok (size == sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION),"size mismatch\n");
|
||||
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
|
||||
ok (basic.hActCtx == handle, "unexpected handle\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_actctx(void)
|
||||
{
|
||||
ULONG_PTR cookie;
|
||||
|
@ -865,6 +901,7 @@ static void test_actctx(void)
|
|||
ok(handle == NULL, "handle = %p, expected NULL\n", handle);
|
||||
ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
|
||||
if(b) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info0);
|
||||
pReleaseActCtx(handle);
|
||||
}
|
||||
|
@ -879,6 +916,7 @@ static void test_actctx(void)
|
|||
handle = test_create("test1.manifest", manifest1);
|
||||
DeleteFileA("test1.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1);
|
||||
test_info_in_assembly(handle, 1, &manifest1_info);
|
||||
|
||||
|
@ -904,6 +942,7 @@ static void test_actctx(void)
|
|||
DeleteFileA("test2.manifest");
|
||||
DeleteFileA("testdep.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info2);
|
||||
test_info_in_assembly(handle, 1, &manifest2_info);
|
||||
test_info_in_assembly(handle, 2, &depmanifest1_info);
|
||||
|
@ -921,6 +960,7 @@ static void test_actctx(void)
|
|||
DeleteFileA("test3.manifest");
|
||||
DeleteFileA("testdep.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info2);
|
||||
test_info_in_assembly(handle, 1, &manifest2_info);
|
||||
test_info_in_assembly(handle, 2, &depmanifest2_info);
|
||||
|
@ -948,6 +988,7 @@ static void test_actctx(void)
|
|||
DeleteFileA("test2-3.manifest");
|
||||
DeleteFileA("testdep.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info2);
|
||||
test_info_in_assembly(handle, 1, &manifest2_info);
|
||||
test_info_in_assembly(handle, 2, &depmanifest3_info);
|
||||
|
@ -976,6 +1017,7 @@ static void test_actctx(void)
|
|||
handle = test_create("test3.manifest", manifest3);
|
||||
DeleteFileA("test3.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1);
|
||||
test_info_in_assembly(handle, 1, &manifest3_info);
|
||||
test_file_info(handle, 0, 0, testlib_dll);
|
||||
|
@ -1002,6 +1044,7 @@ static void test_actctx(void)
|
|||
DeleteFileA("test4.manifest");
|
||||
DeleteFileA("testdep.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info2);
|
||||
test_info_in_assembly(handle, 1, &manifest4_info);
|
||||
test_info_in_assembly(handle, 2, &manifest_comctrl_info);
|
||||
|
@ -1020,6 +1063,7 @@ static void test_actctx(void)
|
|||
handle = test_create("..\\test1.manifest", manifest1);
|
||||
DeleteFileA("..\\test1.manifest");
|
||||
if(handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1);
|
||||
test_info_in_assembly(handle, 1, &manifest1_info);
|
||||
pReleaseActCtx(handle);
|
||||
|
@ -1039,6 +1083,7 @@ static void test_actctx(void)
|
|||
handle = test_create("test1.manifest", manifest1);
|
||||
DeleteFileA("test1.manifest");
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1);
|
||||
test_info_in_assembly(handle, 1, &manifest1_info);
|
||||
pReleaseActCtx(handle);
|
||||
|
@ -1053,6 +1098,7 @@ static void test_actctx(void)
|
|||
handle = test_create("test1.manifest", manifest1);
|
||||
DeleteFileA("test1.manifest");
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1);
|
||||
test_info_in_assembly(handle, 1, &manifest1_info);
|
||||
pReleaseActCtx(handle);
|
||||
|
@ -1071,6 +1117,7 @@ static void test_app_manifest(void)
|
|||
ok(handle == NULL, "handle != NULL\n");
|
||||
ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
|
||||
if(b) {
|
||||
test_basic_info(handle);
|
||||
test_detailed_info(handle, &detailed_info1_child);
|
||||
test_info_in_assembly(handle, 1, &manifest1_child_info);
|
||||
pReleaseActCtx(handle);
|
||||
|
|
|
@ -304,7 +304,7 @@ static void test_get_atom_name(void)
|
|||
do_initW(inW, "abcdefghij", 255);
|
||||
atom = GlobalAddAtomW(inW);
|
||||
ok(atom, "couldn't add atom for %s\n", in);
|
||||
len = GlobalGetAtomNameW(atom, outW, sizeof(outW));
|
||||
len = GlobalGetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
|
||||
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
|
||||
for (i = 0; i < 255; i++)
|
||||
{
|
||||
|
|
|
@ -223,6 +223,7 @@ static void test_FindFirstChangeNotification(void)
|
|||
file = CreateFileA(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %d\n", GetLastError());
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
ret = WriteFile(file, buffer, sizeof(buffer), &count, NULL);
|
||||
ok(ret && count == sizeof(buffer), "WriteFile error: %d\n", GetLastError());
|
||||
ret = CloseHandle(file);
|
||||
|
@ -559,8 +560,8 @@ static void test_readdirectorychanges(void)
|
|||
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
|
||||
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
|
||||
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
|
||||
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
|
||||
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
|
||||
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong\n" );
|
||||
ok( !memcmp(pfni->FileName,&szGa[1],6*sizeof(WCHAR)), "name wrong\n" );
|
||||
|
||||
r = RemoveDirectoryW( subsubdir );
|
||||
ok( r == TRUE, "failed to remove directory\n");
|
||||
|
@ -577,13 +578,21 @@ static void test_readdirectorychanges(void)
|
|||
ok( r == WAIT_OBJECT_0, "should be ready\n" );
|
||||
|
||||
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
|
||||
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
|
||||
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
|
||||
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
|
||||
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
|
||||
/* we may get a notification for the parent dir too */
|
||||
if (pfni->Action == FILE_ACTION_MODIFIED && pfni->NextEntryOffset)
|
||||
{
|
||||
ok( pfni->FileNameLength == 3*sizeof(WCHAR), "len wrong %u\n", pfni->FileNameLength );
|
||||
ok( !memcmp(pfni->FileName,&szGa[1],3*sizeof(WCHAR)), "name wrong\n" );
|
||||
pfni = (PFILE_NOTIFY_INFORMATION)((char *)pfni + pfni->NextEntryOffset);
|
||||
}
|
||||
ok( pfni->NextEntryOffset == 0, "offset wrong %u\n", pfni->NextEntryOffset );
|
||||
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong %u\n", pfni->Action );
|
||||
ok( pfni->FileNameLength == 6*sizeof(WCHAR), "len wrong %u\n", pfni->FileNameLength );
|
||||
ok( !memcmp(pfni->FileName,&szGa[1],6*sizeof(WCHAR)), "name wrong\n" );
|
||||
|
||||
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
|
||||
ok( ov.InternalHigh == 0x18, "ov.InternalHigh wrong\n");
|
||||
dwCount = (char *)&pfni->FileName[pfni->FileNameLength/sizeof(WCHAR)] - buffer;
|
||||
ok( ov.InternalHigh == dwCount, "ov.InternalHigh wrong %lu/%u\n",ov.InternalHigh, dwCount );
|
||||
|
||||
CloseHandle(hdir);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Unit tests for code page to/from unicode translations
|
||||
*
|
||||
* Copyright (c) 2002 Dmitry Timoshkov
|
||||
* Copyright (c) 2008 Colin Finck
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -203,17 +204,165 @@ static void test_overlapped_buffers(void)
|
|||
char buf[256];
|
||||
int ret;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memcpy((WCHAR *)(buf + 1), strW, sizeof(strW));
|
||||
ret = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)(buf + 1), -1, buf, sizeof(buf), NULL, NULL);
|
||||
ok(ret == sizeof(strA), "unexpected ret %d\n", ret);
|
||||
ok(!memcmp(buf, strA, sizeof(strA)), "conversion failed: %s\n", buf);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_string_conversion(LPBOOL bUsedDefaultChar)
|
||||
{
|
||||
char mbc;
|
||||
char mbs[5];
|
||||
int ret;
|
||||
WCHAR wc1 = 228; /* Western Windows-1252 character */
|
||||
WCHAR wc2 = 1088; /* Russian Windows-1251 character not displayable for Windows-1252 */
|
||||
WCHAR wcs[5] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */
|
||||
WCHAR dbwcs[3] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 1, "ret is %d\n", ret);
|
||||
ok(mbc == -28, "mbc is %d\n", mbc);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 1, "ret is %d\n", ret);
|
||||
ok(mbc == 63, "mbc is %d\n", mbc);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
if (IsValidCodePage(1251))
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1251, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 1, "ret is %d\n", ret);
|
||||
ok(mbc == -16, "mbc is %d\n", mbc);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef ||
|
||||
broken(GetLastError() == 0), /* win95 */
|
||||
"GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1251, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 1, "ret is %d\n", ret);
|
||||
ok(mbc == 97, "mbc is %d\n", mbc);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
}
|
||||
else
|
||||
skip("Codepage 1251 not available\n");
|
||||
|
||||
/* This call triggers the last Win32 error */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, wcs, -1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 0, "ret is %d\n", ret);
|
||||
ok(mbc == 84, "mbc is %d\n", mbc);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, wcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 5, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
mbs[0] = 0;
|
||||
|
||||
/* WideCharToMultiByte mustn't add any null character automatically.
|
||||
So in this case, we should get the same string again, even if we only copied the first three bytes. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 3, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
ZeroMemory(mbs, 5);
|
||||
|
||||
/* Now this shouldn't be the case like above as we zeroed the complete string buffer. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 3, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "Th?"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
/* Double-byte tests */
|
||||
ret = WideCharToMultiByte(1252, 0, dbwcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 3, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "??"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
|
||||
/* Length-only tests */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, &wc2, 1, NULL, 0, NULL, bUsedDefaultChar);
|
||||
ok(ret == 1, "ret is %d\n", ret);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, wcs, -1, NULL, 0, NULL, bUsedDefaultChar);
|
||||
ok(ret == 5, "ret is %d\n", ret);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
if (!IsValidCodePage(950))
|
||||
{
|
||||
skip("Codepage 950 not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Double-byte tests */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(950, 0, dbwcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 5, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "µH©Ò"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(950, 0, dbwcs, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
ok(ret == 0, "ret is %d\n", ret);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError());
|
||||
ZeroMemory(mbs, 5);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(950, 0, dbwcs, 1, mbs, sizeof(mbs), NULL, bUsedDefaultChar);
|
||||
ok(ret == 2, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "µH"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
/* Length-only tests */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(950, 0, dbwcs, 1, NULL, 0, NULL, bUsedDefaultChar);
|
||||
ok(ret == 2, "ret is %d\n", ret);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(950, 0, dbwcs, -1, NULL, 0, NULL, bUsedDefaultChar);
|
||||
ok(ret == 5, "ret is %d\n", ret);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(codepage)
|
||||
{
|
||||
BOOL bUsedDefaultChar;
|
||||
|
||||
test_destination_buffer();
|
||||
test_null_source();
|
||||
test_negative_source_length();
|
||||
test_negative_dest_length();
|
||||
test_overlapped_buffers();
|
||||
|
||||
/* WideCharToMultiByte has two code paths, test both here */
|
||||
test_string_conversion(NULL);
|
||||
test_string_conversion(&bUsedDefaultChar);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define TIMEOUT 1000 /* one second for Timeouts*/
|
||||
#define SLOWBAUD 150
|
||||
#define FASTBAUD 115200
|
||||
#define TIMEDELTA 100 /* 100 ms uncertainty allowed */
|
||||
#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
|
||||
|
||||
/* Define the appropriate LOOPBACK(s) TRUE if you have a Loopback cable with
|
||||
* the mentioned shorts connected to your Serial port
|
||||
|
|
|
@ -130,6 +130,49 @@ static void testCursor(HANDLE hCon, COORD sbSize)
|
|||
ERROR_INVALID_PARAMETER, GetLastError());
|
||||
}
|
||||
|
||||
static void testCursorInfo(HANDLE hCon)
|
||||
{
|
||||
BOOL ret;
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetConsoleCursorInfo(NULL, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
|
||||
ERROR_INVALID_HANDLE, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
info.dwSize = -1;
|
||||
ret = GetConsoleCursorInfo(NULL, &info);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(info.dwSize == -1, "Expected no change for dwSize\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
|
||||
ERROR_INVALID_HANDLE, GetLastError());
|
||||
|
||||
/* Test the correct call first to distinguish between win9x and the rest */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetConsoleCursorInfo(hCon, &info);
|
||||
ok(ret, "Expected success\n");
|
||||
ok(info.dwSize == 25 ||
|
||||
info.dwSize == 12 /* win9x */,
|
||||
"Expected 12 or 25, got %d\n", info.dwSize);
|
||||
ok(info.bVisible, "Expected the cursor to be visible\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
|
||||
0xdeadbeef, GetLastError());
|
||||
|
||||
if (info.dwSize == 12)
|
||||
{
|
||||
skip("NULL CONSOLE_CURSOR_INFO will crash on win9x\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetConsoleCursorInfo(hCon, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ok(GetLastError() == ERROR_INVALID_ACCESS, "GetLastError: expecting %u got %u\n",
|
||||
ERROR_INVALID_ACCESS, GetLastError());
|
||||
}
|
||||
|
||||
static void testWriteSimple(HANDLE hCon, COORD sbSize)
|
||||
{
|
||||
COORD c;
|
||||
|
@ -863,6 +906,8 @@ START_TEST(console)
|
|||
|
||||
/* Non interactive tests */
|
||||
testCursor(hConOut, sbi.dwSize);
|
||||
/* test parameters (FIXME: test functionality) */
|
||||
testCursorInfo(hConOut);
|
||||
/* will test wrapped (on/off) & processed (on/off) strings output */
|
||||
testWrite(hConOut, sbi.dwSize);
|
||||
/* will test line scrolling at the bottom of the screen */
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#include <winreg.h>
|
||||
#include <ntndk.h>
|
||||
|
@ -137,6 +139,7 @@ static void doDebugger(int argc, char** argv)
|
|||
logfile=(argc >= 4 ? argv[3] : NULL);
|
||||
blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0);
|
||||
|
||||
blackbox.attach_err=0;
|
||||
if (strstr(myARGV[2], "attach"))
|
||||
{
|
||||
blackbox.attach_rc=DebugActiveProcess(blackbox.pid);
|
||||
|
@ -147,6 +150,7 @@ static void doDebugger(int argc, char** argv)
|
|||
blackbox.attach_rc=TRUE;
|
||||
|
||||
debug_event=(argc >= 6 ? (HANDLE)atol(argv[5]) : NULL);
|
||||
blackbox.debug_err=0;
|
||||
if (debug_event && strstr(myARGV[2], "event"))
|
||||
{
|
||||
blackbox.debug_rc=SetEvent(debug_event);
|
||||
|
@ -156,13 +160,18 @@ static void doDebugger(int argc, char** argv)
|
|||
else
|
||||
blackbox.debug_rc=TRUE;
|
||||
|
||||
get_events(logfile, &start_event, &done_event);
|
||||
if (logfile)
|
||||
{
|
||||
get_events(logfile, &start_event, &done_event);
|
||||
}
|
||||
|
||||
if (strstr(myARGV[2], "order"))
|
||||
{
|
||||
trace("debugger: waiting for the start signal...\n");
|
||||
WaitForSingleObject(start_event, INFINITE);
|
||||
}
|
||||
|
||||
blackbox.nokill_err=0;
|
||||
if (strstr(myARGV[2], "nokill"))
|
||||
{
|
||||
blackbox.nokill_rc=pDebugSetProcessKillOnExit(FALSE);
|
||||
|
@ -172,6 +181,7 @@ static void doDebugger(int argc, char** argv)
|
|||
else
|
||||
blackbox.nokill_rc=TRUE;
|
||||
|
||||
blackbox.detach_err=0;
|
||||
if (strstr(myARGV[2], "detach"))
|
||||
{
|
||||
blackbox.detach_rc=pDebugActiveProcessStop(blackbox.pid);
|
||||
|
@ -181,7 +191,10 @@ static void doDebugger(int argc, char** argv)
|
|||
else
|
||||
blackbox.detach_rc=TRUE;
|
||||
|
||||
save_blackbox(logfile, &blackbox, sizeof(blackbox));
|
||||
if (logfile)
|
||||
{
|
||||
save_blackbox(logfile, &blackbox, sizeof(blackbox));
|
||||
}
|
||||
trace("debugger: done debugging...\n");
|
||||
SetEvent(done_event);
|
||||
|
||||
|
@ -241,7 +254,9 @@ static void crash_and_debug(HKEY hkey, const char* argv0, const char* dbgtasks)
|
|||
"wrong exit code : %08x\n", exit_code);
|
||||
}
|
||||
else
|
||||
ok(exit_code == STATUS_ACCESS_VIOLATION, "exit code = %08x instead of STATUS_ACCESS_VIOLATION\n", exit_code);
|
||||
ok(exit_code == STATUS_ACCESS_VIOLATION ||
|
||||
exit_code == WAIT_ABANDONED, /* win2k3 */
|
||||
"exit code = %08x instead of STATUS_ACCESS_VIOLATION or WAIT_ABANDONED\n", exit_code);
|
||||
CloseHandle(info.hProcess);
|
||||
|
||||
/* ...before the debugger */
|
||||
|
@ -333,6 +348,7 @@ static void test_ExitCode(void)
|
|||
{
|
||||
debugger_val=HeapAlloc(GetProcessHeap(), 0, debugger_size);
|
||||
RegQueryValueExA(hkey, "debugger", NULL, &debugger_type, debugger_val, &debugger_size);
|
||||
trace("HKLM\\%s\\debugger is set to '%s'\n", AeDebug, debugger_val);
|
||||
}
|
||||
}
|
||||
else if (ret == ERROR_ACCESS_DENIED)
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winnls.h"
|
||||
|
||||
static CHAR string[MAX_PATH];
|
||||
#define ok_w(res, format, szString) \
|
||||
\
|
||||
WideCharToMultiByte(CP_ACP, 0, szString, -1, string, MAX_PATH, NULL, NULL); \
|
||||
ok(res, format, string);
|
||||
|
||||
static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
|
||||
static BOOL (WINAPI *pGetComputerNameExW)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD);
|
||||
|
@ -156,7 +163,9 @@ static void test_GetSetEnvironmentVariableW(void)
|
|||
|
||||
lstrcpyW(buf, fooW);
|
||||
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value));
|
||||
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
|
||||
ok_w(lstrcmpW(buf, fooW) == 0 ||
|
||||
lstrlenW(buf) == 0, /* Vista */
|
||||
"Expected untouched or empty buffer, got \"%s\"\n", buf);
|
||||
|
||||
ok(ret_size == lstrlenW(value) + 1,
|
||||
"should return length with terminating 0 ret_size=%d\n", ret_size);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Unit tests for file functions in Wine
|
||||
*
|
||||
* Copyright (c) 2002, 2004 Jakob Eriksson
|
||||
* Copyright (c) 2008 Jeff Zaroyko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -23,9 +24,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/* ReplaceFile requires Windows 2000 or newer */
|
||||
#define _WIN32_WINNT 0x0500
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -777,6 +775,16 @@ static void test_CreateFileW(void)
|
|||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"CreateFileW on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
|
||||
|
||||
ret = CreateDirectoryW(filename, NULL);
|
||||
ok(ret == TRUE, "couldn't create temporary directory\n");
|
||||
hFile = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
ok(hFile != INVALID_HANDLE_VALUE,
|
||||
"expected CreateFile to succeed on existing directory, error: %d\n", GetLastError());
|
||||
CloseHandle(hFile);
|
||||
ret = RemoveDirectoryW(filename);
|
||||
ok(ret, "DeleteFileW: error %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_GetTempFileNameA(void)
|
||||
|
@ -841,6 +849,10 @@ static void test_DeleteFileA( void )
|
|||
static void test_DeleteFileW( void )
|
||||
{
|
||||
BOOL ret;
|
||||
WCHAR pathW[MAX_PATH];
|
||||
WCHAR pathsubW[MAX_PATH];
|
||||
static const WCHAR dirW[] = {'d','e','l','e','t','e','f','i','l','e',0};
|
||||
static const WCHAR subdirW[] = {'\\','s','u','b',0};
|
||||
static const WCHAR emptyW[]={'\0'};
|
||||
|
||||
ret = DeleteFileW(NULL);
|
||||
|
@ -852,6 +864,35 @@ static void test_DeleteFileW( void )
|
|||
ret = DeleteFileW(emptyW);
|
||||
ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
|
||||
"DeleteFileW(\"\") returned ret=%d error=%d\n",ret,GetLastError());
|
||||
|
||||
/* test DeleteFile on empty directory */
|
||||
ret = GetTempPathW(MAX_PATH, pathW);
|
||||
if (ret + sizeof(dirW)/sizeof(WCHAR)-1 + sizeof(subdirW)/sizeof(WCHAR)-1 >= MAX_PATH)
|
||||
{
|
||||
ok(0, "MAX_PATH exceeded in constructing paths\n");
|
||||
return;
|
||||
}
|
||||
lstrcatW(pathW, dirW);
|
||||
lstrcpyW(pathsubW, pathW);
|
||||
lstrcatW(pathsubW, subdirW);
|
||||
ret = CreateDirectoryW(pathW, NULL);
|
||||
ok(ret == TRUE, "couldn't create directory deletefile\n");
|
||||
ret = DeleteFileW(pathW);
|
||||
ok(ret == FALSE, "DeleteFile should fail for empty directories\n");
|
||||
ret = RemoveDirectoryW(pathW);
|
||||
ok(ret == TRUE, "expected to remove directory deletefile\n");
|
||||
|
||||
/* test DeleteFile on non-empty directory */
|
||||
ret = CreateDirectoryW(pathW, NULL);
|
||||
ok(ret == TRUE, "couldn't create directory deletefile\n");
|
||||
ret = CreateDirectoryW(pathsubW, NULL);
|
||||
ok(ret == TRUE, "couldn't create directory deletefile\\sub\n");
|
||||
ret = DeleteFileW(pathW);
|
||||
ok(ret == FALSE, "DeleteFile should fail for non-empty directories\n");
|
||||
ret = RemoveDirectoryW(pathsubW);
|
||||
ok(ret == TRUE, "expected to remove directory deletefile\\sub\n");
|
||||
ret = RemoveDirectoryW(pathW);
|
||||
ok(ret == TRUE, "expected to remove directory deletefile\n");
|
||||
}
|
||||
|
||||
#define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
|
||||
|
@ -1038,6 +1079,7 @@ static void test_LockFile(void)
|
|||
OVERLAPPED overlapped;
|
||||
int limited_LockFile;
|
||||
int limited_UnLockFile;
|
||||
BOOL ret;
|
||||
|
||||
handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
|
@ -1097,10 +1139,15 @@ static void test_LockFile(void)
|
|||
"UnlockFileEx 150,100 again succeeded\n" );
|
||||
}
|
||||
|
||||
ok( LockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "LockFile failed\n" );
|
||||
ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
|
||||
ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
|
||||
ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
|
||||
ret = LockFile( handle, 0, 0x10000000, 0, 0xf0000000 );
|
||||
if (ret)
|
||||
{
|
||||
ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded\n" );
|
||||
ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded\n" );
|
||||
ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed\n" );
|
||||
}
|
||||
else /* win9x */
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong LockFile error %u\n", GetLastError() );
|
||||
|
||||
/* wrap-around lock should not do anything */
|
||||
/* (but still succeeds on NT4 so we don't check result) */
|
||||
|
@ -1351,9 +1398,14 @@ static void test_FindFirstFileA(void)
|
|||
err = GetLastError();
|
||||
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
|
||||
ok( 0 == lstrcmpiA(data.cFileName, "nul"), "wrong name %s\n", data.cFileName );
|
||||
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
|
||||
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
|
||||
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
|
||||
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
|
||||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
|
||||
"wrong attributes %x\n", data.dwFileAttributes );
|
||||
if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
|
||||
{
|
||||
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
|
||||
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
|
||||
}
|
||||
SetLastError( 0xdeadbeaf );
|
||||
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
|
||||
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
|
||||
|
@ -1366,9 +1418,14 @@ static void test_FindFirstFileA(void)
|
|||
err = GetLastError();
|
||||
ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s failed\n", buffer2 );
|
||||
ok( 0 == lstrcmpiA(data.cFileName, "lpt1"), "wrong name %s\n", data.cFileName );
|
||||
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
|
||||
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
|
||||
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes, "wrong attributes %x\n", data.dwFileAttributes );
|
||||
ok( FILE_ATTRIBUTE_ARCHIVE == data.dwFileAttributes ||
|
||||
FILE_ATTRIBUTE_DEVICE == data.dwFileAttributes /* Win9x */,
|
||||
"wrong attributes %x\n", data.dwFileAttributes );
|
||||
if (data.dwFileAttributes == FILE_ATTRIBUTE_ARCHIVE)
|
||||
{
|
||||
ok( 0 == data.nFileSizeHigh, "wrong size %d\n", data.nFileSizeHigh );
|
||||
ok( 0 == data.nFileSizeLow, "wrong size %d\n", data.nFileSizeLow );
|
||||
}
|
||||
SetLastError( 0xdeadbeaf );
|
||||
ok( !FindNextFileA( handle, &data ), "FindNextFileA succeeded\n" );
|
||||
ok( GetLastError() == ERROR_NO_MORE_FILES, "bad error %d\n", GetLastError() );
|
||||
|
@ -1446,7 +1503,13 @@ static void test_FindFirstFileExA(void)
|
|||
_lclose(_lcreat("test-dir\\file2", 0));
|
||||
CreateDirectoryA("test-dir\\dir1", NULL);
|
||||
/* FindExLimitToDirectories is ignored */
|
||||
SetLastError(0xdeadbeef);
|
||||
handle = pFindFirstFileExA("test-dir\\*", FindExInfoStandard, &search_results, FindExSearchLimitToDirectories, NULL, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
skip("FindFirstFileExA is not implemented\n");
|
||||
goto cleanup;
|
||||
}
|
||||
ok(handle != INVALID_HANDLE_VALUE, "FindFirstFile failed (err=%u)\n", GetLastError());
|
||||
ok(strcmp(search_results.cFileName, ".") == 0, "First entry should be '.', is %s\n", search_results.cFileName);
|
||||
|
||||
|
@ -1456,7 +1519,7 @@ static void test_FindFirstFileExA(void)
|
|||
ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
|
||||
|
||||
ok(FindNextFile(handle, &search_results), "Fetching third file failed\n");
|
||||
ok(CHECK_NAME(search_results.cFileName), "Invalid thrid entry - %s\n", search_results.cFileName);
|
||||
ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
|
||||
|
||||
ok(FindNextFile(handle, &search_results), "Fetching fourth file failed\n");
|
||||
ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
|
||||
|
@ -1467,6 +1530,10 @@ static void test_FindFirstFileExA(void)
|
|||
#undef CHECK_NAME
|
||||
|
||||
ok(FindNextFile(handle, &search_results) == FALSE, "Fetching sixth file should failed\n");
|
||||
|
||||
FindClose( handle );
|
||||
|
||||
cleanup:
|
||||
DeleteFileA("test-dir\\file1");
|
||||
DeleteFileA("test-dir\\file2");
|
||||
RemoveDirectoryA("test-dir\\dir1");
|
||||
|
@ -1514,12 +1581,16 @@ static void test_MapFile(void)
|
|||
ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
|
||||
|
||||
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
|
||||
ok( hmap == NULL, "mapping should fail\n");
|
||||
ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
|
||||
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
|
||||
if ( hmap )
|
||||
CloseHandle( hmap );
|
||||
|
||||
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
|
||||
ok( hmap == NULL, "mapping should fail\n");
|
||||
ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
|
||||
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
|
||||
if ( hmap )
|
||||
CloseHandle( hmap );
|
||||
|
||||
/* On XP you can now map again, on Win 95 you cannot. */
|
||||
|
||||
|
@ -1566,18 +1637,25 @@ static void test_async_file_errors(void)
|
|||
szFile[0] = '\0';
|
||||
GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
|
||||
strcat(szFile, "\\win.ini");
|
||||
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
|
||||
ok(hFile != NULL, "CreateFileA(%s ...) failed\n", szFile);
|
||||
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) /* win9x doesn't like FILE_SHARE_DELETE */
|
||||
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
|
||||
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA(%s ...) failed\n", szFile);
|
||||
while (TRUE)
|
||||
{
|
||||
BOOL res;
|
||||
DWORD count;
|
||||
while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
|
||||
;
|
||||
res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
|
||||
/*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
|
||||
if (!res)
|
||||
break;
|
||||
S(U(ovl)).Offset += 4096;
|
||||
if (!GetOverlappedResult(hFile, &ovl, &count, FALSE))
|
||||
break;
|
||||
S(U(ovl)).Offset += count;
|
||||
/* i/o completion routine only called if ReadFileEx returned success.
|
||||
* we only care about violations of this rule so undo what should have
|
||||
* been done */
|
||||
|
@ -1585,6 +1663,7 @@ static void test_async_file_errors(void)
|
|||
}
|
||||
ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
|
||||
/*printf("Error = %ld\n", GetLastError());*/
|
||||
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
||||
}
|
||||
|
||||
static void test_read_write(void)
|
||||
|
@ -1655,26 +1734,28 @@ static void test_OpenFile(void)
|
|||
BOOL ret;
|
||||
DWORD retval;
|
||||
|
||||
static const char *file = "\\regsvr32.exe";
|
||||
static const char *foo = ".\\foo-bar-foo.baz";
|
||||
static const char file[] = "regedit.exe";
|
||||
static const char foo[] = ".\\foo-bar-foo.baz";
|
||||
static const char *foo_too_long = ".\\foo-bar-foo.baz+++++++++++++++"
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
|
||||
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
|
||||
static const char *backslash = "\\";
|
||||
char buff[MAX_PATH];
|
||||
char buff_long[4*MAX_PATH];
|
||||
char filled_0xA5[OFS_MAXPATHNAME];
|
||||
char *p;
|
||||
UINT length;
|
||||
|
||||
/* Check for existing file */
|
||||
length = GetSystemDirectoryA(buff, MAX_PATH);
|
||||
length = GetWindowsDirectoryA(buff, MAX_PATH);
|
||||
|
||||
if (length + lstrlen(file) < MAX_PATH)
|
||||
if (length + sizeof(file) < MAX_PATH)
|
||||
{
|
||||
lstrcatA(buff, file);
|
||||
p = buff + strlen(buff);
|
||||
if (p > buff && p[-1] != '\\') *p++ = '\\';
|
||||
strcpy( p, file );
|
||||
memset(&ofs, 0xA5, sizeof(ofs));
|
||||
SetLastError(0xfaceabee);
|
||||
|
||||
|
@ -1693,9 +1774,11 @@ static void test_OpenFile(void)
|
|||
length = GetCurrentDirectoryA(MAX_PATH, buff);
|
||||
|
||||
/* Check for nonexistent file */
|
||||
if (length + lstrlenA(foo + 1) < MAX_PATH)
|
||||
if (length + sizeof(foo) < MAX_PATH)
|
||||
{
|
||||
lstrcatA(buff, foo + 1); /* Avoid '.' during concatenation */
|
||||
p = buff + strlen(buff);
|
||||
if (p > buff && p[-1] != '\\') *p++ = '\\';
|
||||
strcpy( p, foo + 2 );
|
||||
memset(&ofs, 0xA5, sizeof(ofs));
|
||||
SetLastError(0xfaceabee);
|
||||
|
||||
|
@ -1733,17 +1816,16 @@ static void test_OpenFile(void)
|
|||
ofs.szPathName );
|
||||
}
|
||||
|
||||
length = GetCurrentDirectoryA(MAX_PATH, buff);
|
||||
length += lstrlenA(backslash);
|
||||
length += lstrlenA(filename);
|
||||
length = GetCurrentDirectoryA(MAX_PATH, buff) + sizeof(filename);
|
||||
|
||||
if (length >= MAX_PATH)
|
||||
{
|
||||
trace("Buffer too small, requested length = %d, but MAX_PATH = %d. Skipping test.\n", length, MAX_PATH);
|
||||
return;
|
||||
}
|
||||
lstrcatA(buff, backslash);
|
||||
lstrcatA(buff, filename);
|
||||
p = buff + strlen(buff);
|
||||
if (p > buff && p[-1] != '\\') *p++ = '\\';
|
||||
strcpy( p, filename );
|
||||
|
||||
memset(&ofs, 0xA5, sizeof(ofs));
|
||||
SetLastError(0xfaceabee);
|
||||
|
@ -1753,7 +1835,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ret = CloseHandle((HANDLE)hFile);
|
||||
ok( ret == TRUE, "CloseHandle() returns %d\n", ret );
|
||||
retval = GetFileAttributesA(filename);
|
||||
|
@ -1768,7 +1851,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
|
||||
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
|
||||
ret = CloseHandle((HANDLE)hFile);
|
||||
|
@ -1782,7 +1866,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
|
||||
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
|
||||
ret = CloseHandle((HANDLE)hFile);
|
||||
|
@ -1796,7 +1881,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
|
||||
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
|
||||
ret = CloseHandle((HANDLE)hFile);
|
||||
|
@ -1810,7 +1896,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
|
||||
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
|
||||
|
||||
|
@ -1822,7 +1909,8 @@ static void test_OpenFile(void)
|
|||
ok( GetLastError() == 0xfaceabee || GetLastError() == ERROR_SUCCESS,
|
||||
"GetLastError() returns %d\n", GetLastError() );
|
||||
ok( ofs.cBytes == sizeof(OFSTRUCT), "OpenFile set ofs.cBytes to %d\n", ofs.cBytes );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS, "OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( ofs.nErrCode == ERROR_SUCCESS || broken(ofs.nErrCode != ERROR_SUCCESS) /* win9x */,
|
||||
"OpenFile set ofs.nErrCode to %d\n", ofs.nErrCode );
|
||||
ok( lstrcmpiA(ofs.szPathName, buff) == 0,
|
||||
"OpenFile returned '%s', but was expected to return '%s'\n", ofs.szPathName, buff );
|
||||
|
||||
|
@ -1840,15 +1928,19 @@ static void test_overlapped(void)
|
|||
memset( &ov, 0, sizeof ov );
|
||||
result = 1;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( r == TRUE, "should return false\n");
|
||||
ok( result == 0, "wrong result %u\n", result );
|
||||
if (r)
|
||||
ok( result == 0, "wrong result %u\n", result );
|
||||
else /* win9x */
|
||||
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
|
||||
result = 0;
|
||||
ov.Internal = 0;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( r == TRUE, "should return false\n");
|
||||
ok( result == 0xabcd, "wrong result %u\n", result );
|
||||
if (r)
|
||||
ok( result == 0xabcd, "wrong result %u\n", result );
|
||||
else /* win9x */
|
||||
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xb00 );
|
||||
result = 0;
|
||||
|
@ -1857,14 +1949,15 @@ static void test_overlapped(void)
|
|||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
ok( r == FALSE, "should return false\n");
|
||||
ok( result == 0xabcd, "wrong result %u\n", result );
|
||||
ok( result == 0xabcd || result == 0 /* win9x */, "wrong result %u\n", result );
|
||||
|
||||
SetLastError( 0xb00 );
|
||||
result = 0;
|
||||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
|
||||
"wrong error %u\n", GetLastError() );
|
||||
ok( r == FALSE, "should return false\n");
|
||||
ok( result == 0, "wrong result %u\n", result );
|
||||
|
||||
|
@ -1873,7 +1966,8 @@ static void test_overlapped(void)
|
|||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
|
||||
"wrong error %u\n", GetLastError() );
|
||||
ok( r == FALSE, "should return false\n");
|
||||
|
||||
ResetEvent( ov.hEvent );
|
||||
|
@ -1882,7 +1976,8 @@ static void test_overlapped(void)
|
|||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_IO_INCOMPLETE || GetLastError() == ERROR_INVALID_HANDLE /* win9x */,
|
||||
"wrong error %u\n", GetLastError() );
|
||||
ok( r == FALSE, "should return false\n");
|
||||
|
||||
r = CloseHandle( ov.hEvent );
|
||||
|
@ -1901,19 +1996,23 @@ static void test_RemoveDirectory(void)
|
|||
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
|
||||
|
||||
rc = RemoveDirectory(".");
|
||||
todo_wine {
|
||||
ok( !rc, "RemoveDirectory unexpectedly worked\n" );
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
rc = SetCurrentDirectory("..");
|
||||
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
|
||||
|
||||
rc = SetCurrentDirectory("..");
|
||||
ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
|
||||
|
||||
rc = RemoveDirectory(directory);
|
||||
todo_wine {
|
||||
ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
|
||||
rc = RemoveDirectory(directory);
|
||||
ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL check_file_time( const FILETIME *ft1, const FILETIME *ft2, UINT tolerance )
|
||||
{
|
||||
ULONGLONG t1 = ((ULONGLONG)ft1->dwHighDateTime << 32) | ft1->dwLowDateTime;
|
||||
ULONGLONG t2 = ((ULONGLONG)ft2->dwHighDateTime << 32) | ft2->dwLowDateTime;
|
||||
return abs(t1 - t2) <= tolerance;
|
||||
}
|
||||
|
||||
static void test_ReplaceFileA(void)
|
||||
{
|
||||
char replaced[MAX_PATH], replacement[MAX_PATH], backup[MAX_PATH];
|
||||
|
@ -2021,14 +2120,15 @@ static void test_ReplaceFileA(void)
|
|||
/* make sure that the backup has the old "replaced" filetime */
|
||||
ret = GetFileTime(hBackupFile, NULL, NULL, &ftBackup);
|
||||
ok( ret, "GetFileTime error (backup %d\n", GetLastError());
|
||||
ok(CompareFileTime(&ftBackup, &ftReplaced) == 0,
|
||||
"backup file has wrong filetime\n");
|
||||
ok(check_file_time(&ftBackup, &ftReplaced, 20000000), "backup file has wrong filetime\n");
|
||||
CloseHandle(hBackupFile);
|
||||
/* make sure that the "replaced" has the old replacement filetime */
|
||||
ret = GetFileTime(hReplacedFile, NULL, NULL, &ftReplaced);
|
||||
ok( ret, "GetFileTime error (backup %d\n", GetLastError());
|
||||
ok(CompareFileTime(&ftReplaced, &ftReplacement) == 0,
|
||||
"replaced file has wrong filetime\n");
|
||||
ok(check_file_time(&ftReplaced, &ftReplacement, 20000000),
|
||||
"replaced file has wrong filetime %x%08x / %x%08x\n",
|
||||
ftReplaced.dwHighDateTime, ftReplaced.dwLowDateTime,
|
||||
ftReplacement.dwHighDateTime, ftReplacement.dwLowDateTime );
|
||||
CloseHandle(hReplacedFile);
|
||||
|
||||
/* re-create replacement file for pass w/o backup (blank) */
|
||||
|
@ -2066,7 +2166,8 @@ static void test_ReplaceFileA(void)
|
|||
ok(ret != ERROR_UNABLE_TO_REMOVE_REPLACED, "ReplaceFileA: unexpected error %d\n", GetLastError());
|
||||
/* make sure that the replacement file still exists */
|
||||
hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
||||
ok(hReplacementFile != INVALID_HANDLE_VALUE,
|
||||
ok(hReplacementFile != INVALID_HANDLE_VALUE ||
|
||||
broken(GetLastError() == ERROR_FILE_NOT_FOUND), /* win2k */
|
||||
"unexpected error, replacement file should still exist %d\n", GetLastError());
|
||||
CloseHandle(hReplacementFile);
|
||||
ret = SetFileAttributesA(replaced, FILE_ATTRIBUTE_NORMAL);
|
||||
|
@ -2099,7 +2200,9 @@ static void test_ReplaceFileA(void)
|
|||
|
||||
/* delete temporary files, replacement and replaced are already deleted */
|
||||
ret = DeleteFileA(backup);
|
||||
ok(ret, "DeleteFileA: error (backup) %d\n", GetLastError());
|
||||
ok(ret ||
|
||||
broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
|
||||
"DeleteFileA: error (backup) %d\n", GetLastError());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2170,7 +2273,9 @@ static void test_ReplaceFileW(void)
|
|||
"ReplaceFileW: unexpected error %d\n", GetLastError());
|
||||
|
||||
ret = DeleteFileW(backup);
|
||||
ok(ret, "DeleteFileW: error %d\n", GetLastError());
|
||||
ok(ret ||
|
||||
broken(GetLastError() == ERROR_ACCESS_DENIED), /* win2k */
|
||||
"DeleteFileW: error (backup) %d\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
|
|
|
@ -228,7 +228,9 @@ static void test_message_null_buffer(void)
|
|||
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);
|
||||
error = GetLastError();
|
||||
ok(!ret, "FormatMessageA returned %u\n", ret);
|
||||
ok(error == ERROR_NOT_ENOUGH_MEMORY, "last error %u\n", error);
|
||||
ok(error == ERROR_NOT_ENOUGH_MEMORY ||
|
||||
error == ERROR_INVALID_PARAMETER, /* win9x */
|
||||
"last error %u\n", error);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 0, 0, NULL, 0, NULL);
|
||||
|
|
|
@ -72,6 +72,13 @@ START_TEST(heap)
|
|||
mem = HeapAlloc(GetProcessHeap(), 0, ~0UL);
|
||||
ok(mem == NULL, "memory allocated for size ~0UL\n");
|
||||
|
||||
/* large blocks must be 16-byte aligned */
|
||||
mem = HeapAlloc(GetProcessHeap(), 0, 512 * 1024);
|
||||
ok( mem != NULL, "failed for size 512K\n" );
|
||||
ok( (ULONG_PTR)mem % 16 == 0 || broken((ULONG_PTR)mem % 16) /* win9x */,
|
||||
"512K block not 16-byte aligned\n" );
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
|
||||
/* Global*() functions */
|
||||
gbl = GlobalAlloc(GMEM_MOVEABLE, 0);
|
||||
ok(gbl != NULL, "global memory not allocated for size 0\n");
|
||||
|
@ -185,24 +192,31 @@ START_TEST(heap)
|
|||
/* invalid free */
|
||||
SetLastError(MAGIC_DEAD);
|
||||
mem = GlobalFree(gbl);
|
||||
ok(mem == gbl, "Expected gbl, got %p\n", mem);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE,
|
||||
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||
ok(mem == gbl || broken(mem == NULL) /* nt4 */, "Expected gbl, got %p\n", mem);
|
||||
if (mem == gbl)
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
|
||||
"Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
gbl = GlobalAlloc(GMEM_DDESHARE, 100);
|
||||
|
||||
res = GlobalUnlock(gbl);
|
||||
ok(res == 1, "Expected 1, got %d\n", res);
|
||||
ok(res == 1 ||
|
||||
res == 0, /* win9x */
|
||||
"Expected 1 or 0, got %d\n", res);
|
||||
|
||||
res = GlobalUnlock(gbl);
|
||||
ok(res == 1, "Expected 1, got %d\n", res);
|
||||
ok(res == 1 ||
|
||||
res == 0, /* win9x */
|
||||
"Expected 1 or 0, got %d\n", res);
|
||||
|
||||
/* GlobalSize on an invalid handle */
|
||||
SetLastError(MAGIC_DEAD);
|
||||
size = GlobalSize((HGLOBAL)0xc042);
|
||||
ok(size == 0, "Expected 0, got %ld\n", size);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE,
|
||||
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
|
||||
"Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
/* ####################################### */
|
||||
/* Local*() functions */
|
||||
|
|
|
@ -27,6 +27,13 @@
|
|||
|
||||
#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
|
||||
|
||||
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
|
||||
{
|
||||
if (rva == 0)
|
||||
return NULL;
|
||||
return ((char*) module) + rva;
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
WORD e_magic; /* 00: MZ Header signature */
|
||||
|
@ -103,7 +110,7 @@ static IMAGE_SECTION_HEADER section =
|
|||
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
|
||||
};
|
||||
|
||||
START_TEST(loader)
|
||||
static void test_Loader(void)
|
||||
{
|
||||
static const struct test_data
|
||||
{
|
||||
|
@ -113,6 +120,7 @@ START_TEST(loader)
|
|||
DWORD section_alignment, file_alignment;
|
||||
DWORD size_of_image, size_of_headers;
|
||||
DWORD error; /* 0 means LoadLibrary should succeed */
|
||||
DWORD alt_error; /* alternate error */
|
||||
} td[] =
|
||||
{
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
|
@ -141,7 +149,7 @@ START_TEST(loader)
|
|||
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
|
||||
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
|
||||
sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_INVALID_ADDRESS /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
|
||||
|
@ -168,25 +176,25 @@ START_TEST(loader)
|
|||
1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
|
||||
sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER),
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
0xd0, /* beyond of the end of file */
|
||||
0xc0, /* beyond of the end of file */
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
0x1000,
|
||||
0,
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
1,
|
||||
0,
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
#if 0 /* not power of 2 alignments need more test cases */
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
|
@ -200,13 +208,13 @@ START_TEST(loader)
|
|||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
|
||||
1,
|
||||
0,
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1,
|
||||
1,
|
||||
0,
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
},
|
||||
{ &dos_header, sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
|
@ -227,7 +235,7 @@ START_TEST(loader)
|
|||
0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
|
||||
1,
|
||||
0,
|
||||
ERROR_SUCCESS
|
||||
ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT /* vista is more strict */
|
||||
}
|
||||
};
|
||||
static const char filler[0x1000];
|
||||
|
@ -323,18 +331,11 @@ START_TEST(loader)
|
|||
|
||||
SetLastError(0xdeadbeef);
|
||||
hlib = LoadLibrary(dll_name);
|
||||
if (td[i].error == ERROR_SUCCESS)
|
||||
if (hlib)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
|
||||
ok(hlib != 0, "%d: LoadLibrary error %d\n", i, GetLastError());
|
||||
|
||||
/* No point in crashing. Test crashes on Vista with some of the given files */
|
||||
if (hlib == 0)
|
||||
{
|
||||
skip("Failed to load dll number %d\n", i);
|
||||
goto endloop;
|
||||
}
|
||||
ok( td[i].error == ERROR_SUCCESS, "%d: should have failed\n", i );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(VirtualQuery(hlib, &info, sizeof(info)) == sizeof(info),
|
||||
|
@ -461,8 +462,8 @@ START_TEST(loader)
|
|||
ok(FreeLibrary(hlib_as_data_file), "FreeLibrary error %d\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{ /* LoadLibrary is expected to fail */
|
||||
ok(!hlib, "%d: LoadLibrary should fail\n", i);
|
||||
{
|
||||
ok(td[i].error || td[i].alt_error, "%d: LoadLibrary should succeed\n", i);
|
||||
|
||||
if (GetLastError() == ERROR_GEN_FAILURE) /* Win9x, broken behaviour */
|
||||
{
|
||||
|
@ -471,12 +472,73 @@ START_TEST(loader)
|
|||
return;
|
||||
}
|
||||
|
||||
ok(td[i].error == GetLastError(), "%d: expected error %d, got %d\n",
|
||||
i, td[i].error, GetLastError());
|
||||
ok(td[i].error == GetLastError() || td[i].alt_error == GetLastError(),
|
||||
"%d: expected error %d or %d, got %d\n",
|
||||
i, td[i].error, td[i].alt_error, GetLastError());
|
||||
}
|
||||
|
||||
endloop:
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(DeleteFile(dll_name), "DeleteFile error %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify linking style of import descriptors */
|
||||
static void test_ImportDescriptors(void)
|
||||
{
|
||||
HMODULE kernel32_module = NULL;
|
||||
PIMAGE_DOS_HEADER d_header;
|
||||
PIMAGE_NT_HEADERS nt_headers;
|
||||
DWORD import_dir_size;
|
||||
DWORD_PTR dir_offset;
|
||||
PIMAGE_IMPORT_DESCRIPTOR import_chunk;
|
||||
|
||||
/* Load kernel32 module */
|
||||
kernel32_module = GetModuleHandleA("kernel32.dll");
|
||||
assert( kernel32_module != NULL );
|
||||
|
||||
/* Get PE header info from module image */
|
||||
d_header = (PIMAGE_DOS_HEADER) kernel32_module;
|
||||
nt_headers = (PIMAGE_NT_HEADERS) (((char*) d_header) +
|
||||
d_header->e_lfanew);
|
||||
|
||||
/* Get size of import entry directory */
|
||||
import_dir_size = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
|
||||
if (!import_dir_size)
|
||||
{
|
||||
skip("Unable to continue testing due to missing import directory.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get address of first import chunk */
|
||||
dir_offset = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||
import_chunk = RVAToAddr(dir_offset, kernel32_module);
|
||||
ok(import_chunk != 0, "Invalid import_chunk: %p\n", import_chunk);
|
||||
if (!import_chunk) return;
|
||||
|
||||
/* Iterate through import descriptors and verify set name,
|
||||
* OriginalFirstThunk, and FirstThunk. Core Windows DLLs, such as
|
||||
* kernel32.dll, don't use Borland-style linking, where the table of
|
||||
* imported names is stored directly in FirstThunk and overwritten
|
||||
* by the relocation, instead of being stored in OriginalFirstThunk.
|
||||
* */
|
||||
for (; import_chunk->FirstThunk; import_chunk++)
|
||||
{
|
||||
LPCSTR module_name = RVAToAddr(import_chunk->Name, kernel32_module);
|
||||
PIMAGE_THUNK_DATA name_table = RVAToAddr(
|
||||
U(*import_chunk).OriginalFirstThunk, kernel32_module);
|
||||
PIMAGE_THUNK_DATA iat = RVAToAddr(
|
||||
import_chunk->FirstThunk, kernel32_module);
|
||||
ok(module_name != NULL, "Imported module name should not be NULL\n");
|
||||
ok(name_table != NULL,
|
||||
"Name table for imported module %s should not be NULL\n",
|
||||
module_name);
|
||||
ok(iat != NULL, "IAT for imported module %s should not be NULL\n",
|
||||
module_name);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(loader)
|
||||
{
|
||||
test_Loader();
|
||||
test_ImportDescriptors();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,6 +34,7 @@ static int mailslot_test(void)
|
|||
HANDLE hSlot, hSlot2, hWriter, hWriter2;
|
||||
unsigned char buffer[16];
|
||||
DWORD count, dwMax, dwNext, dwMsgCount, dwTimeout;
|
||||
BOOL ret;
|
||||
|
||||
/* sanity check on GetMailslotInfo */
|
||||
dwMax = dwNext = dwMsgCount = dwTimeout = 0;
|
||||
|
@ -54,10 +55,13 @@ static int mailslot_test(void)
|
|||
|
||||
/* open a mailslot with a null name */
|
||||
hSlot = CreateMailslot( NULL, 0, 0, NULL );
|
||||
ok( hSlot == INVALID_HANDLE_VALUE,
|
||||
"Created mailslot with invalid name\n");
|
||||
ok( GetLastError() == ERROR_PATH_NOT_FOUND,
|
||||
ok( hSlot == INVALID_HANDLE_VALUE || broken(hSlot != INVALID_HANDLE_VALUE), /* win9x */
|
||||
"Created mailslot with invalid name\n");
|
||||
if (hSlot == INVALID_HANDLE_VALUE)
|
||||
ok( GetLastError() == ERROR_PATH_NOT_FOUND,
|
||||
"error should be ERROR_PATH_NOT_FOUND\n");
|
||||
else /* succeeds on win9x */
|
||||
CloseHandle( hSlot );
|
||||
|
||||
/* valid open, but with wacky parameters ... then check them */
|
||||
hSlot = CreateMailslot( szmspath, -1, -1, NULL );
|
||||
|
@ -80,32 +84,36 @@ static int mailslot_test(void)
|
|||
/* try and read/write to it */
|
||||
count = 0;
|
||||
memset(buffer, 0, sizeof buffer);
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
|
||||
"slot read\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
|
||||
ok( !ret || broken(ret), /* win9x */ "slot read\n");
|
||||
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
else ok( count == 0, "wrong count %u\n", count );
|
||||
ok( !WriteFile( hSlot, buffer, sizeof buffer, &count, NULL),
|
||||
"slot write\n");
|
||||
ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
|
||||
|
||||
/* now try and openthe client, but with the wrong sharing mode */
|
||||
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
|
||||
/* now try and open the client, but with the wrong sharing mode */
|
||||
hWriter = CreateFile(szmspath, GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter == INVALID_HANDLE_VALUE, "bad sharing mode\n");
|
||||
ok( GetLastError() == ERROR_SHARING_VIOLATION,
|
||||
"error should be ERROR_SHARING_VIOLATION\n");
|
||||
ok( hWriter != INVALID_HANDLE_VALUE /* vista */ || GetLastError() == ERROR_SHARING_VIOLATION,
|
||||
"error should be ERROR_SHARING_VIOLATION got %p / %u\n", hWriter, GetLastError());
|
||||
if (hWriter != INVALID_HANDLE_VALUE) CloseHandle( hWriter );
|
||||
|
||||
/* now open the client with the correct sharing mode */
|
||||
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot\n");
|
||||
if (hWriter == INVALID_HANDLE_VALUE) /* win9x doesn't like GENERIC_READ */
|
||||
hWriter = CreateFile(szmspath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot err %u\n", GetLastError());
|
||||
|
||||
/*
|
||||
* opening a client should make no difference to
|
||||
* whether we can read or write the mailslot
|
||||
*/
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
|
||||
"slot read\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ret = ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL);
|
||||
ok( !ret || broken(ret), /* win9x */ "slot read\n");
|
||||
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
else ok( count == 0, "wrong count %u\n", count );
|
||||
ok( !WriteFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
|
||||
"slot write\n");
|
||||
ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
|
||||
|
@ -116,12 +124,14 @@ static int mailslot_test(void)
|
|||
*/
|
||||
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
|
||||
"can read client\n");
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
|
||||
"wrong error %u\n", GetLastError() );
|
||||
ok( WriteFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
|
||||
"can't write client\n");
|
||||
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
|
||||
"can read client\n");
|
||||
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ACCESS_DENIED,
|
||||
"wrong error %u\n", GetLastError() );
|
||||
|
||||
/*
|
||||
* seeing as there's something in the slot,
|
||||
|
@ -132,24 +142,28 @@ static int mailslot_test(void)
|
|||
ok( count == (sizeof buffer/2), "short read\n" );
|
||||
|
||||
/* but not again */
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
|
||||
"slot read\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
|
||||
ok( !ret || broken(ret), /* win9x */ "slot read\n");
|
||||
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
else ok( count == 0, "wrong count %u\n", count );
|
||||
|
||||
/* now try open another writer... should fail */
|
||||
hWriter2 = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter2 == INVALID_HANDLE_VALUE, "two writers\n");
|
||||
/* succeeds on vista, don't test */
|
||||
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
|
||||
|
||||
/* now try open another as a reader ... also fails */
|
||||
hWriter2 = CreateFile(szmspath, GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer + reader\n");
|
||||
/* succeeds on vista, don't test */
|
||||
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
|
||||
|
||||
/* now try open another as a writer ... still fails */
|
||||
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer\n");
|
||||
/* succeeds on vista, don't test */
|
||||
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
|
||||
|
||||
/* now open another one */
|
||||
hSlot2 = CreateMailslot( szmspath, 0, 0, NULL );
|
||||
|
@ -172,7 +186,8 @@ static int mailslot_test(void)
|
|||
*/
|
||||
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok( hWriter2 == INVALID_HANDLE_VALUE, "greedy writer succeeded\n");
|
||||
/* succeeds on vista, don't test */
|
||||
if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
|
||||
|
||||
/* now try open another as a writer ... and share with the first */
|
||||
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
|
||||
|
@ -189,8 +204,10 @@ static int mailslot_test(void)
|
|||
ok( dwTimeout == 0, "dwTimeout incorrect\n");
|
||||
|
||||
/* check there's still no data */
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
|
||||
ok( !ret || broken(ret), /* win9x */ "slot read\n");
|
||||
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
else ok( count == 0, "wrong count %u\n", count );
|
||||
|
||||
/* write two messages */
|
||||
buffer[0] = 'a';
|
||||
|
@ -224,9 +241,9 @@ static int mailslot_test(void)
|
|||
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
|
||||
"getmailslotinfo failed\n");
|
||||
ok( dwNext == 1, "dwNext incorrect\n");
|
||||
todo_wine {
|
||||
ok( dwMsgCount == 3, "dwMsgCount incorrect\n");
|
||||
}
|
||||
todo_wine
|
||||
ok( dwMsgCount == 3 || broken(dwMsgCount == 2), /* win9x */
|
||||
"dwMsgCount incorrect %u\n", dwMsgCount);
|
||||
|
||||
buffer[0]=buffer[1]=0;
|
||||
|
||||
|
@ -245,7 +262,8 @@ static int mailslot_test(void)
|
|||
"getmailslotinfo failed\n");
|
||||
ok( dwNext == 2, "dwNext incorrect\n");
|
||||
todo_wine {
|
||||
ok( dwMsgCount == 2, "dwMsgCount incorrect\n");
|
||||
ok( dwMsgCount == 2 || broken(dwMsgCount == 1), /* win9x */
|
||||
"dwMsgCount incorrect %u\n", dwMsgCount);
|
||||
}
|
||||
|
||||
/* read the second message */
|
||||
|
@ -258,9 +276,10 @@ static int mailslot_test(void)
|
|||
dwNext = dwMsgCount = 0;
|
||||
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
|
||||
"getmailslotinfo failed\n");
|
||||
ok( dwNext == 0, "dwNext incorrect\n");
|
||||
ok( dwNext == 0 || broken(dwNext == ~0u), /* win9x */ "dwNext incorrect %u\n", dwNext);
|
||||
todo_wine {
|
||||
ok( dwMsgCount == 1, "dwMsgCount incorrect\n");
|
||||
ok( dwMsgCount == 1 || broken(dwMsgCount == 0), /* win9x */
|
||||
"dwMsgCount incorrect %u\n", dwMsgCount);
|
||||
}
|
||||
|
||||
/* read the 3rd (zero length) message */
|
||||
|
@ -281,9 +300,10 @@ static int mailslot_test(void)
|
|||
ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
|
||||
|
||||
/* check that reads fail */
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
|
||||
"3rd slot read succeeded\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
|
||||
ok( !ret || broken(ret), /* win9x */ "3rd slot read succeeded\n");
|
||||
if (!ret) ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
else ok( count == 0, "wrong count %u\n", count );
|
||||
|
||||
/* finally close the mailslot and its client */
|
||||
ok( CloseHandle( hWriter2 ), "closing 2nd client\n");
|
||||
|
@ -297,7 +317,8 @@ static int mailslot_test(void)
|
|||
memset(buffer, 0, sizeof buffer);
|
||||
dwTimeout = GetTickCount();
|
||||
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError() );
|
||||
ok( GetLastError() == ERROR_SEM_TIMEOUT || broken(GetLastError() == ERROR_ACCESS_DENIED), /* win9x */
|
||||
"wrong error %u\n", GetLastError() );
|
||||
dwTimeout = GetTickCount() - dwTimeout;
|
||||
ok( dwTimeout >= 990, "timeout too short %u\n", dwTimeout );
|
||||
ok( CloseHandle( hSlot ), "closing the mailslot\n");
|
||||
|
|
|
@ -216,6 +216,123 @@ static void testGetProcAddress_Wrong(void)
|
|||
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static void testLoadLibraryEx(void)
|
||||
{
|
||||
CHAR path[MAX_PATH];
|
||||
HMODULE hmodule;
|
||||
HANDLE hfile;
|
||||
|
||||
hfile = CreateFileA("testfile.dll", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "Expected a valid file handle\n");
|
||||
|
||||
/* NULL lpFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA(NULL, NULL, 0);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
|
||||
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
/* empty lpFileName */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA("", NULL, 0);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
|
||||
GetLastError() == ERROR_DLL_NOT_FOUND, /* win9x */
|
||||
"Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
/* hFile is non-NULL */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA("testfile.dll", hfile, 0);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
ok(GetLastError() == ERROR_SHARING_VIOLATION ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER || /* win2k3 */
|
||||
GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
|
||||
"Unexpected last error, got %d\n", GetLastError());
|
||||
|
||||
/* try to open a file that is locked */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA("testfile.dll", NULL, 0);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
todo_wine
|
||||
{
|
||||
ok(GetLastError() == ERROR_SHARING_VIOLATION ||
|
||||
GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
|
||||
"Expected ERROR_SHARING_VIOLATION or ERROR_FILE_NOT_FOUND, got %d\n",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
/* lpFileName does not matter */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA(NULL, hfile, 0);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */
|
||||
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
CloseHandle(hfile);
|
||||
|
||||
/* load empty file */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA("testfile.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
todo_wine
|
||||
{
|
||||
ok(GetLastError() == ERROR_FILE_INVALID ||
|
||||
GetLastError() == ERROR_BAD_FORMAT, /* win9x */
|
||||
"Expected ERROR_FILE_INVALID or ERROR_BAD_FORMAT, got %d\n",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
DeleteFileA("testfile.dll");
|
||||
|
||||
GetSystemDirectoryA(path, MAX_PATH);
|
||||
if (path[lstrlenA(path) - 1] != '\\')
|
||||
lstrcatA(path, "\\");
|
||||
lstrcatA(path, "kernel32.dll");
|
||||
|
||||
/* load kernel32.dll with an absolute path */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
ok(hmodule != 0, "Expected valid module handle\n");
|
||||
ok(GetLastError() == 0xdeadbeef ||
|
||||
GetLastError() == ERROR_SUCCESS, /* win9x */
|
||||
"Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
|
||||
CloseHandle(hmodule);
|
||||
|
||||
/* load kernel32.dll with no path */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA("kernel32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
ok(hmodule != 0, "Expected valid module handle\n");
|
||||
ok(GetLastError() == 0xdeadbeef ||
|
||||
GetLastError() == ERROR_SUCCESS, /* win9x */
|
||||
"Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
|
||||
CloseHandle(hmodule);
|
||||
|
||||
GetCurrentDirectoryA(MAX_PATH, path);
|
||||
if (path[lstrlenA(path) - 1] != '\\')
|
||||
lstrcatA(path, "\\");
|
||||
lstrcatA(path, "kernel32.dll");
|
||||
|
||||
/* load kernel32.dll with an absolute path that does not exist */
|
||||
SetLastError(0xdeadbeef);
|
||||
hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
todo_wine
|
||||
{
|
||||
ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
|
||||
}
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
broken(GetLastError() == ERROR_INVALID_HANDLE), /* nt4 */
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(module)
|
||||
{
|
||||
WCHAR filenameW[MAX_PATH];
|
||||
|
@ -226,7 +343,7 @@ START_TEST(module)
|
|||
GetModuleFileNameW(NULL, filenameW, MAX_PATH);
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
trace("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
|
||||
win_skip("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
|
||||
is_unicode_enabled = FALSE;
|
||||
}
|
||||
|
||||
|
@ -238,4 +355,5 @@ START_TEST(module)
|
|||
testNestedLoadLibraryA();
|
||||
testLoadLibraryA_Wrong();
|
||||
testGetProcAddress_Wrong();
|
||||
testLoadLibraryEx();
|
||||
}
|
||||
|
|
|
@ -465,6 +465,14 @@ static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
|
|||
/* starting with a '.' */
|
||||
sprintf(tmpstr,".\\%s",LONGDIR);
|
||||
test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
|
||||
/* change to root without a trailing backslash. The function call succeeds
|
||||
but the directory is not changed.
|
||||
*/
|
||||
strcpy(tmpstr,"C:");
|
||||
test_setdir(newdir,tmpstr,newdir,1,"check 10");
|
||||
/* works however with a trailing backslash */
|
||||
strcpy(tmpstr,"C:\\");
|
||||
test_setdir(newdir,tmpstr,NULL,1,"check 11");
|
||||
}
|
||||
|
||||
/* Cleanup the mess we made while executing these tests */
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
|
@ -713,14 +712,17 @@ static int test_DisconnectNamedPipe(void)
|
|||
DWORD written;
|
||||
DWORD readden;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
|
||||
/* nMaxInstances */ 1,
|
||||
/* nOutBufSize */ 1024,
|
||||
/* nInBufSize */ 1024,
|
||||
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
|
||||
/* lpSecurityAttrib */ NULL);
|
||||
if (INVALID_HANDLE_VALUE == hnp) {
|
||||
trace ("Seems we have no named pipes.\n");
|
||||
if ((hnp == INVALID_HANDLE_VALUE /* Win98 */ || !hnp /* Win95 */)
|
||||
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
|
||||
|
||||
win_skip("Named pipes are not implemented\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -793,7 +795,7 @@ static void test_CreatePipe(void)
|
|||
size = 32768;
|
||||
buffer = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
for (i = 0; i < size; i++) buffer[i] = i;
|
||||
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, size) != 0, "CreatePipe failed\n");
|
||||
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, (size + 24)) != 0, "CreatePipe failed\n");
|
||||
ok(WriteFile(pipewrite, buffer, size, &written, NULL), "Write to anonymous pipe failed\n");
|
||||
ok(written == size, "Write to anonymous pipe wrote %d bytes\n", written);
|
||||
/* and close the write end, read should still succeed*/
|
||||
|
@ -952,8 +954,8 @@ static void test_ImpersonateNamedPipeClient(HANDLE hClientToken, DWORD security_
|
|||
SetLastError(0xdeadbeef);
|
||||
ret = ImpersonateNamedPipeClient(hPipeServer);
|
||||
error = GetLastError();
|
||||
todo_wine
|
||||
ok(!ret && (error == ERROR_CANNOT_IMPERSONATE), "ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
|
||||
ok(ret /* win2k3 */ || (error == ERROR_CANNOT_IMPERSONATE),
|
||||
"ImpersonateNamedPipeClient should have failed with ERROR_CANNOT_IMPERSONATE instead of %d\n", GetLastError());
|
||||
|
||||
ret = ConnectNamedPipe(hPipeServer, NULL);
|
||||
ok(ret || (GetLastError() == ERROR_PIPE_CONNECTED), "ConnectNamedPipe failed with error %d\n", GetLastError());
|
||||
|
@ -1325,9 +1327,6 @@ START_TEST(pipe)
|
|||
{
|
||||
HMODULE hmod;
|
||||
|
||||
skip("ROS-HACK: Skipping pipe tests -- ros' npfs is in a sorry state\n");
|
||||
return;
|
||||
|
||||
hmod = GetModuleHandle("advapi32.dll");
|
||||
pDuplicateTokenEx = (void *) GetProcAddress(hmod, "DuplicateTokenEx");
|
||||
|
||||
|
|
|
@ -24,12 +24,16 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "wincon.h"
|
||||
#include "winnls.h"
|
||||
#include "winternl.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static HINSTANCE hkernel32;
|
||||
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
||||
|
@ -124,7 +128,6 @@ static char* decodeA(const char* str)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This will be needed to decode Unicode strings saved by the child process
|
||||
* when we test Unicode functions.
|
||||
*/
|
||||
|
@ -145,7 +148,6 @@ static WCHAR* decodeW(const char* str)
|
|||
ptr[len] = '\0';
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************
|
||||
* init
|
||||
|
@ -348,8 +350,18 @@ static void doChild(const char* file, const char* option)
|
|||
childPrintf(hFile, "OutputMode=%ld\n", modeOut);
|
||||
|
||||
/* now that we have written all relevant information, let's change it */
|
||||
ok(SetConsoleCP(1252), "Setting CP\n");
|
||||
ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetConsoleCP(1252);
|
||||
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
win_skip("Setting the codepage is not implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(ret, "Setting CP\n");
|
||||
ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
|
||||
}
|
||||
|
||||
ret = SetConsoleMode(hConIn, modeIn ^ 1);
|
||||
ok( ret, "Setting mode (%d)\n", GetLastError());
|
||||
ret = SetConsoleMode(hConOut, modeOut ^ 1);
|
||||
|
@ -397,6 +409,18 @@ static char* getChildString(const char* sect, const char* key)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static WCHAR* getChildStringW(const char* sect, const char* key)
|
||||
{
|
||||
char buf[1024+4*MAX_LISTED_ENV_VAR];
|
||||
WCHAR* ret;
|
||||
|
||||
GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
|
||||
if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
|
||||
assert(!(strlen(buf) & 1));
|
||||
ret = decodeW(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: this may be moved to the wtmain.c file, because it may be needed by
|
||||
* others... (windows uses stricmp while Un*x uses strcasecmp...)
|
||||
*/
|
||||
|
@ -432,8 +456,35 @@ static void ok_child_string( int line, const char *sect, const char *key,
|
|||
sect, key, expect ? expect : "(null)", result );
|
||||
}
|
||||
|
||||
static void ok_child_stringWA( int line, const char *sect, const char *key,
|
||||
const char *expect, int sensitive )
|
||||
{
|
||||
WCHAR* expectW;
|
||||
CHAR* resultA;
|
||||
DWORD len;
|
||||
WCHAR* result = getChildStringW( sect, key );
|
||||
|
||||
len = MultiByteToWideChar( CP_ACP, 0, expect, -1, NULL, 0);
|
||||
expectW = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
||||
MultiByteToWideChar( CP_ACP, 0, expect, -1, expectW, len);
|
||||
|
||||
len = WideCharToMultiByte( CP_ACP, 0, result, -1, NULL, 0, NULL, NULL);
|
||||
resultA = HeapAlloc(GetProcessHeap(),0,len*sizeof(CHAR));
|
||||
WideCharToMultiByte( CP_ACP, 0, result, -1, resultA, len, NULL, NULL);
|
||||
|
||||
if (sensitive)
|
||||
ok_(__FILE__, line)( lstrcmpW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
|
||||
sect, key, expect ? expect : "(null)", resultA );
|
||||
else
|
||||
ok_(__FILE__, line)( lstrcmpiW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
|
||||
sect, key, expect ? expect : "(null)", resultA );
|
||||
HeapFree(GetProcessHeap(),0,expectW);
|
||||
HeapFree(GetProcessHeap(),0,resultA);
|
||||
}
|
||||
|
||||
#define okChildString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 1 )
|
||||
#define okChildIString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 0 )
|
||||
#define okChildStringWA(sect, key, expect) ok_child_stringWA(__LINE__, (sect), (key), (expect), 1 )
|
||||
|
||||
/* using !expect ensures that the test will fail if the sect/key isn't present
|
||||
* in result file
|
||||
|
@ -450,7 +501,7 @@ static void test_Startup(void)
|
|||
PROCESS_INFORMATION info;
|
||||
STARTUPINFOA startup,si;
|
||||
static CHAR title[] = "I'm the title string",
|
||||
desktop[] = "I'm the desktop string",
|
||||
desktop[] = "winsta0\\default",
|
||||
empty[] = "";
|
||||
|
||||
/* let's start simplistic */
|
||||
|
@ -470,8 +521,6 @@ static void test_Startup(void)
|
|||
GetStartupInfoA(&si);
|
||||
okChildInt("StartupInfoA", "cb", startup.cb);
|
||||
okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
|
||||
ok (si.lpTitle == NULL || !strncmp(si.lpTitle, selfname, strlen(selfname)),
|
||||
"StartupInfoA:lpTitle expected something starting with '%s' or null, got '%s'\n", selfname, si.lpTitle);
|
||||
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
||||
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
||||
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
||||
|
@ -719,6 +768,7 @@ static void test_Startup(void)
|
|||
static void test_CommandLine(void)
|
||||
{
|
||||
char buffer[MAX_PATH], fullpath[MAX_PATH], *lpFilePart, *p;
|
||||
char buffer2[MAX_PATH];
|
||||
PROCESS_INFORMATION info;
|
||||
STARTUPINFOA startup;
|
||||
DWORD len;
|
||||
|
@ -804,9 +854,9 @@ static void test_CommandLine(void)
|
|||
assert ( lpFilePart != 0);
|
||||
*(lpFilePart -1 ) = 0;
|
||||
p = strrchr(fullpath, '\\');
|
||||
assert (p);
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
|
||||
if (p) sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
|
||||
else sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
|
@ -814,11 +864,35 @@ static void test_CommandLine(void)
|
|||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
sprintf(buffer, "..%s/%s", p, exename);
|
||||
if (p) sprintf(buffer, "..%s/%s", p, exename);
|
||||
else sprintf(buffer, "./%s", exename);
|
||||
okChildString("Arguments", "argvA0", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
|
||||
|
||||
/* Using AppName */
|
||||
get_file_name(resfile);
|
||||
len = GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
|
||||
assert ( lpFilePart != 0);
|
||||
*(lpFilePart -1 ) = 0;
|
||||
p = strrchr(fullpath, '\\');
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
if (p) sprintf(buffer, "..%s/%s", p, exename);
|
||||
else sprintf(buffer, "./%s", exename);
|
||||
sprintf(buffer2, "dummy tests/process.c %s \"a\\\"b\\\\\" c\\\" d", resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
sprintf(buffer, "tests/process.c %s", resfile);
|
||||
okChildString("Arguments", "argvA0", "dummy");
|
||||
okChildString("Arguments", "CommandLineA", buffer2);
|
||||
okChildStringWA("Arguments", "CommandLineW", buffer2);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
}
|
||||
|
||||
static void test_Directory(void)
|
||||
|
@ -1127,9 +1201,7 @@ static void test_Console(void)
|
|||
HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
|
||||
const char* msg = "This is a std-handle inheritance test.";
|
||||
unsigned msg_len;
|
||||
|
||||
skip("ROS-HACK: Skipping process console tests\n");
|
||||
return;
|
||||
BOOL run_tests = TRUE;
|
||||
|
||||
memset(&startup, 0, sizeof(startup));
|
||||
startup.cb = sizeof(startup);
|
||||
|
@ -1185,13 +1257,18 @@ static void test_Console(void)
|
|||
/* Try to set invalid CP */
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!SetConsoleCP(0), "Shouldn't succeed\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
|
||||
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
|
||||
"GetLastError: expecting %u got %u\n",
|
||||
ERROR_INVALID_PARAMETER, GetLastError());
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
run_tests = FALSE;
|
||||
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!SetConsoleOutputCP(0), "Shouldn't succeed\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
|
||||
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
|
||||
"GetLastError: expecting %u got %u\n",
|
||||
ERROR_INVALID_PARAMETER, GetLastError());
|
||||
|
||||
|
@ -1234,8 +1311,14 @@ static void test_Console(void)
|
|||
okChildInt("Console", "InputMode", modeIn);
|
||||
okChildInt("Console", "OutputMode", modeOut);
|
||||
|
||||
ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
|
||||
ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
|
||||
if (run_tests)
|
||||
{
|
||||
ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
|
||||
ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
|
||||
}
|
||||
else
|
||||
win_skip("Setting the codepage is not implemented\n");
|
||||
|
||||
ok(modeInC == (modeIn ^ 1), "Wrong console mode\n");
|
||||
ok(modeOutC == (modeOut ^ 1), "Wrong console-SB mode\n");
|
||||
trace("cursor position(X): %d/%d\n",sbi.dwCursorPosition.X, sbiC.dwCursorPosition.X);
|
||||
|
@ -1402,6 +1485,73 @@ static void test_OpenProcess(void)
|
|||
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
}
|
||||
|
||||
static void test_GetProcessVersion(void)
|
||||
{
|
||||
static char cmdline[] = "winver.exe";
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOA si;
|
||||
DWORD ret;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetProcessVersion(0);
|
||||
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetProcessVersion(GetCurrentProcessId());
|
||||
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(ret, "CreateProcess error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetProcessVersion(pi.dwProcessId);
|
||||
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = TerminateProcess(pi.hProcess, 0);
|
||||
ok(ret, "TerminateProcess error %u\n", GetLastError());
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
static void test_Handles(void)
|
||||
{
|
||||
HANDLE handle = GetCurrentProcess();
|
||||
BOOL ret;
|
||||
DWORD code;
|
||||
|
||||
ok( handle == (HANDLE)~(ULONG_PTR)0 ||
|
||||
handle == (HANDLE)(ULONG_PTR)0x7fffffff /* win9x */,
|
||||
"invalid current process handle %p\n", handle );
|
||||
ret = GetExitCodeProcess( handle, &code );
|
||||
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
|
||||
#ifdef _WIN64
|
||||
/* truncated handle */
|
||||
SetLastError( 0xdeadbeef );
|
||||
handle = (HANDLE)((ULONG_PTR)handle & ~0u);
|
||||
ret = GetExitCodeProcess( handle, &code );
|
||||
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
|
||||
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
/* sign-extended handle */
|
||||
SetLastError( 0xdeadbeef );
|
||||
handle = (HANDLE)((LONG_PTR)(int)(ULONG_PTR)handle);
|
||||
ret = GetExitCodeProcess( handle, &code );
|
||||
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
|
||||
/* invalid high-word */
|
||||
SetLastError( 0xdeadbeef );
|
||||
handle = (HANDLE)(((ULONG_PTR)handle & ~0u) + ((ULONG_PTR)1 << 32));
|
||||
ret = GetExitCodeProcess( handle, &code );
|
||||
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
|
||||
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
||||
#endif
|
||||
}
|
||||
|
||||
START_TEST(process)
|
||||
{
|
||||
int b = init();
|
||||
|
@ -1422,6 +1572,8 @@ START_TEST(process)
|
|||
test_Console();
|
||||
test_ExitCode();
|
||||
test_OpenProcess();
|
||||
test_GetProcessVersion();
|
||||
test_Handles();
|
||||
/* things that can be tested:
|
||||
* lookup: check the way program to be executed is searched
|
||||
* handles: check the handle inheritance stuff (+sec options)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "windef.h"
|
||||
|
@ -182,13 +183,14 @@ static void test_profile_sections(void)
|
|||
ok( GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* And a real one */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret=GetPrivateProfileSectionA("section1", buf, sizeof(buf), testfile4);
|
||||
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
|
||||
p[-1] = ',';
|
||||
ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
|
||||
ret, buf);
|
||||
ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
|
||||
ok( GetLastError() == S_OK, "expected S_OK, got %d\n", GetLastError());
|
||||
ok( GetLastError() == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", GetLastError());
|
||||
|
||||
DeleteFileA( testfile4 );
|
||||
}
|
||||
|
@ -266,10 +268,456 @@ static void test_profile_sections_names(void)
|
|||
ok( bufW[1] != 0, "returned buffer terminated with double-null\n" );
|
||||
}
|
||||
|
||||
/* If the ini-file has already been opened with CreateFile, WritePrivateProfileString failed in wine with an error ERROR_SHARING_VIOLATION, some testing here */
|
||||
static void test_profile_existing(void)
|
||||
{
|
||||
static const char *testfile1 = ".\\winesharing1.ini";
|
||||
static const char *testfile2 = ".\\winesharing2.ini";
|
||||
|
||||
static const struct {
|
||||
DWORD dwDesiredAccess;
|
||||
DWORD dwShareMode;
|
||||
DWORD write_error;
|
||||
BOOL read_error;
|
||||
DWORD broken_error;
|
||||
} pe[] = {
|
||||
{GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
|
||||
{GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
|
||||
{GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
|
||||
{GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
|
||||
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
|
||||
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
|
||||
{GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
|
||||
{GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
|
||||
/*Thief demo (bug 5024) opens .ini file like this*/
|
||||
{GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */}
|
||||
};
|
||||
|
||||
int i;
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
HANDLE h = 0;
|
||||
char buffer[MAX_PATH];
|
||||
|
||||
for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++)
|
||||
{
|
||||
h = CreateFile(testfile1, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
|
||||
SetLastError(0xdeadbeef);
|
||||
|
||||
ret = WritePrivateProfileString(SECTION, KEY, "12345", testfile1);
|
||||
if (!pe[i].write_error)
|
||||
{
|
||||
if (!ret)
|
||||
ok( broken(GetLastError() == pe[i].broken_error),
|
||||
"%d: WritePrivateProfileString failed with error %u\n", i, GetLastError() );
|
||||
CloseHandle(h);
|
||||
size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
|
||||
if (ret)
|
||||
ok( size == 5, "%d: test failed, number of characters copied: %d instead of 5\n", i, size );
|
||||
else
|
||||
ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
ok( !ret, "%d: WritePrivateProfileString succeeded\n", i );
|
||||
if (!ret)
|
||||
ok( err == pe[i].write_error, "%d: WritePrivateProfileString failed with error %u/%u\n",
|
||||
i, err, pe[i].write_error );
|
||||
CloseHandle(h);
|
||||
size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
|
||||
ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
|
||||
}
|
||||
|
||||
ok( DeleteFile(testfile1), "delete failed\n" );
|
||||
}
|
||||
|
||||
h = CreateFile(testfile2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
sprintf( buffer, "[%s]\r\n%s=123\r\n", SECTION, KEY );
|
||||
ok( WriteFile( h, buffer, strlen(buffer), &size, NULL ), "failed to write\n" );
|
||||
CloseHandle( h );
|
||||
|
||||
for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++)
|
||||
{
|
||||
h = CreateFile(testfile2, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetPrivateProfileStringA(SECTION, KEY, NULL, buffer, MAX_PATH, testfile2);
|
||||
if (!pe[i].read_error)
|
||||
ok( ret, "%d: GetPrivateProfileString failed with error %u\n", i, GetLastError() );
|
||||
else
|
||||
ok( !ret, "%d: GetPrivateProfileString succeeded\n", i );
|
||||
CloseHandle(h);
|
||||
}
|
||||
ok( DeleteFile(testfile2), "delete failed\n" );
|
||||
}
|
||||
|
||||
static void test_profile_delete_on_close()
|
||||
{
|
||||
static CHAR testfile[] = ".\\testwine5.ini";
|
||||
HANDLE h;
|
||||
DWORD size, res;
|
||||
static const char contents[] = "[" SECTION "]\n" KEY "=123\n";
|
||||
|
||||
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
ok( WriteFile( h, contents, sizeof contents - 1, &size, NULL ),
|
||||
"Cannot write test file: %x\n", GetLastError() );
|
||||
ok( size == sizeof contents - 1, "Test file: partial write\n");
|
||||
|
||||
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
|
||||
ok( res == 123, "Got %d instead of 123\n", res);
|
||||
|
||||
/* This also deletes the file */
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
||||
static void test_profile_refresh(void)
|
||||
{
|
||||
static CHAR testfile[] = ".\\winetest4.ini";
|
||||
HANDLE h;
|
||||
DWORD size, res;
|
||||
static const char contents1[] = "[" SECTION "]\n" KEY "=123\n";
|
||||
static const char contents2[] = "[" SECTION "]\n" KEY "=124\n";
|
||||
|
||||
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
ok( WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL ),
|
||||
"Cannot write test file: %x\n", GetLastError() );
|
||||
ok( size == sizeof contents1 - 1, "Test file: partial write\n");
|
||||
|
||||
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
|
||||
ok( res == 123, "Got %d instead of 123\n", res);
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
/* Test proper invalidation of wine's profile file cache */
|
||||
|
||||
h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
ok( WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL ),
|
||||
"Cannot write test file: %x\n", GetLastError() );
|
||||
ok( size == sizeof contents2 - 1, "Test file: partial write\n");
|
||||
|
||||
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile);
|
||||
ok( res == 124, "Got %d instead of 124\n", res);
|
||||
|
||||
/* This also deletes the file */
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
||||
static void create_test_file(LPCSTR name, LPCSTR data, DWORD size)
|
||||
{
|
||||
HANDLE hfile;
|
||||
DWORD count;
|
||||
|
||||
hfile = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "cannot create %s\n", name);
|
||||
WriteFile(hfile, data, size, &count, NULL);
|
||||
CloseHandle(hfile);
|
||||
}
|
||||
|
||||
static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0;i < MAX_PATH;++i)
|
||||
if(emptystr[i] != 0)
|
||||
{
|
||||
trace("emptystr[%d] = %d\n",i,emptystr[i]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void test_GetPrivateProfileString(const char *content, const char *descript)
|
||||
{
|
||||
DWORD ret;
|
||||
CHAR buf[MAX_PATH];
|
||||
CHAR def_val[MAX_PATH];
|
||||
CHAR path[MAX_PATH];
|
||||
CHAR windir[MAX_PATH];
|
||||
/* NT series crashes on r/o empty strings, so pass an r/w
|
||||
empty string and check for modification */
|
||||
CHAR emptystr[MAX_PATH] = "";
|
||||
LPSTR tempfile;
|
||||
|
||||
static const char filename[] = ".\\winetest.ini";
|
||||
|
||||
trace("test_GetPrivateProfileStringA: %s\n", descript);
|
||||
|
||||
create_test_file(filename, content, lstrlenA(content));
|
||||
|
||||
/* Run this test series with caching. Wine won't cache profile
|
||||
files younger than 2.1 seconds. */
|
||||
Sleep(2500);
|
||||
|
||||
/* lpAppName is NULL */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(NULL, "name1", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 18, "Expected 18, got %d\n", ret);
|
||||
ok(!memcmp(buf, "section1\0section2\0", ret + 1),
|
||||
"Expected \"section1\\0section2\\0\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpAppName is empty */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpAppName is missing */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("notasection", "name1", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpAppName is empty, lpDefault is NULL */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", NULL,
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpAppName is empty, lpDefault is empty */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", "",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpAppName is empty, lpDefault has trailing blank characters */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
|
||||
lstrcpyA(def_val, "default ");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpAppName is empty, many blank characters in lpDefault */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
|
||||
lstrcpyA(def_val, "one two ");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpAppName is empty, blank character but not trailing in lpDefault */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(emptystr, "name1", "one two",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "AppName modified\n");
|
||||
|
||||
/* lpKeyName is NULL */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", NULL, "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 18, "Expected 18, got %d\n", ret);
|
||||
ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
|
||||
"Expected \"name1\\0name2\\0name4\\0\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpKeyName is empty */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", emptystr, "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "KeyName modified\n");
|
||||
|
||||
/* lpKeyName is missing */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "notakey", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpKeyName is empty, lpDefault is NULL */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", emptystr, NULL,
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "KeyName modified\n");
|
||||
|
||||
/* lpKeyName is empty, lpDefault is empty */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", emptystr, "",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "KeyName modified\n");
|
||||
|
||||
/* lpKeyName is empty, lpDefault has trailing blank characters */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
/* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
|
||||
lstrcpyA(def_val, "default ");
|
||||
ret = GetPrivateProfileStringA("section1", emptystr, def_val,
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
ok(emptystr_ok(emptystr), "KeyName modified\n");
|
||||
|
||||
if (0) /* crashes */
|
||||
{
|
||||
/* lpReturnedString is NULL */
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
NULL, MAX_PATH, filename);
|
||||
}
|
||||
|
||||
/* lpFileName is NULL */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, MAX_PATH, NULL);
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpFileName is empty */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, MAX_PATH, "");
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpFileName is nonexistent */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, MAX_PATH, "nonexistent");
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
/* nSize is 0 */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, 0, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "kumquat"), "Expected buf to be unchanged, got \"%s\"\n", buf);
|
||||
|
||||
/* nSize is exact size of output */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, 4, filename);
|
||||
ok(ret == 3, "Expected 3, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val"), "Expected \"val\", got \"%s\"\n", buf);
|
||||
|
||||
/* nSize has room for NULL terminator */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, 5, filename);
|
||||
ok(ret == 4, "Expected 4, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
|
||||
|
||||
/* output is 1 character */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name4", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 1, "Expected 1, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "a"), "Expected \"a\", got \"%s\"\n", buf);
|
||||
|
||||
/* output is 1 character, no room for NULL terminator */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name4", "default",
|
||||
buf, 1, filename);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpAppName is NULL, not enough room for final section name */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA(NULL, "name1", "default",
|
||||
buf, 16, filename);
|
||||
ok(ret == 14, "Expected 14, got %d\n", ret);
|
||||
ok(!memcmp(buf, "section1\0secti\0", ret + 1),
|
||||
"Expected \"section1\\0secti\\0\", got \"%s\"\n", buf);
|
||||
|
||||
/* lpKeyName is NULL, not enough room for final key name */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", NULL, "default",
|
||||
buf, 16, filename);
|
||||
ok(ret == 14, "Expected 14, got %d\n", ret);
|
||||
ok(!memcmp(buf, "name1\0name2\0na\0", ret + 1),
|
||||
"Expected \"name1\\0name2\\0na\\0\", got \"%s\"\n", buf);
|
||||
|
||||
/* key value has quotation marks which are stripped */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name2", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 4, "Expected 4, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val2"), "Expected \"val2\", got \"%s\"\n", buf);
|
||||
|
||||
/* case does not match */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 4, "Expected 4, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
|
||||
|
||||
/* only filename is used */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
|
||||
buf, MAX_PATH, "winetest.ini");
|
||||
ok(ret == 7, "Expected 7, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
|
||||
|
||||
GetWindowsDirectoryA(windir, MAX_PATH);
|
||||
GetTempFileNameA(windir, "pre", 0, path);
|
||||
tempfile = strrchr(path, '\\') + 1;
|
||||
create_test_file(path, content, lstrlenA(content));
|
||||
|
||||
/* only filename is used, file exists in windows directory */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
|
||||
buf, MAX_PATH, tempfile);
|
||||
ok(ret == 4, "Expected 4, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
|
||||
|
||||
/* successful case */
|
||||
lstrcpyA(buf, "kumquat");
|
||||
ret = GetPrivateProfileStringA("section1", "name1", "default",
|
||||
buf, MAX_PATH, filename);
|
||||
ok(ret == 4, "Expected 4, got %d\n", ret);
|
||||
ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
|
||||
|
||||
DeleteFileA(path);
|
||||
DeleteFileA(filename);
|
||||
}
|
||||
|
||||
START_TEST(profile)
|
||||
{
|
||||
test_profile_int();
|
||||
test_profile_string();
|
||||
test_profile_sections();
|
||||
test_profile_sections_names();
|
||||
test_profile_existing();
|
||||
test_profile_delete_on_close();
|
||||
test_profile_refresh();
|
||||
test_GetPrivateProfileString(
|
||||
"[section1]\r\n"
|
||||
"name1=val1\r\n"
|
||||
"name2=\"val2\"\r\n"
|
||||
"name3\r\n"
|
||||
"name4=a\r\n"
|
||||
"[section2]\r\n",
|
||||
"CR+LF");
|
||||
test_GetPrivateProfileString(
|
||||
"[section1]\r"
|
||||
"name1=val1\r"
|
||||
"name2=\"val2\"\r"
|
||||
"name3\r"
|
||||
"name4=a\r"
|
||||
"[section2]\r",
|
||||
"CR only");
|
||||
}
|
||||
|
|
|
@ -173,22 +173,25 @@ static void update_resources_version(void)
|
|||
res = BeginUpdateResource( filename, TRUE );
|
||||
ok( res != NULL, "BeginUpdateResource failed\n");
|
||||
|
||||
r = UpdateResource( res,
|
||||
MAKEINTRESOURCE(0x1230),
|
||||
MAKEINTRESOURCE(0x4567),
|
||||
0xabcd,
|
||||
NULL, 0 );
|
||||
ok( r == FALSE, "UpdateResource failed\n");
|
||||
if (0) /* this causes subsequent tests to fail on Vista */
|
||||
{
|
||||
r = UpdateResource( res,
|
||||
MAKEINTRESOURCE(0x1230),
|
||||
MAKEINTRESOURCE(0x4567),
|
||||
0xabcd,
|
||||
NULL, 0 );
|
||||
ok( r == FALSE, "UpdateResource failed\n");
|
||||
}
|
||||
|
||||
r = UpdateResource( res,
|
||||
MAKEINTRESOURCE(0x1230),
|
||||
MAKEINTRESOURCE(0x4567),
|
||||
0xabcd,
|
||||
foo, sizeof foo );
|
||||
ok( r == TRUE, "UpdateResource failed\n");
|
||||
ok( r == TRUE, "UpdateResource failed: %d\n", GetLastError());
|
||||
|
||||
r = EndUpdateResource( res, FALSE );
|
||||
ok( r, "EndUpdateResource failed\n");
|
||||
ok( r, "EndUpdateResource failed: %d\n", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,7 +252,8 @@ static void check_exe( res_check_func fn )
|
|||
dir = (void*) ((BYTE*) dos + sec[1].VirtualAddress);
|
||||
|
||||
ok( dir->Characteristics == 0, "Characteristics wrong\n");
|
||||
ok( dir->TimeDateStamp == 0, "TimeDateStamp wrong\n");
|
||||
ok( dir->TimeDateStamp == 0 || abs( dir->TimeDateStamp - GetTickCount() ) < 1000 /* nt4 */,
|
||||
"TimeDateStamp wrong %u\n", dir->TimeDateStamp);
|
||||
ok( dir->MajorVersion == 4, "MajorVersion wrong\n");
|
||||
ok( dir->MinorVersion == 0, "MinorVersion wrong\n");
|
||||
|
||||
|
|
|
@ -26,6 +26,15 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
|
||||
static HANDLE (WINAPI *pCreateTimerQueue)(void);
|
||||
static BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
|
||||
PVOID, DWORD, DWORD, ULONG);
|
||||
static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
|
||||
static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
|
||||
static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
|
||||
static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
|
||||
|
||||
static void test_signalandwait(void)
|
||||
{
|
||||
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
|
||||
|
@ -44,7 +53,7 @@ static void test_signalandwait(void)
|
|||
r = pSignalObjectAndWait(NULL, NULL, 0, 0);
|
||||
if (r == ERROR_INVALID_FUNCTION)
|
||||
{
|
||||
trace("SignalObjectAndWait not implemented, skipping tests\n");
|
||||
skip("SignalObjectAndWait is not implemented\n");
|
||||
return; /* Win98/ME */
|
||||
}
|
||||
ok( r == WAIT_FAILED, "should fail\n");
|
||||
|
@ -148,7 +157,34 @@ static void test_mutex(void)
|
|||
todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
|
||||
"ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
|
||||
|
||||
/* test case sensitivity */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
|
||||
ok(!hOpened, "OpenMutex succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_NAME, /* win9x */
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
|
||||
ok(!hOpened, "OpenMutex succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_NAME, /* win9x */
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
|
||||
ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
|
||||
ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
|
||||
CloseHandle(hOpened);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
|
||||
ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
|
||||
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
CloseHandle(hOpened);
|
||||
|
||||
CloseHandle(hCreated);
|
||||
}
|
||||
|
||||
|
@ -245,9 +281,9 @@ static void test_slist(void)
|
|||
ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
|
||||
}
|
||||
|
||||
static void test_event_security(void)
|
||||
static void test_event(void)
|
||||
{
|
||||
HANDLE handle;
|
||||
HANDLE handle, handle2;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_DESCRIPTOR sd;
|
||||
ACL acl;
|
||||
|
@ -280,6 +316,121 @@ static void test_event_security(void)
|
|||
handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
|
||||
ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
|
||||
/* test case sensitivity */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
|
||||
ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
|
||||
ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
|
||||
ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
|
||||
ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
|
||||
ok( !handle2, "OpenEvent succeeded\n");
|
||||
ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_NAME, /* win9x */
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
CloseHandle( handle );
|
||||
}
|
||||
|
||||
static void test_semaphore(void)
|
||||
{
|
||||
HANDLE handle, handle2;
|
||||
|
||||
/* test case sensitivity */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
|
||||
ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
|
||||
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
|
||||
ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
|
||||
ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
|
||||
ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
|
||||
ok( !handle2, "OpenSemaphore succeeded\n");
|
||||
ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_NAME, /* win9x */
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
CloseHandle( handle );
|
||||
}
|
||||
|
||||
static void test_waitable_timer(void)
|
||||
{
|
||||
HANDLE handle, handle2;
|
||||
|
||||
if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
|
||||
{
|
||||
skip("{Create,Open}WaitableTimerA() is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* test case sensitivity */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
|
||||
ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
|
||||
ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
|
||||
ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
|
||||
ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
|
||||
ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
|
||||
ok( !handle2, "OpenWaitableTimer succeeded\n");
|
||||
ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == ERROR_INVALID_NAME, /* win98 */
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
CloseHandle( handle );
|
||||
}
|
||||
|
||||
static HANDLE sem = 0;
|
||||
|
@ -289,7 +440,7 @@ static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTrans
|
|||
ReleaseSemaphore(sem, 1, NULL);
|
||||
}
|
||||
|
||||
static BOOL WINAPI (*p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
|
||||
static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
|
||||
|
||||
static void test_iocp_callback(void)
|
||||
{
|
||||
|
@ -360,16 +511,6 @@ static void test_iocp_callback(void)
|
|||
ret = DeleteFileA(filename);
|
||||
ok( ret, "DeleteFileA: error %d\n", GetLastError());
|
||||
|
||||
hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
|
||||
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
|
||||
retb = p_BindIoCompletionCallback(hFile, NULL, 0);
|
||||
ok(retb == TRUE, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
|
||||
ret = CloseHandle(hFile);
|
||||
ok( ret, "CloseHandle: error %d\n", GetLastError());
|
||||
ret = DeleteFileA(filename);
|
||||
ok( ret, "DeleteFileA: error %d\n", GetLastError());
|
||||
|
||||
/* win2k3 requires the Flags parameter to be zero */
|
||||
SetLastError(0xdeadbeef);
|
||||
hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
|
@ -388,14 +529,435 @@ static void test_iocp_callback(void)
|
|||
|
||||
retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
|
||||
ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Last error is %d\n", GetLastError());
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
|
||||
"Last error is %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
int *pn = (int *) p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
++*pn;
|
||||
}
|
||||
|
||||
struct timer_queue_data1
|
||||
{
|
||||
int num_calls;
|
||||
int max_calls;
|
||||
HANDLE q, t;
|
||||
};
|
||||
|
||||
static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
struct timer_queue_data1 *d = p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
if (d->t && ++d->num_calls == d->max_calls)
|
||||
{
|
||||
BOOL ret;
|
||||
SetLastError(0xdeadbeef);
|
||||
/* Note, XP SP2 does *not* do any deadlock checking, so passing
|
||||
INVALID_HANDLE_VALUE here will just hang. */
|
||||
ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
|
||||
ok(!ret, "DeleteTimerQueueTimer\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
struct timer_queue_data1 *d = p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
if (d->t && ++d->num_calls == d->max_calls)
|
||||
{
|
||||
/* Basically kill the timer since it won't have time to run
|
||||
again. */
|
||||
BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
|
||||
ok(ret, "ChangeTimerQueueTimer\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
struct timer_queue_data1 *d = p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
if (d->t)
|
||||
{
|
||||
/* This tests whether a timer gets flagged for deletion before
|
||||
or after the callback runs. If we start this timer with a
|
||||
period of zero (run once), then ChangeTimerQueueTimer will
|
||||
fail if the timer is already flagged. Hence we really run
|
||||
only once. Otherwise we will run multiple times. */
|
||||
BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
|
||||
ok(ret, "ChangeTimerQueueTimer\n");
|
||||
++d->num_calls;
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
DWORD delay = (DWORD) p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
if (delay)
|
||||
Sleep(delay);
|
||||
}
|
||||
|
||||
static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
|
||||
{
|
||||
struct timer_queue_data1 *d = p;
|
||||
ok(timedOut, "Timer callbacks should always time out\n");
|
||||
/* This tests an original implementation bug where a deleted timer may get
|
||||
to run, but it is tricky to set up. */
|
||||
if (d->q && d->num_calls++ == 0)
|
||||
{
|
||||
/* First run: delete ourselves, then insert and remove a timer
|
||||
that goes in front of us in the sorted timeout list. Once
|
||||
removed, we will still timeout at the faster timer's due time,
|
||||
but this should be a no-op if we are bug-free. There should
|
||||
not be a second run. We can test the value of num_calls later. */
|
||||
BOOL ret;
|
||||
HANDLE t;
|
||||
|
||||
/* The delete will pend while we are in this callback. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
|
||||
ok(!ret, "DeleteTimerQueueTimer\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
|
||||
|
||||
ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer\n");
|
||||
|
||||
/* Now we stay alive by hanging around in the callback. */
|
||||
Sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_timer_queue(void)
|
||||
{
|
||||
HANDLE q, t1, t2, t3, t4, t5;
|
||||
int n1, n2, n3, n4, n5;
|
||||
struct timer_queue_data1 d1, d2, d3, d4;
|
||||
HANDLE e, et1, et2;
|
||||
BOOL ret;
|
||||
|
||||
if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
|
||||
|| !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
|
||||
{
|
||||
skip("TimerQueue API not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test asynchronous deletion of the queue. */
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, NULL);
|
||||
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
/* Test synchronous deletion of the queue and running timers. */
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
/* Called once. */
|
||||
t1 = NULL;
|
||||
n1 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
|
||||
0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* A slow one. */
|
||||
t2 = NULL;
|
||||
n2 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
|
||||
100, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t2 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* A fast one. */
|
||||
t3 = NULL;
|
||||
n3 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
|
||||
10, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t3 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Start really late (it won't start). */
|
||||
t4 = NULL;
|
||||
n4 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
|
||||
10, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t4 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Start soon, but delay so long it won't run again. */
|
||||
t5 = NULL;
|
||||
n5 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
|
||||
10000, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t5 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Give them a chance to do some work. */
|
||||
Sleep(500);
|
||||
|
||||
/* Test deleting a once-only timer. */
|
||||
ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer\n");
|
||||
|
||||
/* A periodic timer. */
|
||||
ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer\n");
|
||||
|
||||
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
ok(n1 == 1, "Timer callback 1\n");
|
||||
ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
|
||||
ok(n4 == 0, "Timer callback 4\n");
|
||||
ok(n5 == 1, "Timer callback 5\n");
|
||||
|
||||
/* Test synchronous deletion of the timer/queue with event trigger. */
|
||||
e = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!e || !et1 || !et2)
|
||||
{
|
||||
skip("Failed to create timer queue descruction event\n");
|
||||
return;
|
||||
}
|
||||
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
/* Run once and finish quickly (should be done when we delete it). */
|
||||
t1 = NULL;
|
||||
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Run once and finish slowly (shouldn't be done when we delete it). */
|
||||
t2 = NULL;
|
||||
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
|
||||
0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t2 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Run once and finish quickly (should be done when we delete it). */
|
||||
t3 = NULL;
|
||||
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t3 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Run once and finish slowly (shouldn't be done when we delete it). */
|
||||
t4 = NULL;
|
||||
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
|
||||
0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t4 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
/* Give them a chance to start. */
|
||||
Sleep(400);
|
||||
|
||||
/* DeleteTimerQueueTimer always returns PENDING with a NULL event,
|
||||
even if the timer is finished. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueTimer(q, t1, NULL);
|
||||
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueTimer(q, t2, NULL);
|
||||
ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueTimer(q, t3, et1);
|
||||
ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
|
||||
ok(GetLastError() == 0xdeadbeef,
|
||||
"DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
|
||||
GetLastError());
|
||||
ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
|
||||
"Timer destruction event not triggered\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueTimer(q, t4, et2);
|
||||
ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
|
||||
"Timer destruction event not triggered\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, e);
|
||||
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
|
||||
"Queue destruction event not triggered\n");
|
||||
CloseHandle(e);
|
||||
|
||||
/* Test deleting/changing a timer in execution. */
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
/* Test changing a once-only timer before it fires (this is allowed,
|
||||
whereas after it fires you cannot). */
|
||||
n1 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
|
||||
0, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer\n");
|
||||
ret = pChangeTimerQueueTimer(q, t1, 0, 0);
|
||||
ok(ret, "ChangeTimerQueueTimer\n");
|
||||
|
||||
d2.t = t2 = NULL;
|
||||
d2.num_calls = 0;
|
||||
d2.max_calls = 3;
|
||||
d2.q = q;
|
||||
ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
|
||||
10, 0);
|
||||
d2.t = t2;
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t2 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
d3.t = t3 = NULL;
|
||||
d3.num_calls = 0;
|
||||
d3.max_calls = 4;
|
||||
d3.q = q;
|
||||
ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
|
||||
10, 0);
|
||||
d3.t = t3;
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t3 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
d4.t = t4 = NULL;
|
||||
d4.num_calls = 0;
|
||||
d4.q = q;
|
||||
ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
|
||||
0, 0);
|
||||
d4.t = t4;
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t4 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
Sleep(500);
|
||||
|
||||
ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueEx\n");
|
||||
ok(n1 == 1, "ChangeTimerQueueTimer\n");
|
||||
ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
|
||||
ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
|
||||
ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
|
||||
|
||||
/* Test an obscure bug that was in the original implementation. */
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
/* All the work is done in the callback. */
|
||||
d1.t = t1 = NULL;
|
||||
d1.num_calls = 0;
|
||||
d1.q = q;
|
||||
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
|
||||
100, WT_EXECUTELONGFUNCTION);
|
||||
d1.t = t1;
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
Sleep(750);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, NULL);
|
||||
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
|
||||
|
||||
/* Test functions on the default timer queue. */
|
||||
t1 = NULL;
|
||||
n1 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
|
||||
1000, 0);
|
||||
ok(ret, "CreateTimerQueueTimer, default queue\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
|
||||
|
||||
ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
|
||||
ok(ret, "ChangeTimerQueueTimer, default queue\n");
|
||||
|
||||
ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer, default queue\n");
|
||||
|
||||
/* Try mixing default and non-default queues. Apparently this works. */
|
||||
q = pCreateTimerQueue();
|
||||
ok(q != NULL, "CreateTimerQueue\n");
|
||||
|
||||
t1 = NULL;
|
||||
n1 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
|
||||
1000, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t1 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
t2 = NULL;
|
||||
n2 = 0;
|
||||
ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
|
||||
1000, 0);
|
||||
ok(ret, "CreateTimerQueueTimer\n");
|
||||
ok(t2 != NULL, "CreateTimerQueueTimer\n");
|
||||
|
||||
ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
|
||||
ok(ret, "ChangeTimerQueueTimer\n");
|
||||
|
||||
ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
|
||||
ok(ret, "ChangeTimerQueueTimer\n");
|
||||
|
||||
ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer\n");
|
||||
|
||||
ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
|
||||
ok(ret, "DeleteTimerQueueTimer\n");
|
||||
|
||||
/* Try to delete the default queue? In any case: not allowed. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(NULL, NULL);
|
||||
ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE,
|
||||
"DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
|
||||
GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pDeleteTimerQueueEx(q, NULL);
|
||||
ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(sync)
|
||||
{
|
||||
HMODULE hdll = GetModuleHandle("kernel32");
|
||||
pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
|
||||
pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
|
||||
pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
|
||||
pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
|
||||
pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
|
||||
pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
|
||||
pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
|
||||
|
||||
test_signalandwait();
|
||||
test_mutex();
|
||||
test_slist();
|
||||
test_event_security();
|
||||
test_event();
|
||||
test_semaphore();
|
||||
test_waitable_timer();
|
||||
test_iocp_callback();
|
||||
test_timer_queue();
|
||||
}
|
||||
|
|
|
@ -18,9 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
|
||||
#define _WIN32_WINNT 0x0500
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -99,6 +97,61 @@ In addition there are no checks that the inheritance works properly in
|
|||
CreateThread
|
||||
*/
|
||||
|
||||
/* Functions to ensure that from a group of threads, only one executes
|
||||
certain chunks of code at a time, and we know which one is executing
|
||||
it. It basically makes multithreaded execution linear, which defeats
|
||||
the purpose of multiple threads, but makes testing easy. */
|
||||
static HANDLE start_event, stop_event;
|
||||
static LONG num_synced;
|
||||
|
||||
static void init_thread_sync_helpers(void)
|
||||
{
|
||||
start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ok(start_event != NULL, "CreateEvent failed\n");
|
||||
stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ok(stop_event != NULL, "CreateEvent failed\n");
|
||||
num_synced = -1;
|
||||
}
|
||||
|
||||
static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
|
||||
{
|
||||
LONG num = InterlockedIncrement(&num_synced);
|
||||
assert(-1 <= num && num <= 1);
|
||||
if (num == 1)
|
||||
{
|
||||
ResetEvent( stop_event );
|
||||
SetEvent( start_event );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD ret = WaitForSingleObject(start_event, 10000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
|
||||
}
|
||||
return sync_id == my_id;
|
||||
}
|
||||
|
||||
static void resync_after_run(void)
|
||||
{
|
||||
LONG num = InterlockedDecrement(&num_synced);
|
||||
assert(-1 <= num && num <= 1);
|
||||
if (num == -1)
|
||||
{
|
||||
ResetEvent( start_event );
|
||||
SetEvent( stop_event );
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD ret = WaitForSingleObject(stop_event, 10000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_thread_sync_helpers(void)
|
||||
{
|
||||
CloseHandle(start_event);
|
||||
CloseHandle(stop_event);
|
||||
}
|
||||
|
||||
DWORD tlsIndex;
|
||||
|
||||
typedef struct {
|
||||
|
@ -320,6 +373,7 @@ static VOID test_CreateThread_basic(void)
|
|||
int error;
|
||||
DWORD i,j;
|
||||
DWORD GLE, ret;
|
||||
DWORD tid;
|
||||
|
||||
/* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
|
||||
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
|
||||
|
@ -377,7 +431,7 @@ static VOID test_CreateThread_basic(void)
|
|||
|
||||
/* Test how passing NULL as a pointer to threadid works */
|
||||
SetLastError(0xFACEaBAD);
|
||||
thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
|
||||
thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
|
||||
GLE = GetLastError();
|
||||
if (thread[0]) { /* NT */
|
||||
ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
|
||||
|
@ -398,6 +452,7 @@ static VOID test_CreateThread_suspended(void)
|
|||
{
|
||||
HANDLE thread;
|
||||
DWORD threadId;
|
||||
DWORD suspend_count;
|
||||
int error;
|
||||
|
||||
thread = CreateThread(NULL,0,threadFunc2,NULL,
|
||||
|
@ -419,6 +474,15 @@ static VOID test_CreateThread_suspended(void)
|
|||
if(error!=WAIT_OBJECT_0) {
|
||||
TerminateThread(thread,1);
|
||||
}
|
||||
|
||||
suspend_count = SuspendThread(thread);
|
||||
ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
|
||||
|
||||
suspend_count = ResumeThread(thread);
|
||||
ok(suspend_count == 0 ||
|
||||
broken(suspend_count == -1), /* win9x */
|
||||
"ResumeThread returned %d, expected 0\n", suspend_count);
|
||||
|
||||
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
|
||||
}
|
||||
|
||||
|
@ -953,6 +1017,183 @@ static void test_RegisterWaitForSingleObject(void)
|
|||
ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
|
||||
}
|
||||
|
||||
static DWORD TLS_main;
|
||||
static DWORD TLS_index0, TLS_index1;
|
||||
|
||||
static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
|
||||
{
|
||||
/* We should NOT inherit the TLS values from our parent or from the
|
||||
main thread. */
|
||||
LPVOID val;
|
||||
|
||||
val = TlsGetValue(TLS_main);
|
||||
ok(val == NULL, "TLS inheritance failed\n");
|
||||
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(val == NULL, "TLS inheritance failed\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(val == NULL, "TLS inheritance failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Basic TLS usage test. Make sure we can create slots and the values we
|
||||
store in them are separate among threads. Also test TLS value
|
||||
inheritance with TLS_InheritanceProc. */
|
||||
static DWORD WINAPI TLS_ThreadProc(LPVOID p)
|
||||
{
|
||||
LONG id = (LONG) p;
|
||||
LPVOID val;
|
||||
BOOL ret;
|
||||
|
||||
if (sync_threads_and_run_one(0, id))
|
||||
{
|
||||
TLS_index0 = TlsAlloc();
|
||||
ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
if (sync_threads_and_run_one(1, id))
|
||||
{
|
||||
TLS_index1 = TlsAlloc();
|
||||
ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
|
||||
|
||||
/* Slot indices should be different even if created in different
|
||||
threads. */
|
||||
ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
|
||||
|
||||
/* Both slots should be initialized to NULL */
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
if (sync_threads_and_run_one(0, id))
|
||||
{
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
|
||||
ret = TlsSetValue(TLS_index0, (LPVOID) 1);
|
||||
ok(ret, "TlsSetValue failed\n");
|
||||
|
||||
ret = TlsSetValue(TLS_index1, (LPVOID) 2);
|
||||
ok(ret, "TlsSetValue failed\n");
|
||||
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
if (sync_threads_and_run_one(1, id))
|
||||
{
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == NULL, "TLS slot not initialized correctly\n");
|
||||
|
||||
ret = TlsSetValue(TLS_index0, (LPVOID) 3);
|
||||
ok(ret, "TlsSetValue failed\n");
|
||||
|
||||
ret = TlsSetValue(TLS_index1, (LPVOID) 4);
|
||||
ok(ret, "TlsSetValue failed\n");
|
||||
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
if (sync_threads_and_run_one(0, id))
|
||||
{
|
||||
HANDLE thread;
|
||||
DWORD waitret, tid;
|
||||
|
||||
val = TlsGetValue(TLS_index0);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
|
||||
|
||||
val = TlsGetValue(TLS_index1);
|
||||
ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
|
||||
ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
|
||||
|
||||
thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
|
||||
ok(thread != NULL, "CreateThread failed\n");
|
||||
waitret = WaitForSingleObject(thread, 60000);
|
||||
ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
CloseHandle(thread);
|
||||
|
||||
ret = TlsFree(TLS_index0);
|
||||
ok(ret, "TlsFree failed\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
if (sync_threads_and_run_one(1, id))
|
||||
{
|
||||
ret = TlsFree(TLS_index1);
|
||||
ok(ret, "TlsFree failed\n");
|
||||
}
|
||||
resync_after_run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_TLS(void)
|
||||
{
|
||||
HANDLE threads[2];
|
||||
LONG i;
|
||||
DWORD ret;
|
||||
BOOL suc;
|
||||
|
||||
init_thread_sync_helpers();
|
||||
|
||||
/* Allocate a TLS slot in the main thread to test for inheritance. */
|
||||
TLS_main = TlsAlloc();
|
||||
ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
|
||||
suc = TlsSetValue(TLS_main, (LPVOID) 4114);
|
||||
ok(suc, "TlsSetValue failed\n");
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
DWORD tid;
|
||||
|
||||
threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
|
||||
ok(threads[i] != NULL, "CreateThread failed\n");
|
||||
}
|
||||
|
||||
ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
|
||||
ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
CloseHandle(threads[i]);
|
||||
|
||||
suc = TlsFree(TLS_main);
|
||||
ok(suc, "TlsFree failed\n");
|
||||
cleanup_thread_sync_helpers();
|
||||
}
|
||||
|
||||
START_TEST(thread)
|
||||
{
|
||||
HINSTANCE lib;
|
||||
|
@ -986,7 +1227,8 @@ START_TEST(thread)
|
|||
while (1)
|
||||
{
|
||||
HANDLE hThread;
|
||||
hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
|
||||
DWORD tid;
|
||||
hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
|
||||
ok(hThread != NULL, "CreateThread failed, error %u\n",
|
||||
GetLastError());
|
||||
ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
|
||||
|
@ -1012,4 +1254,5 @@ START_TEST(thread)
|
|||
#endif
|
||||
test_QueueUserWorkItem();
|
||||
test_RegisterWaitForSingleObject();
|
||||
test_TLS();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "winbase.h"
|
||||
|
||||
|
@ -38,11 +36,17 @@ static void test_timer(void)
|
|||
|
||||
pCreateWaitableTimerA = (fnCreateWaitableTimerA) GetProcAddress( hker, "CreateWaitableTimerA");
|
||||
if( !pCreateWaitableTimerA )
|
||||
{
|
||||
skip("CreateWaitableTimerA is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pSetWaitableTimer = (fnSetWaitableTimer) GetProcAddress( hker, "SetWaitableTimer");
|
||||
if( !pSetWaitableTimer )
|
||||
{
|
||||
skip("SetWaitableTimer is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* try once with a positive number */
|
||||
handle = pCreateWaitableTimerA( NULL, 0, NULL );
|
||||
|
|
|
@ -102,7 +102,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
{
|
||||
HANDLE hSnapshot;
|
||||
PROCESSENTRY32 pe;
|
||||
THREADENTRY32 te;
|
||||
MODULEENTRY32 me;
|
||||
unsigned found = 0;
|
||||
int num = 0;
|
||||
|
@ -144,9 +143,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
* interesting to be there, especially not the just forked off child */
|
||||
ok (childpos !=0, "child is not expected to be at position 0.\n");
|
||||
|
||||
te.dwSize = sizeof(te);
|
||||
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
|
||||
|
||||
me.dwSize = sizeof(me);
|
||||
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
|
||||
|
||||
|
@ -157,7 +153,6 @@ static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
|
||||
{
|
||||
HANDLE hSnapshot;
|
||||
PROCESSENTRY32 pe;
|
||||
THREADENTRY32 te;
|
||||
MODULEENTRY32 me;
|
||||
int num = 0;
|
||||
|
@ -175,7 +170,8 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
{
|
||||
if (te.th32OwnerProcessID == curr_pid) curr_found++;
|
||||
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
|
||||
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
|
||||
if (winetest_debug > 1)
|
||||
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
|
||||
num++;
|
||||
} while (pThread32Next( hSnapshot, &te ));
|
||||
}
|
||||
|
@ -191,16 +187,14 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
{
|
||||
if (te.th32OwnerProcessID == curr_pid) curr_found++;
|
||||
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
|
||||
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
|
||||
if (winetest_debug > 1)
|
||||
trace("PID=%x TID=%x %d\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
|
||||
num--;
|
||||
} while (pThread32Next( hSnapshot, &te ));
|
||||
}
|
||||
ok(curr_found == 1, "couldn't find self in thread list\n");
|
||||
ok(sub_found == 2, "couldn't find sub-process thread's in thread list\n");
|
||||
|
||||
pe.dwSize = sizeof(pe);
|
||||
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
|
||||
|
||||
me.dwSize = sizeof(me);
|
||||
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
|
||||
|
||||
|
@ -278,7 +272,7 @@ static void test_module(DWORD pid, const char* expected[], unsigned num_expected
|
|||
pe.dwSize = sizeof(pe);
|
||||
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
|
||||
|
||||
me.dwSize = sizeof(me);
|
||||
te.dwSize = sizeof(te);
|
||||
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
|
||||
|
||||
CloseHandle(hSnapshot);
|
||||
|
|
|
@ -92,7 +92,9 @@ static void test_GetVersionEx(void)
|
|||
SetLastError(0xdeadbeef);
|
||||
infoExA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
|
||||
ret = GetVersionExA((OSVERSIONINFOA *)&infoExA);
|
||||
ok(ret, "Expected GetVersionExA to succeed\n");
|
||||
ok(ret ||
|
||||
broken(ret == 0), /* win95 */
|
||||
"Expected GetVersionExA to succeed\n");
|
||||
ok(GetLastError() == 0xdeadbeef,
|
||||
"Expected 0xdeadbeef, got %d\n", GetLastError());
|
||||
}
|
||||
|
@ -162,8 +164,12 @@ static void test_VerifyVersionInfo(void)
|
|||
pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MAJORVERSION, VER_GREATER_EQUAL));
|
||||
if (servicepack == 0)
|
||||
ok(!ret && (GetLastError() == ERROR_OLD_WIN_VERSION),
|
||||
"VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", GetLastError());
|
||||
{
|
||||
ok(!ret || broken(ret), /* win2k3 */
|
||||
"VerifyVersionInfoA should have failed\n");
|
||||
ok(GetLastError() == ERROR_OLD_WIN_VERSION,
|
||||
"Expected ERROR_OLD_WIN_VERSION instead of %d\n", GetLastError());
|
||||
}
|
||||
else
|
||||
ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "psdk/winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/test.h"
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
|||
static HINSTANCE hkernel32;
|
||||
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
||||
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
|
||||
static UINT (WINAPI *pGetWriteWatch)(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
|
||||
static UINT (WINAPI *pResetWriteWatch)(LPVOID,SIZE_T);
|
||||
|
||||
/* ############################### */
|
||||
|
||||
|
@ -253,6 +255,32 @@ static void test_VirtualAlloc(void)
|
|||
ok(old_prot == PAGE_READONLY,
|
||||
"wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
|
||||
|
||||
/* invalid protection values */
|
||||
SetLastError(0xdeadbeef);
|
||||
addr2 = VirtualAlloc(NULL, 0x1000, MEM_RESERVE, 0);
|
||||
ok(!addr2, "VirtualAlloc succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
addr2 = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, 0);
|
||||
ok(!addr2, "VirtualAlloc succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_READONLY | PAGE_EXECUTE);
|
||||
ok(!addr2, "VirtualAlloc succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!VirtualProtect(addr1, 0x1000, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY, &old_prot),
|
||||
"VirtualProtect succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!VirtualProtect(addr1, 0x1000, 0, &old_prot), "VirtualProtect succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
|
||||
|
@ -270,6 +298,7 @@ static void test_VirtualAlloc(void)
|
|||
static void test_MapViewOfFile(void)
|
||||
{
|
||||
static const char testfile[] = "testfile.xxx";
|
||||
const char *name;
|
||||
HANDLE file, mapping;
|
||||
void *ptr, *ptr2;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
|
@ -450,50 +479,63 @@ static void test_MapViewOfFile(void)
|
|||
DeleteFileA( testfile );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "Global\\Foo");
|
||||
name = "Local\\Foo";
|
||||
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
|
||||
/* nt4 doesn't have Local\\ */
|
||||
if (!file && GetLastError() == ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
name = "Foo";
|
||||
file = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, name );
|
||||
}
|
||||
ok( file != 0, "CreateFileMapping PAGE_READWRITE error %u\n", GetLastError() );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
mapping = OpenFileMapping( FILE_MAP_READ, FALSE, "Global\\Foo" );
|
||||
mapping = OpenFileMapping( FILE_MAP_READ, FALSE, name );
|
||||
ok( mapping != 0, "OpenFileMapping FILE_MAP_READ error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
|
||||
todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_WRITE should fail\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
|
||||
"VirtualQuery error %u\n", GetLastError() );
|
||||
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
|
||||
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
|
||||
todo_wine ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
|
||||
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
|
||||
todo_wine ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
|
||||
if (!ptr)
|
||||
{
|
||||
ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
|
||||
"VirtualQuery error %u\n", GetLastError() );
|
||||
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
|
||||
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
|
||||
ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect );
|
||||
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
|
||||
ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect );
|
||||
}
|
||||
else win_skip( "no access checks on win9x\n" );
|
||||
UnmapViewOfFile( ptr );
|
||||
CloseHandle( mapping );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, "Global\\Foo" );
|
||||
mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, name );
|
||||
ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
|
||||
todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_READ should fail\n" );
|
||||
todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
|
||||
ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
|
||||
"VirtualQuery error %u\n", GetLastError() );
|
||||
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
|
||||
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
|
||||
ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
|
||||
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
|
||||
ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
|
||||
if (!ptr)
|
||||
{
|
||||
ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
|
||||
ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() );
|
||||
SetLastError(0xdeadbeef);
|
||||
ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info),
|
||||
"VirtualQuery error %u\n", GetLastError() );
|
||||
ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr );
|
||||
ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr );
|
||||
ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect );
|
||||
ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State );
|
||||
ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect );
|
||||
}
|
||||
else win_skip( "no access checks on win9x\n" );
|
||||
UnmapViewOfFile( ptr );
|
||||
CloseHandle( mapping );
|
||||
|
||||
|
@ -506,50 +548,100 @@ todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLast
|
|||
ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
|
||||
ok(ptr != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
|
||||
|
||||
ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
|
||||
/* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
|
||||
ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
|
||||
trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
|
||||
|
||||
ret = VirtualQuery(ptr, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
|
||||
ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
|
||||
ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
|
||||
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.RegionSize == MAPPING_SIZE, "RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
|
||||
todo_wine
|
||||
ok(info.State == MEM_RESERVE, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
|
||||
todo_wine
|
||||
ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
|
||||
{
|
||||
ok(info.AllocationProtect == PAGE_NOACCESS,
|
||||
"AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.Protect == PAGE_NOACCESS,
|
||||
"Protect should have been PAGE_NOACCESS instead of 0x%x\n", info.Protect);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(info.AllocationProtect == PAGE_READWRITE,
|
||||
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.Protect == 0, "Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
}
|
||||
|
||||
ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (ptr != ptr2)
|
||||
{
|
||||
ret = VirtualQuery(ptr2, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
|
||||
ok(info.BaseAddress == ptr2,
|
||||
"BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
|
||||
ok(info.AllocationBase == ptr2,
|
||||
"AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
|
||||
ok(info.AllocationProtect == PAGE_READWRITE,
|
||||
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.RegionSize == MAPPING_SIZE,
|
||||
"RegionSize should have been 0x%x but was 0x%x\n", MAPPING_SIZE, (unsigned int)info.RegionSize);
|
||||
ok(info.State == MEM_RESERVE,
|
||||
"State should have been MEM_RESERVE instead of 0x%x\n", info.State);
|
||||
ok(info.Protect == 0,
|
||||
"Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED,
|
||||
"Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
}
|
||||
|
||||
ptr = VirtualAlloc(ptr, 0x10000, MEM_COMMIT, PAGE_READONLY);
|
||||
ok(ptr != NULL, "VirtualAlloc failed with error %d\n", GetLastError());
|
||||
|
||||
ret = VirtualQuery(ptr, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
|
||||
ok(info.BaseAddress == ptr, "BaseAddress should have been %p but was %p instead\n", ptr, info.BaseAddress);
|
||||
ok(info.AllocationBase == ptr, "AllocationBase should have been %p but was %p instead\n", ptr, info.AllocationBase);
|
||||
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
todo_wine
|
||||
ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
|
||||
ok(info.State == MEM_COMMIT, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
|
||||
ok(info.Protect == PAGE_READWRITE, "Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
|
||||
ptr2 = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
|
||||
/* on NT ptr != ptr2 but on Win9x ptr == ptr2 */
|
||||
ok(ptr2 != NULL, "MapViewOfFile failed with error %d\n", GetLastError());
|
||||
trace("mapping same section resulted in views %p and %p\n", ptr, ptr2);
|
||||
ok(info.Protect == PAGE_READONLY, "Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
if (info.Type == MEM_PRIVATE) /* win9x is different for uncommitted mappings */
|
||||
{
|
||||
ok(info.AllocationProtect == PAGE_NOACCESS,
|
||||
"AllocationProtect should have been PAGE_NOACCESS but was 0x%x\n", info.AllocationProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(info.AllocationProtect == PAGE_READWRITE,
|
||||
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
}
|
||||
|
||||
/* shows that the VirtualAlloc above affects the mapping, not just the
|
||||
* virtual memory in this process - it also affects all other processes
|
||||
* with a view of the mapping, but that isn't tested here */
|
||||
ret = VirtualQuery(ptr2, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
|
||||
ok(info.BaseAddress == ptr2, "BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
|
||||
ok(info.AllocationBase == ptr2, "AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
|
||||
ok(info.AllocationProtect == PAGE_READWRITE, "AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
todo_wine
|
||||
ok(info.RegionSize == 0x10000, "RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
|
||||
ok(info.State == MEM_COMMIT, "State should have been MEM_RESERVE instead of 0x%x\n", info.State);
|
||||
ok(info.Protect == PAGE_READWRITE, "Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
if (ptr != ptr2)
|
||||
{
|
||||
ret = VirtualQuery(ptr2, &info, sizeof(info));
|
||||
ok(ret, "VirtualQuery failed with error %d\n", GetLastError());
|
||||
ok(info.BaseAddress == ptr2,
|
||||
"BaseAddress should have been %p but was %p instead\n", ptr2, info.BaseAddress);
|
||||
ok(info.AllocationBase == ptr2,
|
||||
"AllocationBase should have been %p but was %p instead\n", ptr2, info.AllocationBase);
|
||||
ok(info.AllocationProtect == PAGE_READWRITE,
|
||||
"AllocationProtect should have been PAGE_READWRITE but was 0x%x\n", info.AllocationProtect);
|
||||
ok(info.RegionSize == 0x10000,
|
||||
"RegionSize should have been 0x10000 but was 0x%x\n", (unsigned int)info.RegionSize);
|
||||
ok(info.State == MEM_COMMIT,
|
||||
"State should have been MEM_RESERVE instead of 0x%x\n", info.State);
|
||||
ok(info.Protect == PAGE_READWRITE,
|
||||
"Protect should have been 0 instead of 0x%x\n", info.Protect);
|
||||
ok(info.Type == MEM_MAPPED, "Type should have been MEM_MAPPED instead of 0x%x\n", info.Type);
|
||||
}
|
||||
|
||||
ret = VirtualFree( ptr, 0x10000, MEM_DECOMMIT );
|
||||
ok( !ret || broken(ret) /* win9x */, "VirtualFree succeeded\n" );
|
||||
if (!ret)
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "VirtualFree failed with %u\n", GetLastError() );
|
||||
|
||||
ret = UnmapViewOfFile(ptr2);
|
||||
ok(ret, "UnmapViewOfFile failed with error %d\n", GetLastError());
|
||||
|
@ -622,6 +714,46 @@ static void test_NtMapViewOfSection(void)
|
|||
CloseHandle(hProcess);
|
||||
}
|
||||
|
||||
static void test_CreateFileMapping(void)
|
||||
{
|
||||
HANDLE handle, handle2;
|
||||
|
||||
/* test case sensitivity */
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
|
||||
"Wine Test Mapping");
|
||||
ok( handle != NULL, "CreateFileMapping failed with error %u\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
|
||||
"Wine Test Mapping");
|
||||
ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE, 0, 0x1000,
|
||||
"WINE TEST MAPPING");
|
||||
ok( handle2 != NULL, "CreateFileMapping failed with error %d\n", GetLastError());
|
||||
ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "Wine Test Mapping");
|
||||
ok( handle2 != NULL, "OpenFileMapping failed with error %d\n", GetLastError());
|
||||
CloseHandle( handle2 );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
handle2 = OpenFileMappingA( FILE_MAP_ALL_ACCESS, FALSE, "WINE TEST MAPPING");
|
||||
ok( !handle2, "OpenFileMapping succeeded\n");
|
||||
ok( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME /* win9x */,
|
||||
"wrong error %u\n", GetLastError());
|
||||
|
||||
CloseHandle( handle );
|
||||
}
|
||||
|
||||
static void test_BadPtr(void)
|
||||
{
|
||||
void *ptr = (void*)1;
|
||||
|
@ -631,6 +763,306 @@ static void test_BadPtr(void)
|
|||
ok(IsBadCodePtr(ptr),"IsBadCodePtr(1) failed.\n");
|
||||
}
|
||||
|
||||
static void test_write_watch(void)
|
||||
{
|
||||
char *base;
|
||||
DWORD ret, size, old_prot;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
void *results[64];
|
||||
ULONG_PTR count;
|
||||
ULONG pagesize;
|
||||
|
||||
if (!pGetWriteWatch || !pResetWriteWatch)
|
||||
{
|
||||
win_skip( "GetWriteWatch not supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
size = 0x10000;
|
||||
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, PAGE_READWRITE );
|
||||
if (!base &&
|
||||
(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
win_skip( "MEM_WRITE_WATCH not supported\n" );
|
||||
return;
|
||||
}
|
||||
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
ret = VirtualQuery( base, &info, sizeof(info) );
|
||||
ok(ret, "VirtualQuery failed %u\n", GetLastError());
|
||||
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
|
||||
ok( info.AllocationProtect == PAGE_READWRITE, "wrong AllocationProtect %x\n", info.AllocationProtect );
|
||||
ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
|
||||
ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
|
||||
ok( info.Type == MEM_PRIVATE, "wrong Type 0x%x\n", info.Type );
|
||||
|
||||
count = 64;
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetWriteWatch( 0, NULL, size, results, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
|
||||
broken( GetLastError() == 0xdeadbeef ), /* win98 */
|
||||
"wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetWriteWatch( 0, GetModuleHandle(0), size, results, &count, &pagesize );
|
||||
if (ret)
|
||||
{
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
}
|
||||
else /* win98 */
|
||||
{
|
||||
ok( count == 0, "wrong count %lu\n", count );
|
||||
}
|
||||
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 0, "wrong count %lu\n", count );
|
||||
|
||||
base[pagesize + 1] = 0x44;
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 0, "wrong count %lu\n", count );
|
||||
|
||||
base[2*pagesize + 3] = 0x11;
|
||||
base[4*pagesize + 8] = 0x11;
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 2, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
|
||||
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base + 3*pagesize, 2*pagesize, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
ret = pResetWriteWatch( base, 3*pagesize );
|
||||
ok( !ret, "pResetWriteWatch failed %u\n", GetLastError() );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 4*pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
*(DWORD *)(base + 2*pagesize - 2) = 0xdeadbeef;
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 3, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
|
||||
ok( results[1] == base + 2*pagesize, "wrong result %p\n", results[1] );
|
||||
ok( results[2] == base + 4*pagesize, "wrong result %p\n", results[2] );
|
||||
|
||||
count = 1;
|
||||
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 2, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
|
||||
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
|
||||
|
||||
/* changing protections doesn't affect watches */
|
||||
|
||||
ret = VirtualProtect( base, 3*pagesize, PAGE_READONLY, &old_prot );
|
||||
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
|
||||
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
|
||||
ret = VirtualQuery( base, &info, sizeof(info) );
|
||||
ok(ret, "VirtualQuery failed %u\n", GetLastError());
|
||||
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
|
||||
ok( info.RegionSize == 3*pagesize, "wrong RegionSize 0x%lx\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
|
||||
ok( info.Protect == PAGE_READONLY, "wrong Protect 0x%x\n", info.Protect );
|
||||
|
||||
ret = VirtualProtect( base, 3*pagesize, PAGE_READWRITE, &old_prot );
|
||||
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
|
||||
ok( old_prot == PAGE_READONLY, "wrong old prot %x\n", old_prot );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 2, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 2*pagesize, "wrong result %p\n", results[0] );
|
||||
ok( results[1] == base + 4*pagesize, "wrong result %p\n", results[1] );
|
||||
|
||||
ret = VirtualQuery( base, &info, sizeof(info) );
|
||||
ok(ret, "VirtualQuery failed %u\n", GetLastError());
|
||||
ok( info.BaseAddress == base, "BaseAddress %p instead of %p\n", info.BaseAddress, base );
|
||||
ok( info.RegionSize == size, "wrong RegionSize 0x%lx\n", info.RegionSize );
|
||||
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
|
||||
ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
|
||||
|
||||
/* some invalid parameter tests */
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 0;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
if (ret)
|
||||
{
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetWriteWatch( 0, base, size, results, NULL, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, NULL );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 0;
|
||||
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size * 2, results, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base + size - pagesize, pagesize + 1, results, &count, &pagesize );
|
||||
ok( ret == ~0u, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pResetWriteWatch( base, 0 );
|
||||
ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pResetWriteWatch( GetModuleHandle(0), size );
|
||||
ok( ret == ~0u, "ResetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
}
|
||||
else /* win98 is completely different */
|
||||
{
|
||||
SetLastError( 0xdeadbeef );
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
|
||||
ok( ret == ERROR_INVALID_PARAMETER, "GetWriteWatch succeeded %u\n", ret );
|
||||
ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
|
||||
|
||||
count = 0;
|
||||
ret = pGetWriteWatch( 0, base, size, NULL, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", ret );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0xdeadbeef, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", ret );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, 0, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", ret );
|
||||
|
||||
ret = pResetWriteWatch( base, 0 );
|
||||
ok( !ret, "ResetWriteWatch failed %u\n", ret );
|
||||
|
||||
ret = pResetWriteWatch( GetModuleHandle(0), size );
|
||||
ok( !ret, "ResetWriteWatch failed %u\n", ret );
|
||||
}
|
||||
|
||||
VirtualFree( base, 0, MEM_FREE );
|
||||
|
||||
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_READWRITE );
|
||||
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
VirtualFree( base, 0, MEM_FREE );
|
||||
|
||||
base = VirtualAlloc( 0, size, MEM_WRITE_WATCH, PAGE_READWRITE );
|
||||
ok( !base, "VirtualAlloc succeeded\n" );
|
||||
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
|
||||
|
||||
/* initial protect doesn't matter */
|
||||
|
||||
base = VirtualAlloc( 0, size, MEM_RESERVE | MEM_WRITE_WATCH, PAGE_NOACCESS );
|
||||
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
base = VirtualAlloc( base, size, MEM_COMMIT, PAGE_NOACCESS );
|
||||
ok( base != NULL, "VirtualAlloc failed %u\n", GetLastError() );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 0, "wrong count %lu\n", count );
|
||||
|
||||
ret = VirtualProtect( base, 6*pagesize, PAGE_READWRITE, &old_prot );
|
||||
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
|
||||
ok( old_prot == PAGE_NOACCESS, "wrong old prot %x\n", old_prot );
|
||||
|
||||
base[5*pagesize + 200] = 3;
|
||||
|
||||
ret = VirtualProtect( base, 6*pagesize, PAGE_NOACCESS, &old_prot );
|
||||
ok( ret, "VirtualProtect failed error %u\n", GetLastError() );
|
||||
ok( old_prot == PAGE_READWRITE, "wrong old prot %x\n", old_prot );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
ret = VirtualFree( base, size, MEM_DECOMMIT );
|
||||
ok( ret, "VirtualFree failed %u\n", GetLastError() );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( 0, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 1 || broken(count == 0), /* win98 */
|
||||
"wrong count %lu\n", count );
|
||||
if (count) ok( results[0] == base + 5*pagesize, "wrong result %p\n", results[0] );
|
||||
|
||||
VirtualFree( base, 0, MEM_FREE );
|
||||
}
|
||||
|
||||
START_TEST(virtual)
|
||||
{
|
||||
int argc;
|
||||
|
@ -662,10 +1094,14 @@ START_TEST(virtual)
|
|||
hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
||||
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
||||
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
|
||||
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
|
||||
|
||||
test_VirtualAllocEx();
|
||||
test_VirtualAlloc();
|
||||
test_MapViewOfFile();
|
||||
test_NtMapViewOfSection();
|
||||
test_CreateFileMapping();
|
||||
test_BadPtr();
|
||||
test_write_watch();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD
|
|||
static HANDLE (WINAPI *pFindFirstVolumeA)(LPSTR,DWORD);
|
||||
static BOOL (WINAPI *pFindNextVolumeA)(HANDLE,LPSTR,DWORD);
|
||||
static BOOL (WINAPI *pFindVolumeClose)(HANDLE);
|
||||
static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR);
|
||||
static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR);
|
||||
|
||||
/* ############################### */
|
||||
|
||||
|
@ -37,6 +39,11 @@ static void test_query_dos_deviceA(void)
|
|||
DWORD ret;
|
||||
BOOL found = FALSE;
|
||||
|
||||
if (!pFindFirstVolumeA) {
|
||||
skip("On win9x, HARDDISK and RAMDISK not present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;drivestr[0] <= 'z'; drivestr[0]++) {
|
||||
ret = QueryDosDeviceA( drivestr, buffer, sizeof(buffer));
|
||||
if(ret) {
|
||||
|
@ -44,7 +51,7 @@ static void test_query_dos_deviceA(void)
|
|||
if (strstr(buffer, "HARDDISK") || strstr(buffer, "RAMDISK")) found = TRUE;
|
||||
}
|
||||
}
|
||||
todo_wine ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
|
||||
ok(found, "expected at least one devicename to contain HARDDISK or RAMDISK\n");
|
||||
}
|
||||
|
||||
static void test_FindFirstVolume(void)
|
||||
|
@ -134,6 +141,81 @@ static void test_GetVolumeNameForVolumeMountPointW(void)
|
|||
ok(ret == TRUE, "GetVolumeNameForVolumeMountPointW failed\n");
|
||||
}
|
||||
|
||||
static void test_GetLogicalDriveStringsA(void)
|
||||
{
|
||||
UINT size, size2;
|
||||
char *buf, *ptr;
|
||||
|
||||
if(!pGetLogicalDriveStringsA) {
|
||||
win_skip("GetLogicalDriveStringsA not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size = pGetLogicalDriveStringsA(0, NULL);
|
||||
ok(size%4 == 1, "size = %d\n", size);
|
||||
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
|
||||
*buf = 0;
|
||||
size2 = pGetLogicalDriveStringsA(2, buf);
|
||||
ok(size2 == size, "size2 = %d\n", size2);
|
||||
ok(!*buf, "buf changed\n");
|
||||
|
||||
size2 = pGetLogicalDriveStringsA(size, buf);
|
||||
ok(size2 == size-1, "size2 = %d\n", size2);
|
||||
|
||||
for(ptr = buf; ptr < buf+size2; ptr += 4) {
|
||||
ok(('A' <= *ptr && *ptr <= 'Z') ||
|
||||
(broken('a' <= *ptr && *ptr <= 'z')), /* Win9x and WinMe */
|
||||
"device name '%c' is not uppercase\n", *ptr);
|
||||
ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
|
||||
ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
|
||||
ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
|
||||
}
|
||||
ok(!*ptr, "buf[size2] is not nullbyte\n");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
static void test_GetLogicalDriveStringsW(void)
|
||||
{
|
||||
UINT size, size2;
|
||||
WCHAR *buf, *ptr;
|
||||
|
||||
if(!pGetLogicalDriveStringsW) {
|
||||
win_skip("GetLogicalDriveStringsW not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
size = pGetLogicalDriveStringsW(0, NULL);
|
||||
if (size == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
|
||||
win_skip("GetLogicalDriveStringsW not implemented\n");
|
||||
return;
|
||||
}
|
||||
ok(size%4 == 1, "size = %d\n", size);
|
||||
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
|
||||
|
||||
*buf = 0;
|
||||
size2 = pGetLogicalDriveStringsW(2, buf);
|
||||
ok(size2 == size, "size2 = %d\n", size2);
|
||||
ok(!*buf, "buf changed\n");
|
||||
|
||||
size2 = pGetLogicalDriveStringsW(size, buf);
|
||||
ok(size2 == size-1, "size2 = %d\n", size2);
|
||||
|
||||
for(ptr = buf; ptr < buf+size2; ptr += 4) {
|
||||
ok('A' <= *ptr && *ptr <= 'Z', "device name '%c' is not uppercase\n", *ptr);
|
||||
ok(ptr[1] == ':', "ptr[1] = %c, expected ':'\n", ptr[1]);
|
||||
ok(ptr[2] == '\\', "ptr[2] = %c expected '\\'\n", ptr[2]);
|
||||
ok(!ptr[3], "ptr[3] = %c expected nullbyte\n", ptr[3]);
|
||||
}
|
||||
ok(!*ptr, "buf[size2] is not nullbyte\n");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
START_TEST(volume)
|
||||
{
|
||||
hdll = GetModuleHandleA("kernel32.dll");
|
||||
|
@ -142,9 +224,13 @@ START_TEST(volume)
|
|||
pFindFirstVolumeA = (void *) GetProcAddress(hdll, "FindFirstVolumeA");
|
||||
pFindNextVolumeA = (void *) GetProcAddress(hdll, "FindNextVolumeA");
|
||||
pFindVolumeClose = (void *) GetProcAddress(hdll, "FindVolumeClose");
|
||||
pGetLogicalDriveStringsA = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsA");
|
||||
pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
|
||||
|
||||
test_query_dos_deviceA();
|
||||
test_FindFirstVolume();
|
||||
test_GetVolumeNameForVolumeMountPointA();
|
||||
test_GetVolumeNameForVolumeMountPointW();
|
||||
test_GetLogicalDriveStringsA();
|
||||
test_GetLogicalDriveStringsW();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue