how to get process handle from process id? - c++

I have process Id , I want to get its process handle.
Is there any API available for that.
I tried to use OpenProcess but it returns NULL, and GetLastError =0.
This I am trying on Vista.
I guess I need to enable SeDebugPrivilege before using OpenProcess .
But for enabling SeDebugPrivilege I need to get its Process handle.

OpenProcess(PROCESS_ALL_ACCESS, TRUE, procId);
You'll need to verify that you're using a valid process ID, and that you're permitted the access rights you request from the process.

Is this what you are looking for?
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
CloseHandle(processHandle);
Also, here is some code I use to set debug privledge before injecting DLLs.
void Loader::EnableDebugPriv(void)
{
HANDLE hToken;
LUID SeDebugNameValue;
TOKEN_PRIVILEGES TokenPrivileges;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &SeDebugNameValue))
{
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = SeDebugNameValue;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
CloseHandle(hToken);
}
else
{
CloseHandle(hToken);
throw std::exception("Couldn't adjust token privileges!");
}
}
else
{
CloseHandle(hToken);
throw std::exception("Couldn't look up privilege value!");
}
}
else
{
throw std::exception("Couldn't open process token!");
}
}
I've used the above code on Windows Vista with success.

You would need elevated privileges. Also look at similar question here.

I just had the exact same issue as described: OpenProcess() == NULL and GetLastError() == 0.
Turned out to be the Common Language RunTime Support setting, was set to "Pure" should have been just "Common". Took me ages to find.
For VS2010 c++ goto -> Project Properties -> Configuration Properties -> C/C++ -> General

If you have a process identifier, you can get the process handle by calling the OpenProcess function. OpenProcess enables you to specify the handle's access rights and whether it can be inherited.
FYI:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684868(v=vs.85).aspx

Related

TerminateProcess not working for specific processes

I need to terminate some processes before my program can run, but whenever I run TerminateProcess(), GetLastError() returns 5. What I know so far is that this means that access is denied, I also know that to elevate my rights i need to use AdjustTokenPrivileges(), based on Rango's answer here and Microsoft's documentation here.
What i don't know is why it wont work. Based on what I've read, the following should work:
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_ALL_ACCESS;
//DWORD dwDesiredAccess = ACCESS_SYSTEM_SECURITY;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = NULL;
TOKEN_PRIVILEGES tp = { 0 };
LUID luid;
LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hProcess, FALSE, &tp, 0, NULL, NULL);
hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
As you can tell from the above, I am not sure which dwDesiredAccess I am supposed to use. PROCESS_ALL_ACCESS lets me terminate other simple processes, such as chrome.exe or notepad.exe, but not what i need to terminate. ACCESS_SYSTEM_SECURITY is whats' said to be used by microsoft, but then i cannot terminate any process at all.
Also, is this even close to what i need to do, if not can you please point me in the right direction.
UPDATE: Added UpdatePrivilege() function from here, and called it before calling OpenProcess() function, still no bite.
UPDATE 2: The process I need to terminate is the "afwServ.exe" process, i.e. Avast's firewall. I need to do this so that my firewall is the sole firewall used by Windows. This a requirement of my project.
I think you misunderstood the difference between right and privileges, this answer explains it.
In this case, your current user may not have permission to terminate the specified process. You may first need to use LogonUser and use administrator identity to simulate the process context.
What you want to terminate is a service, you can try using ControlService with SERVICE_CONTROL_STOP to stop the services. But you also need to switch to the user with permission first.

Win7 C++ - Issue starting executable as user from service logged in as user

I am fixing an issue with a windows service that has up to this point had no problems impersonating the current user and starting an executable in that user's session.
My original issue was that I couldn't access information about mounted drives or the files on them. So I found I needed to define the service to log in as the user.
Once I did that I no longer had problems accessing these files, but impersonation for starting the executable no longer works. Or more specifically, my call to WTSQueryUserToken() no longer works, but returns false, and GetLastError() returns ERROR_PRIVILEGE_NOT_HELD.
I don't yet know if I will run into any issues with DuplicateTokenEx() or CreateProcessAsUserA(), but one thing at a time.
My code is as follows (dwSessId was retrieved before this point and is correct):
if (dwSessId >= 0)
{
HANDLE hCurrentToken;
HANDLE hPrimaryToken;
BOOL ok = WTSQueryUserToken(dwSessId, &hCurrentToken);
if (ok)
{
ok = DuplicateTokenEx(hCurrentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hPrimaryToken);
// now we start the executable process as the current user
STARTUPINFOA si;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
ret = (CreateProcessAsUserA(hPrimaryToken, procname.c_str(), NULL, 0, 0, false, CREATE_NO_WINDOW, 0, 0, &si, &m_pProcInfo) != 0);
}
}
else
{
int err = GetLastError();
return false;
}
Per the WTSQueryUserToken() documentation:
To call this function successfully, the calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege.
In other words, you can't configure your service to run as any particular user. But, it can certainly impersonate a user when needed, as long as the thread that is calling WTSQueryUserToken() is not impersonating a user at the time of the call.

How to control Windows services using Windows API easily?

Issue
I would like to control any Windows service using Windows API, but I cannot :(
= What's wrong with my "wanting solution"?
Current solution
The ugliest but functional way I use is following (for Stop command):
void StopService()
{
ShellExecute(Application->Handle,
"open",
"stop.bat",
NULL,
ExtractFilePath(Application->ExeName).c_str(),
SW_SHOW);
}
Where stop.bat is a Windows batch file with following commands:
::the command
sc stop "service name"
::a pause to see if something goes wrong
pause
It is very annoying to have to close launched cmd windows...
Wanting solution
The function bellow appears to be ok. If I try to perform a command to stop an unexisting service, it will show a error message. BUT when I try to run it for an existing service, it runs, but nothing happens with the service (if I ordain to stop it, it does nothing)...
void ControlService(AnsiString ServiceName, DWORD Order)
{
SC_HANDLE Scm, Svc;
SERVICE_STATUS Status;
Scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(Scm != 0)
{
Svc = OpenService(Scm, PChar(ServiceName.c_str()), SERVICE_ALL_ACCESS);
if(Svc != 0)
{
ControlService(Svc, Order, &Status);
// handle Status....
CloseServiceHandle(Svc);
}
else
{
ShowLastError();
}
CloseServiceHandle(Scm);
}
else
{
ShowLastError();
}
}
void ShowLastError()
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
MessageBox(NULL, (char*)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION);
// Free the buffer.
LocalFree(lpMsgBuf);
}
What's wrong?????
Two possible issues you might have run into:
You are checking state of service too soon. The ServiceControl returns immediately, without waiting for the service to complete the request. Your service could transition to SERVICE_STOP_PENDING, and in this case you will have to give it some time and check again.
There are dependent services in running state. You will have to enumerate dependent services, shut them down first, then stop your service.
On #2, there is good explanation with a sample code on MSDN. Here is a quote from the same page:
However, if the SCM determines that other running services are dependent on the specified service, it will not forward the stop request. Instead, it returns ERROR_DEPENDENT_SERVICES_RUNNING. Therefore, to programmatically stop such a service, you must first enumerate and stop its dependent services.

How to check if a process has the administrative rights

How do I properly check if a process is running with administrative rights?
I checked the IsUserAnAdim function in MSDN, but it is not recommended as it might be altered or unavailable in subsequent versions of Windows. Instead, it is recommended to use the CheckTokenMembership function.
Then I looked at the alternate example in MSDN from a description of the CheckTokenMembership function. However, there is Stefan Ozminski's comment in MSDN that mentions that this example does not work properly in Windows Vista if UAC is disabled.
Finally I tried to use Stefan Ozminski's code from MSDN, but it determines that the process has administrative rights even if I launch it under an ordinary user without the administrative rights in Windows 7.
This will tell you if you are running with elevated privileges or not. You can set the manifest to run with most possible if you want it to prompt. There are also other ways to ask windows through code for alternate credentials.
BOOL IsElevated( ) {
BOOL fRet = FALSE;
HANDLE hToken = NULL;
if( OpenProcessToken( GetCurrentProcess( ),TOKEN_QUERY,&hToken ) ) {
TOKEN_ELEVATION Elevation;
DWORD cbSize = sizeof( TOKEN_ELEVATION );
if( GetTokenInformation( hToken, TokenElevation, &Elevation, sizeof( Elevation ), &cbSize ) ) {
fRet = Elevation.TokenIsElevated;
}
}
if( hToken ) {
CloseHandle( hToken );
}
return fRet;
}
You can use LsaOpenPolicy() function.
The LsaOpenPolicy function opens a handle to the Policy object on a local or remote system.
You must run the process "As Administrator" so that the call doesn't fail with ERROR_ACCESS_DENIED.
Source: MSDN

ERROR_INVALID_HANDLE on TerminateProcess (VS C++)

Disclaimer: This is part of the requirement of the program, so it's not meant for anything bad. Feel free to point out any misuse if you spot one. I'm a beginner in C++.
Basically, I'm trying to restart Outlook.exe on Windows using C++.
And this is the code I used to restart Outlook.
#include <TlHelp32.h>
void RestartOutlook() {
PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
MODULEENTRY32 Mo = {sizeof (MODULEENTRY32) };
if(Process32First(hSnapshot, &Pc)){
do{
if(!_stricmp(Pc.szExeFile, "outlook.exe")) {
DWORD pid = Pc.th32ProcessID;
HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
//kill outlook
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
DWORD fdwExit = 0;
GetExitCodeProcess(process, &fdwExit);
TerminateProcess(process, fdwExit);
char * path;
if (Module32First(hModuleSnapshot, &Mo)) {
path = Mo.szExePath;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof (si);
CreateProcess(path, NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi);
}
}
}while(Process32Next(hSnapshot, &Pc));
}
}
The funny part is, this piece of code works perfectly fine on Windows 7. While on Windows XP (SP3), I get duplicated Outlook. The GetLastError gives me 6: ERROR_INVALID_HANDLE. I am really clueless after hours of research.
Any idea?
Anyway, C++ is not my field. I do webs :)
And the code above is a mixture of the following sources:
1: http://www.istorya.net/forums/programming/107435-how-can-i-kill-a-process-using-c.html
2: http://code.activestate.com/recipes/576362-list-system-process-and-process-information-on-win/
Environment: Windows 7, Windows XP, VS2010, Outlook 2003, Outlook 2007, Outlook 2010
I found the culprit.
The reason lies in this line:
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
According to http://msdn.microsoft.com/en-us/library/ms684880(v=vs.85).aspx, PROCESS_ALL_ACCESS is too large for Windows XP/NT system, or more details:
The size of the PROCESS_ALL_ACCESS flag increased on Windows Server 2008 and Windows Vista. If an application compiled for Windows Server 2008 and Windows Vista is run on Windows Server 2003 or Windows XP/2000, the PROCESS_ALL_ACCESS flag is too large and the function specifying this flag fails with ERROR_ACCESS_DENIED. To avoid this problem, specify the minimum set of access rights required for the operation.
Definitely I'm compiling this program on 7, while running on XP definitely causing the problem.
So the solution is, change the PROCESS_ALL_ACCESS to PROCESS_TERMINATE, which
HANDLE process = OpenProcess(PROCESS_TERMINATE, TRUE, pid);
Done!
Thanks #DReJ for quick replies :)
I get that you want Outlook to restart but calling TerminateProcess on Outlook seems like a bad idea in the first place. What if it's in the middle of writing a data file?
A better way would be to find all top-level windows that belong to Outlook, send them a WM_CLOSE and then wait for the process to exit. (You may also have to cope with the user having draft messages open which result in "are you sure" prompts, although if you are doing this in the first place then I assume you know the user isn't in the middle of something?)
An even better way would be to use Outlook's automation interface and tell it to shutdown explicitly.
Your problem maybe related to this piece of code
DWORD fdwExit = 0;
GetExitCodeProcess(process, &fdwExit);
TerminateProcess(process, fdwExit);
First, with GetExitCodeProcess you get status STILL_ACTIVE and after that you terminate process with this status which is not proper I think. Remove GetExitCodeProcess from you code and try TerminateProcess(process, 0); instead.