void slowPoll( void ) { RANDOM_STATE randomState; BYTE buffer[ RANDOM_BUFSIZE ]; MODULEENTRY moduleEntry; GLOBALENTRY globalEntry; TASKENTRY taskEntry; int count; initRandomData( randomState, buffer, RANDOM_BUFSIZE ); /* Walk the global heap getting information on each entry in it. This retrieves the objects linear address, size, handle, lock count, owner, object type, and segment type */ count = 0; globalEntry.dwSize = sizeof( GLOBALENTRY ); if( GlobalFirst( &globalEntry, GLOBAL_ALL ) ) do { addRandomData( randomState, &globalEntry, sizeof( GLOBALENTRY ) ); count++; } while( count < 70 && GlobalNext( &globalEntry, GLOBAL_ALL ) ); /* Walk the module list getting information on each entry in it. This retrieves the module name, handle, reference count, executable path, and next module */ count = 0; moduleEntry.dwSize = sizeof( MODULEENTRY ); if( ModuleFirst( &moduleEntry ) ) do { addRandomData( randomState, &moduleEntry, sizeof( MODULEENTRY ) ); count++; } while( count < 20 && ModuleNext( &moduleEntry ) ); /* Walk the task list getting information on each entry in it. This retrieves the task handle, parent task handle, instance handle, stack segment and offset, stack size, number of pending events, task queue, and the name of module executing the task. We also call TaskGetCSIP() for the code segment and offset of each task if it's safe to do so (note that this call can cause odd things to happen in debuggers and runtime code checkers because of the way TaskGetCSIP() is implemented) */ count = 0; taskEntry.dwSize = sizeof( TASKENTRY ); if( TaskFirst( &taskEntry ) ) do { addRandomData( randomState, &taskEntry, sizeof( TASKENTRY ) ); if( taskEntry.hTask != GetCurrentTask() ) addRandomValue( randomState, TaskGetCSIP( taskEntry.hTask ) ); count++; } while( count < 100 && TaskNext( &taskEntry ) ); /* Flush any remaining data through */ endRandomData( randomState, 100 ); }
/* * horkyFindSegment: * * runs and tries to find a segment. It does this by finding the module * entry in the global heap for this task. The module entry is a lot like * an NE header, except that instead of segment numbers, it has the selector * values themselves. We pass the module entry to accessSegment, who looks * up the selector and causes it to load. * * The reason: load on call segments are not identified by toolhelp, * so mapaddrs for those segments would fail without this putrid code. * As well, the segments themselves are not always loaded (loadoncall * segments), so if you were to look at the memory there, you would see * nothing. * * Special note: this only works for the task that you are debugging. * Windows knows what the current task is, and when you access a not present * segment, it tries to load the segment based on the current task. Thus, * you cannot try to have the debugee fault in a segment belonging to some * other task. Why DLL's work at all (since they are not a "task") is beyond * me. */ static BOOL horkyFindSegment( int module, WORD segment ) { static GLOBALENTRY ge; static HMODULE lastmodid; HMODULE modid; modid = moduleIDs[ module ]; if( !moduleIsDLL[ module ] ) { return( FALSE ); } if( lastmodid == modid ) { accessSegment( ge.hBlock, segment ); return( TRUE ); } lastmodid = modid; ge.dwSize = sizeof( ge ); if( !GlobalFirst( &ge, GLOBAL_ALL ) ) { lastmodid = NULL; return( FALSE ); } do { if( ge.hOwner == modid && ge.wType == GT_MODULE ) { accessSegment( ge.hBlock, segment ); return( TRUE ); } ge.dwSize = sizeof( ge ); } while( GlobalNext( &ge, GLOBAL_ALL ) ); lastmodid = NULL; return( FALSE ); } /* horkyFindSegment */
BOOL MyGlobalFirst( GLOBALENTRY *ge, WORD flags ) { ge->dwSize = sizeof( GLOBALENTRY ); return( GlobalFirst( ge, flags ) ); } /* MyGlobalFirst */
/* * horkyFindSegment - runs and tries to find a segment. It does this by * finding the module entry in the global heap for this task. The module * entry is a lot like an NE header, except that instead of segment numbers, * it has the selector values themselves. For the format of the module entry * see p 319 of Undocumented Windows */ static WORD horkyFindSegment( HMODULE mod, WORD seg ) { WORD sel; WORD offset; GLOBALENTRY ge; if( !GlobalFirst( &ge, GLOBAL_ALL ) ) { return( 0 ); } do { if( ge.hOwner == mod && ge.wType == GT_MODULE ) { ReadMem( (WORD)ge.hBlock, 0x22, &offset, sizeof( offset ) ); offset += 8 + ( 10 * seg ); ReadMem( (WORD)ge.hBlock, offset, &sel, sizeof( sel ) ); return( sel ); } } while( GlobalNext( &ge, GLOBAL_ALL ) ); return( 0 ); }