* Sync with Wine 1.7.17.
CORE-8080
svn path=/trunk/; revision=62842
remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502)
-add_definitions(-D__ROS_LONG64__)
+add_definitions(-D__WINESRC__)
list(APPEND SOURCE
atom.c
#include <stdarg.h>
#include "ntstatus.h"
-/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
+/* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro
* definition errors when we get to winnt.h
*/
#define WIN32_NO_STATUS
{
NTSTATUS res;
RTL_ATOM atom;
- ULONG ptr[(sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR) + sizeof(ULONG)) / sizeof(ULONG)];
+ char ptr[sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR)];
ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr;
ULONG ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR);
memset( ptr, 0xcc, sizeof(ptr) );
res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
- ok(!res, "atom lookup failed with status = 0x%x\n", res);
+ ok(!res, "atom lookup\n");
ok(!lstrcmpW(abi->Name, testAtom1), "ok strings\n");
ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
ok(abi->Name[lstrlenW(testAtom1)] == 0, "wrong string termination %x\n", abi->Name[lstrlenW(testAtom1)]);
OPEN_EXISTING, fflags, NULL);
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
- hEvent = CreateEvent( NULL, 0, 0, NULL );
+ hEvent = CreateEventA( NULL, 0, 0, NULL );
r = pNtNotifyChangeDirectoryFile(hdir,NULL,NULL,NULL,&iosb,NULL,0,0,0);
ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n");
OPEN_EXISTING, fflags, NULL);
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
- hEvent = CreateEvent( NULL, 0, 0, NULL );
+ hEvent = CreateEventA( NULL, 0, 0, NULL );
filter = FILE_NOTIFY_CHANGE_FILE_NAME;
filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
START_TEST(change)
{
- HMODULE hntdll = GetModuleHandle("ntdll");
+ HMODULE hntdll = GetModuleHandleA("ntdll");
if (!hntdll)
{
win_skip("not running on NT, skipping test\n");
continue;
sprintf(buf, "%s\\%s", testdirA, testfiles[i].name);
if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) {
- ret = RemoveDirectory(buf);
+ ret = RemoveDirectoryA(buf);
ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
"Failed to rmdir %s, error %d\n", buf, GetLastError());
} else {
- ret = DeleteFile(buf);
+ ret = DeleteFileA(buf);
ok(ret || (GetLastError() == ERROR_PATH_NOT_FOUND),
"Failed to rm %s, error %d\n", buf, GetLastError());
}
static ULONG (WINAPI *pRtlNtStatusToDosError)(NTSTATUS Status);
static int strict;
-static int prepare_test(void)
+static BOOL prepare_test(void)
{
HMODULE ntdll;
int argc;
if (!pRtlNtStatusToDosError)
{
win_skip("RtlNtStatusToDosError is not available\n");
- return 0;
+ return FALSE;
}
argc = winetest_get_mainargs(&argv);
strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
- return 1;
+ return TRUE;
}
static void cmp_call(NTSTATUS win_nt, ULONG win32, const char* message)
static NTSTATUS (WINAPI *pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
+#if defined(__x86_64__)
+static BOOLEAN (CDECL *pRtlAddFunctionTable)(RUNTIME_FUNCTION*, DWORD, DWORD64);
+static BOOLEAN (CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
+static BOOLEAN (CDECL *pRtlInstallFunctionTableCallback)(DWORD64, DWORD64, DWORD, PGET_RUNTIME_FUNCTION_CALLBACK, PVOID, PCWSTR);
+static PRUNTIME_FUNCTION (WINAPI *pRtlLookupFunctionEntry)(ULONG64, ULONG64*, UNWIND_HISTORY_TABLE*);
+#endif
+
#ifdef __i386__
#ifndef __WINE_WINTRNL_H
return ExceptionContinueSearch;
/* Eip in context is decreased by 1
- * Increase it again, else execution will continue in the middle of a instruction */
+ * Increase it again, else execution will continue in the middle of an instruction */
if(rec->ExceptionCode == EXCEPTION_BREAKPOINT && (context->Eip == (DWORD)code_mem + 0xa))
context->Eip += 1;
return ExceptionContinueExecution;
{
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
- STARTUPINFO si = { 0 };
+ STARTUPINFOA si = { 0 };
DEBUG_EVENT de;
DWORD continuestatus;
PVOID code_mem_address = NULL;
}
sprintf(cmdline, "%s %s %s %p", my_argv[0], my_argv[1], "debuggee", &test_stage);
- ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "could not create child process error: %u\n", GetLastError());
if (!ret)
return;
if (counter > 100)
{
- ok(FALSE, "got way too many exceptions, probably caught in a infinite loop, terminating child\n");
+ ok(FALSE, "got way too many exceptions, probably caught in an infinite loop, terminating child\n");
pNtTerminateProcess(pi.hProcess, 1);
}
else if (counter >= 2) /* skip startup breakpoint */
static void test_dpe_exceptions(void)
{
- static char single_ret[] = {0xC3};
+ static const BYTE single_ret[] = {0xC3};
struct dpe_exception_info info;
NTSTATUS stat;
BOOL has_hw_support;
DWORD val;
ULONG len;
- /* Query DEP with len to small */
+ /* Query DEP with len too small */
stat = pNtQueryInformationProcess(GetCurrentProcess(), ProcessExecuteFlags, &val, sizeof val - 1, &len);
if(stat == STATUS_INVALID_INFO_CLASS)
{
call_virtual_unwind( i, &tests[i] );
}
+static RUNTIME_FUNCTION* CALLBACK dynamic_unwind_callback( DWORD64 pc, PVOID context )
+{
+ static const int code_offset = 1024;
+ static RUNTIME_FUNCTION runtime_func;
+ (*(DWORD *)context)++;
+
+ runtime_func.BeginAddress = code_offset + 16;
+ runtime_func.EndAddress = code_offset + 32;
+ runtime_func.UnwindData = 0;
+ return &runtime_func;
+}
+
+static void test_dynamic_unwind(void)
+{
+ static const int code_offset = 1024;
+ char buf[sizeof(RUNTIME_FUNCTION) + 4];
+ RUNTIME_FUNCTION *runtime_func, *func;
+ ULONG_PTR table, base;
+ DWORD count;
+
+ /* Test RtlAddFunctionTable with aligned RUNTIME_FUNCTION pointer */
+ runtime_func = (RUNTIME_FUNCTION *)buf;
+ runtime_func->BeginAddress = code_offset;
+ runtime_func->EndAddress = code_offset + 16;
+ runtime_func->UnwindData = 0;
+ ok( pRtlAddFunctionTable( runtime_func, 1, (ULONG_PTR)code_mem ),
+ "RtlAddFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
+
+ /* Lookup function outside of any function table */
+ base = 0xdeadbeef;
+ func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 16, &base, NULL );
+ ok( func == NULL,
+ "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n", func );
+ ok( base == 0xdeadbeef,
+ "RtlLookupFunctionEntry modified base address, expected: 0xdeadbeef, got: %lx\n", base );
+
+ /* Test with pointer inside of our function */
+ base = 0xdeadbeef;
+ func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 8, &base, NULL );
+ ok( func == runtime_func,
+ "RtlLookupFunctionEntry didn't return expected function, expected: %p, got: %p\n", runtime_func, func );
+ ok( base == (ULONG_PTR)code_mem,
+ "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (ULONG_PTR)code_mem, base );
+
+ /* Test RtlDeleteFunctionTable */
+ ok( pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable failed for runtime_func = %p (aligned)\n", runtime_func );
+ ok( !pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
+
+ /* Unaligned RUNTIME_FUNCTION pointer */
+ runtime_func = (RUNTIME_FUNCTION *)((ULONG_PTR)buf | 0x3);
+ runtime_func->BeginAddress = code_offset;
+ runtime_func->EndAddress = code_offset + 16;
+ runtime_func->UnwindData = 0;
+ ok( pRtlAddFunctionTable( runtime_func, 1, (ULONG_PTR)code_mem ),
+ "RtlAddFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
+ ok( pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable failed for runtime_func = %p (unaligned)\n", runtime_func );
+
+ /* Attempt to insert the same entry twice */
+ runtime_func = (RUNTIME_FUNCTION *)buf;
+ runtime_func->BeginAddress = code_offset;
+ runtime_func->EndAddress = code_offset + 16;
+ runtime_func->UnwindData = 0;
+ ok( pRtlAddFunctionTable( runtime_func, 1, (ULONG_PTR)code_mem ),
+ "RtlAddFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
+ ok( pRtlAddFunctionTable( runtime_func, 1, (ULONG_PTR)code_mem ),
+ "RtlAddFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
+ ok( pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable failed for runtime_func = %p (first attempt)\n", runtime_func );
+ ok( pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable failed for runtime_func = %p (second attempt)\n", runtime_func );
+ ok( !pRtlDeleteFunctionTable( runtime_func ),
+ "RtlDeleteFunctionTable returned success for nonexistent table runtime_func = %p\n", runtime_func );
+
+ /* Test RtlInstallFunctionTableCallback with both low bits unset */
+ table = (ULONG_PTR)code_mem;
+ ok( !pRtlInstallFunctionTableCallback( table, (ULONG_PTR)code_mem, code_offset + 32, &dynamic_unwind_callback, (PVOID*)&count, NULL ),
+ "RtlInstallFunctionTableCallback returned success for table = %lx\n", table );
+
+ /* Test RtlInstallFunctionTableCallback with both low bits set */
+ table = (ULONG_PTR)code_mem | 0x3;
+ ok( pRtlInstallFunctionTableCallback( table, (ULONG_PTR)code_mem, code_offset + 32, &dynamic_unwind_callback, (PVOID*)&count, NULL ),
+ "RtlInstallFunctionTableCallback failed for table = %lx\n", table );
+
+ /* Lookup function outside of any function table */
+ count = 0;
+ base = 0xdeadbeef;
+ func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 32, &base, NULL );
+ ok( func == NULL,
+ "RtlLookupFunctionEntry returned unexpected function, expected: NULL, got: %p\n", func );
+ ok( base == 0xdeadbeef,
+ "RtlLookupFunctionEntry modified base address, expected: 0xdeadbeef, got: %lx\n", base );
+ ok( !count,
+ "RtlLookupFunctionEntry issued %d unexpected calls to dynamic_unwind_callback\n", count );
+
+ /* Test with pointer inside of our function */
+ count = 0;
+ base = 0xdeadbeef;
+ func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 24, &base, NULL );
+ ok( func != NULL && func->BeginAddress == code_offset + 16 && func->EndAddress == code_offset + 32,
+ "RtlLookupFunctionEntry didn't return expected function, got: %p\n", func );
+ ok( base == (ULONG_PTR)code_mem,
+ "RtlLookupFunctionEntry returned invalid base, expected: %lx, got: %lx\n", (ULONG_PTR)code_mem, base );
+ ok( count == 1,
+ "RtlLookupFunctionEntry issued %d calls to dynamic_unwind_callback, expected: 1\n", count );
+
+ /* Clean up again */
+ ok( pRtlDeleteFunctionTable( (PRUNTIME_FUNCTION)table ),
+ "RtlDeleteFunctionTable failed for table = %p\n", (PVOID)table );
+ ok( !pRtlDeleteFunctionTable( (PRUNTIME_FUNCTION)table ),
+ "RtlDeleteFunctionTable returned success for nonexistent table = %p\n", (PVOID)table );
+
+}
+
#endif /* __x86_64__ */
START_TEST(exception)
"NtQueryInformationProcess" );
pNtSetInformationProcess = (void*)GetProcAddress( hntdll,
"NtSetInformationProcess" );
- pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
+ pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
#ifdef __i386__
if (!pNtCurrentTeb)
test_dpe_exceptions();
#elif defined(__x86_64__)
+ pRtlAddFunctionTable = (void *)GetProcAddress( hntdll,
+ "RtlAddFunctionTable" );
+ pRtlDeleteFunctionTable = (void *)GetProcAddress( hntdll,
+ "RtlDeleteFunctionTable" );
+ pRtlInstallFunctionTableCallback = (void *)GetProcAddress( hntdll,
+ "RtlInstallFunctionTableCallback" );
+ pRtlLookupFunctionEntry = (void *)GetProcAddress( hntdll,
+ "RtlLookupFunctionEntry" );
test_virtual_unwind();
+ if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry)
+ test_dynamic_unwind();
+ else
+ skip( "Dynamic unwind functions not found\n" );
+
#endif
VirtualFree(code_mem, 0, MEM_FREE);
static BOOL create_pipe( HANDLE *read, HANDLE *write, ULONG flags, ULONG size )
{
- *read = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
+ *read = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_INBOUND | flags, PIPE_TYPE_BYTE | PIPE_WAIT,
1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(*read != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
iosb.Information = 0xdeadbeef;
offset.QuadPart = strlen(text) + 2;
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
-todo_wine
- ok(status == STATUS_PENDING || broken(status == STATUS_END_OF_FILE) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
+ ok(status == STATUS_PENDING || status == STATUS_END_OF_FILE /* before Vista */, "expected STATUS_PENDING or STATUS_END_OF_FILE, got %#x\n", status);
if (status == STATUS_PENDING) /* vista */
{
WaitForSingleObject( event, 1000 );
ResetEvent( event );
status = pNtReadFile( handle, event, apc, &apc_count, &iosb, buffer, 2, &offset, NULL );
ok( status == STATUS_END_OF_FILE, "wrong status %x\n", status );
- todo_wine ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
- todo_wine ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
- todo_wine ok( is_signaled( event ), "event is not signaled\n" );
+ ok( U(iosb).Status == STATUS_END_OF_FILE, "wrong status %x\n", U(iosb).Status );
+ ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information );
+ ok( is_signaled( event ), "event is not signaled\n" );
ok( !apc_count, "apc was called\n" );
SleepEx( 1, TRUE ); /* alertable sleep */
ok( !apc_count, "apc was called\n" );
static void append_file_test(void)
{
- const char text[] = "foobar";
+ static const char text[6] = "foobar";
HANDLE handle;
NTSTATUS status;
IO_STATUS_BLOCK iosb;
- DWORD written;
- char path[MAX_PATH], buffer[MAX_PATH];
+ LARGE_INTEGER offset;
+ char path[MAX_PATH], buffer[MAX_PATH], buf[16];
+ DWORD ret;
GetTempPathA( MAX_PATH, path );
GetTempFileNameA( path, "foo", 0, buffer );
+
+ handle = CreateFileA(buffer, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0);
+ ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text, 2, NULL, NULL);
+ ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
+
+ CloseHandle(handle);
+
/* It is possible to open a file with only FILE_APPEND_DATA access flags.
It matches the O_WRONLY|O_APPEND open() posix behavior */
- handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, CREATE_ALWAYS,
- FILE_FLAG_DELETE_ON_CLOSE, 0);
- ok( handle != INVALID_HANDLE_VALUE, "Failed to create a temp file in FILE_APPEND_DATA mode.\n" );
- if(handle == INVALID_HANDLE_VALUE)
- {
- skip("Couldn't create a temporary file, skipping FILE_APPEND_DATA test\n");
- return;
- }
+ handle = CreateFileA(buffer, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
- U(iosb).Status = STATUS_PENDING;
- iosb.Information = 0;
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ offset.QuadPart = 1;
+ status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 2, 2, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
- status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb,
- text, sizeof(text), NULL, NULL);
+ ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
+ ok(ret == 4, "expected 4, got %u\n", ret);
- if (status == STATUS_PENDING)
- {
- WaitForSingleObject( handle, 1000 );
- status = U(iosb).Status;
- }
- written = iosb.Information;
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ offset.QuadPart = 3;
+ status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 4, 2, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 2, "expected 2, got %lu\n", iosb.Information);
- todo_wine
- ok(status == STATUS_SUCCESS && written == sizeof(text), "FILE_APPEND_DATA NtWriteFile failed\n");
+ ret = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
+ ok(ret == 6, "expected 6, got %u\n", ret);
+
+ CloseHandle(handle);
+
+ handle = CreateFileA(buffer, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(handle != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+ memset(buf, 0, sizeof(buf));
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ offset.QuadPart = 0;
+ status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
+ buf[6] = 0;
+ ok(memcmp(buf, text, 6) == 0, "wrong file contents: %s\n", buf);
+
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ offset.QuadPart = 0;
+ status = pNtWriteFile(handle, NULL, NULL, NULL, &iosb, text + 3, 3, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 3, "expected 3, got %lu\n", iosb.Information);
+
+ memset(buf, 0, sizeof(buf));
+ U(iosb).Status = -1;
+ iosb.Information = -1;
+ offset.QuadPart = 0;
+ status = pNtReadFile(handle, 0, NULL, NULL, &iosb, buf, sizeof(buf), &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
+ ok(U(iosb).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iosb).Status);
+ ok(iosb.Information == 6, "expected 6, got %lu\n", iosb.Information);
+ buf[6] = 0;
+ ok(memcmp(buf, "barbar", 6) == 0, "wrong file contents: %s\n", buf);
CloseHandle(handle);
+ DeleteFileA(buffer);
}
static void nt_mailslot_test(void)
static void test_file_disposition_information(void)
{
- char buffer[MAX_PATH + 16];
+ char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
DWORD dirpos;
HANDLE handle, handle2;
NTSTATUS res;
FILE_DISPOSITION_INFORMATION fdi;
BOOL fileDeleted;
+ GetTempPathA( MAX_PATH, tmp_path );
+
/* cannot set disposition on file not opened with delete access */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
res = pNtQueryInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
DeleteFileA( buffer );
/* can set disposition on file opened with proper access */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
DeleteFileA( buffer );
/* cannot set disposition on readonly file */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
DeleteFileA( buffer );
/* can set disposition on file and then reset it */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
DeleteFileA( buffer );
/* Delete-on-close flag doesn't change file disposition until a handle is closed */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = FALSE;
DeleteFileA( buffer );
/* Delete-on-close flag sets disposition when a handle is closed and then it could be changed back */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
ok( DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &handle2, 0, FALSE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
DeleteFileA( buffer );
/* can set disposition on a directory opened with proper access */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
RemoveDirectoryA( buffer );
/* RemoveDirectory sets directory disposition and it can be undone */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
RemoveDirectoryA( buffer );
/* cannot set disposition on a non-empty directory */
- GetTempFileNameA( ".", "dis", 0, buffer );
+ GetTempFileNameA( tmp_path, "dis", 0, buffer );
DeleteFileA( buffer );
ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" );
handle = CreateFileA(buffer, DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
static void test_read_write(void)
{
- static const char contents[] = "1234567890abcd";
+ static const char contents[14] = "1234567890abcd";
char buf[256];
HANDLE hfile;
OVERLAPPED ovl;
IO_STATUS_BLOCK iob;
- DWORD ret, bytes, status;
+ DWORD ret, bytes, status, off;
LARGE_INTEGER offset;
+ LONG i;
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtWriteFile(INVALID_HANDLE_VALUE, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_INVALID_HANDLE, "expected STATUS_OBJECT_TYPE_MISMATCH, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
hfile = create_temp_file(0);
if (!hfile) return;
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_INVALID_USER_BUFFER, "expected STATUS_INVALID_USER_BUFFER, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, NULL, sizeof(contents), NULL, NULL);
ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
- status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
+ status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, 7, NULL, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
- ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 7, "expected 7, got %lu\n", iob.Information);
+
+ SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
+ status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents + 7, sizeof(contents) - 7, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == sizeof(contents) - 7, "expected sizeof(contents)-7, got %lu\n", iob.Information);
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
+ ok(!ret, "ReadFile should fail\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, 0, &bytes, NULL);
+ ok(ret, "ReadFile error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
+ for (i = -20; i < -1; i++)
+ {
+ if (i == -2) continue;
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)i;
+ status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+ ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ }
+
SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
+ ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
+ ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
ok(ret, "WriteFile error %d\n", GetLastError());
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
- iob.Status = -1;
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
+ /* test reading beyond EOF */
+ bytes = -1;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
+ ok(ret, "ReadFile error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ bytes = -1;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, 0, &bytes, NULL);
+ ok(ret, "ReadFile error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ bytes = -1;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, NULL, 0, &bytes, NULL);
+ ok(ret, "ReadFile error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ S(U(ovl)).Offset = sizeof(contents);
+ S(U(ovl)).OffsetHigh = 0;
+ ovl.Internal = -1;
+ ovl.InternalHigh = -1;
+ ovl.hEvent = 0;
+ bytes = -1;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
+ ok(!ret, "ReadFile should fail\n");
+ ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+
+ S(U(ovl)).Offset = sizeof(contents);
+ S(U(ovl)).OffsetHigh = 0;
+ ovl.Internal = -1;
+ ovl.InternalHigh = -1;
+ ovl.hEvent = 0;
+ bytes = -1;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
+ ok(ret, "ReadFile error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+
+ U(iob).Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
-todo_wine
- ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
-todo_wine
+ ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
- iob.Status = -1;
+ U(iob).Status = -1;
+ iob.Information = -1;
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
+ ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = sizeof(contents);
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
+ ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
+ ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = sizeof(contents);
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
-todo_wine
- ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
-todo_wine
+ ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
+ ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+
+ for (i = -20; i < 0; i++)
+ {
+ if (i == -2) continue;
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)i;
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+ ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ }
+
SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
bytes = 0;
ok(bytes == sizeof(contents), "bytes %u\n", bytes);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
- iob.Status = -1;
- iob.Information = -1;
- status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
- ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
-todo_wine
- ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
-todo_wine
- ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
- iob.Status = -1;
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = sizeof(contents) - 4;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
ok(status == STATUS_SUCCESS, "NtWriteFile error %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
- iob.Status = -1;
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
ok(status == STATUS_SUCCESS, "NtReadFile error %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
S(U(ovl)).Offset = sizeof(contents) - 4;
S(U(ovl)).OffsetHigh = 0;
ovl.hEvent = 0;
ok(ret, "WriteFile error %d\n", GetLastError());
ok(bytes == 4, "bytes %u\n", bytes);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == sizeof(contents), "expected sizeof(contents), got %u\n", off);
+
CloseHandle(hfile);
hfile = create_temp_file(FILE_FLAG_OVERLAPPED);
if (!hfile) return;
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(INVALID_HANDLE_VALUE, buf, 0, &bytes, NULL);
+ ok(!ret, "ReadFile should fail\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ S(U(ovl)).Offset = 0;
+ S(U(ovl)).OffsetHigh = 0;
+ ovl.Internal = -1;
+ ovl.InternalHigh = -1;
+ ovl.hEvent = 0;
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ /* ReadFile return value depends on Windows version and testing it is not practical */
+ ReadFile(hfile, buf, 0, &bytes, &ovl);
+ ok(bytes == 0, "bytes %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, contents, sizeof(contents), &bytes, NULL);
-todo_wine
ok(!ret, "WriteFile should fail\n");
-todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
-todo_wine
ok(bytes == 0, "bytes %u\n", bytes);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), NULL, NULL);
-todo_wine
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
-todo_wine
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
-todo_wine
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
- iob.Status = -1;
- iob.Information = -1;
- offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
- status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
-todo_wine
- ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
-todo_wine
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
-todo_wine
- ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ for (i = -20; i < -1; i++)
+ {
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)i;
+ status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+ ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ }
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, contents, sizeof(contents), &offset, NULL);
-todo_wine
- ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* see below */, "expected STATUS_PENDING, got %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
- ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
- /* even fully updated XP passes this test, but it looks like some VMs
- * in a testbot get never updated, so overlapped IO is broken. Instead
- * of fighting with broken tests and adding a bunch of broken() statements
- * it's better to skip further tests completely.
- */
- if (status != STATUS_PENDING)
+ ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
+ if (status == STATUS_PENDING)
{
-todo_wine
- win_skip("broken overlapped IO implementation, update your OS\n");
- CloseHandle(hfile);
- return;
+ ret = WaitForSingleObject(hfile, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
}
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
- ret = WaitForSingleObject(hfile, 3000);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
bytes = 0xdeadbeef;
SetLastError(0xdeadbeef);
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
ok(bytes == 0, "bytes %u\n", bytes);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), NULL, NULL);
ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
- iob.Status = -1;
- iob.Information = -1;
- offset.QuadPart = (LONGLONG)-2 /* FILE_USE_FILE_POINTER_POSITION */;
- status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
- ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
- ok(iob.Status == -1, "expected -1, got %#x\n", iob.Status);
- ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ for (i = -20; i < 0; i++)
+ {
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = (LONGLONG)i;
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+ ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+ }
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+ /* test reading beyond EOF */
offset.QuadPart = sizeof(contents);
S(U(ovl)).Offset = offset.u.LowPart;
S(U(ovl)).OffsetHigh = offset.u.HighPart;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
ok(!ret, "ReadFile should fail\n");
- ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == ERROR_HANDLE_EOF), "expected ERROR_IO_PENDING, got %d\n", GetLastError());
- /* even fully updated XP passes this test, but it looks like some VMs
- * in a testbot get never updated, so overlapped IO is broken. Instead
- * of fighting with broken tests and adding a bunch of broken() statements
- * it's better to skip further tests completely.
- */
- if (GetLastError() != ERROR_IO_PENDING)
+ ret = GetLastError();
+ ok(ret == ERROR_IO_PENDING || ret == ERROR_HANDLE_EOF /* before Vista */, "expected ERROR_IO_PENDING or ERROR_HANDLE_EOF, got %d\n", ret);
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
+ if (ret == ERROR_IO_PENDING)
{
- win_skip("broken overlapped IO implementation, update your OS\n");
- CloseHandle(hfile);
- return;
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
+ ok(!ret, "GetOverlappedResult should report FALSE\n");
+ ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
+ ok(bytes == 0, "expected 0, read %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
}
- ok(bytes == 0, "bytes %u\n", bytes);
- ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
- ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
- bytes = 0xdeadbeef;
- ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
- ok(!ret, "GetOverlappedResult should report FALSE\n");
- ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
- ok(bytes == 0, "expected 0, read %u\n", bytes);
- ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
- ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
- iob.Status = -1;
- iob.Information = -1;
offset.QuadPart = sizeof(contents);
- status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
- ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
- ok(iob.Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", iob.Status);
- ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ S(U(ovl)).Offset = offset.u.LowPart;
+ S(U(ovl)).OffsetHigh = offset.u.HighPart;
+ ovl.Internal = -1;
+ ovl.InternalHigh = -1;
+ ovl.hEvent = 0;
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, buf, 0, &bytes, &ovl);
+ /* ReadFile return value depends on Windows version and testing it is not practical */
+ if (!ret)
+todo_wine
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ret = GetLastError();
+ ok(bytes == 0, "bytes %u\n", bytes);
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+ if (ret == ERROR_IO_PENDING)
+ {
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
+ ok(ret, "GetOverlappedResult should report TRUE\n");
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "expected 0, read %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+ }
+
+ offset.QuadPart = sizeof(contents);
S(U(ovl)).Offset = offset.u.LowPart;
S(U(ovl)).OffsetHigh = offset.u.HighPart;
- ovl.Internal = iob.Status;
- ovl.InternalHigh = iob.Information;
+ ovl.Internal = -1;
+ ovl.InternalHigh = -1;
ovl.hEvent = 0;
bytes = 0xdeadbeef;
- ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
- ok(!ret, "GetOverlappedResult should report FALSE\n");
- ok(GetLastError() == ERROR_HANDLE_EOF, "expected ERROR_HANDLE_EOF, got %d\n", GetLastError());
- ok(bytes == 0, "expected 0, read %u\n", bytes);
- ok((NTSTATUS)ovl.Internal == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#lx\n", ovl.Internal);
- ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(hfile, NULL, 0, &bytes, &ovl);
+ /* ReadFile return value depends on Windows version and testing it is not practical */
+ if (!ret)
+todo_wine
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ret = GetLastError();
+ ok(bytes == 0, "bytes %u\n", bytes);
- SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
+ if (ret == ERROR_IO_PENDING)
+ {
+ bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
+ ok(ret, "GetOverlappedResult should report TRUE\n");
+ ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+ ok(bytes == 0, "expected 0, read %u\n", bytes);
+ ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
+ ok(ovl.InternalHigh == 0, "expected 0, got %lu\n", ovl.InternalHigh);
+ }
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = sizeof(contents);
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
+ if (status == STATUS_PENDING)
+ {
+ ret = WaitForSingleObject(hfile, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ ok(U(iob).Status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ }
+ else
+ {
+ ok(status == STATUS_END_OF_FILE, "expected STATUS_END_OF_FILE, got %#x\n", status);
+ ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+ ok(iob.Information == -1, "expected -1, got %lu\n", iob.Information);
+ }
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
+ U(iob).Status = -1;
+ iob.Information = -1;
+ offset.QuadPart = sizeof(contents);
+ status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
+ if (status == STATUS_PENDING)
+ {
+ ret = WaitForSingleObject(hfile, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ }
+ else
+ {
+ ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+ ok(iob.Information == 0, "expected 0, got %lu\n", iob.Information);
+ }
+
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
- ok(!ret, "ReadFile should fail\n");
- ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
- ok(bytes == 0, "bytes %u\n", bytes);
+ /* ReadFile return value depends on Windows version and testing it is not practical */
+ if (!ret)
+ {
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+ }
+ else ok(bytes == 14, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
ok(!memcmp(contents, buf, sizeof(contents)), "file contents mismatch\n");
- iob.Status = -1;
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
+ SetFilePointer(hfile, sizeof(contents) - 4, NULL, FILE_BEGIN);
+ SetEndOfFile(hfile);
+ SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
+
+ U(iob).Status = -1;
iob.Information = -1;
- offset.QuadPart = sizeof(contents) - 4;
+ offset.QuadPart = (LONGLONG)-1 /* FILE_WRITE_TO_END_OF_FILE */;
status = pNtWriteFile(hfile, 0, NULL, NULL, &iob, "DCBA", 4, &offset, NULL);
- ok(status == STATUS_PENDING || broken(status == STATUS_SUCCESS) /* before Vista */, "expected STATUS_PENDING, got %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(status == STATUS_PENDING || status == STATUS_SUCCESS /* before Vista */, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
+ if (status == STATUS_PENDING)
+ {
+ ret = WaitForSingleObject(hfile, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ }
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == 4, "expected 4, got %lu\n", iob.Information);
- ret = WaitForSingleObject(hfile, 3000);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
- iob.Status = -1;
+ U(iob).Status = -1;
iob.Information = -1;
offset.QuadPart = 0;
status = pNtReadFile(hfile, 0, NULL, NULL, &iob, buf, sizeof(buf), &offset, NULL);
- ok(status == STATUS_PENDING, "expected STATUS_PENDING, got %#x\n", status);
- ok(iob.Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", iob.Status);
+ ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
+ if (status == STATUS_PENDING)
+ {
+ ret = WaitForSingleObject(hfile, 3000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ }
+ ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
ok(iob.Information == sizeof(contents), "expected sizeof(contents), got %lu\n", iob.Information);
- ret = WaitForSingleObject(hfile, 3000);
- ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "DCBA", 4), "file contents mismatch\n");
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
S(U(ovl)).Offset = sizeof(contents) - 4;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
bytes = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, "ABCD", 4, &bytes, &ovl);
- ok(!ret || broken(ret) /* before Vista */, "WriteFile should fail\n");
- ok(GetLastError() == ERROR_IO_PENDING || broken(GetLastError() == 0xdeadbeef) /* before Vista */, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
- ok(bytes == 0 || broken(bytes == 4) /* before Vista */, "bytes %u\n", bytes);
+ /* WriteFile return value depends on Windows version and testing it is not practical */
+ if (!ret)
+ {
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+ }
+ else ok(bytes == 4, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == 4, "expected 4, got %lu\n", ovl.InternalHigh);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
S(U(ovl)).Offset = 0;
S(U(ovl)).OffsetHigh = 0;
ovl.Internal = -1;
bytes = 0;
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buf, sizeof(buf), &bytes, &ovl);
- ok(!ret, "ReadFile should fail\n");
- ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
- ok(bytes == 0, "bytes %u\n", bytes);
+ /* ReadFile return value depends on Windows version and testing it is not practical */
+ if (!ret)
+ {
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ok(bytes == 0, "bytes %u\n", bytes);
+ }
+ else ok(bytes == 14, "bytes %u\n", bytes);
ok((NTSTATUS)ovl.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", ovl.Internal);
ok(ovl.InternalHigh == sizeof(contents), "expected sizeof(contents), got %lu\n", ovl.InternalHigh);
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
bytes = 0xdeadbeef;
ret = GetOverlappedResult(hfile, &ovl, &bytes, TRUE);
ok(ret, "GetOverlappedResult error %d\n", GetLastError());
ok(!memcmp(contents, buf, sizeof(contents) - 4), "file contents mismatch\n");
ok(!memcmp(buf + sizeof(contents) - 4, "ABCD", 4), "file contents mismatch\n");
+ off = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
+ ok(off == 0, "expected 0, got %u\n", off);
+
CloseHandle(hfile);
}
TEST_TARGET_ALIGN(PCSTR, 1)
}
-static void test_pack_PCTSTR(void)
-{
- /* PCTSTR */
- TEST_TYPE_SIZE (PCTSTR, 8)
- TEST_TYPE_ALIGN (PCTSTR, 8)
-}
-
static void test_pack_PCWCH(void)
{
/* PCWCH */
TEST_TARGET_ALIGN(PTOKEN_USER, 8)
}
-static void test_pack_PTSTR(void)
-{
- /* PTSTR */
- TEST_TYPE_SIZE (PTSTR, 8)
- TEST_TYPE_ALIGN (PTSTR, 8)
-}
-
static void test_pack_PULARGE_INTEGER(void)
{
/* PULARGE_INTEGER */
TEST_FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart, 8)
}
-static void test_pack_TCHAR(void)
-{
- /* TCHAR */
- TEST_TYPE_SIZE (TCHAR, 1)
- TEST_TYPE_ALIGN (TCHAR, 1)
-}
-
static void test_pack_TOKEN_DEFAULT_DACL(void)
{
/* TOKEN_DEFAULT_DACL */
TEST_TARGET_ALIGN(PCSTR, 1)
}
-static void test_pack_PCTSTR(void)
-{
- /* PCTSTR */
- TEST_TYPE_SIZE (PCTSTR, 4)
- TEST_TYPE_ALIGN (PCTSTR, 4)
-}
-
static void test_pack_PCWCH(void)
{
/* PCWCH */
TEST_TARGET_ALIGN(PTOKEN_USER, 4)
}
-static void test_pack_PTSTR(void)
-{
- /* PTSTR */
- TEST_TYPE_SIZE (PTSTR, 4)
- TEST_TYPE_ALIGN (PTSTR, 4)
-}
-
static void test_pack_PULARGE_INTEGER(void)
{
/* PULARGE_INTEGER */
TEST_FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart, 8)
}
-static void test_pack_TCHAR(void)
-{
- /* TCHAR */
- TEST_TYPE_SIZE (TCHAR, 1)
- TEST_TYPE_ALIGN (TCHAR, 1)
-}
-
static void test_pack_TOKEN_DEFAULT_DACL(void)
{
/* TOKEN_DEFAULT_DACL */
test_pack_PCCH();
test_pack_PCH();
test_pack_PCSTR();
- test_pack_PCTSTR();
test_pack_PCWCH();
test_pack_PCWSTR();
test_pack_PEXCEPTION_POINTERS();
test_pack_PTOKEN_GROUPS();
test_pack_PTOKEN_PRIVILEGES();
test_pack_PTOKEN_USER();
- test_pack_PTSTR();
test_pack_PULARGE_INTEGER();
test_pack_PVECTORED_EXCEPTION_HANDLER();
test_pack_PVOID();
test_pack_SSIZE_T();
test_pack_SYSTEM_ALARM_ACE();
test_pack_SYSTEM_AUDIT_ACE();
- test_pack_TCHAR();
test_pack_TOKEN_DEFAULT_DACL();
test_pack_TOKEN_GROUPS();
test_pack_TOKEN_OWNER();
static BOOL InitFunctionPtrs(void)
{
/* All needed functions are NT based, so using GetModuleHandle is a good check */
- HMODULE hntdll = GetModuleHandle("ntdll");
+ HMODULE hntdll = GetModuleHandleA("ntdll");
if (!hntdll)
{
win_skip("Not running on NT\n");
/* not present before XP */
pNtGetCurrentProcessorNumber = (void *) GetProcAddress(hntdll, "NtGetCurrentProcessorNumber");
- pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
+ pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
return TRUE;
}
ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER /* vista */,
"Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status);
- /* Use a existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
+ /* Use an existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
trace("Check no ReturnLength pointer\n");
status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
DWORD last_pid;
ULONG ReturnLength;
int i = 0, k = 0;
- int is_nt = 0;
+ BOOL is_nt = FALSE;
SYSTEM_BASIC_INFORMATION sbi;
/* Copy of our winternl.h structure turned into a private one */
DWORD_PTR debug_port = 0xdeadbeef;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
- STARTUPINFO si = { 0 };
+ STARTUPINFOA si = { 0 };
NTSTATUS status;
BOOL ret;
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
si.cb = sizeof(si);
- ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
if (!ret) return;
static void test_query_process_debug_object_handle(int argc, char **argv)
{
char cmdline[MAX_PATH];
- STARTUPINFO si = {0};
+ STARTUPINFOA si = {0};
PROCESS_INFORMATION pi;
BOOL ret;
HANDLE debug_object;
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
si.cb = sizeof(si);
- ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL,
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL,
NULL, &si, &pi);
ok(ret, "CreateProcess failed with last error %u\n", GetLastError());
if (!ret) return;
DWORD debug_flags = 0xdeadbeef;
char cmdline[MAX_PATH];
PROCESS_INFORMATION pi;
- STARTUPINFO si = { 0 };
+ STARTUPINFOA si = { 0 };
NTSTATUS status;
BOOL ret;
sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
si.cb = sizeof(si);
- ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
+ ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
if (!ret) return;
addr = NULL;
status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+
#if defined(__x86_64__) || defined(__i386__)
- memset (addr, 0xc3, 1); /* lret ... in both i386 and x86_64 */
+ *(unsigned char*)addr = 0xc3; /* lret ... in both i386 and x86_64 */
+#elif defined(__arm__)
+ *(unsigned long*)addr = 0xe12fff1e; /* bx lr */
+#else
+ ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
+#endif
trace("trying to execute code in the readwrite only mapped anon file...\n");
f = addr;f();
trace("...done.\n");
-#endif
status = pNtQueryVirtualMemory( GetCurrentProcess(), addr, MemoryBasicInformation, &info, sizeof(info), &retlen );
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
char stackbuf[42];
HMODULE module;
- module = GetModuleHandle( "ntdll.dll" );
+ module = GetModuleHandleA( "ntdll.dll" );
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok (mbi.Type == MEM_IMAGE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_IMAGE);
trace("Check flags of a function entry in NTDLL.DLL at %p\n", pNtQueryVirtualMemory);
- module = GetModuleHandle( "ntdll.dll" );
+ module = GetModuleHandleA( "ntdll.dll" );
status = pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READWRITE);
trace("Check flags of read-only data at %p\n", teststring);
- module = GetModuleHandle( NULL );
+ module = GetModuleHandleA( NULL );
status = pNtQueryVirtualMemory(NtCurrentProcess(), teststring, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
GetSystemInfo(&si);
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
- proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
+ proc_affinity = pbi.AffinityMask;
ok( proc_affinity == (1 << si.dwNumberOfProcessors) - 1, "Unexpected process affinity\n" );
proc_affinity = 1 << si.dwNumberOfProcessors;
status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
- proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
+ proc_affinity = pbi.AffinityMask;
ok( proc_affinity == 2, "Unexpected process affinity\n" );
/* Setting the process affinity changes the thread affinity to match */
status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
trace("dwNumberOfProcessors: %d, current processor: %d\n", si.dwNumberOfProcessors, current_cpu);
status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
- old_process_mask = (DWORD_PTR)pbi.Reserved2[0];
+ old_process_mask = pbi.AffinityMask;
ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
status = pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
trace("Starting test_process_debug_flags()\n");
test_query_process_debug_flags(argc, argv);
- /* belongs into it's own file */
+ /* belongs to its own file */
trace("Starting test_readvirtualmemory()\n");
test_readvirtualmemory();
#include "stdlib.h"
static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*, BOOL, LPCSTR);
-static NTSTATUS (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
+static BOOLEAN (WINAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN, BOOLEAN);
static DWORD (WINAPI *pRtlGetFullPathName_U)(const WCHAR*,ULONG,WCHAR*,WCHAR**);
-static void test_RtlDetermineDosPathNameType(void)
+static void test_RtlDetermineDosPathNameType_U(void)
{
struct test
{
WCHAR buffer[MAX_PATH];
UINT ret;
+ if (!pRtlDetermineDosPathNameType_U)
+ {
+ win_skip("RtlDetermineDosPathNameType_U is not available\n");
+ return;
+ }
+
for (test = tests; test->path; test++)
{
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
}
-static void test_RtlIsDosDeviceName(void)
+static void test_RtlIsDosDeviceName_U(void)
{
struct test
{
static const struct test tests[] =
{
- { "\\\\.\\CON", 8, 6 },
- { "\\\\.\\con", 8, 6 },
+ { "\\\\.\\CON", 8, 6, TRUE }, /* fails on win8 */
+ { "\\\\.\\con", 8, 6, TRUE }, /* fails on win8 */
{ "\\\\.\\CON2", 0, 0 },
{ "", 0, 0 },
{ "\\\\foo\\nul", 0, 0 },
WCHAR buffer[2000];
ULONG ret;
+ if (!pRtlIsDosDeviceName_U)
+ {
+ win_skip("RtlIsDosDeviceName_U is not available\n");
+ return;
+ }
+
for (test = tests; test->path; test++)
{
pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 );
char buff2[12];
BOOLEAN ret, spaces;
+ if (!pRtlIsNameLegalDOS8Dot3)
+ {
+ win_skip("RtlIsNameLegalDOS8Dot3 is not available\n");
+ return;
+ }
+
ustr.MaximumLength = sizeof(buffer);
ustr.Buffer = buffer;
for (test = tests; test->path; test++)
DWORD reslen;
UINT len;
+ if (!pRtlGetFullPathName_U)
+ {
+ win_skip("RtlGetFullPathName_U is not available\n");
+ return;
+ }
+
file_part = (WCHAR *)0xdeadbeef;
lstrcpyW(rbufferW, deadbeefW);
ret = pRtlGetFullPathName_U(NULL, MAX_PATH, rbufferW, &file_part);
pRtlOemStringToUnicodeString = (void *)GetProcAddress(mod,"RtlOemStringToUnicodeString");
pRtlIsNameLegalDOS8Dot3 = (void *)GetProcAddress(mod,"RtlIsNameLegalDOS8Dot3");
pRtlGetFullPathName_U = (void *)GetProcAddress(mod,"RtlGetFullPathName_U");
- if (pRtlDetermineDosPathNameType_U)
- test_RtlDetermineDosPathNameType();
- if (pRtlIsDosDeviceName_U)
- test_RtlIsDosDeviceName();
- if (pRtlIsNameLegalDOS8Dot3)
- test_RtlIsNameLegalDOS8Dot3();
- if (pRtlGetFullPathName_U && pRtlMultiByteToUnicodeN)
- test_RtlGetFullPathName_U();
+
+ test_RtlDetermineDosPathNameType_U();
+ test_RtlIsDosDeviceName_U();
+ test_RtlIsNameLegalDOS8Dot3();
+ test_RtlGetFullPathName_U();
}
static BOOL init_func_ptrs(void)
{
- HMODULE module = GetModuleHandle("ntdll.dll");
+ HMODULE module = GetModuleHandleA("ntdll.dll");
#define loadfunc(name) if (!(p##name = (void *)GetProcAddress(module, #name))) { \
trace("GetProcAddress(%s) failed\n", #name); \
loadfunc(RtlInitUnicodeString)
/* not fatal */
- module = GetModuleHandle("kernel32.dll");
+ module = GetModuleHandleA("kernel32.dll");
pOpenThread = (void *)GetProcAddress(module, "OpenThread");
pQueueUserAPC = (void *)GetProcAddress(module, "QueueUserAPC");
return TRUE;
return FALSE;
}
- pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
+ pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
return TRUE;
}
{
ok(LpcMessage->msg64.MessageType == LPC_REQUEST,
"Expected LPC_REQUEST, got %d\n", LpcMessage->msg64.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg64.Data, REQUEST2),
+ ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST2),
"Expected %s, got %s\n", REQUEST2, LpcMessage->msg64.Data);
- lstrcpy((LPSTR)LpcMessage->msg64.Data, REPLY);
+ strcpy((LPSTR)LpcMessage->msg64.Data, REPLY);
status = pNtReplyPort(PortHandle, &LpcMessage->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
ok(LpcMessage->msg64.MessageType == LPC_REQUEST,
"Expected LPC_REQUEST, got %d\n", LpcMessage->msg64.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg64.Data, REPLY),
+ ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REPLY),
"Expected %s, got %s\n", REPLY, LpcMessage->msg64.Data);
}
else
{
ok(LpcMessage->msg.MessageType == LPC_REQUEST,
"Expected LPC_REQUEST, got %d\n", LpcMessage->msg.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg.Data, REQUEST2),
+ ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST2),
"Expected %s, got %s\n", REQUEST2, LpcMessage->msg.Data);
- lstrcpy((LPSTR)LpcMessage->msg.Data, REPLY);
+ strcpy((LPSTR)LpcMessage->msg.Data, REPLY);
status = pNtReplyPort(PortHandle, &LpcMessage->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
ok(LpcMessage->msg.MessageType == LPC_REQUEST,
"Expected LPC_REQUEST, got %d\n", LpcMessage->msg.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg.Data, REPLY),
+ ok(!strcmp((LPSTR)LpcMessage->msg.Data, REPLY),
"Expected %s, got %s\n", REPLY, LpcMessage->msg.Data);
}
}
LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
out = HeapAlloc(GetProcessHeap(), 0, size);
- LpcMessage->msg64.DataSize = lstrlen(REQUEST1) + 1;
+ LpcMessage->msg64.DataSize = strlen(REQUEST1) + 1;
LpcMessage->msg64.MessageSize = FIELD_OFFSET(LPC_MESSAGE64, Data[LpcMessage->msg64.DataSize]);
- lstrcpy((LPSTR)LpcMessage->msg64.Data, REQUEST1);
+ strcpy((LPSTR)LpcMessage->msg64.Data, REQUEST1);
status = pNtRequestPort(PortHandle, &LpcMessage->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
ok(LpcMessage->msg64.MessageType == 0, "Expected 0, got %d\n", LpcMessage->msg64.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
+ ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
"Expected %s, got %s\n", REQUEST1, LpcMessage->msg64.Data);
/* Fill in the message */
memset(LpcMessage, 0, size);
- LpcMessage->msg64.DataSize = lstrlen(REQUEST2) + 1;
+ LpcMessage->msg64.DataSize = strlen(REQUEST2) + 1;
LpcMessage->msg64.MessageSize = FIELD_OFFSET(LPC_MESSAGE64, Data[LpcMessage->msg64.DataSize]);
- lstrcpy((LPSTR)LpcMessage->msg64.Data, REQUEST2);
+ strcpy((LPSTR)LpcMessage->msg64.Data, REQUEST2);
/* Send the message and wait for the reply */
status = pNtRequestWaitReplyPort(PortHandle, &LpcMessage->msg, &out->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
- ok(!lstrcmp((LPSTR)out->msg64.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg64.Data);
+ ok(!strcmp((LPSTR)out->msg64.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg64.Data);
ok(out->msg64.MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->msg64.MessageType);
}
else
LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
out = HeapAlloc(GetProcessHeap(), 0, size);
- LpcMessage->msg.DataSize = lstrlen(REQUEST1) + 1;
+ LpcMessage->msg.DataSize = strlen(REQUEST1) + 1;
LpcMessage->msg.MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data[LpcMessage->msg.DataSize]);
- lstrcpy((LPSTR)LpcMessage->msg.Data, REQUEST1);
+ strcpy((LPSTR)LpcMessage->msg.Data, REQUEST1);
status = pNtRequestPort(PortHandle, &LpcMessage->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
ok(LpcMessage->msg.MessageType == 0, "Expected 0, got %d\n", LpcMessage->msg.MessageType);
- ok(!lstrcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
+ ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
"Expected %s, got %s\n", REQUEST1, LpcMessage->msg.Data);
/* Fill in the message */
memset(LpcMessage, 0, size);
- LpcMessage->msg.DataSize = lstrlen(REQUEST2) + 1;
+ LpcMessage->msg.DataSize = strlen(REQUEST2) + 1;
LpcMessage->msg.MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data[LpcMessage->msg.DataSize]);
- lstrcpy((LPSTR)LpcMessage->msg.Data, REQUEST2);
+ strcpy((LPSTR)LpcMessage->msg.Data, REQUEST2);
/* Send the message and wait for the reply */
status = pNtRequestWaitReplyPort(PortHandle, &LpcMessage->msg, &out->msg);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
- ok(!lstrcmp((LPSTR)out->msg.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg.Data);
+ ok(!strcmp((LPSTR)out->msg.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg.Data);
ok(out->msg.MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->msg.MessageType);
}
case LPC_DATAGRAM:
if (is_wow64)
- ok(!lstrcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
+ ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
"Expected %s, got %s\n", REQUEST1, LpcMessage->msg64.Data);
else
- ok(!lstrcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
+ ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
"Expected %s, got %s\n", REQUEST1, LpcMessage->msg.Data);
break;
#endif
-static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
+static BOOLEAN (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
static void (WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR);
static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
ULONG, const void*, ULONG );
static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
-static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
+static BOOLEAN (WINAPI * pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR);
static LPVOID (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
+static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
static HMODULE hkernel32 = 0;
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressA");
+ pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
}
hkernel32 = LoadLibraryA("kernel32.dll");
ok(hkernel32 != 0, "LoadLibrary failed\n");
}
}
+static void test_LdrAddRefDll(void)
+{
+ HMODULE mod, mod2;
+ NTSTATUS status;
+ BOOL ret;
+
+ if (!pLdrAddRefDll)
+ {
+ win_skip( "LdrAddRefDll not supported\n" );
+ return;
+ }
+
+ mod = LoadLibraryA("comctl32.dll");
+ ok(mod != NULL, "got %p\n", mod);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+
+ mod2 = GetModuleHandleA("comctl32.dll");
+ ok(mod2 == NULL, "got %p\n", mod2);
+
+ /* load, addref and release 2 times */
+ mod = LoadLibraryA("comctl32.dll");
+ ok(mod != NULL, "got %p\n", mod);
+ status = pLdrAddRefDll(0, mod);
+ ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+
+ mod2 = GetModuleHandleA("comctl32.dll");
+ ok(mod2 != NULL, "got %p\n", mod2);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+
+ mod2 = GetModuleHandleA("comctl32.dll");
+ ok(mod2 == NULL, "got %p\n", mod2);
+
+ /* pin refcount */
+ mod = LoadLibraryA("comctl32.dll");
+ ok(mod != NULL, "got %p\n", mod);
+ status = pLdrAddRefDll(LDR_ADDREF_DLL_PIN, mod);
+ ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
+
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+ ret = FreeLibrary(mod);
+ ok(ret, "got %d\n", ret);
+
+ mod2 = GetModuleHandleA("comctl32.dll");
+ ok(mod2 != NULL, "got %p\n", mod2);
+}
+
START_TEST(rtl)
{
InitFunctionPtrs();
test_RtlIpv4AddressToString();
test_RtlIpv4AddressToStringEx();
test_RtlIpv4StringToAddress();
+ test_LdrAddRefDll();
}
static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
static NTSTATUS (WINAPI *pRtlHashUnicodeString)(PCUNICODE_STRING,BOOLEAN,ULONG,ULONG*);
+static NTSTATUS (WINAPI *pRtlUnicodeToUTF8N)(CHAR *, ULONG, ULONG *, const WCHAR *, ULONG);
+static NTSTATUS (WINAPI *pRtlUTF8ToUnicodeN)(WCHAR *, ULONG, ULONG *, const CHAR *, ULONG);
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
/*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/
pRtlStringFromGUID = (void *)GetProcAddress(hntdll, "RtlStringFromGUID");
pRtlIsTextUnicode = (void *)GetProcAddress(hntdll, "RtlIsTextUnicode");
pRtlHashUnicodeString = (void*)GetProcAddress(hntdll, "RtlHashUnicodeString");
+ pRtlUnicodeToUTF8N = (void*)GetProcAddress(hntdll, "RtlUnicodeToUTF8N");
+ pRtlUTF8ToUnicodeN = (void*)GetProcAddress(hntdll, "RtlUTF8ToUnicodeN");
}
}
}
}
+struct unicode_to_utf8_test {
+ WCHAR unicode[128];
+ const char *expected;
+ NTSTATUS status;
+};
+
+static const struct unicode_to_utf8_test unicode_to_utf8[] = {
+ { { 0 }, "", STATUS_SUCCESS },
+ { { '-',0 }, "-", STATUS_SUCCESS },
+ { { 'h','e','l','l','o',0 }, "hello", STATUS_SUCCESS },
+ { { '-',0x7f,'-',0x80,'-',0xff,'-',0x100,'-',0 }, "-\x7F-\xC2\x80-\xC3\xBF-\xC4\x80-", STATUS_SUCCESS },
+ { { '-',0x7ff,'-',0x800,'-',0 }, "-\xDF\xBF-\xE0\xA0\x80-", STATUS_SUCCESS },
+ { { '-',0xd7ff,'-',0xe000,'-',0 }, "-\xED\x9F\xBF-\xEE\x80\x80-", STATUS_SUCCESS },
+ /* 0x10000 */
+ { { '-',0xffff,'-',0xd800,0xdc00,'-',0 }, "-\xEF\xBF\xBF-\xF0\x90\x80\x80-", STATUS_SUCCESS },
+ /* 0x103ff */ /* 0x10400 */
+ { { '-',0xd800,0xdfff,'-',0xd801,0xdc00,'-',0 }, "-\xF0\x90\x8F\xBF-\xF0\x90\x90\x80-", STATUS_SUCCESS },
+ /* 0x10ffff */
+ { { '-',0xdbff,0xdfff,'-',0 }, "-\xF4\x8F\xBF\xBF-", STATUS_SUCCESS },
+ /* standalone lead surrogates become 0xFFFD */
+ { { '-',0xd800,'-',0xdbff,'-',0 }, "-\xEF\xBF\xBD-\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
+ /* standalone trail surrogates become 0xFFFD */
+ { { '-',0xdc00,'-',0xdfff,'-',0 }, "-\xEF\xBF\xBD-\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
+ /* reverse surrogate pair */
+ { { '-',0xdfff,0xdbff,'-',0 }, "-\xEF\xBF\xBD\xEF\xBF\xBD-", STATUS_SOME_NOT_MAPPED },
+ /* byte order marks */
+ { { '-',0xfeff,'-',0xfffe,'-',0 }, "-\xEF\xBB\xBF-\xEF\xBF\xBE-", STATUS_SUCCESS },
+ { { 0xfeff,'-',0 }, "\xEF\xBB\xBF-", STATUS_SUCCESS },
+ { { 0xfffe,'-',0 }, "\xEF\xBF\xBE-", STATUS_SUCCESS },
+ /* invalid code point */
+ { { 0xffff,'-',0 }, "\xEF\xBF\xBF-", STATUS_SUCCESS },
+ /* canonically equivalent representations -- no normalization should happen */
+ { { '-',0x1e09,'-',0 }, "-\xE1\xB8\x89-", STATUS_SUCCESS },
+ { { '-',0x0107,0x0327,'-',0 }, "-\xC4\x87\xCC\xA7-", STATUS_SUCCESS },
+ { { '-',0x00e7,0x0301,'-',0 }, "-\xC3\xA7\xCC\x81-", STATUS_SUCCESS },
+ { { '-',0x0063,0x0327,0x0301,'-',0 }, "-\x63\xCC\xA7\xCC\x81-", STATUS_SUCCESS },
+ { { '-',0x0063,0x0301,0x0327,'-',0 }, "-\x63\xCC\x81\xCC\xA7-", STATUS_SUCCESS },
+};
+
+static void utf8_expect_(const unsigned char *out_string, ULONG buflen, ULONG out_bytes,
+ const WCHAR *in_string, ULONG in_bytes,
+ NTSTATUS expect_status, int line)
+{
+ NTSTATUS status;
+ ULONG bytes_out;
+ char buffer[128];
+ unsigned char *buf = (unsigned char *)buffer;
+ unsigned int i;
+
+ if (buflen == (ULONG)-1)
+ buflen = sizeof(buffer);
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUnicodeToUTF8N(
+ out_string ? buffer : NULL, buflen, &bytes_out,
+ in_string, in_bytes);
+ ok_(__FILE__, line)(status == expect_status, "status = 0x%x\n", status);
+ ok_(__FILE__, line)(bytes_out == out_bytes, "bytes_out = %u\n", bytes_out);
+ if (out_string)
+ {
+ for (i = 0; i < bytes_out; i++)
+ ok_(__FILE__, line)(buf[i] == out_string[i],
+ "buffer[%d] = 0x%x, expected 0x%x\n",
+ i, buf[i], out_string[i]);
+ for (; i < sizeof(buffer); i++)
+ ok_(__FILE__, line)(buf[i] == 0x55,
+ "buffer[%d] = 0x%x, expected 0x55\n",
+ i, buf[i]);
+ }
+}
+#define utf8_expect(out_string, buflen, out_bytes, in_string, in_bytes, expect_status) \
+ utf8_expect_(out_string, buflen, out_bytes, in_string, in_bytes, expect_status, __LINE__)
+
+static void test_RtlUnicodeToUTF8N(void)
+{
+ NTSTATUS status;
+ ULONG bytes_out;
+ ULONG bytes_out_array[2];
+ void * const invalid_pointer = (void *)0x8;
+ char buffer[128];
+ const WCHAR empty_string[] = { 0 };
+ const WCHAR test_string[] = { 'A',0,'a','b','c','d','e','f','g',0 };
+ const WCHAR special_string[] = { 'X',0x80,0xd800,0 };
+ const unsigned char special_expected[] = { 'X',0xc2,0x80,0xef,0xbf,0xbd,0 };
+ unsigned int input_len;
+ const unsigned int test_count = sizeof(unicode_to_utf8) / sizeof(unicode_to_utf8[0]);
+ unsigned int i;
+
+ if (!pRtlUnicodeToUTF8N)
+ {
+ skip("RtlUnicodeToUTF8N unavailable\n");
+ return;
+ }
+
+ /* show that bytes_out is really ULONG */
+ memset(bytes_out_array, 0x55, sizeof(bytes_out_array));
+ status = pRtlUnicodeToUTF8N(NULL, 0, bytes_out_array, empty_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out_array[0] == 0x00000000, "Got 0x%x\n", bytes_out_array[0]);
+ ok(bytes_out_array[1] == 0x55555555, "Got 0x%x\n", bytes_out_array[1]);
+
+ /* parameter checks */
+ status = pRtlUnicodeToUTF8N(NULL, 0, NULL, NULL, 0);
+ ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
+
+ status = pRtlUnicodeToUTF8N(NULL, 0, NULL, empty_string, 0);
+ ok(status == STATUS_INVALID_PARAMETER, "status = 0x%x\n", status);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, NULL, 0);
+ ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
+ ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, invalid_pointer, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, empty_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, test_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(NULL, 0, &bytes_out, empty_string, 1);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(invalid_pointer, 0, &bytes_out, empty_string, 1);
+ ok(status == STATUS_INVALID_PARAMETER_5, "status = 0x%x\n", status);
+ ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUnicodeToUTF8N(invalid_pointer, 8, &bytes_out, empty_string, 1);
+ ok(status == STATUS_INVALID_PARAMETER_5, "status = 0x%x\n", status);
+ ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
+
+ /* length output with special chars */
+#define length_expect(in_chars, out_bytes, expect_status) \
+ utf8_expect_(NULL, 0, out_bytes, \
+ special_string, in_chars * sizeof(WCHAR), \
+ expect_status, __LINE__)
+
+ length_expect(0, 0, STATUS_SUCCESS);
+ length_expect(1, 1, STATUS_SUCCESS);
+ length_expect(2, 3, STATUS_SUCCESS);
+ length_expect(3, 6, STATUS_SOME_NOT_MAPPED);
+ length_expect(4, 7, STATUS_SOME_NOT_MAPPED);
+#undef length_expect
+
+ /* output truncation */
+#define truncate_expect(buflen, out_bytes, expect_status) \
+ utf8_expect_(special_expected, buflen, out_bytes, \
+ special_string, sizeof(special_string), \
+ expect_status, __LINE__)
+
+ truncate_expect(0, 0, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(1, 1, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(2, 1, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(3, 3, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(4, 3, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(5, 3, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(6, 6, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(7, 7, STATUS_SOME_NOT_MAPPED);
+#undef truncate_expect
+
+ /* conversion behavior with varying input length */
+ for (input_len = 0; input_len <= sizeof(test_string); input_len++) {
+ /* no output buffer, just length */
+ utf8_expect(NULL, 0, input_len / sizeof(WCHAR),
+ test_string, input_len, STATUS_SUCCESS);
+
+ /* write output */
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUnicodeToUTF8N(
+ buffer, sizeof(buffer), &bytes_out,
+ test_string, input_len);
+ if (input_len % sizeof(WCHAR) == 0) {
+ ok(status == STATUS_SUCCESS,
+ "(len %u): status = 0x%x\n", input_len, status);
+ ok(bytes_out == input_len / sizeof(WCHAR),
+ "(len %u): bytes_out = 0x%x\n", input_len, bytes_out);
+ for (i = 0; i < bytes_out; i++) {
+ ok(buffer[i] == test_string[i],
+ "(len %u): buffer[%d] = 0x%x, expected 0x%x\n",
+ input_len, i, buffer[i], test_string[i]);
+ }
+ for (; i < sizeof(buffer); i++) {
+ ok(buffer[i] == 0x55,
+ "(len %u): buffer[%d] = 0x%x\n", input_len, i, buffer[i]);
+ }
+ } else {
+ ok(status == STATUS_INVALID_PARAMETER_5,
+ "(len %u): status = 0x%x\n", input_len, status);
+ ok(bytes_out == 0x55555555,
+ "(len %u): bytes_out = 0x%x\n", input_len, bytes_out);
+ for (i = 0; i < sizeof(buffer); i++) {
+ ok(buffer[i] == 0x55,
+ "(len %u): buffer[%d] = 0x%x\n", input_len, i, buffer[i]);
+ }
+ }
+ }
+
+ /* test cases for special characters */
+ for (i = 0; i < test_count; i++) {
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUnicodeToUTF8N(
+ buffer, sizeof(buffer), &bytes_out,
+ unicode_to_utf8[i].unicode, lstrlenW(unicode_to_utf8[i].unicode) * sizeof(WCHAR));
+ ok(status == unicode_to_utf8[i].status,
+ "(test %d): status is 0x%x, expected 0x%x\n",
+ i, status, unicode_to_utf8[i].status);
+ ok(bytes_out == strlen(unicode_to_utf8[i].expected),
+ "(test %d): bytes_out is %u, expected %u\n",
+ i, bytes_out, lstrlenA(unicode_to_utf8[i].expected));
+ ok(!memcmp(buffer, unicode_to_utf8[i].expected, bytes_out),
+ "(test %d): got \"%.*s\", expected \"%s\"\n",
+ i, bytes_out, buffer, unicode_to_utf8[i].expected);
+ ok(buffer[bytes_out] == 0x55,
+ "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
+
+ /* same test but include the null terminator */
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUnicodeToUTF8N(
+ buffer, sizeof(buffer), &bytes_out,
+ unicode_to_utf8[i].unicode, (lstrlenW(unicode_to_utf8[i].unicode) + 1) * sizeof(WCHAR));
+ ok(status == unicode_to_utf8[i].status,
+ "(test %d): status is 0x%x, expected 0x%x\n",
+ i, status, unicode_to_utf8[i].status);
+ ok(bytes_out == strlen(unicode_to_utf8[i].expected) + 1,
+ "(test %d): bytes_out is %u, expected %u\n",
+ i, bytes_out, lstrlenA(unicode_to_utf8[i].expected) + 1);
+ ok(!memcmp(buffer, unicode_to_utf8[i].expected, bytes_out),
+ "(test %d): got \"%.*s\", expected \"%s\"\n",
+ i, bytes_out, buffer, unicode_to_utf8[i].expected);
+ ok(buffer[bytes_out] == 0x55,
+ "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
+ }
+}
+
+struct utf8_to_unicode_test {
+ const char *utf8;
+ WCHAR expected[128];
+ NTSTATUS status;
+};
+
+static const struct utf8_to_unicode_test utf8_to_unicode[] = {
+ { "", { 0 }, STATUS_SUCCESS },
+ { "-", { '-',0 }, STATUS_SUCCESS },
+ { "hello", { 'h','e','l','l','o',0 }, STATUS_SUCCESS },
+ /* first and last of each range */
+ { "-\x7F-\xC2\x80-\xC3\xBF-\xC4\x80-", { '-',0x7f,'-',0x80,'-',0xff,'-',0x100,'-',0 }, STATUS_SUCCESS },
+ { "-\xDF\xBF-\xE0\xA0\x80-", { '-',0x7ff,'-',0x800,'-',0 }, STATUS_SUCCESS },
+ { "-\xED\x9F\xBF-\xEE\x80\x80-", { '-',0xd7ff,'-',0xe000,'-',0 }, STATUS_SUCCESS },
+ /* 0x10000 */
+ { "-\xEF\xBF\xBF-\xF0\x90\x80\x80-", { '-',0xffff,'-',0xd800,0xdc00,'-',0 }, STATUS_SUCCESS },
+ /* 0x103ff */ /* 0x10400 */
+ { "-\xF0\x90\x8F\xBF-\xF0\x90\x90\x80-", { '-',0xd800,0xdfff,'-',0xd801,0xdc00,'-',0 }, STATUS_SUCCESS },
+ /* 0x10ffff */
+ { "-\xF4\x8F\xBF\xBF-", { '-',0xdbff,0xdfff,'-',0 }, STATUS_SUCCESS },
+ /* standalone surrogate code points */
+ /* 0xd800 */ /* 0xdbff */
+ { "-\xED\xA0\x80-\xED\xAF\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0xdc00 */ /* 0xdfff */
+ { "-\xED\xB0\x80-\xED\xBF\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* UTF-8 encoded surrogate pair */
+ /* 0xdbff *//* 0xdfff */
+ { "-\xED\xAF\xBF\xED\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* reverse surrogate pair */
+ /* 0xdfff *//* 0xdbff */
+ { "-\xED\xBF\xBF\xED\xAF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* code points outside the UTF-16 range */
+ /* 0x110000 */
+ { "-\xF4\x90\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0x1fffff */
+ { "-\xF7\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0x200000 */
+ { "-\xFA\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0x3ffffff */
+ { "-\xFB\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0x4000000 */
+ { "-\xFC\x84\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* 0x7fffffff */
+ { "-\xFD\xBF\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* overlong encodings of each length for -, NUL, and the highest possible value */
+ { "-\xC0\xAD-\xC0\x80-\xC1\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xE0\x80\xAD-\xE0\x80\x80-\xE0\x9F\xBF-", { '-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF0\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF0\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF0\x8F\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF8\x80\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF8\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xF8\x87\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xFC\x80\x80\x80\x80\xAD-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xFC\x80\x80\x80\x80\x80-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "-\xFC\x83\xBF\xBF\xBF\xBF-", { '-',0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* invalid bytes */
+ { "\xFE", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFF", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFE\xBF\xBF\xBF\xBF\xBF\xBF\xBF\xBF", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFF\xBF\xBF\xBF\xBF\xBF\xBF\xBF\xBF", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFF\x80\x80\x80\x80\x80\x80\x80\x80", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFF\x40\x80\x80\x80\x80\x80\x80\x80", { 0xfffd,0x40,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ /* lone continuation bytes */
+ { "\x80", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\x80\x80", { 0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xBF", { 0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xBF\xBF", { 0xfffd,0xfffd,0 }, STATUS_SOME_NOT_MAPPED },
+ /* incomplete sequences */
+ { "\xC2-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xE0\xA0-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xF0\x90\x80-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xF4\x8F\xBF-", { 0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFA\x80\x80\x80-", { 0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ { "\xFC\x84\x80\x80\x80-", { 0xfffd,0xfffd,0xfffd,0xfffd,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* multibyte sequence followed by lone continuation byte */
+ { "\xE0\xA0\x80\x80-", { 0x800,0xfffd,'-',0 }, STATUS_SOME_NOT_MAPPED },
+ /* byte order marks */
+ { "-\xEF\xBB\xBF-\xEF\xBF\xBE-", { '-',0xfeff,'-',0xfffe,'-',0 }, STATUS_SUCCESS },
+ { "\xEF\xBB\xBF-", { 0xfeff,'-',0 }, STATUS_SUCCESS },
+ { "\xEF\xBF\xBE-", { 0xfffe,'-',0 }, STATUS_SUCCESS },
+ /* invalid code point */
+ /* 0xffff */
+ { "\xEF\xBF\xBF-", { 0xffff,'-',0 }, STATUS_SUCCESS },
+ /* canonically equivalent representations -- no normalization should happen */
+ { "-\xE1\xB8\x89-", { '-',0x1e09,'-',0 }, STATUS_SUCCESS },
+ { "-\xC4\x87\xCC\xA7-", { '-',0x0107,0x0327,'-',0 }, STATUS_SUCCESS },
+ { "-\xC3\xA7\xCC\x81-", { '-',0x00e7,0x0301,'-',0 }, STATUS_SUCCESS },
+ { "-\x63\xCC\xA7\xCC\x81-", { '-',0x0063,0x0327,0x0301,'-',0 }, STATUS_SUCCESS },
+ { "-\x63\xCC\x81\xCC\xA7-", { '-',0x0063,0x0301,0x0327,'-',0 }, STATUS_SUCCESS },
+};
+
+static void unicode_expect_(const WCHAR *out_string, ULONG buflen, ULONG out_chars,
+ const char *in_string, ULONG in_chars,
+ NTSTATUS expect_status, int line)
+{
+ NTSTATUS status;
+ ULONG bytes_out;
+ WCHAR buffer[128];
+ unsigned int i;
+
+ if (buflen == (ULONG)-1)
+ buflen = sizeof(buffer);
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUTF8ToUnicodeN(
+ out_string ? buffer : NULL, buflen, &bytes_out,
+ in_string, in_chars);
+ ok_(__FILE__, line)(status == expect_status, "status = 0x%x\n", status);
+ ok_(__FILE__, line)(bytes_out == out_chars * sizeof(WCHAR),
+ "bytes_out = %u, expected %u\n", bytes_out, out_chars * (ULONG)sizeof(WCHAR));
+ if (out_string)
+ {
+ for (i = 0; i < bytes_out / sizeof(WCHAR); i++)
+ ok_(__FILE__, line)(buffer[i] == out_string[i],
+ "buffer[%d] = 0x%x, expected 0x%x\n",
+ i, buffer[i], out_string[i]);
+ for (; i < sizeof(buffer) / sizeof(WCHAR); i++)
+ ok_(__FILE__, line)(buffer[i] == 0x5555,
+ "buffer[%d] = 0x%x, expected 0x5555\n",
+ i, buffer[i]);
+ }
+}
+#define unicode_expect(out_string, buflen, out_chars, in_string, in_chars, expect_status) \
+ unicode_expect_(out_string, buflen, out_chars, in_string, in_chars, expect_status, __LINE__)
+
+static void test_RtlUTF8ToUnicodeN(void)
+{
+ NTSTATUS status;
+ ULONG bytes_out;
+ ULONG bytes_out_array[2];
+ void * const invalid_pointer = (void *)0x8;
+ WCHAR buffer[128];
+ const char empty_string[] = "";
+ const char test_string[] = "A\0abcdefg";
+ const WCHAR test_stringW[] = {'A',0,'a','b','c','d','e','f','g',0 };
+ const char special_string[] = { 'X',0xc2,0x80,0xF0,0x90,0x80,0x80,0 };
+ const WCHAR special_expected[] = { 'X',0x80,0xd800,0xdc00,0 };
+ unsigned int input_len;
+ const unsigned int test_count = sizeof(utf8_to_unicode) / sizeof(utf8_to_unicode[0]);
+ unsigned int i;
+
+ if (!pRtlUTF8ToUnicodeN)
+ {
+ skip("RtlUTF8ToUnicodeN unavailable\n");
+ return;
+ }
+
+ /* show that bytes_out is really ULONG */
+ memset(bytes_out_array, 0x55, sizeof(bytes_out_array));
+ status = pRtlUTF8ToUnicodeN(NULL, 0, bytes_out_array, empty_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out_array[0] == 0x00000000, "Got 0x%x\n", bytes_out_array[0]);
+ ok(bytes_out_array[1] == 0x55555555, "Got 0x%x\n", bytes_out_array[1]);
+
+ /* parameter checks */
+ status = pRtlUTF8ToUnicodeN(NULL, 0, NULL, NULL, 0);
+ ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
+
+ status = pRtlUTF8ToUnicodeN(NULL, 0, NULL, empty_string, 0);
+ ok(status == STATUS_INVALID_PARAMETER, "status = 0x%x\n", status);
+
+ bytes_out = 0x55555555;
+ status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, NULL, 0);
+ ok(status == STATUS_INVALID_PARAMETER_4, "status = 0x%x\n", status);
+ ok(bytes_out == 0x55555555, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, invalid_pointer, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, empty_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, test_string, 0);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == 0, "bytes_out = 0x%x\n", bytes_out);
+
+ bytes_out = 0x55555555;
+ status = pRtlUTF8ToUnicodeN(NULL, 0, &bytes_out, empty_string, 1);
+ ok(status == STATUS_SUCCESS, "status = 0x%x\n", status);
+ ok(bytes_out == sizeof(WCHAR), "bytes_out = 0x%x\n", bytes_out);
+
+ /* length output with special chars */
+#define length_expect(in_chars, out_chars, expect_status) \
+ unicode_expect_(NULL, 0, out_chars, special_string, in_chars, \
+ expect_status, __LINE__)
+
+ length_expect(0, 0, STATUS_SUCCESS);
+ length_expect(1, 1, STATUS_SUCCESS);
+ length_expect(2, 2, STATUS_SOME_NOT_MAPPED);
+ length_expect(3, 2, STATUS_SUCCESS);
+ length_expect(4, 3, STATUS_SOME_NOT_MAPPED);
+ length_expect(5, 3, STATUS_SOME_NOT_MAPPED);
+ length_expect(6, 3, STATUS_SOME_NOT_MAPPED);
+ length_expect(7, 4, STATUS_SUCCESS);
+ length_expect(8, 5, STATUS_SUCCESS);
+#undef length_expect
+
+ /* output truncation */
+#define truncate_expect(buflen, out_chars, expect_status) \
+ unicode_expect_(special_expected, buflen, out_chars, \
+ special_string, sizeof(special_string), \
+ expect_status, __LINE__)
+
+ truncate_expect( 0, 0, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 1, 0, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 2, 1, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 3, 1, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 4, 2, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 5, 2, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 6, 3, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 7, 3, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 8, 4, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect( 9, 4, STATUS_BUFFER_TOO_SMALL);
+ truncate_expect(10, 5, STATUS_SUCCESS);
+#undef truncate_expect
+
+ /* conversion behavior with varying input length */
+ for (input_len = 0; input_len <= sizeof(test_string); input_len++) {
+ /* no output buffer, just length */
+ unicode_expect(NULL, 0, input_len,
+ test_string, input_len, STATUS_SUCCESS);
+
+ /* write output */
+ unicode_expect(test_stringW, -1, input_len,
+ test_string, input_len, STATUS_SUCCESS);
+ }
+
+ /* test cases for special characters */
+ for (i = 0; i < test_count; i++) {
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUTF8ToUnicodeN(
+ buffer, sizeof(buffer), &bytes_out,
+ utf8_to_unicode[i].utf8, strlen(utf8_to_unicode[i].utf8));
+ ok(status == utf8_to_unicode[i].status,
+ "(test %d): status is 0x%x, expected 0x%x\n",
+ i, status, utf8_to_unicode[i].status);
+ ok(bytes_out == lstrlenW(utf8_to_unicode[i].expected) * sizeof(WCHAR),
+ "(test %d): bytes_out is %u, expected %u\n",
+ i, bytes_out, lstrlenW(utf8_to_unicode[i].expected) * (ULONG)sizeof(WCHAR));
+ ok(!memcmp(buffer, utf8_to_unicode[i].expected, bytes_out),
+ "(test %d): got %s, expected %s\n",
+ i, wine_dbgstr_wn(buffer, bytes_out / sizeof(WCHAR)), wine_dbgstr_w(utf8_to_unicode[i].expected));
+ ok(buffer[bytes_out] == 0x5555,
+ "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
+
+ /* same test but include the null terminator */
+ bytes_out = 0x55555555;
+ memset(buffer, 0x55, sizeof(buffer));
+ status = pRtlUTF8ToUnicodeN(
+ buffer, sizeof(buffer), &bytes_out,
+ utf8_to_unicode[i].utf8, strlen(utf8_to_unicode[i].utf8) + 1);
+ ok(status == utf8_to_unicode[i].status,
+ "(test %d): status is 0x%x, expected 0x%x\n",
+ i, status, utf8_to_unicode[i].status);
+ ok(bytes_out == (lstrlenW(utf8_to_unicode[i].expected) + 1) * sizeof(WCHAR),
+ "(test %d): bytes_out is %u, expected %u\n",
+ i, bytes_out, (lstrlenW(utf8_to_unicode[i].expected) + 1) * (ULONG)sizeof(WCHAR));
+ ok(!memcmp(buffer, utf8_to_unicode[i].expected, bytes_out),
+ "(test %d): got %s, expected %s\n",
+ i, wine_dbgstr_wn(buffer, bytes_out / sizeof(WCHAR)), wine_dbgstr_w(utf8_to_unicode[i].expected));
+ ok(buffer[bytes_out] == 0x5555,
+ "(test %d): behind string: 0x%x\n", i, buffer[bytes_out]);
+ }
+}
+
START_TEST(rtlstr)
{
InitFunctionPtrs();
test_RtlDowncaseUnicodeString();
}
test_RtlHashUnicodeString();
+ test_RtlUnicodeToUTF8N();
+ test_RtlUTF8ToUnicodeN();
}
static void (__cdecl *p_qsort)(void *,size_t,size_t, int(__cdecl *compar)(const void *, const void *) );
static void* (__cdecl *p_bsearch)(void *,void*,size_t,size_t, int(__cdecl *compar)(const void *, const void *) );
+static int (__cdecl *p__snprintf)(char *, size_t, const char *, ...);
static void InitFunctionPtrs(void)
p_wcsrchr= (void *)GetProcAddress(hntdll, "wcsrchr");
p_qsort= (void *)GetProcAddress(hntdll, "qsort");
p_bsearch= (void *)GetProcAddress(hntdll, "bsearch");
+
+ p__snprintf = (void *)GetProcAddress(hntdll, "_snprintf");
} /* if */
}
}
}
+static void test__snprintf(void)
+{
+ const char *origstring = "XXXXXXXXXXXX";
+ const char *teststring = "hello world";
+ char buffer[32];
+ int res;
+
+ res = p__snprintf(NULL, 0, teststring);
+ ok(res == lstrlenA(teststring) || broken(res == -1) /* <= w2k */,
+ "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring));
+
+ if (res != -1)
+ {
+ res = p__snprintf(NULL, 1, teststring);
+ ok(res == lstrlenA(teststring) /* WinXP */ || res < 0 /* Vista and greater */,
+ "_snprintf returned %d, expected %d or < 0.\n", res, lstrlenA(teststring));
+ }
+ res = p__snprintf(buffer, strlen(teststring) - 1, teststring);
+ ok(res < 0, "_snprintf returned %d, expected < 0.\n", res);
+
+ strcpy(buffer, origstring);
+ res = p__snprintf(buffer, strlen(teststring), teststring);
+ ok(res == lstrlenA(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring));
+ ok(!strcmp(buffer, "hello worldX"), "_snprintf returned buffer '%s', expected 'hello worldX'.\n", buffer);
+
+ strcpy(buffer, origstring);
+ res = p__snprintf(buffer, strlen(teststring) + 1, teststring);
+ ok(res == lstrlenA(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring));
+ ok(!strcmp(buffer, teststring), "_snprintf returned buffer '%s', expected '%s'.\n", buffer, teststring);
+}
+
START_TEST(string)
{
InitFunctionPtrs();
test_qsort();
if (p_bsearch)
test_bsearch();
+ if (p__snprintf)
+ test__snprintf();
}
/* Automatically generated file; DO NOT EDIT!! */
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
#define STANDALONE
-#include "wine/test.h"
+#include <wine/test.h>
extern void func_atom(void);
extern void func_change(void);
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
-static inline int IsLeapYear(int Year)
+static inline BOOL IsLeapYear(int Year)
{
- return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
+ return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
}
/* start time of the tests */