Windows C++ : Getting the process name from a process ID

It seems the opposite is a better documented problem (e.g. Get Process ID (PID) from process name (string) – C++ Windows API), so just in case some one out there has a Process ID, and needs to translate it into the actual name, here goes:

std::string ProcIDtoProcName(std::uint32_t pid) {
    
    std::string result = "UNKNOWN";
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess != NULL) {
        char buffer[MAX_PATH];
        GetProcessImageFileNameA(hProcess, buffer, MAX_PATH);        
        result = std::string(buffer);
        CloseHandle(hProcess);
        // see note below
        auto friendlyResult = convertWinPath(result); 
        return friendlyResult;
    }    
    
    return result;
}

Note the convertWinPath function. the “GetProcessImageFileNameA” is a windows API which returns the image name from the point of view of the kernel. The kernel does not deal in logical drive letters like C: or D:, and instead would output a raw device path such as \Device\HarddiskVolume0\.

For the sake of user friendliness, it’s advisable to lookup the corresponding drive letter, for example like so:

std::string convertWinPath(std::string pathname) {

    std::regex e("\\\\Device\\\\HarddiskVolume[0-9]+\\\\");
    std::smatch device_match;

    // check if the incoming pathname actually includes the raw device path
    if (std::regex_search(pathname, device_match, e)) {
        auto devicePath = device_match[0].str();
        std::string driveLetter = "";
        
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
        std::wstring wPathname = converter.from_bytes(pathname);
       
        LPCWSTR pathLP = wPathname.c_str();
        WCHAR volume_path[MAX_PATH];  // MAX_PATH = 256

        // this is the actial windows API call
        GetVolumePathNameW(pathLP, volume_path, MAX_PATH);
        
        // there's a bunch of ways to convert from wstring to string, here i happen to use
        // a function included in the krabsetw library
        driveLetter = krabs::from_wstring(volume_path);        

        // again - multiple ways of replacing the device path with the drive letter,
        // here I happen to use a function provided by the "boost" library
        boost::replace_first(pathname, devicePath, driveLetter);

    }
    return pathname;
}