Solved

How do i get the file path of a running process in Windows NT.

Posted on 2001-08-03
5
1,302 Views
Last Modified: 2013-12-03
Hello,

How do i get the file path of a running process in Windows NT.
Following is the code to get names of processes running in NT system, which
i got from MSDN.
Is it possible to get Process file path by modifiying following code ?

-------------------------------------------------------
// #define INITIAL_SIZE        51200
#define EXTEND_SIZE         25600
#define REGKEY_PERF         "software\\microsoft\\windows
nt\\currentversion\\perflib"
#define REGSUBKEY_COUNTERS  "Counters"
#define PROCESS_COUNTER     "process"
#define PROCESSID_COUNTER   "id process"
#define UNKNOWN_TASK        "unknown"

DWORD
GetTaskListNT(
PTASK_LIST pTask,
DWORD dwNumTasks
)

/*++

Routine Description:

Provides an API for getting a list of tasks running at the time of the
API call. This function uses the registry performance data to get the
task list and is therefore straight WIN32 calls that anyone can call.

Arguments:

dwNumTasks - maximum number of tasks that the pTask array can hold

Return Value:

Number of tasks placed into the pTask array.

--*/

{
DWORD rc;
HKEY hKeyNames;
DWORD dwType;
DWORD dwSize;
LPBYTE buf = NULL;
CHAR szSubKey[1024];
LANGID lid;
LPSTR p;
LPSTR p2;
PPERF_DATA_BLOCK pPerf;
PPERF_OBJECT_TYPE pObj;
PPERF_INSTANCE_DEFINITION pInst;
PPERF_COUNTER_BLOCK pCounter;
PPERF_COUNTER_DEFINITION pCounterDef;
DWORD i;
DWORD dwProcessIdTitle;
DWORD dwProcessIdCounter;
CHAR szProcessName[MAX_PATH];
DWORD dwLimit = dwNumTasks - 1;



//
// Look for the list of counters. Always use the neutral
// English version, regardless of the local language. We
// are looking for some particular keys, and we are always
// going to do our looking in English. We are not going
// to show the user the counter names, so there is no need
// to go find the corresponding name in the local language.
//
lid = MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL );
sprintf( szSubKey, "%s\\%03x", REGKEY_PERF, lid );
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szSubKey,
0,
KEY_READ,
&hKeyNames
);
if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// get the buffer size for the counter names
//
rc = RegQueryValueEx( hKeyNames,
REGSUBKEY_COUNTERS,
NULL,
&dwType,
NULL,
&dwSize
);

if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// allocate the counter names buffer
//
buf = (LPBYTE) malloc( dwSize );
if (buf == NULL) {
goto exit;
}
memset( buf, 0, dwSize );

//
// read the counter names from the registry
//
rc = RegQueryValueEx( hKeyNames,
REGSUBKEY_COUNTERS,
NULL,
&dwType,
buf,
&dwSize
);

if (rc != ERROR_SUCCESS) {
goto exit;
}

//
// now loop thru the counter names looking for the following counters:
//
// 1. "Process" process name
// 2. "ID Process" process id
//
// the buffer contains multiple null terminated strings and then
// finally null terminated at the end. the strings are in pairs of
// counter number and counter name.
//

p = buf;
while (*p) {
if (p > buf) {
for( p2=p-2; isdigit(*p2); p2--) ;
}
if (stricmp(p, PROCESS_COUNTER) == 0) {
//
// look backwards for the counter number
//
for( p2=p-2; isdigit(*p2); p2--) ;
strcpy( szSubKey, p2+1 );
}
else
if (stricmp(p, PROCESSID_COUNTER) == 0) {
//
// look backwards for the counter number
//
for( p2=p-2; isdigit(*p2); p2--) ;
dwProcessIdTitle = atol( p2+1 );
}
//
// next string
//
p += (strlen(p) + 1);
}

//
// free the counter names buffer
//
free( buf );


//
// allocate the initial buffer for the performance data
//
dwSize = INITIAL_SIZE;
buf = malloc( dwSize );
if (buf == NULL) {
goto exit;
}
memset( buf, 0, dwSize );


while (TRUE) {

rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
szSubKey,
NULL,
&dwType,
buf,
&dwSize
);

pPerf = (PPERF_DATA_BLOCK) buf;

//
// check for success and valid perf data block signature
//
if ((rc == ERROR_SUCCESS) &&
(dwSize > 0) &&
(pPerf)->Signature[0] == (WCHAR)'P' &&
(pPerf)->Signature[1] == (WCHAR)'E' &&
(pPerf)->Signature[2] == (WCHAR)'R' &&
(pPerf)->Signature[3] == (WCHAR)'F' ) {
break;
}

//
// if buffer is not big enough, reallocate and try again
//
if (rc == ERROR_MORE_DATA) {
dwSize += EXTEND_SIZE;
buf = realloc( buf, dwSize );
memset( buf, 0, dwSize );
}
else {
goto exit;
}
}

//
// set the perf_object_type pointer
//
pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);

//
// loop thru the performance counter definition records looking
// for the process id counter and then save its offset
//
pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
for (i=0; i<(DWORD)pObj->NumCounters; i++) {
if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {
dwProcessIdCounter = pCounterDef->CounterOffset;
break;
}
pCounterDef++;
}

dwNumTasks = min( dwLimit, (DWORD)pObj->NumInstances );

pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);

//
// loop thru the performance instance data extracting each process name
// and process id
//
for (i=0; i<dwNumTasks; i++) {
//
// pointer to the process name
//
p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);

//
// convert it to ascii
//
rc = WideCharToMultiByte( CP_ACP,
0,
(LPCWSTR)p,
-1,
szProcessName,
sizeof(szProcessName),
NULL,
NULL
);

if (!rc) {
//
// if we cant convert the string then use a default value
//
strcpy( pTask->ProcessName, UNKNOWN_TASK );
}

if (strlen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {
strcpy( pTask->ProcessName, szProcessName );
strcat( pTask->ProcessName, ".exe" );
}

//
// get the process id
//
pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
pTask->flags = 0;
pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
if (pTask->dwProcessId == 0) {
pTask->dwProcessId = (DWORD)-2;
}

//
// next process
//
pTask++;
pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter +
pCounter->ByteLength);
}

exit:
if (buf) {
free( buf );
}

RegCloseKey( hKeyNames );
RegCloseKey( HKEY_PERFORMANCE_DATA );

return dwNumTasks;
}
-------------------------------------------------------


Thanx,

Nagaraj





0
Comment
Question by:Nagarajhr
  • 2
  • 2
5 Comments
 
LVL 15

Expert Comment

by:NickRepin
ID: 6351003
HOWTO: Enumerate Applications in Win32
http://support.microsoft.com/support/kb/articles/Q175/0/30.ASP

<<the PSAPI.DLL also contains a variety of useful functions. .... EnumProcesses(), EnumProcessModules(), GetModuleFileNameEx(), GetModuleBaseName()
EnumProcesses()

......

Now you have an array with each process ID in the system. If your goal is to get the name of the process, then you must first get a handle. To get a handle from a process ID, use OpenProcess().

....

To get the first module of a process call the EnumProcessModules()

....

Remember that a process doesn't really have a name, but that the first module in the process is going to be the executable of the process. Now you can use the hModule with the GetModuleFileNameEx(), GetModuleBaseName() to get the full path name, or the simple module name for the process executable.

....

By repeating this for each process ID returned with the EnumProcesses(),you create a list of processes under Windows NT.

>>
0
 

Author Comment

by:Nagarajhr
ID: 6351138
Thank you Mr. NickRepin,

I will check it in my code and reply in another two days.

But i want to know that is it possible to get process file path ( i.e. complete file path of a process in hard disk as C:\WinNT\...\..EXE ) with the help of Process ID or Process name without using PSAPI functions. Because PSAPI functions requires PSAPI DLL, which is not included  in Windows NT ( ver.4 ) system DLLs.
0
 
LVL 15

Accepted Solution

by:
NickRepin earned 200 total points
ID: 6351149
You can re-distribute PSAPI DLL with your application, in case of NT4 prior to Service Pack XXX (sorry, cannot recall the exact number).
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6354946
Both NT4 and Win2k only give you the executable *names*, not the *paths*, when using the performance counters, or when using the undocumented NtGetSystemInformation, or when using the toolhelp functions (Win2k).
The only way of getting the full paths is to either use PsApi.dll (as Nick already pointed out), or doing exactly what PsApi.dll does internally. You can reverse engineer PsApi.dll, it's no big problem (I've done that already).

Regards, Madshi.
0
 

Author Comment

by:Nagarajhr
ID: 6355050
Thank you for your suggestions.

Nagaraj
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question