/* * doStartTask: * * handle NFY_STARTTASK notification * * If we are waiting for the debuggee to load, then this is the task. * We remember the module and task ID's, and plant a breakpoint at the * starting address of the application. We can do that now, since we * now know the code selector for the segment with the start address. * * Otherwise, we simply record it so that we can notify the debugger * about a loaded module later. */ static BOOL doStartTask( DWORD data ) { char val; TASKENTRY te; te.dwSize = sizeof( te ); TaskFindHandle( &te, TaskAtNotify ); if( DebuggerState == LOADING_DEBUGEE ) { DebugeeModule = te.hModule; DebugeeTask = TaskAtNotify; StopNewTask.loc.segment = HIWORD( data ); ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &StopNewTask.value, 1 ); val = '\xcc'; WriteMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &val, 1 ); ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &val, 1 ); Out((OUT_RUN," wrote breakpoint at %04x:%04lx, oldbyte=%02x(is now %02x)", StopNewTask.loc.segment, StopNewTask.loc.offset, StopNewTask.value, val )); Out((OUT_RUN," StartTask: cs:ip = %Fp", data )); ToDebugger( TASK_LOADED ); } else { AddModuleLoaded( te.hModule, FALSE ); } return( FALSE ); } /* doStartTask */
/* * GetMonitorInfo - refresh information about the local heap being monitored */ static BOOL GetMonitorInfo( LocalMonInfo *info ) { LocalMonInfo old_info; TASKENTRY taskinfo; LOCALENTRY localinfo; BOOL ret; WORD i; old_info = *info; memset( &localinfo, 0, sizeof( LOCALENTRY ) ); localinfo.dwSize = sizeof( LOCALENTRY ); memset( &taskinfo, 0, sizeof( TASKENTRY ) ); taskinfo.dwSize = sizeof( TASKENTRY ); TaskFindHandle( &taskinfo, info->task_hdl ); info->sizes[ STATIC_SIZE ] = taskinfo.wStackTop; info->sizes[ STACK_SIZE ] = taskinfo.wStackBottom - taskinfo.wStackTop; info->sizes[ FIXED_SIZE ] = 0; info->sizes[ MOVE_SIZE ] = 0; info->sizes[ FREE_SIZE ] = 0; ret = LocalFirst( &localinfo, info->handle ); while( ret ) { switch( localinfo.wFlags ) { case LF_FIXED: info->sizes[ FIXED_SIZE ] += localinfo.wSize; break; case LF_MOVEABLE: info->sizes[ MOVE_SIZE ] += localinfo.wSize; break; case LF_FREE: info->sizes[ FREE_SIZE ] += localinfo.wSize; break; } ret = LocalNext( &localinfo ); } info->stack_used = taskinfo.wStackBottom - taskinfo.wStackMinimum; if( !memcmp( info, &old_info, sizeof( LocalMonInfo ) ) ) { return( FALSE ); } info->sizes[ OTHER_SIZE ] = info->total_size; for( i=0; i < SIZE_CNT; i++ ) { if( i != OTHER_SIZE ) info->sizes[ OTHER_SIZE ] -= info->sizes[i]; } return( TRUE ); }
/* * GetRealCSIP - get the CS:IP of a stopped task, cuz microsoft only tells * you that the task is stopped in the kernel (gee, that's * useful!!) */ DWORD GetRealCSIP( HTASK htask, HMODULE *mod ) { DWORD csip; STACKTRACEENTRY se; GLOBALENTRY ge; TASKENTRY te; te.dwSize = sizeof( te ); if( TaskFindHandle( &te, htask ) == NULL ) { return( 0L ); } if( mod != NULL ) { *mod = te.hModule; } csip = TaskGetCSIP( htask ); if( csip == 0L ) { return( 0L ); } se.dwSize = sizeof( se ); if( !StackTraceFirst( &se, htask ) ) { return( csip ); } csip = MAKECSIP( se.wCS, se.wIP ); while( 1 ) { se.dwSize = sizeof( se ); if( !StackTraceNext( &se ) ) { break; } csip = MAKECSIP( se.wCS, se.wIP ); ge.dwSize = sizeof( ge ); if( GlobalEntryHandle( &ge, (HGLOBAL)se.wCS ) ) { if( ge.hOwner == te.hModule ) { break; } } } return( csip ); } /* GetRealCSIP */
// pre-process input file, creating a tmp file // In order to get the return code of the C pre-processor, I'm // spawing a batch file that invokes CL, and creates a signal file // if it is successful. VOID NEAR DoPreProcess ( ) { char szBuffer[255]; HANDLE hInstCpp; TASKENTRY taskentry; FILE * hFile; CHAR * szTempBatch; CHAR * szTempSig; CHAR * szTempRoot; ERR err = ERR_CPP; // assume error int cbTempFilenames; char * szComSpec; // figure out the names of the temp files // (note: uses OEM char set) szTempRoot = tempnam(".", "~mkt"); // get base name for temp files hFile = fopen(szTempRoot, "w"); // create the file now, to if (hFile == NULL) // reserve this set of names ParseError(ERR_CPP); fclose(hFile); cbTempFilenames = strlen(szTempRoot)+1+3+1; // base name + ext + null szTempBatch = malloc(cbTempFilenames); // for .BAT file strcpy(szTempBatch, szTempRoot); strcat(szTempBatch, ".bat"); szTempSig = malloc(cbTempFilenames); // for .SIG file strcpy(szTempSig, szTempRoot); strcat(szTempSig, ".sig"); szTempFile = malloc(cbTempFilenames); // for pre-processed oupput strcpy(szTempFile, szTempRoot); strcat(szTempFile, ".inp"); // CONSIDER: Check for existence of any of these files, if any exist, then // CONSIDER: try a different base name for the files. // open the temp .BAT file hFile = fopen(szTempBatch, "w"); if (hFile == NULL) goto cleanup2; // all errors after this point should go to 'cleanup' if (fputs(szBatchStart, hFile) < 0) // write the first part goto cleanup; sprintf(szBuffer, "%s %s%s %s>", szCppExe, szCppOpts, szCppDefs, szInputFile); // convert this string to the OEM char set AnsiToOem(szBuffer, szBuffer); // append szTempFile strcat(szBuffer, szTempFile); strcat(szBuffer, "\n"); if (fputs(szBuffer, hFile) < 0) // write the CPP command goto cleanup; sprintf(szBuffer, szBatchEnd, szTempSig); if (fputs(szBuffer, hFile) < 0) // write the error check code goto cleanup; fclose(hFile); hFile = NULL; // file no longer open szComSpec = getenv("COMSPEC"); if (szComSpec == NULL) szComSpec = "command.com"; sprintf(szBuffer, "%s /c %s", szComSpec, szTempBatch); hInstCpp = WinExec(szBuffer, SW_SHOWMINIMIZED); // shell the pre-processor if (hInstCpp < 32) // if error spawning pre-processor goto cleanup; Yield(); // give it a chance to start // find task associated with this instance. In extreme cases it may have // finished even before we're executing this code. taskentry.dwSize = sizeof(TASKENTRY); if (TaskFirst(&taskentry) == 0) { goto taskdone; } while (taskentry.hInst != hInstCpp) { if (TaskNext(&taskentry) == 0) { goto taskdone; } } hTaskCpp = taskentry.hTask; while (IsTask(hTaskCpp)) { SideAssert(TaskFindHandle(&taskentry, hTaskCpp) != 0); if (taskentry.hInst != hInstCpp) { // different hInst associated with this htask, // so the app must have terminated break; } Yield(); // wait until it's done } taskdone: // If signal file doesn't exist, then there was a problem pre-processing // the input file. If it exists, then it worked. if (!MyRemove(szTempSig)) err = ERR_NONE; // it worked! cleanup: if (hFile) // close tmp batch file if fclose(hFile); // error during write SideAssert(MyRemove(szTempBatch) == 0); // delete tmp batch file cleanup2: SideAssert(MyRemove(szTempRoot) == 0); // delete placeholder file if (err != ERR_NONE) // report any error ParseError(err); }
BOOL MyTaskFindHandle( TASKENTRY *te, HTASK h ) { te->dwSize = sizeof( TASKENTRY ); return( TaskFindHandle( te, h ) ); } /* MyTaskFindHandle */