@Phantomotap
I'm not having problems with Code::Blocks in general, just for some reason their DLL project wizard doesn't give me the option to compile as C. There is probably a way around this, but I'm admittedly not an expert IDE user. As far as people like Elysia posting comments about my code, I don't mind it if they can persuade me to believe that method or technique is better than mine. I'm not using pure C, I used C++ in the main() function I posted, but if you didn't read that last part then I understand. If my techniques seem to be controversial on this forum, I might as well post my whole class to give people an idea of what I'm going for. I will include that at the end of this post.
@Elysia
I disagree that my code has "bugs and other complexity", I've spent a great deal of time restructuring it since my last post I made about goto. I think it's actually quite nice right now.
As far as I know of, there is no standard for processes yet, so most of my functions will be win32 functions. I do use some C++ functions, like cout, but other than I don't really use them. I could start experimenting more, which I usually don't do near as much as I should, but I might wait until I have my program written. I may use vectors later, but I'm still not fully convinced I need them. I do agree with you on the issue of allocating my class on the heap, I misunderstood that a bit because I'm used to having to use new in C# for classes.
The Id variable is an integer, which you can see in my function declaration. I'm not using "void * arguments" to those. It represents the identifier for a Windows process, and actually that's not even unique to just Windows anyways. You might have a point on the std::sting class, but I can't say for sure since I haven't used it yet.
Code:
class systemSnapshot
{
private:
array_t processArrayInfo;
processInfo * processes;
HANDLE snapshot;
PROCESSENTRY32 entry;
bool sortedByName;
bool sortedById;
void DestroyModuleResources( moduleInfo * modules, int arraySize )
{
if ( modules )
{
for ( int i = 0; i < arraySize; ++i )
if ( modules[i].name )
free( modules[i].name );
free( modules );
}
}
void DestroyProcessResources( processInfo * processes, int arraySize )
{
if ( processes )
{
for ( int i = 0; i < arraySize; ++i )
if ( processes[i].name )
free( processes[i].name );
free( processes );
}
}
void DestroyResources( )
{
sortedById = false;
sortedByName = false;
for ( int i = 0; i < processArrayInfo.elements; ++i )
DestroyModuleResources( processes[i].modules, processes[i].moduleCount );
DestroyProcessResources( processes, processArrayInfo.elements );
processes = NULL;
if ( snapshot != INVALID_HANDLE_VALUE )
CloseHandle( snapshot );
}
bool CreateSnapshot( )
{
snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
return snapshot != INVALID_HANDLE_VALUE;
}
bool GetFirstProcessEntry( )
{
entry.dwSize = sizeof( PROCESSENTRY32 );
bool status = Process32First( snapshot, &entry );
if ( !status )
{
showWindowsError( "Process32First()", false );
DestroyResources( );
}
return status;
}
bool SetExecutableName( processInfo * process, const char * name )
{
process->name = copyString( name );
if ( !name )
DestroyResources( );
return name != NULL;
}
bool CreateProcessArray( )
{
processArrayInfo.memory = ( processInfo * )createArray( &processArrayInfo, DEFAULT_ELEMENTS, sizeof( processInfo ), zeroArray );
if ( !processArrayInfo.memory )
DestroyResources( );
return processArrayInfo.memory != NULL;
}
bool IncreaseProcessArraySize( )
{
processArrayInfo.memory = ( processInfo * )increaseArraySize( &processArrayInfo, DEFAULT_ELEMENTS );
if ( !processArrayInfo.memory )
DestroyResources( );
return processArrayInfo.memory != NULL;
}
bool ResizeProcessArrayTo( int arraySize )
{
processArrayInfo.elements = arraySize;
processArrayInfo.memory = resizeArray( &processArrayInfo );
if ( !processArrayInfo.memory )
DestroyResources( );
return processArrayInfo.memory != NULL;
}
static int CompareId( const void * a, const void * b )
{
processInfo * processA = ( processInfo * )a;
processInfo * processB = ( processInfo * )b;
return processA->pId - processB->pId;
}
static int CompareName( const void * a, const void * b )
{
processInfo * processA = ( processInfo * )a;
processInfo * processB = ( processInfo * )b;
return strcmp( processA->name, processB->name );
}
public :
systemSnapshot( )
{
memset( ( void * )&processArrayInfo, 0, sizeof( array_t ) );
processes = NULL;
sortedById = false;
sortedByName = false;
}
bool TakeSnapshot( int flags )
{
int processCount = 0;
if ( processes )
DestroyResources( );
if ( !CreateSnapshot( ) )
return false;
if ( !GetFirstProcessEntry( ) )
return false;
if ( !CreateProcessArray( ) )
return false;
do
{
processes = ( processInfo * )processArrayInfo.memory;
processes[processCount].pId = entry.th32ProcessID;
processes[processCount].parentPId = entry.th32ParentProcessID;
processes[processCount].threadCount = entry.cntThreads;
processes[processCount].modules = NULL;
if ( flags & SAVE_MODULE_INFORMATION );
/* TODO : Add code to save information for process modules */
if ( !SetExecutableName( &processes[processCount], entry.szExeFile ) )
return false;
if ( ++processCount >= processArrayInfo.elements - 1 )
if ( !IncreaseProcessArraySize( ) )
return false;
} while ( Process32Next( snapshot, &entry ) );
if ( !ResizeProcessArrayTo( processCount ) )
return false;
CloseHandle( snapshot );
snapshot = INVALID_HANDLE_VALUE;
return true;
}
processInfo * FindProcess( int Id )
{
static processInfo process = { 0 };
processInfo key = { NULL, Id, 0, 0, 0, NULL };
processInfo * temp = NULL;
sortedByName = false;
if ( !processes )
return NULL;
if ( !sortedById )
qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareId );
if ( !temp )
return NULL;
process = *temp;
return &process;
}
processInfo * FindProcess( const char * name )
{
static processInfo process = { 0 };
processInfo key = { ( char * )name, 0, 0, 0, 0, NULL };
processInfo * temp = NULL;
sortedByName = false;
if ( !processes || !name )
return NULL;
if ( !sortedByName )
qsort( processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
temp = ( processInfo * )bsearch( &key, processes, processArrayInfo.elements, sizeof( *processes ), CompareName );
if ( !temp )
return NULL;
process = *temp;
return &process;
}
void PrintData( )
{
for ( int i = 0; i < processArrayInfo.elements; ++i )
{
cout << END << "Process #" << ( i + 1 ) << END;
cout << "Process image name : " << processes[i].name << END;
cout << "Process identifier : " << processes[i].pId << END;
cout << "Process parent identifier : " << processes[i].parentPId << END;
cout << "Thread count : " << processes[i].threadCount << END;
}
}
void PrintData( processInfo * process )
{
if ( !process )
return;
cout << "Process image name : " << process->name << END;
cout << "Process identifier : " << process->pId << END;
cout << "Process parent identifier : " << process->parentPId << END;
cout << "Thread count : " << process->threadCount << END;
}
~systemSnapshot( )
{
DestroyResources();
}
};
Here's some extra declarations :
Code:
typedef struct moduleInfo
{
char * name;
int baseAddress;
int sizeBytes;
} moduleInfo;
typedef struct processInfo
{
char * name;
int pId;
int parentPId;
int threadCount;
int moduleCount;
moduleInfo * modules;
} processInfo;
enum
{
DEFAULT_SNAPSHOT = 0x1,
SAVE_MODULE_INFORMATION = 0x2
};
#define DEFAULT_ELEMENTS 255
I know people may complain about my code since it's using win32 functions, but I'm posting it to show how I wrote the class to prove my point. Otherwise I wouldn't have posted it, since I'm not a big fan of dumping the majority of my program online for everyone.