Jump to content
Tuts 4 You

Sending Alt+Pause (Alt+Break) to dosbox debugger???


CodeExplorer

Recommended Posts

SendInput acts in the same way with:
keybd_event('A', 0, 0, 0);
keybd_event('A', 0, KEYEVENTF_KEYUP, 0);

I found that after executing the code the key is send to the program who made the call to keybd_event
and not the program I wanted even if I set to foreground using:
    HWND w_handle = GetMainWindowHandle(GetPid());
    ::SetForegroundWindow(w_handle);

SendMessage Api won't work at all for this program!
I only could think of CreateRemoteThread(keybd_event)!
 

Link to comment

I've looked a bit to DOSBOX source code: https://sourceforge.net/p/dosbox/code-0/HEAD/tree/

			/* Non-focus priority is set to pause; check to see if we've lost window or input focus
			 * i.e. has the window been minimised or made inactive?
			 */
			if (sdl.priority.nofocus == PRIORITY_LEVEL_PAUSE) {
				if ((event.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) && (!event.active.gain)) {
					/* Window has lost focus, pause the emulator.
					 * This is similar to what PauseDOSBox() does, but the exit criteria is different.
					 * Instead of waiting for the user to hit Alt-Break, we wait for the window to
					 * regain window or input focus.
					 */
					bool paused = true;
					SDL_Event ev;

					GFX_SetTitle(-1,-1,true);
					KEYBOARD_ClrBuffer();
//					SDL_Delay(500);
//					while (SDL_PollEvent(&ev)) {
						// flush event queue.
//					}

					while (paused) {
						// WaitEvent waits for an event rather than polling, so CPU usage drops to zero
						SDL_WaitEvent(&ev);

						switch (ev.type) {
						case SDL_QUIT: throw(0); break; // a bit redundant at linux at least as the active events gets before the quit event.
						case SDL_ACTIVEEVENT:     // wait until we get window focus back
							if (ev.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) {
								// We've got focus back, so unpause and break out of the loop
								if (ev.active.gain) {
									paused = false;
									GFX_SetTitle(-1,-1,false);
								}

								/* Now poke a "release ALT" command into the keyboard buffer
								 * we have to do this, otherwise ALT will 'stick' and cause
								 * problems with the app running in the DOSBox.
								 */
								KEYBOARD_AddKey(KBD_leftalt, false);
								KEYBOARD_AddKey(KBD_rightalt, false);
							}
							break;
						}
					}
				}
			}

And the method PauseDOSBox:

static void PauseDOSBox(bool pressed) {
	if (!pressed)
		return;
	GFX_SetTitle(-1,-1,true);
	bool paused = true;
	KEYBOARD_ClrBuffer();
	SDL_Delay(500);
	SDL_Event event;
	while (SDL_PollEvent(&event)) {
		// flush event queue.
	}

	while (paused) {
		SDL_WaitEvent(&event);    // since we're not polling, cpu usage drops to 0.
		switch (event.type) {

			case SDL_QUIT: KillSwitch(true); break;
			case SDL_KEYDOWN:   // Must use Pause/Break Key to resume.
			case SDL_KEYUP:
			if(event.key.keysym.sym == SDLK_PAUSE) {

				paused = false;
				GFX_SetTitle(-1,-1,false);
				break;
			}
#if defined (MACOSX)
			if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod == KMOD_RMETA || event.key.keysym.mod == KMOD_LMETA) ) {
				/* On macs, all aps exit when pressing cmd-q */
				KillSwitch(true);
				break;
			}
#endif
		}
	}
}

My guess is that:
if(event.key.keysym.sym == SDLK_PAUSE)
is the Alt+Pause key!

 

 

Link to comment

Found a solution that works:
https://www.codeproject.com/Articles/6819/SendKeys-in-C
Still working at it. The sleep part is important!

Edit: found a way:
    HWND w_handle = GetMainWindowHandle(GetPid());
    CSendKeys sk;
    sk.AppActivate(w_handle);
    //Send "Hello world!"
    sk.SendKeys("{DELAY=22}%{BREAK}");
    sk.SendKeys("{DELAY=22}%{BREAK}");

 

Edited by CodeExplorer
Link to comment

When I am not debugging all works ok.
Now what I want to do is set breakpoint on read and when the breakpoint is reached press Alt+Pause: also break DOS box debugger: unfortunately doesn't work;

int process_id = GetPid();
if (process_id<0) return;
HardwareBreakpoint bp;

int ThreadID = 0;
m_logs1.SetLimitText(0);

UINT limit = m_logs1.GetLimitText(); //The current text limit, in bytes, for this CEdit object.

	if (RegisterHotKey(
        NULL,
        1,
        MOD_ALT,  //  | MOD_NOREPEAT
        0x43))  //0x43 is 'C'
    {
        _tprintf(_T("Hotkey 'ALT+C' registered!\n"));
    }


if (DebugActiveProcess(process_id))
{

	 bool ss=true;
   	 DEBUG_EVENT DE={0};
   	 while(ss)
   	 {
		 
   		 WaitForDebugEvent(&DE,INFINITE);
   		 LogString(GetDebugEventName(DE.dwDebugEventCode));
   		 switch(DE.dwDebugEventCode)
   		 {

   		 case CREATE_PROCESS_DEBUG_EVENT:
		{
		ThreadID = DE.dwThreadId;
		func OpenThread=(func)GetProcAddress(GetModuleHandle("KERNEL32.dll"), "OpenThread");
		HANDLE threadhandle = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | 
			THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, 0, DE.dwThreadId);

		char txt[10];
		GetDlgItemText(IDC_EDIT1, txt, 10);

		long break_address = strtol(txt, 0, 16);
		bool set_ok = bp.Set(threadhandle, (DWORD)(break_address), 4, HardwareBreakpoint::Read);
		 break;  // 00403010
		}
		 //
		 //ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);

   		 case EXIT_PROCESS_DEBUG_EVENT:
   			 ss=false;
   			 break;
		 
   		 case EXCEPTION_DEBUG_EVENT:
		{
			EXCEPTION_DEBUG_INFO& exception = DE.u.Exception;
			switch( exception.ExceptionRecord.ExceptionCode)
				{
				case EXCEPTION_SINGLE_STEP:  // Same value as EXCEPTION_BREAKPOINT
				
				Beep( 750, 300 );
				LogString("Single step");

				MSG msg = {0};
				while (GetMessage(&msg, NULL, 0, 0) != 0)
				 {
				if (msg.message == WM_HOTKEY)
				{
				ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_CONTINUE);
				break;
				}

				}



				break;
				}

		ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
		}

   		 }
   		 ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_CONTINUE);
	}	


}


}

This is the code I'm using
When I do "sk.AppActivate(w_handle);"
which does the fallowing:

bool CSendKeys::AppActivate(HWND wnd)
{
  if (wnd == NULL)
    return false;

  ::SendMessage(wnd, WM_SYSCOMMAND, SC_HOTKEY, (LPARAM) wnd);
  ::SendMessage(wnd, WM_SYSCOMMAND, SC_RESTORE, (LPARAM) wnd);
 
  ::ShowWindow(wnd, SW_SHOW);
  ::SetForegroundWindow(wnd);
  ::SetFocus(wnd);

  return true;
}

my created program stucks!
Any way I could fix this?
 

 

Link to comment

Found https://sourceforge.net/p/dosbox/code-0/HEAD/tree/dosbox/trunk/src/gui/sdlmain.cpp#l1481

#if C_DEBUG
/* Pause binds with activate-debugger */
#else
MAPPER_AddHandler(&PauseDOSBox, MK_pause, MMOD2, "pause", "Pause DBox");
#endif
 
And found SSL library
https://libsdl.org/download-2.0.php

I couldn't find the "Pause DBox" string in compiled exes.
 
Edited by CodeExplorer
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...