| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- /*============================================================================
- KWSys - Kitware System Library
- Copyright 2000-2016 Kitware, Inc., Insight Software Consortium
- Distributed under the OSI-approved BSD License (the "License");
- see accompanying file Copyright.txt for details.
- This software is distributed WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License for more information.
- ============================================================================*/
- #include "kwsysPrivate.h"
- // Ignore Windows version levels defined by command-line flags. This
- // source needs access to all APIs available on the host in order for
- // the test to run properly. The test binary is not installed anyway.
- #undef _WIN32_WINNT
- #undef NTDDI_VERSION
- #include KWSYS_HEADER(Encoding.hxx)
- // Work-around CMake dependency scanning limitation. This must
- // duplicate the above list of headers.
- #if 0
- # include "Encoding.hxx.in"
- #endif
- #if defined(_WIN32)
- #include <windows.h>
- #include <string.h>
- #include <wchar.h>
- #include <iostream>
- #include <stdexcept>
- #include "testConsoleBuf.hxx"
- #if defined(_MSC_VER) && _MSC_VER >= 1800
- # define KWSYS_WINDOWS_DEPRECATED_GetVersion
- #endif
- // يونيكود
- static const WCHAR UnicodeInputTestString[] = L"\u064A\u0648\u0646\u064A\u0643\u0648\u062F!";
- static UINT TestCodepage = KWSYS_ENCODING_DEFAULT_CODEPAGE;
- static const DWORD waitTimeout = 10 * 1000;
- static STARTUPINFO startupInfo;
- static PROCESS_INFORMATION processInfo;
- static HANDLE syncEvent;
- static std::string encodedInputTestString;
- static std::string encodedTestString;
- //----------------------------------------------------------------------------
- static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
- {
- BOOL bInheritHandles = FALSE;
- DWORD dwCreationFlags = 0;
- memset(&processInfo, 0, sizeof(processInfo));
- memset(&startupInfo, 0, sizeof(startupInfo));
- startupInfo.cb = sizeof(startupInfo);
- startupInfo.dwFlags = STARTF_USESHOWWINDOW;
- startupInfo.wShowWindow = SW_HIDE;
- if (hIn || hOut || hErr) {
- startupInfo.dwFlags |= STARTF_USESTDHANDLES;
- startupInfo.hStdInput = hIn;
- startupInfo.hStdOutput = hOut;
- startupInfo.hStdError = hErr;
- bInheritHandles = TRUE;
- }
- WCHAR cmd[MAX_PATH];
- if (GetModuleFileNameW(NULL, cmd, MAX_PATH) == 0) {
- std::cerr << "GetModuleFileName failed!" << std::endl;
- return false;
- }
- WCHAR *p = cmd + wcslen(cmd);
- while (p > cmd && *p != L'\\') p--;
- *(p+1) = 0;
- wcscat(cmd, cmdConsoleBufChild);
- wcscat(cmd, L".exe");
- bool success = CreateProcessW(NULL, // No module name (use command line)
- cmd, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- bInheritHandles, // Set handle inheritance
- dwCreationFlags,
- NULL, // Use parent's environment block
- NULL, // Use parent's starting directory
- &startupInfo, // Pointer to STARTUPINFO structure
- &processInfo) != 0; // Pointer to PROCESS_INFORMATION structure
- if (!success) {
- DWORD lastError = GetLastError();
- std::cerr.setf(std::ios::hex, std::ios::basefield);
- std::cerr << "CreateProcess(" << kwsys::Encoding::ToNarrow(cmd)
- << ") failed with error: 0x" << lastError << "!" << std::endl;
- LPWSTR message;
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- lastError,
- 0,
- (LPWSTR)&message, 0,
- NULL)
- ) {
- std::cerr << "Error message: " << kwsys::Encoding::ToNarrow(message) << std::endl;
- HeapFree(GetProcessHeap(), 0, message);
- } else {
- std::cerr << "FormatMessage() failed with error: 0x" << GetLastError() << "!" << std::endl;
- }
- std::cerr.unsetf(std::ios::hex);
- }
- return success;
- }
- //----------------------------------------------------------------------------
- static void finishProcess(bool success)
- {
- if (success) {
- success = WaitForSingleObject(processInfo.hProcess, waitTimeout)
- == WAIT_OBJECT_0;
- };
- if (!success) {
- TerminateProcess(processInfo.hProcess, 1);
- }
- CloseHandle(processInfo.hProcess);
- CloseHandle(processInfo.hThread);
- }
- //----------------------------------------------------------------------------
- static bool createPipe(PHANDLE readPipe, PHANDLE writePipe)
- {
- SECURITY_ATTRIBUTES securityAttributes;
- securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
- return CreatePipe(readPipe, writePipe, &securityAttributes, 0) == 0
- ? false : true;
- }
- //----------------------------------------------------------------------------
- static void finishPipe(HANDLE readPipe, HANDLE writePipe)
- {
- if (readPipe != INVALID_HANDLE_VALUE) {
- CloseHandle(readPipe);
- }
- if (writePipe != INVALID_HANDLE_VALUE) {
- CloseHandle(writePipe);
- }
- }
- //----------------------------------------------------------------------------
- static HANDLE createFile(LPCWSTR fileName)
- {
- SECURITY_ATTRIBUTES securityAttributes;
- securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
- HANDLE file = CreateFileW(fileName,
- GENERIC_READ | GENERIC_WRITE,
- 0, // do not share
- &securityAttributes,
- CREATE_ALWAYS, // overwrite existing
- FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
- NULL); // no template
- if (file == INVALID_HANDLE_VALUE) {
- std::cerr << "CreateFile(" << kwsys::Encoding::ToNarrow(fileName)
- << ") failed!" << std::endl;
- }
- return file;
- }
- //----------------------------------------------------------------------------
- static void finishFile(HANDLE file)
- {
- if (file != INVALID_HANDLE_VALUE) {
- CloseHandle(file);
- }
- }
- //----------------------------------------------------------------------------
- #ifndef MAPVK_VK_TO_VSC
- # define MAPVK_VK_TO_VSC (0)
- #endif
- static void writeInputKeyEvent(INPUT_RECORD inputBuffer[], WCHAR chr)
- {
- inputBuffer[0].EventType = KEY_EVENT;
- inputBuffer[0].Event.KeyEvent.bKeyDown = TRUE;
- inputBuffer[0].Event.KeyEvent.wRepeatCount = 1;
- SHORT keyCode = VkKeyScanW(chr);
- if (keyCode == -1) {
- // Character can't be entered with current keyboard layout
- // Just set any, it doesn't really matter
- keyCode = 'K';
- }
- inputBuffer[0].Event.KeyEvent.wVirtualKeyCode = LOBYTE(keyCode);
- inputBuffer[0].Event.KeyEvent.wVirtualScanCode =
- MapVirtualKey(inputBuffer[0].Event.KeyEvent.wVirtualKeyCode,
- MAPVK_VK_TO_VSC);
- inputBuffer[0].Event.KeyEvent.uChar.UnicodeChar = chr;
- inputBuffer[0].Event.KeyEvent.dwControlKeyState = 0;
- if ((HIBYTE(keyCode) & 1) == 1) {
- inputBuffer[0].Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
- }
- if ((HIBYTE(keyCode) & 2) == 2) {
- inputBuffer[0].Event.KeyEvent.dwControlKeyState |= RIGHT_CTRL_PRESSED;
- }
- if ((HIBYTE(keyCode) & 4) == 4) {
- inputBuffer[0].Event.KeyEvent.dwControlKeyState |= RIGHT_ALT_PRESSED;
- }
- inputBuffer[1].EventType = inputBuffer[0].EventType;
- inputBuffer[1].Event.KeyEvent.bKeyDown = FALSE;
- inputBuffer[1].Event.KeyEvent.wRepeatCount = 1;
- inputBuffer[1].Event.KeyEvent.wVirtualKeyCode = inputBuffer[0].Event.
- KeyEvent.wVirtualKeyCode;
- inputBuffer[1].Event.KeyEvent.wVirtualScanCode = inputBuffer[0].Event.
- KeyEvent.wVirtualScanCode;
- inputBuffer[1].Event.KeyEvent.uChar.UnicodeChar = inputBuffer[0].Event.
- KeyEvent.uChar.UnicodeChar;
- inputBuffer[1].Event.KeyEvent.dwControlKeyState = 0;
- }
- //----------------------------------------------------------------------------
- static int testPipe()
- {
- int didFail = 1;
- HANDLE inPipeRead = INVALID_HANDLE_VALUE;
- HANDLE inPipeWrite = INVALID_HANDLE_VALUE;
- HANDLE outPipeRead = INVALID_HANDLE_VALUE;
- HANDLE outPipeWrite = INVALID_HANDLE_VALUE;
- HANDLE errPipeRead = INVALID_HANDLE_VALUE;
- HANDLE errPipeWrite = INVALID_HANDLE_VALUE;
- UINT currentCodepage = GetConsoleCP();
- char buffer[200];
- try {
- if (!createPipe(&inPipeRead, &inPipeWrite) ||
- !createPipe(&outPipeRead, &outPipeWrite) ||
- !createPipe(&errPipeRead, &errPipeWrite)) {
- throw std::runtime_error("createFile failed!");
- }
- if (TestCodepage == CP_ACP) {
- TestCodepage = GetACP();
- }
- if (!SetConsoleCP(TestCodepage)) {
- throw std::runtime_error("SetConsoleCP failed!");
- }
- DWORD bytesWritten = 0;
- if (!WriteFile(inPipeWrite, encodedInputTestString.c_str(),
- (DWORD)encodedInputTestString.size(), &bytesWritten, NULL)
- || bytesWritten == 0) {
- throw std::runtime_error("WriteFile failed!");
- }
- if (createProcess(inPipeRead, outPipeWrite, errPipeWrite)) {
- try {
- Sleep(100);
- if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
- throw std::runtime_error("WaitForSingleObject failed!");
- }
- DWORD bytesRead = 0;
- if (!ReadFile(outPipeRead, buffer, sizeof(buffer), &bytesRead, NULL)
- || bytesRead == 0) {
- throw std::runtime_error("ReadFile failed!");
- }
- if ((bytesRead < encodedTestString.size() + 1 + encodedInputTestString.size()
- && !ReadFile(outPipeRead, buffer + bytesRead,
- sizeof(buffer) - bytesRead, &bytesRead, NULL))
- || bytesRead == 0) {
- throw std::runtime_error("ReadFile failed!");
- }
- if (memcmp(buffer, encodedTestString.c_str(),
- encodedTestString.size()) == 0 &&
- memcmp(buffer + encodedTestString.size() + 1,
- encodedInputTestString.c_str(),
- encodedInputTestString.size()) == 0) {
- bytesRead = 0;
- if (!ReadFile(errPipeRead, buffer, sizeof(buffer), &bytesRead, NULL)
- || bytesRead == 0) {
- throw std::runtime_error("ReadFile failed!");
- }
- buffer[bytesRead - 1] = 0;
- didFail = encodedTestString.compare(buffer) == 0 ? 0 : 1;
- }
- if (didFail != 0) {
- std::cerr << "Pipe's output didn't match expected output!" << std::endl << std::flush;
- }
- } catch (const std::runtime_error &ex) {
- std::cerr << ex.what() << std::endl << std::flush;
- }
- finishProcess(didFail == 0);
- }
- } catch (const std::runtime_error &ex) {
- std::cerr << ex.what() << std::endl << std::flush;
- }
- finishPipe(inPipeRead, inPipeWrite);
- finishPipe(outPipeRead, outPipeWrite);
- finishPipe(errPipeRead, errPipeWrite);
- SetConsoleCP(currentCodepage);
- return didFail;
- }
- //----------------------------------------------------------------------------
- static int testFile()
- {
- int didFail = 1;
- HANDLE inFile = INVALID_HANDLE_VALUE;
- HANDLE outFile = INVALID_HANDLE_VALUE;
- HANDLE errFile = INVALID_HANDLE_VALUE;
- try {
- if ((inFile = createFile(L"stdinFile.txt")) == INVALID_HANDLE_VALUE ||
- (outFile = createFile(L"stdoutFile.txt")) == INVALID_HANDLE_VALUE ||
- (errFile = createFile(L"stderrFile.txt")) == INVALID_HANDLE_VALUE) {
- throw std::runtime_error("createFile failed!");
- }
- int length = 0;
- DWORD bytesWritten = 0;
- char buffer[200];
- if ((length = WideCharToMultiByte(TestCodepage, 0, UnicodeInputTestString, -1,
- buffer, sizeof(buffer),
- NULL, NULL)) == 0) {
- throw std::runtime_error("WideCharToMultiByte failed!");
- }
- buffer[length - 1] = '\n';
- if (!WriteFile(inFile, buffer, length, &bytesWritten, NULL)
- || bytesWritten == 0) {
- throw std::runtime_error("WriteFile failed!");
- }
- if (SetFilePointer(inFile, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
- throw std::runtime_error("SetFilePointer failed!");
- }
- if (createProcess(inFile, outFile, errFile)) {
- DWORD bytesRead = 0;
- try {
- Sleep(100);
- if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
- throw std::runtime_error("WaitForSingleObject failed!");
- }
- if (SetFilePointer(outFile, 0, 0, FILE_BEGIN)
- == INVALID_SET_FILE_POINTER) {
- throw std::runtime_error("SetFilePointer failed!");
- }
- if (!ReadFile(outFile, buffer, sizeof(buffer), &bytesRead, NULL)
- || bytesRead == 0) {
- throw std::runtime_error("ReadFile failed!");
- }
- buffer[bytesRead - 1] = 0;
- if (memcmp(buffer, encodedTestString.c_str(),
- encodedTestString.size()) == 0 &&
- memcmp(buffer + encodedTestString.size() + 1,
- encodedInputTestString.c_str(),
- encodedInputTestString.size() - 1) == 0) {
- bytesRead = 0;
- if (SetFilePointer(errFile, 0, 0, FILE_BEGIN)
- == INVALID_SET_FILE_POINTER) {
- throw std::runtime_error("SetFilePointer failed!");
- }
- if (!ReadFile(errFile, buffer, sizeof(buffer), &bytesRead, NULL)
- || bytesRead == 0) {
- throw std::runtime_error("ReadFile failed!");
- }
- buffer[bytesRead - 1] = 0;
- didFail = encodedTestString.compare(buffer) == 0 ? 0 : 1;
- }
- if (didFail != 0) {
- std::cerr << "File's output didn't match expected output!" << std::endl << std::flush;
- }
- } catch (const std::runtime_error &ex) {
- std::cerr << ex.what() << std::endl << std::flush;
- }
- finishProcess(didFail == 0);
- }
- } catch (const std::runtime_error &ex) {
- std::cerr << ex.what() << std::endl << std::flush;
- }
- finishFile(inFile);
- finishFile(outFile);
- finishFile(errFile);
- return didFail;
- }
- #ifndef _WIN32_WINNT_VISTA
- # define _WIN32_WINNT_VISTA 0x0600
- #endif
- //----------------------------------------------------------------------------
- static int testConsole()
- {
- int didFail = 1;
- HANDLE parentIn = GetStdHandle(STD_INPUT_HANDLE);
- HANDLE parentOut = GetStdHandle(STD_OUTPUT_HANDLE);
- HANDLE parentErr = GetStdHandle(STD_ERROR_HANDLE);
- HANDLE hIn = parentIn;
- HANDLE hOut = parentOut;
- DWORD consoleMode;
- bool newConsole = false;
- bool forceNewConsole = false;
- bool restoreConsole = false;
- LPCWSTR TestFaceName = L"Lucida Console";
- const DWORD TestFontFamily = 0x00000036;
- const DWORD TestFontSize = 0x000c0000;
- HKEY hConsoleKey;
- WCHAR FaceName[200];
- DWORD FaceNameSize = sizeof(FaceName);
- DWORD FontFamily = TestFontFamily;
- DWORD FontSize = TestFontSize;
- #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
- # pragma warning (push)
- # ifdef __INTEL_COMPILER
- # pragma warning (disable:1478)
- # else
- # pragma warning (disable:4996)
- # endif
- #endif
- const bool isVistaOrGreater = LOBYTE(LOWORD(GetVersion())) >= HIBYTE(_WIN32_WINNT_VISTA);
- #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersion
- # pragma warning (pop)
- #endif
- if (!isVistaOrGreater) {
- if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ | KEY_WRITE,
- &hConsoleKey) == ERROR_SUCCESS) {
- DWORD dwordSize = sizeof(DWORD);
- if (RegQueryValueExW(hConsoleKey, L"FontFamily", NULL, NULL,
- (LPBYTE)&FontFamily, &dwordSize) == ERROR_SUCCESS) {
- if (FontFamily != TestFontFamily) {
- RegQueryValueExW(hConsoleKey, L"FaceName", NULL, NULL,
- (LPBYTE)FaceName, &FaceNameSize);
- RegQueryValueExW(hConsoleKey, L"FontSize", NULL, NULL,
- (LPBYTE)&FontSize, &dwordSize);
- RegSetValueExW(hConsoleKey, L"FontFamily", 0, REG_DWORD,
- (BYTE *)&TestFontFamily, sizeof(TestFontFamily));
- RegSetValueExW(hConsoleKey, L"FaceName", 0, REG_SZ,
- (BYTE *)TestFaceName, (DWORD)((wcslen(TestFaceName) + 1) * sizeof(WCHAR)));
- RegSetValueExW(hConsoleKey, L"FontSize", 0, REG_DWORD,
- (BYTE *)&TestFontSize, sizeof(TestFontSize));
- restoreConsole = true;
- forceNewConsole = true;
- }
- } else {
- std::cerr << "RegGetValueW(FontFamily) failed!" << std::endl << std::flush;
- }
- RegCloseKey(hConsoleKey);
- } else {
- std::cerr << "RegOpenKeyExW(HKEY_CURRENT_USER\\Console) failed!" << std::endl << std::flush;
- }
- }
- if (forceNewConsole || GetConsoleMode(parentOut, &consoleMode) == 0) {
- // Not a real console, let's create new one.
- FreeConsole();
- if (!AllocConsole()) {
- std::cerr << "AllocConsole failed!" << std::endl << std::flush;
- return didFail;
- }
- SECURITY_ATTRIBUTES securityAttributes;
- securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttributes.bInheritHandle = TRUE;
- securityAttributes.lpSecurityDescriptor = NULL;
- hIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, 0,
- &securityAttributes, OPEN_EXISTING, 0, NULL);
- hOut = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, 0,
- &securityAttributes, OPEN_EXISTING, 0, NULL);
- SetStdHandle(STD_INPUT_HANDLE, hIn);
- SetStdHandle(STD_OUTPUT_HANDLE, hOut);
- SetStdHandle(STD_ERROR_HANDLE, hOut);
- newConsole = true;
- }
- #if _WIN32_WINNT >= _WIN32_WINNT_VISTA
- if (isVistaOrGreater) {
- CONSOLE_FONT_INFOEX consoleFont;
- memset(&consoleFont, 0, sizeof(consoleFont));
- consoleFont.cbSize = sizeof(consoleFont);
- HMODULE kernel32 = LoadLibraryW(L"kernel32.dll");
- typedef BOOL (WINAPI *GetCurrentConsoleFontExFunc)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
- typedef BOOL (WINAPI *SetCurrentConsoleFontExFunc)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
- GetCurrentConsoleFontExFunc getConsoleFont = (GetCurrentConsoleFontExFunc)GetProcAddress(kernel32, "GetCurrentConsoleFontEx");
- SetCurrentConsoleFontExFunc setConsoleFont = (SetCurrentConsoleFontExFunc)GetProcAddress(kernel32, "SetCurrentConsoleFontEx");
- if (getConsoleFont(hOut, FALSE, &consoleFont)) {
- if (consoleFont.FontFamily != TestFontFamily) {
- consoleFont.FontFamily = TestFontFamily;
- wcscpy(consoleFont.FaceName, TestFaceName);
- if (!setConsoleFont(hOut, FALSE, &consoleFont)) {
- std::cerr << "SetCurrentConsoleFontEx failed!" << std::endl << std::flush;
- }
- }
- } else {
- std::cerr << "GetCurrentConsoleFontEx failed!" << std::endl << std::flush;
- }
- } else {
- #endif
- if (restoreConsole && RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0,
- KEY_WRITE, &hConsoleKey) == ERROR_SUCCESS) {
- RegSetValueExW(hConsoleKey, L"FontFamily", 0, REG_DWORD,
- (BYTE *)&FontFamily, sizeof(FontFamily));
- RegSetValueExW(hConsoleKey, L"FaceName", 0, REG_SZ,
- (BYTE *)FaceName, FaceNameSize);
- RegSetValueExW(hConsoleKey, L"FontSize", 0, REG_DWORD,
- (BYTE *)&FontSize, sizeof(FontSize));
- RegCloseKey(hConsoleKey);
- }
- #if _WIN32_WINNT >= _WIN32_WINNT_VISTA
- }
- #endif
- if (createProcess(NULL, NULL, NULL)) {
- try {
- if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
- throw std::runtime_error("WaitForSingleObject failed!");
- }
- INPUT_RECORD inputBuffer[(sizeof(UnicodeInputTestString) /
- sizeof(UnicodeInputTestString[0])) * 2];
- memset(&inputBuffer, 0, sizeof(inputBuffer));
- unsigned int i = 0;
- for (i = 0; i < (sizeof(UnicodeInputTestString) /
- sizeof(UnicodeInputTestString[0]) - 1); i++) {
- writeInputKeyEvent(&inputBuffer[i*2], UnicodeInputTestString[i]);
- }
- writeInputKeyEvent(&inputBuffer[i*2], VK_RETURN);
- DWORD eventsWritten = 0;
- if (!WriteConsoleInputW(hIn, inputBuffer, sizeof(inputBuffer) /
- sizeof(inputBuffer[0]),
- &eventsWritten) || eventsWritten == 0) {
- throw std::runtime_error("WriteConsoleInput failed!");
- }
- if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
- throw std::runtime_error("WaitForSingleObject failed!");
- }
- CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
- if (!GetConsoleScreenBufferInfo(hOut, &screenBufferInfo)) {
- throw std::runtime_error("GetConsoleScreenBufferInfo failed!");
- }
- COORD coord;
- DWORD charsRead = 0;
- coord.X = 0;
- coord.Y = screenBufferInfo.dwCursorPosition.Y - 4;
- WCHAR *outputBuffer = new WCHAR[screenBufferInfo.dwSize.X * 4];
- if (!ReadConsoleOutputCharacterW(hOut, outputBuffer,
- screenBufferInfo.dwSize.X * 4, coord, &charsRead)
- || charsRead == 0) {
- delete[] outputBuffer;
- throw std::runtime_error("ReadConsoleOutputCharacter failed!");
- }
- std::wstring wideTestString = kwsys::Encoding::ToWide(encodedTestString);
- std::wstring wideInputTestString = kwsys::Encoding::ToWide(encodedInputTestString);
- if (memcmp(outputBuffer, wideTestString.c_str(), wideTestString.size()) == 0 &&
- memcmp(outputBuffer + screenBufferInfo.dwSize.X * 1,
- wideTestString.c_str(), wideTestString.size()) == 0 &&
- memcmp(outputBuffer + screenBufferInfo.dwSize.X * 2,
- UnicodeInputTestString, sizeof(UnicodeInputTestString) -
- sizeof(WCHAR)) == 0 &&
- memcmp(outputBuffer + screenBufferInfo.dwSize.X * 3,
- wideInputTestString.c_str(), wideInputTestString.size() - 1) == 0
- ) {
- didFail = 0;
- } else {
- std::cerr << "Console's output didn't match expected output!" << std::endl << std::flush;
- }
- delete[] outputBuffer;
- } catch (const std::runtime_error &ex) {
- std::cerr << ex.what() << std::endl << std::flush;
- }
- finishProcess(didFail == 0);
- }
- if (newConsole) {
- SetStdHandle(STD_INPUT_HANDLE, parentIn);
- SetStdHandle(STD_OUTPUT_HANDLE, parentOut);
- SetStdHandle(STD_ERROR_HANDLE, parentErr);
- CloseHandle(hIn);
- CloseHandle(hOut);
- FreeConsole();
- }
- return didFail;
- }
- #endif
- //----------------------------------------------------------------------------
- int testConsoleBuf(int, char*[])
- {
- int ret = 0;
- #if defined(_WIN32)
- syncEvent = CreateEventW(NULL,
- FALSE, // auto-reset event
- FALSE, // initial state is nonsignaled
- SyncEventName); // object name
- if (!syncEvent) {
- std::cerr << "CreateEvent failed " << GetLastError() << std::endl;
- return 1;
- }
- encodedTestString = kwsys::Encoding::ToNarrow(UnicodeTestString);
- encodedInputTestString = kwsys::Encoding::ToNarrow(UnicodeInputTestString);
- encodedInputTestString += "\n";
- ret |= testPipe();
- ret |= testFile();
- ret |= testConsole();
- CloseHandle(syncEvent);
- #endif
- return ret;
- }
|