[USER32] Implement the special case in CreateWindowStationW() that, when no window...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 16 Jun 2018 17:43:59 +0000 (19:43 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 19 Aug 2018 20:18:22 +0000 (22:18 +0200)
Observed via API monitoring.
This corresponds to the case where Win32k creates a window station whose name is based on the logon session identifier for the calling process.

Add also a note about the fact that we need to use a per-session-based WindowStation directory name, as done already in Win32k.

CORE-11933 and PR #621.

win32ss/user/user32/misc/winsta.c

index 24f6d89..7308ad1 100644 (file)
@@ -60,32 +60,49 @@ CreateWindowStationW(
     NTSTATUS Status;
     HWINSTA hWinSta;
     UNICODE_STRING WindowStationName;
+    // FIXME: We should cache a per-session directory (see ntuser\winsta.c!UserCreateWinstaDirectory).
     UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
     OBJECT_ATTRIBUTES ObjectAttributes;
     HANDLE hWindowStationsDir;
 
-    /* Open WindowStations directory */
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &WindowStationsDir,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
+    /*
+     * If provided, the window station name is always relative to the
+     * current user session's WindowStations directory.
+     * Otherwise (the window station name is NULL or an empty string),
+     * pass both an empty string and no WindowStations directory handle
+     * to win32k, so that it will create a window station whose name
+     * is based on the logon session identifier for the calling process.
+     */
+    if (lpwinsta && *lpwinsta)
+    {
+        /* Open WindowStations directory */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &WindowStationsDir,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+
+        Status = NtOpenDirectoryObject(&hWindowStationsDir,
+                                       DIRECTORY_CREATE_OBJECT,
+                                       &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            ERR("Failed to open WindowStations directory\n");
+            return NULL;
+        }
 
-    Status = NtOpenDirectoryObject(&hWindowStationsDir,
-                                   DIRECTORY_CREATE_OBJECT,
-                                   &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
+        RtlInitUnicodeString(&WindowStationName, lpwinsta);
+    }
+    else
     {
-        ERR("Failed to open WindowStations directory\n");
-        return NULL;
+        lpwinsta = NULL;
+        hWindowStationsDir = NULL;
     }
 
-    RtlInitUnicodeString(&WindowStationName, lpwinsta);
-
     /* Create the window station object */
     InitializeObjectAttributes(&ObjectAttributes,
-                               &WindowStationName,
-                               OBJ_CASE_INSENSITIVE,
+                               lpwinsta ? &WindowStationName : NULL,
+                               OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
                                hWindowStationsDir,
                                NULL);
 
@@ -99,7 +116,8 @@ CreateWindowStationW(
                                         dwDesiredAccess,
                                         0, 0, 0, 0, 0);
 
-    NtClose(hWindowStationsDir);
+    if (hWindowStationsDir)
+        NtClose(hWindowStationsDir);
 
     return hWinSta;
 }
@@ -349,6 +367,7 @@ OpenWindowStationW(
     NTSTATUS Status;
     HWINSTA hWinSta;
     UNICODE_STRING WindowStationName;
+    // FIXME: We should cache a per-session directory (see ntuser\winsta.c!UserCreateWinstaDirectory).
     UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
     OBJECT_ATTRIBUTES ObjectAttributes;
     HANDLE hWindowStationsDir;