📄 dbgthrd.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: 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 + -