Solved

How to get Process/Service full path using the process id only, mainly on Itanuim with windows 2003 R2

Posted on 2006-11-27
13
2,584 Views
Last Modified: 2013-12-03
can you recommend an easy way to find running process binary path by pid on window only.
For example I would like to take process pid (1234) and trace the full path to the binary that is running (c:\program files\...\abc.exe).

I am getting errors while trying to investigate a process under windows 2003 R2
I need the solution to be in C++ and won't involve anything that can be consider as a security holes.

10x
Assaf
0
Comment
Question by:Assaf_Gantz
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
13 Comments
 
LVL 8

Expert Comment

by:mxjijo
ID: 18023472

Take a look at
http://msdn2.microsoft.com/en-gb/library/ms683196.aspx

They also have an example
http://msdn2.microsoft.com/en-gb/library/ms682621.aspx

Basically you need to do a OpenProcess() on your target process id to get a handle to the process.
Then use that handle as described in above article to query file names.

Hope you are aware that your monitor process need proper privilages to query these kind of information.
Please let us know if you have trouble settings process privilages.

best
~J
0
 
LVL 3

Expert Comment

by:srinims
ID: 18028509
you have to get in to the parent process of all.( desktop window). check process explorer tool of sysinternals for detailed process in tree view.

yu can get the desktop window using GetDesktopWindow function.

Then you have to get in to each process using the getchildprocess handle, using Enumerate all windows (EnumWindows()),
you can check the name of the process. and if it matches with your criteria. then you can get the details of the particular process.

or else if you have pid. then you have to get to the pid from getting handle. and you have to compare with the pid you have
to get pid from handle GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);

in windows you can control everything only with the handle.

from the handle you can get the path of the particular process

0
 
LVL 3

Expert Comment

by:srinims
ID: 18028552
this what you are exactly looking for..
get use of the same function in vc++, and solve it.
http://www.elists.org/pipermail/delphi-talk/2004-September/019577.html
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 3

Assisted Solution

by:srinims
srinims earned 200 total points
ID: 18028606
for windows 2003 u might need this function.

GetProcessImageFileName


pls look into http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocessimagefilename.asp
0
 

Author Comment

by:Assaf_Gantz
ID: 18028864
All your answers are being tried but my main issue those process
I am looking for are SERVICES and I just can get the OpenProcess command open them without getting any errors.

I have Admin privilages on the box and still I am not able to view the process information.

0
 

Author Comment

by:Assaf_Gantz
ID: 18031408
Here some additional info This is the error message when ever I try to investigate the Process:

 
error failed to open process
Failed to open process. pid: 7772, error 5
.\main.cpp:855, Win32 error: Access is denied, code: 5
Please choose pid to memdump 0 to quit [7772]: 7916
0
 
LVL 8

Expert Comment

by:mxjijo
ID: 18032496

As I mentioned earlier, your process needs special privilages to open other processes.
Copy th efollowing function to your source and call it once before you make OpenProcess() call.

BOOL GrabKillerPrivilage()
{
    TOKEN_PRIVILEGES Priv, PrivOld;
    DWORD cbPriv = sizeof(PrivOld);
    HANDLE hToken;
     DWORD  dwError;

    // get current thread token
    if (!OpenThreadToken(GetCurrentThread(),
                         TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
                         FALSE, &hToken))
    {
        if (GetLastError() != ERROR_NO_TOKEN)
            return FALSE;
        // revert to the process token, if not impersonating
        if (!OpenProcessToken(GetCurrentProcess(),
                              TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
                              &hToken))
            return FALSE;
    }

    Priv.PrivilegeCount                    = 1;
    Priv.Privileges[0].Attributes     = SE_PRIVILEGE_ENABLED;
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Priv.Privileges[0].Luid);

    // try to enable the privilege
    if (!AdjustTokenPrivileges(hToken,
                                        FALSE,
                                        &Priv,
                                        sizeof(Priv),
                                        &PrivOld,
                                        &cbPriv))
    {
        dwError = GetLastError();
        CloseHandle(hToken);
        return SetLastError(dwError), FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        // the SE_DEBUG_NAME privilege is not in the caller's token
        CloseHandle(hToken);
        return SetLastError(ERROR_ACCESS_DENIED), FALSE;
    }

     return TRUE;
}
0
 

Author Comment

by:Assaf_Gantz
ID: 18032638
We are slowly getting closer, below my code and the output
Still we fail on Itanium

Output:

C:\>proc_test2.exe 476
Pid to examine 476
*** OpenThreadToken failed is it ERROR_NO_TOKEN ?
*** EnumProcessModules failed
C:\Documents and Settings\agantz\My Documents\Visual Studio Projects\proc_test2\proc_test.cpp:125, Win32 error: Only par
t of a ReadProcessMemory or WriteProcessMemory request was completed, code: 299


CODE:

// proc_cmd.cpp : Defines the entry point for the application.
//

// #include "stdafx.h"
#include <iostream.h>
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <Aclapi.h>
#include <stdlib.h>



PCHAR GetLastWin32ErrorMsg(int ErrorCode)
{
  int Len;
  __declspec(thread) static char Buffer[255];

  Len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, ErrorCode, 0, Buffer,
    sizeof(Buffer), NULL);

  while (Len > 0 && Buffer[Len - 1] > 0 && Buffer[Len - 1] < 32 || Buffer[Len - 1] == '.')
      Len--;
  Buffer[Len] = '\0';
  return Buffer;
}

#define CHECK_ERROR_CODE(Result) {        \
    if (Result != ERROR_SUCCESS) {        \
          fprintf(stderr, "%s:%d, Win32 error: %s, code: %d\n", __FILE__, __LINE__, GetLastWin32ErrorMsg(Result), Result); \
    }}

#define WIN32CHECK(Result) if (!Result)      {CHECK_ERROR_CODE(GetLastError())}




BOOL GrabKillerPrivilage()
{
    TOKEN_PRIVILEGES Priv, PrivOld;
    DWORD cbPriv = sizeof(PrivOld);
    HANDLE hToken;
    DWORD  dwError;

    // get current thread token
    if (!OpenThreadToken(GetCurrentThread(),
                         TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
                         FALSE, &hToken))
    {
            cout << "*** OpenThreadToken failed is it ERROR_NO_TOKEN ?" << endl;
        if (GetLastError() != ERROR_NO_TOKEN) {
                  cout << "*** OpenThreadToken failed" << endl;
                  return FALSE;
            }
        // revert to the process token, if not impersonating
        if (!OpenProcessToken(GetCurrentProcess(),
                              TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,
                              &hToken)) {
                  cout << "*** OpenProcessToken failed" << endl;
            return FALSE;
            }
    }

    Priv.PrivilegeCount                    = 1;
    Priv.Privileges[0].Attributes     = SE_PRIVILEGE_ENABLED;
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Priv.Privileges[0].Luid);

    // try to enable the privilege
    if (!AdjustTokenPrivileges(hToken,
                                        FALSE,
                                        &Priv,
                                        sizeof(Priv),
                                        &PrivOld,
                                        &cbPriv))
    {
            cout << "*** AdjustTokenPrivileges failed" << endl;
        dwError = GetLastError();
        CloseHandle(hToken);
        return SetLastError(dwError), FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
            cout << "*** SE_DEBUG_NAME privilege is not in the caller's token" << endl;
        // the SE_DEBUG_NAME privilege is not in the caller's token
        CloseHandle(hToken);
            SetLastError(ERROR_ACCESS_DENIED);
            return FALSE;
        //return SetLastError(ERROR_ACCESS_DENIED), FALSE;
    }

     return TRUE;
}


int main (int argc, char *argv[])
{
      if (argc < 2) {
            cout << "Usage: " << argv[0] << " <PID>" << endl;
            return -1;
      }

      int nPid = atoi(argv[1]);
      cout << "Pid to examine " << nPid << endl;


      WIN32CHECK(GrabKillerPrivilage());


    HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nPid);  
      char ProcessCmd[1024];

      if(hProc){
        HMODULE hMod;
            
            DWORD   needed;
                  
            if(EnumProcessModules(hProc, &hMod, sizeof(hMod), &needed)) {
              WIN32CHECK(GetModuleFileNameEx(hProc, hMod, ProcessCmd, sizeof(ProcessCmd)/ sizeof(ProcessCmd[0])));

              cout << "Process CMD = " << ProcessCmd << endl;

            } else {
              cout << "*** EnumProcessModules failed" << endl;
              WIN32CHECK(0);
            }
       
        CloseHandle(hProc);
      } else {
            cout << "*** OpenProcess failed" << endl;
            WIN32CHECK(0);
      }



      return 0;
}
0
 
LVL 8

Expert Comment

by:mxjijo
ID: 18033198
You can try these:

1) Change the hMod parameter of EnumProcesModule to an array - like this

HMODULE hMod[1024];
EnumProcessModules(hProc, &hMod, sizeof(hMod), &needed)) ;

2) If you are interesed only the exe file name you don't have to call EnumProcessModules.
Call GetModuleBaseName instead.

0
 

Author Comment

by:Assaf_Gantz
ID: 18038047
1. I am getting the same error
2. I need the full path to the binary not just the name

I think the problem related to 64 bits and I saw online that EnumProcessModulesEx
https://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/enumprocessmodulesex.asp
0
 

Author Comment

by:Assaf_Gantz
ID: 18039221
I see that some others identify this problem

http://www.64bit-world.com/forums/archive/index.php/t-5367.html
0
 
LVL 8

Accepted Solution

by:
mxjijo earned 300 total points
ID: 18039252

Yes, I noticed the 64 bit problem yesterday. That was the reason why I suggested GetModuleBaseName ()
http://www.osronline.com/showThread.cfm?link=78670

Unfortunately I can't find any solution for the 64 bit problem.
Try GetProcessImageFileName() like this:

     HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, nPid);  
     char ProcessCmd[1024];

     if (hProc) {
         GetProcessImageFileName(hProc, ProcessCmd, 1024);
         cout << ProcessCmd;
         CloseHandle(hProc);
     } else {
          cout << "*** OpenProcess failed" << endl;
          WIN32CHECK(0);
     }

0
 

Author Comment

by:Assaf_Gantz
ID: 18046023
I know it is not the full answer but it was helping me understand what's going on
10x
Assaf
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
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…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

751 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