Signed-off-by: Zebediah Figura z.figura12@gmail.com --- For whatever reason, on the w8 test machine, WindowsUpdate.log is virtualized, and the virtualized contents differ from those of the real file. NtQueryDirectoryFile() retrieves the size of the latter, but NtOpenFile() opens the former. Use a temporary directory to avoid any problems related to virtualization.
dlls/ntdll/tests/file.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b4223b3..2e57918 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -347,6 +347,7 @@ static void create_file_test(void)
static void open_file_test(void) { + static const WCHAR testdirW[] = {'o','p','e','n','f','i','l','e','t','e','s','t',0}; static const char testdata[] = "Hello World"; static WCHAR fooW[] = {'f','o','o',0}; NTSTATUS status; @@ -415,6 +416,27 @@ static void open_file_test(void) FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE ); ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status ); CloseHandle( handle ); + CloseHandle( dir ); + + GetTempPathW( MAX_PATH, path ); + lstrcatW( path, testdirW ); + CreateDirectoryW( path, NULL ); + + pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL ); + attr.RootDirectory = NULL; + status = pNtOpenFile( &dir, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io, + FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT ); + ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status ); + pRtlFreeUnicodeString( &nameW ); + + GetTempFileNameW( path, fooW, 0, tmpfile ); + file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() ); + numbytes = 0xdeadbeef; + ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL ); + ok( ret, "WriteFile failed with error %u\n", GetLastError() ); + ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" ); + CloseHandle( file );
/* try open by file id */
@@ -436,15 +458,7 @@ static void open_file_test(void) FILE_SHARE_READ, FILE_OPEN_BY_FILE_ID | ((info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? FILE_DIRECTORY_FILE : 0) ); - ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED || status == STATUS_NOT_IMPLEMENTED || status == STATUS_SHARING_VIOLATION, - "open %s failed %x\n", wine_dbgstr_w(info->FileName), status ); - if (status == STATUS_NOT_IMPLEMENTED) - { - win_skip( "FILE_OPEN_BY_FILE_ID not supported\n" ); - break; - } - if (status == STATUS_SHARING_VIOLATION) - trace( "%s is currently open\n", wine_dbgstr_w(info->FileName) ); + ok( status == STATUS_SUCCESS, "open %s failed %x\n", wine_dbgstr_w(info->FileName), status ); if (!status) { BYTE buf[sizeof(FILE_ALL_INFORMATION) + MAX_PATH * sizeof(WCHAR)]; @@ -480,18 +494,7 @@ static void open_file_test(void) CloseHandle( dir ); CloseHandle( root );
- GetTempPathW( MAX_PATH, path ); - GetTempFileNameW( path, fooW, 0, tmpfile ); pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL ); - - file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 ); - ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() ); - numbytes = 0xdeadbeef; - ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL ); - ok( ret, "WriteFile failed with error %u\n", GetLastError() ); - ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" ); - CloseHandle( file ); - attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &nameW; @@ -547,6 +550,7 @@ static void open_file_test(void) CloseHandle( file ); CloseHandle( root ); DeleteFileW( tmpfile ); + RemoveDirectoryW( path ); }
static void delete_file_test(void)
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 2e57918..fd56bc2 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; @@ -885,6 +866,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; @@ -897,13 +881,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 ); @@ -915,7 +898,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 ); @@ -964,14 +949,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 );
@@ -983,27 +969,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 ); @@ -1038,14 +1026,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 fd56bc2..b66b857 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -897,203 +897,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)
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 b66b857..4d920d9 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -864,7 +864,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; @@ -872,9 +872,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 );
@@ -890,15 +895,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; @@ -907,6 +914,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, @@ -1077,6 +1091,7 @@ todo_wine
CloseHandle( server ); CloseHandle( client ); + pNtClose( h ); }
static void test_file_full_size_information(void) @@ -2925,24 +2940,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; @@ -4470,7 +4467,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();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/file.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ include/winternl.h | 7 ++++ 2 files changed, 93 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 4d920d9..aaf6d61 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*); @@ -864,9 +865,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; @@ -880,6 +889,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 );
@@ -896,6 +908,79 @@ 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 ); + + SleepEx( 1, TRUE ); + pNtClose( h ); }
@@ -4450,6 +4535,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);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/sync.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5e7c463..b7cbff3 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) @@ -1243,6 +1244,7 @@ @ stub ZwReleaseProcessMutant @ stdcall -private ZwReleaseSemaphore(long long ptr) NtReleaseSemaphore @ stdcall -private ZwRemoveIoCompletion(ptr ptr ptr ptr ptr) NtRemoveIoCompletion +@ stdcall -private ZwRemoveIoCompletionEx(ptr ptr long ptr ptr long) NtRemoveIoCompletionEx # @ stub ZwRemoveProcessDebug @ stdcall -private ZwRenameKey(long ptr) NtRenameKey @ stdcall -private ZwReplaceKey(ptr long ptr) NtReplaceKey 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 | 111 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 33cae4b..eb27d55 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,114 @@ 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 failed\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(!(ULONG)entries[0].Internal, "wrong internal %#x\n", (ULONG)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 failed\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(!(ULONG)entries[0].Internal, "wrong internal %#x\n", (ULONG)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(!(ULONG)entries[1].Internal, "wrong internal %#x\n", (ULONG)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) /* Vista */, "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"); + + user_apc_ran = FALSE; + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + + ret = PostQueuedCompletionStatus( port, 123, 456, &ovl ); + ok(ret, "PostQueuedCompletionStatus failed: %u\n", GetLastError()); + + ret = pGetQueuedCompletionStatusEx( port, entries, 2, &count, 0, TRUE ); + ok(ret, "GetQueuedCompletionStatusEx failed\n"); + ok(count == 1, "wrong count %u\n", count); + ok(!user_apc_ran, "user APC should not have run\n"); + + SleepEx(0, TRUE); + + CloseHandle( port ); +} + START_TEST(file) { InitFunctionPointers(); @@ -5046,4 +5156,5 @@ START_TEST(file) test_GetFinalPathNameByHandleW(); test_SetFileInformationByHandle(); test_GetFileAttributesExW(); + test_post_completion(); }
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..517ee3f 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -2389,6 +2389,25 @@ BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOf return FALSE; }
+/****************************************************************************** + * GetQueuedCompletionStatusEx (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);