From c0ac2afb19ca6e5ad3999f47744b9210c22fa758 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Thu, 21 May 2015 17:19:51 +0900
Subject: [PATCH] server: Create the null device and its symlink.

---
 dlls/ntdll/tests/om.c | 20 ++++++--------------
 server/device.c       | 16 ++++++++++++++++
 server/directory.c    | 11 ++++++++++-
 server/file.h         |  7 +++++++
 server/object.h       |  4 ----
 5 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index 71380a73292..fa6f2c33466 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -658,9 +658,9 @@ static void test_symboliclink(void)
 
     pRtlCreateUnicodeStringFromAsciiz(&str, "test-link\\NUL");
     status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0);
-    todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    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);
-    todo_wine ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
+    ok(status == STATUS_SUCCESS, "Failed to open NUL device(%08x)\n", status);
     pRtlFreeUnicodeString(&str);
 
     pNtClose(h);
@@ -1053,31 +1053,24 @@ static void test_null_device(void)
     pRtlCreateUnicodeStringFromAsciiz(&str, "\\Device\\Null");
     InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
     status = pNtOpenSymbolicLinkObject(&null, SYMBOLIC_LINK_QUERY, &attr);
-    todo_wine
     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);
-    todo_wine
     ok(status == STATUS_SUCCESS,
        "expected STATUS_SUCCESS, got %08x\n", status);
-    if (status != STATUS_SUCCESS)
-    {
-        skip("opening \\Device\\Null failed, skipping read/write tests\n");
-        goto out;
-    }
 
     SetLastError(0xdeadbeef);
     ret = WriteFile(null, buf, sizeof(buf), &num_bytes, NULL);
-    ok(!ret, "WriteFile unexpectedly succeeded\n");
-    ok(GetLastError() == ERROR_INVALID_PARAMETER,
+    todo_wine ok(!ret, "WriteFile unexpectedly succeeded\n");
+    todo_wine 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,
+    todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
 
     num_bytes = 0xdeadbeef;
@@ -1109,12 +1102,11 @@ static void test_null_device(void)
         ret = GetOverlappedResult(null, &ov, &num_bytes, TRUE);
         ok(!ret, "GetOverlappedResult unexpectedly succeeded\n");
     }
-    ok(GetLastError() == ERROR_HANDLE_EOF,
+    todo_wine ok(GetLastError() == ERROR_HANDLE_EOF,
        "expected ERROR_HANDLE_EOF, got %u\n", GetLastError());
 
     pNtClose(null);
 
-out:
     null = CreateFileA("\\\\.\\Null", GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
diff --git a/server/device.c b/server/device.c
index de11a9aaa91..dc0325ef797 100644
--- a/server/device.c
+++ b/server/device.c
@@ -534,6 +534,22 @@ static struct device *create_device( struct directory *root, const struct unicod
     return device;
 }
 
+struct device *create_unix_device( struct directory *root, const struct unicode_str *name,
+                                   const char *unix_path )
+{
+    struct device *device;
+
+    if ((device = create_named_object_dir( root, name, 0, &device_ops )))
+    {
+        device->unix_path = strdup( unix_path );
+        device->manager = NULL;  /* no manager, requests go straight to the Unix device */
+        list_init( &device->files );
+        make_object_static( &device->obj );
+    }
+    return device;
+
+}
+
 /* terminate requests when the underlying device is deleted */
 static void delete_file( struct device_file *file )
 {
diff --git a/server/directory.c b/server/directory.c
index 7c5e7db0eb9..471b8443343 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -366,6 +366,7 @@ void init_directories(void)
     static const WCHAR dir_globalW[] = {'\\','?','?'};
     static const WCHAR dir_driverW[] = {'D','r','i','v','e','r'};
     static const WCHAR dir_deviceW[] = {'D','e','v','i','c','e'};
+    static const WCHAR dir_nullW[] = {'\\','D','e','v','i','c','e','\\','N','u','l','l'};
     static const WCHAR dir_basenamedW[] = {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s'};
     static const WCHAR dir_named_pipeW[] = {'\\','D','e','v','i','c','e','\\','N','a','m','e','d','P','i','p','e'};
     static const WCHAR dir_mailslotW[] = {'\\','D','e','v','i','c','e','\\','M','a','i','l','S','l','o','t'};
@@ -375,6 +376,7 @@ void init_directories(void)
     static const struct unicode_str dir_global_str = {dir_globalW, sizeof(dir_globalW)};
     static const struct unicode_str dir_driver_str = {dir_driverW, sizeof(dir_driverW)};
     static const struct unicode_str dir_device_str = {dir_deviceW, sizeof(dir_deviceW)};
+    static const struct unicode_str dir_null_str   = {dir_nullW, sizeof(dir_nullW)};
     static const struct unicode_str dir_basenamed_str = {dir_basenamedW, sizeof(dir_basenamedW)};
     static const struct unicode_str dir_named_pipe_str = {dir_named_pipeW, sizeof(dir_named_pipeW)};
     static const struct unicode_str dir_mailslot_str = {dir_mailslotW, sizeof(dir_mailslotW)};
@@ -386,6 +388,7 @@ void init_directories(void)
     static const WCHAR link_dosdevW[] = {'D','o','s','D','e','v','i','c','e','s'};
     static const WCHAR link_globalW[] = {'G','l','o','b','a','l'};
     static const WCHAR link_localW[]  = {'L','o','c','a','l'};
+    static const WCHAR link_nulW[]    = {'N','U','L'};
     static const WCHAR link_pipeW[]   = {'P','I','P','E'};
     static const WCHAR link_mailslotW[] = {'M','A','I','L','S','L','O','T'};
     static const WCHAR link_0W[]      = {'0'};
@@ -394,6 +397,7 @@ void init_directories(void)
     static const struct unicode_str link_dosdev_str = {link_dosdevW, sizeof(link_dosdevW)};
     static const struct unicode_str link_global_str = {link_globalW, sizeof(link_globalW)};
     static const struct unicode_str link_local_str  = {link_localW, sizeof(link_localW)};
+    static const struct unicode_str link_nul_str    = {link_nulW, sizeof(link_nulW)};
     static const struct unicode_str link_pipe_str   = {link_pipeW, sizeof(link_pipeW)};
     static const struct unicode_str link_mailslot_str = {link_mailslotW, sizeof(link_mailslotW)};
     static const struct unicode_str link_0_str      = {link_0W, sizeof(link_0W)};
@@ -403,8 +407,10 @@ void init_directories(void)
     /* devices */
     static const WCHAR named_pipeW[] = {'N','a','m','e','d','P','i','p','e'};
     static const WCHAR mailslotW[] = {'M','a','i','l','S','l','o','t'};
+    static const WCHAR nullW[] = {'N','u','l','l'};
     static const struct unicode_str named_pipe_str = {named_pipeW, sizeof(named_pipeW)};
     static const struct unicode_str mailslot_str = {mailslotW, sizeof(mailslotW)};
+    static const struct unicode_str null_str = {nullW, sizeof(nullW)};
 
     /* events */
     static const WCHAR event_low_memW[] = {'L','o','w','M','e','m','o','r','y','C','o','n','d','i','t','i','o','n'};
@@ -426,7 +432,7 @@ void init_directories(void)
     static const struct unicode_str keyed_event_crit_sect_str = {keyed_event_crit_sectW, sizeof(keyed_event_crit_sectW)};
 
     struct directory *dir_driver, *dir_device, *dir_global, *dir_basenamed, *dir_sessions, *dir_kernel;
-    struct symlink *link_dosdev, *link_global1, *link_global2, *link_local, *link_pipe, *link_mailslot, *link_0, *link_session;
+    struct symlink *link_dosdev, *link_global1, *link_global2, *link_local, *link_nul, *link_pipe, *link_mailslot, *link_0, *link_session;
     struct keyed_event *keyed_event;
     unsigned int i;
 
@@ -447,12 +453,14 @@ void init_directories(void)
     /* devices */
     create_named_pipe_device( dir_device, &named_pipe_str );
     create_mailslot_device( dir_device, &mailslot_str );
+    create_unix_device( dir_device, &null_str, "/dev/null" );
 
     /* symlinks */
     link_dosdev    = create_symlink( root_directory, &link_dosdev_str, 0, &dir_global_str );
     link_global1   = create_symlink( dir_global, &link_global_str, 0, &dir_global_str );
     link_global2   = create_symlink( dir_basenamed, &link_global_str, 0, &dir_basenamed_str );
     link_local     = create_symlink( dir_basenamed, &link_local_str, 0, &dir_basenamed_str );
+    link_nul       = create_symlink( dir_global, &link_nul_str, 0, &dir_null_str );
     link_pipe      = create_symlink( dir_global, &link_pipe_str, 0, &dir_named_pipe_str );
     link_mailslot  = create_symlink( dir_global, &link_mailslot_str, 0, &dir_mailslot_str );
     link_0         = create_symlink( dir_sessions, &link_0_str, 0, &dir_basenamed_str );
@@ -461,6 +469,7 @@ void init_directories(void)
     make_object_static( (struct object *)link_global1 );
     make_object_static( (struct object *)link_global2 );
     make_object_static( (struct object *)link_local );
+    make_object_static( (struct object *)link_nul );
     make_object_static( (struct object *)link_pipe );
     make_object_static( (struct object *)link_mailslot );
     make_object_static( (struct object *)link_0 );
diff --git a/server/file.h b/server/file.h
index 603b6868a2d..b5e0ca71b56 100644
--- a/server/file.h
+++ b/server/file.h
@@ -138,6 +138,13 @@ extern obj_handle_t open_mapping_file( struct process *process, struct mapping *
 extern struct mapping *grab_mapping_unless_removable( struct mapping *mapping );
 extern int get_page_size(void);
 
+/* device functions */
+
+extern void create_named_pipe_device( struct directory *root, const struct unicode_str *name );
+extern void create_mailslot_device( struct directory *root, const struct unicode_str *name );
+extern struct device *create_unix_device( struct directory *root, const struct unicode_str *name,
+                                          const char *unix_path );
+
 /* change notification functions */
 
 extern void do_change_notify( int unix_fd );
diff --git a/server/object.h b/server/object.h
index 00bef385973..b59811f44b0 100644
--- a/server/object.h
+++ b/server/object.h
@@ -224,10 +224,6 @@ extern void init_directories(void);
 extern struct symlink *create_symlink( struct directory *root, const struct unicode_str *name,
                                        unsigned int attr, const struct unicode_str *target );
 
-/* devices */
-extern void create_named_pipe_device( struct directory *root, const struct unicode_str *name );
-extern void create_mailslot_device( struct directory *root, const struct unicode_str *name );
-
 /* global variables */
 
   /* command-line options */
-- 
GitLab