Terminating a process - c++

We have an application that has 3 processes as shown in the image below.
What I wanted to do is to terminate these processes. After reading a few tutorials, I was able to collate these codes. However, it's not working properly. The output is shown after the code.
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
pe32.dwSize = sizeof( PROCESSENTRY32 );
std::string message = "";
int processCounter = 0;
while( Process32Next( hProcessSnap, &pe32 ) ) {
char ch[260];
char DefChar = ' ';
WideCharToMultiByte(CP_ACP,0,pe32.szExeFile,-1, ch,260,&DefChar, NULL);
//A std:string using the char* constructor.
std::string process(ch);
if( process == "bridge.exe" ) {
std::wstring stemp = std::wstring(process.begin(), process.end());
LPCWSTR sw = stemp.c_str();
HWND windowHandle = FindWindowW( NULL, sw );
DWORD* dwProcessId = new DWORD;
GetWindowThreadProcessId( windowHandle, dwProcessId );
message.append( process );
message.append( "-" );
std::ostringstream converter;
converter << *dwProcessId;
message.append( converter.str() );
message.append( "-" );
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, *dwProcessId);
if( hProcess == NULL ) {
BOOL result = TerminateProcess(hProcess, 0);
message.append( "NULL" );
}
message.append( "\n" );
CloseHandle(hProcess);
}
}
This is the output:
bridge.exe-4597928-NULL
bridge.exe-4597568-NULL
bridge.exe-4587524-NULL
hProcess returns NULL. What did I miss? Thanks.

Related

Serial communication between pc and Arduino through USB

I have some C++ code that I need to use for serial communication between PC and Arduino. The file "Serial.cpp" is including a file called "stdafx.h" that doesn't exist in the project or anywhere on my computer, which obviously causes an error.
Other than that, I also get other errors, such as C2065 'CSerial': undeclared identifier.
Here are the three files that are in the project:
Serial.h
#ifndef __SERIAL_H__
#define __SERIAL_H__
#pragma once
#include <Windows.h>
#include <memory.h>
#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04
#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
class CSerial
{
public:
CSerial();
~CSerial();
BOOL Open( int nPort = 2, int nBaud = 9600 );
BOOL Close( void );
int ReadData( void *, int );
int SendData( const char *, int );
int ReadDataWaiting( void );
BOOL IsOpened( void ){ return( m_bOpened ); }
protected:
BOOL WriteCommByte( unsigned char );
HANDLE m_hIDComDev;
OVERLAPPED m_OverlappedRead, m_OverlappedWrite;
bool m_bOpened;
};
#endif
Serial.cpp
// Serial.cpp
#include "stdafx.h"
#include "Serial.h"
CSerial::CSerial()
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = false;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );
wchar_t szPort[15];
wchar_t szComParams[50];
DCB dcb;
wsprintf( szPort, L"COM%d", nPort );
m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == NULL ) return( FALSE );
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
wsprintf( szComParams, L"COM%d:%d,n,8,1", nPort, nBaud );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
return( FALSE );
}
m_bOpened = TRUE;
return( m_bOpened );
}
BOOL CSerial::Close( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
m_bOpened = FALSE;
m_hIDComDev = NULL;
return( TRUE );
}
BOOL CSerial::WriteCommByte( unsigned char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
else{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return( TRUE );
}
int CSerial::SendData( const char *buffer, int size )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwBytesWritten = 0;
int i;
for( i=0; i<size; i++ ){
WriteCommByte( buffer[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
}
int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return( (int) ComStat.cbInQue );
}
int CSerial::ReadData( void *buffer, int limit )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
SerialExample.cpp
bool sendExample(int port, int baudRate)
{
char data[4];
CSerial* s = new CSerial();
if(!s->Open(port, baudRate))
{
std_out << _T("Could not open COM") << port << endl;
return false;
}
// Sending a string of 4 characters
data[0] = 0x31;
data[1] = 0x32;
data[2] = 0x33;
data[3] = 0x0D; // ASCII CR
s->SendData(data, 4);
s->Close();
delete s;
}
Does anyone know what I have to do?
stdafx.h is a precompiled header for Visual studio. so if you are not working in visual studio, you can just remove it and it should work just fine.
In regard to the compiler not recognizing the CSerial class -
I don't see where you include "CSerial.h" in SerialExample.cpp (i.e: #include "CSerial.h"), but if you do, this may also be a symptom of CSerial.cpp not compiling (less likely though)...
Hope this helps,
Lior

Uninitialized Read Error

i have written a method to get all process id's inside a c++ project.
Int CProcessHelper::GetAllPIDs(const char *processName, _STL_NAMESPACE_::vector<DWORD> &pids)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
HANDLE hProcess;
BOOL bContinue;
pids.clear();
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
return 0;
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
bContinue = Process32First( hProcessSnap, &pe32 );
while(bContinue)
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
if( hProcess != NULL )
{
TCHAR szModName[MAX_PATH];
// Get the full path to the module's file.
if(GetModuleFileNameEx( hProcess, NULL, szModName,
sizeof(szModName)))
{
char *ptr = strrchr(szModName, '\\');
if( (ptr && stricmp(ptr+1, processName) == 0) ||
stricmp(szModName, processName) == 0)
{
pids.push_back(pe32.th32ProcessID);
/*CloseHandle( hProcess );
pid = pe32.th32ProcessID;
break;*/
}
}
CloseHandle( hProcess );
}
bContinue = Process32Next( hProcessSnap, &pe32 );
}
CloseHandle( hProcessSnap );
return (int) pids.size();
}
When i run this code under Dr Memory, i am getting following "Uninitialized Read" errors:
Uninitialized Read Error 1
at this line:
if(GetModuleFileNameEx( hProcess, NULL, szModName,
sizeof(szModName)))
2nd error is :
Uninitialized Read Error 2
at this line -
bContinue = Process32First( hProcessSnap, &pe32 );
i am not getting by Dr Memory reporting me these errors. Are these only false positive errors?
Please help me to identify which part is uninitialized here.
If you look at the attached Dr Memory error screenshot carefully, you will notice that both the errors have call to the
KERNELBASE.dll!WideCharToMultiByte
Since i am using TCHAR(1.e of char type, rather then of WCHAR type(wide char)) for szFileName var.
TCHAR szModName[MAX_PATH];
I am not getting why it is calling WideCharToMultiByte() method as i am using a method which accept char type rather then a wide char type.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);
pe32.th32ProcessID is not set yet, it's uninitialized memory. OpenProcess() is also not needed for your purpose.
if (GetModuleFileNameEx(hProcess, NULL, szModName, sizeof(szModName)))
this function is unnecessary, the executable name is exposed by the PROCESSENTRY32 structure. In addition, the last argument should use strlen, not sizeof because you want number of characters not size of buffer.
There are other issues with this code as well, rather than trying to reinvent the wheel, MSDN has a complete commented source code for doing what you want to do using the ToolHelp32Snapshot collection of functions, you can find it here.
Here is a concise example I have modified to fit your needs without any problems:
#include <windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <Psapi.h>
int GetAllPIDs(const char* processName, std::vector<DWORD>& pids)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (Process32First(hSnap, &procEntry))
{
do
{
if (!_stricmp(procEntry.szExeFile, processName))
{
pids.push_back(procEntry.th32ProcessID);
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return (int)pids.size();
}
int main()
{
std::vector<DWORD> piddies;
GetAllPIDs("calc.exe", piddies);
for (auto p : piddies)
{
std::cout << "0x" << std::hex << p << std::endl;
}
std::getchar();
return 0;
}

Check if process is running - Windows

i'm using QT to check if process is running and i used the same code in msdn site.
It worked fine on Visual Studio but i'm having a problem making it work on QT.
Here's the code :
bool matchProcessName( DWORD processID, std::string processName)
{
TCHAR szProcessName[MAX_PATH] = TEXT(L"notepad.exe");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Compare process name with your string
bool matchFound = !_tcscmp(szProcessName, processName.c_str() );
// Release the handle to the process.
CloseHandle( hProcess );
return matchFound;
}
The Error i'm getting is this :
error: cannot convert 'TCHAR*' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'
How can i make this work on QT ?
Thanks alot.
Update
I also tried this code :
DWORD FindProcessId(char* processName)
{
char* p = strrchr(processName, '\\');
if(p)
processName = p+1;
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if ( processesSnapshot == INVALID_HANDLE_VALUE )
return 0;
Process32First(processesSnapshot, &processInfo);
if ( !strcmp(processName, processInfo.szExeFile) )
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
while ( Process32Next(processesSnapshot, &processInfo) )
{
if ( !strcmp(processName, processInfo.szExeFile) )
{
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
CloseHandle(processesSnapshot);
return 0;
}
I'm also getting an error :cannot convert 'WCHAR*' to 'const char*' for argument '2' to 'int strcmp(const char*, const char*)'
I prefer if i can make 2nd method work !
Thanks again
It has nothing to do with Qt.
In the updated code, PROCESSENTRY32.szExeFile is a TCHAR[],
i.e. it is a WCHAR[] if the macro _UNCODE is defined else is a char[].
So you have to transfer your char *processName to TCHAR[] and use _tcscmp(...) to compare TCHAR[].
Modified code:
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <Psapi.h>
#include <cstring>
#include <string>
#define MIN(x, y) ((x) > (y)) ? (y) : (x)
void cstringToTCHAR(TCHAR *dst, const char *src, size_t l) {
#if defined(_UNICODE) || defined(UNICODE
mbstowcs(dst, src, l);
#else
memcpy(dst, src, l);
#endif
}
bool matchProcessName( DWORD processID, std::string processName)
{
TCHAR szProcessName[MAX_PATH] = _T("notepad.exe");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Compare process name with your string
TCHAR systemEncodeProcessName[30];
size_t processNameLen = MIN((processName.size() + 1), 30);
cstringToTCHAR(systemEncodeProcessName, processName.c_str(), processNameLen);
bool matchFound = !_tcscmp(szProcessName, systemEncodeProcessName);
// Release the handle to the process.
CloseHandle( hProcess );
return matchFound;
}
DWORD FindProcessId(char* processName) {
char* p = strrchr(processName, '\\');
if(p) {
processName = p+1;
}
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE) {
return 0;
}
//Transfer char array to TCHAR array.
TCHAR systemEncodeProcessName[30];//Maybe need more or dynamic allocation.
size_t processNameLen = MIN((strlen(processName) + 1), 30);
cstringToTCHAR(systemEncodeProcessName, processName, processNameLen);
Process32First(processesSnapshot, &processInfo);
if (!_tcscmp(systemEncodeProcessName, processInfo.szExeFile)) {
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
while ( Process32Next(processesSnapshot, &processInfo) ) {
if ( !_tcscmp(systemEncodeProcessName, processInfo.szExeFile) ) {
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
CloseHandle(processesSnapshot);
return 0;
}
Update
In Qt creator(3.3.0), the _UNICODE macro looks like missing in Windows platform, just add
DEFINES += _UNICODE
in your .pro file and then run qmake && build.

How can I programmatically retrieve the details of a 64 bit process in C++?

My goal is to get the full command line of a 64 bit process programmatically. I have understood and written this code where I do a process walk of all the currently running processes and get each of their details. But the issue is that this code fails to do the same for a 64 bit process (one that is not running under WOW64).
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
BOOL GetProcessList( FILE *f);
BOOL ListProcessModules( DWORD dwPID, FILE *f);
BOOL ListProcessThreads( DWORD dwOwnerPID, FILE *f );
void printError( TCHAR* msg, FILE *f );
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL IsWow64(HANDLE processHandle)
{
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if(fnIsWow64Process != NULL)
{
if (!fnIsWow64Process(processHandle, &bIsWow64))
{
//handle error
}
}
return bIsWow64;
}
int main( void )
{
FILE *f = fopen("file_.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
GetProcessList(f);
return 0;
}
BOOL GetProcessList( FILE *f)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
fprintf(f, "start writing:\n");
/*
myfile.open ("example.txt");
myfile << "writing starts here..." << endl;
*/
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)"), f);
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First"), f ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
_tprintf( TEXT("\n\n=====================================================" ));
_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
_tprintf( TEXT("\n-------------------------------------------------------" ));
fprintf(f, "\n\n=====================================================");
fprintf(f, "\nPROCESS NAME: %s", pe32.szExeFile );
fprintf(f, "\n------------------------------------------------------------");
/*
myfile << "\n\n=====================================================";
myfile << "\nPROCESS NAME " << pe32.szExeFile;
myfile << "\n-----------------------------------------------------------";
*/
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
//is hProcess the handle to the process?
if( hProcess == NULL )
printError( TEXT("OpenProcess"), f );
else
{
if(IsWow64(hProcess)){
_tprintf(TEXT("\nThe process is running under WOW64.\n"));
fprintf(f, "\nThe process is running under WOW64.\n");
//myfile << "\nThe process is running under WOW64.\n";
}
else{
_tprintf(TEXT("\nThe process is not running under WOW64.\n"));
fprintf(f, "\nThe process is not running under WOW64.\n");
//myfile << "\nThe process is not running under WOW64.\n";
}
dwPriorityClass = GetPriorityClass( hProcess );
if( !dwPriorityClass )
printError( TEXT("GetPriorityClass"), f );
CloseHandle( hProcess );
}
_tprintf( TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID );
_tprintf( TEXT("\n Thread count = %d"), pe32.cntThreads );
_tprintf( TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
_tprintf( TEXT("\n Priority base = %d"), pe32.pcPriClassBase );
fprintf(f, "\n Process ID = 0x%08X", pe32.th32ProcessID);
fprintf(f, "\n Thread count = %d", pe32.cntThreads );
fprintf(f, "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID );
fprintf(f, "\n Priority base = %d", pe32.pcPriClassBase );
if( dwPriorityClass )
_tprintf( TEXT("\n Priority class = %d"), dwPriorityClass );
// List the modules and threads associated with this process
ListProcessModules( pe32.th32ProcessID,f );
ListProcessThreads( pe32.th32ProcessID,f );
char *cmd_line = NULL;
//get_cmdline_from_pid(pe32.th32ProcessID, cmd_line);
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
BOOL ListProcessModules( DWORD dwPID,FILE *f )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of modules)"), f );
return( FALSE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
printError( TEXT("Module32First"), f ); // show cause of failure
CloseHandle( hModuleSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the module list of the process,
// and display information about each module
do
{
_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );
_tprintf( TEXT("\n Executable = %s"), me32.szExePath );
_tprintf( TEXT("\n Process ID = 0x%08X"), me32.th32ProcessID );
_tprintf( TEXT("\n Ref count (g) = 0x%04X"), me32.GlblcntUsage );
_tprintf( TEXT("\n Ref count (p) = 0x%04X"), me32.ProccntUsage );
_tprintf( TEXT("\n Base address = 0x%08X"), (DWORD) me32.modBaseAddr );
_tprintf( TEXT("\n Base size = %d"), me32.modBaseSize );
fprintf(f, "\n\n MODULE NAME: %s", me32.szModule );
fprintf(f, "\n Executable = %s", me32.szExePath );
fprintf(f, "\n Process ID = 0x%08X", me32.th32ProcessID );
fprintf(f, "\n Ref count (g) = 0x%04X", me32.GlblcntUsage );
fprintf(f, "\n Ref count (p) = 0x%04X", me32.ProccntUsage );
fprintf(f, "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr );
fprintf(f, "\n Base size = %d", me32.modBaseSize );
} while( Module32Next( hModuleSnap, &me32 ) );
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL ListProcessThreads( DWORD dwOwnerPID,FILE *f )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
printError( TEXT("Thread32First"), f ); // show cause of failure
CloseHandle( hThreadSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
_tprintf( TEXT("\n\n THREAD ID = 0x%08X"), te32.th32ThreadID );
_tprintf( TEXT("\n Base priority = %d"), te32.tpBasePri );
_tprintf( TEXT("\n Delta priority = %d"), te32.tpDeltaPri );
_tprintf( TEXT("\n"));
fprintf(f, "\n\n THREAD ID = 0x%08X", te32.th32ThreadID);
fprintf(f, "\n Base priority = %d", te32.tpBasePri );
fprintf(f, "\n Delta priority = %d", te32.tpDeltaPri );
fprintf(f, "\n");
}
} while( Thread32Next(hThreadSnap, &te32 ) );
CloseHandle( hThreadSnap );
return( TRUE );
}
void printError( TCHAR* msg, FILE *f )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
// Display the message
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
fprintf(f, "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg);
}
It gives me the ERROR CODE 299, which indicates that it could not read or write memory from the process, and thus does not provide me the executable command for any 64 bit process.
=====================================================
PROCESS NAME: taskhostex.exe
------------------------------------------------------------
The process is not running under WOW64.
Process ID = 0x00001954
Thread count = 10
Parent process ID = 0x000003BC
Priority base = 8
WARNING: CreateToolhelp32Snapshot (of modules) failed with error 299 (Only part of a ReadProcessMemory or WriteProcessMemory request was completed)
Could anyone please help me out with getting around this issue?
Thanks.
This is not possible. From the documentation:
If the specified process is a 64-bit process and the caller is a
32-bit process, this function fails and the last error code is
ERROR_PARTIAL_COPY (299).
You need to compile your code as 64-bit.
Here more about this issue: How to enum modules in a 64bit process from a 32bit WOW process.

RegOpenKeyEx returning Error 87 aka "INVALID_PARAMETER"

I am implementing a recursive registry delete using RegOpenKeyEx, RegDeleteKey and RegEnumKey.
Problem:: Though the code works perfectly fine for Vista x86/x64 and Win 7 x86/x64 but fails on XP for some keys in HKCR
Problem Area:: HKCR\Installer\Products\SomeKey
Error Code:: 87 (INVALID_PARAMETER)
Weird Behaviour:: Deletes the key the moment I open the key using REGEDIT.
Code::
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub )
{
BOOL bRet = TRUE ;
LONG lRet ;
DWORD dwSize = MAX_PATH ;
TCHAR szName[MAX_PATH] ;
TCHAR szFullKey[MAX_PATH * 2] ;
HKEY hKeySub = NULL ;
HRESULT hr = NULL ;
do{
lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKeySub ) ;
printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
if( lRet == ERROR_FILE_NOT_FOUND )
{
bRet = TRUE ;
break ;
}
else
{
bRet = FALSE ;
break ;
}
}
while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL)) )
{
bRet = RcrsvRegDel( hKeySub, szName) ;
if( bRet == FALSE )
break ;
}
if( hKeySub != NULL )
{
RegCloseKey(hKeySub) ;
hKeySub = NULL ;
}
lRet = RegDeleteKey( hKey, lpszSub ) ;
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet == ERROR_SUCCESS )
{
bRet = TRUE ;
break ;
}
}while(0) ;
return bRet ;
}
Any idea whats goin on?
UPDATE::
I have also tried the samDesired Parameter with following flags
-KEY_READ
-KEY_READ | KEY_WRITE
-KEY_ENUMERATE_SUB_KEYS
-KEY_ENUMERATE_SUB_KEYS | DELETE
Neither of the above flag works :-(
Because you can not use RegDeleteKey with handle was opened with flag KEY_WOW64_32KEY.
see http://msdn.microsoft.com/en-us/library/aa384129(v=vs.85).aspx for info.
You have to use RegDeleteKeyEx with same keys.
You can do like this. Take the flag as input parameter and pass one flag for the RegOpenKeyEx and again a set of flags when calling the recursive function. I have tried your code and it is working perfectly now, though it is not sure as to what was it that was causing the problem.
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub, DWORD dwOpenFlags )
{
BOOL bRet = TRUE ;
LONG lRet ;
DWORD dwSize = MAX_PATH ;
TCHAR szName[MAX_PATH] ;
HKEY hKeySub = NULL ;
HRESULT hr = NULL ;
HANDLE hProcess = NULL ;
HANDLE hToken = NULL ;
do{
bRet = SetPrivilege( SE_BACKUP_NAME, TRUE ) ;
if( bRet == FALSE )
{
bRet = FALSE ;
break ;
}
lRet = RegOpenKeyEx( hKey, lpszSub, 0, dwOpenFlags, &hKeySub ) ;
if( lRet != ERROR_SUCCESS )
{
bRet = FALSE ;
break ;
}
while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL,
NULL, NULL, NULL)) )
if( !RcrsvRegDel(hKeySub, szName, dwOpenFlags) )
{
bRet = FALSE ;
break ;
}
lRet = RegDeleteKey( hKey, lpszSub ) ;
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
bRet = FALSE ;
break ;
}
if( hKeySub != NULL )
{
RegCloseKey(hKeySub) ;
hKeySub = NULL ;
}
}while(0) ;
return bRet ;
}
static BOOL SetPrivilege( LPCTSTR lpszPrivilege, BOOL bEnablePrivilege )
{
LUID luid ;
BOOL bRet = TRUE ;
HANDLE hToken = NULL ;
HANDLE hProcess = NULL ;
TOKEN_PRIVILEGES tp ;
do{
hProcess = GetCurrentProcess() ;
if( 0 == OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) )
{
bRet = FALSE ;
break ;
}
if( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) )
{
bRet = FALSE ;
break ;
}
tp.PrivilegeCount = 1 ;
tp.Privileges[0].Luid = luid ;
if( bEnablePrivilege )
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
else
tp.Privileges[0].Attributes = 0 ;
if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL) )
{
bRet = FALSE ;
break ;
}
if( ERROR_NOT_ALL_ASSIGNED == GetLastError() )
{
bRet = FALSE ;
break ;
}
}while(0) ;
if( hToken != NULL ) CloseHandle( hToken ) ;
return bRet ;
}
You cannot use RegDeleteKey() to delete a 32-bit key on a 64-bit system. The documentation says as much:
The RegDeleteKey function cannot be used to access an alternate registry view.
You must use RegDeleteKeyEx() instead.
Try something like this:
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
extern LPFN_ISWOW64PROCESS fnIsWow64Process;
typedef LONG (WINAPI *LPFN_REGDELETEKEYEX)(HKEY, LPCTSTR, REGSAM, DWORD);
extern LPFN_REGDELETEKEYEX fnRegDeleteKeyEx;
.
BOOL WINAPI IsWow64Process_Impl(HANDLE hHandle, PBOOL Wow64Process);
{
*Wow64Process = FALSE;
return TRUE;
}
BOOL WINAPI IsWow64Process_Stub(HANDLE hProcess, PBOOL Wow64Process)
{
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
if ( NULL == fnIsWow64Process )
fnIsWow64Process = &IsWow64Process_Impl;
return fnIsWow64Process(hProcess, Wow64Process);
}
LONG WINAPI RegDeleteKeyEx_Impl(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
return RegDeleteKey( hKey, lpSubKey );
}
LONG WINAPI RegDeleteKeyEx_Stub(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
fnRegDeleteKeyEx = (LPFN_REGDELETEKEYEX) GetProcAddress(GetModuleHandle(TEXT("advapi32")),
#ifdef UNICODE
"RegDeleteKeyExW"
#else
"RegDeleteKeyExA"
#endif
);
if ( NULL == fnRegDeleteKeyEx )
fnRegDeleteKeyEx = &RegDeleteKeyEx_Impl;
return fnRegDeleteKeyEx( hKey, lpSubKey, samDesired, dwReserved );
}
LPFN_ISWOW64PROCESS fnIsWow64Process = &IsWow64Process_Stub;
LPFN_REGDELETEKEYEX fnRegDeleteKeyEx = &RegDeleteKeyEx_Stub;
.
BOOL IsWin64()
{
#if defined(_WIN64)
return FALSE; // 64-bit programs run only on Win64
#elif defined(_WIN32)
// 32-bit programs run on both 32-bit and 64-bit Windows so must sniff
BOOL f64 = FALSE;
return fnIsWow64Process(GetCurrentProcess(), &f64) && f64;
#else
return FALSE; // Win64 does not support Win16
#endif
}
.
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub )
{
BOOL bRet = TRUE;
LONG lRet;
DWORD dwSize;
TCHAR szName[MAX_PATH+1];
HKEY hKeySub = NULL;
REGSAM Wow64Flag = (IsWin64()) ? KEY_WOW64_32KEY : 0;
lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | DELETE | Wow64Flag, &hKeySub ) ;
printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
if ( lRet != ERROR_FILE_NOT_FOUND )
bRet = FALSE;
}
else
{
do
{
dwSize = MAX_PATH;
lRet = RegEnumKeyEx( hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL );
if ( lRet != ERROR_SUCCESS )
{
if ( lRet != ERROR_NO_MORE_ITEMS )
bRet = FALSE;
break;
}
bRet = RcrsvRegDel( hKeySub, szName );
if ( !bRet )
break;
}
while (1);
RegCloseKey(hKeySub);
if ( bRet )
{
if ( Wow64Flag != 0 )
lRet = fnRegDeleteKeyEx( hKey, lpszSub, Wow64Flag, 0 );
else
lRet = RegDeleteKey( hKey, lpszSub );
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if ( lRet != ERROR_SUCCESS )
bRet = FALSE;
}
}
return bRet;
}
With that said, consider using RegDeleteTree() or SHDeleteKey() instead. Let them do the recursion for you.