trap_retval ReqFile_string_to_fullpath( void ) { char *name; char *fullname; const char *ext_list; file_string_to_fullpath_req *acc; file_string_to_fullpath_ret *ret; tiny_ret_t rc; acc = GetInPtr( 0 ); name = GetInPtr( sizeof( *acc ) ); ret = GetOutPtr( 0 ); fullname = GetOutPtr( sizeof( *ret ) ); if( acc->file_type == TF_TYPE_EXE ) { ext_list = DosExtList; } else { ext_list = ""; } rc = FindProgFile( name, fullname, ext_list ); if( TINY_OK( rc ) ) { ret->err = 0; } else { ret->err = TINY_INFO( rc ); *fullname = '\0'; } return( sizeof( *ret ) + 1 + strlen( fullname ) ); }
trap_retval ReqProg_load( void ) { char buffer[160]; char *src; char *dst; char *name; char *endparm; const char *err; tiny_ret_t rc; prog_load_ret *ret; trap_elen len; SaveVectors( OrigVectors ); _DBG_EnterFunc( "AccLoadProg()" ); ret = GetOutPtr( 0 ); src = name = GetInPtr( sizeof( prog_load_req ) ); rc = FindProgFile( src, buffer, DosExtList ); endparm = LinkParms; while( *endparm++ != '\0' ) {} // skip trap parameters strcpy( endparm, buffer ); // add command line // result is as follow // "trap parameters string"+"\0"+"command line string"+"\0" err = RemoteLink( LinkParms, false ); if( err != NULL ) { _DBG_Writeln( "Can't RemoteLink" ); TinyWrite( TINY_ERR, err, strlen( err ) ); LoadError = err; ret->err = 1; len = 0; } else { if( TINY_OK( rc ) ) { while( *src++ != '\0' ) {} len = GetTotalSize() - ( src - name ) - sizeof( prog_load_req ); dst = (char *)buffer; while( *dst++ != '\0' ) {}; memcpy( dst, src, len ); dst += len; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( In_Mx_Ptr[0].ptr, sizeof( prog_load_req ) ); _DBG_Writeln( "AddPacket" ); AddPacket( buffer, dst - buffer ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( ret, sizeof( *ret ) ); } else { len = DoAccess(); } _DBG_Writeln( "Linked --" ); if( ret->err != 0 ) { get_err_text_req erracc; prog_kill_req killacc; trap_elen msg_len; _DBG_Writeln( "loadret->errcode != 0" ); if( LoadError == NULL ) { _DBG_Writeln( "making a REQ_GET_ERR_TEXT request" ); erracc.req = REQ_GET_ERR_TEXT; erracc.err = ret->err; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( &erracc, sizeof( erracc ) ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); msg_len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( FailMsg, msg_len ); _DBG_Write( "FailMsg : " ); _DBG_NoTabWriteln( FailMsg ); LoadError = FailMsg; } _DBG_Writeln( "making a REQ_PROG_KILL request" ); killacc.req = REQ_PROG_KILL; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( &killacc, sizeof( killacc ) ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); GetPacket(); //RemovePacket( &erracc, msg_len ); RemoteUnLink(); TaskLoaded = false; } } if( ret->err == 0 ) { _DBG_Writeln( "loadret->error_code == 0" ); TaskLoaded = true; } SaveVectors( LoadVectors ); SaveVectors( CurrVectors ); _DBG_ExitFunc( "AccLoadProg()" ); return( len ); }
/* * AccLoadProg - create a new process for debugging */ trap_retval ReqProg_load( void ) { char *parm; char *src; char *dst; char *endsrc; char exe_name[PATH_MAX]; char ch; BOOL rc; int len; MYCONTEXT con; thread_info *ti; HANDLE handle; prog_load_req *acc; prog_load_ret *ret; header_info hi; WORD stack; WORD version; DWORD pid; DWORD pid_started; DWORD cr_flags; char *buff; size_t nBuffRequired; char *dll_name; char *service_name; char *dll_destination; char *service_parm; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); parm = GetInPtr( sizeof( *acc ) ); /* * reset status variables */ LastExceptionCode = -1; DebugString = NULL; DebugeeEnded = FALSE; RemoveAllThreads(); FreeLibList(); DidWaitForDebugEvent = FALSE; DebugeePid = 0; DebugeeTid = 0; SupportingExactBreakpoints = 0; /* * check if pid is specified */ ParseServiceStuff( parm, &dll_name, &service_name, &dll_destination, &service_parm ); pid = 0; src = parm; /* // Just to be really safe! */ nBuffRequired = GetTotalSize() + PATH_MAX + 16; buff = LocalAlloc( LMEM_FIXED, nBuffRequired ); if( buff == NULL ) { ret->err = ERROR_NOT_ENOUGH_MEMORY; return( sizeof( *ret ) ); } if( *src == '#' ) { src++; pid = strtoul( src, &endsrc, 16 ); if( pid == 0 ) { pid = -1; } strcpy( buff, endsrc ); } else { while( isdigit( *src ) ) { src++; } if( *src == 0 && src != parm ) { pid = atoi( parm ); } } /* * get program to debug. If the user has specified a pid, then * skip directly to doing a DebugActiveProcess */ IsWOW = FALSE; #if !defined( MD_x64 ) IsDOS = FALSE; #endif if( pid == 0 ) { ret->err = FindProgFile( parm, exe_name, NtExtList ); if( ret->err != 0 ) { goto error_exit; } /* * Get type of application */ handle = CreateFile( (LPTSTR)exe_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if( handle == INVALID_HANDLE_VALUE ) { ret->err = GetLastError(); goto error_exit; } GetFullPathName( exe_name, MAX_PATH, CurrEXEName, NULL ); /* * get the parm list */ if( strchr( CurrEXEName, ' ' ) != NULL ) { strcpy( buff, "\"" ); strcat( buff, CurrEXEName ); strcat( buff, "\"" ); } else { strcpy( buff, CurrEXEName ); } dst = &buff[strlen( buff )]; src = parm; while( *src != 0 ) { ++src; } // parm layout // <--parameters-->0<--program_name-->0<--arguments-->0 // for( len = GetTotalSize() - sizeof( *acc ) - (src - parm) - 1; len > 0; --len ) { ch = *src; if( ch == 0 ) { ch = ' '; } *dst = ch; ++dst; ++src; } *dst = 0; cr_flags = DEBUG_ONLY_THIS_PROCESS; if( !GetEXEHeader( handle, &hi, &stack ) ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } if( hi.sig == EXE_PE ) { if( IS_PE64( hi.u.peh ) ) { DebugeeSubsystem = PE64( hi.u.peh ).subsystem; } else { DebugeeSubsystem = PE32( hi.u.peh ).subsystem; #if defined( MD_x64 ) IsWOW = TRUE; #endif } if( DebugeeSubsystem == SS_WINDOWS_CHAR ) { cr_flags |= CREATE_NEW_CONSOLE; } #if !defined( MD_x64 ) } else if( hi.sig == EXE_NE ) { IsWOW = TRUE; /* * find out the pid of WOW, if it is already running. */ pVDMEnumProcessWOW( EnumWOWProcessFunc, (LPARAM)&pid ); if( pid != 0 ) { version = LOWORD( GetVersion() ); if( LOBYTE( version ) == 3 && HIBYTE( version ) < 50 ) { int kill = MessageBox( NULL, TRP_NT_wow_warning, TRP_The_WATCOM_Debugger, MB_APPLMODAL + MB_YESNO ); if( kill == IDYES ) { DWORD axs = PROCESS_TERMINATE+STANDARD_RIGHTS_REQUIRED; HANDLE hprocess = OpenProcess( axs, FALSE, pid ); if( hprocess != 0 && TerminateProcess( hprocess, 0 ) ) { CloseHandle( hprocess ); pid = 0; } } } else { cr_flags |= CREATE_SEPARATE_WOW_VDM; pid = 0; // always start a new VDM. } } if( pid != 0 ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } } else { IsDOS = TRUE; #endif } CloseHandle( handle ); } /* * start the debugee */ pid_started = pid; if( *dll_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_DLLNAME ); strcat( buff, dll_name ); } if( *service_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICE ); strcat( buff, service_name ); } if( *dll_destination ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_COPYDIR ); strcat( buff, dll_destination ); } if( *service_parm ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICEPARM ); strcat( buff, service_parm ); } ret->err = StartControlThread( buff, &pid_started, cr_flags ); if( ret->err != 0 ) { goto error_exit; } /* * CREATE_PROCESS_DEBUG_EVENT will always be the first debug event. * If it is not, then something is horribly wrong. */ rc = MyWaitForDebugEvent(); if( !rc || ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) || ( DebugEvent.dwProcessId != pid_started ) ) { ret->err = GetLastError(); goto error_exit; } ProcessInfo.pid = DebugEvent.dwProcessId; ProcessInfo.process_handle = DebugEvent.u.CreateProcessInfo.hProcess; ProcessInfo.base_addr = DebugEvent.u.CreateProcessInfo.lpBaseOfImage; AddProcess( &hi ); AddThread( DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.hThread, DebugEvent.u.CreateProcessInfo.lpStartAddress ); DebugeePid = DebugEvent.dwProcessId; DebugeeTid = DebugEvent.dwThreadId; LastDebugEventTid = DebugEvent.dwThreadId; #if defined( MD_x86 ) #ifdef WOW if( IsWOW ) { ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } if( pid ) { addAllWOWModules(); } else { addKERNEL(); } /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD ) con.SegCs; WOWAppInfo.offset = ( WORD ) con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else if( IsDOS ) { // TODO! Clean up this code ret->flags = 0; //LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } #if 0 if( pid ) { addAllWOWModules(); } else { addKERNEL(); } #endif /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD )con.SegCs; WOWAppInfo.offset = ( WORD )con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else { #else { #endif #else { #endif LPVOID base; if( pid == 0 ) { base = (LPVOID)DebugEvent.u.CreateProcessInfo.lpStartAddress; } else { base = 0; } ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; if( executeUntilStart( pid != 0 ) ) { LPVOID old; /* * make the application load our DLL, so that we can have it * run code out of it. One small note: this will not work right * if the app does not load our DLL at the same address the * debugger loaded it at!!! */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); old = (LPVOID)AdjustIP( &con, 0 ); if( base != 0 ) { SetIP( &con, base ); } MySetThreadContext( ti, &con ); SetIP( &con, old ); MySetThreadContext( ti, &con ); } ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); #if defined( MD_x86 ) FlatCS = con.SegCs; FlatDS = con.SegDs; #endif ret->flags |= LD_FLAG_IS_BIG; } ret->flags |= LD_FLAG_HAVE_RUNTIME_DLLS; if( pid != 0 ) { ret->flags |= LD_FLAG_IS_STARTED; } ret->mod_handle = 0; error_exit: if( buff != NULL ) { LocalFree( buff ); } return( sizeof( *ret ) ); } trap_retval ReqProg_kill( void ) { prog_kill_ret *ret; ret = GetOutPtr( 0 ); ret->err = 0; DelProcess( TRUE ); StopControlThread(); return( sizeof( *ret ) ); }
/* * AccLoadProg * * To load a app, we do the following: * * Case 1: debugging an existing task * - Find its current CS:IP. * - Plant a breakpoint at the current CS:IP * * Case 2: starting a task from scratch * - Look up the start address from the .EXE * - WinExec the app * - Wait for the STARTASK notification for the app * - Plant a breakpoint at its start address * * - Wait for the app to hit the breakpoint * - Check if the app is a 32-bit app (look for "DEADBEEF" in code seg). * If it is a 32-bit app: * - Flip the "DEADBEEF" to "BEEFDEAD". If the extender see's the * "BEEFDEAD", it executes a breakpoint right before it jumps to * the 32-bit code * - Let the app run until a breakpoint is hit * - Trace one instruction. This leaves you at the first instruction * of the 32-bit code */ trap_retval ReqProg_load( void ) { char exe_name[_MAX_PATH]; char drive[_MAX_DRIVE],directory[_MAX_DIR]; char buff[256]; lm_parms loadp; word_struct cmdshow; char *parm; char *src; char *dst; char ch; unsigned a,b; private_msg pmsg; char sig[sizeof(DWORD)]; HTASK tid; DWORD csip; prog_load_req *acc; prog_load_ret *ret; char *end; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); ret->flags = LD_FLAG_IS_PROT | LD_FLAG_HAVE_RUNTIME_DLLS; parm = GetInPtr( sizeof( *acc ) ); /* * reset flags */ OutPos = 0; WasStarted = FALSE; LoadingDebugee = TRUE; Debugging32BitApp = FALSE; AddAllCurrentModules(); /* * check for task id */ tid = 0; src = parm; if( *src == '#' ) { src++; tid = (HTASK)strtol( src, NULL, 16 ); } else { while( *src != 0 ) { if( !isdigit( *src ) ) { break; } src++; } if( *src == 0 && src != parm ) { tid = (HTASK)atoi( parm ); } } if( tid != 0 ) { csip = GetRealCSIP( tid, &DebugeeModule ); if( csip == 0 ) { tid = 0; } else { DebugeeTask = tid; StopNewTask.loc.segment = FP_SEG( (LPVOID) csip ); StopNewTask.loc.offset = FP_OFF( (LPVOID) csip ); ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &StopNewTask.value, 1 ); ch = '\xcc'; WriteMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &ch, 1 ); } } else { tid = 0; } /* * get the file to execute */ if( tid == 0 ) { if( TINY_ERROR( FindProgFile( parm, exe_name, DosExtList ) ) ) { exe_name[0] = 0; } else { _splitpath( exe_name, drive, directory, NULL, NULL ); a = tolower( drive[0] ) - 'a' + 1; _dos_setdrive( a, &b ); directory[ strlen( directory ) - 1 ] = 0; chdir( directory ); } /* * get the parm list */ src = parm; while( *src != 0 ) ++src; ++src; end = GetInPtr( GetTotalSize() - 1 ); dst = &buff[1]; for( ;; ) { if( src > end ) break; ch = *src; if( ch == 0 ) ch = ' '; *dst = ch; ++dst; ++src; } if( dst > &buff[1] ) --dst; *dst = '\0'; buff[0] = dst-buff-1; /* * get starting point in task */ if( !GetStartAddress( exe_name, &StopNewTask.loc ) ) { Out((OUT_ERR,"Could not get starting address")); ret->err = WINERR_NOSTART; LoadingDebugee = FALSE; return( sizeof( *ret ) ); } StopNewTask.segment_number = StopNewTask.loc.segment; Out((OUT_LOAD,"Loading %s, cs:ip = %04x:%04lx", exe_name, StopNewTask.loc.segment, StopNewTask.loc.offset )); /* * load the task */ loadp.cmdshow = &cmdshow; loadp.wEnvSeg = 0; loadp.lpCmdLine = (LPSTR) buff; loadp.cmdshow->mustbe2 = 2; loadp.cmdshow->cmdshow = SW_NORMAL; loadp.reserved = 0L; DebuggerState = LOADING_DEBUGEE; DebugeeInstance = LoadModule( exe_name, (LPVOID) &loadp ); if( (UINT)DebugeeInstance < 32 ) { Out((OUT_ERR,"Debugee did not load %d", DebugeeInstance)); ret->err = WINERR_NOLOAD; LoadingDebugee = FALSE; return( sizeof( *ret ) ); } DebuggerWaitForMessage( WAITING_FOR_TASK_LOAD, NULL, RESTART_APP ); } AddDebugeeModule(); pmsg = DebuggerWaitForMessage( WAITING_FOR_BREAKPOINT, DebugeeTask, RESTART_APP ); if( pmsg == START_BP_HIT ) { ret->err = 0; ret->task_id = (unsigned_32)DebugeeTask; /* * look for 32-bit windows application */ ReadMem( IntResult.CS, SIG_OFF, sig, sizeof( DWORD ) ); if( !StopOnExtender && (!memcmp( sig, win386sig, 4 ) || !memcmp( sig, win386sig2, 4 )) ) { Out((OUT_LOAD,"Is Win32App" )); Debugging32BitApp = TRUE; /* * make sure that WDEBUG.386 is installed */ if( !WDebug386 ) { ret->err = WINERR_NODEBUG32; /* Can't debug 32 bit app */ LoadingDebugee = FALSE; return( sizeof( *ret ) ); } ret->flags |= LD_FLAG_IS_BIG; if( tid == 0 ) { WriteMem( IntResult.CS, SIG_OFF, win386sig2, sizeof( DWORD ) ); pmsg = DebuggerWaitForMessage( GOING_TO_32BIT_START, DebugeeTask, RESTART_APP ); if( pmsg == FAULT_HIT && IntResult.InterruptNumber == INT_3 ) { IntResult.EIP++; SingleStepMode(); pmsg = DebuggerWaitForMessage( GOING_TO_32BIT_START, DebugeeTask, RESTART_APP ); if( pmsg != FAULT_HIT || IntResult.InterruptNumber != INT_1 ) { Out((OUT_ERR,"Expected INT_1 not found")); ret->err = WINERR_NOINT1; } } else { Out((OUT_ERR,"Expected INT_3 not found")); ret->err = WINERR_NOINT3; } } } if( tid != 0 ) { ret->flags |= LD_FLAG_IS_STARTED; WasStarted = TRUE; } } else { Out((OUT_ERR,"Starting breakpoint not found, pmsg=%d", pmsg )); ret->err = WINERR_STARTNOTFOUND; } #if 0 if( DebugeeTask != NULL ) { InitASynchHook(); } #endif LoadingDebugee = FALSE; CurrentModule = 1; ret->mod_handle = 0; return( sizeof( *ret ) ); }