⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 softmode.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
字号:
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <env.h>
#define INCL_PM
#define INCL_BASE
#define INCL_DOSDEVICES
#define INCL_DOSFILEMGR
#define INCL_DOSMEMMGR
#define INCL_DOSSIGNALS
#define INCL_WINSYS
#define INCL_WINHOOKS
#define INCL_WINMESSAGEMGR
#include <os2.h>
#include <os2dbg.h>
#include <i86.h>
#include "pmhook.h"//
#include "trpimp.h"

extern BOOL APIENTRY WinLockInput( HWND, USHORT );
extern BOOL APIENTRY WinQuerySendMsg( HAB, HMQ, HMQ, PQMSG );
extern BOOL APIENTRY WinReplyMsg( HAB, HMQ, HMQ, MRESULT );
extern BOOL APIENTRY WinWakeThread( HMQ );
extern HMQ  APIENTRY WinQueueFromID( HAB, PID, TID );
extern BOOL APIENTRY WinThreadAssocQueue( HAB, HMQ );


HAB                     HabDebugger;
HWND                    HwndDebugger;

static HWND             HwndDummy;
static BOOL             InHardMode;
static BOOL             NeedHardMode = FALSE;
static HOOKPROC         *PSendMsgHookProc;
static SETHMQPROC       *PSetHmqDebugee;
static HMODULE          HookDLL;
//static HWND           DBActiveWnd;
//static HWND           DBFocusWnd;
//static HWND           AppActiveWnd;
//static HWND           AppFocusWnd;

#define MAX_QUEUES      50
static HMQ              AssumedQueues[ MAX_QUEUES ];
static int              NumAssumedQueues;

typedef struct {
    HMQ         hmq;
} thread_data;

static  unsigned long   BeginThreadSem = { 0 };
static  thread_data     *BeginThreadArg;

#define STACK_SIZE 10000

void APIENTRY SoftModeThread( thread_data *thread )
{
    QMSG        qmsg;
    ULONG       rc;
    RECTL       rcl;
    HPS         ps;

    rc = WinThreadAssocQueue( HabDebugger, thread->hmq );
    PSetHmqDebugee( thread->hmq, HwndDummy );
    rc = WinSetHook( HabDebugger, NULL, HK_SENDMSG, (PFN)PSendMsgHookProc, HookDLL );
    while( WinQuerySendMsg( HabDebugger, NULL, thread->hmq, &qmsg ) ) {
        WinReplyMsg( HabDebugger, NULL, thread->hmq, (MRESULT) 0 );
    }
    while( WinGetMsg( HabDebugger, &qmsg, 0, 0, 0 ) ) { // handle messages for task
        switch( qmsg.msg ) {
        case WM_PAINT:
            ps = WinBeginPaint( qmsg.hwnd, 0, &rcl );
            WinEndPaint( ps );
            break;
        default:
            WinDefWindowProc( qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2 );
        }
    }
    WinReleaseHook( HabDebugger, NULL, HK_SENDMSG, (PFN)PSendMsgHookProc, HookDLL );
    PSetHmqDebugee( thread->hmq, NULL );
    WinThreadAssocQueue( HabDebugger, NULL );
    WinPostMsg( HwndDebugger, WM_QUIT, 0, 0 ); // tell debugger we're done
}

static void BeginThreadHelper( void )
{
    thread_data *_arg;

    _arg = BeginThreadArg;
    DosSemClear( &BeginThreadSem );
    SoftModeThread( _arg );
    DosExit( EXIT_THREAD, 0 );
}


void BeginSoftModeThread( thread_data *arglist )
{
    TID         tid;
    SEL         sel;
    char        *stack;

    DosSemRequest( &BeginThreadSem, -1L );
    DosAllocSeg( STACK_SIZE + sizeof( thread_data ), (PSEL)&sel, 0 );
    stack = MK_FP( sel, 0 );
    BeginThreadArg = (thread_data*)stack;
    stack += sizeof( thread_data );
    *BeginThreadArg = *arglist;
    DosCreateThread( (PFNTHREAD)BeginThreadHelper, &tid, stack+STACK_SIZE );
}


char SetHardMode( char hard )
{
    char        old;

    old = NeedHardMode;
    NeedHardMode = hard;
    return( old );
}

BOOL IsPMDebugger( void )
{
    return( HabDebugger != NULL );
}

void CreateDummyWindow( void )
{
    ULONG flCreate;
    HWND        frame;

    WinRegisterClass( HabDebugger, "Dummy", WinDefWindowProc, CS_SIZEREDRAW, 0 );
    flCreate = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_MINMAX;
    frame = WinCreateStdWindow( HWND_DESKTOP, 0L, &flCreate, "Dummy",
                                    "", 0L, NULL, 99, &HwndDummy );
    if( frame == NULL ) {
        HwndDummy = HwndDebugger;
    }
}

void GrabThreadQueue( PID pid, TID tid )
{
    thread_data         thread;
    int                 i;

    if( HwndDummy == NULL ) CreateDummyWindow();
    thread.hmq = WinQueueFromID( HabDebugger, pid, tid );
    if( thread.hmq == NULL ) return;
    for( i = 0; i < NumAssumedQueues; ++i ) {
        if( thread.hmq == AssumedQueues[i] ) return;
    }
    AssumedQueues[ NumAssumedQueues ] = thread.hmq;
    ++NumAssumedQueues;
    BeginSoftModeThread( &thread );
}

void ReleaseThreadQueue( PID pid, TID tid )
{
    HMQ                 hmq;
    int                 i;

    pid=pid;tid=tid;
    hmq = WinQueueFromID( HabDebugger, pid, tid );
    if( hmq == NULL ) return;
    for( i = 0; i < NumAssumedQueues; ++i ) {
        if( hmq == AssumedQueues[i] ) {
            WinPostQueueMsg( hmq, WM_QUIT, 0, 0 ); // break one soft mode loop
            AssumedQueues[ i ] = NULL;
            break;
        }
    }
}

void ForAllTids( PID pid, void (*rtn)( PID pid, TID tid ) )
{
    TID tid;

    for( tid = 1; tid <= 256; ++tid ) {
        rtn( pid, tid );
    }
}

void WakeOneThread( PID pid, TID tid )
{
    HMQ         hmq;

    hmq = WinQueueFromID( HabDebugger, pid, tid );
    if( hmq != NULL ) {
        WinWakeThread( hmq );
    }
}

VOID WakeThreads( PID pid )
{
    ForAllTids( pid, WakeOneThread );
}

void EnterSoftMode( PID pid )
{
    if( NumAssumedQueues != 0 ) return;
    ForAllTids( pid, GrabThreadQueue );
//    AppFocusWnd = WinQueryFocus( HWND_DESKTOP, 0 );
//    AppActiveWnd = WinQueryActiveWindow( HWND_DESKTOP, 0 );
//    if( WinIsWindow( HabDebugger, DBFocusWnd ) ) WinSetFocus( HWND_DESKTOP, DBFocusWnd );
//    if( WinIsWindow( HabDebugger, DBActiveWnd ) ) WinSetActiveWindow( HWND_DESKTOP, DBActiveWnd );
}

void ExitSoftMode( PID pid )
{
    int         i;
    QMSG        qmsg;

    ForAllTids( pid, ReleaseThreadQueue );
    for( i = 0; i < NumAssumedQueues; ++i ) { // wait for NumAssumedQueues WM_QUIT messages
        while( WinGetMsg( HabDebugger, &qmsg, 0L, 0, 0 ) ) {
            WinDispatchMsg( HabDebugger, &qmsg );
        }
    }
    NumAssumedQueues = 0;
//    DBFocusWnd = WinQueryFocus( HWND_DESKTOP, 0 );
//    DBActiveWnd = WinQueryActiveWindow( HWND_DESKTOP, 0 );
//    if( WinIsWindow( HabDebugger, AppFocusWnd ) ) WinSetFocus( HWND_DESKTOP, AppFocusWnd );
//    if( WinIsWindow( HabDebugger, AppActiveWnd ) ) WinSetActiveWindow( HWND_DESKTOP, AppActiveWnd );
}

void EnterHardMode( void )
{
    if( InHardMode ) return;
    WinLockInput( 0, TRUE );
    InHardMode = TRUE;
}

void ExitHardMode( void )
{
    if( !InHardMode ) return;
    WinLockInput( 0, FALSE );
    InHardMode = FALSE;
}

void AssumeQueue( PID pid, TID tid )
{
    tid=tid;
    if( !IsPMDebugger() ) return;
    if( NeedHardMode == (char)-1 ) return;
    if( NeedHardMode ) {
        EnterHardMode();
    } else {
        EnterSoftMode( pid );
    }
}

void ReleaseQueue( PID pid, TID tid )
{
    tid=tid;
    if( !IsPMDebugger() ) return;
    if( NeedHardMode == (char)-1 ) return;
    if( NeedHardMode ) {
        ExitHardMode();
    } else {
        ExitSoftMode( pid );
    }
}

void TellSoftModeHandles( HAB hab, HWND hwnd )
{
    HabDebugger = hab;
    HwndDebugger = hwnd;
}

VOID InitSoftDebug( VOID )
{
    DosLoadModule( NULL, 0, HOOKER, &HookDLL );
    DosGetProcAddr( HookDLL, "SENDMSGHOOKPROC", (PFN*)&PSendMsgHookProc );
    DosGetProcAddr( HookDLL, "SETHMQDEBUGEE", (PFN*)&PSetHmqDebugee );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -