Example #1
0
void frobkey(int press, int release, int scan, int key, int ascii)
{
	INPUT_RECORD		ckey;
	DWORD d;
	SHORT s;

	ckey.EventType=KEY_EVENT;
	ckey.Event.KeyEvent.dwControlKeyState=0;
	if(alt)
		ckey.Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
	if(ctrl)
		ckey.Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
	if(shift)
		ckey.Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
	ckey.Event.KeyEvent.wRepeatCount=1;
	ckey.Event.KeyEvent.wVirtualKeyCode=key;	/* ALT key */
	ckey.Event.KeyEvent.wVirtualScanCode=scan;
	ckey.Event.KeyEvent.uChar.AsciiChar=ascii;
	if(press) {
		ckey.Event.KeyEvent.bKeyDown=TRUE;
		d=0;
		while(!d) {
			if(!WriteConsoleInput(console_input, &ckey, 1, &d))
				d=0;
		}
	}
	if(release) {
		ckey.Event.KeyEvent.bKeyDown=FALSE;
		d=0;
		while(!d) {
			if(!WriteConsoleInput(console_input, &ckey, 1, &d))
				d=0;
		}
	}
}
void QConsolePrivate::sendConsoleText (const QString& s)
{
  // Send the string in chunks of 512 characters. Each character is
  // translated into an equivalent keypress event.

#define TEXT_CHUNK_SIZE 512

  int len = s.length ();
  INPUT_RECORD events[TEXT_CHUNK_SIZE];
  DWORD nEvents = 0, written;
  HANDLE hStdIn = GetStdHandle (STD_INPUT_HANDLE);

  ZeroMemory (events, sizeof (events));

  for (int i = 0; i < len; i++)
    {
      QChar c = s.at (i);

      if (c == L'\r' || c == L'\n')
        {
          if (c == L'\r' && i < (len - 1) && s.at (i+1) == L'\n')
            i++;
          if (nEvents)
            {
              WriteConsoleInput (hStdIn, events, nEvents, &written);
              nEvents = 0;
              ZeroMemory (events, sizeof (events));
            }
          PostMessage (m_consoleWindow, WM_KEYDOWN, VK_RETURN, 0x001C0001);
          PostMessage (m_consoleWindow, WM_KEYDOWN, VK_RETURN, 0xC01C0001);
        }
      else
        {
          events[nEvents].EventType                        = KEY_EVENT;
          events[nEvents].Event.KeyEvent.bKeyDown          = TRUE;
          events[nEvents].Event.KeyEvent.wRepeatCount      = 1;
          events[nEvents].Event.KeyEvent.wVirtualKeyCode   =
            LOBYTE (VkKeyScan (c.unicode ()));
          events[nEvents].Event.KeyEvent.wVirtualScanCode  = 0;
          events[nEvents].Event.KeyEvent.uChar.UnicodeChar = c.unicode ();
          events[nEvents].Event.KeyEvent.dwControlKeyState = 0;
          nEvents++;
        }

      if (nEvents == TEXT_CHUNK_SIZE
          || (nEvents > 0 && i == (len - 1)))
        {
          WriteConsoleInput (hStdIn, events, nEvents, &written);
          nEvents = 0;
          ZeroMemory (events, sizeof (events));
        }
    }
}
void LogonConsole::Kill()
{
	_thread->kill=true;
#if (defined( WIN32 ) || defined( WIN64 ) )
	/* write the return keydown/keyup event */
	DWORD dwTmp;
	INPUT_RECORD ir[2];
	ir[0].EventType = KEY_EVENT;
	ir[0].Event.KeyEvent.bKeyDown = TRUE;
	ir[0].Event.KeyEvent.dwControlKeyState = 288;
	ir[0].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[0].Event.KeyEvent.wRepeatCount = 1;
	ir[0].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[0].Event.KeyEvent.wVirtualScanCode = 28;
	ir[1].EventType = KEY_EVENT;
	ir[1].Event.KeyEvent.bKeyDown = FALSE;
	ir[1].Event.KeyEvent.dwControlKeyState = 288;
	ir[1].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[1].Event.KeyEvent.wRepeatCount = 1;
	ir[1].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[1].Event.KeyEvent.wVirtualScanCode = 28;
	WriteConsoleInput (GetStdHandle(STD_INPUT_HANDLE), ir, 2, & dwTmp);
#endif
	printf("Waiting for console thread to terminate....\n");
	while(_thread != NULL)
	{
		Sleep(100);
	}
	printf("Console shut down.\n");
}
void ConsoleThread::terminate()
{
	m_threadRunning = false;
#ifdef WIN32
	/* write the return keydown/keyup event */
	DWORD dwTmp;
	INPUT_RECORD ir[2];
	ir[0].EventType = KEY_EVENT;
	ir[0].Event.KeyEvent.bKeyDown = TRUE;
	ir[0].Event.KeyEvent.dwControlKeyState = 288;
	ir[0].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[0].Event.KeyEvent.wRepeatCount = 1;
	ir[0].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[0].Event.KeyEvent.wVirtualScanCode = 28;
	ir[1].EventType = KEY_EVENT;
	ir[1].Event.KeyEvent.bKeyDown = FALSE;
	ir[1].Event.KeyEvent.dwControlKeyState = 288;
	ir[1].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[1].Event.KeyEvent.wRepeatCount = 1;
	ir[1].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[1].Event.KeyEvent.wVirtualScanCode = 28;
	WriteConsoleInput( GetStdHandle( STD_INPUT_HANDLE ), ir, 2, & dwTmp );
#endif
	printf( "Waiting for console thread to terminate....\n" );
	while( m_isRunning )
	{
		Sleep( 100 );
	}
	printf( "Console shut down.\n" );
}
Example #5
0
WORD scrollkeys() {
	HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
	INPUT_RECORD InputRecord;
	BOOL done = FALSE;

	while (!done) {
		DWORD dwInput;
		WaitForSingleObject( hConsole, INFINITE );
		if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){
			done = TRUE;
			continue;
		}
		if (InputRecord.EventType == KEY_EVENT &&
			InputRecord.Event.KeyEvent.bKeyDown ) {
			// Why not just return the key code?  (Paul Brannan 12/5/98)
			return InputRecord.Event.KeyEvent.wVirtualKeyCode;
		} else if(InputRecord.EventType == MOUSE_EVENT) {
			if(!InputRecord.Event.MouseEvent.dwEventFlags) {
				// Put the mouse's X and Y coords back into the input buffer
				WriteConsoleInput(hConsole, &InputRecord, 1, &dwInput);
				return SC_MOUSE;
			}
		}
	}
	return SC_ESC;
}
Example #6
0
static void __write_console_input(LPCWSTR str, DWORD length)
{
	if(!str || !length) return;

	INPUT_RECORD *p, *buf;
	DWORD	i = 0;
	p = buf = new INPUT_RECORD[ length ];

	for( ; i < length ; i++, p++) {
		p->EventType = KEY_EVENT;
		p->Event.KeyEvent.bKeyDown = TRUE;
		p->Event.KeyEvent.wRepeatCount = 1;
		p->Event.KeyEvent.wVirtualKeyCode = 0;
		p->Event.KeyEvent.wVirtualScanCode = 0;
		p->Event.KeyEvent.uChar.UnicodeChar = 0;
		p->Event.KeyEvent.dwControlKeyState = 0;
		if(*str == '\r') {
			str++;
			length--;
		}
		if(*str == '\n') {
			p->Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
			str++;
		} else {
			p->Event.KeyEvent.uChar.UnicodeChar = *str++;
		}
	}

	WriteConsoleInput(gStdIn, buf, length, &length);
	delete [] buf;
}
Example #7
0
void LogonConsole::Kill()
{
	_thread->kill.SetVal(true);
#ifdef WIN32
	/* write the return keydown/keyup event */
	DWORD dwTmp;
	INPUT_RECORD ir[2];
	ir[0].EventType = KEY_EVENT;
	ir[0].Event.KeyEvent.bKeyDown = TRUE;
	ir[0].Event.KeyEvent.dwControlKeyState = 288;
	ir[0].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[0].Event.KeyEvent.wRepeatCount = 1;
	ir[0].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[0].Event.KeyEvent.wVirtualScanCode = 28;
	ir[1].EventType = KEY_EVENT;
	ir[1].Event.KeyEvent.bKeyDown = FALSE;
	ir[1].Event.KeyEvent.dwControlKeyState = 288;
	ir[1].Event.KeyEvent.uChar.AsciiChar = 13;
	ir[1].Event.KeyEvent.wRepeatCount = 1;
	ir[1].Event.KeyEvent.wVirtualKeyCode = 13;
	ir[1].Event.KeyEvent.wVirtualScanCode = 28;
	WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ir, 2, & dwTmp);
#endif
	LOG_BASIC("Waiting for console thread to terminate....");
	while(_thread != NULL)
	{
		arcpro::Sleep(100);
	}
	LOG_BASIC("Console shut down.");
}
Example #8
0
static void __attribute__((destructor)) exit_console (void)
{
#if !defined(BUILDING_UTILS)
    if (!has_console)
        return;

    if (started_from_a_gui || !attached_to_console) {
        puts("\nPress any key to exit");
        _getch();
    }
    else {
        /*
         * The calling shell doesn't append a <CR> to the cmd-line when we exit a
         * GUI app. Get the prompt back by putting a <CR> in the console input queue.
         */
        HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);

        if (!started_from_a_gui && hStdin != INVALID_HANDLE_VALUE) {
            INPUT_RECORD rec;
            DWORD written;

            memset (&rec, 0, sizeof(rec));
            rec.EventType = KEY_EVENT;
            rec.Event.KeyEvent.bKeyDown = TRUE;
            rec.Event.KeyEvent.wRepeatCount = 1;
            rec.Event.KeyEvent.wVirtualKeyCode = 13;
            rec.Event.KeyEvent.uChar.AsciiChar = 13;
            WriteConsoleInput(hStdin, &rec, 1, &written);
        }
    }
    FreeConsole();  /* free allocated or attached console */
    has_console = FALSE;
#endif
}
    virtual unsigned ThreadHandlerProc(void)
    {
	CHAR boxName[50];
	DWORD err, dwWritten;
	IPCMsg msg;

	wsprintf(boxName, "ExpectInjector_pid%d", GetCurrentProcessId());

	// Create the shared memory IPC transfer mechanism by name
	// (a mailbox).
	ConsoleDebuggerIPC = 
		new CMclMailbox(IPC_NUMSLOTS, IPC_SLOTSIZE, boxName);

	// Check status.
	err = ConsoleDebuggerIPC->Status();
	if (err != NO_ERROR && err != ERROR_ALREADY_EXISTS) {
	    OutputDebugString(GetSysMsg(err));
	    delete ConsoleDebuggerIPC;
	    return 0x666;
	}

	OutputDebugString("Expect's injector DLL loaded and ready.\n");

	// forever loop receiving messages over IPC.
	while (ConsoleDebuggerIPC->GetAlertable(&msg, interrupt)) {
	    switch (msg.type) {
	    case CTRL_EVENT:
		// Generate a Ctrl+C or Ctrl+Break to cause the equivalent
		// of a SIGINT into this process.
		GenerateConsoleCtrlEvent(msg.event, 0);
		break;
	    case IRECORD:
		// Stuff it into this console as if it had been entered
		// by the user.
#ifdef IPC_MAXRECORDS
		// If IPC_MAXRECORDS is defined, we have grouped key events.
		WriteConsoleInput(console, msg.irecord, msg.event,
				  &dwWritten);
#else
		WriteConsoleInput(console, &msg.irecord, 1, &dwWritten);
#endif
		break;
	    }
	}
	delete ConsoleDebuggerIPC;
	return 0;
    }
Example #10
0
BOOL WriteText (LPCTSTR szText)
{
    DWORD			dwWritten;
    INPUT_RECORD	rec;
    char			upper, *sz;

    sz = (LPTSTR) szText;

    while (*sz)
    {
        // 13 is the code for a carriage return (\n) instead of 10.
        if (*sz == 10)
            *sz = 13;

        upper = toupper(*sz);

        rec.EventType = KEY_EVENT;
        rec.Event.KeyEvent.bKeyDown = TRUE;
        rec.Event.KeyEvent.wRepeatCount = 1;
        rec.Event.KeyEvent.wVirtualKeyCode = upper;
        rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
        rec.Event.KeyEvent.uChar.AsciiChar = *sz;
        rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
        rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;

        WriteConsoleInput(
            hStdin,
            &rec,
            1,
            &dwWritten);

        rec.Event.KeyEvent.bKeyDown = FALSE;

        WriteConsoleInput(
            hStdin,
            &rec,
            1,
            &dwWritten);

        sz++;
    }

    //ServerWindowProcCommandExecute ();

    return TRUE;
}
virtual bool WriteInput(INPUT_RECORD* Buffer, size_t Length, size_t& NumberOfEventsWritten) const override
{
	if(Global->Opt->WindowMode && Buffer->EventType==MOUSE_EVENT)
	{
		Buffer->Event.MouseEvent.dwMousePosition.Y+=GetDelta();
	}
	DWORD dwNumberOfEventsWritten = 0;
	bool Result = WriteConsoleInput(GetInputHandle(), Buffer, static_cast<DWORD>(Length), &dwNumberOfEventsWritten)!=FALSE;
	NumberOfEventsWritten = dwNumberOfEventsWritten;
	return Result;
}
	/////////////////////////////////////////////////////////////////////// 
	// GetAndSendInputThread
	// Thread procedure that monitors the console for input and sends input
	// to the child process through the input pipe.
	// This thread ends when the child application exits.
	/////////////////////////////////////////////////////////////////////// 
	DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
	{
		CHAR read_buff[256];
		DWORD nBytesWrote;
		HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
		HANDLE hconin=CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
		// Get input from our console and send it to child through the pipe.
		printf("Hmmm...\n");

		while (bRunThread)
		{
			Sleep(1000);
			INPUT_RECORD inputRecords[4];

			inputRecords[0].EventType = KEY_EVENT;
			inputRecords[0].Event.KeyEvent.bKeyDown = TRUE;
			inputRecords[0].Event.KeyEvent.uChar.UnicodeChar = '?';
			inputRecords[1].EventType = KEY_EVENT;
			inputRecords[1].Event.KeyEvent.bKeyDown = FALSE;
			inputRecords[1].Event.KeyEvent.uChar.UnicodeChar = '?';
			inputRecords[2].EventType = KEY_EVENT;
			inputRecords[2].Event.KeyEvent.bKeyDown = TRUE;
			inputRecords[2].Event.KeyEvent.dwControlKeyState = 0;
			inputRecords[2].Event.KeyEvent.uChar.UnicodeChar = '\r';
			inputRecords[2].Event.KeyEvent.wRepeatCount = 1;
			inputRecords[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
			inputRecords[2].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
			inputRecords[3].EventType = KEY_EVENT;
			inputRecords[3].Event.KeyEvent.bKeyDown = FALSE;
			inputRecords[3].Event.KeyEvent.dwControlKeyState = 0;
			inputRecords[3].Event.KeyEvent.uChar.UnicodeChar = '\r';
			inputRecords[3].Event.KeyEvent.wRepeatCount = 1;
			inputRecords[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
			inputRecords[3].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);


			if (!WriteConsoleInput(hPipeWrite,inputRecords,sizeof(inputRecords) / sizeof(*inputRecords),&nBytesWrote))
			{
				if (GetLastError() == ERROR_NO_DATA) {
					printf("NO ERROR\n");
					break; // Pipe was closed (normal exit path).
				} else {
					DisplayError("WriteConsoleInput");
				}
			} else {
				printf("Hmmm success...\n");
			}
		}

		return 1;
	}
Example #13
0
BOOL WINAPI
co_console_widget_control_handler(DWORD T)
{
	DWORD r;
	INPUT_RECORD c;

	if (!(T == CTRL_CLOSE_EVENT || T == CTRL_LOGOFF_EVENT)) 
		return false;

	memset(&c, 0, sizeof(INPUT_RECORD));
	c.EventType = KEY_EVENT;
	WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &c, 1, &r);
	return ctrl_exit = true;
}
Example #14
0
JNIEXPORT void JNICALL Java_com_yifanlu_Josh_Josh_WRITECONSOLEINPUT
  (JNIEnv *env, jclass jcls, jlong pointer, jint eventType, jintArray data, jint length)
{
    HANDLE hIn = pointerToHandle(pointer);
    INPUT_RECORD InRec;
    DWORD NumWrote;

	jint *body = env->GetIntArrayElements(data, 0);
	
	InRec.EventType = eventType;
	switch(InRec.EventType){
		case FOCUS_EVENT:
			{
				InRec.Event.FocusEvent.bSetFocus = (body[1] == 1 ? TRUE : FALSE);
				break;
			}
		case KEY_EVENT:
			{
				InRec.Event.KeyEvent.bKeyDown = (body[1] == 1 ? TRUE : FALSE);
				InRec.Event.KeyEvent.wRepeatCount = body[2];
				InRec.Event.KeyEvent.wVirtualKeyCode = body[3];
				InRec.Event.KeyEvent.wVirtualScanCode = body[4];
				InRec.Event.KeyEvent.uChar.UnicodeChar = (char)body[5];
				InRec.Event.KeyEvent.dwControlKeyState = body[6];
				break;
			}
		case MENU_EVENT:
			{
				InRec.Event.MenuEvent.dwCommandId = body[1];
				break;
			}
		case MOUSE_EVENT:
			{
				InRec.Event.MouseEvent.dwMousePosition.X = body[1];
				InRec.Event.MouseEvent.dwMousePosition.Y = body[2];
				InRec.Event.MouseEvent.dwButtonState = body[3];
				InRec.Event.MouseEvent.dwControlKeyState = body[4];
				InRec.Event.MouseEvent.dwEventFlags = body[5];
				break;
			}
		case WINDOW_BUFFER_SIZE_EVENT:
			{
				InRec.Event.WindowBufferSizeEvent.dwSize.X = body[1];
				InRec.Event.WindowBufferSizeEvent.dwSize.Y = body[2];
				break;
			}
	}

	WriteConsoleInput(hIn, &InRec, length, &NumWrote);
}
Example #15
0
void SendSequence(LPTSTR seq) {
    DWORD out;
    INPUT_RECORD in;
    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);

    in.EventType = KEY_EVENT;
    in.Event.KeyEvent.bKeyDown = TRUE;
    in.Event.KeyEvent.wRepeatCount = 1;
    in.Event.KeyEvent.wVirtualKeyCode = 0;
    in.Event.KeyEvent.wVirtualScanCode = 0;
    in.Event.KeyEvent.dwControlKeyState = 0;
    for (; *seq; ++seq) {
        in.Event.KeyEvent.uChar.UnicodeChar = *seq;
        WriteConsoleInput(hStdIn, &in, 1, &out);
    }
}
Example #16
0
void writeConsoleReturn()
{
    DWORD num_events_written;
    INPUT_RECORD inprec[2];
    DWORD vk = VK_RETURN;
    inprec[0].EventType = KEY_EVENT;
    inprec[0].Event.KeyEvent.bKeyDown = TRUE;
    inprec[0].Event.KeyEvent.wRepeatCount = 1;
    inprec[0].Event.KeyEvent.wVirtualKeyCode = vk;
    inprec[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
    inprec[0].Event.KeyEvent.uChar.UnicodeChar = MapVirtualKey(vk, MAPVK_VK_TO_CHAR);
    inprec[0].Event.KeyEvent.dwControlKeyState = 0;
    inprec[1] = inprec[0];
    inprec[1].Event.KeyEvent.bKeyDown = FALSE;

    WriteConsoleInput(gStdIn, inprec, sizeof inprec / sizeof inprec[0], &num_events_written);
}
Example #17
0
/*--------------------------------------------------------------------------*/
static void simulateCarriageReturn(void)
{
    INPUT_RECORD rec;
    DWORD written;

    memset (&rec, 0, sizeof(rec));
    rec.EventType = KEY_EVENT;
    rec.Event.KeyEvent.bKeyDown = TRUE;
    rec.Event.KeyEvent.wRepeatCount = 13;
    rec.Event.KeyEvent.uChar.AsciiChar = 13;

    if (!Win32InputStream)
    {
        Win32InputStream = GetStdHandle(STD_INPUT_HANDLE);
    }
    WriteConsoleInput(Win32InputStream, &rec, 1, &written);
}
Example #18
0
static void
win_trigger_event(struct win32_signal *ws)
{
  if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read))
    SetEvent (ws->in.read);
  else /* generate a key-press event */
    {
      DWORD tmp;
      INPUT_RECORD ir;
      HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);

      CLEAR(ir);
      ir.EventType = KEY_EVENT;
      ir.Event.KeyEvent.bKeyDown = true;
      if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp))
        msg(M_WARN|M_ERRNO, "WARN: win_trigger_event: WriteConsoleInput");
    }
}
void CHIDCmd::FlushPreCommand()
{
    bool bSysCmd = false;
	while ( m_nPreCommands > 0 )
	{
        bool bCmd = OnCommand(m_ppPreCommands[0], &bSysCmd, true);

        qDebug() << m_nPreCommands << " : " << m_ppPreCommands[0];
		m_nPreCommands--;
		delete [] m_ppPreCommands[0];
		if ( m_nPreCommands == 0 )
		{
			delete [] m_ppPreCommands;
			m_ppPreCommands = NULL;
		}
		else
		{
			char ** ppPreCommands = new char *[m_nPreCommands];
			memcpy(ppPreCommands, m_ppPreCommands + 1, m_nPreCommands * sizeof(char *));
			delete [] m_ppPreCommands;
			m_ppPreCommands = ppPreCommands;
		}

		if ( !bCmd )
		{
#ifdef Q_OS_WIN
            HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
            INPUT_RECORD ir;
            ir.EventType = KEY_EVENT;
            ir.Event.KeyEvent.bKeyDown = 1;
            ir.Event.KeyEvent.wRepeatCount = 1;
            ir.Event.KeyEvent.wVirtualKeyCode = VK_SPACE;
            ir.Event.KeyEvent.wVirtualScanCode = 0x39;
            ir.Event.KeyEvent.uChar.AsciiChar = ' ';
            ir.Event.KeyEvent.dwControlKeyState = 0x0;
            DWORD dwWrite;
            WriteConsoleInput(hIn, &ir, 1, &dwWrite);
#endif
			return;
		}
		if ( !bSysCmd )
			break;
	}
}
Example #20
0
void FlushMouseEvents()
{
	if (ghConWnd)
	{
		HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
		DWORD nTotal = 0;
		if (GetNumberOfConsoleInputEvents(h, &nTotal) && nTotal)
		{
			INPUT_RECORD *pr = (INPUT_RECORD*)calloc(nTotal, sizeof(*pr));
			if (pr && PeekConsoleInput(h, pr, nTotal, &nTotal) && nTotal)
			{
				bool bHasMouse = false;
				DWORD j = 0;
				for (DWORD i = 0; i < nTotal; i++)
				{
					if (pr[i].EventType == MOUSE_EVENT)
					{
						bHasMouse = true;
						continue;
					}
					else
					{
						if (i > j)
							pr[j] = pr[i];
						j++;
					}
				}

				// Если были мышиные события - сбросить их
				if (bHasMouse)
				{
					if (FlushConsoleInputBuffer(h))
					{
						// Но если были НЕ мышиные - вернуть их в буфер
						if (j > 0)
						{
							WriteConsoleInput(h, pr, j, &nTotal);
						}
					}
				}
			}
		}
	}
}
Example #21
0
	bool console::WriteInput(INPUT_RECORD* Buffer, size_t Length, size_t& NumberOfEventsWritten) const
	{
		if (sWindowMode)
		{
			const auto Delta = GetDelta();

			for (auto& i : span(Buffer, Length))
			{
				if (i.EventType == MOUSE_EVENT)
				{
					i.Event.MouseEvent.dwMousePosition.Y += Delta;
				}
			}
		}
		DWORD dwNumberOfEventsWritten = 0;
		bool Result = WriteConsoleInput(GetInputHandle(), Buffer, static_cast<DWORD>(Length), &dwNumberOfEventsWritten) != FALSE;
		NumberOfEventsWritten = dwNumberOfEventsWritten;
		return Result;
	}
Example #22
0
BOOL
consoleEnterCancelEvent (
    )
{

    INPUT_RECORD    Record;
    DWORD           dw;

    Record.EventType = KEY_EVENT;
    Record.Event.KeyEvent.bKeyDown            = TRUE;
    Record.Event.KeyEvent.wRepeatCount	      = 0;
    Record.Event.KeyEvent.wVirtualKeyCode     = VK_CANCEL;
    Record.Event.KeyEvent.wVirtualScanCode    = 0;
    Record.Event.KeyEvent.uChar.AsciiChar     = 0;
    Record.Event.KeyEvent.dwControlKeyState   = 0;

    PutEvent( &Record );

    Record.Event.KeyEvent.bKeyDown = TRUE;
    WriteConsoleInput( hInput, &Record, 1, &dw );

    return TRUE;
}
Example #23
0
static void stop_stdin_thread(void)
{
    if (input_thread) {
        CONSOLE_SCREEN_BUFFER_INFO sb;
        INPUT_RECORD ir = {0};
        DWORD written;

        // This is not enough because the background thread may be blocked in ReadFile
        input_run = false;
        SetEvent(input_processed);

        /* We'll soon push VK_RETURN to the console input, which will result in a newline,
           so move the cursor up one line to avoid showing it. */
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sb);
        if (sb.dwCursorPosition.Y > 0) {
            sb.dwCursorPosition.Y--;
            SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), sb.dwCursorPosition);
        }

        ir.EventType = KEY_EVENT;
        ir.Event.KeyEvent.bKeyDown = TRUE;
        ir.Event.KeyEvent.dwControlKeyState = 0;
        ir.Event.KeyEvent.uChar.AsciiChar = '\r';
        ir.Event.KeyEvent.wRepeatCount = 1;

        // Write a newline to snap the background thread out of the blocking ReadFile call
        WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &written);

        WaitForSingleObject(input_thread, INFINITE);
        CloseHandle(input_thread);
    }

    if (input_processed)
        CloseHandle(input_processed);
    if (input_available)
        CloseHandle(input_available);
}
Example #24
0
/// Main function
int Master::Run()
{
    /// worldd PID file creation
    std::string pidfile = sConfig.GetStringDefault("PidFile", "");
    if(!pidfile.empty())
    {
        uint32 pid = CreatePIDFile(pidfile);
        if( !pid )
        {
            sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
            Log::WaitBeforeContinueIfNeed();
            return 1;
        }

        sLog.outString( "Daemon PID: %u\n", pid );
    }

    ///- Start the databases
    if (!_StartDB())
    {
        Log::WaitBeforeContinueIfNeed();
        return 1;
    }

    ///- Initialize the World
    sWorld.SetInitialWorldSettings();

    #ifndef WIN32
    detachDaemon();
    #endif
    //server loaded successfully => enable async DB requests
    //this is done to forbid any async transactions during server startup!
    CharacterDatabase.AllowAsyncTransactions();
    WorldDatabase.AllowAsyncTransactions();
    LoginDatabase.AllowAsyncTransactions();

    ///- Catch termination signals
    _HookSignals();

    ///- Launch WorldRunnable thread
    ACE_Based::Thread world_thread(new WorldRunnable);
    world_thread.setPriority(ACE_Based::Highest);

    // set realmbuilds depend on mangosd expected builds, and set server online
    {
        std::string builds = AcceptableClientBuildsListStr();
        LoginDatabase.escape_string(builds);
        LoginDatabase.DirectPExecute("UPDATE realmlist SET realmflags = realmflags & ~(%u), population = 0, realmbuilds = '%s'  WHERE id = '%u'", REALM_FLAG_OFFLINE, builds.c_str(), realmID);
    }

    ACE_Based::Thread* cliThread = NULL;

#ifdef WIN32
    if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
#else
    if (sConfig.GetBoolDefault("Console.Enable", true))
#endif
    {
        ///- Launch CliRunnable thread
        cliThread = new ACE_Based::Thread(new CliRunnable);
    }

    ACE_Based::Thread* rar_thread = NULL;
    if(sConfig.GetBoolDefault ("Ra.Enable", false))
    {
        rar_thread = new ACE_Based::Thread(new RARunnable);
    }

    ///- Handle affinity for multiple processors and process priority on Windows
    #ifdef WIN32
    {
        HANDLE hProcess = GetCurrentProcess();

        uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
        if(Aff > 0)
        {
            ULONG_PTR appAff;
            ULONG_PTR sysAff;

            if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
            {
                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors

                if(!curAff )
                {
                    sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for mangosd. Accessible processors bitmask (hex): %x",Aff,appAff);
                }
                else
                {
                    if(SetProcessAffinityMask(hProcess,curAff))
                        sLog.outString("Using processors (bitmask, hex): %x", curAff);
                    else
                        sLog.outError("Can't set used processors (hex): %x",curAff);
                }
            }
            sLog.outString();
        }

        bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);

//        if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/)
        if(Prio)
        {
            if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
                sLog.outString("mangosd process priority class set to HIGH");
            else
                sLog.outError("Can't set mangosd process priority class.");
            sLog.outString();
        }
    }
    #endif

    ///- Start soap serving thread
    ACE_Based::Thread* soap_thread = NULL;

    if(sConfig.GetBoolDefault("SOAP.Enabled", false))
    {
        MaNGOSsoapRunnable *runnable = new MaNGOSsoapRunnable();

        runnable->setListenArguments(sConfig.GetStringDefault("SOAP.IP", "127.0.0.1"), sConfig.GetIntDefault("SOAP.Port", 7878));
        soap_thread = new ACE_Based::Thread(runnable);
    }

    ///- Start up freeze catcher thread
    ACE_Based::Thread* freeze_thread = NULL;
    if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0))
    {
        FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
        fdr->SetDelayTime(freeze_delay*1000);
        freeze_thread = new ACE_Based::Thread(fdr);
        freeze_thread->setPriority(ACE_Based::Highest);
    }

    ///- Launch the world listener socket
    uint16 wsport = sWorld.getConfig (CONFIG_UINT32_PORT_WORLD);
    std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0");

    if (sWorldSocketMgr->StartNetwork (wsport, bind_ip) == -1)
    {
        sLog.outError ("Failed to start network");
        Log::WaitBeforeContinueIfNeed();
        World::StopNow(ERROR_EXIT_CODE);
        // go down and shutdown the server
    }

    sWorldSocketMgr->Wait ();

    ///- Stop freeze protection before shutdown tasks
    if (freeze_thread)
    {
        freeze_thread->destroy();
        delete freeze_thread;
    }

    ///- Stop soap thread
    if(soap_thread)
    {
        soap_thread->wait();
        soap_thread->destroy();
        delete soap_thread;
    }

    ///- Set server offline in realmlist
    LoginDatabase.DirectPExecute("UPDATE realmlist SET realmflags = realmflags | %u WHERE id = '%u'", REALM_FLAG_OFFLINE, realmID);

    ///- Remove signal handling before leaving
    _UnhookSignals();

    // when the main thread closes the singletons get unloaded
    // since worldrunnable uses them, it will crash if unloaded after master
    world_thread.wait();

    if(rar_thread)
    {
        rar_thread->wait();
        rar_thread->destroy();
        delete rar_thread;
    }

    ///- Clean account database before leaving
    clearOnlineAccounts();

    // send all still queued mass mails (before DB connections shutdown)
    sMassMailMgr.Update(true);

    ///- Wait for DB delay threads to end
    CharacterDatabase.HaltDelayThread();
    WorldDatabase.HaltDelayThread();
    LoginDatabase.HaltDelayThread();

    sLog.outString( "Halting process..." );

    if (cliThread)
    {
        #ifdef WIN32

        // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
        //_exit(1);
        // send keyboard input to safely unblock the CLI thread
        INPUT_RECORD b[5];
        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
        b[0].EventType = KEY_EVENT;
        b[0].Event.KeyEvent.bKeyDown = TRUE;
        b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[0].Event.KeyEvent.wRepeatCount = 1;

        b[1].EventType = KEY_EVENT;
        b[1].Event.KeyEvent.bKeyDown = FALSE;
        b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[1].Event.KeyEvent.wRepeatCount = 1;

        b[2].EventType = KEY_EVENT;
        b[2].Event.KeyEvent.bKeyDown = TRUE;
        b[2].Event.KeyEvent.dwControlKeyState = 0;
        b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[2].Event.KeyEvent.wRepeatCount = 1;
        b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;

        b[3].EventType = KEY_EVENT;
        b[3].Event.KeyEvent.bKeyDown = FALSE;
        b[3].Event.KeyEvent.dwControlKeyState = 0;
        b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
        b[3].Event.KeyEvent.wRepeatCount = 1;
        DWORD numb;
        BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb);

        cliThread->wait();

        #else

        cliThread->destroy();

        #endif

        delete cliThread;
    }

    ///- Exit the process with specified return value
    uint8 worldExitCode = World::GetExitCode();
    FILE* exitFile = fopen("mangos-exit.log","w");
    fprintf(exitFile,"%d\n",worldExitCode);
    sLog.outString( "\nWorld exit code = %d\n",worldExitCode );
    //fprintf(exitFile,"%d",worldExitCode);
    fflush(exitFile);
    fclose(exitFile);

    return worldExitCode;
}
Example #25
0
/// Main function
int Master::Run()
{
    BigNumber seed1;
    seed1.SetRand(16 * 8);

    sLog->outString("%s (worldserver-daemon)", _FULLVERSION);
    sLog->outString("<Ctrl-C> to stop.\n");

    sLog->outString(" ______                       __");
    sLog->outString("/\\__  _\\       __          __/\\ \\__");
    sLog->outString("\\/_/\\ \\/ _ __ /\\_\\    ___ /\\_\\ \\, _\\  __  __");
    sLog->outString("   \\ \\ \\/\\`'__\\/\\ \\ /' _ `\\/\\ \\ \\ \\/ /\\ \\/\\ \\");
    sLog->outString("    \\ \\ \\ \\ \\/ \\ \\ \\/\\ \\/\\ \\ \\ \\ \\ \\_\\ \\ \\_\\ \\");
    sLog->outString("     \\ \\_\\ \\_\\  \\ \\_\\ \\_\\ \\_\\ \\_\\ \\__\\\\/`____ \\");
    sLog->outString("      \\/_/\\/_/   \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\");
    sLog->outString("                                 C O R E  /\\___/");
    sLog->outString("http://TrinityCore.org                    \\/__/\n");

    /// worldserver PID file creation
    std::string pidfile = ConfigMgr::GetStringDefault("PidFile", "");
    if (!pidfile.empty())
    {
        uint32 pid = CreatePIDFile(pidfile);
        if (!pid)
        {
            sLog->outError("Cannot create PID file %s.\n", pidfile.c_str());
            return 1;
        }

        sLog->outString("Daemon PID: %u\n", pid);
    }

    ///- Start the databases
    if (!_StartDB())
        return 1;

    // set server offline (not connectable)
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID);

    ///- Initialize the World
    sWorld->SetInitialWorldSettings();

    // Initialise the signal handlers
    WorldServerSignalHandler SignalINT, SignalTERM;
    #ifdef _WIN32
    WorldServerSignalHandler SignalBREAK;
    #endif /* _WIN32 */

    // Register worldserver's signal handlers
    ACE_Sig_Handler Handler;
    Handler.register_handler(SIGINT, &SignalINT);
    Handler.register_handler(SIGTERM, &SignalTERM);
    #ifdef _WIN32
    Handler.register_handler(SIGBREAK, &SignalBREAK);
    #endif /* _WIN32 */

    ///- Launch WorldRunnable thread
    ACE_Based::Thread world_thread(new WorldRunnable);
    world_thread.setPriority(ACE_Based::Highest);

    ACE_Based::Thread* cliThread = NULL;

#ifdef _WIN32
    if (ConfigMgr::GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
#else
    if (ConfigMgr::GetBoolDefault("Console.Enable", true))
#endif
    {
        ///- Launch CliRunnable thread
        cliThread = new ACE_Based::Thread(new CliRunnable);
    }

    ACE_Based::Thread rar_thread(new RARunnable);

    ///- Handle affinity for multiple processors and process priority on Windows
    #ifdef _WIN32
    {
        HANDLE hProcess = GetCurrentProcess();

        uint32 Aff = ConfigMgr::GetIntDefault("UseProcessors", 0);
        if (Aff > 0)
        {
            ULONG_PTR appAff;
            ULONG_PTR sysAff;

            if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
            {
                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors

                if (!curAff)
                {
                    sLog->outError("Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", Aff, appAff);
                }
                else
                {
                    if (SetProcessAffinityMask(hProcess, curAff))
                        sLog->outString("Using processors (bitmask, hex): %x", curAff);
                    else
                        sLog->outError("Can't set used processors (hex): %x", curAff);
                }
            }
            sLog->outString("");
        }

        bool Prio = ConfigMgr::GetBoolDefault("ProcessPriority", false);

        //if (Prio && (m_ServiceStatus == -1)  /* need set to default process priority class in service mode*/)
        if (Prio)
        {
            if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
                sLog->outString("worldserver process priority class set to HIGH");
            else
                sLog->outError("Can't set worldserver process priority class.");
            sLog->outString("");
        }
    }
    #endif
    //Start soap serving thread
    ACE_Based::Thread* soap_thread = NULL;

    if (ConfigMgr::GetBoolDefault("SOAP.Enabled", false))
    {
        TCSoapRunnable* runnable = new TCSoapRunnable();
        runnable->setListenArguments(ConfigMgr::GetStringDefault("SOAP.IP", "127.0.0.1"), ConfigMgr::GetIntDefault("SOAP.Port", 7878));
        soap_thread = new ACE_Based::Thread(runnable);
    }

    ///- Start up freeze catcher thread
    if (uint32 freeze_delay = ConfigMgr::GetIntDefault("MaxCoreStuckTime", 0))
    {
        FreezeDetectorRunnable* fdr = new FreezeDetectorRunnable();
        fdr->SetDelayTime(freeze_delay*1000);
        ACE_Based::Thread freeze_thread(fdr);
        freeze_thread.setPriority(ACE_Based::Highest);
    }

    ///- Launch the world listener socket
    uint16 wsport = sWorld->getIntConfig(CONFIG_PORT_WORLD);
    std::string bind_ip = ConfigMgr::GetStringDefault("BindIP", "0.0.0.0");

    if (sWorldSocketMgr->StartNetwork(wsport, bind_ip.c_str ()) == -1)
    {
        sLog->outError("Failed to start network");
        World::StopNow(ERROR_EXIT_CODE);
        // go down and shutdown the server
    }

    // set server online (allow connecting now)
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmID);

    sLog->outString("%s (worldserver-daemon) ready...", _FULLVERSION);

    // when the main thread closes the singletons get unloaded
    // since worldrunnable uses them, it will crash if unloaded after master
    world_thread.wait();
    rar_thread.wait();

    if (soap_thread)
    {
        soap_thread->wait();
        soap_thread->destroy();
        delete soap_thread;
    }

    // set server offline
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID);

    ///- Clean database before leaving
    ClearOnlineAccounts();

    _StopDB();

    sLog->outString("Halting process...");

    if (cliThread)
    {
        #ifdef _WIN32

        // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
        //_exit(1);
        // send keyboard input to safely unblock the CLI thread
        INPUT_RECORD b[5];
        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
        b[0].EventType = KEY_EVENT;
        b[0].Event.KeyEvent.bKeyDown = TRUE;
        b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[0].Event.KeyEvent.wRepeatCount = 1;

        b[1].EventType = KEY_EVENT;
        b[1].Event.KeyEvent.bKeyDown = FALSE;
        b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[1].Event.KeyEvent.wRepeatCount = 1;

        b[2].EventType = KEY_EVENT;
        b[2].Event.KeyEvent.bKeyDown = TRUE;
        b[2].Event.KeyEvent.dwControlKeyState = 0;
        b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[2].Event.KeyEvent.wRepeatCount = 1;
        b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;

        b[3].EventType = KEY_EVENT;
        b[3].Event.KeyEvent.bKeyDown = FALSE;
        b[3].Event.KeyEvent.dwControlKeyState = 0;
        b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
        b[3].Event.KeyEvent.wRepeatCount = 1;
        DWORD numb;
        WriteConsoleInput(hStdIn, b, 4, &numb);

        cliThread->wait();

        #else

        cliThread->destroy();

        #endif

        delete cliThread;
    }

    // for some unknown reason, unloading scripts here and not in worldrunnable
    // fixes a memory leak related to detaching threads from the module
    //UnloadScriptingModule();

    // Exit the process with specified return value
    return World::GetExitCode();
}
Example #26
0
BOOL SendConsoleEvent(INPUT_RECORD* pr, UINT nCount)
{
	if (!nCount || !pr)
	{
		_ASSERTE(nCount>0 && pr!=NULL);
		return FALSE;
	}

	BOOL fSuccess = FALSE;
	//// Если сейчас идет ресайз - нежелательно помещение в буфер событий
	//if (gpSrv->bInSyncResize)
	//	WaitForSingleObject(gpSrv->hAllowInputEvent, MAX_SYNCSETSIZE_WAIT);
	//DWORD nCurInputCount = 0, cbWritten = 0;
	//INPUT_RECORD irDummy[2] = {{0},{0}};
	//HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); // тут был ghConIn
	// 02.04.2010 Maks - перенесено в WaitConsoleReady
	//// 27.06.2009 Maks - If input queue is not empty - wait for a while, to avoid conflicts with FAR reading queue
	//// 19.02.2010 Maks - замена на GetNumberOfConsoleInputEvents
	////if (PeekConsoleInput(hIn, irDummy, 1, &(nCurInputCount = 0)) && nCurInputCount > 0) {
	//if (GetNumberOfConsoleInputEvents(hIn, &(nCurInputCount = 0)) && nCurInputCount > 0) {
	//	DWORD dwStartTick = GetTickCount();
	//	WARNING("Do NOT wait, but place event in Cyclic queue");
	//	do {
	//		Sleep(5);
	//		//if (!PeekConsoleInput(hIn, irDummy, 1, &(nCurInputCount = 0)))
	//		if (!GetNumberOfConsoleInputEvents(hIn, &(nCurInputCount = 0)))
	//			nCurInputCount = 0;
	//	} while ((nCurInputCount > 0) && ((GetTickCount() - dwStartTick) < MAX_INPUT_QUEUE_EMPTY_WAIT));
	//}
	INPUT_RECORD* prNew = NULL;
	int nAllCount = 0;
	BOOL lbReqEmpty = FALSE;

	for (UINT n = 0; n < nCount; n++)
	{
		if (pr[n].EventType != KEY_EVENT)
		{
			nAllCount++;
			if (!lbReqEmpty && (pr[n].EventType == MOUSE_EVENT))
			{
				// По всей видимости дурит консоль Windows.
				// Если в буфере сейчас еще есть мышиные события, то запись
				// в буфер возвращает ОК, но считывающее приложение получает 0-событий.
				// В итоге, получаем пропуск некоторых событий, что очень неприятно 
				// при выделении кучи файлов правой кнопкой мыши (проводкой с зажатой кнопкой)
				if (pr[n].Event.MouseEvent.dwButtonState /*== RIGHTMOST_BUTTON_PRESSED*/)
					lbReqEmpty = TRUE;
			}
		}
		else
		{
			WORD vk = pr[n].Event.KeyEvent.wVirtualKeyCode;
			if (((vk == VK_RETURN) || (vk == VK_SPACE)) && gpSrv->pAppMap)
			{
				// github#19: don't post Enter/Space KeyUp events to the console input buffer
				// Also, type in PS prompt
				// get-help Get-ChildItem -full | out-host -paging
				// And press "Enter". You'll get one waste reaction for "Enter" KeyUp
				static DWORD nLastPID = 0;
				static WORD nLastVK = 0;
				bool bBypass = false;
				if (pr[n].Event.KeyEvent.bKeyDown)
				{
					// The application may use Read only for getting the event when it is ready
					// So the application is not waiting for and simple nReadConsoleInputPID
					// will be zero most of time...
					nLastPID = gpSrv->pAppMap->Ptr()->nLastReadInputPID;
					nLastVK = nLastPID ? vk : 0;
					bBypass = true;
				}
				else
				{
					if ((nLastPID != gpSrv->pAppMap->Ptr()->nLastReadInputPID)
						|| (nLastVK != vk))
					{
						// Skip this event
						pr[n].EventType = 0;
						nLastPID = 0; nLastVK = 0;
						continue;
					}
					else
					{
						bBypass = true;
					}
				}
				// Else - allow Enter/Space KeyUp
				UNREFERENCED_PARAMETER(bBypass);
			}

			if (!pr[n].Event.KeyEvent.wRepeatCount)
			{
				_ASSERTE(pr[n].Event.KeyEvent.wRepeatCount!=0);
				pr[n].Event.KeyEvent.wRepeatCount = 1;
			}

			nAllCount += pr[n].Event.KeyEvent.wRepeatCount;
		}
	}

	if (nAllCount > (int)nCount)
	{
		prNew = (INPUT_RECORD*)malloc(sizeof(INPUT_RECORD)*nAllCount);

		if (prNew)
		{
			INPUT_RECORD* ppr = prNew;
			INPUT_RECORD* pprMod = NULL;

			for (UINT n = 0; n < nCount; n++)
			{
				if (!pr[n].EventType)
					continue;

				*(ppr++) = pr[n];

				if (pr[n].EventType == KEY_EVENT)
				{
					UINT nCurCount = pr[n].Event.KeyEvent.wRepeatCount;

					if (nCurCount > 1)
					{
						pprMod = (ppr-1);
						pprMod->Event.KeyEvent.wRepeatCount = 1;

						for (UINT i = 1; i < nCurCount; i++)
						{
							*(ppr++) = *pprMod;
						}
					}
				}
				else if (!lbReqEmpty && (pr[n].EventType == MOUSE_EVENT))
				{
					// По всей видимости дурит консоль Windows.
					// Если в буфере сейчас еще есть мышиные события, то запись
					// в буфер возвращает ОК, но считывающее приложение получает 0-событий.
					// В итоге, получаем пропуск некоторых событий, что очень неприятно 
					// при выделении кучи файлов правой кнопкой мыши (проводкой с зажатой кнопкой)
					if (pr[n].Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
						lbReqEmpty = TRUE;
				}
			}

			pr = prNew;
			_ASSERTE(nAllCount == (ppr-prNew));
			nCount = (UINT)(ppr-prNew);
		}
	}

	// Если не готов - все равно запишем
	DEBUGTEST(BOOL bConReady = )
	WaitConsoleReady(lbReqEmpty);


	DWORD cbWritten = 0;

#ifdef _DEBUG
	wchar_t* pszDbgCurChars = NULL;
	wchar_t szDbg[255];
	for (UINT i = 0; i < nCount; i++)
	{
		switch (pr[i].EventType)
		{
		case MOUSE_EVENT:
			_wsprintf(szDbg, SKIPLEN(countof(szDbg))
				L"*** ConEmuC.MouseEvent(X=%i,Y=%i,Btns=0x%04x,Moved=%i)\n",
				pr[i].Event.MouseEvent.dwMousePosition.X, pr[i].Event.MouseEvent.dwMousePosition.Y, pr[i].Event.MouseEvent.dwButtonState, (pr[i].Event.MouseEvent.dwEventFlags & MOUSE_MOVED));
			DEBUGSTRINPUTWRITE(szDbg);
			
			#ifdef _DEBUG
			{
				static int LastMsButton;
				if ((LastMsButton & 1) && (pr[i].Event.MouseEvent.dwButtonState == 0))
				{
					// LButton was Down, now - Up
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
				else if (!LastMsButton && (pr[i].Event.MouseEvent.dwButtonState & 1))
				{
					// LButton was Up, now - Down
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
				else
				{ //-V523
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
			}
			#endif
			break;
		case KEY_EVENT:
			{
				wchar_t szCh[3] = {pr[i].Event.KeyEvent.uChar.UnicodeChar};
				switch (szCh[0])
				{
				case 8:  szCh[0] = L'\\'; szCh[1] = L'b'; break;
				case 9:  szCh[0] = L'\\'; szCh[1] = L't'; break;
				case 10: szCh[0] = L'\\'; szCh[1] = L'r'; break;
				case 13: szCh[0] = L'\\'; szCh[1] = L'n'; break;
				case 27: szCh[0] = L'\\'; szCh[1] = L'e'; break;
				}
				_wsprintf(szDbg, SKIPLEN(countof(szDbg))
					L"*** ConEmuC.KeybdEvent(%s, VK=%u, CH=%s)\n",
					pr[i].Event.KeyEvent.bKeyDown ? L"Dn" : L"Up", pr[i].Event.KeyEvent.wVirtualKeyCode, szCh);
				DEBUGSTRINPUTWRITE(szDbg);
			}
			break;
		}

		// Only for input_bug search purposes in Debug builds
		LONG idx = (InterlockedIncrement(&gn_LogWrittenChars) & (gn_LogWrittenCharsMax-1))*2;
		if (!pszDbgCurChars) pszDbgCurChars = gs_LogWrittenChars+idx;
		if (pr[i].EventType == KEY_EVENT)
		{
			gs_LogWrittenChars[idx++] = pr[i].Event.KeyEvent.bKeyDown ? L'\\' : L'/';
			gs_LogWrittenChars[idx] = pr[i].Event.KeyEvent.uChar.UnicodeChar ? pr[i].Event.KeyEvent.uChar.UnicodeChar : L'.';
		}
		else
		{
			gs_LogWrittenChars[idx++] = L'=';
			switch (pr[i].EventType)
			{
			case MOUSE_EVENT:
				gs_LogWrittenChars[idx] = L'm'; break;
			case WINDOW_BUFFER_SIZE_EVENT:
				gs_LogWrittenChars[idx] = L'w'; break;
			case MENU_EVENT:
				gs_LogWrittenChars[idx] = L'e'; break;
			case FOCUS_EVENT:
				gs_LogWrittenChars[idx] = L'f'; break;
			default:
				gs_LogWrittenChars[idx] = L'x'; break;
			}
		}
		gs_LogWrittenChars[++idx] = 0;
	}
	int nDbgSendLen = pszDbgCurChars ? lstrlen(pszDbgCurChars) : -1;
	SetLastError(0);
#endif

	InputLogger::Log(InputLogger::Event::evt_WriteConInput, nCount);

	HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); // тут был ghConIn
	// Strange VIM reaction on xterm-keypresses
	if ((nCount > 2) && (nCount <= 32) && (pr->EventType == KEY_EVENT) && (pr->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))
	{
		DWORD nWritten = 0; cbWritten = 0;
		for (UINT n = 0; n < nCount; n++)
		{
			if ((n + 1) == nCount)
			{
				DEBUGTEST(bConReady = ) WaitConsoleReady(TRUE);
			}
			fSuccess = WriteConsoleInput(hIn, pr+n, 1, &nWritten);
			if (fSuccess) cbWritten += nWritten;
		}
Example #27
0
/// Main function
int Master::Run()
{
    /// worldd PID file creation
    std::string pidfile = sConfig.GetStringDefault("PidFile", "");
    if(!pidfile.empty())
    {
        uint32 pid = CreatePIDFile(pidfile);
        if( !pid )
        {
            sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
            return 1;
        }

        sLog.outString( "Daemon PID: %u\n", pid );
    }

    ///- Start the databases
    if (!_StartDB())
        return 1;

    ///- Initialize the World
    sWorld.SetInitialWorldSettings();

    ///- Catch termination signals
    _HookSignals();

    ///- Launch WorldRunnable thread
    ACE_Based::Thread world_thread(new WorldRunnable);
    world_thread.setPriority(ACE_Based::Highest);

    // set server online
    loginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID);

    ACE_Based::Thread* cliThread = NULL;

#ifdef WIN32
    if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
#else
    if (sConfig.GetBoolDefault("Console.Enable", true))
#endif
    {
        ///- Launch CliRunnable thread
        cliThread = new ACE_Based::Thread(new CliRunnable);
    }

    ACE_Based::Thread rar_thread(new RARunnable);

    ///- Handle affinity for multiple processors and process priority on Windows
    #ifdef WIN32
    {
        HANDLE hProcess = GetCurrentProcess();

        uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
        if(Aff > 0)
        {
            ULONG_PTR appAff;
            ULONG_PTR sysAff;

            if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
            {
                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors

                if(!curAff )
                {
                    sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for mangosd. Accessible processors bitmask (hex): %x",Aff,appAff);
                }
                else
                {
                    if(SetProcessAffinityMask(hProcess,curAff))
                        sLog.outString("Using processors (bitmask, hex): %x", curAff);
                    else
                        sLog.outError("Can't set used processors (hex): %x",curAff);
                }
            }
            sLog.outString();
        }

        bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);

//        if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/)
        if(Prio)
        {
            if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
                sLog.outString("mangosd process priority class set to HIGH");
            else
                sLog.outError("ERROR: Can't set mangosd process priority class.");
            sLog.outString();
        }
    }
    #endif

    uint32 realCurrTime, realPrevTime;
    realCurrTime = realPrevTime = getMSTime();

    uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME);

    ///- Start up freeze catcher thread
    if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0))
    {
        FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
        fdr->SetDelayTime(freeze_delay*1000);
        ACE_Based::Thread freeze_thread(fdr);
        freeze_thread.setPriority(ACE_Based::Highest);
    }

    ///- Launch the world listener socket
    port_t wsport = sWorld.getConfig (CONFIG_PORT_WORLD);
    std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0");

    if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1)
    {
        sLog.outError ("Failed to start network");
        World::StopNow(ERROR_EXIT_CODE);
        // go down and shutdown the server
    }

    sWorldSocketMgr->Wait ();

    // set server offline
    loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID);

    ///- Remove signal handling before leaving
    _UnhookSignals();

    // when the main thread closes the singletons get unloaded
    // since worldrunnable uses them, it will crash if unloaded after master
    world_thread.wait();
    rar_thread.wait ();

    ///- Clean database before leaving
    clearOnlineAccounts();

    ///- Wait for delay threads to end
    CharacterDatabase.HaltDelayThread();
    WorldDatabase.HaltDelayThread();
    loginDatabase.HaltDelayThread();

    sLog.outString( "Halting process..." );

    if (cliThread)
    {
        #ifdef WIN32

        // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
        //_exit(1);
        // send keyboard input to safely unblock the CLI thread
        INPUT_RECORD b[5];
        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
        b[0].EventType = KEY_EVENT;
        b[0].Event.KeyEvent.bKeyDown = TRUE;
        b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[0].Event.KeyEvent.wRepeatCount = 1;

        b[1].EventType = KEY_EVENT;
        b[1].Event.KeyEvent.bKeyDown = FALSE;
        b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[1].Event.KeyEvent.wRepeatCount = 1;

        b[2].EventType = KEY_EVENT;
        b[2].Event.KeyEvent.bKeyDown = TRUE;
        b[2].Event.KeyEvent.dwControlKeyState = 0;
        b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[2].Event.KeyEvent.wRepeatCount = 1;
        b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;

        b[3].EventType = KEY_EVENT;
        b[3].Event.KeyEvent.bKeyDown = FALSE;
        b[3].Event.KeyEvent.dwControlKeyState = 0;
        b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
        b[3].Event.KeyEvent.wRepeatCount = 1;
        DWORD numb;
        BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb);

        cliThread->wait();

        #else

        cliThread->destroy();

        #endif

        delete cliThread;
    }

    // for some unknown reason, unloading scripts here and not in worldrunnable
    // fixes a memory leak related to detaching threads from the module
    UnloadScriptingModule();

    // Exit the process with specified return value
    return World::GetExitCode();
}
Example #28
0
BOOL SendConsoleEvent(INPUT_RECORD* pr, UINT nCount)
{
	if (!nCount || !pr)
	{
		_ASSERTE(nCount>0 && pr!=NULL);
		return FALSE;
	}

	BOOL fSuccess = FALSE;
	//// Если сейчас идет ресайз - нежелательно помещение в буфер событий
	//if (gpSrv->bInSyncResize)
	//	WaitForSingleObject(gpSrv->hAllowInputEvent, MAX_SYNCSETSIZE_WAIT);
	//DWORD nCurInputCount = 0, cbWritten = 0;
	//INPUT_RECORD irDummy[2] = {{0},{0}};
	//HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); // тут был ghConIn
	// 02.04.2010 Maks - перенесено в WaitConsoleReady
	//// 27.06.2009 Maks - If input queue is not empty - wait for a while, to avoid conflicts with FAR reading queue
	//// 19.02.2010 Maks - замена на GetNumberOfConsoleInputEvents
	////if (PeekConsoleInput(hIn, irDummy, 1, &(nCurInputCount = 0)) && nCurInputCount > 0) {
	//if (GetNumberOfConsoleInputEvents(hIn, &(nCurInputCount = 0)) && nCurInputCount > 0) {
	//	DWORD dwStartTick = GetTickCount();
	//	WARNING("Do NOT wait, but place event in Cyclic queue");
	//	do {
	//		Sleep(5);
	//		//if (!PeekConsoleInput(hIn, irDummy, 1, &(nCurInputCount = 0)))
	//		if (!GetNumberOfConsoleInputEvents(hIn, &(nCurInputCount = 0)))
	//			nCurInputCount = 0;
	//	} while ((nCurInputCount > 0) && ((GetTickCount() - dwStartTick) < MAX_INPUT_QUEUE_EMPTY_WAIT));
	//}
	INPUT_RECORD* prNew = NULL;
	int nAllCount = 0;
	BOOL lbReqEmpty = FALSE;

	for (UINT n = 0; n < nCount; n++)
	{
		if (pr[n].EventType != KEY_EVENT)
		{
			nAllCount++;
			if (!lbReqEmpty && (pr[n].EventType == MOUSE_EVENT))
			{
				// По всей видимости дурит консоль Windows.
				// Если в буфере сейчас еще есть мышиные события, то запись
				// в буфер возвращает ОК, но считывающее приложение получает 0-событий.
				// В итоге, получаем пропуск некоторых событий, что очень неприятно 
				// при выделении кучи файлов правой кнопкой мыши (проводкой с зажатой кнопкой)
				if (pr[n].Event.MouseEvent.dwButtonState /*== RIGHTMOST_BUTTON_PRESSED*/)
					lbReqEmpty = TRUE;
			}
		}
		else
		{
			if (!pr[n].Event.KeyEvent.wRepeatCount)
			{
				_ASSERTE(pr[n].Event.KeyEvent.wRepeatCount!=0);
				pr[n].Event.KeyEvent.wRepeatCount = 1;
			}

			nAllCount += pr[n].Event.KeyEvent.wRepeatCount;
		}
	}

	if (nAllCount > (int)nCount)
	{
		prNew = (INPUT_RECORD*)malloc(sizeof(INPUT_RECORD)*nAllCount);

		if (prNew)
		{
			INPUT_RECORD* ppr = prNew;
			INPUT_RECORD* pprMod = NULL;

			for(UINT n = 0; n < nCount; n++)
			{
				*(ppr++) = pr[n];

				if (pr[n].EventType == KEY_EVENT)
				{
					UINT nCurCount = pr[n].Event.KeyEvent.wRepeatCount;

					if (nCurCount > 1)
					{
						pprMod = (ppr-1);
						pprMod->Event.KeyEvent.wRepeatCount = 1;

						for(UINT i = 1; i < nCurCount; i++)
						{
							*(ppr++) = *pprMod;
						}
					}
				}
				else if (!lbReqEmpty && (pr[n].EventType == MOUSE_EVENT))
				{
					// По всей видимости дурит консоль Windows.
					// Если в буфере сейчас еще есть мышиные события, то запись
					// в буфер возвращает ОК, но считывающее приложение получает 0-событий.
					// В итоге, получаем пропуск некоторых событий, что очень неприятно 
					// при выделении кучи файлов правой кнопкой мыши (проводкой с зажатой кнопкой)
					if (pr[n].Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
						lbReqEmpty = TRUE;
				}
			}

			pr = prNew;
			_ASSERTE(nAllCount == (ppr-prNew));
			nCount = (UINT)(ppr-prNew);
		}
	}

	// Если не готов - все равно запишем
	DEBUGTEST(BOOL bConReady = )
	WaitConsoleReady(lbReqEmpty);


	DWORD cbWritten = 0;

#ifdef _DEBUG
	wchar_t* pszDbgCurChars = NULL;
	wchar_t szDbg[255];
	for (UINT i = 0; i < nCount; i++)
	{
		if (pr[i].EventType == MOUSE_EVENT)
		{
			_wsprintf(szDbg, SKIPLEN(countof(szDbg))
				L"*** ConEmuC.MouseEvent(X=%i,Y=%i,Btns=0x%04x,Moved=%i)\n",
				pr[i].Event.MouseEvent.dwMousePosition.X, pr[i].Event.MouseEvent.dwMousePosition.Y, pr[i].Event.MouseEvent.dwButtonState, (pr[i].Event.MouseEvent.dwEventFlags & MOUSE_MOVED));
			DEBUGSTRINPUTWRITE(szDbg);
			
			#ifdef _DEBUG
			{
				static int LastMsButton;
				if ((LastMsButton & 1) && (pr[i].Event.MouseEvent.dwButtonState == 0))
				{
					// LButton was Down, now - Up
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
				else if (!LastMsButton && (pr[i].Event.MouseEvent.dwButtonState & 1))
				{
					// LButton was Up, now - Down
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
				else
				{ //-V523
					LastMsButton = pr[i].Event.MouseEvent.dwButtonState;
				}
			}
			#endif
		}

		// Only for input_bug search purposes in Debug builds
		LONG idx = (InterlockedIncrement(&gn_LogWrittenChars) & (gn_LogWrittenCharsMax-1))*2;
		if (!pszDbgCurChars) pszDbgCurChars = gs_LogWrittenChars+idx;
		if (pr[i].EventType == KEY_EVENT)
		{
			gs_LogWrittenChars[idx++] = pr[i].Event.KeyEvent.bKeyDown ? L'\\' : L'/';
			gs_LogWrittenChars[idx] = pr[i].Event.KeyEvent.uChar.UnicodeChar ? pr[i].Event.KeyEvent.uChar.UnicodeChar : L'.';
		}
		else
		{
			gs_LogWrittenChars[idx++] = L'=';
			switch (pr[i].EventType)
			{
			case MOUSE_EVENT:
				gs_LogWrittenChars[idx] = L'm'; break;
			case WINDOW_BUFFER_SIZE_EVENT:
				gs_LogWrittenChars[idx] = L'w'; break;
			case MENU_EVENT:
				gs_LogWrittenChars[idx] = L'e'; break;
			case FOCUS_EVENT:
				gs_LogWrittenChars[idx] = L'f'; break;
			default:
				gs_LogWrittenChars[idx] = L'x'; break;
			}
		}
		gs_LogWrittenChars[++idx] = 0;
	}
	int nDbgSendLen = pszDbgCurChars ? lstrlen(pszDbgCurChars) : -1;
	SetLastError(0);
#endif


	HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); // тут был ghConIn
	fSuccess = WriteConsoleInput(hIn, pr, nCount, &cbWritten);

	// Error ERROR_INVALID_HANDLE may occurs when ConEmu was Attached to some external console with redirected input.

#ifdef _DEBUG
	DWORD dwErr = GetLastError();
	if (!fSuccess || (nCount != cbWritten))
	{
		_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"### WriteConsoleInput(Write=%i, Written=%i, Left=%i, Err=x%X)\n", nCount, cbWritten, gpSrv->InputQueue.GetNumberOfBufferEvents(), dwErr);
		DEBUGSTRINPUTWRITEFAIL(szDbg);
	}
	else
	{
		_wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"*** WriteConsoleInput(Write=%i, Written=%i, Left=%i)\n", nCount, cbWritten, gpSrv->InputQueue.GetNumberOfBufferEvents());
		DEBUGSTRINPUTWRITEALL(szDbg);
	}
	_ASSERTE((fSuccess && cbWritten==nCount) || (!fSuccess && dwErr==ERROR_INVALID_HANDLE && gbAttachMode));
#endif

	if (prNew) free(prNew);

	return fSuccess;
}
Example #29
0
/// Main function
int Master::Run()
{
    OpenSSLCrypto::threadsSetup();
    BigNumber seed1;
    seed1.SetRand(16 * 8);

    TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon)", _FULLVERSION);
    TC_LOG_INFO("server.worldserver", " ");
    TC_LOG_INFO("server.worldserver", " A World of Warcraft Cataclsym 4.3.4 Emulator  ");
    TC_LOG_INFO("server.worldserver", "       _/_/              _/          _/_/_/    _/_/    _/_/_/    _/_/_/_/  ");
    TC_LOG_INFO("server.worldserver", "    _/    _/  _/  _/_/  _/  _/    _/        _/    _/  _/    _/  _/         ");
    TC_LOG_INFO("server.worldserver", "   _/_/_/_/  _/_/      _/_/      _/        _/    _/  _/_/_/    _/_/_/      ");
    TC_LOG_INFO("server.worldserver", "  _/    _/  _/        _/  _/    _/        _/    _/  _/    _/  _/           ");
    TC_LOG_INFO("server.worldserver", " _/    _/  _/        _/    _/    _/_/_/    _/_/    _/    _/  _/_/_/_/   NG ");
    TC_LOG_INFO("server.worldserver", " Arkania Community (c) 2017!                         <http://arkania.net/> ");
    TC_LOG_INFO("server.worldserver", " ");
    TC_LOG_INFO("server.worldserver", "<Ctrl-C> to stop.\n");

    /// worldserver PID file creation
    std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
    if (!pidFile.empty())
    {
        if (uint32 pid = CreatePIDFile(pidFile))
            TC_LOG_INFO("server.worldserver", "Daemon PID: %u\n", pid);
        else
        {
            TC_LOG_ERROR("server.worldserver", "Cannot create PID file %s.\n", pidFile.c_str());
            return 1;
        }
    }

    ///- Start the databases
    if (!_StartDB())
        return 1;

    // set server offline (not connectable)
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID);

    ///- Initialize the World
    sWorld->SetInitialWorldSettings();

    ///- Initialize the signal handlers
    WorldServerSignalHandler signalINT, signalTERM;
    #ifdef _WIN32
    WorldServerSignalHandler signalBREAK;
    #endif /* _WIN32 */

    ///- Register worldserver's signal handlers
    ACE_Sig_Handler handle;
    handle.register_handler(SIGINT, &signalINT);
    handle.register_handler(SIGTERM, &signalTERM);
#ifdef _WIN32
    handle.register_handler(SIGBREAK, &signalBREAK);
#endif

    ///- Launch WorldRunnable thread
    ACE_Based::Thread worldThread(new WorldRunnable);
    worldThread.setPriority(ACE_Based::Highest);

    ACE_Based::Thread* cliThread = nullptr;

#ifdef _WIN32
    if (sConfigMgr->GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
#else
    if (sConfigMgr->GetBoolDefault("Console.Enable", true))
#endif
    {
        ///- Launch CliRunnable thread
        cliThread = new ACE_Based::Thread(new CliRunnable);
    }

    ACE_Based::Thread rarThread(new RARunnable);

#if defined(_WIN32) || defined(__linux__)
    
    ///- Handle affinity for multiple processors and process priority
    uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0);
    bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false);

#ifdef _WIN32 // Windows
    
    HANDLE hProcess = GetCurrentProcess();
    
    if (affinity > 0)
    {
        ULONG_PTR appAff;
        ULONG_PTR sysAff;
        
        if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
        {
            ULONG_PTR currentAffinity = affinity & appAff;            // remove non accessible processors
            
            if (!currentAffinity)
                TC_LOG_ERROR("server.worldserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", affinity, appAff);
            else if (SetProcessAffinityMask(hProcess, currentAffinity))
                TC_LOG_INFO("server.worldserver", "Using processors (bitmask, hex): %x", currentAffinity);
            else
                TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x", currentAffinity);
        }
    }
    
    if (highPriority)
    {
        if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
            TC_LOG_INFO("server.worldserver", "worldserver process priority class set to HIGH");
        else
            TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class.");
    }
    
#else // Linux
    
    if (affinity > 0)
    {
        cpu_set_t mask;
        CPU_ZERO(&mask);

        for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i)
            if (affinity & (1 << i))
                CPU_SET(i, &mask);

        if (sched_setaffinity(0, sizeof(mask), &mask))
            TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno));
        else
        {
            CPU_ZERO(&mask);
            sched_getaffinity(0, sizeof(mask), &mask);
            TC_LOG_INFO("server.worldserver", "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask));
        }
    }

    if (highPriority)
    {
        if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY))
            TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class, error: %s", strerror(errno));
        else
            TC_LOG_INFO("server.worldserver", "worldserver process priority class set to %i", getpriority(PRIO_PROCESS, 0));
    }
    
#endif
#endif

    //Start soap serving thread
    ACE_Based::Thread* soapThread = nullptr;

    if (sConfigMgr->GetBoolDefault("SOAP.Enabled", false))
    {
        TCSoapRunnable* runnable = new TCSoapRunnable();
        runnable->SetListenArguments(sConfigMgr->GetStringDefault("SOAP.IP", "127.0.0.1"), uint16(sConfigMgr->GetIntDefault("SOAP.Port", 7878)));
        soapThread = new ACE_Based::Thread(runnable);
    }

    ///- Start up freeze catcher thread
    if (uint32 freezeDelay = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0))
    {
        FreezeDetectorRunnable* fdr = new FreezeDetectorRunnable();
        fdr->SetDelayTime(freezeDelay * 1000);
        ACE_Based::Thread freezeThread(fdr);
        freezeThread.setPriority(ACE_Based::Highest);
    }

    ///- Launch the world listener socket
    uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD));
    std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");

    if (sWorldSocketMgr->StartNetwork(worldPort, bindIp.c_str()) == -1)
    {
        TC_LOG_ERROR("server.worldserver", "Failed to start network");
        World::StopNow(ERROR_EXIT_CODE);
        // go down and shutdown the server
    }

    // set server online (allow connecting now)
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmID);

    TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", _FULLVERSION);

#ifdef _DEBUG
    ASSERT(false);  // my debugging stop
#endif

    // when the main thread closes the singletons get unloaded
    // since worldrunnable uses them, it will crash if unloaded after master
    worldThread.wait();
    rarThread.wait();

    if (soapThread)
    {
        soapThread->wait();
        soapThread->destroy();
        delete soapThread;
    }

    // set server offline
    LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID);

    ///- Clean database before leaving
    ClearOnlineAccounts();

    _StopDB();

    TC_LOG_INFO("server.worldserver", "Halting process...");

    if (cliThread)
    {
        #ifdef _WIN32

        // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
        //_exit(1);
        // send keyboard input to safely unblock the CLI thread
        INPUT_RECORD b[4];
        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
        b[0].EventType = KEY_EVENT;
        b[0].Event.KeyEvent.bKeyDown = TRUE;
        b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[0].Event.KeyEvent.wRepeatCount = 1;

        b[1].EventType = KEY_EVENT;
        b[1].Event.KeyEvent.bKeyDown = FALSE;
        b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[1].Event.KeyEvent.wRepeatCount = 1;

        b[2].EventType = KEY_EVENT;
        b[2].Event.KeyEvent.bKeyDown = TRUE;
        b[2].Event.KeyEvent.dwControlKeyState = 0;
        b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[2].Event.KeyEvent.wRepeatCount = 1;
        b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;

        b[3].EventType = KEY_EVENT;
        b[3].Event.KeyEvent.bKeyDown = FALSE;
        b[3].Event.KeyEvent.dwControlKeyState = 0;
        b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
        b[3].Event.KeyEvent.wRepeatCount = 1;
        DWORD numb;
        WriteConsoleInput(hStdIn, b, 4, &numb);

        cliThread->wait();

        #else

        cliThread->destroy();

        #endif

        delete cliThread;
    }

    // for some unknown reason, unloading scripts here and not in worldrunnable
    // fixes a memory leak related to detaching threads from the module
    //UnloadScriptingModule();

    OpenSSLCrypto::threadsCleanup();
    // Exit the process with specified return value
    return World::GetExitCode();
}
Example #30
0
// Main function
int Master::Run()
{
    sLog.outString("%s [core-daemon]", _FULLVERSION);
    sLog.outString("<Ctrl-C> to stop.");
    sLog.outString(" ");
    sLog.outString("              BBBBBB                BBB     ");
    sLog.outString("          BBBB:..:::BB        BBBBBBBBB     ");
    sLog.outString("         B:::::BBB:::B      BB:....:::B     ");
    sLog.outString("          BB:::B BB::B     B:::BBBB:::B     ");
    sLog.outString("           B:::B BB:.B    B:::B    BB.:B    ");
    sLog.outString("           B:::BBB::BBB  BB::B      BB.B    ");
    sLog.outString("           B.:..BBB....BBB.:.B              ");
    sLog.outString("           B...BB  BB..:BB...B              ");
    sLog.outString("           B...B    B..:BB...B              ");
    sLog.outString("           B...B    B..BBB...B              ");
    sLog.outString("           B...B   BB.BBBB...B              ");
    sLog.outString("           B...B BB:.BB  B...BB             ");
    sLog.outString("          B: . B. :BB     B . B        BBB  ");
    sLog.outString("         B: ..:BBBB       B:  .B      BB .B ");
    sLog.outString("          BBBBB            B.  :B     B.: B ");
    sLog.outString("                            B.  :BB    BB:BB");
    sLog.outString("     BlizzLikeCore 2012(c)   BB   BBBBBBB B ");
    sLog.outString("  <blizzlike.servegame.com>    BBB.    .BB  ");
    sLog.outString("                                 BBBBBBBB   ");
    sLog.outString(" ");

    // worldd PID file creation
    std::string pidfile = sConfig.GetStringDefault("PidFile", "");
    if (!pidfile.empty())
    {
        uint32 pid = CreatePIDFile(pidfile);
        if (!pid)
        {
            sLog.outError("Cannot create PID file %s.\n", pidfile.c_str());
            return 1;
        }

        sLog.outString("Daemon PID: %u\n", pid);
    }

    // Start the databases
    if (!_StartDB())
        return 1;

    // Initialize the World
    sWorld.SetInitialWorldSettings();

    // Catch termination signals
    _HookSignals();

    // Launch WorldRunnable thread
    ACE_Based::Thread world_thread(new WorldRunnable);
    world_thread.setPriority(ACE_Based::Highest);

    // set realmbuilds depend on BlizzLikeCore expected builds, and set server online
    std::string builds = AcceptableClientBuildsListStr();
    LoginDatabase.escape_string(builds);
    LoginDatabase.PExecute("UPDATE realmlist SET realmflags = realmflags & ~(%u), population = 0, realmbuilds = '%s'  WHERE id = '%d'", REALM_FLAG_OFFLINE, builds.c_str(), realmID);

    ACE_Based::Thread* cliThread = NULL;

#ifdef _WIN32
    if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/)
#else
    if (sConfig.GetBoolDefault("Console.Enable", true))
#endif
    {
        // Launch CliRunnable thread
        cliThread = new ACE_Based::Thread(new CliRunnable);
    }

    ACE_Based::Thread rar_thread(new RARunnable);

    // Handle affinity for multiple processors and process priority on Windows
    #ifdef _WIN32
    {
        HANDLE hProcess = GetCurrentProcess();

        uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
        if (Aff > 0)
        {
            ULONG_PTR appAff;
            ULONG_PTR sysAff;

            if (GetProcessAffinityMask(hProcess,&appAff,&sysAff))
            {
                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors

                if (!curAff)
                {
                    sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for BlizzLikeCore. Accessible processors bitmask (hex): %x",Aff,appAff);
                }
                else
                {
                    if (SetProcessAffinityMask(hProcess,curAff))
                        sLog.outString("Using processors (bitmask, hex): %x", curAff);
                    else
                        sLog.outError("Can't set used processors (hex): %x",curAff);
                }
            }
            sLog.outString();
        }

        bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);

        if (Prio)
        {
            if (SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
                sLog.outString("BlizzLikeCore process priority class set to HIGH");
            else
                sLog.outError("ERROR: Can't set BlizzLikeCore process priority class.");
            sLog.outString();
        }
    }
    #endif

    // Start soap serving thread
    ACE_Based::Thread* soap_thread = NULL;

    if (sConfig.GetBoolDefault("SOAP.Enabled", false))
    {
        BCSoapRunnable *runnable = new BCSoapRunnable();

        runnable->setListenArguments(sConfig.GetStringDefault("SOAP.IP", "127.0.0.1"), sConfig.GetIntDefault("SOAP.Port", 7878));
        soap_thread = new ACE_Based::Thread(runnable);
    }

    uint32 realCurrTime, realPrevTime;
    realCurrTime = realPrevTime = getMSTime();

    uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME);

    // Start up freeze catcher thread
    ACE_Based::Thread* freeze_thread = NULL;
    if (uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0))
    {
        FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable();
        fdr->SetDelayTime(freeze_delay*1000);
        freeze_thread = new ACE_Based::Thread(fdr);
        freeze_thread->setPriority(ACE_Based::Highest);
    }

    // Launch the world listener socket
    uint16 wsport = sWorld.getConfig(CONFIG_PORT_WORLD);
    std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0");

    if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1)
    {
        sLog.outError("Failed to start network");
        World::StopNow(ERROR_EXIT_CODE);
        // go down and shutdown the server
    }

    sWorldSocketMgr->Wait();

    // Stop freeze protection before shutdown tasks
    if (freeze_thread)
    {
        freeze_thread->destroy();
        delete freeze_thread;
    }

    // Stop soap thread
    if (soap_thread)
    {
        soap_thread->wait();
        soap_thread->destroy();
        delete soap_thread;
    }

    // Set server offline in realmlist
    LoginDatabase.PExecute("UPDATE realmlist SET realmflags = realmflags | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID);

    // Remove signal handling before leaving
    _UnhookSignals();

    // when the main thread closes the singletons get unloaded
    // since worldrunnable uses them, it will crash if unloaded after master
    world_thread.wait();
    rar_thread.wait ();

    // Clean account database before leaving
    clearOnlineAccounts();

    // Wait for delay threads to end
    CharacterDatabase.HaltDelayThread();
    WorldDatabase.HaltDelayThread();
    LoginDatabase.HaltDelayThread();

    sLog.outString("Halting process...");

    if (cliThread)
    {
        #ifdef _WIN32

        // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
        //_exit(1);
        // send keyboard input to safely unblock the CLI thread
        INPUT_RECORD b[5];
        HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
        b[0].EventType = KEY_EVENT;
        b[0].Event.KeyEvent.bKeyDown = TRUE;
        b[0].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[0].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[0].Event.KeyEvent.wRepeatCount = 1;

        b[1].EventType = KEY_EVENT;
        b[1].Event.KeyEvent.bKeyDown = FALSE;
        b[1].Event.KeyEvent.uChar.AsciiChar = 'X';
        b[1].Event.KeyEvent.wVirtualKeyCode = 'X';
        b[1].Event.KeyEvent.wRepeatCount = 1;

        b[2].EventType = KEY_EVENT;
        b[2].Event.KeyEvent.bKeyDown = TRUE;
        b[2].Event.KeyEvent.dwControlKeyState = 0;
        b[2].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[2].Event.KeyEvent.wRepeatCount = 1;
        b[2].Event.KeyEvent.wVirtualScanCode = 0x1c;

        b[3].EventType = KEY_EVENT;
        b[3].Event.KeyEvent.bKeyDown = FALSE;
        b[3].Event.KeyEvent.dwControlKeyState = 0;
        b[3].Event.KeyEvent.uChar.AsciiChar = '\r';
        b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
        b[3].Event.KeyEvent.wVirtualScanCode = 0x1c;
        b[3].Event.KeyEvent.wRepeatCount = 1;
        DWORD numb;
        WriteConsoleInput(hStdIn, b, 4, &numb);

        cliThread->wait();

        #else

        cliThread->destroy();

        #endif

        delete cliThread;
    }

    // for some unknown reason, unloading scripts here and not in worldrunnable
    // fixes a memory leak related to detaching threads from the module
    //UnloadScriptingModule();

    // Exit the process with specified return value
    return World::GetExitCode();
}