[NTDLL_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / ntdll / om.c
index cca05c9..65e9260 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include "ntdll_test.h"
-#include "winternl.h"
+#include "wine/winternl.h"
 #include "stdio.h"
 #include "winnt.h"
 #include "stdlib.h"
@@ -54,6 +54,7 @@ static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJE
 static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
 static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
 static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
 
 #define KEYEDEVENT_WAIT       0x0001
 #define KEYEDEVENT_WAKE       0x0002
@@ -150,7 +151,7 @@ static void test_namespace_pipe(void)
 
     pRtlInitUnicodeString(&str, buffer3);
     InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
     ok(status == STATUS_OBJECT_PATH_NOT_FOUND ||
        status == STATUS_PIPE_NOT_AVAILABLE ||
        status == STATUS_OBJECT_NAME_INVALID || /* vista */
@@ -159,7 +160,7 @@ static void test_namespace_pipe(void)
 
     pRtlInitUnicodeString(&str, buffer4);
     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
     ok(status == STATUS_OBJECT_NAME_NOT_FOUND ||
        status == STATUS_OBJECT_NAME_INVALID, /* vista */
         "NtOpenFile should have failed with STATUS_OBJECT_NAME_NOT_FOUND got(%08x)\n", status);
@@ -657,8 +658,10 @@ static void test_symboliclink(void)
     pRtlFreeUnicodeString(&target);
 
     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
-    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
-    todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
+    ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_DIRECTORY_FILE);
+    ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
     pRtlFreeUnicodeString(&str);
 
     pNtClose(h);
@@ -672,12 +675,16 @@ static void test_query_object(void)
                                  '\\','t','e','s','t','_','e','v','e','n','t'};
     static const WCHAR type_event[] = {'E','v','e','n','t'};
     static const WCHAR type_file[] = {'F','i','l','e'};
+    static const WCHAR type_iocompletion[] = {'I','o','C','o','m','p','l','e','t','i','o','n'};
+    static const WCHAR type_directory[] = {'D','i','r','e','c','t','o','r','y'};
+    static const WCHAR type_section[] = {'S','e','c','t','i','o','n'};
     HANDLE handle;
     char buffer[1024];
     NTSTATUS status;
     ULONG len, expected_len;
     UNICODE_STRING *str;
-    char dir[MAX_PATH];
+    char dir[MAX_PATH], tmp_path[MAX_PATH], file1[MAX_PATH + 16];
+    LARGE_INTEGER size;
 
     handle = CreateEventA( NULL, FALSE, FALSE, "test_event" );
 
@@ -688,8 +695,8 @@ static void test_query_object(void)
 
     len = 0;
     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, 0, &len );
-    todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
-    todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
+    ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
 
     len = 0;
     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(UNICODE_STRING), &len );
@@ -698,8 +705,8 @@ static void test_query_object(void)
 
     len = 0;
     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(OBJECT_TYPE_INFORMATION), &len );
-    todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
-    todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
+    ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
 
     len = 0;
     status = pNtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
@@ -720,17 +727,17 @@ static void test_query_object(void)
     len = 0;
     memset( buffer, 0, sizeof(buffer) );
     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
-    todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
-    todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
     str = (UNICODE_STRING *)buffer;
-    todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR), "unexpected len %u\n", len );
-    todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_event, sizeof(type_file) ),
+    ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR), "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_event, sizeof(type_event) ),
                   "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
 
     len -= sizeof(WCHAR);
     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, len, &len );
-    todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
-    todo_wine ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryObject failed %x\n", status );
+    ok( len >= sizeof(OBJECT_TYPE_INFORMATION) + sizeof(type_event) + sizeof(WCHAR), "unexpected len %u\n", len );
 
     pNtClose( handle );
 
@@ -775,15 +782,75 @@ static void test_query_object(void)
     len = 0;
     memset( buffer, 0, sizeof(buffer) );
     status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
-    todo_wine ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
-    todo_wine ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
     str = (UNICODE_STRING *)buffer;
     expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
-    todo_wine ok( len >= expected_len, "unexpected len %u\n", len );
-    todo_wine ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
                   "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
 
     pNtClose( handle );
+
+    GetTempPathA(MAX_PATH, tmp_path);
+    GetTempFileNameA(tmp_path, "foo", 0, file1);
+    handle = CreateFileA(file1, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_file, sizeof(type_file) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    DeleteFileA( file1 );
+    pNtClose( handle );
+
+    status = pNtCreateIoCompletion( &handle, IO_COMPLETION_ALL_ACCESS, NULL, 0 );
+    ok( status == STATUS_SUCCESS, "NtCreateIoCompletion failed %x\n", status);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_iocompletion, sizeof(type_iocompletion) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
+
+    status = pNtCreateDirectoryObject( &handle, DIRECTORY_QUERY, NULL );
+    ok(status == STATUS_SUCCESS, "Failed to create Directory %08x\n", status);
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_directory, sizeof(type_directory) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
+
+    size.u.LowPart = 256;
+    size.u.HighPart = 0;
+    status = pNtCreateSection( &handle, SECTION_MAP_WRITE, NULL, &size, PAGE_READWRITE, SEC_COMMIT, 0 );
+    ok( status == STATUS_SUCCESS , "NtCreateSection returned %x\n", status );
+    len = 0;
+    memset( buffer, 0, sizeof(buffer) );
+    status = pNtQueryObject( handle, ObjectTypeInformation, buffer, sizeof(buffer), &len );
+    ok( status == STATUS_SUCCESS, "NtQueryObject failed %x\n", status );
+    ok( len > sizeof(OBJECT_TYPE_INFORMATION), "unexpected len %u\n", len );
+    str = (UNICODE_STRING *)buffer;
+    expected_len = sizeof(OBJECT_TYPE_INFORMATION) + str->Length + sizeof(WCHAR);
+    ok( len >= expected_len, "unexpected len %u\n", len );
+    ok( str->Buffer && !memcmp( str->Buffer, type_section, sizeof(type_section) ),
+                  "wrong/bad type name %s (%p)\n", wine_dbgstr_w(str->Buffer), str->Buffer );
+    pNtClose( handle );
 }
 
 static void test_type_mismatch(void)
@@ -835,14 +902,14 @@ static void test_event(void)
     status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
     ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
 
-    status = pNtClose(Event);
+    pNtClose(Event);
 
     status = pNtQueryEvent(Event2, EventBasicInformation, &info, sizeof(info), NULL);
     ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
     ok( info.EventType == 1 && info.EventState == 0,
         "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
 
-    status = pNtClose(Event2);
+    pNtClose(Event2);
 }
 
 static const WCHAR keyed_nameW[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',
@@ -1032,6 +1099,97 @@ static void test_keyed_events(void)
     NtClose( event );
 }
 
+static void test_null_device(void)
+{
+    OBJECT_ATTRIBUTES attr;
+    IO_STATUS_BLOCK iosb;
+    UNICODE_STRING str;
+    NTSTATUS status;
+    DWORD num_bytes;
+    OVERLAPPED ov;
+    char buf[64];
+    HANDLE null;
+    BOOL ret;
+
+    memset(buf, 0xAA, sizeof(buf));
+    memset(&ov, 0, sizeof(ov));
+    ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+
+    pRtlCreateUnicodeStringFromAsciiz(&str, "\\Device\\Null");
+    InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
+    status = pNtOpenSymbolicLinkObject(&null, SYMBOLIC_LINK_QUERY, &attr);
+    ok(status == STATUS_OBJECT_TYPE_MISMATCH,
+       "expected STATUS_OBJECT_TYPE_MISMATCH, got %08x\n", status);
+
+    status = pNtOpenFile(&null, GENERIC_READ | GENERIC_WRITE, &attr, &iosb,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE, 0);
+    ok(status == STATUS_SUCCESS,
+       "expected STATUS_SUCCESS, got %08x\n", status);
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(null, buf, sizeof(buf), &num_bytes, NULL);
+    ok(!ret, "WriteFile unexpectedly succeeded\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER,
+       "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = ReadFile(null, buf, sizeof(buf), &num_bytes, NULL);
+    ok(!ret, "ReadFile unexpectedly succeeded\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER,
+       "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
+
+    num_bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(null, buf, sizeof(buf), &num_bytes, &ov);
+    if (ret || GetLastError() != ERROR_IO_PENDING)
+    {
+        ok(ret, "WriteFile failed with error %u\n", GetLastError());
+    }
+    else
+    {
+        num_bytes = 0xdeadbeef;
+        ret = GetOverlappedResult(null, &ov, &num_bytes, TRUE);
+        ok(ret, "GetOverlappedResult failed with error %u\n", GetLastError());
+    }
+    ok(num_bytes == sizeof(buf), "expected num_bytes = %u, got %u\n",
+       (DWORD)sizeof(buf), num_bytes);
+
+    num_bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadFile(null, buf, sizeof(buf), &num_bytes, &ov);
+    if (ret || GetLastError() != ERROR_IO_PENDING)
+    {
+        ok(!ret, "ReadFile unexpectedly succeeded\n");
+    }
+    else
+    {
+        num_bytes = 0xdeadbeef;
+        ret = GetOverlappedResult(null, &ov, &num_bytes, TRUE);
+        ok(!ret, "GetOverlappedResult unexpectedly succeeded\n");
+    }
+    ok(GetLastError() == ERROR_HANDLE_EOF,
+       "expected ERROR_HANDLE_EOF, got %u\n", GetLastError());
+
+    pNtClose(null);
+
+    null = CreateFileA("\\\\.\\Null", GENERIC_READ | GENERIC_WRITE,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(null == INVALID_HANDLE_VALUE, "CreateFileA unexpectedly succeeded\n");
+    ok(GetLastError() == ERROR_FILE_NOT_FOUND,
+       "expected ERROR_FILE_NOT_FOUND, got %u\n", GetLastError());
+
+    null = CreateFileA("\\\\.\\Device\\Null", GENERIC_READ | GENERIC_WRITE,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(null == INVALID_HANDLE_VALUE, "CreateFileA unexpectedly succeeded\n");
+    ok(GetLastError() == ERROR_PATH_NOT_FOUND,
+       "expected ERROR_PATH_NOT_FOUND, got %u\n", GetLastError());
+
+    pRtlFreeUnicodeString(&str);
+    CloseHandle(ov.hEvent);
+}
+
 START_TEST(om)
 {
     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -1071,6 +1229,7 @@ START_TEST(om)
     pNtOpenKeyedEvent       =  (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
     pNtWaitForKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
     pNtReleaseKeyedEvent    =  (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
+    pNtCreateIoCompletion   =  (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
 
     test_case_sensitive();
     test_namespace_pipe();
@@ -1080,8 +1239,6 @@ START_TEST(om)
     test_query_object();
     test_type_mismatch();
     test_event();
-    if (winetest_interactive)
-        test_keyed_events();
-    else
-        skip("Skipping test_keyed_events(). ROSTESTS-118.\n");
+    test_keyed_events();
+    test_null_device();
 }