[ROSTESTS] Add an interactive test for window stations. See also PR #621.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 17 Jun 2018 19:39:44 +0000 (21:39 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 22 Jul 2018 17:03:17 +0000 (19:03 +0200)
modules/rostests/win32/user32/CMakeLists.txt
modules/rostests/win32/user32/winstation/CMakeLists.txt [new file with mode: 0644]
modules/rostests/win32/user32/winstation/resource.h [new file with mode: 0644]
modules/rostests/win32/user32/winstation/winstation.c [new file with mode: 0644]
modules/rostests/win32/user32/winstation/winstation.rc [new file with mode: 0644]

index 8298a91..d1d8397 100644 (file)
@@ -1,3 +1,4 @@
 add_subdirectory(biditext)
 add_subdirectory(paintdesktop)
 add_subdirectory(sysicon)
 add_subdirectory(biditext)
 add_subdirectory(paintdesktop)
 add_subdirectory(sysicon)
+add_subdirectory(winstation)
diff --git a/modules/rostests/win32/user32/winstation/CMakeLists.txt b/modules/rostests/win32/user32/winstation/CMakeLists.txt
new file mode 100644 (file)
index 0000000..88d6ea8
--- /dev/null
@@ -0,0 +1,5 @@
+
+add_executable(winstation winstation.c winstation.rc)
+set_module_type(winstation win32gui UNICODE)
+add_importlibs(winstation user32 msvcrt kernel32)
+add_rostests_file(TARGET winstation SUBDIR suppl)
diff --git a/modules/rostests/win32/user32/winstation/resource.h b/modules/rostests/win32/user32/winstation/resource.h
new file mode 100644 (file)
index 0000000..795deab
--- /dev/null
@@ -0,0 +1,2 @@
+#define IDD_ABOUTBOX    101
+#define IDC_STATIC      -1
diff --git a/modules/rostests/win32/user32/winstation/winstation.c b/modules/rostests/win32/user32/winstation/winstation.c
new file mode 100644 (file)
index 0000000..f2434db
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * PROJECT:     ReactOS Tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Tests some aspects of the Window Station API.
+ * COPYRIGHT:   Copyright 2018 Hermes Belusca-Maito
+ */
+
+#include <windef.h>
+#include <winbase.h>
+#include <wincon.h>
+#include <winuser.h>
+
+#include <strsafe.h>
+
+#include "resource.h"
+
+
+/*
+ * Logging facilities
+ */
+
+typedef struct _LOG_FILE
+{
+    HANDLE  hLogFile;
+    PWCHAR  pBuffer;
+    size_t  cbBufferSize;
+} LOG_FILE, *PLOG_FILE;
+
+BOOL
+InitLog(
+    OUT PLOG_FILE LogFile,
+    IN LPCWSTR LogFileName,
+    IN PWCHAR pBuffer,
+    IN size_t cbBufferSize)
+{
+    HANDLE hLogFile;
+
+    ZeroMemory(LogFile, sizeof(*LogFile));
+
+    hLogFile = CreateFileW(LogFileName,
+                           GENERIC_WRITE,
+                           FILE_SHARE_READ,
+                           NULL,
+                           OPEN_ALWAYS,
+                           FILE_ATTRIBUTE_NORMAL,
+                           NULL);
+    if (hLogFile == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    LogFile->hLogFile = hLogFile;
+    LogFile->pBuffer  = pBuffer;
+    LogFile->cbBufferSize = cbBufferSize;
+
+    return TRUE;
+}
+
+VOID
+CloseLog(
+    IN PLOG_FILE LogFile)
+{
+    CloseHandle(LogFile->hLogFile);
+    ZeroMemory(LogFile, sizeof(*LogFile));
+}
+
+BOOL
+WriteToLog(
+    IN PLOG_FILE LogFile,
+    IN LPCVOID Buffer,
+    IN DWORD dwBufferSize)
+{
+    return WriteFile(LogFile->hLogFile,
+                     Buffer,
+                     dwBufferSize,
+                     &dwBufferSize, NULL);
+}
+
+BOOL
+WriteToLogPuts(
+    IN PLOG_FILE LogFile,
+    IN LPCWSTR String)
+{
+    return WriteToLog(LogFile,
+                      String,
+                      wcslen(String) * sizeof(WCHAR));
+}
+
+BOOL
+WriteToLogPrintfV(
+    IN PLOG_FILE LogFile,
+    IN LPCWSTR Format,
+    IN va_list args)
+{
+    StringCbVPrintfW(LogFile->pBuffer,
+                     LogFile->cbBufferSize,
+                     Format, args);
+
+    return WriteToLog(LogFile,
+                      LogFile->pBuffer,
+                      wcslen(LogFile->pBuffer) * sizeof(WCHAR));
+}
+
+BOOL
+WriteToLogPrintf(
+    IN PLOG_FILE LogFile,
+    IN LPCWSTR Format,
+    ...)
+{
+    BOOL bRet;
+    va_list args;
+
+    va_start(args, Format);
+    bRet = WriteToLogPrintfV(LogFile, Format, args);
+    va_end(args);
+
+    return bRet;
+}
+
+
+/*
+ * Window Station tests
+ */
+
+BOOL
+CALLBACK
+EnumDesktopProc(
+    IN LPWSTR lpszDesktop,
+    IN LPARAM lParam)
+{
+    PLOG_FILE LogFile = (PLOG_FILE)lParam;
+
+    WriteToLogPrintf(LogFile, L" :: Found desktop '%s'\r\n", lpszDesktop);
+
+    /* Continue the enumeration */
+    return TRUE;
+}
+
+/*
+ * This test inspects the same window station aspects that are used in the
+ * Cygwin fhandler_console.cc!fhandler_console::create_invisible_console()
+ * function, see:
+ *   https://github.com/cygwin/cygwin/blob/7b9bfb4136f23655e243bab89fb62b04bdbacc7f/winsup/cygwin/fhandler_console.cc#L2494
+ */
+VOID DoTest(HWND hWnd)
+{
+    HWINSTA hWinSta;
+    LPCWSTR lpszWinSta = L"Test-WinSta";
+    BOOL bIsItOk;
+    LOG_FILE LogFile;
+    WCHAR szBuffer[2048];
+
+    bIsItOk = InitLog(&LogFile, L"test_winsta.log", szBuffer, sizeof(szBuffer));
+    if (!bIsItOk)
+    {
+        MessageBoxW(hWnd, L"Could not create the log file, stopping test now...", L"Error", MB_ICONERROR | MB_OK);
+        return;
+    }
+
+    /* Switch output to UTF-16 (little endian) */
+    WriteToLog(&LogFile, "\xFF\xFE", 2);
+
+    WriteToLogPrintf(&LogFile, L"Creating Window Station '%s'\r\n", lpszWinSta);
+    hWinSta = CreateWindowStationW(lpszWinSta, 0, WINSTA_ALL_ACCESS, NULL);
+    WriteToLogPrintf(&LogFile, L"--> Returned handle 0x%p ; last error: %lu\r\n", hWinSta, GetLastError());
+
+    if (!hWinSta)
+    {
+        WriteToLogPuts(&LogFile, L"\r\nHandle is NULL, cannot proceed further, stopping the test!\r\n\r\n");
+        return;
+    }
+
+    WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (before process attach)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile);
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    WriteToLogPrintf(&LogFile, L"Setting current process to Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = SetProcessWindowStation(hWinSta);
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (after process attach, before allocating console)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile);
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    WriteToLogPrintf(&LogFile, L"Allocating a new console on Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = AllocConsole();
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (after allocating console)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile);
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    WriteToLogPrintf(&LogFile, L"Now closing Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta);
+    bIsItOk = CloseWindowStation(hWinSta);
+    WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n\r\n",
+                     (bIsItOk ? L"success" : L"failure"), GetLastError());
+
+    CloseLog(&LogFile);
+}
+
+INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    UNREFERENCED_PARAMETER(lParam);
+    switch (message)
+    {
+    case WM_INITDIALOG:
+        return (INT_PTR)TRUE;
+
+    case WM_COMMAND:
+        switch (LOWORD(wParam))
+        {
+            case IDOK:
+                DoTest(hDlg);
+                EndDialog(hDlg, LOWORD(wParam));
+                break;
+
+            case IDCANCEL:
+            default:
+                EndDialog(hDlg, LOWORD(wParam));
+                break;
+        }
+        return (INT_PTR)TRUE;
+    }
+    return (INT_PTR)FALSE;
+}
+
+int APIENTRY wWinMain(HINSTANCE hInstance,
+                      HINSTANCE hPrevInstance,
+                      LPWSTR    lpCmdLine,
+                      int       nCmdShow)
+{
+    UNREFERENCED_PARAMETER(hPrevInstance);
+    UNREFERENCED_PARAMETER(lpCmdLine);
+
+    return DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_ABOUTBOX), NULL, About);
+}
diff --git a/modules/rostests/win32/user32/winstation/winstation.rc b/modules/rostests/win32/user32/winstation/winstation.rc
new file mode 100644 (file)
index 0000000..0e9e05f
--- /dev/null
@@ -0,0 +1,15 @@
+
+#include <windef.h>
+#include <winuser.h>
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Test WindowStation"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+    CTEXT           "Test for WindowStation\nTo start the test, press on the button below.",IDC_STATIC,7,7,156,20,SS_NOPREFIX
+    DEFPUSHBUTTON   "Start!",IDOK,7,32,156,23,WS_GROUP
+END