1 /* 2 * PROJECT: ReactOS Tests 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Tests some aspects of the Window Station API. 5 * COPYRIGHT: Copyright 2018 Hermes Belusca-Maito 6 */ 7 8 #include <windef.h> 9 #include <winbase.h> 10 #include <wincon.h> 11 #include <winuser.h> 12 13 #include <strsafe.h> 14 15 #include "resource.h" 16 17 18 /* 19 * Logging facilities 20 */ 21 22 typedef struct _LOG_FILE 23 { 24 HANDLE hLogFile; 25 PWCHAR pBuffer; 26 size_t cbBufferSize; 27 } LOG_FILE, *PLOG_FILE; 28 29 BOOL 30 InitLog( 31 OUT PLOG_FILE LogFile, 32 IN LPCWSTR LogFileName, 33 IN PWCHAR pBuffer, 34 IN size_t cbBufferSize) 35 { 36 HANDLE hLogFile; 37 38 ZeroMemory(LogFile, sizeof(*LogFile)); 39 40 hLogFile = CreateFileW(LogFileName, 41 GENERIC_WRITE, 42 FILE_SHARE_READ, 43 NULL, 44 OPEN_ALWAYS, 45 FILE_ATTRIBUTE_NORMAL, 46 NULL); 47 if (hLogFile == INVALID_HANDLE_VALUE) 48 return FALSE; 49 50 LogFile->hLogFile = hLogFile; 51 LogFile->pBuffer = pBuffer; 52 LogFile->cbBufferSize = cbBufferSize; 53 54 return TRUE; 55 } 56 57 VOID 58 CloseLog( 59 IN PLOG_FILE LogFile) 60 { 61 CloseHandle(LogFile->hLogFile); 62 ZeroMemory(LogFile, sizeof(*LogFile)); 63 } 64 65 BOOL 66 WriteToLog( 67 IN PLOG_FILE LogFile, 68 IN LPCVOID Buffer, 69 IN DWORD dwBufferSize) 70 { 71 return WriteFile(LogFile->hLogFile, 72 Buffer, 73 dwBufferSize, 74 &dwBufferSize, NULL); 75 } 76 77 BOOL 78 WriteToLogPuts( 79 IN PLOG_FILE LogFile, 80 IN LPCWSTR String) 81 { 82 return WriteToLog(LogFile, 83 String, 84 wcslen(String) * sizeof(WCHAR)); 85 } 86 87 BOOL 88 WriteToLogPrintfV( 89 IN PLOG_FILE LogFile, 90 IN LPCWSTR Format, 91 IN va_list args) 92 { 93 StringCbVPrintfW(LogFile->pBuffer, 94 LogFile->cbBufferSize, 95 Format, args); 96 97 return WriteToLog(LogFile, 98 LogFile->pBuffer, 99 wcslen(LogFile->pBuffer) * sizeof(WCHAR)); 100 } 101 102 BOOL 103 WriteToLogPrintf( 104 IN PLOG_FILE LogFile, 105 IN LPCWSTR Format, 106 ...) 107 { 108 BOOL bRet; 109 va_list args; 110 111 va_start(args, Format); 112 bRet = WriteToLogPrintfV(LogFile, Format, args); 113 va_end(args); 114 115 return bRet; 116 } 117 118 119 /* 120 * Window Station tests 121 */ 122 123 BOOL 124 CALLBACK 125 EnumDesktopProc( 126 IN LPWSTR lpszDesktop, 127 IN LPARAM lParam) 128 { 129 PLOG_FILE LogFile = (PLOG_FILE)lParam; 130 131 WriteToLogPrintf(LogFile, L" :: Found desktop '%s'\r\n", lpszDesktop); 132 133 /* Continue the enumeration */ 134 return TRUE; 135 } 136 137 /* 138 * This test inspects the same window station aspects that are used in the 139 * Cygwin fhandler_console.cc!fhandler_console::create_invisible_console() 140 * function, see: 141 * https://github.com/cygwin/cygwin/blob/7b9bfb4136f23655e243bab89fb62b04bdbacc7f/winsup/cygwin/fhandler_console.cc#L2494 142 */ 143 VOID DoTest(HWND hWnd) 144 { 145 HWINSTA hWinSta; 146 LPCWSTR lpszWinSta = L"Test-WinSta"; 147 BOOL bIsItOk; 148 LOG_FILE LogFile; 149 WCHAR szBuffer[2048]; 150 151 bIsItOk = InitLog(&LogFile, L"test_winsta.log", szBuffer, sizeof(szBuffer)); 152 if (!bIsItOk) 153 { 154 MessageBoxW(hWnd, L"Could not create the log file, stopping test now...", L"Error", MB_ICONERROR | MB_OK); 155 return; 156 } 157 158 /* Switch output to UTF-16 (little endian) */ 159 WriteToLog(&LogFile, "\xFF\xFE", 2); 160 161 WriteToLogPrintf(&LogFile, L"Creating Window Station '%s'\r\n", lpszWinSta); 162 hWinSta = CreateWindowStationW(lpszWinSta, 0, WINSTA_ALL_ACCESS, NULL); 163 WriteToLogPrintf(&LogFile, L"--> Returned handle 0x%p ; last error: %lu\r\n", hWinSta, GetLastError()); 164 165 if (!hWinSta) 166 { 167 WriteToLogPuts(&LogFile, L"\r\nHandle is NULL, cannot proceed further, stopping the test!\r\n\r\n"); 168 return; 169 } 170 171 WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (before process attach)\r\n", lpszWinSta, hWinSta); 172 bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile); 173 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n", 174 (bIsItOk ? L"success" : L"failure"), GetLastError()); 175 176 WriteToLogPrintf(&LogFile, L"Setting current process to Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta); 177 bIsItOk = SetProcessWindowStation(hWinSta); 178 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n", 179 (bIsItOk ? L"success" : L"failure"), GetLastError()); 180 181 WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (after process attach, before allocating console)\r\n", lpszWinSta, hWinSta); 182 bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile); 183 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n", 184 (bIsItOk ? L"success" : L"failure"), GetLastError()); 185 186 WriteToLogPrintf(&LogFile, L"Allocating a new console on Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta); 187 bIsItOk = AllocConsole(); 188 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n", 189 (bIsItOk ? L"success" : L"failure"), GetLastError()); 190 191 WriteToLogPrintf(&LogFile, L"Enumerate desktops on Window Station '%s' (0x%p) (after allocating console)\r\n", lpszWinSta, hWinSta); 192 bIsItOk = EnumDesktopsW(hWinSta, EnumDesktopProc, (LPARAM)&LogFile); 193 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n", 194 (bIsItOk ? L"success" : L"failure"), GetLastError()); 195 196 WriteToLogPrintf(&LogFile, L"Now closing Window Station '%s' (0x%p)\r\n", lpszWinSta, hWinSta); 197 bIsItOk = CloseWindowStation(hWinSta); 198 WriteToLogPrintf(&LogFile, L"--> Returned %s ; last error: %lu\r\n\r\n", 199 (bIsItOk ? L"success" : L"failure"), GetLastError()); 200 201 CloseLog(&LogFile); 202 } 203 204 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 205 { 206 UNREFERENCED_PARAMETER(lParam); 207 switch (message) 208 { 209 case WM_INITDIALOG: 210 return (INT_PTR)TRUE; 211 212 case WM_COMMAND: 213 switch (LOWORD(wParam)) 214 { 215 case IDOK: 216 DoTest(hDlg); 217 EndDialog(hDlg, LOWORD(wParam)); 218 break; 219 220 case IDCANCEL: 221 default: 222 EndDialog(hDlg, LOWORD(wParam)); 223 break; 224 } 225 return (INT_PTR)TRUE; 226 } 227 return (INT_PTR)FALSE; 228 } 229 230 int APIENTRY wWinMain(HINSTANCE hInstance, 231 HINSTANCE hPrevInstance, 232 LPWSTR lpCmdLine, 233 int nCmdShow) 234 { 235 UNREFERENCED_PARAMETER(hPrevInstance); 236 UNREFERENCED_PARAMETER(lpCmdLine); 237 238 return DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_ABOUTBOX), NULL, About); 239 } 240