mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[KERNEL32_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
svn path=/trunk/; revision=70069
This commit is contained in:
parent
e2b52d2ea8
commit
a3183aed2b
18 changed files with 3224 additions and 376 deletions
|
@ -16,6 +16,8 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <wine/test.h>
|
||||
#include <winbase.h>
|
||||
#include <windef.h>
|
||||
|
@ -39,6 +41,10 @@ static BOOL (WINAPI *pQueryActCtxW)(DWORD,HANDLE,PVOID,ULONG,PVOID,SIZE_T,SIZE
|
|||
static VOID (WINAPI *pReleaseActCtx)(HANDLE);
|
||||
static BOOL (WINAPI *pFindActCtxSectionGuid)(DWORD,const GUID*,ULONG,const GUID*,PACTCTX_SECTION_KEYED_DATA);
|
||||
|
||||
static NTSTATUS(NTAPI *pRtlFindActivationContextSectionString)(DWORD,const GUID *,ULONG,PUNICODE_STRING,PACTCTX_SECTION_KEYED_DATA);
|
||||
static BOOLEAN (NTAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, PCSZ);
|
||||
static VOID (NTAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||
|
||||
static const char* strw(LPCWSTR x)
|
||||
{
|
||||
static char buffer[1024];
|
||||
|
@ -53,6 +59,10 @@ static const char* strw(LPCWSTR x)
|
|||
#define ARCH "x86"
|
||||
#elif defined __x86_64__
|
||||
#define ARCH "amd64"
|
||||
#elif defined __arm__
|
||||
#define ARCH "arm"
|
||||
#elif defined __aarch64__
|
||||
#define ARCH "arm64"
|
||||
#else
|
||||
#define ARCH "none"
|
||||
#endif
|
||||
|
@ -2048,6 +2058,124 @@ static void test_app_manifest(void)
|
|||
}
|
||||
}
|
||||
|
||||
static HANDLE create_manifest(const char *filename, const char *data, int line)
|
||||
{
|
||||
HANDLE handle;
|
||||
create_manifest_file(filename, data, -1, NULL, NULL);
|
||||
|
||||
handle = test_create(filename);
|
||||
ok_(__FILE__, line)(handle != INVALID_HANDLE_VALUE,
|
||||
"handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
|
||||
|
||||
DeleteFileA(filename);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void kernel32_find(ULONG section, const char *string_to_find, BOOL should_find, int line)
|
||||
{
|
||||
UNICODE_STRING string_to_findW;
|
||||
ACTCTX_SECTION_KEYED_DATA data;
|
||||
BOOL ret;
|
||||
DWORD err;
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&string_to_findW, string_to_find);
|
||||
|
||||
memset(&data, 0xfe, sizeof(data));
|
||||
data.cbSize = sizeof(data);
|
||||
|
||||
SetLastError(0);
|
||||
ret = pFindActCtxSectionStringA(0, NULL, section, string_to_find, &data);
|
||||
err = GetLastError();
|
||||
ok_(__FILE__, line)(ret == should_find,
|
||||
"FindActCtxSectionStringA: expected ret = %u, got %u\n", should_find, ret);
|
||||
ok_(__FILE__, line)(err == (should_find ? ERROR_SUCCESS : ERROR_SXS_KEY_NOT_FOUND),
|
||||
"FindActCtxSectionStringA: unexpected error %u\n", err);
|
||||
|
||||
memset(&data, 0xfe, sizeof(data));
|
||||
data.cbSize = sizeof(data);
|
||||
|
||||
SetLastError(0);
|
||||
ret = pFindActCtxSectionStringW(0, NULL, section, string_to_findW.Buffer, &data);
|
||||
err = GetLastError();
|
||||
ok_(__FILE__, line)(ret == should_find,
|
||||
"FindActCtxSectionStringW: expected ret = %u, got %u\n", should_find, ret);
|
||||
ok_(__FILE__, line)(err == (should_find ? ERROR_SUCCESS : ERROR_SXS_KEY_NOT_FOUND),
|
||||
"FindActCtxSectionStringW: unexpected error %u\n", err);
|
||||
|
||||
SetLastError(0);
|
||||
ret = pFindActCtxSectionStringA(0, NULL, section, string_to_find, NULL);
|
||||
err = GetLastError();
|
||||
ok_(__FILE__, line)(!ret,
|
||||
"FindActCtxSectionStringA: expected failure, got %u\n", ret);
|
||||
ok_(__FILE__, line)(err == ERROR_INVALID_PARAMETER,
|
||||
"FindActCtxSectionStringA: unexpected error %u\n", err);
|
||||
|
||||
SetLastError(0);
|
||||
ret = pFindActCtxSectionStringW(0, NULL, section, string_to_findW.Buffer, NULL);
|
||||
err = GetLastError();
|
||||
ok_(__FILE__, line)(!ret,
|
||||
"FindActCtxSectionStringW: expected failure, got %u\n", ret);
|
||||
ok_(__FILE__, line)(err == ERROR_INVALID_PARAMETER,
|
||||
"FindActCtxSectionStringW: unexpected error %u\n", err);
|
||||
|
||||
pRtlFreeUnicodeString(&string_to_findW);
|
||||
}
|
||||
|
||||
static void ntdll_find(ULONG section, const char *string_to_find, BOOL should_find, int line)
|
||||
{
|
||||
UNICODE_STRING string_to_findW;
|
||||
ACTCTX_SECTION_KEYED_DATA data;
|
||||
NTSTATUS ret;
|
||||
|
||||
pRtlCreateUnicodeStringFromAsciiz(&string_to_findW, string_to_find);
|
||||
|
||||
memset(&data, 0xfe, sizeof(data));
|
||||
data.cbSize = sizeof(data);
|
||||
|
||||
ret = pRtlFindActivationContextSectionString(0, NULL, section, &string_to_findW, &data);
|
||||
ok_(__FILE__, line)(ret == (should_find ? STATUS_SUCCESS : STATUS_SXS_KEY_NOT_FOUND),
|
||||
"RtlFindActivationContextSectionString: unexpected status 0x%x\n", ret);
|
||||
|
||||
ret = pRtlFindActivationContextSectionString(0, NULL, section, &string_to_findW, NULL);
|
||||
ok_(__FILE__, line)(ret == (should_find ? STATUS_SUCCESS : STATUS_SXS_KEY_NOT_FOUND),
|
||||
"RtlFindActivationContextSectionString: unexpected status 0x%x\n", ret);
|
||||
|
||||
pRtlFreeUnicodeString(&string_to_findW);
|
||||
}
|
||||
|
||||
static void test_findsectionstring(void)
|
||||
{
|
||||
HANDLE handle;
|
||||
BOOL ret;
|
||||
ULONG_PTR cookie;
|
||||
|
||||
handle = create_manifest("test.manifest", testdep_manifest3, __LINE__);
|
||||
ret = pActivateActCtx(handle, &cookie);
|
||||
ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
|
||||
|
||||
/* first we show the parameter validation from kernel32 */
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, __LINE__);
|
||||
kernel32_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, __LINE__);
|
||||
|
||||
/* then we show that ntdll plays by different rules */
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, "testdep", FALSE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib.dll", TRUE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib2.dll", TRUE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, "testlib3.dll", FALSE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass", TRUE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass2", TRUE, __LINE__);
|
||||
ntdll_find(ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, "wndClass3", FALSE, __LINE__);
|
||||
|
||||
ret = pDeactivateActCtx(0, cookie);
|
||||
ok(ret, "DeactivateActCtx failed: %u\n", GetLastError());
|
||||
pReleaseActCtx(handle);
|
||||
}
|
||||
|
||||
static void run_child_process(void)
|
||||
{
|
||||
char cmdline[MAX_PATH];
|
||||
|
@ -2263,9 +2391,9 @@ todo_wine
|
|||
|
||||
static BOOL init_funcs(void)
|
||||
{
|
||||
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
||||
HMODULE hLibrary = GetModuleHandleA("kernel32.dll");
|
||||
|
||||
#define X(f) if (!(p##f = (void*)GetProcAddress(hKernel32, #f))) return FALSE;
|
||||
#define X(f) if (!(p##f = (void*)GetProcAddress(hLibrary, #f))) return FALSE;
|
||||
X(ActivateActCtx);
|
||||
X(CreateActCtxA);
|
||||
X(CreateActCtxW);
|
||||
|
@ -2277,6 +2405,11 @@ static BOOL init_funcs(void)
|
|||
X(QueryActCtxW);
|
||||
X(ReleaseActCtx);
|
||||
X(FindActCtxSectionGuid);
|
||||
|
||||
hLibrary = GetModuleHandleA("ntdll.dll");
|
||||
X(RtlFindActivationContextSectionString);
|
||||
X(RtlCreateUnicodeStringFromAsciiz);
|
||||
X(RtlFreeUnicodeString);
|
||||
#undef X
|
||||
|
||||
return TRUE;
|
||||
|
@ -2303,5 +2436,6 @@ START_TEST(actctx)
|
|||
|
||||
test_actctx();
|
||||
test_CreateActCtx();
|
||||
test_findsectionstring();
|
||||
run_child_process();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
|
||||
static const char foobarA[] = "foobar";
|
||||
static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
|
||||
|
||||
static void test_destination_buffer(void)
|
||||
|
@ -144,48 +145,57 @@ static void test_negative_source_length(void)
|
|||
static void test_negative_dest_length(void)
|
||||
{
|
||||
int len, i;
|
||||
static char buf[LONGBUFLEN];
|
||||
static WCHAR bufW[LONGBUFLEN];
|
||||
static char bufA[LONGBUFLEN];
|
||||
static WCHAR originalW[LONGBUFLEN];
|
||||
static char originalA[LONGBUFLEN];
|
||||
DWORD theError;
|
||||
|
||||
/* Test return on -1 dest length */
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(buf,'x',sizeof(buf));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buf, -1, NULL, NULL);
|
||||
todo_wine {
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"WideCharToMultiByte(destlen -1): len=%d error=%x\n", len, GetLastError());
|
||||
}
|
||||
memset(bufA,'x',sizeof(bufA));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, bufA, -1, NULL, NULL);
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"WideCharToMultiByte(destlen -1): len=%d error=%x\n", len, GetLastError());
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(bufW,'x',sizeof(bufW));
|
||||
len = MultiByteToWideChar(CP_ACP, 0, foobarA, -1, bufW, -1);
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"MultiByteToWideChar(destlen -1): len=%d error=%x\n", len, GetLastError());
|
||||
|
||||
/* Test return on -1000 dest length */
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(buf,'x',sizeof(buf));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buf, -1000, NULL, NULL);
|
||||
todo_wine {
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"WideCharToMultiByte(destlen -1000): len=%d error=%x\n", len, GetLastError());
|
||||
}
|
||||
memset(bufA,'x',sizeof(bufA));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, bufA, -1000, NULL, NULL);
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"WideCharToMultiByte(destlen -1000): len=%d error=%x\n", len, GetLastError());
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(bufW,'x',sizeof(bufW));
|
||||
len = MultiByteToWideChar(CP_ACP, 0, foobarA, -1000, bufW, -1);
|
||||
ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"MultiByteToWideChar(destlen -1000): len=%d error=%x\n", len, GetLastError());
|
||||
|
||||
/* Test return on INT_MAX dest length */
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(buf,'x',sizeof(buf));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, buf, INT_MAX, NULL, NULL);
|
||||
ok(len == 7 && !lstrcmpA(buf, "foobar") && GetLastError() == 0xdeadbeef,
|
||||
memset(bufA,'x',sizeof(bufA));
|
||||
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, bufA, INT_MAX, NULL, NULL);
|
||||
ok(len == 7 && !lstrcmpA(bufA, "foobar") && GetLastError() == 0xdeadbeef,
|
||||
"WideCharToMultiByte(destlen INT_MAX): len=%d error=%x\n", len, GetLastError());
|
||||
|
||||
/* Test return on INT_MAX dest length and very long input */
|
||||
SetLastError( 0xdeadbeef );
|
||||
memset(buf,'x',sizeof(buf));
|
||||
memset(bufA,'x',sizeof(bufA));
|
||||
for (i=0; i < LONGBUFLEN - 1; i++) {
|
||||
originalW[i] = 'Q';
|
||||
originalA[i] = 'Q';
|
||||
}
|
||||
originalW[LONGBUFLEN-1] = 0;
|
||||
originalA[LONGBUFLEN-1] = 0;
|
||||
len = WideCharToMultiByte(CP_ACP, 0, originalW, -1, buf, INT_MAX, NULL, NULL);
|
||||
len = WideCharToMultiByte(CP_ACP, 0, originalW, -1, bufA, INT_MAX, NULL, NULL);
|
||||
theError = GetLastError();
|
||||
ok(len == LONGBUFLEN && !lstrcmpA(buf, originalA) && theError == 0xdeadbeef,
|
||||
ok(len == LONGBUFLEN && !lstrcmpA(bufA, originalA) && theError == 0xdeadbeef,
|
||||
"WideCharToMultiByte(srclen %d, destlen INT_MAX): len %d error=%x\n", LONGBUFLEN, len, theError);
|
||||
|
||||
}
|
||||
|
@ -276,12 +286,14 @@ static void test_overlapped_buffers(void)
|
|||
static void test_string_conversion(LPBOOL bUsedDefaultChar)
|
||||
{
|
||||
char mbc;
|
||||
char mbs[5];
|
||||
char mbs[15];
|
||||
int ret;
|
||||
WCHAR wc1 = 228; /* Western Windows-1252 character */
|
||||
WCHAR wc2 = 1088; /* Russian Windows-1251 character not displayable for Windows-1252 */
|
||||
static const WCHAR wcs[] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */
|
||||
static const WCHAR dbwcs[] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */
|
||||
static const WCHAR dbwcs2[] = {0x7bb8, 0x3d, 0xc813, 0xac00, 0xb77d, 0};
|
||||
static const char default_char[] = {0xa3, 0xbf, 0};
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar);
|
||||
|
@ -358,6 +370,11 @@ static void test_string_conversion(LPBOOL bUsedDefaultChar)
|
|||
ok(!strcmp(mbs, "??"), "mbs is %s\n", mbs);
|
||||
if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar);
|
||||
|
||||
ret = WideCharToMultiByte(936, WC_COMPOSITECHECK, dbwcs2, -1, mbs, sizeof(mbs), (const char *)default_char, bUsedDefaultChar);
|
||||
ok(ret == 10, "ret is %d\n", ret);
|
||||
ok(!strcmp(mbs, "\xf3\xe7\x3d\xa3\xbf\xa3\xbf\xa3\xbf"), "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);
|
||||
|
|
|
@ -941,7 +941,8 @@ static void test_waittxempty(void)
|
|||
evtmask = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
res = WaitCommEvent(hcom, &evtmask, &ovl_wait);
|
||||
ok((!res && GetLastError() == ERROR_IO_PENDING) || res /* busy system */, "%d: WaitCommEvent error %d\n", i, GetLastError());
|
||||
ok(res /* busy system */ || GetLastError() == ERROR_IO_PENDING,
|
||||
"%d: WaitCommEvent error %d\n", i, GetLastError());
|
||||
|
||||
res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
|
||||
if (i == 0)
|
||||
|
|
|
@ -2588,6 +2588,99 @@ static void test_ReadConsole(void)
|
|||
ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
|
||||
}
|
||||
|
||||
static void test_GetCurrentConsoleFont(HANDLE std_output)
|
||||
{
|
||||
BOOL ret;
|
||||
CONSOLE_FONT_INFO cfi;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
short int width, height;
|
||||
COORD c;
|
||||
|
||||
memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetCurrentConsoleFont(NULL, FALSE, &cfi);
|
||||
ok(!ret, "got %d, expected 0\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
|
||||
ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
|
||||
ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
|
||||
|
||||
memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE), FALSE, &cfi);
|
||||
ok(!ret, "got %d, expected 0\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
|
||||
ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
|
||||
ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
|
||||
|
||||
memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetCurrentConsoleFont(std_output, FALSE, &cfi);
|
||||
ok(ret, "got %d, expected non-zero\n", ret);
|
||||
ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
|
||||
GetConsoleScreenBufferInfo(std_output, &csbi);
|
||||
width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
c = GetConsoleFontSize(std_output, cfi.nFont);
|
||||
ok(cfi.dwFontSize.X == width || cfi.dwFontSize.X == c.X /* Vista and higher */,
|
||||
"got %d, expected %d\n", cfi.dwFontSize.X, width);
|
||||
ok(cfi.dwFontSize.Y == height || cfi.dwFontSize.Y == c.Y /* Vista and higher */,
|
||||
"got %d, expected %d\n", cfi.dwFontSize.Y, height);
|
||||
}
|
||||
|
||||
static void test_GetConsoleFontSize(HANDLE std_output)
|
||||
{
|
||||
COORD c;
|
||||
DWORD index = 0;
|
||||
CONSOLE_FONT_INFO cfi;
|
||||
RECT r;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
LONG font_width, font_height;
|
||||
HMODULE hmod;
|
||||
DWORD (WINAPI *pGetNumberOfConsoleFonts)(void);
|
||||
|
||||
memset(&c, 10, sizeof(COORD));
|
||||
SetLastError(0xdeadbeef);
|
||||
c = GetConsoleFontSize(NULL, index);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
|
||||
ok(!c.X, "got %d, expected 0\n", c.X);
|
||||
ok(!c.Y, "got %d, expected 0\n", c.Y);
|
||||
|
||||
memset(&c, 10, sizeof(COORD));
|
||||
SetLastError(0xdeadbeef);
|
||||
c = GetConsoleFontSize(GetStdHandle(STD_INPUT_HANDLE), index);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
|
||||
ok(!c.X, "got %d, expected 0\n", c.X);
|
||||
ok(!c.Y, "got %d, expected 0\n", c.Y);
|
||||
|
||||
GetCurrentConsoleFont(std_output, FALSE, &cfi);
|
||||
memset(&c, 10, sizeof(COORD));
|
||||
SetLastError(0xdeadbeef);
|
||||
c = GetConsoleFontSize(std_output, cfi.nFont);
|
||||
ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
|
||||
GetClientRect(GetConsoleWindow(), &r);
|
||||
GetConsoleScreenBufferInfo(std_output, &csbi);
|
||||
font_width = (r.right - r.left + 1) / csbi.srWindow.Right;
|
||||
font_height = (r.bottom - r.top + 1) / csbi.srWindow.Bottom;
|
||||
ok(c.X == font_width, "got %d, expected %d\n", c.X, font_width);
|
||||
ok(c.Y == font_height, "got %d, expected %d\n", c.Y, font_height);
|
||||
|
||||
hmod = GetModuleHandleA("kernel32.dll");
|
||||
pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts");
|
||||
if (!pGetNumberOfConsoleFonts)
|
||||
{
|
||||
win_skip("GetNumberOfConsoleFonts is not available\n");
|
||||
return;
|
||||
}
|
||||
index = pGetNumberOfConsoleFonts();
|
||||
|
||||
memset(&c, 10, sizeof(COORD));
|
||||
SetLastError(0xdeadbeef);
|
||||
c = GetConsoleFontSize(std_output, index);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
|
||||
ok(!c.X, "got %d, expected 0\n", c.X);
|
||||
ok(!c.Y, "got %d, expected 0\n", c.Y);
|
||||
}
|
||||
|
||||
START_TEST(console)
|
||||
{
|
||||
static const char font_name[] = "Lucida Console";
|
||||
|
@ -2720,4 +2813,6 @@ START_TEST(console)
|
|||
test_ReadConsoleOutputCharacterA(hConOut);
|
||||
test_ReadConsoleOutputCharacterW(hConOut);
|
||||
test_ReadConsoleOutputAttribute(hConOut);
|
||||
test_GetCurrentConsoleFont(hConOut);
|
||||
test_GetConsoleFontSize(hConOut);
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ typedef struct
|
|||
|
||||
static void doCrash(int argc, char** argv)
|
||||
{
|
||||
char* p;
|
||||
volatile char* p;
|
||||
|
||||
/* make sure the exception gets to the debugger */
|
||||
SetErrorMode( 0 );
|
||||
|
|
|
@ -28,12 +28,17 @@
|
|||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winnls.h"
|
||||
#include "fileapi.h"
|
||||
#include <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <wine/test.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wine/winternl.h>
|
||||
#include <winnls.h>
|
||||
#include <fileapi.h>
|
||||
|
||||
#undef DeleteFile /* needed for FILE_DISPOSITION_INFO */
|
||||
|
||||
static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
|
||||
static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
|
||||
|
@ -46,8 +51,13 @@ static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD
|
|||
static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
|
||||
static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
|
||||
static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*);
|
||||
static DWORD (WINAPI* pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
|
||||
static DWORD (WINAPI* pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
|
||||
static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
|
||||
static DWORD (WINAPI *pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
|
||||
static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
|
||||
PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
|
||||
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*);
|
||||
static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN);
|
||||
static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD);
|
||||
|
||||
static const char filename[] = "testfile.xxx";
|
||||
static const char sillytext[] =
|
||||
|
@ -72,8 +82,13 @@ struct test_list {
|
|||
|
||||
static void InitFunctionPointers(void)
|
||||
{
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll");
|
||||
HMODULE hkernel32 = GetModuleHandleA("kernel32");
|
||||
|
||||
pNtCreateFile = (void *)GetProcAddress(hntdll, "NtCreateFile");
|
||||
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
|
||||
pRtlAnsiStringToUnicodeString = (void *)GetProcAddress(hntdll, "RtlAnsiStringToUnicodeString");
|
||||
|
||||
pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA");
|
||||
pReplaceFileA=(void*)GetProcAddress(hkernel32, "ReplaceFileA");
|
||||
pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW");
|
||||
|
@ -87,6 +102,7 @@ static void InitFunctionPointers(void)
|
|||
pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
|
||||
pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
|
||||
pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW");
|
||||
pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle");
|
||||
}
|
||||
|
||||
static void test__hread( void )
|
||||
|
@ -243,15 +259,36 @@ static void test__lclose( void )
|
|||
ok( ret != 0, "DeleteFile failed (%d)\n", GetLastError( ) );
|
||||
}
|
||||
|
||||
/* helper function for test__lcreat */
|
||||
static void get_nt_pathW( const char *name, UNICODE_STRING *nameW )
|
||||
{
|
||||
UNICODE_STRING strW;
|
||||
ANSI_STRING str;
|
||||
NTSTATUS status;
|
||||
BOOLEAN ret;
|
||||
RtlInitAnsiString( &str, name );
|
||||
|
||||
status = pRtlAnsiStringToUnicodeString( &strW, &str, TRUE );
|
||||
ok( !status, "RtlAnsiStringToUnicodeString failed with %08x\n", status );
|
||||
|
||||
ret = pRtlDosPathNameToNtPathName_U( strW.Buffer, nameW, NULL, NULL );
|
||||
ok( ret, "RtlDosPathNameToNtPathName_U failed\n" );
|
||||
|
||||
RtlFreeUnicodeString( &strW );
|
||||
}
|
||||
|
||||
static void test__lcreat( void )
|
||||
{
|
||||
UNICODE_STRING filenameW;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
HFILE filehandle;
|
||||
char buffer[10000];
|
||||
WIN32_FIND_DATAA search_results;
|
||||
char slashname[] = "testfi/";
|
||||
int err;
|
||||
HANDLE find;
|
||||
HANDLE find, file;
|
||||
NTSTATUS status;
|
||||
BOOL ret;
|
||||
|
||||
filehandle = _lcreat( filename, 0 );
|
||||
|
@ -287,12 +324,64 @@ static void test__lcreat( void )
|
|||
ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
|
||||
FindClose( find );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ok( 0 == DeleteFileA( filename ), "shouldn't be able to delete a readonly file\n" );
|
||||
ok( GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError() );
|
||||
|
||||
ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
|
||||
|
||||
ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file!\n" );
|
||||
|
||||
filehandle = _lcreat( filename, 1 ); /* readonly */
|
||||
ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError() );
|
||||
ok( HFILE_ERROR != _hwrite( filehandle, sillytext, strlen(sillytext) ),
|
||||
"_hwrite shouldn't be able to write never the less\n" );
|
||||
ok( HFILE_ERROR != _lclose(filehandle), "_lclose complains\n" );
|
||||
|
||||
find = FindFirstFileA( filename, &search_results );
|
||||
ok( INVALID_HANDLE_VALUE != find, "should be able to find file\n" );
|
||||
FindClose( find );
|
||||
|
||||
get_nt_pathW( filename, &filenameW );
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &filenameW;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
status = NtCreateFile( &file, GENERIC_READ | GENERIC_WRITE | DELETE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
|
||||
ok( status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %08x\n", status );
|
||||
ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
|
||||
|
||||
status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
|
||||
ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
|
||||
|
||||
status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_DIRECTORY_FILE, NULL, 0 );
|
||||
ok( status == STATUS_NOT_A_DIRECTORY, "expected STATUS_NOT_A_DIRECTORY, got %08x\n", status );
|
||||
|
||||
status = NtCreateFile( &file, DELETE, &attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN_IF, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0 );
|
||||
todo_wine
|
||||
ok( status == STATUS_CANNOT_DELETE, "expected STATUS_CANNOT_DELETE, got %08x\n", status );
|
||||
if (!status) CloseHandle( file );
|
||||
|
||||
RtlFreeUnicodeString( &filenameW );
|
||||
|
||||
todo_wine
|
||||
ok( GetFileAttributesA( filename ) != INVALID_FILE_ATTRIBUTES, "file was deleted\n" );
|
||||
todo_wine
|
||||
ok( SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL ) != 0, "couldn't change attributes on file\n" );
|
||||
todo_wine
|
||||
ok( DeleteFileA( filename ) != 0, "now it should be possible to delete the file\n" );
|
||||
|
||||
filehandle = _lcreat( filename, 2 );
|
||||
ok( HFILE_ERROR != filehandle, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError( ) );
|
||||
|
||||
|
@ -1024,6 +1113,57 @@ static void test_CopyFile2(void)
|
|||
DeleteFileW(dest);
|
||||
}
|
||||
|
||||
static DWORD WINAPI copy_progress_cb(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred,
|
||||
LARGE_INTEGER stream_size, LARGE_INTEGER stream_transferred,
|
||||
DWORD stream, DWORD reason, HANDLE source, HANDLE dest, LPVOID userdata)
|
||||
{
|
||||
ok(reason == CALLBACK_STREAM_SWITCH, "expected CALLBACK_STREAM_SWITCH, got %u\n", reason);
|
||||
CloseHandle(userdata);
|
||||
return PROGRESS_CANCEL;
|
||||
}
|
||||
|
||||
static void test_CopyFileEx(void)
|
||||
{
|
||||
char temp_path[MAX_PATH];
|
||||
char source[MAX_PATH], dest[MAX_PATH];
|
||||
static const char prefix[] = "pfx";
|
||||
HANDLE hfile;
|
||||
DWORD ret;
|
||||
BOOL retok;
|
||||
|
||||
ret = GetTempPathA(MAX_PATH, temp_path);
|
||||
ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
|
||||
ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
|
||||
|
||||
ret = GetTempFileNameA(temp_path, prefix, 0, source);
|
||||
ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
|
||||
|
||||
ret = GetTempFileNameA(temp_path, prefix, 0, dest);
|
||||
ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
|
||||
|
||||
hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
|
||||
ok(!retok, "CopyFileExA unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
|
||||
ok(GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES, "file was deleted\n");
|
||||
|
||||
hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, 0);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
|
||||
ok(!retok, "CopyFileExA unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %d\n", GetLastError());
|
||||
ok(GetFileAttributesA(dest) == INVALID_FILE_ATTRIBUTES, "file was not deleted\n");
|
||||
|
||||
ret = DeleteFileA(source);
|
||||
ok(ret, "DeleteFileA failed with error %d\n", GetLastError());
|
||||
ret = DeleteFileA(dest);
|
||||
ok(!ret, "DeleteFileA unexpectedly succeeded\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging routine to dump a buffer in a hexdump-like fashion.
|
||||
*/
|
||||
|
@ -1646,14 +1786,12 @@ static void test_DeleteFileA( void )
|
|||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = DeleteFileA(temp_file);
|
||||
todo_wine
|
||||
ok(ret, "DeleteFile error %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CloseHandle(hfile);
|
||||
ok(ret, "CloseHandle error %d\n", GetLastError());
|
||||
ret = DeleteFileA(temp_file);
|
||||
todo_wine
|
||||
ok(!ret, "DeleteFile should fail\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
|
@ -3689,11 +3827,21 @@ else
|
|||
static void test_GetFileInformationByHandleEx(void)
|
||||
{
|
||||
int i;
|
||||
char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024];
|
||||
char tempPath[MAX_PATH], tempFileName[MAX_PATH], buffer[1024], *strPtr;
|
||||
BOOL ret;
|
||||
DWORD ret2;
|
||||
HANDLE directory;
|
||||
DWORD ret2, written;
|
||||
HANDLE directory, file;
|
||||
FILE_ID_BOTH_DIR_INFO *bothDirInfo;
|
||||
FILE_BASIC_INFO *basicInfo;
|
||||
FILE_STANDARD_INFO *standardInfo;
|
||||
FILE_NAME_INFO *nameInfo;
|
||||
LARGE_INTEGER prevWrite;
|
||||
FILE_IO_PRIORITY_HINT_INFO priohintinfo;
|
||||
FILE_ALLOCATION_INFO allocinfo;
|
||||
FILE_DISPOSITION_INFO dispinfo;
|
||||
FILE_END_OF_FILE_INFO eofinfo;
|
||||
FILE_RENAME_INFO renameinfo;
|
||||
|
||||
struct {
|
||||
FILE_INFO_BY_HANDLE_CLASS handleClass;
|
||||
void *ptr;
|
||||
|
@ -3756,6 +3904,89 @@ static void test_GetFileInformationByHandleEx(void)
|
|||
}
|
||||
|
||||
CloseHandle(directory);
|
||||
|
||||
file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
|
||||
"got error %u.\n", GetLastError());
|
||||
|
||||
/* Test FileBasicInfo; make sure the write time changes when a file is updated */
|
||||
memset(buffer, 0xff, sizeof(buffer));
|
||||
ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
|
||||
ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
|
||||
basicInfo = (FILE_BASIC_INFO *)buffer;
|
||||
prevWrite = basicInfo->LastWriteTime;
|
||||
CloseHandle(file);
|
||||
|
||||
Sleep(30); /* Make sure a new write time is different from the previous */
|
||||
|
||||
/* Write something to the file, to make sure the write time has changed */
|
||||
file = CreateFileA(tempFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
|
||||
"got error %u.\n", GetLastError());
|
||||
ret = WriteFile(file, tempFileName, strlen(tempFileName), &written, NULL);
|
||||
ok(ret, "GetFileInformationByHandleEx: Write failed\n");
|
||||
CloseHandle(file);
|
||||
|
||||
file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "GetFileInformationByHandleEx: failed to open the temp file, "
|
||||
"got error %u.\n", GetLastError());
|
||||
|
||||
memset(buffer, 0xff, sizeof(buffer));
|
||||
ret = pGetFileInformationByHandleEx(file, FileBasicInfo, buffer, sizeof(buffer));
|
||||
ok(ret, "GetFileInformationByHandleEx: failed to get FileBasicInfo, %u\n", GetLastError());
|
||||
basicInfo = (FILE_BASIC_INFO *)buffer;
|
||||
/* Could also check that the creation time didn't change - on windows
|
||||
* it doesn't, but on wine, it does change even if it shouldn't. */
|
||||
ok(basicInfo->LastWriteTime.QuadPart != prevWrite.QuadPart,
|
||||
"GetFileInformationByHandleEx: last write time didn't change\n");
|
||||
|
||||
/* Test FileStandardInfo, check some basic parameters */
|
||||
memset(buffer, 0xff, sizeof(buffer));
|
||||
ret = pGetFileInformationByHandleEx(file, FileStandardInfo, buffer, sizeof(buffer));
|
||||
ok(ret, "GetFileInformationByHandleEx: failed to get FileStandardInfo, %u\n", GetLastError());
|
||||
standardInfo = (FILE_STANDARD_INFO *)buffer;
|
||||
ok(standardInfo->NumberOfLinks == 1, "GetFileInformationByHandleEx: Unexpcted number of links\n");
|
||||
ok(standardInfo->DeletePending == FALSE, "GetFileInformationByHandleEx: Unexpcted pending delete\n");
|
||||
ok(standardInfo->Directory == FALSE, "GetFileInformationByHandleEx: Incorrect directory flag\n");
|
||||
|
||||
/* Test FileNameInfo */
|
||||
memset(buffer, 0xff, sizeof(buffer));
|
||||
ret = pGetFileInformationByHandleEx(file, FileNameInfo, buffer, sizeof(buffer));
|
||||
ok(ret, "GetFileInformationByHandleEx: failed to get FileNameInfo, %u\n", GetLastError());
|
||||
nameInfo = (FILE_NAME_INFO *)buffer;
|
||||
strPtr = strchr(tempFileName, '\\');
|
||||
ok(strPtr != NULL, "GetFileInformationByHandleEx: Temp filename didn't contain backslash\n");
|
||||
ok(nameInfo->FileNameLength == strlen(strPtr) * 2,
|
||||
"GetFileInformationByHandleEx: Incorrect file name length\n");
|
||||
for (i = 0; i < nameInfo->FileNameLength/2; i++)
|
||||
ok(strPtr[i] == nameInfo->FileName[i], "Incorrect filename char %d: %c vs %c\n",
|
||||
i, strPtr[i], nameInfo->FileName[i]);
|
||||
|
||||
/* invalid classes */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetFileInformationByHandleEx(file, FileEndOfFileInfo, &eofinfo, sizeof(eofinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetFileInformationByHandleEx(file, FileIoPriorityHintInfo, &priohintinfo, sizeof(priohintinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetFileInformationByHandleEx(file, FileAllocationInfo, &allocinfo, sizeof(allocinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetFileInformationByHandleEx(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetFileInformationByHandleEx(file, FileRenameInfo, &renameinfo, sizeof(renameinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
CloseHandle(file);
|
||||
DeleteFileA(tempFileName);
|
||||
}
|
||||
|
||||
|
@ -4186,201 +4417,261 @@ todo_wine
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_GetFinalPathNameByHandleA(void)
|
||||
{
|
||||
static char prefix[] = "GetFinalPathNameByHandleA";
|
||||
static char dos_prefix[] = "\\\\?\\";
|
||||
char temp_path[MAX_PATH], test_path[MAX_PATH];
|
||||
char long_path[MAX_PATH], result_path[MAX_PATH];
|
||||
char dos_path[sizeof(dos_prefix) + MAX_PATH];
|
||||
HANDLE hFile;
|
||||
char dos_path[MAX_PATH + sizeof(dos_prefix)];
|
||||
HANDLE file;
|
||||
DWORD count;
|
||||
UINT ret;
|
||||
|
||||
if (!pGetFinalPathNameByHandleA)
|
||||
{
|
||||
win_skip("GetFinalPathNameByHandleA is missing\n");
|
||||
skip("GetFinalPathNameByHandleA is missing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test calling with INVALID_HANDLE_VALUE */
|
||||
SetLastError(0xdeadbeaf);
|
||||
count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == 0, "Expected length 0, got %d\n", count);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %x\n", GetLastError());
|
||||
ok(count == 0, "Expected length 0, got %u\n", count);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
|
||||
|
||||
count = GetTempPathA(MAX_PATH, temp_path);
|
||||
ok(count, "Failed to get temp path, error %x\n", GetLastError());
|
||||
if (!count) return;
|
||||
|
||||
ok(count, "Failed to get temp path, error %u\n", GetLastError());
|
||||
ret = GetTempFileNameA(temp_path, prefix, 0, test_path);
|
||||
ok(ret != 0, "GetTempFileNameA error %x\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
ok(ret != 0, "GetTempFileNameA error %u\n", GetLastError());
|
||||
ret = GetLongPathNameA(test_path, long_path, MAX_PATH);
|
||||
ok(ret != 0, "GetLongPathNameA error %x\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
hFile = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %x\n", GetLastError());
|
||||
if (hFile == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
dos_path[0] = 0;
|
||||
strcat(dos_path, dos_prefix);
|
||||
ok(ret != 0, "GetLongPathNameA error %u\n", GetLastError());
|
||||
strcpy(dos_path, dos_prefix);
|
||||
strcat(dos_path, long_path);
|
||||
|
||||
file = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFileA error %u\n", GetLastError());
|
||||
|
||||
/* Test VOLUME_NAME_DOS with sufficient buffer size */
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleA(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
count = pGetFinalPathNameByHandleA(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
|
||||
if (count && count <= MAX_PATH)
|
||||
ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path);
|
||||
ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path);
|
||||
|
||||
/* Test VOLUME_NAME_DOS with insufficient buffer size */
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
|
||||
ok(result_path[0] == 0x11, "Result path was modified\n");
|
||||
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
|
||||
ok(result_path[0] == 0x11, "Result path was modified\n");
|
||||
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
|
||||
ok(result_path[0] == 0x11, "Result path was modified\n");
|
||||
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
count = pGetFinalPathNameByHandleA(file, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == strlen(dos_path), "Expected length %u, got %u\n", (DWORD)strlen(dos_path), count);
|
||||
ok(result_path[0] != 0x11, "Result path was not modified\n");
|
||||
ok(!result_path[strlen(dos_path)], "Expected nullterminated string\n");
|
||||
ok(result_path[strlen(dos_path)+1] == 0x11, "Buffer overflow\n");
|
||||
|
||||
CloseHandle(hFile);
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
static void test_GetFinalPathNameByHandleW(void)
|
||||
{
|
||||
static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h','N','a','m','e','B','y','H','a','n','d','l','e','W','\0'};
|
||||
static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h',
|
||||
'N','a','m','e','B','y','H','a','n','d','l','e','W','\0'};
|
||||
static WCHAR dos_prefix[] = {'\\','\\','?','\\','\0'};
|
||||
WCHAR temp_path[MAX_PATH], test_path[MAX_PATH];
|
||||
WCHAR long_path[MAX_PATH], result_path[MAX_PATH];
|
||||
WCHAR dos_path[MAX_PATH + sizeof(dos_prefix)];
|
||||
WCHAR drive_part[MAX_PATH];
|
||||
WCHAR *file_part;
|
||||
WCHAR volume_path[MAX_PATH+50];
|
||||
WCHAR nt_path[2*MAX_PATH];
|
||||
HANDLE hFile;
|
||||
WCHAR volume_path[MAX_PATH + 50];
|
||||
WCHAR nt_path[2 * MAX_PATH];
|
||||
BOOL success;
|
||||
HANDLE file;
|
||||
DWORD count;
|
||||
UINT ret;
|
||||
|
||||
if (!pGetFinalPathNameByHandleW)
|
||||
{
|
||||
win_skip("GetFinalPathNameByHandleW is missing\n");
|
||||
skip("GetFinalPathNameByHandleW is missing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test calling with INVALID_HANDLE_VALUE */
|
||||
SetLastError(0xdeadbeaf);
|
||||
count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == 0, "Expected length 0, got %d\n", count);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
|
||||
ok(count == 0, "Expected length 0, got %u\n", count);
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
|
||||
|
||||
count = GetTempPathW(MAX_PATH, temp_path);
|
||||
ok(count, "Failed to get temp path, error %d\n", GetLastError());
|
||||
if (!count) return;
|
||||
|
||||
ok(count, "Failed to get temp path, error %u\n", GetLastError());
|
||||
ret = GetTempFileNameW(temp_path, prefix, 0, test_path);
|
||||
ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
ok(ret != 0, "GetTempFileNameW error %u\n", GetLastError());
|
||||
ret = GetLongPathNameW(test_path, long_path, MAX_PATH);
|
||||
ok(ret != 0, "GetLongPathNameW error %d\n", GetLastError());
|
||||
if (!ret) return;
|
||||
|
||||
hFile = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileW error %d\n", GetLastError());
|
||||
if (hFile == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
dos_path[0] = 0;
|
||||
lstrcatW(dos_path, dos_prefix);
|
||||
ok(ret != 0, "GetLongPathNameW error %u\n", GetLastError());
|
||||
lstrcpyW(dos_path, dos_prefix);
|
||||
lstrcatW(dos_path, long_path);
|
||||
|
||||
file = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFileW error %u\n", GetLastError());
|
||||
|
||||
/* Test VOLUME_NAME_DOS with sufficient buffer size */
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count);
|
||||
if (count && count <= MAX_PATH)
|
||||
ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path));
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count);
|
||||
ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path));
|
||||
|
||||
/* Test VOLUME_NAME_DOS with insufficient buffer size */
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count);
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count);
|
||||
ok(result_path[0] == 0x1111, "Result path was modified\n");
|
||||
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count);
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path) + 1, "Expected length %u, got %u\n", lstrlenW(dos_path) + 1, count);
|
||||
ok(result_path[0] == 0x1111, "Result path was modified\n");
|
||||
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count);
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
ok(count == lstrlenW(dos_path), "Expected length %u, got %u\n", lstrlenW(dos_path), count);
|
||||
ok(result_path[0] != 0x1111, "Result path was not modified\n");
|
||||
ok(!result_path[lstrlenW(dos_path)], "Expected nullterminated string\n");
|
||||
ok(result_path[lstrlenW(dos_path)+1] == 0x1111, "Buffer overflow\n");
|
||||
|
||||
if (!GetVolumePathNameW(long_path, drive_part, MAX_PATH))
|
||||
{
|
||||
ok(0, "Failed to get drive part, error: %d\n", GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return;
|
||||
}
|
||||
success = GetVolumePathNameW(long_path, drive_part, MAX_PATH);
|
||||
ok(success, "GetVolumePathNameW error %u\n", GetLastError());
|
||||
success = GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR));
|
||||
ok(success, "GetVolumeNameForVolumeMountPointW error %u\n", GetLastError());
|
||||
|
||||
if (!GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR)))
|
||||
ok(0, "GetVolumeNameForVolumeMountPointW failed, error: %d\n", GetLastError());
|
||||
else
|
||||
{
|
||||
/* Test for VOLUME_NAME_GUID */
|
||||
lstrcatW(volume_path, long_path + lstrlenW(drive_part));
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID);
|
||||
ok(count == lstrlenW(volume_path), "Expected length %d, got %d\n", lstrlenW(volume_path), count);
|
||||
if (count && count <= MAX_PATH)
|
||||
ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path));
|
||||
}
|
||||
/* Test for VOLUME_NAME_GUID */
|
||||
lstrcatW(volume_path, long_path + lstrlenW(drive_part));
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID);
|
||||
ok(count == lstrlenW(volume_path), "Expected length %u, got %u\n", lstrlenW(volume_path), count);
|
||||
ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path));
|
||||
|
||||
/* Test for VOLUME_NAME_NONE */
|
||||
file_part = long_path + lstrlenW(drive_part) - 1;
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE);
|
||||
ok(count == lstrlenW(file_part), "Expected length %d, got %d\n", lstrlenW(file_part), count);
|
||||
if (count && count <= MAX_PATH)
|
||||
ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(file_part), wine_dbgstr_w(result_path));
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE);
|
||||
ok(count == lstrlenW(file_part), "Expected length %u, got %u\n", lstrlenW(file_part), count);
|
||||
ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(file_part), wine_dbgstr_w(result_path));
|
||||
|
||||
drive_part[lstrlenW(drive_part)-1] = 0;
|
||||
if (!QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR)))
|
||||
ok(0, "QueryDosDeviceW failed, error: %d\n", GetLastError());
|
||||
else
|
||||
success = QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR));
|
||||
ok(success, "QueryDosDeviceW error %u\n", GetLastError());
|
||||
|
||||
/* Test for VOLUME_NAME_NT */
|
||||
lstrcatW(nt_path, file_part);
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(file, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
|
||||
ok(count == lstrlenW(nt_path), "Expected length %u, got %u\n", lstrlenW(nt_path), count);
|
||||
ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path));
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
static void test_SetFileInformationByHandle(void)
|
||||
{
|
||||
FILE_ATTRIBUTE_TAG_INFO fileattrinfo = { 0 };
|
||||
FILE_REMOTE_PROTOCOL_INFO protinfo = { 0 };
|
||||
FILE_STANDARD_INFO stdinfo;
|
||||
FILE_COMPRESSION_INFO compressinfo;
|
||||
FILE_DISPOSITION_INFO dispinfo;
|
||||
char tempFileName[MAX_PATH];
|
||||
char tempPath[MAX_PATH];
|
||||
HANDLE file;
|
||||
BOOL ret;
|
||||
|
||||
if (!pSetFileInformationByHandle)
|
||||
{
|
||||
/* Test for VOLUME_NAME_NT */
|
||||
lstrcatW(nt_path, file_part);
|
||||
memset(result_path, 0x11, sizeof(result_path));
|
||||
count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
|
||||
ok(count == lstrlenW(nt_path), "Expected length %d, got %d\n", lstrlenW(nt_path), count);
|
||||
if (count && count <= MAX_PATH)
|
||||
ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n",
|
||||
wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path));
|
||||
win_skip("SetFileInformationByHandle is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
ret = GetTempPathA(sizeof(tempPath), tempPath);
|
||||
ok(ret, "GetTempPathA failed, got error %u.\n", GetLastError());
|
||||
|
||||
/* ensure the existence of a file in the temp folder */
|
||||
ret = GetTempFileNameA(tempPath, "abc", 0, tempFileName);
|
||||
ok(ret, "GetTempFileNameA failed, got error %u.\n", GetLastError());
|
||||
|
||||
file = CreateFileA(tempFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "failed to open the temp file, error %u.\n", GetLastError());
|
||||
|
||||
/* invalid classes */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pSetFileInformationByHandle(file, FileStandardInfo, &stdinfo, sizeof(stdinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
memset(&compressinfo, 0, sizeof(compressinfo));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pSetFileInformationByHandle(file, FileCompressionInfo, &compressinfo, sizeof(compressinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pSetFileInformationByHandle(file, FileAttributeTagInfo, &fileattrinfo, sizeof(fileattrinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
memset(&protinfo, 0, sizeof(protinfo));
|
||||
protinfo.StructureVersion = 1;
|
||||
protinfo.StructureSize = sizeof(protinfo);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pSetFileInformationByHandle(file, FileRemoteProtocolInfo, &protinfo, sizeof(protinfo));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
/* test FileDispositionInfo, additional details already covered by ntdll tests */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, 0);
|
||||
todo_wine
|
||||
ok(!ret && GetLastError() == ERROR_BAD_LENGTH, "got %d, error %d\n", ret, GetLastError());
|
||||
|
||||
dispinfo.DeleteFile = TRUE;
|
||||
ret = pSetFileInformationByHandle(file, FileDispositionInfo, &dispinfo, sizeof(dispinfo));
|
||||
ok(ret, "setting FileDispositionInfo failed, error %d\n", GetLastError());
|
||||
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
static void test_GetFileAttributesExW(void)
|
||||
{
|
||||
static const WCHAR path1[] = {'\\','\\','?','\\',0};
|
||||
static const WCHAR path2[] = {'\\','?','?','\\',0};
|
||||
static const WCHAR path3[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
|
||||
WIN32_FILE_ATTRIBUTE_DATA info;
|
||||
BOOL ret;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetFileAttributesExW(path1, GetFileExInfoStandard, &info);
|
||||
ok(!ret, "GetFileAttributesExW succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetFileAttributesExW(path2, GetFileExInfoStandard, &info);
|
||||
ok(!ret, "GetFileAttributesExW succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_NAME, "Expected error ERROR_INVALID_NAME, got %u\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetFileAttributesExW(path3, GetFileExInfoStandard, &info);
|
||||
ok(!ret, "GetFileAttributesExW succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
|
@ -4399,6 +4690,7 @@ START_TEST(file)
|
|||
test_CopyFileA();
|
||||
test_CopyFileW();
|
||||
test_CopyFile2();
|
||||
test_CopyFileEx();
|
||||
test_CreateFile();
|
||||
test_CreateFileA();
|
||||
test_CreateFileW();
|
||||
|
@ -4437,4 +4729,6 @@ START_TEST(file)
|
|||
test_file_access();
|
||||
test_GetFinalPathNameByHandleA();
|
||||
test_GetFinalPathNameByHandleW();
|
||||
test_SetFileInformationByHandle();
|
||||
test_GetFileAttributesExW();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define HEAP_VALIDATE_PARAMS 0x40000000
|
||||
|
||||
static BOOL (WINAPI *pHeapQueryInformation)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
|
||||
static BOOL (WINAPI *pGetPhysicallyInstalledSystemMemory)(ULONGLONG *);
|
||||
static ULONG (WINAPI *pRtlGetNtGlobalFlags)(void);
|
||||
|
||||
struct heap_layout
|
||||
|
@ -1145,6 +1146,38 @@ static void test_child_heap( const char *arg )
|
|||
test_heap_checks( expect_heap );
|
||||
}
|
||||
|
||||
static void test_GetPhysicallyInstalledSystemMemory(void)
|
||||
{
|
||||
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
|
||||
MEMORYSTATUSEX memstatus;
|
||||
ULONGLONG total_memory;
|
||||
BOOL ret;
|
||||
|
||||
pGetPhysicallyInstalledSystemMemory = (void *)GetProcAddress(kernel32, "GetPhysicallyInstalledSystemMemory");
|
||||
if (!pGetPhysicallyInstalledSystemMemory)
|
||||
{
|
||||
win_skip("GetPhysicallyInstalledSystemMemory is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetPhysicallyInstalledSystemMemory(NULL);
|
||||
ok(!ret, "GetPhysicallyInstalledSystemMemory should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
|
||||
|
||||
total_memory = 0;
|
||||
ret = pGetPhysicallyInstalledSystemMemory(&total_memory);
|
||||
ok(ret, "GetPhysicallyInstalledSystemMemory unexpectedly failed\n");
|
||||
ok(total_memory != 0, "expected total_memory != 0\n");
|
||||
|
||||
memstatus.dwLength = sizeof(memstatus);
|
||||
ret = GlobalMemoryStatusEx(&memstatus);
|
||||
ok(ret, "GlobalMemoryStatusEx unexpectedly failed\n");
|
||||
ok(total_memory >= memstatus.ullTotalPhys / 1024,
|
||||
"expected total_memory >= memstatus.ullTotalPhys / 1024\n");
|
||||
}
|
||||
|
||||
START_TEST(heap)
|
||||
{
|
||||
int argc;
|
||||
|
@ -1172,7 +1205,9 @@ START_TEST(heap)
|
|||
test_sized_HeapReAlloc(1, (1 << 20));
|
||||
test_sized_HeapReAlloc((1 << 20), (2 << 20));
|
||||
test_sized_HeapReAlloc((1 << 20), 1);
|
||||
|
||||
test_HeapQueryInformation();
|
||||
test_GetPhysicallyInstalledSystemMemory();
|
||||
|
||||
if (pRtlGetNtGlobalFlags)
|
||||
{
|
||||
|
|
|
@ -68,6 +68,7 @@ static void (WINAPI *pRtlReleasePebLock)(void);
|
|||
static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR,
|
||||
PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
|
||||
PIMAGE_THUNK_DATA ThunkAddress,ULONG);
|
||||
static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *);
|
||||
|
||||
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
|
||||
{
|
||||
|
@ -374,6 +375,16 @@ static void test_Loader(void)
|
|||
1,
|
||||
0,
|
||||
{ ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
|
||||
},
|
||||
/* Minimal PE image that Windows7 is able to load: 268 bytes */
|
||||
{ 0x04,
|
||||
0, 0xf0, /* optional header size just forces 0xf0 bytes to be written,
|
||||
0 or another number don't change the behaviour, what really
|
||||
matters is file size regardless of values in the headers */
|
||||
0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
|
||||
0x40, /* minimal image size that Windows7 accepts */
|
||||
0,
|
||||
{ ERROR_SUCCESS }
|
||||
}
|
||||
};
|
||||
int i;
|
||||
|
@ -788,15 +799,6 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
|
|||
size = 0;
|
||||
status = pNtMapViewOfSection(hmap, GetCurrentProcess(), &addr2, 0, 0, &offset,
|
||||
&size, 1 /* ViewShare */, 0, PAGE_READONLY);
|
||||
/* FIXME: remove once Wine is fixed */
|
||||
if (status != STATUS_IMAGE_NOT_AT_BASE)
|
||||
{
|
||||
todo_wine {
|
||||
ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status);
|
||||
ok(addr2 != 0, "mapped address should be valid\n");
|
||||
}
|
||||
goto wine_is_broken;
|
||||
}
|
||||
ok(status == STATUS_IMAGE_NOT_AT_BASE, "expected STATUS_IMAGE_NOT_AT_BASE, got %x\n", status);
|
||||
ok(addr2 != 0, "mapped address should be valid\n");
|
||||
ok(addr2 != addr1, "mapped addresses should be different\n");
|
||||
|
@ -850,7 +852,6 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
|
|||
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
||||
}
|
||||
|
||||
wine_is_broken:
|
||||
status = pNtUnmapViewOfSection(GetCurrentProcess(), addr1);
|
||||
ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection error %x\n", status);
|
||||
|
||||
|
@ -1411,7 +1412,8 @@ static DWORD WINAPI semaphore_thread_proc(void *param)
|
|||
|
||||
while (1)
|
||||
{
|
||||
trace("%04u: semaphore_thread_proc: still alive\n", GetCurrentThreadId());
|
||||
if (winetest_debug > 1)
|
||||
trace("%04u: semaphore_thread_proc: still alive\n", GetCurrentThreadId());
|
||||
if (WaitForSingleObject(stop_event, 50) != WAIT_TIMEOUT) break;
|
||||
}
|
||||
|
||||
|
@ -1549,7 +1551,7 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
|
|||
ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
|
||||
}
|
||||
|
||||
/* win7 doesn't allow to create a thread during process shutdown,
|
||||
/* win7 doesn't allow creating a thread during process shutdown but
|
||||
* earlier Windows versions allow it.
|
||||
*/
|
||||
noop_thread_started = 0;
|
||||
|
@ -1678,8 +1680,8 @@ todo_wine
|
|||
trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
|
||||
|
||||
ret = pRtlDllShutdownInProgress();
|
||||
/* win7 doesn't allow to create a thread during process shutdown,
|
||||
* earlier Windows versions allow it, and DLL_THREAD_DETACH is
|
||||
/* win7 doesn't allow creating a thread during process shutdown but
|
||||
* earlier Windows versions allow it. In that case DLL_THREAD_DETACH is
|
||||
* sent on thread exit, but DLL_THREAD_ATTACH is never received.
|
||||
*/
|
||||
if (noop_thread_started)
|
||||
|
@ -2702,7 +2704,7 @@ static void test_ResolveDelayLoadedAPI(void)
|
|||
return;
|
||||
}
|
||||
|
||||
delaydir = RtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size);
|
||||
delaydir = pRtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size);
|
||||
if (!delaydir)
|
||||
{
|
||||
skip("haven't found section for delay import directory.\n");
|
||||
|
@ -2782,6 +2784,7 @@ START_TEST(loader)
|
|||
pLdrUnlockLoaderLock = (void *)GetProcAddress(ntdll, "LdrUnlockLoaderLock");
|
||||
pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
|
||||
pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
|
||||
pRtlImageDirectoryEntryToData = (void *)GetProcAddress(ntdll, "RtlImageDirectoryEntryToData");
|
||||
pResolveDelayLoadedAPI = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ResolveDelayLoadedAPI");
|
||||
|
||||
GetSystemInfo( &si );
|
||||
|
|
|
@ -1637,7 +1637,13 @@ static const struct comparestringa_entry comparestringa_data[] = {
|
|||
{ LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1, CSTR_LESS_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1, CSTR_GREATER_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9, CSTR_EQUAL },
|
||||
{ LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN }
|
||||
{ LOCALE_SYSTEM_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10, CSTR_LESS_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, 0, "a-", 3, "a\0", 3, CSTR_GREATER_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, 0, "a'", 3, "a\0", 3, CSTR_GREATER_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "a-", 3, "a\0", 3, CSTR_GREATER_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "a'", 3, "a\0", 3, CSTR_GREATER_THAN },
|
||||
{ LOCALE_SYSTEM_DEFAULT, NORM_IGNORESYMBOLS, "a.", 3, "a\0", 3, CSTR_EQUAL },
|
||||
{ LOCALE_SYSTEM_DEFAULT, NORM_IGNORESYMBOLS, "a ", 3, "a\0", 3, CSTR_EQUAL },
|
||||
};
|
||||
|
||||
static void test_CompareStringA(void)
|
||||
|
@ -2421,7 +2427,7 @@ static void test_LocaleNameToLCID(void)
|
|||
buffer[0] = 0;
|
||||
SetLastError(0xdeadbeef);
|
||||
lcid = pLocaleNameToLCID(LOCALE_NAME_INVARIANT, 0);
|
||||
todo_wine ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
|
||||
ok(lcid == 0x7F, "Expected lcid = 0x7F, got %08x, error %d\n", lcid, GetLastError());
|
||||
ret = pLCIDToLocaleName(lcid, buffer, LOCALE_NAME_MAX_LENGTH, 0);
|
||||
ok(ret > 0, "Expected ret > 0, got %d, error %d\n", ret, GetLastError());
|
||||
trace("%08x, %s\n", lcid, wine_dbgstr_w(buffer));
|
||||
|
@ -3135,13 +3141,17 @@ static void test_ConvertDefaultLocale(void)
|
|||
LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
|
||||
LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
|
||||
LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
|
||||
lcid = ConvertDefaultLocale(LOCALE_INVARIANT);
|
||||
ok(lcid == LOCALE_INVARIANT || broken(lcid == 0x47f) /* win2k[3]/winxp */,
|
||||
"Expected lcid = %08x, got %08x\n", LOCALE_INVARIANT, lcid);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
|
||||
DWORD dwFlags, LONG_PTR lParam)
|
||||
{
|
||||
trace("%08x, %s, %s, %08x, %08lx\n",
|
||||
lgrpid, lpszNum, lpszName, dwFlags, lParam);
|
||||
if (winetest_debug > 1)
|
||||
trace("%08x, %s, %s, %08x, %08lx\n",
|
||||
lgrpid, lpszNum, lpszName, dwFlags, lParam);
|
||||
|
||||
ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
|
||||
"Enumerated grp %d not valid (flags %d)\n", lgrpid, dwFlags);
|
||||
|
@ -3190,7 +3200,8 @@ static void test_EnumSystemLanguageGroupsA(void)
|
|||
|
||||
static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam )
|
||||
{
|
||||
trace( "%s %x\n", wine_dbgstr_w(name), flags );
|
||||
if (winetest_debug > 1)
|
||||
trace( "%s %x\n", wine_dbgstr_w(name), flags );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3215,7 +3226,8 @@ static void test_EnumSystemLocalesEx(void)
|
|||
static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
|
||||
LONG_PTR lParam)
|
||||
{
|
||||
trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
|
||||
if (winetest_debug > 1)
|
||||
trace("%08x, %08x, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
|
||||
|
||||
/* invalid locale enumerated on some platforms */
|
||||
if (lcid == 0)
|
||||
|
@ -3296,7 +3308,8 @@ static void test_SetLocaleInfoA(void)
|
|||
|
||||
static BOOL CALLBACK luilocale_proc1A(LPSTR value, LONG_PTR lParam)
|
||||
{
|
||||
trace("%s %08lx\n", value, lParam);
|
||||
if (winetest_debug > 1)
|
||||
trace("%s %08lx\n", value, lParam);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
@ -3354,6 +3367,7 @@ static void test_EnumUILanguageA(void)
|
|||
}
|
||||
|
||||
static char date_fmt_buf[1024];
|
||||
static WCHAR date_fmt_bufW[1024];
|
||||
|
||||
static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
|
||||
{
|
||||
|
@ -3362,6 +3376,12 @@ static BOOL CALLBACK enum_datetime_procA(LPSTR fmt)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK enum_datetime_procW(WCHAR *fmt)
|
||||
{
|
||||
lstrcatW(date_fmt_bufW, fmt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void test_EnumDateFormatsA(void)
|
||||
{
|
||||
char *p, buf[256];
|
||||
|
@ -3469,6 +3489,57 @@ static void test_EnumTimeFormatsA(void)
|
|||
ok(!lstrcmpA(date_fmt_buf, buf), "expected \"%s\" got \"%s\"\n", date_fmt_buf, buf);
|
||||
}
|
||||
|
||||
static void test_EnumTimeFormatsW(void)
|
||||
{
|
||||
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
|
||||
WCHAR bufW[256];
|
||||
BOOL ret;
|
||||
|
||||
date_fmt_bufW[0] = 0;
|
||||
ret = EnumTimeFormatsW(enum_datetime_procW, lcid, 0);
|
||||
ok(ret, "EnumTimeFormatsW(0) error %d\n", GetLastError());
|
||||
ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, sizeof(bufW)/sizeof(bufW[0]));
|
||||
ok(ret, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
|
||||
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
|
||||
wine_dbgstr_w(bufW));
|
||||
|
||||
date_fmt_bufW[0] = 0;
|
||||
ret = EnumTimeFormatsW(enum_datetime_procW, lcid, LOCALE_USE_CP_ACP);
|
||||
ok(ret, "EnumTimeFormatsW(LOCALE_USE_CP_ACP) error %d\n", GetLastError());
|
||||
ret = GetLocaleInfoW(lcid, LOCALE_STIMEFORMAT, bufW, sizeof(bufW)/sizeof(bufW[0]));
|
||||
ok(ret, "GetLocaleInfoW(LOCALE_STIMEFORMAT) error %d\n", GetLastError());
|
||||
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
|
||||
wine_dbgstr_w(bufW));
|
||||
|
||||
/* TIME_NOSECONDS is Win7+ feature */
|
||||
date_fmt_bufW[0] = 0;
|
||||
ret = EnumTimeFormatsW(enum_datetime_procW, lcid, TIME_NOSECONDS);
|
||||
if (!ret && GetLastError() == ERROR_INVALID_FLAGS)
|
||||
win_skip("EnumTimeFormatsW doesn't support TIME_NOSECONDS\n");
|
||||
else {
|
||||
char buf[256];
|
||||
|
||||
ok(ret, "EnumTimeFormatsW(TIME_NOSECONDS) error %d\n", GetLastError());
|
||||
ret = GetLocaleInfoW(lcid, LOCALE_SSHORTTIME, bufW, sizeof(bufW)/sizeof(bufW[0]));
|
||||
ok(ret, "GetLocaleInfoW(LOCALE_SSHORTTIME) error %d\n", GetLastError());
|
||||
ok(!lstrcmpW(date_fmt_bufW, bufW), "expected \"%s\" got \"%s\"\n", wine_dbgstr_w(date_fmt_bufW),
|
||||
wine_dbgstr_w(bufW));
|
||||
|
||||
/* EnumTimeFormatsA doesn't support this flag */
|
||||
ret = EnumTimeFormatsA(enum_datetime_procA, lcid, TIME_NOSECONDS);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS, "EnumTimeFormatsA(TIME_NOSECONDS) ret %d, error %d\n", ret,
|
||||
GetLastError());
|
||||
|
||||
ret = EnumTimeFormatsA(NULL, lcid, TIME_NOSECONDS);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS, "EnumTimeFormatsA(TIME_NOSECONDS) ret %d, error %d\n", ret,
|
||||
GetLastError());
|
||||
|
||||
/* And it's not supported by GetLocaleInfoA either */
|
||||
ret = GetLocaleInfoA(lcid, LOCALE_SSHORTTIME, buf, sizeof(buf)/sizeof(buf[0]));
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS, "GetLocaleInfoA(LOCALE_SSHORTTIME) ret %d, error %d\n", ret,
|
||||
GetLastError());
|
||||
}
|
||||
}
|
||||
static void test_GetCPInfo(void)
|
||||
{
|
||||
BOOL ret;
|
||||
|
@ -3581,10 +3652,26 @@ static void test_GetStringTypeW(void)
|
|||
static const WCHAR space_special[] = {0x09, 0x0d, 0x85};
|
||||
|
||||
WORD types[20];
|
||||
BOOL ret;
|
||||
WCHAR ch;
|
||||
BOOL res;
|
||||
int i;
|
||||
|
||||
/* NULL src */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetStringTypeW(CT_CTYPE1, NULL, 0, NULL);
|
||||
ok(!ret, "got %d\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetStringTypeW(CT_CTYPE1, NULL, 0, types);
|
||||
ok(!ret, "got %d\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = GetStringTypeW(CT_CTYPE1, NULL, 5, types);
|
||||
ok(!ret, "got %d\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError());
|
||||
|
||||
memset(types,0,sizeof(types));
|
||||
GetStringTypeW(CT_CTYPE1, blanks, 5, types);
|
||||
for (i = 0; i < 5; i++)
|
||||
|
@ -3640,15 +3727,6 @@ static void test_GetStringTypeW(void)
|
|||
for (i = 0; i < 3; i++)
|
||||
ok(types[i] & C1_SPACE || broken(types[i] == C1_CNTRL) || broken(types[i] == 0), "incorrect types returned for %x -> (%x does not have %x)\n",space_special[i], types[i], C1_SPACE );
|
||||
|
||||
for (i = -1; i < 3; i++)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(types, 0, sizeof(types));
|
||||
res = GetStringTypeW(CT_CTYPE1, NULL, i, types);
|
||||
ok(!res, "GetStringTypeW unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error, got %u\n", GetLastError());
|
||||
}
|
||||
|
||||
/* surrogate pairs */
|
||||
ch = 0xd800;
|
||||
memset(types, 0, sizeof(types));
|
||||
|
@ -4083,6 +4161,8 @@ static void test_IsValidLocaleName(void)
|
|||
ok(!ret, "IsValidLocaleName should have failed\n");
|
||||
ret = pIsValidLocaleName(zzzzW);
|
||||
ok(!ret, "IsValidLocaleName should have failed\n");
|
||||
ret = pIsValidLocaleName(LOCALE_NAME_INVARIANT);
|
||||
ok(ret, "IsValidLocaleName failed\n");
|
||||
}
|
||||
|
||||
static void test_CompareStringOrdinal(void)
|
||||
|
@ -4232,7 +4312,7 @@ static void test_GetGeoInfo(void)
|
|||
|
||||
/* try invalid type value */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetGeoInfoA(203, GEO_PARENT + 1, NULL, 0, 0);
|
||||
ret = pGetGeoInfoA(203, GEO_CURRENCYSYMBOL + 1, NULL, 0, 0);
|
||||
ok(ret == 0, "got %d\n", ret);
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS, "got %d\n", GetLastError());
|
||||
}
|
||||
|
@ -4304,11 +4384,196 @@ static void test_EnumSystemGeoID(void)
|
|||
}
|
||||
}
|
||||
|
||||
struct invariant_entry {
|
||||
const char *name;
|
||||
int id;
|
||||
const char *expect;
|
||||
};
|
||||
|
||||
#define X(x) #x, x
|
||||
static const struct invariant_entry invariant_list[] = {
|
||||
{ X(LOCALE_ILANGUAGE), "007f" },
|
||||
{ X(LOCALE_SENGLANGUAGE), "Invariant Language" },
|
||||
{ X(LOCALE_SABBREVLANGNAME), "IVL" },
|
||||
{ X(LOCALE_SNATIVELANGNAME), "Invariant Language" },
|
||||
{ X(LOCALE_ICOUNTRY), "1" },
|
||||
{ X(LOCALE_SENGCOUNTRY), "Invariant Country" },
|
||||
{ X(LOCALE_SABBREVCTRYNAME), "IVC" },
|
||||
{ X(LOCALE_SNATIVECTRYNAME), "Invariant Country" },
|
||||
{ X(LOCALE_IDEFAULTLANGUAGE), "0409" },
|
||||
{ X(LOCALE_IDEFAULTCOUNTRY), "1" },
|
||||
{ X(LOCALE_IDEFAULTCODEPAGE), "437" },
|
||||
{ X(LOCALE_IDEFAULTANSICODEPAGE), "1252" },
|
||||
{ X(LOCALE_IDEFAULTMACCODEPAGE), "10000" },
|
||||
{ X(LOCALE_SLIST), "," },
|
||||
{ X(LOCALE_IMEASURE), "0" },
|
||||
{ X(LOCALE_SDECIMAL), "." },
|
||||
{ X(LOCALE_STHOUSAND), "," },
|
||||
{ X(LOCALE_SGROUPING), "3;0" },
|
||||
{ X(LOCALE_IDIGITS), "2" },
|
||||
{ X(LOCALE_ILZERO), "1" },
|
||||
{ X(LOCALE_INEGNUMBER), "1" },
|
||||
{ X(LOCALE_SNATIVEDIGITS), "0123456789" },
|
||||
{ X(LOCALE_SCURRENCY), "\x00a4" },
|
||||
{ X(LOCALE_SINTLSYMBOL), "XDR" },
|
||||
{ X(LOCALE_SMONDECIMALSEP), "." },
|
||||
{ X(LOCALE_SMONTHOUSANDSEP), "," },
|
||||
{ X(LOCALE_SMONGROUPING), "3;0" },
|
||||
{ X(LOCALE_ICURRDIGITS), "2" },
|
||||
{ X(LOCALE_IINTLCURRDIGITS), "2" },
|
||||
{ X(LOCALE_ICURRENCY), "0" },
|
||||
{ X(LOCALE_INEGCURR), "0" },
|
||||
{ X(LOCALE_SDATE), "/" },
|
||||
{ X(LOCALE_STIME), ":" },
|
||||
{ X(LOCALE_SSHORTDATE), "MM/dd/yyyy" },
|
||||
{ X(LOCALE_SLONGDATE), "dddd, dd MMMM yyyy" },
|
||||
{ X(LOCALE_STIMEFORMAT), "HH:mm:ss" },
|
||||
{ X(LOCALE_IDATE), "0" },
|
||||
{ X(LOCALE_ILDATE), "1" },
|
||||
{ X(LOCALE_ITIME), "1" },
|
||||
{ X(LOCALE_ITIMEMARKPOSN), "0" },
|
||||
{ X(LOCALE_ICENTURY), "1" },
|
||||
{ X(LOCALE_ITLZERO), "1" },
|
||||
{ X(LOCALE_IDAYLZERO), "1" },
|
||||
{ X(LOCALE_IMONLZERO), "1" },
|
||||
{ X(LOCALE_S1159), "AM" },
|
||||
{ X(LOCALE_S2359), "PM" },
|
||||
{ X(LOCALE_ICALENDARTYPE), "1" },
|
||||
{ X(LOCALE_IOPTIONALCALENDAR), "0" },
|
||||
{ X(LOCALE_IFIRSTDAYOFWEEK), "6" },
|
||||
{ X(LOCALE_IFIRSTWEEKOFYEAR), "0" },
|
||||
{ X(LOCALE_SDAYNAME1), "Monday" },
|
||||
{ X(LOCALE_SDAYNAME2), "Tuesday" },
|
||||
{ X(LOCALE_SDAYNAME3), "Wednesday" },
|
||||
{ X(LOCALE_SDAYNAME4), "Thursday" },
|
||||
{ X(LOCALE_SDAYNAME5), "Friday" },
|
||||
{ X(LOCALE_SDAYNAME6), "Saturday" },
|
||||
{ X(LOCALE_SDAYNAME7), "Sunday" },
|
||||
{ X(LOCALE_SABBREVDAYNAME1), "Mon" },
|
||||
{ X(LOCALE_SABBREVDAYNAME2), "Tue" },
|
||||
{ X(LOCALE_SABBREVDAYNAME3), "Wed" },
|
||||
{ X(LOCALE_SABBREVDAYNAME4), "Thu" },
|
||||
{ X(LOCALE_SABBREVDAYNAME5), "Fri" },
|
||||
{ X(LOCALE_SABBREVDAYNAME6), "Sat" },
|
||||
{ X(LOCALE_SABBREVDAYNAME7), "Sun" },
|
||||
{ X(LOCALE_SMONTHNAME1), "January" },
|
||||
{ X(LOCALE_SMONTHNAME2), "February" },
|
||||
{ X(LOCALE_SMONTHNAME3), "March" },
|
||||
{ X(LOCALE_SMONTHNAME4), "April" },
|
||||
{ X(LOCALE_SMONTHNAME5), "May" },
|
||||
{ X(LOCALE_SMONTHNAME6), "June" },
|
||||
{ X(LOCALE_SMONTHNAME7), "July" },
|
||||
{ X(LOCALE_SMONTHNAME8), "August" },
|
||||
{ X(LOCALE_SMONTHNAME9), "September" },
|
||||
{ X(LOCALE_SMONTHNAME10), "October" },
|
||||
{ X(LOCALE_SMONTHNAME11), "November" },
|
||||
{ X(LOCALE_SMONTHNAME12), "December" },
|
||||
{ X(LOCALE_SMONTHNAME13), "" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME1), "Jan" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME2), "Feb" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME3), "Mar" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME4), "Apr" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME5), "May" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME6), "Jun" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME7), "Jul" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME8), "Aug" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME9), "Sep" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME10), "Oct" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME11), "Nov" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME12), "Dec" },
|
||||
{ X(LOCALE_SABBREVMONTHNAME13), "" },
|
||||
{ X(LOCALE_SPOSITIVESIGN), "+" },
|
||||
{ X(LOCALE_SNEGATIVESIGN), "-" },
|
||||
{ X(LOCALE_IPOSSIGNPOSN), "3" },
|
||||
{ X(LOCALE_INEGSIGNPOSN), "0" },
|
||||
{ X(LOCALE_IPOSSYMPRECEDES), "1" },
|
||||
{ X(LOCALE_IPOSSEPBYSPACE), "0" },
|
||||
{ X(LOCALE_INEGSYMPRECEDES), "1" },
|
||||
{ X(LOCALE_INEGSEPBYSPACE), "0" },
|
||||
{ X(LOCALE_SISO639LANGNAME), "iv" },
|
||||
{ X(LOCALE_SISO3166CTRYNAME), "IV" },
|
||||
{ X(LOCALE_IDEFAULTEBCDICCODEPAGE), "037" },
|
||||
{ X(LOCALE_IPAPERSIZE), "9" },
|
||||
{ X(LOCALE_SENGCURRNAME), "International Monetary Fund" },
|
||||
{ X(LOCALE_SNATIVECURRNAME), "International Monetary Fund" },
|
||||
{ X(LOCALE_SYEARMONTH), "yyyy MMMM" },
|
||||
{ X(LOCALE_IDIGITSUBSTITUTION), "1" },
|
||||
{ X(LOCALE_SNAME), "" },
|
||||
{ X(LOCALE_SSCRIPTS), "Latn;" },
|
||||
{ 0 }
|
||||
};
|
||||
#undef X
|
||||
|
||||
static void test_invariant(void)
|
||||
{
|
||||
int ret;
|
||||
int len;
|
||||
char buffer[BUFFER_SIZE];
|
||||
const struct invariant_entry *ptr = invariant_list;
|
||||
|
||||
if (!GetLocaleInfoA(LOCALE_INVARIANT, NUO|LOCALE_SLANGUAGE, buffer, sizeof(buffer)))
|
||||
{
|
||||
win_skip("GetLocaleInfoA(LOCALE_INVARIANT) not supported\n"); /* win2k */
|
||||
return;
|
||||
}
|
||||
|
||||
while (ptr->name)
|
||||
{
|
||||
ret = GetLocaleInfoA(LOCALE_INVARIANT, NUO|ptr->id, buffer, sizeof(buffer));
|
||||
if (!ret && (ptr->id == LOCALE_SNAME || ptr->id == LOCALE_SSCRIPTS))
|
||||
win_skip("not supported\n"); /* winxp/win2k3 */
|
||||
else
|
||||
{
|
||||
len = strlen(ptr->expect)+1; /* include \0 */
|
||||
ok(ret == len, "For id %d, expected ret == %d, got %d, error %d\n",
|
||||
ptr->id, len, ret, GetLastError());
|
||||
ok(!strcmp(buffer, ptr->expect), "For id %d, Expected %s, got '%s'\n",
|
||||
ptr->id, ptr->expect, buffer);
|
||||
}
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if ((PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_ENGLISH) ||
|
||||
(PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH))
|
||||
{
|
||||
skip("Non-English locale\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* some locales translate these */
|
||||
static const char lang[] = "Invariant Language (Invariant Country)";
|
||||
static const char cntry[] = "Invariant Country";
|
||||
static const char sortm[] = "Math Alphanumerics";
|
||||
static const char sortd[] = "Default"; /* win2k3 */
|
||||
|
||||
ret = GetLocaleInfoA(LOCALE_INVARIANT, NUO|LOCALE_SLANGUAGE, buffer, sizeof(buffer));
|
||||
len = lstrlenA(lang) + 1;
|
||||
ok(ret == len, "Expected ret == %d, got %d, error %d\n", len, ret, GetLastError());
|
||||
ok(!strcmp(buffer, lang), "Expected %s, got '%s'\n", lang, buffer);
|
||||
|
||||
ret = GetLocaleInfoA(LOCALE_INVARIANT, NUO|LOCALE_SCOUNTRY, buffer, sizeof(buffer));
|
||||
len = lstrlenA(cntry) + 1;
|
||||
ok(ret == len, "Expected ret == %d, got %d, error %d\n", len, ret, GetLastError());
|
||||
ok(!strcmp(buffer, cntry), "Expected %s, got '%s'\n", cntry, buffer);
|
||||
|
||||
ret = GetLocaleInfoA(LOCALE_INVARIANT, NUO|LOCALE_SSORTNAME, buffer, sizeof(buffer));
|
||||
if (ret == lstrlenA(sortm)+1)
|
||||
ok(!strcmp(buffer, sortm), "Expected %s, got '%s'\n", sortm, buffer);
|
||||
else if (ret == lstrlenA(sortd)+1) /* win2k3 */
|
||||
ok(!strcmp(buffer, sortd), "Expected %s, got '%s'\n", sortd, buffer);
|
||||
else
|
||||
ok(0, "Expected ret == %d or %d, got %d, error %d\n",
|
||||
lstrlenA(sortm)+1, lstrlenA(sortd)+1, ret, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(locale)
|
||||
{
|
||||
InitFunctionPointers();
|
||||
|
||||
test_EnumTimeFormatsA();
|
||||
test_EnumTimeFormatsW();
|
||||
test_EnumDateFormatsA();
|
||||
test_GetLocaleInfoA();
|
||||
test_GetLocaleInfoW();
|
||||
|
@ -4343,6 +4608,7 @@ START_TEST(locale)
|
|||
test_CompareStringOrdinal();
|
||||
test_GetGeoInfo();
|
||||
test_EnumSystemGeoID();
|
||||
test_invariant();
|
||||
/* this requires collation table patch to make it MS compatible */
|
||||
if (0) test_sorting();
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
#define ARCH "x86"
|
||||
#elif defined __x86_64__
|
||||
#define ARCH "amd64"
|
||||
#elif defined __arm__
|
||||
#define ARCH "arm"
|
||||
#elif defined __aarch64__
|
||||
#define ARCH "arm64"
|
||||
#else
|
||||
#define ARCH "none"
|
||||
#endif
|
||||
|
@ -75,6 +79,9 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
|
|||
static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
|
||||
static void (WINAPI *pReleaseActCtx)(HANDLE);
|
||||
|
||||
static BOOL (WINAPI *pCheckNameLegalDOS8Dot3W)(const WCHAR *, char *, DWORD, BOOL *, BOOL *);
|
||||
static BOOL (WINAPI *pCheckNameLegalDOS8Dot3A)(const char *, char *, DWORD, BOOL *, BOOL *);
|
||||
|
||||
/* a structure to deal with wine todos somewhat cleanly */
|
||||
typedef struct {
|
||||
DWORD shortlen;
|
||||
|
@ -922,7 +929,7 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
|
|||
|
||||
static void test_GetTempPathA(char* tmp_dir)
|
||||
{
|
||||
DWORD len, len_with_null;
|
||||
DWORD len, slen, len_with_null;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
len_with_null = strlen(tmp_dir) + 1;
|
||||
|
@ -953,12 +960,29 @@ static void test_GetTempPathA(char* tmp_dir)
|
|||
len = GetTempPathA(len, buf);
|
||||
ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
|
||||
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
|
||||
|
||||
memset(buf, 'a', sizeof(buf));
|
||||
len = GetTempPathA(sizeof(buf), buf);
|
||||
ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
|
||||
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
|
||||
/* The rest of the buffer remains untouched */
|
||||
slen = len + 1;
|
||||
for(len++; len < sizeof(buf); len++)
|
||||
ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
|
||||
|
||||
/* When the buffer is not long enough it remains untouched */
|
||||
memset(buf, 'a', sizeof(buf));
|
||||
len = GetTempPathA(slen / 2, buf);
|
||||
ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
|
||||
"expected %d, got %d\n", slen, len);
|
||||
for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
|
||||
ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
|
||||
}
|
||||
|
||||
static void test_GetTempPathW(char* tmp_dir)
|
||||
{
|
||||
DWORD len, len_with_null;
|
||||
WCHAR buf[MAX_PATH];
|
||||
DWORD len, slen, len_with_null;
|
||||
WCHAR buf[MAX_PATH], *long_buf;
|
||||
WCHAR tmp_dirW[MAX_PATH];
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
|
||||
|
@ -996,6 +1020,69 @@ static void test_GetTempPathW(char* tmp_dir)
|
|||
len = GetTempPathW(len, buf);
|
||||
ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
|
||||
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
|
||||
|
||||
for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
|
||||
buf[len] = 'a';
|
||||
len = GetTempPathW(len, buf);
|
||||
ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
|
||||
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
|
||||
/* The rest of the buffer must be zeroed */
|
||||
slen = len + 1;
|
||||
for(len++; len < sizeof(buf) / sizeof(buf[0]); len++)
|
||||
ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
|
||||
|
||||
/* When the buffer is not long enough the length passed is zeroed */
|
||||
for(len = 0; len < sizeof(buf) / sizeof(buf[0]); len++)
|
||||
buf[len] = 'a';
|
||||
len = GetTempPathW(slen / 2, buf);
|
||||
ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
|
||||
"expected %d, got %d\n", slen, len);
|
||||
|
||||
{
|
||||
/* In Windows 8 when TMP var points to a drive only (like C:) instead of a
|
||||
* full directory the behavior changes. It will start filling the path but
|
||||
* will later truncate the buffer before returning. So the generic test
|
||||
* below will fail for this Windows 8 corner case.
|
||||
*/
|
||||
char tmp_var[64];
|
||||
DWORD version = GetVersion();
|
||||
GetEnvironmentVariableA("TMP", tmp_var, sizeof(tmp_var));
|
||||
if (strlen(tmp_var) == 2 && version >= 0x00060002)
|
||||
return;
|
||||
}
|
||||
|
||||
for(len = 0; len < slen / 2; len++)
|
||||
ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
|
||||
for(; len < sizeof(buf) / sizeof(buf[0]); len++)
|
||||
ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
|
||||
|
||||
/* bogus application from bug 38220 passes the count value in sizeof(buffer)
|
||||
* instead the correct count of WCHAR, this test catches this case. */
|
||||
slen = 65534;
|
||||
long_buf = HeapAlloc(GetProcessHeap(), 0, slen * sizeof(WCHAR));
|
||||
if (!long_buf)
|
||||
{
|
||||
skip("Could not allocate memory for the test\n");
|
||||
return;
|
||||
}
|
||||
for(len = 0; len < slen; len++)
|
||||
long_buf[len] = 0xCC;
|
||||
len = GetTempPathW(slen, long_buf);
|
||||
ok(lstrcmpiW(long_buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
|
||||
ok(len == lstrlenW(long_buf), "returned length should be equal to the length of string\n");
|
||||
/* the remaining buffer must be zeroed up to different values in different OS versions.
|
||||
* <= XP - 32766
|
||||
* > XP - 32767
|
||||
* to simplify testing we will test only until XP.
|
||||
*/
|
||||
for(; len < 32767; len++)
|
||||
ok(long_buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, long_buf[len]);
|
||||
/* we will know skip the test that is in the middle of the OS difference by
|
||||
* incrementing len and then resume the test for the untouched part. */
|
||||
for(len++; len < slen; len++)
|
||||
ok(long_buf[len] == 0xcc, "expected 0xcc at [%d], got 0x%x\n", len, long_buf[len]);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, long_buf);
|
||||
}
|
||||
|
||||
static void test_GetTempPath(void)
|
||||
|
@ -1266,33 +1353,49 @@ static void test_GetLongPathNameW(void)
|
|||
|
||||
static void test_GetShortPathNameW(void)
|
||||
{
|
||||
WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
|
||||
WCHAR path[MAX_PATH];
|
||||
static const WCHAR extended_prefix[] = {'\\','\\','?','\\',0};
|
||||
static const WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
|
||||
static const WCHAR name[] = { 't', 'e', 's', 't', 0 };
|
||||
static const WCHAR backSlash[] = { '\\', 0 };
|
||||
static const WCHAR a_bcdeW[] = {'a','.','b','c','d','e',0};
|
||||
WCHAR path[MAX_PATH], tmppath[MAX_PATH], *ptr;
|
||||
WCHAR short_path[MAX_PATH];
|
||||
DWORD length;
|
||||
HANDLE file;
|
||||
int ret;
|
||||
WCHAR name[] = { 't', 'e', 's', 't', 0 };
|
||||
WCHAR backSlash[] = { '\\', 0 };
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
GetTempPathW( MAX_PATH, path );
|
||||
GetTempPathW( MAX_PATH, tmppath );
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
win_skip("GetTempPathW is not implemented\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lstrcpyW( path, tmppath );
|
||||
lstrcatW( path, test_path );
|
||||
lstrcatW( path, backSlash );
|
||||
ret = CreateDirectoryW( path, NULL );
|
||||
ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
|
||||
|
||||
/* Starting a main part of test */
|
||||
|
||||
/* extended path \\?\C:\path\ */
|
||||
lstrcpyW( path, extended_prefix );
|
||||
lstrcatW( path, tmppath );
|
||||
lstrcatW( path, test_path );
|
||||
lstrcatW( path, backSlash );
|
||||
short_path[0] = 0;
|
||||
length = GetShortPathNameW( path, short_path, sizeof(short_path) / sizeof(*short_path) );
|
||||
ok( length, "GetShortPathNameW returned 0.\n" );
|
||||
|
||||
lstrcpyW( path, tmppath );
|
||||
lstrcatW( path, test_path );
|
||||
lstrcatW( path, backSlash );
|
||||
length = GetShortPathNameW( path, short_path, 0 );
|
||||
ok( length, "GetShortPathNameW returned 0.\n" );
|
||||
ret = GetShortPathNameW( path, short_path, length );
|
||||
ok( ret, "GetShortPathNameW returned 0.\n" );
|
||||
ok( ret && ret == length-1, "GetShortPathNameW returned 0.\n" );
|
||||
|
||||
lstrcatW( short_path, name );
|
||||
|
||||
|
@ -1304,11 +1407,24 @@ static void test_GetShortPathNameW(void)
|
|||
|
||||
file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
|
||||
|
||||
/* End test */
|
||||
CloseHandle( file );
|
||||
ret = DeleteFileW( short_path );
|
||||
ok( ret, "Cannot delete file.\n" );
|
||||
|
||||
ptr = path + lstrlenW(path);
|
||||
lstrcpyW( ptr, a_bcdeW);
|
||||
file = CreateFileW( path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
|
||||
CloseHandle( file );
|
||||
|
||||
length = GetShortPathNameW( path, short_path, sizeof(short_path)/sizeof(*short_path) );
|
||||
ok( length, "GetShortPathNameW failed: %u.\n", GetLastError() );
|
||||
|
||||
ret = DeleteFileW( path );
|
||||
ok( ret, "Cannot delete file.\n" );
|
||||
*ptr = 0;
|
||||
|
||||
/* End test */
|
||||
ret = RemoveDirectoryW( path );
|
||||
ok( ret, "Cannot delete directory.\n" );
|
||||
}
|
||||
|
@ -1989,6 +2105,8 @@ static void init_pointers(void)
|
|||
MAKEFUNC(DeactivateActCtx);
|
||||
MAKEFUNC(GetCurrentActCtx);
|
||||
MAKEFUNC(ReleaseActCtx);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3W);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3A);
|
||||
#undef MAKEFUNC
|
||||
}
|
||||
|
||||
|
@ -2050,6 +2168,73 @@ static void test_relative_path(void)
|
|||
RemoveDirectoryA("bar");
|
||||
}
|
||||
|
||||
static void test_CheckNameLegalDOS8Dot3(void)
|
||||
{
|
||||
static const WCHAR has_driveW[] = {'C',':','\\','a','.','t','x','t',0};
|
||||
static const WCHAR has_pathW[] = {'b','\\','a','.','t','x','t',0};
|
||||
static const WCHAR too_longW[] = {'a','l','o','n','g','f','i','l','e','n','a','m','e','.','t','x','t',0};
|
||||
static const WCHAR twodotsW[] = {'t','e','s','t','.','e','s','t','.','t','x','t',0};
|
||||
static const WCHAR longextW[] = {'t','e','s','t','.','t','x','t','t','x','t',0};
|
||||
static const WCHAR emptyW[] = {0};
|
||||
static const WCHAR funnycharsW[] = {'!','#','$','%','&','\'','(',')','.','-','@','^',0};
|
||||
static const WCHAR length8W[] = {'t','e','s','t','t','e','s','t','.','t','x','t',0};
|
||||
static const WCHAR length1W[] = {'t',0};
|
||||
static const WCHAR withspaceW[] = {'t','e','s','t',' ','e','s','t','.','t','x','t',0};
|
||||
|
||||
static const struct {
|
||||
const WCHAR *name;
|
||||
BOOL should_be_legal, has_space;
|
||||
} cases[] = {
|
||||
{has_driveW, FALSE, FALSE},
|
||||
{has_pathW, FALSE, FALSE},
|
||||
{too_longW, FALSE, FALSE},
|
||||
{twodotsW, FALSE, FALSE},
|
||||
{longextW, FALSE, FALSE},
|
||||
{emptyW, TRUE /* ! */, FALSE},
|
||||
{funnycharsW, TRUE, FALSE},
|
||||
{length8W, TRUE, FALSE},
|
||||
{length1W, TRUE, FALSE},
|
||||
{withspaceW, TRUE, TRUE},
|
||||
};
|
||||
|
||||
BOOL br, is_legal, has_space;
|
||||
char astr[64];
|
||||
DWORD i;
|
||||
|
||||
if(!pCheckNameLegalDOS8Dot3W){
|
||||
win_skip("Missing CheckNameLegalDOS8Dot3, skipping tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
br = pCheckNameLegalDOS8Dot3W(NULL, NULL, 0, NULL, &is_legal);
|
||||
ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
|
||||
|
||||
br = pCheckNameLegalDOS8Dot3A(NULL, NULL, 0, NULL, &is_legal);
|
||||
ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
|
||||
|
||||
br = pCheckNameLegalDOS8Dot3W(length8W, NULL, 0, NULL, NULL);
|
||||
ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
|
||||
|
||||
br = pCheckNameLegalDOS8Dot3A("testtest.txt", NULL, 0, NULL, NULL);
|
||||
ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
|
||||
|
||||
for(i = 0; i < sizeof(cases)/sizeof(*cases); ++i){
|
||||
br = pCheckNameLegalDOS8Dot3W(cases[i].name, NULL, 0, &has_space, &is_legal);
|
||||
ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", wine_dbgstr_w(cases[i].name));
|
||||
ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", wine_dbgstr_w(cases[i].name));
|
||||
if(is_legal)
|
||||
ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
|
||||
|
||||
WideCharToMultiByte(CP_ACP, 0, cases[i].name, -1, astr, sizeof(astr), NULL, NULL);
|
||||
|
||||
br = pCheckNameLegalDOS8Dot3A(astr, NULL, 0, &has_space, &is_legal);
|
||||
ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", astr);
|
||||
ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", astr);
|
||||
if(is_legal)
|
||||
ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(path)
|
||||
{
|
||||
CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
|
||||
|
@ -2082,4 +2267,5 @@ START_TEST(path)
|
|||
test_SearchPathW();
|
||||
test_GetFullPathNameA();
|
||||
test_GetFullPathNameW();
|
||||
test_CheckNameLegalDOS8Dot3();
|
||||
}
|
||||
|
|
|
@ -487,7 +487,7 @@ static void test_CreateNamedPipe(int pipemode)
|
|||
ok(written == sizeof(obuf2), "write file len 3b\n");
|
||||
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE) {
|
||||
todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
|
||||
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -515,7 +515,7 @@ static void test_CreateNamedPipe(int pipemode)
|
|||
ok(written == sizeof(obuf2), "write file len 4b\n");
|
||||
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE) {
|
||||
todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
|
||||
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1162,6 +1162,8 @@ static void test_CloseNamedPipe(void)
|
|||
char ibuf[32];
|
||||
DWORD written;
|
||||
DWORD readden;
|
||||
DWORD state;
|
||||
BOOL ret;
|
||||
|
||||
hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
|
@ -1196,10 +1198,21 @@ static void test_CloseNamedPipe(void)
|
|||
ok(readden == sizeof(obuf), "got %d bytes\n", readden);
|
||||
/* pipe is empty now */
|
||||
|
||||
ret = GetNamedPipeHandleStateA(hFile, &state, NULL, NULL, NULL, NULL, 0);
|
||||
todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
||||
ret = SetNamedPipeHandleState(hFile, &state, NULL, NULL);
|
||||
todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!ReadFile(hFile, ibuf, 0, &readden, NULL), "ReadFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
SetLastError(0);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
@ -1230,11 +1243,21 @@ static void test_CloseNamedPipe(void)
|
|||
ok(readden == 0, "got %d bytes\n", readden);
|
||||
/* pipe is empty now */
|
||||
|
||||
ret = GetNamedPipeHandleStateA(hFile, &state, NULL, NULL, NULL, NULL, 0);
|
||||
todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
||||
ret = SetNamedPipeHandleState(hFile, &state, NULL, NULL);
|
||||
todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
SetLastError(0);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
@ -1272,10 +1295,21 @@ static void test_CloseNamedPipe(void)
|
|||
ok(readden == sizeof(obuf), "got %d bytes\n", readden);
|
||||
/* pipe is empty now */
|
||||
|
||||
ret = GetNamedPipeHandleStateA(hnp, &state, NULL, NULL, NULL, NULL, 0);
|
||||
ok(ret, "GetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
||||
ret = SetNamedPipeHandleState(hFile, &state, NULL, NULL);
|
||||
ok(!ret, "SetNamedPipeHandleState unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() returned %08x, expected ERROR_INVALID_HANDLE\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!ReadFile(hnp, ibuf, 0, &readden, NULL), "ReadFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
SetLastError(0);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
}
|
||||
|
@ -1306,10 +1340,22 @@ static void test_CloseNamedPipe(void)
|
|||
ok(readden == 0, "got %d bytes\n", readden);
|
||||
/* pipe is empty now */
|
||||
|
||||
ret = GetNamedPipeHandleStateA(hnp, &state, NULL, NULL, NULL, NULL, 0);
|
||||
ok(ret, "GetNamedPipeHandleState failed with %d\n", GetLastError());
|
||||
ret = SetNamedPipeHandleState(hFile, &state, NULL, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
state = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
||||
ret = SetNamedPipeHandleState(hFile, &state, NULL, NULL);
|
||||
ok(!ret, "SetNamedPipeHandleState unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() returned %08x, expected ERROR_INVALID_HANDLE\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
SetLastError(0);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
}
|
||||
|
@ -2851,20 +2897,17 @@ static void test_readfileex_pending(void)
|
|||
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
|
||||
|
||||
/* free up some space in the pipe */
|
||||
ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
|
||||
ok(ret == TRUE, "ReadFile failed\n");
|
||||
|
||||
ok(completion_called == 0, "completion routine called during ReadFile\n");
|
||||
|
||||
wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
|
||||
if (wait == WAIT_TIMEOUT)
|
||||
for (i=0; i<256; i++)
|
||||
{
|
||||
ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
|
||||
ok(ret == TRUE, "ReadFile failed\n");
|
||||
|
||||
ok(completion_called == 0, "completion routine called during ReadFile\n");
|
||||
|
||||
wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
|
||||
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0 || wait == WAIT_TIMEOUT,
|
||||
"WaitForSingleObject returned %x\n", wait);
|
||||
if (wait != WAIT_TIMEOUT) break;
|
||||
}
|
||||
|
||||
ok(completion_called == 1, "completion routine not called\n");
|
||||
|
@ -2886,6 +2929,7 @@ static void test_readfileex_pending(void)
|
|||
num_bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
|
||||
ok(!ret, "ReadFile should fail\n");
|
||||
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
|
||||
ok(num_bytes == 0, "bytes %u\n", num_bytes);
|
||||
ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
|
||||
|
@ -2943,7 +2987,6 @@ todo_wine
|
|||
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
|
||||
wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
todo_wine
|
||||
ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
|
||||
ok(completion_called == 0, "completion routine called before writing to file\n");
|
||||
|
||||
|
@ -3221,7 +3264,6 @@ todo_wine
|
|||
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
|
||||
ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
|
||||
wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
todo_wine
|
||||
ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
|
||||
ok(completion_called == 0, "completion routine called before writing to file\n");
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,6 +56,9 @@ static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
|
|||
static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
|
||||
static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
|
||||
static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
|
||||
|
||||
static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
|
||||
|
||||
static void test_signalandwait(void)
|
||||
|
@ -102,7 +105,7 @@ static void test_signalandwait(void)
|
|||
for (i = 0; i < 10000; i++)
|
||||
{
|
||||
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
|
||||
ok( r == WAIT_OBJECT_0, "should succeed\n");
|
||||
ok(r == WAIT_OBJECT_0, "should succeed\n");
|
||||
}
|
||||
|
||||
/* event[0] is not signalled */
|
||||
|
@ -2308,8 +2311,184 @@ static void test_srwlock_example(void)
|
|||
trace("number of total exclusive accesses is %d\n", srwlock_protected_value);
|
||||
}
|
||||
|
||||
static DWORD WINAPI alertable_wait_thread(void *param)
|
||||
{
|
||||
HANDLE *semaphores = param;
|
||||
LARGE_INTEGER timeout;
|
||||
NTSTATUS status;
|
||||
DWORD result;
|
||||
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE);
|
||||
ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %u\n", result);
|
||||
result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
timeout.QuadPart = -10000000;
|
||||
status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
|
||||
ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
|
||||
timeout.QuadPart = -2000000;
|
||||
status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
|
||||
ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08x\n", status);
|
||||
|
||||
ReleaseSemaphore(semaphores[0], 1, NULL);
|
||||
timeout.QuadPart = -10000000;
|
||||
status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
|
||||
ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
|
||||
result = WaitForSingleObject(semaphores[0], 0);
|
||||
ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CALLBACK alertable_wait_apc(ULONG_PTR userdata)
|
||||
{
|
||||
HANDLE *semaphores = (void *)userdata;
|
||||
ReleaseSemaphore(semaphores[1], 1, NULL);
|
||||
}
|
||||
|
||||
static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata)
|
||||
{
|
||||
HANDLE *semaphores = (void *)userdata;
|
||||
DWORD result;
|
||||
|
||||
result = WaitForSingleObject(semaphores[0], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
}
|
||||
|
||||
static void test_alertable_wait(void)
|
||||
{
|
||||
HANDLE thread, semaphores[2];
|
||||
DWORD result;
|
||||
|
||||
semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
|
||||
ok(semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
|
||||
semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
|
||||
ok(semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
|
||||
thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL);
|
||||
ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
|
||||
|
||||
result = WaitForSingleObject(semaphores[0], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
|
||||
result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
|
||||
ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
|
||||
|
||||
result = WaitForSingleObject(semaphores[0], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
|
||||
result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
|
||||
ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
|
||||
|
||||
result = WaitForSingleObject(semaphores[0], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
|
||||
result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
|
||||
ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
|
||||
result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
|
||||
ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
|
||||
ReleaseSemaphore(semaphores[0], 2, NULL);
|
||||
|
||||
result = WaitForSingleObject(thread, 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
CloseHandle(thread);
|
||||
CloseHandle(semaphores[0]);
|
||||
CloseHandle(semaphores[1]);
|
||||
}
|
||||
|
||||
struct apc_deadlock_info
|
||||
{
|
||||
PROCESS_INFORMATION *pi;
|
||||
HANDLE event;
|
||||
BOOL running;
|
||||
};
|
||||
|
||||
static DWORD WINAPI apc_deadlock_thread(void *param)
|
||||
{
|
||||
struct apc_deadlock_info *info = param;
|
||||
PROCESS_INFORMATION *pi = info->pi;
|
||||
NTSTATUS status;
|
||||
SIZE_T size;
|
||||
void *base;
|
||||
|
||||
while (info->running)
|
||||
{
|
||||
base = NULL;
|
||||
size = 0x1000;
|
||||
status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
|
||||
ok(base != NULL, "expected base != NULL, got %p\n", base);
|
||||
SetEvent(info->event);
|
||||
|
||||
size = 0;
|
||||
status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
|
||||
ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
|
||||
SetEvent(info->event);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_apc_deadlock(void)
|
||||
{
|
||||
struct apc_deadlock_info info;
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOA si = { sizeof(si) };
|
||||
char cmdline[MAX_PATH];
|
||||
HANDLE event, thread;
|
||||
DWORD result;
|
||||
BOOL success;
|
||||
char **argv;
|
||||
int i;
|
||||
|
||||
winetest_get_mainargs(&argv);
|
||||
sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
|
||||
success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
||||
ok(success, "CreateProcess failed with %u\n", GetLastError());
|
||||
|
||||
event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
ok(event != NULL, "CreateEvent failed with %u\n", GetLastError());
|
||||
|
||||
info.pi = π
|
||||
info.event = event;
|
||||
info.running = TRUE;
|
||||
|
||||
thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
|
||||
ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
|
||||
result = WaitForSingleObject(event, 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
result = SuspendThread(pi.hThread);
|
||||
ok(result == 0, "expected 0, got %u\n", result);
|
||||
|
||||
WaitForSingleObject(event, 0); /* reset event */
|
||||
result = WaitForSingleObject(event, 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
|
||||
result = ResumeThread(pi.hThread);
|
||||
ok(result == 1, "expected 1, got %u\n", result);
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
info.running = FALSE;
|
||||
result = WaitForSingleObject(thread, 1000);
|
||||
ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
|
||||
CloseHandle(thread);
|
||||
CloseHandle(event);
|
||||
|
||||
TerminateProcess(pi.hProcess, 0);
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
|
||||
START_TEST(sync)
|
||||
{
|
||||
char **argv;
|
||||
int argc;
|
||||
HMODULE hdll = GetModuleHandleA("kernel32.dll");
|
||||
HMODULE hntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
|
@ -2338,8 +2517,21 @@ START_TEST(sync)
|
|||
pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
|
||||
pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
|
||||
pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
|
||||
pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
|
||||
pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
|
||||
pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
|
||||
|
||||
argc = winetest_get_mainargs( &argv );
|
||||
if (argc >= 3)
|
||||
{
|
||||
if (!strcmp(argv[2], "apc_deadlock"))
|
||||
{
|
||||
HANDLE handle = GetCurrentThread();
|
||||
for (;;) WaitForMultipleObjectsEx(1, &handle, FALSE, INFINITE, TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
test_signalandwait();
|
||||
test_mutex();
|
||||
test_slist();
|
||||
|
@ -2355,4 +2547,6 @@ START_TEST(sync)
|
|||
test_condvars_consumer_producer();
|
||||
test_srwlock_base();
|
||||
test_srwlock_example();
|
||||
test_alertable_wait();
|
||||
test_apc_deadlock();
|
||||
}
|
||||
|
|
|
@ -25,13 +25,18 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <wine/test.h>
|
||||
/* the tests intentionally pass invalid pointers and need an exception handler */
|
||||
#define WINE_NO_INLINE_STRING
|
||||
|
||||
#include <ntstatus.h>
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winnt.h>
|
||||
#include <winerror.h>
|
||||
#include <winnls.h>
|
||||
#include <wine/winternl.h>
|
||||
#include <wine/test.h>
|
||||
|
||||
/* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
|
||||
#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
|
||||
|
@ -63,6 +68,10 @@
|
|||
#define ARCH "x86"
|
||||
#elif defined __x86_64__
|
||||
#define ARCH "amd64"
|
||||
#elif defined __arm__
|
||||
#define ARCH "arm"
|
||||
#elif defined __aarch64__
|
||||
#define ARCH "arm64"
|
||||
#else
|
||||
#define ARCH "none"
|
||||
#endif
|
||||
|
@ -84,10 +93,15 @@ static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
|
|||
static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
|
||||
static void (WINAPI *pReleaseActCtx)(HANDLE);
|
||||
static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
|
||||
static void (WINAPI *pCloseThreadpool)(PTP_POOL);
|
||||
static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON);
|
||||
static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
|
||||
static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
|
||||
static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
|
||||
static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
|
||||
static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
|
||||
static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
|
||||
static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
|
||||
|
||||
static HANDLE create_target_process(const char *arg)
|
||||
{
|
||||
|
@ -213,9 +227,8 @@ static DWORD WINAPI threadFunc1(LPVOID p)
|
|||
/* Double check that all threads really did run by validating that
|
||||
they have all written to the shared memory. There should be no race
|
||||
here, since all threads were synchronized after the write.*/
|
||||
for(i=0;i<NUM_THREADS;i++) {
|
||||
while(tstruct->threadmem[i]==0) ;
|
||||
}
|
||||
for (i = 0; i < NUM_THREADS; i++)
|
||||
ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
|
||||
|
||||
/* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
|
||||
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
|
||||
|
@ -866,6 +879,15 @@ static VOID test_thread_processor(void)
|
|||
retMask = SetThreadAffinityMask(curthread,~0);
|
||||
ok(broken(retMask==0) || retMask==processMask,
|
||||
"SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
|
||||
|
||||
if (retMask == processMask)
|
||||
{
|
||||
/* Show that the "all processors" flag is handled in ntdll */
|
||||
DWORD_PTR mask = ~0u;
|
||||
NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
|
||||
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status);
|
||||
}
|
||||
|
||||
if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
|
||||
{
|
||||
/* only the low 32-bits matter */
|
||||
|
@ -875,41 +897,99 @@ static VOID test_thread_processor(void)
|
|||
ok(retMask == processMask, "SetThreadAffinityMask failed\n");
|
||||
}
|
||||
/* NOTE: This only works on WinNT/2000/XP) */
|
||||
if (pSetThreadIdealProcessor) {
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,0);
|
||||
if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
win_skip("SetThreadIdealProcessor is not implemented\n");
|
||||
return;
|
||||
}
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed\n");
|
||||
if (pSetThreadIdealProcessor)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,0);
|
||||
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed\n");
|
||||
|
||||
if (is_wow64)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
|
||||
todo_wine
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
|
||||
if (is_wow64)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
|
||||
todo_wine
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,65);
|
||||
ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
|
||||
ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
}
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,65);
|
||||
ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
|
||||
ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
|
||||
ok(GetLastError()==ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
}
|
||||
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed\n");
|
||||
}
|
||||
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
|
||||
ok(error!=-1, "SetThreadIdealProcessor failed\n");
|
||||
}
|
||||
else
|
||||
win_skip("SetThreadIdealProcessor is not implemented\n");
|
||||
}
|
||||
|
||||
if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
|
||||
{
|
||||
GROUP_AFFINITY affinity, affinity_new;
|
||||
NTSTATUS status;
|
||||
|
||||
memset(&affinity, 0, sizeof(affinity));
|
||||
ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS), /* Win 7 and 8 */
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
|
||||
|
||||
memset(&affinity_new, 0, sizeof(affinity_new));
|
||||
affinity_new.Group = 0;
|
||||
affinity_new.Mask = affinity.Mask;
|
||||
ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
|
||||
ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
|
||||
affinity_new.Mask, affinity.Mask);
|
||||
|
||||
/* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
|
||||
affinity_new.Group = 0;
|
||||
affinity_new.Mask = ~0u;
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
|
||||
affinity_new.Mask = 0x1;
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
|
||||
ok(GetLastError() == ERROR_NOACCESS,
|
||||
"Expected ERROR_NOACCESS, got %d\n", GetLastError());
|
||||
|
||||
/* show that the access violation was detected in ntdll */
|
||||
status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
|
||||
ok(status == STATUS_ACCESS_VIOLATION,
|
||||
"Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
|
||||
|
||||
/* restore original mask */
|
||||
affinity_new.Group = 0;
|
||||
affinity_new.Mask = affinity.Mask;
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
|
||||
ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
|
||||
affinity_new.Mask, affinity.Mask);
|
||||
}
|
||||
else
|
||||
win_skip("Get/SetThreadGroupAffinity not available\n");
|
||||
}
|
||||
|
||||
static VOID test_GetThreadExitCode(void)
|
||||
|
@ -1648,6 +1728,7 @@ static void test_threadpool(void)
|
|||
|
||||
pool = pCreateThreadpool(NULL);
|
||||
ok (pool != NULL, "CreateThreadpool failed\n");
|
||||
pCloseThreadpool(pool);
|
||||
}
|
||||
|
||||
static void test_reserved_tls(void)
|
||||
|
@ -1687,9 +1768,113 @@ static void test_reserved_tls(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_thread_info(void)
|
||||
{
|
||||
char buf[4096];
|
||||
static const ULONG info_size[] =
|
||||
{
|
||||
sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
|
||||
sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
|
||||
sizeof(ULONG), /* ThreadPriority */
|
||||
sizeof(ULONG), /* ThreadBasePriority */
|
||||
sizeof(ULONG_PTR), /* ThreadAffinityMask */
|
||||
sizeof(HANDLE), /* ThreadImpersonationToken */
|
||||
sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
|
||||
sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
|
||||
0, /* ThreadEventPair_Reusable */
|
||||
sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
|
||||
sizeof(ULONG), /* ThreadZeroTlsCell */
|
||||
sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
|
||||
sizeof(ULONG), /* ThreadAmILastThread */
|
||||
sizeof(ULONG), /* ThreadIdealProcessor */
|
||||
sizeof(ULONG), /* ThreadPriorityBoost */
|
||||
sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
|
||||
sizeof(ULONG), /* ThreadIsIoPending */
|
||||
sizeof(BOOLEAN), /* ThreadHideFromDebugger */
|
||||
/* FIXME: Add remaining classes */
|
||||
};
|
||||
HANDLE thread;
|
||||
ULONG i, status, ret_len;
|
||||
|
||||
if (!pOpenThread)
|
||||
{
|
||||
win_skip("OpenThread is not available on this platform\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pNtQueryInformationThread)
|
||||
{
|
||||
win_skip("NtQueryInformationThread is not available on this platform\n");
|
||||
return;
|
||||
}
|
||||
|
||||
thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
|
||||
if (!thread)
|
||||
{
|
||||
win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++)
|
||||
{
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
#ifdef __i386__
|
||||
if (i == ThreadDescriptorTableEntry)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
|
||||
|
||||
ctx.ContextFlags = CONTEXT_SEGMENTS;
|
||||
GetThreadContext(GetCurrentThread(), &ctx);
|
||||
tdi->Selector = ctx.SegDs;
|
||||
}
|
||||
#endif
|
||||
ret_len = 0;
|
||||
status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
|
||||
if (status == STATUS_NOT_IMPLEMENTED) continue;
|
||||
if (status == STATUS_INVALID_INFO_CLASS) continue;
|
||||
if (status == STATUS_UNSUCCESSFUL) continue;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case ThreadBasicInformation:
|
||||
case ThreadAmILastThread:
|
||||
case ThreadPriorityBoost:
|
||||
ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
|
||||
break;
|
||||
|
||||
#ifdef __i386__
|
||||
case ThreadDescriptorTableEntry:
|
||||
ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
|
||||
"for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ThreadTimes:
|
||||
todo_wine
|
||||
ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
|
||||
break;
|
||||
|
||||
case ThreadAffinityMask:
|
||||
case ThreadQuerySetWin32StartAddress:
|
||||
todo_wine
|
||||
ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
|
||||
break;
|
||||
|
||||
default:
|
||||
ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
static void init_funcs(void)
|
||||
{
|
||||
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
||||
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
|
||||
so that the compile passes */
|
||||
|
@ -1712,28 +1897,34 @@ static void init_funcs(void)
|
|||
X(ReleaseActCtx);
|
||||
|
||||
X(CreateThreadpool);
|
||||
X(CloseThreadpool);
|
||||
X(CreateThreadpoolWork);
|
||||
X(SubmitThreadpoolWork);
|
||||
X(WaitForThreadpoolWorkCallbacks);
|
||||
X(CloseThreadpoolWork);
|
||||
|
||||
X(GetThreadGroupAffinity);
|
||||
X(SetThreadGroupAffinity);
|
||||
#undef X
|
||||
|
||||
#define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
|
||||
if (ntdll)
|
||||
{
|
||||
X(NtQueryInformationThread);
|
||||
X(RtlGetThreadErrorMode);
|
||||
X(NtSetInformationThread);
|
||||
}
|
||||
#undef X
|
||||
}
|
||||
|
||||
START_TEST(thread)
|
||||
{
|
||||
HINSTANCE ntdll;
|
||||
int argc;
|
||||
char **argv;
|
||||
argc = winetest_get_mainargs( &argv );
|
||||
|
||||
init_funcs();
|
||||
|
||||
ntdll=GetModuleHandleA("ntdll.dll");
|
||||
if (ntdll)
|
||||
{
|
||||
pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
|
||||
}
|
||||
|
||||
if (argc >= 3)
|
||||
{
|
||||
if (!strcmp(argv[2], "sleep"))
|
||||
|
@ -1760,6 +1951,7 @@ START_TEST(thread)
|
|||
return;
|
||||
}
|
||||
|
||||
test_thread_info();
|
||||
test_reserved_tls();
|
||||
test_CreateRemoteThread();
|
||||
test_CreateThread_basic();
|
||||
|
|
|
@ -29,6 +29,8 @@ static BOOL (WINAPI *pSystemTimeToTzSpecificLocalTime)(LPTIME_ZONE_INFORMATION,
|
|||
static BOOL (WINAPI *pGetSystemTimes)(LPFILETIME, LPFILETIME, LPFILETIME);
|
||||
static int (WINAPI *pGetCalendarInfoA)(LCID,CALID,CALTYPE,LPSTR,int,LPDWORD);
|
||||
static int (WINAPI *pGetCalendarInfoW)(LCID,CALID,CALTYPE,LPWSTR,int,LPDWORD);
|
||||
static DWORD (WINAPI *pGetDynamicTimeZoneInformation)(DYNAMIC_TIME_ZONE_INFORMATION*);
|
||||
static void (WINAPI *pGetSystemTimePreciseAsFileTime)(LPFILETIME);
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define SECSPERDAY 86400
|
||||
|
@ -732,8 +734,75 @@ static void test_GetCalendarInfo(void)
|
|||
ok( ret2, "GetCalendarInfoW failed err %u\n", GetLastError() );
|
||||
ret2 = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
|
||||
ok( ret == ret2, "got %d, expected %d\n", ret, ret2 );
|
||||
|
||||
}
|
||||
|
||||
static void test_GetDynamicTimeZoneInformation(void)
|
||||
{
|
||||
DYNAMIC_TIME_ZONE_INFORMATION dyninfo;
|
||||
TIME_ZONE_INFORMATION tzinfo;
|
||||
DWORD ret, ret2;
|
||||
|
||||
if (!pGetDynamicTimeZoneInformation)
|
||||
{
|
||||
win_skip("GetDynamicTimeZoneInformation() is not supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = pGetDynamicTimeZoneInformation(&dyninfo);
|
||||
ret2 = GetTimeZoneInformation(&tzinfo);
|
||||
ok(ret == ret2, "got %d, %d\n", ret, ret2);
|
||||
|
||||
ok(dyninfo.Bias == tzinfo.Bias, "got %d, %d\n", dyninfo.Bias, tzinfo.Bias);
|
||||
ok(!lstrcmpW(dyninfo.StandardName, tzinfo.StandardName), "got std name %s, %s\n",
|
||||
wine_dbgstr_w(dyninfo.StandardName), wine_dbgstr_w(tzinfo.StandardName));
|
||||
ok(!memcmp(&dyninfo.StandardDate, &tzinfo.StandardDate, sizeof(dyninfo.StandardDate)), "got different StandardDate\n");
|
||||
ok(dyninfo.StandardBias == tzinfo.StandardBias, "got %d, %d\n", dyninfo.StandardBias, tzinfo.StandardBias);
|
||||
ok(!lstrcmpW(dyninfo.DaylightName, tzinfo.DaylightName), "got daylight name %s, %s\n",
|
||||
wine_dbgstr_w(dyninfo.DaylightName), wine_dbgstr_w(tzinfo.DaylightName));
|
||||
ok(!memcmp(&dyninfo.DaylightDate, &tzinfo.DaylightDate, sizeof(dyninfo.DaylightDate)), "got different DaylightDate\n");
|
||||
ok(dyninfo.TimeZoneKeyName[0] != 0, "got empty tz keyname\n");
|
||||
trace("Dyn TimeZoneKeyName %s\n", wine_dbgstr_w(dyninfo.TimeZoneKeyName));
|
||||
}
|
||||
|
||||
static ULONGLONG get_longlong_time(FILETIME *time)
|
||||
{
|
||||
ULARGE_INTEGER uli;
|
||||
uli.u.LowPart = time->dwLowDateTime;
|
||||
uli.u.HighPart = time->dwHighDateTime;
|
||||
return uli.QuadPart;
|
||||
}
|
||||
|
||||
static void test_GetSystemTimePreciseAsFileTime(void)
|
||||
{
|
||||
FILETIME ft;
|
||||
ULONGLONG time1, time2;
|
||||
LONGLONG diff;
|
||||
|
||||
if (!pGetSystemTimePreciseAsFileTime)
|
||||
{
|
||||
win_skip("GetSystemTimePreciseAsFileTime() is not supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
time1 = get_longlong_time(&ft);
|
||||
pGetSystemTimePreciseAsFileTime(&ft);
|
||||
time2 = get_longlong_time(&ft);
|
||||
diff = time2 - time1;
|
||||
if (diff < 0)
|
||||
diff = -diff;
|
||||
ok(diff < 1000000, "Difference between GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime more than 100 ms\n");
|
||||
|
||||
pGetSystemTimePreciseAsFileTime(&ft);
|
||||
time1 = get_longlong_time(&ft);
|
||||
do {
|
||||
pGetSystemTimePreciseAsFileTime(&ft);
|
||||
time2 = get_longlong_time(&ft);
|
||||
} while (time2 == time1);
|
||||
diff = time2 - time1;
|
||||
ok(diff < 10000 && diff > 0, "GetSystemTimePreciseAsFileTime incremented by more than 1 ms\n");
|
||||
}
|
||||
|
||||
static void test_GetSystemTimes(void)
|
||||
{
|
||||
|
||||
|
@ -743,7 +812,7 @@ static void test_GetSystemTimes(void)
|
|||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi;
|
||||
SYSTEM_BASIC_INFORMATION sbi;
|
||||
ULONG ReturnLength;
|
||||
double total_usertime = 0.0, total_kerneltime = 0.0, total_idletime = 0.0;
|
||||
ULARGE_INTEGER total_usertime, total_kerneltime, total_idletime;
|
||||
|
||||
if (!pGetSystemTimes)
|
||||
{
|
||||
|
@ -753,6 +822,9 @@ static void test_GetSystemTimes(void)
|
|||
|
||||
ok( pGetSystemTimes(NULL, NULL, NULL), "GetSystemTimes failed unexpectedly\n" );
|
||||
|
||||
total_usertime.QuadPart = 0;
|
||||
total_kerneltime.QuadPart = 0;
|
||||
total_idletime.QuadPart = 0;
|
||||
memset( &idletime, 0x11, sizeof(idletime) );
|
||||
memset( &kerneltime, 0x11, sizeof(kerneltime) );
|
||||
memset( &usertime, 0x11, sizeof(usertime) );
|
||||
|
@ -761,19 +833,11 @@ static void test_GetSystemTimes(void)
|
|||
|
||||
ul1.LowPart = idletime.dwLowDateTime;
|
||||
ul1.HighPart = idletime.dwHighDateTime;
|
||||
|
||||
trace( "IdleTime: %f seconds\n", (double)ul1.QuadPart/10000000.0 );
|
||||
|
||||
ul2.LowPart = kerneltime.dwLowDateTime;
|
||||
ul2.HighPart = kerneltime.dwHighDateTime;
|
||||
|
||||
trace( "KernelTime: %f seconds\n", (double)ul2.QuadPart/10000000.0 );
|
||||
|
||||
ul3.LowPart = usertime.dwLowDateTime;
|
||||
ul3.HighPart = usertime.dwHighDateTime;
|
||||
|
||||
trace( "UserTime: %f seconds\n", (double)ul3.QuadPart/10000000.0 );
|
||||
|
||||
ok( !NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength),
|
||||
"NtQuerySystemInformation failed\n" );
|
||||
ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength );
|
||||
|
@ -787,22 +851,20 @@ static void test_GetSystemTimes(void)
|
|||
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors);
|
||||
|
||||
ok( !NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi,
|
||||
sizeof(*sppi), &ReturnLength),
|
||||
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors,
|
||||
&ReturnLength),
|
||||
"NtQuerySystemInformation failed\n" );
|
||||
|
||||
for (i = 0; i < sbi.NumberOfProcessors; i++)
|
||||
{
|
||||
total_usertime += (double)(sppi[i].UserTime.QuadPart)/10000000.0;
|
||||
total_kerneltime += (double)(sppi[i].KernelTime.QuadPart)/10000000.0;
|
||||
total_idletime += (double)(sppi[i].IdleTime.QuadPart)/10000000.0;
|
||||
total_usertime.QuadPart += sppi[i].UserTime.QuadPart;
|
||||
total_kerneltime.QuadPart += sppi[i].KernelTime.QuadPart;
|
||||
total_idletime.QuadPart += sppi[i].IdleTime.QuadPart;
|
||||
}
|
||||
|
||||
trace( "total_idletime %f total_kerneltime %f total_usertime %f \n", total_idletime,
|
||||
total_kerneltime, total_usertime );
|
||||
|
||||
ok( (total_idletime - (double)ul1.QuadPart/10000000.0) < 1.0, "test idletime failed\n" );
|
||||
ok( (total_kerneltime - (double)ul2.QuadPart/10000000.0) < 1.0, "test kerneltime failed\n" );
|
||||
ok( (total_usertime - (double)ul3.QuadPart/10000000.0) < 1.0, "test usertime failed\n" );
|
||||
ok( total_idletime.QuadPart - ul1.QuadPart < 10000000, "test idletime failed\n" );
|
||||
ok( total_kerneltime.QuadPart - ul2.QuadPart < 10000000, "test kerneltime failed\n" );
|
||||
ok( total_usertime.QuadPart - ul3.QuadPart < 10000000, "test usertime failed\n" );
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, sppi);
|
||||
}
|
||||
|
@ -815,6 +877,8 @@ START_TEST(time)
|
|||
pGetSystemTimes = (void *)GetProcAddress( hKernel, "GetSystemTimes");
|
||||
pGetCalendarInfoA = (void *)GetProcAddress(hKernel, "GetCalendarInfoA");
|
||||
pGetCalendarInfoW = (void *)GetProcAddress(hKernel, "GetCalendarInfoW");
|
||||
pGetDynamicTimeZoneInformation = (void *)GetProcAddress(hKernel, "GetDynamicTimeZoneInformation");
|
||||
pGetSystemTimePreciseAsFileTime = (void *)GetProcAddress(hKernel, "GetSystemTimePreciseAsFileTime");
|
||||
|
||||
test_conversions();
|
||||
test_invalid_arg();
|
||||
|
@ -825,4 +889,6 @@ START_TEST(time)
|
|||
test_GetSystemTimes();
|
||||
test_FileTimeToDosDateTime();
|
||||
test_GetCalendarInfo();
|
||||
test_GetDynamicTimeZoneInformation();
|
||||
test_GetSystemTimePreciseAsFileTime();
|
||||
}
|
||||
|
|
|
@ -175,8 +175,8 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
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");
|
||||
ok(curr_found, "couldn't find self in thread list\n");
|
||||
ok(sub_found >= 2, "couldn't find sub-process threads in thread list\n");
|
||||
|
||||
/* check that first really resets enumeration */
|
||||
curr_found = 0;
|
||||
|
@ -192,8 +192,8 @@ static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
|
|||
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");
|
||||
ok(curr_found, "couldn't find self in thread list\n");
|
||||
ok(sub_found >= 2, "couldn't find sub-process threads in thread list\n");
|
||||
|
||||
me.dwSize = sizeof(me);
|
||||
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
|
||||
|
|
|
@ -47,7 +47,11 @@ static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
|||
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
|
||||
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
|
||||
static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
static NTSTATUS (WINAPI *pNtQuerySection)(HANDLE, int, PVOID, ULONG, PULONG);
|
||||
static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
|
||||
static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
|
||||
|
||||
/* ############################### */
|
||||
|
||||
|
@ -254,6 +258,8 @@ static void test_VirtualAlloc(void)
|
|||
void *addr1, *addr2;
|
||||
DWORD old_prot;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
NTSTATUS status;
|
||||
SIZE_T size;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
|
||||
|
@ -389,6 +395,42 @@ static void test_VirtualAlloc(void)
|
|||
"got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
|
||||
|
||||
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
|
||||
addr1 = VirtualAlloc(0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
ok(addr1 != NULL, "VirtualAlloc failed\n");
|
||||
ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1);
|
||||
|
||||
/* allocation conflicts because of 64k align */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
|
||||
/* it should conflict, even when zero_bits is explicitly set */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 12, &size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
todo_wine
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
|
||||
/* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
|
||||
SetLastError(0xdeadbeef);
|
||||
addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
|
||||
ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
|
||||
|
||||
/* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size, MEM_RESERVE |
|
||||
MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
|
||||
todo_wine
|
||||
ok(status == STATUS_INVALID_PARAMETER_5, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
|
||||
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
}
|
||||
|
||||
static void test_MapViewOfFile(void)
|
||||
|
@ -974,8 +1016,8 @@ static void test_NtMapViewOfSection(void)
|
|||
static const char data[] = "test data for NtMapViewOfSection";
|
||||
char buffer[sizeof(data)];
|
||||
HANDLE file, mapping;
|
||||
void *ptr;
|
||||
BOOL ret;
|
||||
void *ptr, *ptr2;
|
||||
BOOL is_wow64, ret;
|
||||
DWORD status, written;
|
||||
SIZE_T size, result;
|
||||
LARGE_INTEGER offset;
|
||||
|
@ -1005,12 +1047,154 @@ static void test_NtMapViewOfSection(void)
|
|||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( !status, "NtMapViewOfSection failed status %x\n", status );
|
||||
ok( !((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr );
|
||||
|
||||
ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
|
||||
ok( ret, "ReadProcessMemory failed\n" );
|
||||
ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
|
||||
ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
|
||||
|
||||
/* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
|
||||
ptr2 = NULL;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
ptr2 = NULL;
|
||||
size = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
/* mapping at the same page conflicts */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* offset has to be aligned */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 1;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* ptr has to be aligned */
|
||||
ptr2 = (char *)ptr + 42;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* still not 64k aligned */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* zero_bits != 0 is not allowed when an address is set */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 0x1001;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 1;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
|
||||
!pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64))
|
||||
{
|
||||
/* new memory region conflicts with previous mapping */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 42;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x1000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
/* the address is rounded down if not on a page boundary */
|
||||
ptr2 = (char *)ptr + 0x1001;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x1000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 0x2000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x2000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_INVALID_PARAMETER_9, "NtMapViewOfSection returned %x\n", status );
|
||||
}
|
||||
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
|
@ -1270,12 +1454,17 @@ static void test_IsBadCodePtr(void)
|
|||
|
||||
static void test_write_watch(void)
|
||||
{
|
||||
char *base;
|
||||
DWORD ret, size, old_prot;
|
||||
static const char pipename[] = "\\\\.\\pipe\\test_write_watch_pipe";
|
||||
static const char testdata[] = "Hello World";
|
||||
DWORD ret, size, old_prot, num_bytes;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
HANDLE readpipe, writepipe;
|
||||
OVERLAPPED overlapped;
|
||||
void *results[64];
|
||||
ULONG_PTR count;
|
||||
ULONG pagesize;
|
||||
BOOL success;
|
||||
char *base;
|
||||
|
||||
if (!pGetWriteWatch || !pResetWriteWatch)
|
||||
{
|
||||
|
@ -1423,6 +1612,64 @@ static void test_write_watch(void)
|
|||
ok( info.State == MEM_COMMIT, "wrong State 0x%x\n", info.State );
|
||||
ok( info.Protect == PAGE_READWRITE, "wrong Protect 0x%x\n", info.Protect );
|
||||
|
||||
/* ReadFile should trigger write watches */
|
||||
|
||||
memset( &overlapped, 0, sizeof(overlapped) );
|
||||
overlapped.hEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
|
||||
|
||||
readpipe = CreateNamedPipeA( pipename, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_INBOUND,
|
||||
PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024,
|
||||
NMPWAIT_USE_DEFAULT_WAIT, NULL );
|
||||
ok( readpipe != INVALID_HANDLE_VALUE, "CreateNamedPipeA failed %u\n", GetLastError() );
|
||||
|
||||
success = ConnectNamedPipe( readpipe, &overlapped );
|
||||
ok( !success, "ConnectNamedPipe unexpectedly succeeded\n" );
|
||||
ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
|
||||
|
||||
writepipe = CreateFileA( pipename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
|
||||
ok( writepipe != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError() );
|
||||
|
||||
ret = WaitForSingleObject( overlapped.hEvent, 1000 );
|
||||
ok( ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret );
|
||||
|
||||
memset( base, 0, size );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 16, "wrong count %lu\n", count );
|
||||
|
||||
success = ReadFile( readpipe, base, size, NULL, &overlapped );
|
||||
ok( !success, "ReadFile unexpectedly succeeded\n" );
|
||||
ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
|
||||
|
||||
count = 64;
|
||||
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
ok( count == 16, "wrong count %lu\n", count );
|
||||
|
||||
num_bytes = 0;
|
||||
success = WriteFile( writepipe, testdata, sizeof(testdata), &num_bytes, NULL );
|
||||
ok( success, "WriteFile failed %u\n", GetLastError() );
|
||||
ok( num_bytes == sizeof(testdata), "wrong number of bytes written\n" );
|
||||
|
||||
num_bytes = 0;
|
||||
success = GetOverlappedResult( readpipe, &overlapped, &num_bytes, TRUE );
|
||||
ok( success, "GetOverlappedResult failed %u\n", GetLastError() );
|
||||
ok( num_bytes == sizeof(testdata), "wrong number of bytes read\n" );
|
||||
ok( !memcmp( base, testdata, sizeof(testdata)), "didn't receive expected data\n" );
|
||||
|
||||
count = 64;
|
||||
memset( results, 0, sizeof(results) );
|
||||
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
|
||||
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
|
||||
todo_wine ok( count == 1, "wrong count %lu\n", count );
|
||||
ok( results[0] == base, "wrong result %p\n", results[0] );
|
||||
|
||||
CloseHandle( readpipe );
|
||||
CloseHandle( writepipe );
|
||||
CloseHandle( overlapped.hEvent );
|
||||
|
||||
/* some invalid parameter tests */
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
|
@ -2496,6 +2743,9 @@ static void test_VirtualProtect(void)
|
|||
DWORD ret, old_prot, rw_prot, exec_prot, i, j;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
SYSTEM_INFO si;
|
||||
void *addr;
|
||||
SIZE_T size;
|
||||
NTSTATUS status;
|
||||
|
||||
GetSystemInfo(&si);
|
||||
trace("system page size %#x\n", si.dwPageSize);
|
||||
|
@ -2504,6 +2754,26 @@ static void test_VirtualProtect(void)
|
|||
base = VirtualAlloc(0, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
|
||||
ok(base != NULL, "VirtualAlloc failed %d\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = VirtualProtect(base, si.dwPageSize, PAGE_READONLY, NULL);
|
||||
ok(!ret, "VirtualProtect should fail\n");
|
||||
ok(GetLastError() == ERROR_NOACCESS, "expected ERROR_NOACCESS, got %d\n", GetLastError());
|
||||
old_prot = 0xdeadbeef;
|
||||
ret = VirtualProtect(base, si.dwPageSize, PAGE_NOACCESS, &old_prot);
|
||||
ok(ret, "VirtualProtect failed %d\n", GetLastError());
|
||||
ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
|
||||
|
||||
addr = base;
|
||||
size = si.dwPageSize;
|
||||
status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_READONLY, NULL);
|
||||
ok(status == STATUS_ACCESS_VIOLATION, "NtProtectVirtualMemory should fail, got %08x\n", status);
|
||||
addr = base;
|
||||
size = si.dwPageSize;
|
||||
old_prot = 0xdeadbeef;
|
||||
status = pNtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, PAGE_NOACCESS, &old_prot);
|
||||
ok(status == STATUS_SUCCESS, "NtProtectVirtualMemory should succeed, got %08x\n", status);
|
||||
ok(old_prot == PAGE_NOACCESS, "got %#x != expected PAGE_NOACCESS\n", old_prot);
|
||||
|
||||
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
|
@ -3726,6 +3996,7 @@ START_TEST(virtual)
|
|||
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
|
||||
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
|
||||
pGetProcessDEPPolicy = (void *)GetProcAddress( hkernel32, "GetProcessDEPPolicy" );
|
||||
pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
|
||||
pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
|
||||
pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
|
||||
pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
|
||||
|
@ -3733,6 +4004,9 @@ START_TEST(virtual)
|
|||
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
|
||||
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
|
||||
pNtQuerySection = (void *)GetProcAddress( hntdll, "NtQuerySection" );
|
||||
pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
|
||||
pNtAllocateVirtualMemory = (void *)GetProcAddress( hntdll, "NtAllocateVirtualMemory" );
|
||||
pNtFreeVirtualMemory = (void *)GetProcAddress( hntdll, "NtFreeVirtualMemory" );
|
||||
|
||||
test_shared_memory(FALSE);
|
||||
test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
|
||||
|
|
|
@ -54,6 +54,7 @@ static UINT (WINAPI *pGetLogicalDriveStringsA)(UINT,LPSTR);
|
|||
static UINT (WINAPI *pGetLogicalDriveStringsW)(UINT,LPWSTR);
|
||||
static BOOL (WINAPI *pGetVolumeInformationA)(LPCSTR, LPSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD);
|
||||
static BOOL (WINAPI *pGetVolumePathNameA)(LPCSTR, LPSTR, DWORD);
|
||||
static BOOL (WINAPI *pGetVolumePathNameW)(LPWSTR, LPWSTR, DWORD);
|
||||
static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameA)(LPCSTR, LPSTR, DWORD, LPDWORD);
|
||||
static BOOL (WINAPI *pGetVolumePathNamesForVolumeNameW)(LPCWSTR, LPWSTR, DWORD, LPDWORD);
|
||||
|
||||
|
@ -535,7 +536,7 @@ static void test_enum_vols(void)
|
|||
/*get windows drive letter and update strings for testing */
|
||||
ret = GetWindowsDirectoryA( windowsdir, sizeof(windowsdir) );
|
||||
ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
|
||||
ok(ret != 0, "GetWindowsDirecory: error %d\n", GetLastError());
|
||||
ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
|
||||
path[0] = windowsdir[0];
|
||||
|
||||
/* get the unique volume name for the windows drive */
|
||||
|
@ -593,82 +594,291 @@ static void test_disk_extents(void)
|
|||
|
||||
static void test_GetVolumePathNameA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
char volume[MAX_PATH];
|
||||
char expected[] = "C:\\", pathC1[] = "C:\\", pathC2[] = "C::";
|
||||
char volume_path[MAX_PATH], cwd[MAX_PATH];
|
||||
struct {
|
||||
const char *file_name;
|
||||
const char *path_name;
|
||||
DWORD path_len;
|
||||
DWORD error;
|
||||
DWORD broken_error;
|
||||
} test_paths[] = {
|
||||
{ /* test 0: NULL parameters, 0 output length */
|
||||
NULL, NULL, 0,
|
||||
ERROR_INVALID_PARAMETER, 0xdeadbeef /* winxp */
|
||||
},
|
||||
{ /* test 1: empty input, NULL output, 0 output length */
|
||||
"", NULL, 0,
|
||||
ERROR_INVALID_PARAMETER, 0xdeadbeef /* winxp */
|
||||
},
|
||||
{ /* test 2: valid input, NULL output, 0 output length */
|
||||
"C:\\", NULL, 0,
|
||||
ERROR_INVALID_PARAMETER, ERROR_FILENAME_EXCED_RANGE /* winxp */
|
||||
},
|
||||
{ /* test 3: valid input, valid output, 0 output length */
|
||||
"C:\\", "C:\\", 0,
|
||||
ERROR_INVALID_PARAMETER, ERROR_FILENAME_EXCED_RANGE /* winxp */
|
||||
},
|
||||
{ /* test 4: valid input, valid output, 1 output length */
|
||||
"C:\\", "C:\\", 1,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 5: valid input, valid output, valid output length */
|
||||
"C:\\", "C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 6: lowercase input, uppercase output, valid output length */
|
||||
"c:\\", "C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 7: poor quality input, valid output, valid output length */
|
||||
"C::", "C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 8: really bogus input, valid output, 1 output length */
|
||||
"\\\\$$$", "C:\\", 1,
|
||||
ERROR_INVALID_NAME, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 9: a reasonable DOS path that is guaranteed to exist */
|
||||
"C:\\windows\\system32", "C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 10: a reasonable DOS path that shouldn't exist */
|
||||
"C:\\windows\\system32\\AnInvalidFolder", "C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 11: a reasonable NT-converted DOS path that shouldn't exist */
|
||||
"\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 12: an unreasonable NT-converted DOS path */
|
||||
"\\\\?\\InvalidDrive:\\AnInvalidFolder", "\\\\?\\InvalidDrive:\\" /* win2k, winxp */,
|
||||
sizeof(volume_path),
|
||||
ERROR_INVALID_NAME, NO_ERROR
|
||||
},
|
||||
{ /* test 13: an unreasonable NT volume path */
|
||||
"\\\\?\\Volume{00000000-00-0000-0000-000000000000}\\AnInvalidFolder",
|
||||
"\\\\?\\Volume{00000000-00-0000-0000-000000000000}\\" /* win2k, winxp */,
|
||||
sizeof(volume_path),
|
||||
ERROR_INVALID_NAME, NO_ERROR
|
||||
},
|
||||
{ /* test 14: an unreasonable NT-ish path */
|
||||
"\\\\ReallyBogus\\InvalidDrive:\\AnInvalidFolder",
|
||||
"\\\\ReallyBogus\\InvalidDrive:\\" /* win2k, winxp */, sizeof(volume_path),
|
||||
ERROR_INVALID_NAME, NO_ERROR
|
||||
},
|
||||
{ /* test 15: poor quality input, valid output, valid output length, different drive */
|
||||
"D::", "D:\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 16: unused drive letter */
|
||||
"M::", "C:\\", 4,
|
||||
ERROR_FILE_NOT_FOUND, ERROR_MORE_DATA
|
||||
},
|
||||
{ /* test 17: an unreasonable DOS path */
|
||||
"InvalidDrive:\\AnInvalidFolder", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 18: a reasonable device path */
|
||||
"\\??\\CdRom0", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 19: an unreasonable device path */
|
||||
"\\??\\ReallyBogus", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 20 */
|
||||
"C:", "C:", 2,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 21 */
|
||||
"C:", "C:", 3,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 22 */
|
||||
"C:\\", "C:", 2,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 23 */
|
||||
"C:\\", "C:", 3,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 24 */
|
||||
"C::", "C:", 2,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 25 */
|
||||
"C::", "C:", 3,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 26 */
|
||||
"C::", "C:\\", 4,
|
||||
NO_ERROR, ERROR_MORE_DATA
|
||||
},
|
||||
{ /* test 27 */
|
||||
"C:\\windows\\system32\\AnInvalidFolder", "C:", 3,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 28 */
|
||||
"\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 3,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 29 */
|
||||
"\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 6,
|
||||
ERROR_FILENAME_EXCED_RANGE, NO_ERROR
|
||||
},
|
||||
{ /* test 30 */
|
||||
"\\\\?\\C:\\AnInvalidFolder", "\\\\?\\C:", 7,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 31 */
|
||||
"\\\\?\\c:\\AnInvalidFolder", "\\\\?\\c:", 7,
|
||||
NO_ERROR, ERROR_FILENAME_EXCED_RANGE
|
||||
},
|
||||
{ /* test 32 */
|
||||
"C:/", "C:\\", 4,
|
||||
NO_ERROR, ERROR_MORE_DATA
|
||||
},
|
||||
{ /* test 33 */
|
||||
"M:/", "", 4,
|
||||
ERROR_FILE_NOT_FOUND, ERROR_MORE_DATA
|
||||
},
|
||||
{ /* test 34 */
|
||||
"C:ABC:DEF:\\AnInvalidFolder", "C:\\", 4,
|
||||
NO_ERROR, ERROR_MORE_DATA
|
||||
},
|
||||
{ /* test 35 */
|
||||
"?:ABC:DEF:\\AnInvalidFolder", "?:\\" /* win2k, winxp */, sizeof(volume_path),
|
||||
ERROR_FILE_NOT_FOUND, NO_ERROR
|
||||
},
|
||||
{ /* test 36 */
|
||||
"relative/path", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 37 */
|
||||
"/unix-style/absolute/path", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 38 */
|
||||
"\\??\\C:\\NonExistent", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 39 */
|
||||
"\\??\\M:\\NonExistent", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 40 */
|
||||
"somefile:def", "%CurrentDrive%\\", sizeof(volume_path),
|
||||
NO_ERROR, NO_ERROR
|
||||
},
|
||||
{ /* test 41 */
|
||||
"s:omefile", "S:\\" /* win2k, winxp */, sizeof(volume_path),
|
||||
ERROR_FILE_NOT_FOUND, NO_ERROR
|
||||
},
|
||||
};
|
||||
BOOL ret, success;
|
||||
DWORD error;
|
||||
UINT i;
|
||||
|
||||
/* GetVolumePathNameA is not present before w2k */
|
||||
if (!pGetVolumePathNameA)
|
||||
{
|
||||
win_skip("required functions not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA(NULL, NULL, 0);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_INVALID_PARAMETER
|
||||
|| broken( error == 0xdeadbeef) /* <=XP */,
|
||||
"expected ERROR_INVALID_PARAMETER got %u\n", error);
|
||||
/* Obtain the drive of the working directory */
|
||||
ret = GetCurrentDirectoryA( sizeof(cwd), cwd );
|
||||
ok( ret, "Failed to obtain the current working directory.\n" );
|
||||
cwd[2] = 0;
|
||||
ret = SetEnvironmentVariableA( "CurrentDrive", cwd );
|
||||
ok( ret, "Failed to set an environment variable for the current working drive.\n" );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA("", NULL, 0);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_INVALID_PARAMETER
|
||||
|| broken( error == 0xdeadbeef) /* <=XP */,
|
||||
"expected ERROR_INVALID_PARAMETER got %u\n", error);
|
||||
for (i=0; i<sizeof(test_paths)/sizeof(test_paths[0]); i++)
|
||||
{
|
||||
BOOL broken_ret = test_paths[i].broken_error == NO_ERROR;
|
||||
char *output = (test_paths[i].path_name != NULL ? volume_path : NULL);
|
||||
BOOL expected_ret = test_paths[i].error == NO_ERROR;
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA(pathC1, NULL, 0);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_INVALID_PARAMETER
|
||||
|| broken(error == ERROR_FILENAME_EXCED_RANGE) /* <=XP */,
|
||||
"expected ERROR_INVALID_PARAMETER got %u\n", error);
|
||||
volume_path[0] = 0;
|
||||
if (test_paths[i].path_len < sizeof(volume_path))
|
||||
volume_path[ test_paths[i].path_len ] = 0x11;
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA(pathC1, volume, 0);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_INVALID_PARAMETER
|
||||
|| broken(error == ERROR_FILENAME_EXCED_RANGE ) /* <=XP */,
|
||||
"expected ERROR_INVALID_PARAMETER got %u\n", error);
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA( test_paths[i].file_name, output, test_paths[i].path_len );
|
||||
error = GetLastError();
|
||||
ok(ret == expected_ret || broken(ret == broken_ret),
|
||||
"GetVolumePathName test %d %s unexpectedly.\n",
|
||||
i, test_paths[i].error == NO_ERROR ? "failed" : "succeeded");
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA(pathC1, volume, 1);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_FILENAME_EXCED_RANGE, "expected ERROR_FILENAME_EXCED_RANGE got %u\n", error);
|
||||
if (ret)
|
||||
{
|
||||
char path_name[MAX_PATH];
|
||||
|
||||
volume[0] = '\0';
|
||||
ret = pGetVolumePathNameA(pathC1, volume, sizeof(volume));
|
||||
ok(ret, "expected success\n");
|
||||
ok(!strcmp(expected, volume), "expected name '%s', returned '%s'\n", pathC1, volume);
|
||||
ExpandEnvironmentStringsA( test_paths[i].path_name, path_name, MAX_PATH);
|
||||
/* If we succeeded then make sure the path is correct */
|
||||
success = (strcmp( volume_path, path_name ) == 0)
|
||||
|| broken(strcasecmp( volume_path, path_name ) == 0) /* XP */;
|
||||
ok(success, "GetVolumePathName test %d unexpectedly returned path %s (expected %s).\n",
|
||||
i, volume_path, path_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* On success Windows always returns ERROR_MORE_DATA, so only worry about failure */
|
||||
success = (error == test_paths[i].error || broken(error == test_paths[i].broken_error));
|
||||
ok(success, "GetVolumePathName test %d unexpectedly returned error 0x%x (expected 0x%x).\n",
|
||||
i, error, test_paths[i].error);
|
||||
}
|
||||
|
||||
pathC1[0] = tolower(pathC1[0]);
|
||||
volume[0] = '\0';
|
||||
ret = pGetVolumePathNameA(pathC1, volume, sizeof(volume));
|
||||
ok(ret, "expected success\n");
|
||||
todo_wine
|
||||
ok(!strcmp(expected, volume) || broken(!strcasecmp(expected, volume)) /* <=XP */,
|
||||
"expected name '%s', returned '%s'\n", expected, volume);
|
||||
if (test_paths[i].path_len < sizeof(volume_path))
|
||||
ok(volume_path[ test_paths[i].path_len ] == 0x11,
|
||||
"GetVolumePathName test %d corrupted byte after end of buffer.\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
volume[0] = '\0';
|
||||
ret = pGetVolumePathNameA(pathC2, volume, sizeof(volume));
|
||||
todo_wine
|
||||
ok(ret, "expected success\n");
|
||||
todo_wine
|
||||
ok(!strcmp(expected, volume), "expected name '%s', returned '%s'\n", expected, volume);
|
||||
static void test_GetVolumePathNameW(void)
|
||||
{
|
||||
static WCHAR drive_c1[] = {'C',':',0};
|
||||
static WCHAR drive_c2[] = {'C',':','\\',0};
|
||||
WCHAR volume_path[MAX_PATH];
|
||||
BOOL ret;
|
||||
|
||||
/* test an invalid path */
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = pGetVolumePathNameA("\\\\$$$", volume, 1);
|
||||
error = GetLastError();
|
||||
ok(!ret, "expected failure\n");
|
||||
ok(error == ERROR_INVALID_NAME || broken(ERROR_FILENAME_EXCED_RANGE) /* <=2000 */,
|
||||
"expected ERROR_INVALID_NAME got %u\n", error);
|
||||
if (!pGetVolumePathNameW)
|
||||
{
|
||||
win_skip("required functions not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
volume_path[0] = 0;
|
||||
volume_path[1] = 0x11;
|
||||
ret = pGetVolumePathNameW( drive_c1, volume_path, 1 );
|
||||
ok(!ret, "GetVolumePathNameW test succeeded unexpectedly.\n");
|
||||
ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE, "GetVolumePathNameW unexpectedly returned error 0x%x (expected 0x%x).\n",
|
||||
GetLastError(), ERROR_FILENAME_EXCED_RANGE);
|
||||
ok(volume_path[1] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
|
||||
|
||||
volume_path[0] = 0;
|
||||
volume_path[2] = 0x11;
|
||||
ret = pGetVolumePathNameW( drive_c1, volume_path, 2 );
|
||||
ok(!ret, "GetVolumePathNameW test succeeded unexpectedly.\n");
|
||||
ok(GetLastError() == ERROR_FILENAME_EXCED_RANGE, "GetVolumePathNameW unexpectedly returned error 0x%x (expected 0x%x).\n",
|
||||
GetLastError(), ERROR_FILENAME_EXCED_RANGE);
|
||||
ok(volume_path[2] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
|
||||
|
||||
volume_path[0] = 0;
|
||||
volume_path[3] = 0x11;
|
||||
ret = pGetVolumePathNameW( drive_c1, volume_path, 3 );
|
||||
ok(ret || broken(!ret) /* win2k */, "GetVolumePathNameW test failed unexpectedly.\n");
|
||||
ok(memcmp(volume_path, drive_c1, sizeof(drive_c1)) == 0
|
||||
|| broken(volume_path[0] == 0) /* win2k */,
|
||||
"GetVolumePathNameW unexpectedly returned wrong path.\n");
|
||||
ok(volume_path[3] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
|
||||
|
||||
volume_path[0] = 0;
|
||||
volume_path[4] = 0x11;
|
||||
ret = pGetVolumePathNameW( drive_c1, volume_path, 4 );
|
||||
ok(ret, "GetVolumePathNameW test failed unexpectedly.\n");
|
||||
ok(memcmp(volume_path, drive_c2, sizeof(drive_c2)) == 0, "GetVolumePathNameW unexpectedly returned wrong path.\n");
|
||||
ok(volume_path[4] == 0x11, "GetVolumePathW corrupted byte after end of buffer.\n");
|
||||
}
|
||||
|
||||
static void test_GetVolumePathNamesForVolumeNameA(void)
|
||||
|
@ -1016,6 +1226,7 @@ START_TEST(volume)
|
|||
pGetLogicalDriveStringsW = (void *) GetProcAddress(hdll, "GetLogicalDriveStringsW");
|
||||
pGetVolumeInformationA = (void *) GetProcAddress(hdll, "GetVolumeInformationA");
|
||||
pGetVolumePathNameA = (void *) GetProcAddress(hdll, "GetVolumePathNameA");
|
||||
pGetVolumePathNameW = (void *) GetProcAddress(hdll, "GetVolumePathNameW");
|
||||
pGetVolumePathNamesForVolumeNameA = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameA");
|
||||
pGetVolumePathNamesForVolumeNameW = (void *) GetProcAddress(hdll, "GetVolumePathNamesForVolumeNameW");
|
||||
|
||||
|
@ -1023,6 +1234,7 @@ START_TEST(volume)
|
|||
test_define_dos_deviceA();
|
||||
test_FindFirstVolume();
|
||||
test_GetVolumePathNameA();
|
||||
test_GetVolumePathNameW();
|
||||
test_GetVolumeNameForVolumeMountPointA();
|
||||
test_GetVolumeNameForVolumeMountPointW();
|
||||
test_GetLogicalDriveStringsA();
|
||||
|
|
Loading…
Reference in a new issue