Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*Copyright (c) 2008 Billy O'Neal
- *
- *Permission is hereby granted, free of charge, to any person obtaining a copy
- *of this software and associated documentation files (the "Software"), to deal
- *in the Software without restriction, including without limitation the rights
- *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- *copies of the Software, and to permit persons to whom the Software is
- *furnished to do so, subject to the following conditions:
- *
- *The above copyright notice and this permission notice shall be included in
- *all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- *THE SOFTWARE.
- *
- * ConsoleTools.cpp -- A bunch of console management functions.
- */
- #include "stdafx.h"
- using namespace std;
- consoleToolsProvider::consoleToolsProvider()
- {
- initialize();
- }
- consoleToolsProvider::~consoleToolsProvider()
- {
- std::map<HANDLE,control>::iterator it;
- it = animationThreads.begin();
- for(register unsigned int idx = 0; idx < animationThreads.size(); idx++) {
- TerminateThread((*it).first,0);
- CloseHandle((*it).first);
- it++;
- }
- animationThreads.clear();
- }
- void consoleToolsProvider::initialize()
- {
- //Zero out origin
- origin.X = 0;
- origin.Y = 0;
- //Get the current console
- current_Console = GetStdHandle(STD_OUTPUT_HANDLE);
- //Get attributes of the current console
- GetConsoleScreenBufferInfo(current_Console,¤t_Screen);
- //Reset threading
- animationLocked = false;
- handleValid = false;
- }
- void consoleToolsProvider::color(char background, char foreground)
- {
- WORD attributes;
- //Set the foreground attribute
- switch (foreground) {
- case '0':
- //Black = 0
- attributes = NULL;
- break;
- case '1':
- //Blue = 1
- attributes = FOREGROUND_BLUE;
- break;
- case '2':
- //Green = 2
- attributes = FOREGROUND_GREEN;
- break;
- case '3':
- //Aqua = 3
- attributes = FOREGROUND_BLUE | FOREGROUND_GREEN;
- break;
- case '4':
- //Red = 4
- attributes = FOREGROUND_RED;
- break;
- case '5':
- //Purple = 5
- attributes = FOREGROUND_BLUE | FOREGROUND_RED;
- break;
- case '6':
- //Yellow = 6
- attributes = FOREGROUND_RED | FOREGROUND_GREEN;
- break;
- case '7':
- //White = 7
- attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
- break;
- case '8':
- //Gray = 8
- attributes = FOREGROUND_INTENSITY;
- break;
- case '9':
- //Light Blue = 9
- attributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
- break;
- case 'A':
- //Light Green = A
- attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
- break;
- case 'B':
- //Light Aqua = B
- attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
- break;
- case 'C':
- //Light Red = C
- attributes = FOREGROUND_RED | FOREGROUND_INTENSITY;
- break;
- case 'D':
- //Light Purple = D
- attributes = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
- break;
- case 'E':
- //Light Yellow = E
- attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
- break;
- case 'F':
- //Bright White = F
- attributes = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
- break;
- }
- //Set the background attribute
- switch (background) {
- //Black = 0
- case '1':
- //Blue = 1
- attributes = attributes | BACKGROUND_BLUE;
- break;
- case '2':
- //Green = 2
- attributes = attributes | FOREGROUND_GREEN;
- break;
- case '3':
- //Aqua = 3
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_GREEN;
- break;
- case '4':
- //Red = 4
- attributes = attributes | BACKGROUND_RED;
- break;
- case '5':
- //Purple = 5
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_RED;
- break;
- case '6':
- //Yellow = 6
- attributes = attributes | BACKGROUND_RED | BACKGROUND_GREEN;
- break;
- case '7':
- //White = 7
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
- break;
- case '8':
- //Gray = 8
- attributes = attributes | BACKGROUND_INTENSITY;
- break;
- case '9':
- //Light Blue = 9
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
- break;
- case 'A':
- //Light Green = A
- attributes = attributes | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
- break;
- case 'B':
- //Light Aqua = B
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
- break;
- case 'C':
- //Light Red = C
- attributes = attributes | BACKGROUND_RED | BACKGROUND_INTENSITY;
- break;
- case 'D':
- //Light Purple = D
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_INTENSITY;
- break;
- case 'E':
- //Light Yellow = E
- attributes = attributes | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
- break;
- case 'F':
- //Bright White = F
- attributes = attributes | BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
- break;
- }
- SetConsoleTextAttribute(current_Console,attributes);
- FillConsoleOutputAttribute(current_Console,attributes,current_Screen.dwSize.X * current_Screen.dwSize.Y,origin,NULL);
- }
- void consoleToolsProvider::clear()
- {
- //Clear output buffer
- FillConsoleOutputCharacter(current_Console,_T(' '),current_Screen.dwSize.X * current_Screen.dwSize.Y,origin,NULL);
- SetConsoleCursorPosition(current_Console,origin);
- }
- void consoleToolsProvider::pause()
- {
- _getch();
- }
- void consoleToolsProvider::title(LPCTSTR title)
- {
- SetConsoleTitle(title);
- }
- void consoleToolsProvider::drawProgressBar(unsigned short topX, unsigned short topY, unsigned short bottomX, unsigned short bottomY, unsigned short percent, TCHAR usedChar, TCHAR unusedChar, TCHAR leftBoundChar, TCHAR rightBoundChar)
- {
- //reinitialize the current console and screen
- initialize();
- //define the rectangle we will use to draw
- SMALL_RECT drawRect;
- drawRect.Left = topX;
- drawRect.Top = topY;
- drawRect.Right = bottomX;
- drawRect.Bottom = bottomY;
- //Build the array of characters to actually write
- CHAR_INFO *drawnCharacters;
- unsigned int width, height;
- //Find the width and height of the area we are going to draw
- width = bottomX - topX;
- height = bottomY - topY + 1;
- //Find the number of characters on each line which will be filled with each type of character.
- unsigned short int usedLen = (percent*(width-2)/100);
- unsigned short int unusedLen = (width-2) - usedLen;
- //do the actual allocation
- drawnCharacters = new CHAR_INFO[height*width+1];
- //Apply the current console attributes to each CHAR_INFO struture
- WORD attrs = current_Screen.wAttributes;
- for(register unsigned int idx = 0; idx <= width*height;idx++) {
- drawnCharacters[idx].Attributes = attrs;
- }
- //Loop Per Line
- for(register unsigned int currentLine = 0; currentLine < height; currentLine++) {
- #ifdef _UNICODE
- //Draw the bounds characters
- drawnCharacters[currentLine*width].Char.UnicodeChar = leftBoundChar;
- drawnCharacters[(currentLine+1)*width-1].Char.UnicodeChar = rightBoundChar;
- //Draw the used characters
- for(register unsigned int curChar = 1; curChar <= usedLen; curChar++) {
- drawnCharacters[currentLine*width+curChar].Char.UnicodeChar = usedChar;
- }
- //Draw the unused characters
- for(register unsigned int curChar = usedLen+1; curChar < width-1; curChar++) {
- drawnCharacters[currentLine*width+curChar].Char.UnicodeChar = unusedChar;
- }
- #else
- //Draw the bounds characters
- drawnCharacters[currentLine*width].Char.AsciiChar = leftBoundChar;
- drawnCharacters[(currentLine+1)*width-1].Char.AsciiChar = rightBoundChar;
- //Draw the used characters
- for(register unsigned int curChar = 1; curChar <= usedLen; curChar++) {
- drawnCharacters[currentLine*width+curChar].Char.AsciiChar = usedChar;
- }
- //Draw the unused characters
- for(register unsigned int curChar = usedLen+1; curChar < width-1; curChar++) {
- drawnCharacters[currentLine*width+curChar].Char.AsciiChar = unusedChar;
- }
- #endif
- }
- //Do the actual write
- //Create arrayBounds coordinate for API
- COORD arrayBounds;
- arrayBounds.X = width;
- arrayBounds.Y = height;
- WriteConsoleOutput(current_Console,drawnCharacters,arrayBounds,origin,&drawRect);
- delete [] drawnCharacters;
- }
- HANDLE consoleToolsProvider::drawActivityIndicator(enum activityIndicatorMode mode, unsigned short int topX, unsigned short int topY, unsigned short int bottomX, unsigned short int bottomY, DWORD sleepInterval, TCHAR usedChar, TCHAR unusedChar, TCHAR leftBoundChar, TCHAR rightBoundChar)
- {
- HANDLE tempHandle;
- LPTHREAD_START_ROUTINE targetFunction = &animate;
- //Build a structure of arguments to pass to the animation function
- animationArgs *valuesStruct;
- valuesStruct = new animationArgs;
- valuesStruct->caller = this;
- valuesStruct->mode = mode;
- valuesStruct->topX = topX;
- valuesStruct->topY = topY;
- valuesStruct->bottomX = bottomX;
- valuesStruct->bottomY = bottomY;
- valuesStruct->sleepInterval = sleepInterval;
- valuesStruct->usedChar = usedChar;
- valuesStruct->unusedChar = unusedChar;
- valuesStruct->leftBoundChar = leftBoundChar;
- valuesStruct->rightBoundChar = rightBoundChar;
- while (animationLocked) {Sleep(1);}
- animationLocked = true;
- tempHandle = CreateThread(NULL,NULL,targetFunction,valuesStruct,NULL,NULL);
- animationThreads.insert(std::pair<HANDLE,control>(tempHandle,NORMAL));
- lastThread = tempHandle;
- handleValid = true;
- while (animationLocked) {Sleep(1);}; // Wait until thread starts
- return tempHandle;
- }
- void consoleToolsProvider::stopActivityIndicator(HANDLE indicatorHandle, control action)
- {
- while (animationLocked) {
- Sleep(10);
- }
- animationLocked = true;
- animationThreads[indicatorHandle] = action;
- animationLocked = false;
- }
- DWORD WINAPI animate(LPVOID params)
- {
- while(!((animationArgs *) params)->caller->handleValid) {Sleep(1);}; //Wait until handle is valid
- HANDLE currentThread = ((animationArgs *) params)->caller->lastThread; //get copy of handle
- ((animationArgs *) params)->caller->handleValid = false; //We've got the handle, mark as invalid
- //Copy the content of the structure we were sent into our temporary thread, at the same time casting and freeing the ram used.
- animationArgs arguments;
- memcpy(&arguments,params,sizeof(animationArgs));
- //Free the temp structure we were called with
- delete params;
- arguments.caller->animationLocked = false; //Release lock on the map
- //define the rectangle we will use to draw
- SMALL_RECT drawRect;
- drawRect.Left = arguments.topX;
- drawRect.Top = arguments.topY;
- drawRect.Right = arguments.bottomX;
- drawRect.Bottom = arguments.bottomY;
- //Build the array of characters to actually write
- CHAR_INFO *drawnCharacters;
- unsigned int width, height;
- //Find the width and height of the area we are going to draw
- width = arguments.bottomX - arguments.topX;
- height = arguments.bottomY - arguments.topY;
- COORD arrayBounds;
- arrayBounds.X = width;
- arrayBounds.Y = height;
- //do the actual allocation
- drawnCharacters = new CHAR_INFO[height*width+1];
- //variable for use in loop later defining current state
- unsigned int state = 1;
- unsigned short int writeIndex;
- //Apply the current console attributes to each CHAR_INFO struture
- WORD attrs = arguments.caller->current_Screen.wAttributes;
- for(register unsigned int idx = 0; idx <= width*height;idx++) {
- drawnCharacters[idx].Attributes = attrs;
- }
- //Infinite loop which will be terminated with threading message.
- for(;;) {
- //Zero out the current state of the buffer
- for(register unsigned int idx = 0; idx <= width*height;idx++) {
- #ifdef _UNICODE
- drawnCharacters[idx].Char.UnicodeChar = arguments.unusedChar;
- #else
- drawnCharacters[idx].Char.AsciiChar = arguments.unusedChar;
- #endif
- }
- switch(arguments.mode) {
- case OSCILIATE:
- //If we've looped the whole way, then reset state
- if (state >= floor((float)width*2)-4) state = 1;
- writeIndex = state;
- if (writeIndex >= width - 1) {
- writeIndex = width - 2 - (writeIndex-width);
- }
- if (writeIndex == (width-2)) state++;
- for(unsigned short int currentLine = 0; currentLine < height; currentLine++) {
- #ifdef _UNICODE
- //Draw caps
- drawnCharacters[currentLine*width].Char.UnicodeChar = arguments.leftBoundChar;
- drawnCharacters[(currentLine+1)*width-1].Char.UnicodeChar = arguments.rightBoundChar;
- drawnCharacters[currentLine*width+writeIndex].Char.UnicodeChar = arguments.usedChar;
- #else
- drawnCharacters[currentLine*width].Char.AsciiChar = arguments.leftBoundChar;
- drawnCharacters[(currentLine+1)*width-1].Char.AsciiChar = arguments.rightBoundChar;
- drawnCharacters[currentLine*width+writeIndex].Char.AsciiChar = arguments.usedChar;
- #endif
- }
- break;
- case CHASE:
- default:
- //If we've looped the whole way, then reset state
- if (state == 2) state = 0;
- for(register unsigned short int idx = 0; idx < height; idx++) {
- #ifdef _UNICODE
- //Draw caps
- drawnCharacters[idx*width].Char.UnicodeChar = arguments.leftBoundChar;
- drawnCharacters[(idx+1)*width-1].Char.UnicodeChar = arguments.rightBoundChar;
- for(register unsigned short int charPos = idx*width+1; charPos < ((idx+1)*width)-2;charPos += 2) {
- if (state) {
- drawnCharacters[charPos].Char.UnicodeChar = arguments.usedChar;
- } else {
- drawnCharacters[charPos+1].Char.UnicodeChar = arguments.usedChar;
- }
- }
- #else
- //Draw caps
- drawnCharacters[idx*width].Char.AsciiChar = arguments.leftBoundChar;
- drawnCharacters[(idx+1)*width-1].Char.AsciiChar = arguments.rightBoundChar;
- for(register unsigned short int charPos = idx*width+1; charPos < ((idx+1)*width)-2;charPos += 2) {
- if (state) {
- drawnCharacters[charPos].Char.AsciiChar = arguments.usedChar;
- } else {
- drawnCharacters[charPos+1].Char.AsciiChar = arguments.usedChar;
- }
- }
- #endif
- }
- break;
- }
- state++;
- //Draw the buffer we've created
- WriteConsoleOutput(arguments.caller->current_Console,drawnCharacters,arrayBounds,arguments.caller->origin,&drawRect);
- Sleep(arguments.sleepInterval);
- while (arguments.caller->animationLocked == true) {Sleep(1);}; //Wait until we can lock it
- arguments.caller->animationLocked = true;
- if (arguments.caller->animationThreads[currentThread] == TERMINATE || arguments.caller->animationThreads[currentThread] == CLEAR) {
- break;
- }
- arguments.caller->animationLocked = false;
- }
- if (arguments.caller->animationThreads[currentThread] == CLEAR) {
- for(register unsigned int idx = 0; idx <= width*height;idx++) {
- #ifdef _UNICODE
- drawnCharacters[idx].Char.UnicodeChar = arguments.unusedChar;
- #else
- drawnCharacters[idx].Char.AsciiChar = arguments.unusedChar;
- #endif
- }
- WriteConsoleOutput(arguments.caller->current_Console,drawnCharacters,arrayBounds,arguments.caller->origin,&drawRect);
- }
- arguments.caller->animationLocked = false;
- delete [] drawnCharacters;
- return 0;
- }
- LPTSTR consoleToolsProvider::getTextOfCommand(const LPTSTR command)
- {
- DWORD nothing;
- HANDLE hBatchFile, hTempFile;
- LPTSTR result;
- //Initialize random number generator
- static unsigned int randSeed = 0;
- if (randSeed == 0) {
- randSeed = (unsigned int) time(NULL);
- }
- std::srand(randSeed);
- //
- //Generate a random batch file name
- //
- DWORD tempLen;
- tempLen = GetEnvironmentVariable(_T("temp"),NULL,NULL);
- LPTSTR batchFileName;
- batchFileName = new TCHAR[tempLen+14];
- GetEnvironmentVariable(_T("temp"),batchFileName,tempLen+14);
- _tcscat(batchFileName,_T("\\batch"));
- TCHAR * finger = batchFileName + _tcslen(batchFileName);
- for(register unsigned short int idx = 0; idx <= 3; idx++) {
- *finger = 48 + rand() % 10;
- finger++;
- }
- *finger = _T('\0');
- _tcscat(batchFileName,_T(".bat"));
- LPTSTR tempFileName = new TCHAR[tempLen+13];
- GetEnvironmentVariable(_T("temp"),tempFileName,tempLen+13);
- _tcscat(tempFileName,_T("\\text"));
- finger = tempFileName + _tcslen(tempFileName);
- for(register unsigned short int idx = 0; idx <= 3; idx++) {
- *finger = 48 + rand() % 10;
- finger++;
- }
- *finger = _T('\0');
- _tcscat(tempFileName,_T(".txt"));
- hBatchFile = CreateFile(batchFileName,GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,NULL);
- if (hBatchFile == INVALID_HANDLE_VALUE) {
- throw GetLastError();
- }
- WriteFile(hBatchFile,"@echo off\n",strlen("@echo off\n"),¬hing,NULL);
- #ifndef _UNICODE
- if (!WriteFile(hBatchFile,command,_tcslen(command)*sizeof(TCHAR),¬hing,NULL)) {
- throw GetLastError();
- }
- #else
- LPSTR commandTemp;
- char toast = '?';
- BOOL toast2 = false;
- commandTemp = new char[_tcslen(command)+1];
- WideCharToMultiByte(CP_ACP,WC_NO_BEST_FIT_CHARS|WC_COMPOSITECHECK,command,-1,commandTemp,_tcslen(command)+1,&toast,&toast2);
- if (!WriteFile(hBatchFile,commandTemp,_tcslen(command),¬hing,NULL)) {
- throw GetLastError();
- }
- delete [] commandTemp;
- #endif
- CloseHandle(hBatchFile);
- DWORD processResult;
- STARTUPINFO si = { sizeof(STARTUPINFO) };
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- PROCESS_INFORMATION pi;
- LPTSTR PROCcommmand;
- PROCcommmand = new TCHAR[_tcslen(batchFileName)+_tcslen(tempFileName) + 15];
- _tcscpy(PROCcommmand,_T("\""));
- _tcscat(PROCcommmand,batchFileName);
- _tcscat(PROCcommmand,_T("\" > \""));
- _tcscat(PROCcommmand,tempFileName);
- _tcscat(PROCcommmand,_T("\""));
- //Turn off stderror to show nothing
- HANDLE stdOld;
- stdOld = GetStdHandle(STD_ERROR_HANDLE);
- HANDLE hNullFile = CreateFile(_T("nul"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
- SetStdHandle(STD_ERROR_HANDLE,hNullFile);
- //CREATE_NO_WINDOW
- CreateProcess(NULL,PROCcommmand,NULL,NULL,false,NULL,NULL,NULL,&si,&pi);
- do
- {
- GetExitCodeProcess(pi.hProcess,&processResult);
- Sleep(50);
- } while (processResult == STILL_ACTIVE);
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- delete [] PROCcommmand;
- //Turn stderror back on
- SetStdHandle(STD_ERROR_HANDLE,stdOld);
- CloseHandle(hNullFile);
- //Wait for the process to write out stuff to disk
- Sleep(100);
- LARGE_INTEGER allocateSize;
- hTempFile = CreateFile(tempFileName,GENERIC_READ,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if (hTempFile == INVALID_HANDLE_VALUE) {
- throw GetLastError();
- }
- GetFileSizeEx(hTempFile,&allocateSize);
- result = (TCHAR *) new char[allocateSize.LowPart+1];
- ReadFile(hTempFile,(LPVOID)result,allocateSize.LowPart,¬hing,NULL);
- *((char*)result + allocateSize.LowPart) = '\0';
- CloseHandle(hTempFile);
- DeleteFile(batchFileName);
- DeleteFile(tempFileName);
- delete [] tempFileName;
- delete [] batchFileName;
- #ifdef _UNICODE
- LPTSTR resultConverted;
- resultConverted = new TCHAR[allocateSize.LowPart+1];
- MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,(LPCSTR)result,-1,resultConverted,allocateSize.LowPart+1);
- delete [] result;
- result = resultConverted;
- #endif
- return result;
- }
- void consoleToolsProvider::Error(DWORD code)
- {
- //Translate the DWORD into a usable error message.
- LPTSTR lpBuffer;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,code,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&lpBuffer,0,NULL);
- //Write the message
- WriteConsole(current_Console,lpBuffer,_tcslen(lpBuffer),NULL,NULL);
- //Free ram allocated by FormatMessage
- LocalFree(&lpBuffer);
- }
- void consoleToolsProvider::Write(const LPTSTR toWrite)
- {
- LPSTR converted;
- CHAR toast = '?';
- #ifdef _UNICODE
- BOOL toastBool;
- converted = new CHAR[_tcslen(toWrite)+1];
- WideCharToMultiByte(CP_ACP,WC_NO_BEST_FIT_CHARS|WC_COMPOSITECHECK,toWrite,-1,converted,_tcslen(toWrite)+1,&toast,&toastBool);
- #else
- converted = toWrite;
- #endif
- std::cout << converted;
- #ifdef _UNICODE
- delete [] converted;
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement