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

📄 dbgthrd.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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:  Service thread for local debugging with GUI debugger.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include "srvcdbg.h"
#include "stdnt.h"
#include "trperr.h"


typedef enum {
    CTL_START,
    CTL_STOP,
    CTL_WAIT,
    CTL_CONTINUE
}   ctl_request;

static struct {
    // control overhead
    ctl_request request;
    HANDLE      requestsem;
    HANDLE      requestdonesem;
    HANDLE      hThread;
    BOOL        on_control_thread;
    BOOL        control_thread_running;
    BOOL        req_done;

    // CTL_*
    BOOL        rc;

    // CTL_START
    DWORD       pid;
    DWORD       flags;
    char        *name;

    // CTL_CONTINUE
    DWORD       how;
    DWORD       err;

}               Shared;


static void CantDoIt( void )
{
    if( PendingProgramInterrupt ) {
        if( MessageBox( 0, TRP_WIN_wanna_kill, TRP_The_WATCOM_Debugger,
                    MB_SYSTEMMODAL + MB_YESNO + MB_ICONQUESTION ) == IDYES ) {
            Terminate();
        }
    } else if( MessageBox( 0, TRP_WIN_wanna_interrupt, TRP_The_WATCOM_Debugger,
                  MB_SYSTEMMODAL + MB_YESNO + MB_ICONQUESTION ) == IDYES ) {
        InterruptProgram();
    }
}

/*
 * DoContinueDebugEvent
 */
static BOOL DoContinueDebugEvent( DWORD continue_how )
{
    SetLastError( 0 );
    if( !DidWaitForDebugEvent ) {
        return( FALSE );
    }
    return( ContinueDebugEvent( DebugeePid, LastDebugEventTid, continue_how ) );
}

static void StopDebuggee( void );
static void RequestDone( void );
static BOOL StartDebuggee( void );
static BOOL DoWaitForDebugEvent( void );

static bool DoOneControlRequest( void )
{
    Shared.on_control_thread = TRUE;
    if( Shared.request == CTL_STOP ) {
        StopDebuggee();
        RequestDone();
        return( FALSE );
    } else if( Shared.request == CTL_START ) {
        Shared.err = 0;
        if( !StartDebuggee() ) {
            Shared.err = GetLastError();
        }
        RequestDone();
    } else if( Shared.request == CTL_WAIT ) {
        Shared.rc = DoWaitForDebugEvent();
        RequestDone();
    } else if( Shared.request == CTL_CONTINUE ) {
        DoContinueDebugEvent( Shared.how );
        RequestDone();
    }
    return( TRUE );
}

#define MAX_HWNDS 40 // maximum number of hwnds in the debugger
static HWND InvalidHWNDs[MAX_HWNDS];
static int  NumInvalid = 0;


// NB: ProcessQueuedRepains() currently doesn't do anything useful
void ProcessQueuedRepaints( void )
{
    int     i;
    RECT    r;

    for( i = 0; i < NumInvalid; ++i ) {
        GetWindowRect( InvalidHWNDs[i], &r );
        InvalidateRect( InvalidHWNDs[i], &r, FALSE );
    }
    NumInvalid = 0;
}

static void ControlReq( ctl_request req )
{
    MSG     msg;
    HWND    hwnd;
    BOOL    is_dbg_wnd;
    char    buff[10];

    Shared.request = req;
    if( !Shared.control_thread_running ) {
        DoOneControlRequest(); // short circuit multithread stuff
        return;
    }
    ReleaseSemaphore( Shared.requestsem, 1, NULL );
    if( !IsWindow( DebuggerWindow ) ) {
        DebuggerWindow = NULL;
    }
    if( DebuggerWindow == NULL ) {
        WaitForSingleObject( Shared.requestdonesem, INFINITE );
    } else {
        while( !Shared.req_done ) { 
            if ( !GetMessage( &msg, NULL, 0, 0 ) )
            	  break;    // break on WM_QUIT, when Windows requests this. (If ever)
            hwnd = msg.hwnd;
            is_dbg_wnd = FALSE;
            while( hwnd ) {
                if( hwnd == DebuggerWindow ) {
                    is_dbg_wnd = TRUE;
                    break;
                }
                hwnd = GetParent( hwnd );
            }
            GetClassName( msg.hwnd, buff, sizeof( buff ) - 1 );
            if( !is_dbg_wnd || strcmp( buff, "WTool" ) == 0 ) {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            } else {
                switch( msg.message ) {
                case WM_KEYDOWN:
                    if( msg.wParam == VK_CANCEL ) {
                        InterruptProgram();
                    }
                    break;
                case WM_SYSKEYDOWN: // Do not activate menu on F10 single step in GUI debugger
                	  if( msg.wParam == VK_F10 && !strcmp( buff, "GUIClass" ) ) {
                	  	  break;
                      }
                      // fall through!
                case WM_COMMAND:
                    CantDoIt();
                    break;
                case WM_LBUTTONDOWN:
                case WM_RBUTTONDOWN:
                case WM_MBUTTONDOWN:
                    CantDoIt();
                    break;
                case WM_MOUSEMOVE:
                    break;
                case WM_PAINT:
                    // WM_PAINT must be sent to the target window in order
                    // to remove it from the queue 
                    DefWindowProc( msg.hwnd, msg.message, msg.wParam, msg.lParam );
                    break;
                default:
                    DefWindowProc( DebuggerWindow, msg.message, msg.wParam,
                        msg.lParam );
                }
            }
        }
        Shared.req_done = FALSE;    // Reset  
        ReleaseSemaphore( Shared.requestdonesem, 1, NULL );
    }
}

static void RequestDone( void )
{
    if( !Shared.control_thread_running ) {
        return;
    }
    Shared.on_control_thread = FALSE;
    if( !IsWindow( DebuggerWindow ) ) {
        DebuggerWindow = NULL;
    }
    if( DebuggerWindow == NULL ) {
        ReleaseSemaphore( Shared.requestdonesem, 1, NULL );
    } else {
        Shared.req_done = TRUE; 
        // Notify that something has happened, avoid delay
        PostMessage( DebuggerWindow, WM_NULL, 0, 0 ); 
        WaitForSingleObject( Shared.requestdonesem, INFINITE );
    }
}

static DWORD WINAPI ControlFunc( void *parm )
{
    parm = parm;
    for( ;; ) {
        WaitForSingleObject( Shared.requestsem, INFINITE );
        if( !DoOneControlRequest() ) {
            break;
        }
    }
    return( 0 ); // thread over!
}

#pragma library(advapi32)
static BOOL MyDebugActiveProcess( DWORD dwPidToDebug )
{
    HANDLE              Token;
    PTOKEN_PRIVILEGES   NewPrivileges;
    BYTE                OldPriv[1024];
    PBYTE               pbOldPriv;
    ULONG               cbNeeded;
    BOOL                b;
    BOOLEAN             fRc;
    LUID                LuidPrivilege;
    size_t              extras;

    //
    // Make sure we have access to adjust and to get the old token privileges
    //
    if( !OpenProcessToken( GetCurrentProcess(),
                           TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token ) ) {
        goto done;
    }

    cbNeeded = 0;

    //
    // Initialize the privilege adjustment structure
    //

    LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege );

    extras = ( 1 - ANYSIZE_ARRAY ) * sizeof( LUID_AND_ATTRIBUTES );
    NewPrivileges = calloc( 1, sizeof( TOKEN_PRIVILEGES ) + extras );
                                                  
    if( NewPrivileges == NULL ) {
        CloseHandle( Token );
        goto done;
    }

    NewPrivileges->PrivilegeCount = 1;
    NewPrivileges->Privileges[0].Luid = LuidPrivilege;
    NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    //
    // Enable the privilege
    //

    pbOldPriv = OldPriv;
    fRc = AdjustTokenPrivileges( Token, FALSE, NewPrivileges, 1024,
            ( PTOKEN_PRIVILEGES )pbOldPriv, &cbNeeded );

    if( !fRc ) {

        //
        // If the stack was too small to hold the privileges
        // then allocate off the heap
        //
        if( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
            pbOldPriv = calloc( 1, cbNeeded );
            if( pbOldPriv == NULL ) {
                CloseHandle( Token );
                goto done;
            }

            fRc = AdjustTokenPrivileges( Token, FALSE, NewPrivileges, cbNeeded,
                    ( PTOKEN_PRIVILEGES )pbOldPriv, &cbNeeded );
        }
    }

    b = DebugActiveProcess( dwPidToDebug );

    CloseHandle( Token );

    return( b );
done:
    ;
    return( DebugActiveProcess( dwPidToDebug ) );
}

static int match( const char *p, const char *criterion )
{
    int result;

    result = strnicmp( p + 1, criterion, strlen( criterion ) ) == 0;
    return( result );
}

void ParseServiceStuff( char *name,
    char **pdll_name, char **pservice_name,
    char **pdll_destination, char **pservice_parm )
{
    char        *p;

    ( *pdll_name ) = "";
    ( *pservice_name ) = "";
    ( *pdll_destination ) = "";
    ( *pservice_parm ) = "";
    while( ( p = strrchr( name, LOAD_PROG_CHR_DELIM ) ) != NULL ) {
        if( match( p, LOAD_PROG_STR_DLLNAME ) ) {
            *p = '\0';
            ( *pdll_name ) = p + strlen( LOAD_PROG_STR_DLLNAME ) + 1;
            if( ( *pdll_name )[0] == '"' ) {
                ( *pdll_name )[strlen( *pdll_name ) - 1]= '\0';
                ( *pdll_name )++;
            }
        } else if( match( p, LOAD_PROG_STR_SERVICE ) ) {
            *p = '\0';
            ( *pservice_name ) = p + strlen( LOAD_PROG_STR_SERVICE ) + 1;
            if( ( *pservice_name )[0] == '"' ) {
                ( *pservice_name )[strlen( *pservice_name ) - 1]= '\0';
                ( *pservice_name )++;
            }
        } else if( match( p, LOAD_PROG_STR_SERVICEPARM ) ) {
            *p = '\0';
            ( *pservice_parm ) = p + strlen( LOAD_PROG_STR_SERVICEPARM ) + 1;
            if( ( *pservice_parm )[0] == '"' ) {
                ( *pservice_parm )[strlen( *pservice_parm ) - 1]= '\0';
                ( *pservice_parm )++;
            }
        } else if( match( p, LOAD_PROG_STR_COPYDIR ) ) {
            *p = '\0';
            ( *pdll_destination ) = p + strlen( LOAD_PROG_STR_COPYDIR ) + 1;
            if( ( *pdll_destination )[0] == '"' ) {
                ( *pdll_destination )[strlen( *pdll_destination ) - 1]= '\0';
                ( *pdll_destination )++;
            }
        } else {
            break;
        }
    }
}

typedef long( __stdcall *SELECTPROCESS ) ( char *name );

static BOOL StartDebuggee( void )
{
    STARTUPINFO         sinfo;
    PROCESS_INFORMATION pinfo;
    BOOL                rc;
    DWORD               oldErrorMode = SetErrorMode( 0 );
    HMODULE             mod;
    SELECTPROCESS       select;
    char                *dll_name;
    char                *service_name;
    char                *dll_destination;
    char                *service_parm;
    SC_HANDLE           service_manager;
    SC_HANDLE           service;
    SERVICE_STATUS      status;
    DWORD               i;
    char                buff[_MAX_PATH];
    char                fname[_MAX_FNAME];
    char                ext[_MAX_EXT];

    ParseServiceStuff( Shared.name, &dll_name, &service_name, &dll_destination,
        &service_parm );
    service = NULL;
    service_manager = NULL;
    if( service_name[0] ) {
        service_manager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
        if( service_manager == NULL ) {
            AddMessagePrefix( "Unable to open service manager", 0 );
            rc = FALSE;

⌨️ 快捷键说明

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