c++windowsvisual-c++privilegescross-process

How to use OpenProcessToken, AdjustTokenPrivileges, and GetExitCodeProcess in VC++ 2005


I read a couple of posts on how to check if a process has exited from a different process (I realize some people get hung up on semantics here, but just humor me) and I tried to implement it but am running into the error code 5 ("ERROR_ACCESS_DENIED") all over the place.

Here is what I do.

1) Process 1 (P1) launches process 2 and writes to a shared memory location its own PID.

2) Process 2 (P2) reads the PID from shared memory

3) P2 calls OpenProcess(...) with P1's PID to save a handle that it can check later.

4) P2 calls GetExitCodeProcess(...) with P1's PID repeatedly and checks for a STILL_ACTIVE code.

In the above method, I keep getting the ACCESS_DENIED error on GetExitCodeProcess. I've tried modifying P2's privileges by using the below code from MSDN's docs:

HANDLE proc_h = OpenProcess(SYNCHRONIZE, FALSE, GetCurrentProcessId());
HANDLE hToken;
OpenProcessToken(proc_h, TOKEN_ADJUST_PRIVILEGES, &hToken);

LookupPrivilegeValue(NULL, lpszPrivilege, &luid );

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Enable the privilege
AdjustTokenPrivileges(hToken, 
                      FALSE, 
                      &tp, 
                      sizeof(TOKEN_PRIVILEGES), 
                      (PTOKEN_PRIVILEGES) NULL, 
                      (PDWORD) NULL);

But I keep getting the ACCESS_DENIED error on the call to OpenProcessToken(...) method. So does this indicate some sort of system level hurdle? I do have admin rights on my machine and I'm running XP.

Thanks in advance for any help.


Solution

  • The handle passed to GetExitCodeProcess requires PROCESS_QUERY_INFORMATION access right. The following works fine:

    int main(int a_argc, char** a_argv)
    {
        int pid = atoi(*(a_argv + 1));
    
        HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
    
        if (NULL != h)
        {
            Sleep(2000);
            DWORD exit_code;
            if (FALSE == GetExitCodeProcess(h, &exit_code))
            {
                std::cerr << "GetExitCodeProcess() failure: " <<
                    GetLastError() << "\n";
            }
            else if (STILL_ACTIVE == exit_code)
            {
                std::cout << "Still running\n";
            }
            else
            {
                std::cout << "exit code=" << exit_code << "\n";
            }
        }
        else
        {
            std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
        }
    
        return 0;
    }
    

    Instead of polling on GetExitCodeProcess open the handle with SYNCHRONIZE and wait for it to exit:

    int main(int a_argc, char** a_argv)
    {
        int pid = atoi(*(a_argv + 1));
    
        HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid);
    
        if (NULL != h)
        {
            WaitForSingleObject(h, 5000); // Change to 'INFINITE' wait if req'd
            DWORD exit_code;
            if (FALSE == GetExitCodeProcess(h, &exit_code))
            {
                std::cerr << "GetExitCodeProcess() failure: " <<
                    GetLastError() << "\n";
            }
            else if (STILL_ACTIVE == exit_code)
            {
                std::cout << "Still running\n";
            }
            else
            {
                std::cout << "exit code=" << exit_code << "\n";
            }
        }
        else
        {
            std::cerr << "OpenProcess() failure: " << GetLastError() << "\n";
        }
    
        return 0;
    }