Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/file.c | 106 ++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 58 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b4223b3..b7ccf49 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -108,10 +108,6 @@ static HANDLE create_temp_file( ULONG flags ) #define CKEY_FIRST 0x1030341 #define CKEY_SECOND 0x132E46
-static ULONG_PTR completionKey; -static IO_STATUS_BLOCK ioSb; -static ULONG_PTR completionValue; - static ULONG get_pending_msgs(HANDLE h) { NTSTATUS res; @@ -124,21 +120,6 @@ static ULONG get_pending_msgs(HANDLE h) return a; }
-static BOOL get_msg(HANDLE h) -{ - LARGE_INTEGER timeout = {{-10000000*3}}; - DWORD res = pNtRemoveIoCompletion( h, &completionKey, &completionValue, &ioSb, &timeout); - ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %x\n", res ); - if (res != STATUS_SUCCESS) - { - completionKey = completionValue = 0; - memset(&ioSb, 0, sizeof(ioSb)); - return FALSE; - } - return TRUE; -} - - static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved ) { int *count = arg; @@ -881,6 +862,9 @@ static void nt_mailslot_test(void)
static void test_iocp_setcompletion(HANDLE h) { + LARGE_INTEGER timeout = {{0}}; + IO_STATUS_BLOCK iosb; + ULONG_PTR key, value; NTSTATUS res; ULONG count; SIZE_T size = 3; @@ -893,13 +877,12 @@ static void test_iocp_setcompletion(HANDLE h) count = get_pending_msgs(h); ok( count == 1, "Unexpected msg count: %d\n", count );
- if (get_msg(h)) - { - ok( completionKey == CKEY_FIRST, "Invalid completion key: %lx\n", completionKey ); - ok( ioSb.Information == size, "Invalid ioSb.Information: %lu\n", ioSb.Information ); - ok( U(ioSb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid ioSb.Status: %x\n", U(ioSb).Status); - ok( completionValue == CVALUE_FIRST, "Invalid completion value: %lx\n", completionValue ); - } + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_FIRST, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == size, "Invalid iosb.Information: %lu\n", iosb.Information ); + ok( U(iosb).Status == STATUS_INVALID_DEVICE_REQUEST, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == CVALUE_FIRST, "Invalid completion value: %#lx\n", value );
count = get_pending_msgs(h); ok( !count, "Unexpected msg count: %d\n", count ); @@ -911,7 +894,9 @@ static void test_iocp_fileio(HANDLE h)
IO_STATUS_BLOCK iosb; FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND}; + LARGE_INTEGER timeout = {{0}}; HANDLE hPipeSrv, hPipeClt; + ULONG_PTR key, value; NTSTATUS res;
hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL ); @@ -960,14 +945,15 @@ static void test_iocp_fileio(HANDLE h) ok( !count, "Unexpected msg count: %ld\n", count ); WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
- if (get_msg(h)) - { - ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); - ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information ); - ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status); - ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); - ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); - } + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), + "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", + recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); count = get_pending_msgs(h); ok( !count, "Unexpected msg count: %ld\n", count );
@@ -979,27 +965,29 @@ static void test_iocp_fileio(HANDLE h) ReadFile( hPipeSrv, recv_buf, 2, &read, &o); count = get_pending_msgs(h); ok( count == 1, "Unexpected msg count: %ld\n", count ); - if (get_msg(h)) - { - ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); - ok( ioSb.Information == 2, "Invalid ioSb.Information: %ld\n", ioSb.Information ); - ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status); - ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); - ok( !memcmp( send_buf, recv_buf, 2 ), "Receive buffer (%x %x) did not match send buffer (%x %x)\n", recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] ); - } + + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 2, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, 2 ), + "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n", + recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o); CloseHandle( hPipeSrv ); count = get_pending_msgs(h); ok( count == 1, "Unexpected msg count: %ld\n", count ); - if (get_msg(h)) - { - ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); - ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information ); - /* wine sends wrong status here */ - ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status); - ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); - } + + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %lx\n", key ); + ok( iosb.Information == 0, "Invalid iosb.Information: %ld\n", iosb.Information ); + /* wine sends wrong status here */ + ok( U(iosb).Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %lx\n", value ); }
CloseHandle( hPipeClt ); @@ -1034,14 +1022,16 @@ static void test_iocp_fileio(HANDLE h)
WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL );
- if (get_msg(h)) - { - ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); - ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information ); - ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status); - ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); - ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), "Receive buffer (%x %x %x) did not match send buffer (%x %x %x)\n", recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); - } + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), + "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", + recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); + count = get_pending_msgs(h); ok( !count, "Unexpected msg count: %ld\n", count );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/file.c | 309 +++++++++++++++++++++++------------------------- 1 file changed, 146 insertions(+), 163 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b7ccf49..0773ad3 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -893,203 +893,186 @@ static void test_iocp_fileio(HANDLE h) static const char pipe_name[] = "\\.\pipe\iocompletiontestnamedpipe";
IO_STATUS_BLOCK iosb; + BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN]; FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND}; LARGE_INTEGER timeout = {{0}}; - HANDLE hPipeSrv, hPipeClt; + HANDLE server, client; ULONG_PTR key, value; + OVERLAPPED o = {0}; + int apc_count = 0; NTSTATUS res; + DWORD read; + long count;
- hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL ); - ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" ); - if (hPipeSrv != INVALID_HANDLE_VALUE ) - { - hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); - ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" ); - if (hPipeClt != INVALID_HANDLE_VALUE) - { - U(iosb).Status = 0xdeadbeef; - res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation ); - ok( res == STATUS_INVALID_PARAMETER, "Unexpected NtSetInformationFile on non-overlapped handle: %x\n", res ); - ok( U(iosb).Status == STATUS_INVALID_PARAMETER /* 98 */ || U(iosb).Status == 0xdeadbeef /* NT4+ */, - "Unexpected iosb.Status on non-overlapped handle: %x\n", U(iosb).Status ); - CloseHandle(hPipeClt); - } - CloseHandle( hPipeSrv ); - } + server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 4, 1024, 1024, 1000, NULL ); + ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() ); + client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); + ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
- hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL ); - ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" ); - if (hPipeSrv == INVALID_HANDLE_VALUE ) - return; + U(iosb).Status = 0xdeadbeef; + res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation ); + ok( res == STATUS_INVALID_PARAMETER, "NtSetInformationFile failed: %#x\n", res ); +todo_wine + ok( U(iosb).Status == 0xdeadbeef, "wrong status %#x\n", U(iosb).Status ); + CloseHandle( client ); + CloseHandle( server );
- hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); - ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" ); - if (hPipeClt != INVALID_HANDLE_VALUE) - { - OVERLAPPED o = {0,}; - BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN]; - DWORD read; - long count; + server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 4, 1024, 1024, 1000, NULL ); + ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() ); + client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); + ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
- U(iosb).Status = 0xdeadbeef; - res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation ); - ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res ); - ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status ); + U(iosb).Status = 0xdeadbeef; + res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation ); + ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %#x\n", res ); + ok( U(iosb).Status == STATUS_SUCCESS, "wrong status %#x\n", U(iosb).Status );
- memset( send_buf, 0, TEST_BUF_LEN ); - memset( recv_buf, 0xde, TEST_BUF_LEN ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); - ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); - WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL ); + memset( send_buf, 0, TEST_BUF_LEN ); + memset( recv_buf, 0xde, TEST_BUF_LEN ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count ); + ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count ); + WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
- res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); - ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); - ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); - ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); - ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); - ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); - ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), - "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", - recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), + "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", + recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- memset( send_buf, 0, TEST_BUF_LEN ); - memset( recv_buf, 0xde, TEST_BUF_LEN ); - WriteFile( hPipeClt, send_buf, 2, &read, NULL ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); - ReadFile( hPipeSrv, recv_buf, 2, &read, &o); - count = get_pending_msgs(h); - ok( count == 1, "Unexpected msg count: %ld\n", count ); + memset( send_buf, 0, TEST_BUF_LEN ); + memset( recv_buf, 0xde, TEST_BUF_LEN ); + WriteFile( client, send_buf, 2, &read, NULL ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count ); + ReadFile( server, recv_buf, 2, &read, &o); + count = get_pending_msgs(h); + ok( count == 1, "Unexpected msg count: %ld\n", count );
- res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); - ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); - ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); - ok( iosb.Information == 2, "Invalid iosb.Information: %ld\n", iosb.Information ); - ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); - ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); - ok( !memcmp( send_buf, recv_buf, 2 ), - "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n", - recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] ); + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 2, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, 2 ), + "Receive buffer (%02x %02x) did not match send buffer (%02x %02x)\n", + recv_buf[0], recv_buf[1], send_buf[0], send_buf[1] );
- ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o); - CloseHandle( hPipeSrv ); - count = get_pending_msgs(h); - ok( count == 1, "Unexpected msg count: %ld\n", count ); + ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o); + CloseHandle( server ); + count = get_pending_msgs(h); + ok( count == 1, "Unexpected msg count: %ld\n", count );
- res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); - ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); - ok( key == CKEY_SECOND, "Invalid completion key: %lx\n", key ); - ok( iosb.Information == 0, "Invalid iosb.Information: %ld\n", iosb.Information ); - /* wine sends wrong status here */ - ok( U(iosb).Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %x\n", U(iosb).Status ); - ok( value == (ULONG_PTR)&o, "Invalid completion value: %lx\n", value ); - } + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %lx\n", key ); + ok( iosb.Information == 0, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_PIPE_BROKEN, "Invalid iosb.Status: %x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %lx\n", value );
- CloseHandle( hPipeClt ); + CloseHandle( client );
/* test associating a completion port with a handle after an async is queued */ - hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL ); - ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" ); - if (hPipeSrv == INVALID_HANDLE_VALUE ) - return; - hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); - ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" ); - if (hPipeClt != INVALID_HANDLE_VALUE) - { - OVERLAPPED o = {0,}; - BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN]; - int apc_count = 0; - DWORD read; - long count; + server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 4, 1024, 1024, 1000, NULL ); + ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() ); + client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); + ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
- memset( send_buf, 0, TEST_BUF_LEN ); - memset( recv_buf, 0xde, TEST_BUF_LEN ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); - ReadFile( hPipeSrv, recv_buf, TEST_BUF_LEN, &read, &o); + memset( send_buf, 0, TEST_BUF_LEN ); + memset( recv_buf, 0xde, TEST_BUF_LEN ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count ); + ReadFile( server, recv_buf, TEST_BUF_LEN, &read, &o);
- U(iosb).Status = 0xdeadbeef; - res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation ); - ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res ); - ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + U(iosb).Status = 0xdeadbeef; + res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation ); + ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res ); + ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL ); + WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
- res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); - ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); - ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); - ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); - ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); - ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); - ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), - "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", - recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] ); + res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletion failed: %#x\n", res ); + ok( key == CKEY_SECOND, "Invalid completion key: %#lx\n", key ); + ok( iosb.Information == 3, "Invalid iosb.Information: %ld\n", iosb.Information ); + ok( U(iosb).Status == STATUS_SUCCESS, "Invalid iosb.Status: %#x\n", U(iosb).Status ); + ok( value == (ULONG_PTR)&o, "Invalid completion value: %#lx\n", value ); + ok( !memcmp( send_buf, recv_buf, TEST_BUF_LEN ), + "Receive buffer (%02x %02x %02x) did not match send buffer (%02x %02x %02x)\n", + recv_buf[0], recv_buf[1], recv_buf[2], send_buf[0], send_buf[1], send_buf[2] );
- count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- /* using APCs on handle with associated completion port is not allowed */ - res = pNtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); - ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res); - } + /* using APCs on handle with associated completion port is not allowed */ + res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); + ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
- CloseHandle( hPipeSrv ); - CloseHandle( hPipeClt ); + CloseHandle( server ); + CloseHandle( client );
/* test associating a completion port with a handle after an async using APC is queued */ - hPipeSrv = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 4, 1024, 1024, 1000, NULL ); - ok( hPipeSrv != INVALID_HANDLE_VALUE, "Cannot create named pipe\n" ); - if (hPipeSrv == INVALID_HANDLE_VALUE ) - return; - hPipeClt = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); - ok( hPipeClt != INVALID_HANDLE_VALUE, "Cannot connect to pipe\n" ); - if (hPipeClt != INVALID_HANDLE_VALUE) - { - BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN]; - int apc_count = 0; - DWORD read; - long count; + server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 4, 1024, 1024, 1000, NULL ); + ok( server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed: %u\n", GetLastError() ); + client = CreateFileA( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL ); + ok( client != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError() );
- memset( send_buf, 0, TEST_BUF_LEN ); - memset( recv_buf, 0xde, TEST_BUF_LEN ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + apc_count = 0; + memset( send_buf, 0, TEST_BUF_LEN ); + memset( recv_buf, 0xde, TEST_BUF_LEN ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- res = pNtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); - ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res); + res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); + ok(res == STATUS_PENDING, "NtReadFile returned %x\n", res);
- U(iosb).Status = 0xdeadbeef; - res = pNtSetInformationFile( hPipeSrv, &iosb, &fci, sizeof(fci), FileCompletionInformation ); - ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res ); - ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status ); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + U(iosb).Status = 0xdeadbeef; + res = pNtSetInformationFile( server, &iosb, &fci, sizeof(fci), FileCompletionInformation ); + ok( res == STATUS_SUCCESS, "NtSetInformationFile failed: %x\n", res ); + ok( U(iosb).Status == STATUS_SUCCESS, "iosb.Status invalid: %x\n", U(iosb).Status ); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- WriteFile( hPipeClt, send_buf, TEST_BUF_LEN, &read, NULL ); + WriteFile( client, send_buf, TEST_BUF_LEN, &read, NULL );
- ok(!apc_count, "apc_count = %u\n", apc_count); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + ok(!apc_count, "apc_count = %u\n", apc_count); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- SleepEx(1, TRUE); /* alertable sleep */ - ok(apc_count == 1, "apc was not called\n"); - count = get_pending_msgs(h); - ok( !count, "Unexpected msg count: %ld\n", count ); + SleepEx(1, TRUE); /* alertable sleep */ + ok(apc_count == 1, "apc was not called\n"); + count = get_pending_msgs(h); + ok( !count, "Unexpected msg count: %ld\n", count );
- /* using APCs on handle with associated completion port is not allowed */ - res = pNtReadFile( hPipeSrv, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); - ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res); - } + /* using APCs on handle with associated completion port is not allowed */ + res = pNtReadFile( server, NULL, apc, &apc_count, &iosb, recv_buf, sizeof(recv_buf), NULL, NULL ); + ok(res == STATUS_INVALID_PARAMETER, "NtReadFile returned %x\n", res);
- CloseHandle( hPipeSrv ); - CloseHandle( hPipeClt ); + CloseHandle( server ); + CloseHandle( client ); }
static void test_file_full_size_information(void)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=42671
Your paranoid android.
=== w8 (32 bit Windows report) ===
ntdll: file.c:441: Test failed: mismatched file size for L"WindowsUpdate.log"
Call I/O completion tests directly.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/file.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 0773ad3..88b2b9b 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -860,7 +860,7 @@ static void nt_mailslot_test(void) ok( rc == STATUS_SUCCESS, "NtClose failed\n"); }
-static void test_iocp_setcompletion(HANDLE h) +static void test_set_io_completion(void) { LARGE_INTEGER timeout = {{0}}; IO_STATUS_BLOCK iosb; @@ -868,9 +868,14 @@ static void test_iocp_setcompletion(HANDLE h) NTSTATUS res; ULONG count; SIZE_T size = 3; + HANDLE h;
if (sizeof(size) > 4) size |= (ULONGLONG)0x12345678 << 32;
+ res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 ); + ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#x\n", res ); + ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h ); + res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size ); ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
@@ -886,15 +891,17 @@ static void test_iocp_setcompletion(HANDLE h)
count = get_pending_msgs(h); ok( !count, "Unexpected msg count: %d\n", count ); + + pNtClose( h ); }
-static void test_iocp_fileio(HANDLE h) +static void test_file_io_completion(void) { static const char pipe_name[] = "\\.\pipe\iocompletiontestnamedpipe";
IO_STATUS_BLOCK iosb; BYTE send_buf[TEST_BUF_LEN], recv_buf[TEST_BUF_LEN]; - FILE_COMPLETION_INFORMATION fci = {h, CKEY_SECOND}; + FILE_COMPLETION_INFORMATION fci; LARGE_INTEGER timeout = {{0}}; HANDLE server, client; ULONG_PTR key, value; @@ -903,6 +910,13 @@ static void test_iocp_fileio(HANDLE h) NTSTATUS res; DWORD read; long count; + HANDLE h; + + res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0 ); + ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#x\n", res ); + ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h ); + fci.CompletionPort = h; + fci.CompletionKey = CKEY_SECOND;
server = CreateNamedPipeA( pipe_name, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, @@ -1073,6 +1087,7 @@ todo_wine
CloseHandle( server ); CloseHandle( client ); + pNtClose( h ); }
static void test_file_full_size_information(void) @@ -2921,24 +2936,6 @@ todo_wine RemoveDirectoryA( buffer ); }
-static void test_iocompletion(void) -{ - HANDLE h = INVALID_HANDLE_VALUE; - NTSTATUS res; - - res = pNtCreateIoCompletion( &h, IO_COMPLETION_ALL_ACCESS, NULL, 0); - - ok( res == 0, "NtCreateIoCompletion anonymous failed: %x\n", res ); - ok( h && h != INVALID_HANDLE_VALUE, "Invalid handle returned\n" ); - - if ( h && h != INVALID_HANDLE_VALUE) - { - test_iocp_setcompletion(h); - test_iocp_fileio(h); - pNtClose(h); - } -} - static void test_file_name_information(void) { WCHAR *file_name, *volume_prefix, *expected; @@ -4466,7 +4463,8 @@ START_TEST(file) read_file_test(); append_file_test(); nt_mailslot_test(); - test_iocompletion(); + test_set_io_completion(); + test_file_io_completion(); test_file_basic_information(); test_file_all_information(); test_file_both_information();
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=42672
Your paranoid android.
=== w8 (32 bit Windows report) ===
ntdll: file.c:441: Test failed: mismatched file size for L"WindowsUpdate.log"
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/file.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ include/winternl.h | 7 +++++ 2 files changed, 91 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 88b2b9b..8b6db89 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -74,6 +74,7 @@ static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_AT static NTSTATUS (WINAPI *pNtOpenIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); static NTSTATUS (WINAPI *pNtQueryIoCompletion)(HANDLE, IO_COMPLETION_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER); +static NTSTATUS (WINAPI *pNtRemoveIoCompletionEx)(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN); static NTSTATUS (WINAPI *pNtSetIoCompletion)(HANDLE, ULONG_PTR, ULONG_PTR, NTSTATUS, SIZE_T); static NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS); static NTSTATUS (WINAPI *pNtQueryAttributesFile)(const OBJECT_ATTRIBUTES*,FILE_BASIC_INFORMATION*); @@ -860,9 +861,17 @@ static void nt_mailslot_test(void) ok( rc == STATUS_SUCCESS, "NtClose failed\n"); }
+static void WINAPI user_apc_proc(ULONG_PTR arg) +{ + unsigned int *apc_count = (unsigned int *)arg; + ++*apc_count; +} + static void test_set_io_completion(void) { + FILE_IO_COMPLETION_INFORMATION info[2] = {{0}}; LARGE_INTEGER timeout = {{0}}; + unsigned int apc_count; IO_STATUS_BLOCK iosb; ULONG_PTR key, value; NTSTATUS res; @@ -876,6 +885,9 @@ static void test_set_io_completion(void) ok( res == STATUS_SUCCESS, "NtCreateIoCompletion failed: %#x\n", res ); ok( h && h != INVALID_HANDLE_VALUE, "got invalid handle %p\n", h );
+ res = pNtRemoveIoCompletion( h, &key, &value, &iosb, &timeout ); + ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletion failed: %#x\n", res ); + res = pNtSetIoCompletion( h, CKEY_FIRST, CVALUE_FIRST, STATUS_INVALID_DEVICE_REQUEST, size ); ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %x\n", res );
@@ -892,6 +904,77 @@ static void test_set_io_completion(void) count = get_pending_msgs(h); ok( !count, "Unexpected msg count: %d\n", count );
+ if (!pNtRemoveIoCompletionEx) + { + skip("NtRemoveIoCompletionEx() not present\n"); + pNtClose( h ); + return; + } + + count = 0xdeadbeef; + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE ); + ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 1, "wrong count %u\n", count ); + + res = pNtSetIoCompletion( h, 123, 456, 789, size ); + ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res ); + + count = 0xdeadbeef; + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 1, "wrong count %u\n", count ); + ok( info[0].CompletionKey == 123, "wrong key %#lx\n", info[0].CompletionKey ); + ok( info[0].CompletionValue == 456, "wrong value %#lx\n", info[0].CompletionValue ); + ok( info[0].IoStatusBlock.Information == size, "wrong information %#lx\n", + info[0].IoStatusBlock.Information ); + ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#x\n", U(info[0].IoStatusBlock).Status); + + res = pNtSetIoCompletion( h, 123, 456, 789, size ); + ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res ); + + res = pNtSetIoCompletion( h, 12, 34, 56, size ); + ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res ); + + count = 0xdeadbeef; + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 2, "wrong count %u\n", count ); + ok( info[0].CompletionKey == 123, "wrong key %#lx\n", info[0].CompletionKey ); + ok( info[0].CompletionValue == 456, "wrong value %#lx\n", info[0].CompletionValue ); + ok( info[0].IoStatusBlock.Information == size, "wrong information %#lx\n", + info[0].IoStatusBlock.Information ); + ok( U(info[0].IoStatusBlock).Status == 789, "wrong status %#x\n", U(info[0].IoStatusBlock).Status); + ok( info[1].CompletionKey == 12, "wrong key %#lx\n", info[1].CompletionKey ); + ok( info[1].CompletionValue == 34, "wrong value %#lx\n", info[1].CompletionValue ); + ok( info[1].IoStatusBlock.Information == size, "wrong information %#lx\n", + info[1].IoStatusBlock.Information ); + ok( U(info[1].IoStatusBlock).Status == 56, "wrong status %#x\n", U(info[1].IoStatusBlock).Status); + + apc_count = 0; + QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count ); + + count = 0xdeadbeef; + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, FALSE ); + ok( res == STATUS_TIMEOUT, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 1, "wrong count %u\n", count ); + ok( !apc_count, "wrong apc count %d\n", apc_count ); + + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE ); + ok( res == STATUS_USER_APC, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 1, "wrong count %u\n", count ); + ok( apc_count == 1, "wrong apc count %u\n", apc_count ); + + apc_count = 0; + QueueUserAPC( user_apc_proc, GetCurrentThread(), (ULONG_PTR)&apc_count ); + + res = pNtSetIoCompletion( h, 123, 456, 789, size ); + ok( res == STATUS_SUCCESS, "NtSetIoCompletion failed: %#x\n", res ); + + res = pNtRemoveIoCompletionEx( h, info, 2, &count, &timeout, TRUE ); + ok( res == STATUS_SUCCESS, "NtRemoveIoCompletionEx failed: %#x\n", res ); + ok( count == 1, "wrong count %u\n", count ); + ok( !apc_count, "wrong apc count %u\n", apc_count ); + pNtClose( h ); }
@@ -4446,6 +4529,7 @@ START_TEST(file) pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion"); pNtQueryIoCompletion = (void *)GetProcAddress(hntdll, "NtQueryIoCompletion"); pNtRemoveIoCompletion = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletion"); + pNtRemoveIoCompletionEx = (void *)GetProcAddress(hntdll, "NtRemoveIoCompletionEx"); pNtSetIoCompletion = (void *)GetProcAddress(hntdll, "NtSetIoCompletion"); pNtSetInformationFile = (void *)GetProcAddress(hntdll, "NtSetInformationFile"); pNtQueryAttributesFile = (void *)GetProcAddress(hntdll, "NtQueryAttributesFile"); diff --git a/include/winternl.h b/include/winternl.h index c718d4c..74f49a1 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2128,6 +2128,12 @@ typedef struct _FILE_COMPLETION_INFORMATION { #define IO_COMPLETION_MODIFY_STATE 0x0002 #define IO_COMPLETION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+typedef struct _FILE_IO_COMPLETION_INFORMATION { + ULONG_PTR CompletionKey; + ULONG_PTR CompletionValue; + IO_STATUS_BLOCK IoStatusBlock; +} FILE_IO_COMPLETION_INFORMATION, *PFILE_IO_COMPLETION_INFORMATION; + typedef enum _HARDERROR_RESPONSE_OPTION { OptionAbortRetryIgnore, OptionOk, @@ -2469,6 +2475,7 @@ NTSYSAPI NTSTATUS WINAPI NtReleaseKeyedEvent(HANDLE,const void*,BOOLEAN,const L NTSYSAPI NTSTATUS WINAPI NtReleaseMutant(HANDLE,PLONG); NTSYSAPI NTSTATUS WINAPI NtReleaseSemaphore(HANDLE,ULONG,PULONG); NTSYSAPI NTSTATUS WINAPI NtRemoveIoCompletion(HANDLE,PULONG_PTR,PULONG_PTR,PIO_STATUS_BLOCK,PLARGE_INTEGER); +NTSYSAPI NTSTATUS WINAPI NtRemoveIoCompletionEx(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtRenameKey(HANDLE,UNICODE_STRING*); NTSYSAPI NTSTATUS WINAPI NtReplaceKey(POBJECT_ATTRIBUTES,HANDLE,POBJECT_ATTRIBUTES); NTSYSAPI NTSTATUS WINAPI NtReplyPort(HANDLE,PLPC_MESSAGE);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=42673
Your paranoid android.
=== w8 (32 bit Windows report) ===
ntdll: file.c:442: Test failed: mismatched file size for L"WindowsUpdate.log"
=== wvistau64 (64 bit Windows report) ===
ntdll: file.c:1163: Test failed: apc was not called
=== w2008s64 (64 bit Windows report) ===
ntdll: file.c:1163: Test failed: apc was not called
=== w7pro64 (64 bit Windows report) ===
ntdll: file.c:1163: Test failed: apc was not called
=== w864 (64 bit Windows report) ===
ntdll: file.c:1163: Test failed: apc was not called
=== w1064 (64 bit Windows report) ===
ntdll: file.c:1163: Test failed: apc was not called
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/sync.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5e7c463..37e4e8e 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -308,6 +308,7 @@ @ stub NtReleaseProcessMutant @ stdcall NtReleaseSemaphore(long long ptr) @ stdcall NtRemoveIoCompletion(ptr ptr ptr ptr ptr) +@ stdcall NtRemoveIoCompletionEx(ptr ptr long ptr ptr long) # @ stub NtRemoveProcessDebug @ stdcall NtRenameKey(long ptr) @ stdcall NtReplaceKey(ptr long ptr) diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index bb462f2..4ae8e36 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1334,6 +1334,54 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE CompletionPort, PULONG_PTR Completi }
/****************************************************************** + * NtRemoveIoCompletionEx (NTDLL.@) + * ZwRemoveIoCompletionEx (NTDLL.@) + */ +NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE port, FILE_IO_COMPLETION_INFORMATION *info, ULONG count, + ULONG *written, LARGE_INTEGER *timeout, BOOLEAN alertable ) +{ + NTSTATUS ret; + ULONG i = 0; + + TRACE("%p %p %u %p %p %u\n", port, info, count, written, timeout, alertable); + + for (;;) + { + for (;;) + { + SERVER_START_REQ( remove_completion ) + { + req->handle = wine_server_obj_handle( port ); + if (!(ret = wine_server_call( req ))) + { + info[i].CompletionKey = reply->ckey; + info[i].CompletionValue = reply->cvalue; + info[i].IoStatusBlock.Information = reply->information; + info[i].IoStatusBlock.u.Status = reply->status; + } + } + SERVER_END_REQ; + + if (ret != STATUS_SUCCESS) break; + + if (i++ >= count) break; + } + + if (i && ret == STATUS_PENDING) + { + ret = STATUS_SUCCESS; + break; + } + + ret = NtWaitForSingleObject( port, alertable, timeout ); + if (ret != WAIT_OBJECT_0) break; + } + + *written = i ? i : 1; + return ret; +} + +/****************************************************************** * NtOpenIoCompletion (NTDLL.@) * ZwOpenIoCompletion (NTDLL.@) *
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/tests/file.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 33cae4b..a4a839f 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -60,6 +60,7 @@ static NTSTATUS (WINAPI *pNtCreateFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(LPCWSTR, PUNICODE_STRING, PWSTR*, CURDIR*); static NTSTATUS (WINAPI *pRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PCANSI_STRING, BOOLEAN); static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void*, DWORD); +static BOOL (WINAPI *pGetQueuedCompletionStatusEx)(HANDLE, OVERLAPPED_ENTRY*, ULONG, ULONG*, DWORD, BOOL);
static const char filename[] = "testfile.xxx"; static const char sillytext[] = @@ -105,6 +106,7 @@ static void InitFunctionPointers(void) pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA"); pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW"); pSetFileInformationByHandle = (void *) GetProcAddress(hkernel32, "SetFileInformationByHandle"); + pGetQueuedCompletionStatusEx = (void *) GetProcAddress(hkernel32, "GetQueuedCompletionStatusEx"); }
static void test__hread( void ) @@ -4988,6 +4990,101 @@ static void test_GetFileAttributesExW(void) ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected error ERROR_FILE_NOT_FOUND, got %u\n", GetLastError()); }
+static void test_post_completion(void) +{ + OVERLAPPED ovl, ovl2, *povl; + OVERLAPPED_ENTRY entries[2]; + ULONG_PTR key; + HANDLE port; + ULONG count; + DWORD size; + BOOL ret; + + port = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 999, 0 ); + ok(port != NULL, "CreateIoCompletionPort failed: %u\n", GetLastError()); + + ret = GetQueuedCompletionStatus( port, &size, &key, &povl, 0 ); + ok(!ret, "GetQueuedCompletionStatus succeeded\n"); + ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError()); + + ret = PostQueuedCompletionStatus( port, 123, 456, &ovl ); + ok(ret, "PostQueuedCompletionStatus failed: %u\n", GetLastError()); + + ret = GetQueuedCompletionStatus( port, &size, &key, &povl, 0 ); + ok(ret, "GetQueuedCompletionStatus failed: %u\n", GetLastError()); + ok(size == 123, "wrong size %u\n", size); + ok(key == 456, "wrong key %lu\n", key); + ok(povl == &ovl, "wrong ovl %p\n", povl); + + ret = GetQueuedCompletionStatus( port, &size, &key, &povl, 0 ); + ok(!ret, "GetQueuedCompletionStatus succeeded\n"); + ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError()); + + if (!pGetQueuedCompletionStatusEx) + { + skip("GetQueuedCompletionStatusEx not available\n"); + CloseHandle( port ); + return; + } + + count = 0xdeadbeef; + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, FALSE ); + ok(!ret, "GetQueuedCompletionStatusEx succeeded\n"); + ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError()); + ok(count == 1, "wrong count %u\n", count); + + ret = PostQueuedCompletionStatus( port, 123, 456, &ovl ); + ok(ret, "PostQueuedCompletionStatus failed: %u\n", GetLastError()); + + count = 0xdeadbeef; + memset( entries, 0xcc, sizeof(entries) ); + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, FALSE ); + ok(ret, "GetQueuedCompletionStatusEx succeeded\n"); + ok(count == 1, "wrong count %u\n", count); + ok(entries[0].lpCompletionKey == 456, "wrong key %lu\n", entries[0].lpCompletionKey); + ok(entries[0].lpOverlapped == &ovl, "wrong ovl %p\n", entries[0].lpOverlapped); + ok(!entries[0].Internal, "wrong internal %lu\n", entries[0].Internal); + ok(entries[0].dwNumberOfBytesTransferred == 123, "wrong size %u\n", entries[0].dwNumberOfBytesTransferred); + + ret = PostQueuedCompletionStatus( port, 123, 456, &ovl ); + ok(ret, "PostQueuedCompletionStatus failed: %u\n", GetLastError()); + + ret = PostQueuedCompletionStatus( port, 654, 321, &ovl2 ); + ok(ret, "PostQueuedCompletionStatus failed: %u\n", GetLastError()); + + count = 0xdeadbeef; + memset( entries, 0xcc, sizeof(entries) ); + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, FALSE ); + ok(ret, "GetQueuedCompletionStatusEx succeeded\n"); + ok(count == 2, "wrong count %u\n", count); + ok(entries[0].lpCompletionKey == 456, "wrong key %lu\n", entries[0].lpCompletionKey); + ok(entries[0].lpOverlapped == &ovl, "wrong ovl %p\n", entries[0].lpOverlapped); + ok(!entries[0].Internal, "wrong internal %lu\n", entries[0].Internal); + ok(entries[0].dwNumberOfBytesTransferred == 123, "wrong size %u\n", entries[0].dwNumberOfBytesTransferred); + ok(entries[1].lpCompletionKey == 321, "wrong key %lu\n", entries[1].lpCompletionKey); + ok(entries[1].lpOverlapped == &ovl2, "wrong ovl %p\n", entries[1].lpOverlapped); + ok(!entries[1].Internal, "wrong internal %lu\n", entries[1].Internal); + ok(entries[1].dwNumberOfBytesTransferred == 654, "wrong size %u\n", entries[1].dwNumberOfBytesTransferred); + + user_apc_ran = FALSE; + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, FALSE ); + ok(!ret, "GetQueuedCompletionStatusEx succeeded\n"); + ok(GetLastError() == WAIT_TIMEOUT, "wrong error %u\n", GetLastError()); + ok(count == 1, "wrong count %u\n", count); + ok(!user_apc_ran, "user APC should not have run\n"); + + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, TRUE ); + ok(!ret || broken(ret), "GetQueuedCompletionStatusEx succeeded\n"); + if (!ret) + ok(GetLastError() == WAIT_IO_COMPLETION, "wrong error %u\n", GetLastError()); + ok(count == 1, "wrong count %u\n", count); + ok(user_apc_ran, "user APC should have run\n"); + + CloseHandle( port ); +} + START_TEST(file) { InitFunctionPointers(); @@ -5046,4 +5143,5 @@ START_TEST(file) test_GetFinalPathNameByHandleW(); test_SetFileInformationByHandle(); test_GetFileAttributesExW(); + test_post_completion(); }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=42675
Your paranoid android.
=== w2008s64 (64 bit Windows report) ===
kernel32: file.c:5062: Test failed: wrong internal 0 file.c:5066: Test failed: wrong internal 0
=== w7pro64 (64 bit Windows report) ===
kernel32: file.c:5046: Test failed: wrong internal 0 file.c:5062: Test failed: wrong internal 0 file.c:5066: Test failed: wrong internal 0
=== w1064 (64 bit Windows report) ===
kernel32: file.c:5046: Test failed: wrong internal 0 file.c:5062: Test failed: wrong internal 0 file.c:5066: Test failed: wrong internal 0
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43878 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- .../api-ms-win-core-io-l1-1-0.spec | 2 +- .../api-ms-win-core-io-l1-1-1.spec | 2 +- dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/sync.c | 19 +++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 2 +- include/winbase.h | 1 + 6 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/dlls/api-ms-win-core-io-l1-1-0/api-ms-win-core-io-l1-1-0.spec b/dlls/api-ms-win-core-io-l1-1-0/api-ms-win-core-io-l1-1-0.spec index f73e427..ea0fd94 100644 --- a/dlls/api-ms-win-core-io-l1-1-0/api-ms-win-core-io-l1-1-0.spec +++ b/dlls/api-ms-win-core-io-l1-1-0/api-ms-win-core-io-l1-1-0.spec @@ -3,5 +3,5 @@ @ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) kernel32.DeviceIoControl @ stdcall GetOverlappedResult(long ptr ptr long) kernel32.GetOverlappedResult @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) kernel32.GetQueuedCompletionStatus -@ stub GetQueuedCompletionStatusEx +@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) kernel32.GetQueuedCompletionStatusEx @ stdcall PostQueuedCompletionStatus(long long ptr ptr) kernel32.PostQueuedCompletionStatus diff --git a/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec b/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec index 73aae1a..907c0b4 100644 --- a/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec +++ b/dlls/api-ms-win-core-io-l1-1-1/api-ms-win-core-io-l1-1-1.spec @@ -6,5 +6,5 @@ @ stdcall GetOverlappedResult(long ptr ptr long) kernel32.GetOverlappedResult @ stub GetOverlappedResultEx @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) kernel32.GetQueuedCompletionStatus -@ stub GetQueuedCompletionStatusEx +@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) kernel32.GetQueuedCompletionStatusEx @ stdcall PostQueuedCompletionStatus(long long ptr ptr) kernel32.PostQueuedCompletionStatus diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 9db7d98..e17ee97 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -804,7 +804,7 @@ @ stdcall GetProfileStringA(str str str ptr long) @ stdcall GetProfileStringW(wstr wstr wstr ptr long) @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) -# @ stub GetQueuedCompletionStatusEx +@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) @ stub -i386 GetSLCallbackTarget @ stub -i386 GetSLCallbackTemplate @ stdcall GetShortPathNameA(str ptr long) diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 1345aca..67f75af 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -2389,6 +2389,25 @@ BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOf return FALSE; }
+/****************************************************************************** + * GetQueuedCompletionStatus (KERNEL32.@) + */ +BOOL WINAPI GetQueuedCompletionStatusEx( HANDLE port, OVERLAPPED_ENTRY *entries, ULONG count, + ULONG *written, DWORD timeout, BOOL alertable ) +{ + LARGE_INTEGER time; + NTSTATUS ret; + + TRACE("%p %p %u %p %u %u\n", port, entries, count, written, timeout, alertable); + + ret = NtRemoveIoCompletionEx( port, (FILE_IO_COMPLETION_INFORMATION *)entries, count, + written, get_nt_timeout( &time, timeout ), alertable ); + if (ret == STATUS_SUCCESS) return TRUE; + else if (ret == STATUS_TIMEOUT) SetLastError( WAIT_TIMEOUT ); + else if (ret == STATUS_USER_APC) SetLastError( WAIT_IO_COMPLETION ); + else SetLastError( RtlNtStatusToDosError(ret) ); + return FALSE; +}
/****************************************************************************** * PostQueuedCompletionStatus (KERNEL32.@) diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 2980576..7fa8c1d 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -645,7 +645,7 @@ # @ stub GetPublisherCacheFolder # @ stub GetPublisherRootFolder @ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) kernel32.GetQueuedCompletionStatus -@ stub GetQueuedCompletionStatusEx +@ stdcall GetQueuedCompletionStatusEx(ptr ptr long ptr long long) kernel32.GetQueuedCompletionStatusEx # @ stub GetRegistryExtensionFlags # @ stub GetRoamingLastObservedChangeTime @ stdcall GetSecurityDescriptorControl(ptr ptr ptr) advapi32.GetSecurityDescriptorControl diff --git a/include/winbase.h b/include/winbase.h index de52e5a..ea450e1 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2205,6 +2205,7 @@ WINBASEAPI INT WINAPI GetProfileStringA(LPCSTR,LPCSTR,LPCSTR,LPSTR,UINT) WINBASEAPI INT WINAPI GetProfileStringW(LPCWSTR,LPCWSTR,LPCWSTR,LPWSTR,UINT); #define GetProfileString WINELIB_NAME_AW(GetProfileString) WINBASEAPI BOOL WINAPI GetQueuedCompletionStatus(HANDLE,LPDWORD,PULONG_PTR,LPOVERLAPPED*,DWORD); +WINBASEAPI BOOL WINAPI GetQueuedCompletionStatusEx(HANDLE,OVERLAPPED_ENTRY*,ULONG,ULONG*,DWORD,BOOL); WINADVAPI BOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR_CONTROL,LPDWORD); WINADVAPI BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,LPBOOL,PACL *,LPBOOL); WINADVAPI BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID *,LPBOOL);
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=42670
Your paranoid android.
=== w8 (32 bit Windows report) ===
ntdll: file.c:441: Test failed: mismatched file size for L"WindowsUpdate.log"