OpenProcess function returns invalid handles - c++

I'm working on an application that creates multiple desktops and gives the user the ability to start whatever applications he desires under the desktop he is currently using.
When that desktop is closed (using a combo key) I want close all applications opened under that desktop. In order to do this I enumarate all processes using the EnumProcesses function and retrive a handle based on every process identifier returned by EnumProcesses using OpenProcess function. Using GetThreadId I retrieve the thread identifier which is used as the parameter for GetThreadDesktop function and the returned handle is compared with the one from my desktop, so I can find out in which desktop the process runs.
At least in theory, this works, because for every process identifier, OpenProcess function returns an invalid handle for GetThreadId (error code 6). I'm running the application as administrator and I enable the SeDebugPrivilege privilege.
I don't understand why the returned handle is always invalid, here is the code that I use:
void iterateProcesses(HDESK threadDesktop)
{
EnableDebugPriv(); // functions enables the SeDebugPrivilege privilege
int found = 0;
int wanted = 0;
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded);
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++)
{
if (aProcesses[i] != 0)
{
found++;
if (GetThreadDesktop(checkProcess(aProcesses[i])) == threadDesktop)
{
wanted++;
}
}
}
}
DWORD checkProcess(DWORD processID)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processID);
GetLastError(); // if in the manifest file under 'UAC execution level'
// the application does not requests for administrator rights
// GetLastError() will return code 5 (access denied)
DWORD dwThreadId = GetThreadId(hProcess);
GetLastError(); // return code 6 (ERROR_INVALID_HANDLE)
// dwThreadId returned is always 0 because the handle is not valid
CloseHandle(hProcess);
return dwThreadId;
}

Your error checking is wrong. Please read the documentation again. Only call GetLastError if the function failed.
It's reasonable that you will only be able to get all access to a process handle if you are executing elevated. But you do need to check the value returned by OpenProcess, as described in the documentation. Only proceed if that value indicates success. Otherwise, call GetLastError to find out why.
You are expected to pass a thread handle to GetThreadId. hProcess is a process handle. Hence the ERROR_INVALID_HANDLE error code. But again, you are not checking for errors properly. You must first check the return value, as stated in the documentation. Only if that indicates failure do you call GetLastError.
I'm not sure how you can expect to get a single thread from a process. Processes can, and do, have many threads. Indeed threads can be created and destroyed so perhaps the thread you are looking for is not there anymore. All the same, here's how to enumerate threads in a process: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686852.aspx

Related

Replacing vector with array or static vector for a better approach

My application runs particular number of processes(different executables) using createprocess(windows api) in parallel(using threads). User can refresh / close my application at any time. As of now, I am pushing the process handles into vector and whenever close request received, I am iterating the vector and terminating(using GetExitCodeProcess and TerminateProcess APIs) and closing(using CloseHandle API) the process handles. Also I am closing the handle of the process when it is completed. The problem with current model is, whenever process completed handle will be closed and when close request received again I will try to close it using vector(handle is not updated). To solve this, I have to update/remove the handle in/from the vector. To do this, need to maintain index.
Since I know the number of process, I want to create a static vector and update it rather than pushing a local object to a vector. Can someone suggest a best approach.
Below is the sample code.
//member object
std::vector<PROCESS_INFORMATION> mProcessHandles;
//this is a thread and will be called multiple times with different executable names in the application
void method(std::string executable)
{
STARTUPINFO startInfo{};
PROCESS_INFORMATION procInfo{};
bool ret = CreateProcess(NULL, executable, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo);
mProcessInfo.push_back(procInfo);
if(ret)
{
WaitForSingleObject(procInfo.hProcess, INFINITE);
CloseHandle(procInfo.hProcess);
procInfo.hProcess = NULL;
CloseHandle(procInfo.hThread);
procInfo.hThread = NULL;
}
return;
}
//this will be called when application close requested
void forceKill()
{
for (auto &processHandlesIt : mProcessHandles)
{
DWORD errorcode = 0;
GetExitCodeProcess(processHandlesIt.hProcess, &errorcode);
if (errorcode == STILL_ACTIVE)
{
TerminateProcess(processHandlesIt.hProcess, errorcode);
}
CloseHandle(processHandlesIt.hProcess);
processHandlesIt.hProcess = NULL;
CloseHandle(processHandlesIt.hThread);
processHandlesIt.hThread = NULL;
}
}
You should not use handles (in GetExitCodeProcess for example) after they are closed.
I would simply not close those process handles in the threads, and just leave them for the forceKill or other clean-up function to close.
Also, since you are not using procInfo.hThread, you could close it right after CreateProcess returns.
I guess you are not using any other members of the procInfo, so you could only store the process' handles in your vector.

The handle OpenThread() had returned,QueueUserApc() thinks it is invalid

I would to use the function--QueueUserApc(),but it returns 0,and GetLastError() returns 6--invalid handle.There is only one handle--the second parameter of the function QueueUserApc(),but it was returned by OpenThread().so what's wrong there??????
part of the code:
void WINAPI My_IDtoHandle(IN PDWORD IDArray,
IN DWORD dwNumber,
OUT PHANDLE * Thread_Handle_Array)
{
PHANDLE handlearray;
DWORD count = 0;
handlearray = (PHANDLE)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwNumber*sizeof(HANDLE));
for (; count < dwNumber; count++)
{
handlearray[count] = OpenThread(THREAD_ALL_ACCESS,
FALSE,
IDArray[count]);
if (handlearray[count] == NULL)
printf("Open the thread-%d is failed!\n\n", IDArray[count]);
}
*Thread_Handle_Array = handlearray;
return;
}
call the function above:
result = QueueUserAPC((PAPCFUNC)SetEvent,
Thread_Handle_Array[count],
(ULONG_PTR)(Target_Event_Handle_Array + count));
if (result == 0)
{
printf("The inserting of the %dth function-SetEvent is failed!\n\n", count + 1);
printf("The error code is %d\n\n", GetLastError());
}
And the handle the OpenThread returned is strang:
It seems that the problem was attempting to queue an APC to a 64-bit thread from a 32-bit thread.
The documentation says:
Similarly, if a 64-bit process queues an APC to a 32-bit process or vice versa, addresses will be incorrect and the target application will crash.
... which was apparently added in response to a bug report as described in this USENET post seven years ago. At that time it seems that any such call to QueueUserAPC() would fail with ERROR_INVALID_FUNCTION but would also crash the target thread.
It seems likely that this issue was later addressed by explicitly blocking any such attempt and reporting ERROR_INVALID_HANDLE.

How can an independent DLL find out what Token file accesses will be made with?

If the parent process has used LogonUser so that the access token being used for file access is different than than the token the process was started with, how can the DLL find out the NT User name that the file accesses will be processed under?
If I had a specific file location then I could use GetFileSecurity, however I don't know any guaranteed accessible paths in the context of the DLL.
If I used the following:
PSID ownedSID(NULL);
SECURITY_INFORMATION siRequested = OWNER_SECURITY_INFORMATION;
wSecInfoOK = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, siRequested, &ownedSID, NULL, NULL, NULL, NULL);
then the PSID returned references the Windows user of the logged on process rather than that under which any writes will be treated as!
New Question in light comment / answer from #arx
I am now using TokenUser with GetTokenInformation on the handle from OpenThreadToken, but again I am getting the launching user but not the impersonated user
HANDLE hThreadToken = NULL;
if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hThreadToken))
{
// success
CHeapPtr<TOKEN_USER, CGlobalAllocator> pToken;
DWORD length = 0U, dwError(0UL);
if (!GetTokenInformation(hThreadToken, TokenUser, NULL, 0, &length) && ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
pToken.AllocateBytes(length);
SetLastError(ERROR_SUCCESS);//Reset last error - we have now allocated the required memory so the buffer is now big enough i.e GetLastError() != ERROR_INSUFFICIENT_BUFFER
if (pToken && GetTokenInformation(hThreadToken, TokenUser, pToken, length, &length))
{
if (IsValidSid(pToken->User.Sid))
sFailedUser = WinSecurityInfo::GetAccountSID(pToken->User.Sid, dwError);
}
dwError = GetLastError();
if (dwError)
{
boost::system::error_code sidError = MakeSysError(dwError);
TRACE("Error text for GetLastError() = '%s'\n", sidError.message().c_str());
}
}
}
P.S WinSecurityInfo::GetAccountSID is just a wrapper around LookupAccountSid
P.P.S Tried both FALSE and TRUE in OpenThreadToken, no change
You are looking at the wrong information in the thread token retrieved with OpenThreadToken. To get the identity of the user being impersonated you need to look at the TokenUser, not the TokenOwner.
Use GetTokenInformation to retrieve the user.
However, rather than going to great lengths to work in the face of impersonation, it is more usual to specify as part of your API contract that you don't. And then ignore the problem.

Why does GetProcessImageFileName return null instead of the address of the process?

I am trying to pool the list of all processes in Qt.For this purpose i am using Windows API.
the following code demonstrates my effort so far:
QList<QString> frmProcess::GetAllRunningProcesses()
{
HANDLE hSysSnapshot = NULL;
HANDLE processHandle;
PROCESSENTRY32 proc;
proc.dwSize = sizeof(proc);
hSysSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
Process32First(hSysSnapshot,&proc);
proc.dwSize = sizeof(proc);
ui->listWidget->clear();
LPWSTR processPath;
list.clear();
do
{
//This block of code is to get each process's path and store it in a list
//PROCESS_ALL_ACCESS is commented out since it fails the program on start-up
processHandle = OpenProcess( /*PROCESS_ALL_ACCESS*/PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, proc.th32ProcessID );
GetProcessImageFileName(processHandle,processPath,MAX_PATH);
procpaths.append(QString::fromWCharArray(processPath));
list.append(QString::fromWCharArray(proc.szExeFile));
} while(Process32Next(hSysSnapshot,&proc));
CloseHandle( hSysSnapshot );
return list;
}
In the code posted above, I am trying to get as much as information i can get on a process, for this i am pooling the process names with the help of CreateToolhelp32Snapshot and then get their path with GetProcessImageFileName. And all of this happen in a timer tick event each milliseconds.
If i run the program , after couple of seconds it crashes, I get segmentation fault.
I also tried debugging since i couldn't get any path relating to any process!
And to my surprise i only get empty strings for path of each process!
What am i doing wrong?
Your GetProcessImageFileName does not receive a proper argument. processPath has to point to valid buffer.
TCHAR processPath[MAX_PATH] = { 0 };
GetProcessImageFileName(processHandle, processPath, _countof(processPath));
Also, you want to check returned value to see if you succeeded or not.

Close handle to a mutex in another process

I want to close a handle to a mutex located in another process, so I can run more than one instance of the application.
I already know this can be done, see Process Explorer. Example: Windows Minesweeper (Windows 7) uses a mutex to only allow one game, so I thought I would use it as an example since it's pre-installed with Windows and therefore easier for you guys to guide me.
The mutex that I need to close is \Sessions\1\BaseNamedObjects\Oberon_Minesweeper_Singleton, which I found using Process Explorer.
After closing this mutex I was able to launch two games of Minesweeper, but I want to do this in my program using C++.
After some searching I have found that I might need the API DuplicateHandle. So far I haven't been able to close the handle on this mutex.
Here is my code so far:
#include <Windows.h>
#include <iostream>
using namespace std;
void printerror(LPSTR location){
printf("Error: %s_%d", location, GetLastError());
cin.get();
}
int main(){
DWORD pid = 0;
HWND hMineWnd = FindWindow("Minesweeper", "Minesveiper");
GetWindowThreadProcessId(hMineWnd, &pid);
HANDLE hProc =OpenProcess(PROCESS_DUP_HANDLE, 0, pid);
if(hProc == NULL){
printerror("1");
return 1;
}
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, "Oberon_Minesweeper_Singleton");
if(hMutex == NULL){
printerror("2");
return 2;
}
if(DuplicateHandle(hProc, hMutex, NULL, 0, 0, FALSE, DUPLICATE_CLOSE_SOURCE) == 0){
printerror("3");
return 3;
}
if(CloseHandle(hMutex) == 0){
printerror("4");
return 4;
}
return 0;
}
This code returns 0, but the mutex is still there, and I am not able to launch more games of Minesweeper. I think some of my parameters to DuplicateHandle are wrong.
The second argument to DuplicateHandle expects "an open object handle that is valid in the context of the source process", however I believe the handle you're passing in would only be valid within the current process (OpenMutex creates a new handle to an existing mutex object). You'll likely need to determine what the mutex's handle is in the remote process, and use that value when calling DuplicateHandle.