Exemplo n.º 1
0
/*
 * 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 = NULL;
    size_t          nBuffRequired = 0;
    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;
    if( NULL == ( buff = malloc( nBuffRequired ) ) ) {
        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 ) {
        if( FindFilePath( parm, exe_name, ExtensionList ) != 0 ) {
            ret->err = ERROR_FILE_NOT_FOUND;
            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 ) {
        free( buff );
        buff = NULL;
    }
    return( sizeof( *ret ) );

}

trap_retval ReqProg_kill( void )
{
    prog_kill_ret   *ret;

    ret = GetOutPtr( 0 );
    ret->err = 0;
    DelProcess( TRUE );
    StopControlThread();
    return( sizeof( *ret ) );
}
Exemplo n.º 2
0
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;
            goto failed;
        }
    }
    if( service_manager != NULL ) {
        ENUM_SERVICE_STATUS *eenum = NULL;
        DWORD               bytesNeeded;
        DWORD               servicesReturned;
        DWORD               resumeHandle = 0;

        EnumServicesStatus( service_manager, SERVICE_WIN32 + SERVICE_DRIVER, SERVICE_ACTIVE + SERVICE_INACTIVE, NULL, 0, &bytesNeeded, &servicesReturned, &resumeHandle );
        if( servicesReturned == 0 ) {
            eenum = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, bytesNeeded );
            if( eenum == NULL ) {
                rc = FALSE;
                goto failed;
            }
            EnumServicesStatus( service_manager, SERVICE_WIN32 + SERVICE_DRIVER, SERVICE_ACTIVE + SERVICE_INACTIVE, eenum, bytesNeeded, &bytesNeeded, &servicesReturned, &resumeHandle );
            for( i = 0; i < servicesReturned; ++i ) {
                strlwr( eenum[i].lpServiceName );
                strlwr( eenum[i].lpDisplayName );
            }
            strlwr( service_name );
            for( i = 0; i < servicesReturned; ++i ) {
                if( strcmp( eenum[i].lpServiceName, service_name ) == 0 ) {
                    service_name = eenum[i].lpServiceName;
                    goto done;
                }
            }

            for( i = 0; i < servicesReturned; ++i ) {
                if( strcmp( eenum[i].lpDisplayName, service_name ) == 0 ) {
                    service_name = eenum[i].lpServiceName;
                    goto done;
                }
            }

            for( i = 0; i < servicesReturned; ++i ) {
                if( strstr( eenum[i].lpServiceName, service_name ) != 0 ) {
                    service_name = eenum[i].lpServiceName;
                    goto done;
                }
            }

            for( i = 0; i < servicesReturned; ++i ) {
                if( strstr( eenum[i].lpDisplayName, service_name ) != 0 ) {
                    service_name = eenum[i].lpServiceName;
                    goto done;
                }
            }
        }
    done:
        service = OpenService( service_manager, service_name, SERVICE_ALL_ACCESS );
        if( service == NULL ) {
            AddMessagePrefix( "Unable to open the specified service", 0 );
            rc = FALSE;
            goto failed;
        }
        LocalFree( eenum );
    }

    if( service != NULL ) {
        if( ControlService( service, SERVICE_CONTROL_STOP, &status ) ) {
            i = 0;
            for( ;; ) {
                if( i == 40 ) {
                    AddMessagePrefix( "Unable to stop the specified service", 0 );
                    Shared.err = ERROR_SERVICE_REQUEST_TIMEOUT;
                    goto failed;
                }
                if( !QueryServiceStatus( service, &status ) ) {
                    AddMessagePrefix( "Unable to stop the specified service", 0 );
                    rc = FALSE;
                    goto failed;
                }
                if( status.dwCurrentState == SERVICE_STOPPED )
                    break;
                Sleep( 500 );
                ++i;
            }
        }
    }

    if( dll_name[0] && dll_destination[0] ) {
        char *end;
        WIN32_FIND_DATA dat;
        strcpy( buff, dll_destination );
        end = buff + strlen( buff ) - 1;
        if( *end != '\\' && *end != '/' ) {
            strcat( buff, "\\" );
        }
        strcat( buff, "." );
        if( FindFirstFile( buff, &dat ) != INVALID_HANDLE_VALUE ) {
           if( dat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                _splitpath( dll_name, NULL, NULL, fname, ext );
                _makepath( buff, NULL, dll_destination, fname, ext );
                dll_destination = buff;
            }
        }
        if( !CopyFile( dll_name, dll_destination, FALSE ) ) {
            AddMessagePrefix( "Unable to copy '", 3000 );
            strcat( MsgPrefix, dll_name );
            strcat( MsgPrefix, "' to '" );
            strcat( MsgPrefix, dll_destination );
            strcat( MsgPrefix, "'" );
            rc = FALSE;
            goto failed;
        }
    }

    if( service != NULL ) {
        char const *parm[2];
        parm[0] = service_parm;
        parm[1] = NULL;
        StartService( service, 0, parm );
        i = 0;
        for( ;; ) {
            if( i == 40 ) {
                AddMessagePrefix( "Unable to start the specified service", 0 );
                Shared.err = ERROR_SERVICE_REQUEST_TIMEOUT;
                goto failed;
            }
            if( !QueryServiceStatus( service, &status ) ) {
                AddMessagePrefix( "Unable to start the specified service", 0 );
                rc = FALSE;
                goto failed;
            }
            if( status.dwCurrentState == SERVICE_RUNNING )
                break;
            Sleep( 500 );
            ++i;
        }
        CloseServiceHandle( service );
        Sleep( 1000 ); // just in case it's slow!
    }
    if( service_manager != NULL ) {
        CloseServiceHandle( service_manager );
    }

    if( Shared.pid == -1 ) {
        mod = LoadLibrary( "PView.dll" );
        if( mod != NULL ) {
            select = ( SELECTPROCESS )GetProcAddress( mod, "_SelectProcess@4" );
            if( select != NULL ) {
                if( Shared.name == NULL || Shared.name[0] == '\0' ) {
                    Shared.pid = ( *select ) ( "" );
                } else {
                    i = 0;
                    for( ;; ) {
                        if( i == 10 ) {
                            Shared.pid = ( *select ) ( "" );
                            break;
                        }
                        Shared.pid = ( *select ) ( Shared.name );
                        if( Shared.pid != 0 && Shared.pid != -1 ) {
                            break;
                        }
                        Sleep( 500 );
                        ++i;
                    }
                }
            }
        }
        CloseHandle( mod );
    }
    if( Shared.pid != 0 && Shared.pid != -1 ) {
        rc = MyDebugActiveProcess( Shared.pid );
#if !defined( MD_x64 )
        if( IsWOW ) {
            /*
             * WOW was already running, so we start up wowdeb (this
             * is used in debugging WOW, provided with NT), and
             * then we do a "CreateProcess" on the WOW app.  Since WOW
             * is already running, this doesn't really create a process,
             * but instead has the existing WOW start the 16-bit task.
             */
            memset( &sinfo, 0, sizeof( sinfo ) );
            sinfo.cb = sizeof( sinfo );
            sinfo.wShowWindow = SW_NORMAL;
            rc = CreateProcess( NULL,           /* application name */
                                "wowdeb.exe",   /* command line */
                                NULL,           /* process attributes */
                                NULL,           /* thread attributes */
                                TRUE,           /* inherit handles */
                                0,              /* creation flags */
                                NULL,           /* environment block */
                                NULL,           /* starting directory */
                                &sinfo,         /* startup info */
                                &pinfo          /* process info */
                                );
            rc = CreateProcess( NULL,           /* application name */
                                Shared.name,    /* command line */
                                NULL,           /* process attributes */
                                NULL,           /* thread attributes */
                                TRUE,           /* inherit handles */
                                0,              /* creation flags */
                                NULL,           /* environment block */
                                NULL,           /* starting directory */
                                &sinfo,         /* startup info */
                                &pinfo          /* process info */
                                );
        }
#endif
        pinfo.dwProcessId = Shared.pid;
    } else {
        memset( &sinfo, 0, sizeof( sinfo ) );
        sinfo.cb = sizeof( sinfo );
        sinfo.wShowWindow = SW_NORMAL;
        rc = CreateProcess( NULL,               /* application name */
                            Shared.name,        /* command line */
                            NULL,               /* process attributes */
                            NULL,               /* thread attributes */
                            TRUE,              /* inherit handles */
                            Shared.flags,       /* creation flags */
                            NULL,               /* environment block */
                            NULL,               /* starting directory */
                            &sinfo,             /* startup info */
                            &pinfo              /* process info */
                            );
    }
failed:
    SetErrorMode( oldErrorMode );
    Shared.pid = pinfo.dwProcessId;
    return( rc );
}