|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 2000
//
// File: processinfo.cpp
//
//--------------------------------------------------------------------------
// ProcessInfo.cpp: implementation of the CProcessInfo class.
//
//////////////////////////////////////////////////////////////////////
#ifndef NO_STRICT
#ifndef STRICT
#define STRICT 1
#endif
#endif /* NO_STRICT */
#include <WINDOWS.H>
#include <STDIO.H>
#include <TCHAR.H>
#include <TIME.H>
#include "Globals.h"
#include "ProcessInfo.h"
#include "ProcessInfoNode.h"
#include "ProgramOptions.h"
#include "Processes.h"
#include "ModuleInfo.h"
#include "ModuleInfoNode.h"
#include "ModuleInfoCache.h"
#include "FileData.h"
#include "UtilityFunctions.h"
#include "DmpFile.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CProcessInfo::CProcessInfo() { m_fInitialized = false; m_tszProcessName= NULL; m_iProcessID = 0; m_lpModuleInfoHead = NULL; m_hModuleInfoHeadMutex = NULL; m_iNumberOfModules = 0; m_lpInputFile = NULL; m_lpOutputFile = NULL; m_lpModuleInfoCache = NULL; m_hModuleInfoHeadMutex = NULL; m_lpDmpFile = NULL; }
CProcessInfo::~CProcessInfo() { if (m_tszProcessName) delete [] m_tszProcessName;
WaitForSingleObject(m_hModuleInfoHeadMutex, INFINITE);
// If we have Module Info Objects... nuke them now...
if (m_lpModuleInfoHead) {
CModuleInfoNode * lpModuleInfoNodePointer = m_lpModuleInfoHead; CModuleInfoNode * lpModuleInfoNodePointerToDelete = m_lpModuleInfoHead;
// Traverse the linked list to the end..
while (lpModuleInfoNodePointer) { // Keep looking for the end...
// Advance our pointer to the next node...
lpModuleInfoNodePointer = lpModuleInfoNodePointer->m_lpNextModuleInfoNode; // Delete the one behind us...
delete lpModuleInfoNodePointerToDelete;
// Set the node to delete to the current...
lpModuleInfoNodePointerToDelete = lpModuleInfoNodePointer; } // Now, clear out the Head pointer...
m_lpModuleInfoHead = NULL; }
// Be a good citizen and release the Mutex
ReleaseMutex(m_hModuleInfoHeadMutex);
// Now, close the Mutex
if (m_hModuleInfoHeadMutex) { CloseHandle(m_hModuleInfoHeadMutex); m_hModuleInfoHeadMutex = NULL; }
}
//bool CProcessInfo::Initialize(CProgramOptions *lpProgramOptions, CModuleInfoCache * lpModuleInfoCache, CFileData * lpInputFile, CFileData * lpOutputFile)
bool CProcessInfo::Initialize(CModuleInfoCache * lpModuleInfoCache, CFileData * lpInputFile, CFileData * lpOutputFile, CDmpFile * lpDmpFile) { if (lpModuleInfoCache == NULL) return false;
// Let's save off big objects so we don't have to keep passing this to
// our methods...
m_lpInputFile = lpInputFile; m_lpOutputFile = lpOutputFile; m_lpModuleInfoCache = lpModuleInfoCache; m_lpDmpFile = lpDmpFile; m_hModuleInfoHeadMutex = CreateMutex(NULL, FALSE, NULL);
if (m_hModuleInfoHeadMutex == NULL) return false;
m_fInitialized = true; return true; }
bool CProcessInfo::EnumerateModules(DWORD iProcessID, CProcesses * lpProcesses, LPTSTR tszProcessName) { bool fReturn = true;
// Is this being collected interactively?
if (g_lpProgramOptions->GetMode(CProgramOptions::InputProcessesFromLiveSystemMode)) { // Invoke the correct Process Collection Method
if (lpProcesses->GetProcessCollectionMethod() == CProcesses::TOOLHELP32_METHOD) { fReturn = EnumerateModulesForRunningProcessUsingTOOLHELP32(iProcessID, tszProcessName); } else if (lpProcesses->GetProcessCollectionMethod() == CProcesses::PSAPI_METHOD) { fReturn = EnumerateModulesForRunningProcessUsingPSAPI(iProcessID); } }
// Is this being collected from a file?
if (g_lpProgramOptions->GetMode(CProgramOptions::InputCSVFileMode)) { fReturn = EnumerateModulesFromFile(iProcessID, tszProcessName); }
return fReturn; }
bool CProcessInfo::fModuleNameMatches(LPTSTR tszProcessName, LPTSTR tszModulePath) { if (!tszProcessName || !tszModulePath) return false;
TCHAR fname1[_MAX_FNAME], fname2[_MAX_FNAME]; TCHAR ext1[_MAX_EXT], ext2[_MAX_EXT];
_tsplitpath( tszProcessName, NULL, NULL, fname1, ext1 ); _tsplitpath( tszModulePath, NULL, NULL, fname2, ext2 );
if (!ext1 && _tcsicmp(ext1, ext2)) return false; // Extensions must match (if provided on process name)
if (_tcsicmp(fname1, fname2)) return false; // Filename must match
// Do we care about a full path? If so, we can add in drive and dir vars...
return true; }
//
// This function takes a provided tszFileName, and looks to see if it has an
// extension of EXE. If it does, it's saved off...
bool CProcessInfo::fIsProcessName(LPTSTR tszFileName) { if (!tszFileName) return false;
TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT];
_tsplitpath( tszFileName, NULL, NULL, fname, ext );
if (!ext || _tcsicmp(ext, TEXT(".EXE"))) return false; // Extensions must match (if provided on process name)
// Let's save off the process name...
m_tszProcessName = new TCHAR[_tcsclen(fname)+_tcsclen(ext)+1];
if (m_tszProcessName == NULL) return false;
_stprintf(m_tszProcessName, TEXT("%s%s"), _tcsupr(fname), _tcsupr(ext));
// Yup! It's the Process Name...
return true; }
bool CProcessInfo::AddNewModuleInfoObject(CModuleInfo *lpModuleInfo) { if (!m_fInitialized) return false;
// First, create a ModuleInfoNode object and then attach it to the bottom of the
// linked list of nodes...
CModuleInfoNode * lpModuleInfoNode = new CModuleInfoNode(lpModuleInfo);
if (lpModuleInfoNode == NULL) return false; // Couldn't allocate memory..
// Acquire Mutex object to protect the linked-list...
WaitForSingleObject(m_hModuleInfoHeadMutex, INFINITE);
CModuleInfoNode * lpModuleInfoNodePointer = m_lpModuleInfoHead;
if (lpModuleInfoNodePointer) {
// Traverse the linked list to the end..
while (lpModuleInfoNodePointer->m_lpNextModuleInfoNode) { // Keep looking for the end...
lpModuleInfoNodePointer = lpModuleInfoNodePointer->m_lpNextModuleInfoNode; } lpModuleInfoNodePointer->m_lpNextModuleInfoNode = lpModuleInfoNode;
} else { // First time through, the Process Info Head pointer is null...
m_lpModuleInfoHead = lpModuleInfoNode; }
// Be a good citizen and release the Mutex
ReleaseMutex(m_hModuleInfoHeadMutex);
InterlockedIncrement(&m_iNumberOfModules);
return true; }
bool CProcessInfo::OutputProcessData(CollectionTypes enumCollectionType, bool fCSVFileContext, bool fDumpHeader) { if (g_lpProgramOptions->GetMode(CProgramOptions::PrintTaskListMode)) { if ( g_lpProgramOptions->IsRunningWindowsNT() ) { // Provide TLIST like output (though no window text info)
_tprintf(TEXT("%4d %s\n"), m_iProcessID, m_tszProcessName); } else { // Provide TLIST like output (though no window text info)
_tprintf(TEXT("%9d %s\n"), m_iProcessID, m_tszProcessName); } return true; }
// Output to STDOUT?
if ( !g_lpProgramOptions->GetMode(CProgramOptions::QuietMode) ) { // Output to Stdout?
if (!OutputProcessDataToStdout(enumCollectionType, fCSVFileContext, fDumpHeader)) return false; }
if (!g_lpProgramOptions->GetMode(CProgramOptions::QuietMode)) { CUtilityFunctions::OutputLineOfDashes(); // Output to STDOUT
_tprintf(TEXT("\nProcess Name [%s] - PID=%d (0x%x) - "), m_tszProcessName, m_iProcessID, m_iProcessID); }
// Output to file?
if (g_lpProgramOptions->GetMode(CProgramOptions::OutputCSVFileMode)) { // Try and output to file...
if (!OutputProcessDataToFile(enumCollectionType, fDumpHeader)) return false; }
if (m_lpModuleInfoHead) { if (!g_lpProgramOptions->GetMode(CProgramOptions::QuietMode)) { _tprintf(TEXT("%d modules recorded\n\n"), m_iNumberOfModules); CUtilityFunctions::OutputLineOfDashes(); _tprintf(TEXT("\n")); }
CModuleInfoNode * lpCurrentModuleInfoNode = m_lpModuleInfoHead;
unsigned int dwModuleNumber = 1;
while (lpCurrentModuleInfoNode) { // We have a node... print out Module Info for it...
if (lpCurrentModuleInfoNode->m_lpModuleInfo) { lpCurrentModuleInfoNode->m_lpModuleInfo->OutputData(m_tszProcessName, m_iProcessID, dwModuleNumber); dwModuleNumber++; }
lpCurrentModuleInfoNode = lpCurrentModuleInfoNode->m_lpNextModuleInfoNode; }
} else { if (!g_lpProgramOptions->GetMode(CProgramOptions::QuietMode) && fDumpHeader) { _tprintf(TEXT("no recorded modules\n\n")); CUtilityFunctions::OutputLineOfDashes(); _tprintf(TEXT("\n")); } } return true; }
//bool CProcessInfo::OutputProcessDataToStdout(LPCTSTR tszOutputContext, bool fDumpHeader)
bool CProcessInfo::OutputProcessDataToStdout(CollectionTypes enumCollectionType, bool fCSVFileContext, bool fDumpHeader) { if (fDumpHeader) { CUtilityFunctions::OutputLineOfStars(); _tprintf(TEXT("%s - Printing Process Information for 1 Process.\n"), g_tszCollectionArray[enumCollectionType].tszCSVLabel); _tprintf(TEXT("%s - Context: %s\n"), g_tszCollectionArray[enumCollectionType].tszCSVLabel, fCSVFileContext ? g_tszCollectionArray[enumCollectionType].tszCSVContext : g_tszCollectionArray[enumCollectionType].tszLocalContext); CUtilityFunctions::OutputLineOfStars(); }
return true; }
bool CProcessInfo::OutputProcessDataToFile(CollectionTypes enumCollectionType, bool fDumpHeader) { // We skip output of the [processes ]header if -E was specified...
if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode) && fDumpHeader) { // Write out the Process tag so I can detect this output format...
if (!m_lpOutputFile->WriteString(TEXT("\r\n")) || !m_lpOutputFile->WriteString(g_tszCollectionArray[enumCollectionType].tszCSVLabel) || !m_lpOutputFile->WriteString(TEXT("\r\n")) ) { _tprintf(TEXT("Failure writing CSV header to file [%s]!"), m_lpOutputFile->GetFilePath()); m_lpOutputFile->PrintLastError(); return false; } }
// We skip output of the [processes ]header if -E was specified...
if (g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode) && fDumpHeader) { // Write out the header... for the -E option...
if (!m_lpOutputFile->WriteString(TEXT("Module Path,Symbol Status,Time/Date String,File Version,Company Name,File Description,File Time/Date String,Local DBG Status,Local DBG,Local PDB Status,Local PDB\r\n"))) { _tprintf(TEXT("Failure writing CSV header to file [%s]!"), m_lpOutputFile->GetFilePath()); m_lpOutputFile->PrintLastError(); return false; }
} else { if (fDumpHeader) { // Write out the Process Header
if (!m_lpOutputFile->WriteString(g_tszCollectionArray[enumCollectionType].tszCSVColumnHeaders)) { _tprintf(TEXT("Failure writing CSV header to file [%s]!"), m_lpOutputFile->GetFilePath()); m_lpOutputFile->PrintLastError(); return false; } } }
return true; }
bool CProcessInfo::EnumerateModulesForRunningProcessUsingPSAPI(DWORD iProcessID) { HMODULE hMod[1024] ; HANDLE hProcess = NULL; TCHAR tszFileName[_MAX_PATH] ; DWORD cbNeeded; bool fReturn = true; // Optimisim ;)
tszFileName[0] = 0 ; CModuleInfo * lpModuleInfo = NULL; // Open the process (if we can... security does not
// permit every process in the system).
if (iProcessID) { // Only try to open a Process ID if it's not 0
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION| PROCESS_VM_READ, FALSE, iProcessID ) ; } if( hProcess != NULL ) { // Save off our PID (in case we need it later?)
m_iProcessID = iProcessID;
// Now, get a handle to each of the modules
// in our target process...
// Here we call EnumProcessModules to get only the
// first module in the process this is important,
// because this will be the .EXE module for which we
// will retrieve the full path name in a second.
if( g_lpDelayLoad->EnumProcessModules( hProcess, hMod, sizeof( hMod ), &cbNeeded ) ) { int iNumberOfModules = cbNeeded / sizeof(HMODULE); bool fProcessNameFound = false; bool fNew = false; for(int i=0; i<iNumberOfModules; i++) { // Get Full pathname!
if( !g_lpDelayLoad->GetModuleFileNameEx( hProcess, hMod[i], tszFileName, sizeof( tszFileName ) ) ) { tszFileName[0] = 0 ; } else {
CUtilityFunctions::UnMungePathIfNecessary(tszFileName);
// We need a full path to the module to do anything useful with it...
// At this point, let's ... party...
if (!fProcessNameFound) fProcessNameFound = fIsProcessName(tszFileName); // First, if we were provided a Process name on the commandline, we
// need to look for a match on the 1st module...
if (i == 0 && g_lpProgramOptions->GetProcessName()) {
if (!fModuleNameMatches(g_lpProgramOptions->GetProcessName(), tszFileName)) { // Bail if this is not a match, and we requested one...
fReturn = false; goto cleanup; } }
// Are we ONLY interested in the process list?
if (g_lpProgramOptions->GetMode(CProgramOptions::PrintTaskListMode)) { // All we want is process name.. bail before collecting module info...
fReturn = true; goto cleanup; }
// If "-MATCH" was specified, look to see if this filename meets our criteria
// before we save this away in our module cache...
if (!g_lpProgramOptions->fDoesModuleMatchOurSearch(tszFileName)) continue;
// Okay, let's go ahead and get a ModuleInfo Object from our cache...
// If pfNew returns TRUE, then this object is new and we'll need
// to populate it with data...
lpModuleInfo = m_lpModuleInfoCache->AddNewModuleInfoObject(tszFileName, &fNew);
if (false == fNew) { // We may have the object in the cache... now we need to
// save a pointer to this object in our Process Info list
AddNewModuleInfoObject(lpModuleInfo); // Just do our best...
continue; // We save having to get the module info again for this module...
}
// Not in the cache... so we need to init it, and get the module info...
// Okay, let's create a ModuleInfo object and pass this down
// routines that will populate it full of data...
if (!lpModuleInfo->Initialize(NULL, m_lpOutputFile, NULL)) { continue; // Hmmm... memory error?
}
// Let's do it!! Populate the ModuleInfo object with data!!!!
if (!lpModuleInfo->GetModuleInfo(tszFileName)) { // Well, for now we've at least got the path to the module...
// Go ahead and get another module..
continue; }
// Start obtaining information about the modules...
// We may have the object in the cache... now we need to
// save a pointer to this object in our Process Info list
if (!AddNewModuleInfoObject(lpModuleInfo)) { // Failure adding the node.... This is pretty serious...
continue; }
} } fReturn = true; // Looks good...
} else { fReturn = false;
if (!g_lpProgramOptions->GetProcessName()) { // Let's not be so hasty... we couldn't enum modules, but to be friendly we can probably put a name
// to the Process (based on the Process ID)...
//
// This Process ID tends to be "System"
//
// On Windows 2000, the Process ID tends to be 8
//
// On Windows NT 4.0, this Process ID tends to be 2
switch (m_iProcessID) { case 2: case 8: SetProcessName(TEXT("SYSTEM")); fReturn = true; break;
default: // Couldn't enumerate modules...
fReturn = false; } } } cleanup: CloseHandle( hProcess ) ; } else { // Gotta be able to open the process to look at it...
fReturn = false;
if (!g_lpProgramOptions->GetProcessName()) { // Let's not be so hasty... we couldn't enum modules, but to be friendly we can probably put a name
// to the Process (based on the Process ID)...
//
// On Windows 2000, the only Process ID we can't open at all tends to be the "System Idle Process"
switch (m_iProcessID) { case 0: SetProcessName(TEXT("[SYSTEM PROCESS]")); fReturn = true; break;
default: // Couldn't enumerate modules...
fReturn = false; } } }
return fReturn; }
bool CProcessInfo::EnumerateModulesFromFile(DWORD iProcessID, LPTSTR tszProcessName) { CModuleInfo * lpModuleInfo;
// I need these near the end when I probe to see if the next module
// is for this process...
enum { BUFFER_SIZE = 128}; char szTempProcessName[BUFFER_SIZE]; char szProcessName[BUFFER_SIZE]; DWORD iTempProcessID;
// Let's save away the Process Name...
// Unfortunately, when reading from the CSV file, the data is MBCS... so I need
// to convert...
CUtilityFunctions::CopyTSTRStringToAnsi(tszProcessName, szProcessName, BUFFER_SIZE);
// Copy the Process ID
m_iProcessID = iProcessID;
// Local buffer for reading data...
char szModulePath[_MAX_PATH+1]; TCHAR tszModulePath[_MAX_PATH+1]; bool fDone = false; bool fNew = false;
while (!fDone) { // Read in the Module Path
if (!m_lpInputFile->ReadString(szModulePath, _MAX_PATH+1)) return true;
CUtilityFunctions::CopyAnsiStringToTSTR(szModulePath, tszModulePath, _MAX_PATH+1);
// If "-MATCH" was specified, look to see if this filename meets our criteria
// before we save this away in our module cache...
if (!g_lpProgramOptions->fDoesModuleMatchOurSearch(tszModulePath)) { // Okay... read to the start of the next line...
if (!m_lpInputFile->ReadFileLine()) goto cleanup;
goto probe_line; // We save having to get the module info again for this module...
}
// Okay, let's go ahead and get a ModuleInfo Object from our cache...
// If pfNew returns TRUE, then this object is new and we'll need
// to populate it with data...
lpModuleInfo = m_lpModuleInfoCache->AddNewModuleInfoObject(tszModulePath, &fNew);
if (false == fNew) { // We may have the object in the cache... now we need to
// save a pointer to this object in our Process Info list
AddNewModuleInfoObject(lpModuleInfo); // Just do our best...
// Okay... read to the start of the next line...
if (!m_lpInputFile->ReadFileLine()) goto cleanup;
goto probe_line; // We save having to get the module info again for this module...
}
// Not in the cache... so we need to init it, and get the module info...
if (!lpModuleInfo->Initialize(m_lpInputFile, m_lpOutputFile, NULL)) { return false; // Hmmm... memory error?
}
// Let's do it!! Populate the ModuleInfo object with data!!!!
if (!lpModuleInfo->GetModuleInfo(tszModulePath, false, 0, true) ) { // Well, we tried and failed...
return false; }
// Start obtaining information about the modules...
if (!AddNewModuleInfoObject(lpModuleInfo)) { // Failure adding the node.... This is pretty serious...
return false; } // Okay, let's go ahead and probe to see what's coming...
probe_line: // Read the first field (should be blank, unless this is a new collection type
if (m_lpInputFile->ReadString()) goto cleanup;
// Read the Process Name...
if (!m_lpInputFile->ReadString(szTempProcessName, BUFFER_SIZE)) goto cleanup;
// Compare the process name to the current process...
if (_stricmp(szTempProcessName, szProcessName)) goto cleanup;
// Read the Process ID
if (!m_lpInputFile->ReadDWORD(&iTempProcessID)) goto cleanup;
// Compare the process ID to the current process ID
if (iTempProcessID != iProcessID) goto cleanup; }
cleanup: // We need to reset out pointer so the functions above us can re-read
// them (they expect to)...
m_lpInputFile->ResetBufferPointerToStart(); return true; }
bool CProcessInfo::EnumerateModulesForRunningProcessUsingTOOLHELP32(DWORD iProcessID, LPTSTR tszProcessName) { BOOL bFlag; MODULEENTRY32 modentry; TCHAR tszFileName[_MAX_PATH]; bool fProcessNameFound = false; bool fProcessNameProvided = false; bool fReturn = false; bool fNew = false; int iNumberOfModules = 0; HANDLE hSnapShot = INVALID_HANDLE_VALUE; CModuleInfo * lpModuleInfo = NULL;
// Save off our PID (in case we need it later?)
m_iProcessID = iProcessID;
if (tszProcessName && SetProcessName(tszProcessName)) { fProcessNameProvided = true; }
// If we were provided a process name to match, we can do it here...
if ( fProcessNameProvided && g_lpProgramOptions->GetProcessName() ) { // Let's go ahead and look to see if this is a module name match
fProcessNameFound = fModuleNameMatches(g_lpProgramOptions->GetProcessName(), GetProcessName());
// Quit now if we can...
if (fProcessNameFound == false) goto cleanup; }
// If we're doing this for TLIST output... then we already have the process name...
// We're done!
if (g_lpProgramOptions->GetMode(CProgramOptions::PrintTaskListMode)) { fReturn = true; goto cleanup; }
// Get a handle to a Toolhelp snapshot of the systems processes.
hSnapShot = g_lpDelayLoad->CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, iProcessID);
if( hSnapShot == INVALID_HANDLE_VALUE ) { goto cleanup; }
// Get the first process' information.
modentry.dwSize = sizeof(MODULEENTRY32) ; bFlag = g_lpDelayLoad->Module32First( hSnapShot, &modentry ) ;
// While there are modules, keep looping.
while( bFlag ) { // We have a new module for this process!
iNumberOfModules++;
// Copy the path!
_tcscpy(tszFileName, modentry.szExePath);
//#ifdef _DEBUG
// _tprintf(TEXT("[%d] Module = %s\n"), iNumberOfModules, tszFileName);
//#endif
CUtilityFunctions::UnMungePathIfNecessary(tszFileName);
// If "-MATCH" was specified, look to see if this filename meets our criteria
// before we save this away in our module cache...
if (!g_lpProgramOptions->fDoesModuleMatchOurSearch(tszFileName)) goto getnextmodule; // Okay, let's go ahead and get a ModuleInfo Object from our cache...
// If pfNew returns TRUE, then this object is new and we'll need
// to populate it with data...
lpModuleInfo = m_lpModuleInfoCache->AddNewModuleInfoObject(tszFileName, &fNew);
if (false == fNew) { // We may have the object in the cache... now we need to
// save a pointer to this object in our Process Info list
AddNewModuleInfoObject(lpModuleInfo); // Just do our best...
// We save having to get the module info again for this module...
goto getnextmodule; }
// Not in the cache... so we need to init it, and get the module info...
// Okay, let's create a ModuleInfo object and pass this down
// routines that will populate it full of data...
if (lpModuleInfo->Initialize(NULL, m_lpOutputFile, NULL)) {
// Let's do it!! Populate the ModuleInfo object with data!!!!
if (lpModuleInfo->GetModuleInfo(tszFileName)) { // Start obtaining information about the modules...
// We may have the object in the cache... now we need to
// save a pointer to this object in our Process Info list
if (AddNewModuleInfoObject(lpModuleInfo)) { } } } getnextmodule: // Get the next Module...
modentry.dwSize = sizeof(MODULEENTRY32) ; bFlag = g_lpDelayLoad->Module32Next( hSnapShot, &modentry ); }
fReturn = true; cleanup: if (hSnapShot != INVALID_HANDLE_VALUE) CloseHandle(hSnapShot);
return fReturn; }
bool CProcessInfo::SetProcessName(LPTSTR tszFileName) { // Confirm we were given a process name...
if (!tszFileName) return false;
TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT]; TCHAR tszTempFileName[_MAX_FNAME+_MAX_EXT+1];
// Let's extract the filename from the module path
_tsplitpath( tszFileName, NULL, NULL, fname, ext );
// Reconstruct the filename...
_stprintf(tszTempFileName, TEXT("%s%s"), _tcsupr(fname), _tcsupr(ext));
// Let's free anything that's already here...
if (m_tszProcessName) delete [] m_tszProcessName;
// No conversion necessary... copy over...
m_tszProcessName = new TCHAR[_tcslen(tszTempFileName)+1]; if (!m_tszProcessName) return false;
_tcscpy(m_tszProcessName, tszTempFileName);
return true; }
LPTSTR CProcessInfo::GetProcessName() { return m_tszProcessName; }
bool CProcessInfo::GetProcessData() { // Is this being collected from a file?
if (g_lpProgramOptions->GetMode(CProgramOptions::InputCSVFileMode)) GetProcessDataFromFile();
return true; }
bool CProcessInfo::GetProcessDataFromFile() { // Read the Process Header Line
if (!m_lpInputFile->ReadFileLine()) return false;
// Currently, we don't actually read the data...
enum { BUFFER_SIZE = 128}; char szProcessName[BUFFER_SIZE];
TCHAR tszProcessName[BUFFER_SIZE];
DWORD iProcessID;
// Read the first field (should be blank, unless this is a new collection type
if (m_lpInputFile->ReadString()) return true;
bool fReturn = true; while (fReturn == true) { // Read the process name...
if (0 == m_lpInputFile->ReadString(szProcessName, BUFFER_SIZE)) break;
if (!m_lpInputFile->ReadDWORD(&iProcessID)) { fReturn = false; break; }
// We need to convert this to Unicode possibly... (it will be copied in EnumModules())
CUtilityFunctions::CopyAnsiStringToTSTR(szProcessName, tszProcessName, BUFFER_SIZE);
// Save the process name...
SetProcessName(tszProcessName);
// Enumerate the modules for the process
if (!EnumerateModules(iProcessID, NULL, tszProcessName)) { fReturn = false; break; }
// Before we read a new line... are we already pointing to the end?
if (m_lpInputFile->EndOfFile()) { break; }
// Read the first field (should be blank, unless this is a new collection type
if (m_lpInputFile->ReadString()) break; } // We don't expect to find anything...
return fReturn;
}
|