How to get the process ID when starting Mozilla Firefox? - c++

The task of getting the PID of the process that I'm starting, CreateProcess() ProcessInformation.dwProcessId does a great job of this, but in my case, the process that I start opens the child processes and then closes, and I need to get all the PIDs that creates the process I am opening.
I found this code, it receives the child PIDs but they do not match the final Firefox window, what am I doing wrong
Source:
CreateProcess returns handle different than launched Chrome.exe
Update 1
After Drake Wu - MSFT comment, I used the following code
int test(const wchar_t* programPath) {
HANDLE Job = CreateJobObject(nullptr, nullptr);
if (!Job) {
std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
return 0;
}
HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
if (!IOPort) {
std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
return 0;
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;
if (!SetInformationJobObject(Job,
JobObjectAssociateCompletionPortInformation,
&Port, sizeof(Port))) {
std::cout << "SetInformation, error " << GetLastError() << std::endl;
return 0;
}
PROCESS_INFORMATION ProcessInformation;
STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
LPWSTR szCmdline = const_cast<LPWSTR>(programPath);
if (!CreateProcessW(
programPath,
nullptr,
nullptr,
nullptr,
FALSE,
CREATE_SUSPENDED,
nullptr,
nullptr,
&StartupInfo,
&ProcessInformation))
{
std::cout << "CreateProcess, error " << GetLastError() << std::endl;
return 0;
}
std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) {
std::cout << "Assign, error " << GetLastError() << std::endl;
return 0;
}
ResumeThread(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;
while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
{
switch (CompletionCode)
{
case JOB_OBJECT_MSG_NEW_PROCESS:
std::cout << "New PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_EXIT_PROCESS:
std::cout << "Exit PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
break;
default:
break;
}
if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
break;
}
std::cout << "All done" << std::endl;
}
and I got the following results:
standart Firefox
test(L"C:\\Program Files\\Mozilla Firefox\\firefox.exe");
portable edition Firefox
test(L"D:\\FirefoxPortable\\FirefoxPortable.exe");
As before, PIDs are incorrectly returned. In the case of the portable version, the process hangs on the while loop, in the case of the standard version of firefox, GetQueuedCompletionStatus() returns JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO. Why am I getting the wrong result?
Update 2
I ran Visual Studio as an administrator and, but on standard startup everything displays correctly

I tested that the process of Firefox is not new and exit in order(the pid obtained by CreateProcess will exit), and your code will not receive the new Firefox process if there is any new process created later.
You could use swtich-case statement, the following sample work for me:
int openProgram(const wchar_t* programPath) {
HANDLE Job = CreateJobObject(nullptr, nullptr);
if (!Job) {
std::cout << "CreateJobObject, error " << GetLastError() << std::endl;
return 0;
}
HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1);
if (!IOPort) {
std::cout << "CreateIoCompletionPort, error " << GetLastError() << std::endl;
return 0;
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;
if (!SetInformationJobObject(Job,
JobObjectAssociateCompletionPortInformation,
&Port, sizeof(Port))) {
std::cout << "SetInformation, error " << GetLastError() << std::endl;
return 0;
}
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
LPTSTR szCmdline = _tcsdup(programPath);
if (!CreateProcessW(
nullptr,
szCmdline,
nullptr,
nullptr,
FALSE,
CREATE_SUSPENDED,
nullptr,
nullptr,
&StartupInfo,
&ProcessInformation))
{
std::cout << "CreateProcess, error " << GetLastError() << std::endl;
return 0;
}
std::cout << "PID: " << ProcessInformation.dwProcessId << std::endl;
if (!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) {
std::cout << "Assign, error " << GetLastError() << std::endl;
return 0;
}
ResumeThread(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;
while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
{
switch (CompletionCode)
{
case JOB_OBJECT_MSG_NEW_PROCESS:
std::cout << "New PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_EXIT_PROCESS:
std::cout << "Exit PID: " << (int)Overlapped << std::endl;
break;
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
std::cout << "JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO" << std::endl;
break;
default:
break;
}
if (CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
break;
}
std::cout << "All done" << std::endl;
}
Result:

Related

ptrace - Input/Output Error (errno 5) on 32 bits only

I was trying to inject a shared library in another process and I managed to get it working on x64. Though, when I tried using it for 32bits, something weird is happening: ptrace is not being able to execute properly due to an Input/Output error (errno 5). I don't know what to do, since this same code worked for x64.
Then, I tried to make a smaller example using a function that I called test_ptrace. Surprisingly, the error doesn't happen there, though it is doing essentially the same thing (allocate memory on target process, inject a payload, set registers to match the payload, run the payload). When I saw the error was not happening, I tried again injecting the shared library with ptrace using a function called load_library. But unfortunately, there the error was again.
//this is the function that is NOT working, 'load_library'
void* load_library(pid_t pid, std::string path, int mode)
{
int status;
struct user_regs_struct old_regs, regs;
void* dlopen_ex = (void*)0xf7c29700; //I disabled ASLR, so this address does not change
void* handle_ex = (void*)-1;
unsigned char inj_buf[] =
{
0x51, //push ecx
0x53, //push ebx
0xFF, 0xD0, //call eax
0xCC, //int3 (SIGTRAP)
};
size_t path_size = path.size();
size_t inj_size = sizeof(inj_buf) + path_size;
void* inj_addr = allocate_memory(pid, inj_size, PROT_EXEC | PROT_READ | PROT_WRITE);
void* path_addr = (void*)((uintptr_t)inj_addr + sizeof(inj_buf));
write_memory(pid, inj_addr, (void*)inj_buf, sizeof(inj_buf));
write_memory(pid, path_addr, (void*)path.c_str(), path_size);
if(ptrace(PTRACE_ATTACH, pid, NULL, NULL))
{
perror("PTRACE_ATTACH");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
wait(&status);
if(ptrace(PTRACE_GETREGS, pid, NULL, &old_regs) == -1)
{
perror("PTRACE_GETREGS");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
regs.eax = (unsigned long)dlopen_ex;
regs.ebx = (unsigned long)path_addr;
regs.ecx = (unsigned long)mode;
regs.eip = (unsigned long)inj_addr;
if(ptrace(PTRACE_SETREGS, pid, NULL, &regs) == -1)
{
perror("PTRACE_SETREGS");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
if(ptrace(PTRACE_CONT, pid, NULL, NULL) == -1)
{
perror("PTRACE_CONT");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
waitpid(pid, &status, WSTOPPED);
if(ptrace(PTRACE_GETREGS, pid, NULL, &regs) == -1)
{
perror("PTRACE_GETREGS");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
handle_ex = (void*)old_regs.eax;
if(ptrace(PTRACE_SETREGS, pid, NULL, &old_regs) == -1)
{
perror("PTRACE_SETREGS");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
if(ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1)
{
perror("PTRACE_DETACH");
std::cout << "Errno: " << errno << std::endl;
return handle_ex;
}
deallocate_memory(pid, inj_addr, inj_size);
return handle_ex;
}
//this one, though, is working, but it is very similar to the function
//above (except it doesn't restore the execution, but the code of the
//other function doesn't even get there anyway.
void test_ptrace(pid_t pid)
{
int status;
struct user_regs_struct regs;
unsigned char inj_buf[] =
{
0xCD, 0x80, //int80 (syscall)
0xCC, //int3 (SIGTRAP)
};
void* inj_addr = allocate_memory(pid, sizeof(inj_buf), PROT_EXEC | PROT_READ | PROT_WRITE);
write_memory(pid, inj_addr, inj_buf, sizeof(inj_buf));
std::cout << "--ptrace test started--" << std::endl;
if(ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1)
{
perror("PTRACE_ATTACH");
std::cout << "Errno: " << errno << std::endl;
return;
}
wait(&status);
if(ptrace(PTRACE_GETREGS, pid, NULL, &regs) == -1)
{
perror("PTRACE_GETREGS");
std::cout << "Errno: " << errno << std::endl;
return;
}
regs.eax = __NR_exit;
regs.ebx = 222;
regs.eip = (unsigned long)inj_addr;
if(ptrace(PTRACE_SETREGS, pid, NULL, &regs) == -1)
{
perror("PTRACE_SETREGS");
std::cout << "Errno: " << errno << std::endl;
return;
}
if(ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1)
{
perror("PTRACE_DETACH");
std::cout << "Errno: " << errno << std::endl;
return;
}
std::cout << "--ptrace test ended--" << std::endl;
}
Program entry:
int main()
{
pid_t pid = get_process_id("target");
std::cout << "PID: " << pid << std::endl;
std::string lib_path = "<my_path>/ptrace-test/libtest.so";
load_library(pid, lib_path, RTLD_LAZY);
return 0;
}
Output:
PID: 2383
PTRACE_SETREGS: Input/output error
Errno: 5
If you need the whole project as a 'minimal' reproducible example, here you go: https://github.com/rdbo/ptrace-test
The PID is correct, I'm running as root, both the tracer and the tracee are compiled with G++ on 32 bits. Running up-to-date Manjaro. Any ideas?
I fixed it. Don't ask me how, though, I have no clue. I followed the exact same logic and out of sudden it worked. I used the working test_ptrace and kept putting the load_library code on it line by line to see what could be causing the problem. Turns out, I got it fixed and still don't know what it was. Anyways, here's the code (it is a bit messed up, because I didn't expect it to work):
void load_library(pid_t pid, std::string lib_path)
{
int status;
struct user_regs_struct old_regs, regs;
unsigned char inj_buf[] =
{
0x51, //push ecx
0x53, //push ebx
0xFF, 0xD0, //call eax
0xCC, //int3 (SIGTRAP)
};
size_t inj_size = sizeof(inj_buf) + lib_path.size();
void* inj_addr = allocate_memory(pid, inj_size, PROT_EXEC | PROT_READ | PROT_WRITE);
void* path_addr = (void*)((uintptr_t)inj_addr + sizeof(inj_buf));
write_memory(pid, inj_addr, inj_buf, sizeof(inj_buf));
write_memory(pid, path_addr, (void*)lib_path.c_str(), lib_path.size());
std::cout << "--ptrace test started--" << std::endl;
if(ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1)
{
perror("PTRACE_ATTACH");
std::cout << "Errno: " << errno << std::endl;
return;
}
wait(&status);
if(ptrace(PTRACE_GETREGS, pid, NULL, &old_regs) == -1)
{
perror("PTRACE_GETREGS");
std::cout << "Errno: " << errno << std::endl;
return;
}
regs = old_regs;
long dlopen_ex = 0xf7c28700;
regs.eax = dlopen_ex;
regs.ebx = (long)path_addr;
regs.ecx = RTLD_LAZY;
regs.eip = (unsigned long)inj_addr;
if(ptrace(PTRACE_SETREGS, pid, NULL, &regs) == -1)
{
perror("PTRACE_SETREGS");
std::cout << "Errno: " << errno << std::endl;
return;
}
ptrace(PTRACE_CONT, pid, NULL, NULL);
waitpid(pid, &status, WSTOPPED);
ptrace(PTRACE_SETREGS, pid, NULL, &old_regs);
if(ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1)
{
perror("PTRACE_DETACH");
std::cout << "Errno: " << errno << std::endl;
return;
}
deallocate_memory(pid, inj_addr, inj_size);
std::cout << "--ptrace test ended--" << std::endl;
}
Output:
PID: 24615
--ptrace test started--
--ptrace test ended--
Target Process:
PID: 24615
dlopen: 0xf7c28700
Waiting...
Injected!
Waiting...
Waiting...
Waiting...
Waiting...
EDIT:
I just remembered I ran the following command as root (could've been it, not sure though):
echo 0 > /proc/sys/kernel/yama/ptrace_scope
EDIT2: It was not it, the code is still working after a reboot. Also, I improved the code a bit on the GitHub repository.

ReadProcessMemory() Returning 0 ERROR_PARTIAL_COPY

#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;
DWORD GetModuleBase(LPSTR lpModuleName, DWORD dwProcessId)
{
MODULEENTRY32 lpModuleEntry = {0};
HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );
if(!hSnapShot)
return NULL;
lpModuleEntry.dwSize = sizeof(lpModuleEntry);
BOOL bModule = Module32First( hSnapShot, &lpModuleEntry );
while(bModule)
{
if(!strcmp( lpModuleEntry.szModule, lpModuleName ) )
{
CloseHandle( hSnapShot );
return (DWORDLONG)lpModuleEntry.modBaseAddr;
}
bModule = Module32Next( hSnapShot, &lpModuleEntry );
}
CloseHandle( hSnapShot );
return NULL;
}
int main() {
DWORD pID;
DWORDLONG off1, off2;
DWORDLONG baseAddress;
char moduleName[] = _T("AoE2DE_s.exe");
HWND hGameWindow;
HANDLE pHandle;
//Get Handles
hGameWindow = FindWindow(NULL, "Age of Empires II: Definitive Edition");
cout << "Game Window: " << hGameWindow << std::endl;
GetWindowThreadProcessId(hGameWindow, &pID);
cout << "Process ID: " << pID << std::endl;
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
cout << "Process Handle: " << std::hex << pHandle << std::endl;
//Get Client Base Addy
DWORDLONG clientBase = GetModuleBase(moduleName, pID);
cout << "Client Base: " << clientBase << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
DWORD lastError = GetLastError();
cout << "Error: " << lastError << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x18), &off1, sizeof(DWORDLONG), NULL);
cout << "After Offset 1: " << std::hex << off1 << std::endl;
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x9230), &off2, sizeof(DWORDLONG), NULL);
cout << "After Final Offset: " << off2 << std::endl;
cin.get();
}
The error occurs on this line:
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), NULL);
Application output for debugging purposes:
Game Window: 0x1307c2
Process ID: 11988
Process Handle: 0xec
Client Base: cc640000
Error: 12b
Base Address: 0
After Offset 1: 401519
After Final Offset: 8
Not sure how it is failing here, I'm somewhat new to this. Everything else goes through perfectly without error's but fails on the first ReadProcessMemory() if someone can help bring the solution for this to light I would be grateful.
ReadProcessMemory is defined like this:
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesRead
);
If it returns zero then there has been an error, and only in that case GetLastError will return a meaningfull error number.
So correct usage would be:
SIZE_T readBytes;
if (!ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x2BFCA18), &baseAddress, sizeof(DWORDLONG), &readBytes)) {
DWORD lastError = GetLastError();
cout << "ReadProcessMemory failed: Error: " << lastError << " read " << readBytes << std::endl;
}
else
{
cout << "ReadProcessMemory succeeded"; << std::endl;
cout << "Base Address: " << std::hex << baseAddress << std::endl;
}

WriteProcessMemory not working for some reason

This is all the source code for a program i'm trying to make, and I can't get WriteProcessMemory to work at all. It returns the correct messages, saying that everything went successfully, but nothing actually changes in the game. Does anyone know of a fix?
#include <iostream>
#include <Windows.h>
using namespace std;
// variables
int plcHold = 1;
string hlthLoop = "OFF";
string ammoLoop = "OFF";
DWORD pid;
DWORD playerAddr;
DWORD hlthOffs = 0xF8;
// main function
int main()
{
// finding pid, opening proc, finding player address
HWND hwnd = FindWindowA(NULL, "AssaultCube");
if(hwnd == NULL)
{
cout << "Error; Couldn't find window" << endl;
} else{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(pHandle == NULL)
{
cout << "Error; Couldn't open process" << endl;
} else{
ReadProcessMemory(pHandle, (LPCVOID)0x50F4F4, &playerAddr, sizeof(playerAddr), 0);
if(ReadProcessMemory != FALSE)
{
cout << "Health successfully read!" << endl;
} else{
cout << "Error code " << GetLastError << endl;
}
}
while(plcHold == 1){
cout << "========== *****'s Assault Cube Trainer ==========\n" << endl;
cout << "=============== Health Loop - " << hlthLoop << " ================" << endl;
Sleep(1500);
system("cls");
if(GetAsyncKeyState(0x5A))
{
cout << "Health successfully edited!" << endl;
WriteProcessMemory(pHandle, LPVOID(playerAddr + hlthOffs), 0, sizeof(999), 0);
CloseHandle(pHandle);
}
}
}
return 0;
}
You're passing a null pointer to WriteProcessMemory for the third (lpBuffer) parameter. You have to pass the address of the actual value, not the value itself. If you want to write an integer value, try this:
DWORD val = 0; // or 999?
WriteProcessMemory(
pHandle, static_cast<LPVOID>(playerAddr + hlthOffs),
&val, sizeof(val), 0);

System.NullReferenceException object reference not set to an instance

I'm a beginner with C++. In my code, I am trying to get a list of the updates installed on the machine.
In my machine 1, I'm using Windows 7, and the code work perfectly. But in machine 2, using Windows 7 too, I get the error.
I don't understand enough to know what actually needs fixing, or how to fix it.
My program stops working with the below code, and displays this error:
unhandled exception system.NullReferenceException object reference not set to an instance
try
{
HRESULT hr;
hr = CoInitialize(NULL);
IUpdateSession* iUpdate;
IUpdateSearcher* searcher;
ISearchResult* results;
BSTR criteria = SysAllocString(L"IsInstalled=0 or IsHidden=1 or IsPresent=1");
hr = CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&iUpdate);
hr = iUpdate->CreateUpdateSearcher(&searcher);
//wcout << L"Searching for updates ..." << endl;
hr = searcher->Search(criteria, &results);
SysFreeString(criteria);
switch (hr)
{
case S_OK:
//wcout << L"List of applicable items on the machine:" << endl;
break;
case WU_E_LEGACYSERVER:
wcout << L"No server selection enabled" << endl;
case WU_E_INVALID_CRITERIA:
wcout << L"Invalid search criteria" << endl;
}
IUpdateCollection *updateList;
IUpdate *updateItem;
LONG updateSize = 0;
LONG totalKB = 0;
results->get_Updates(&updateList);
updateList->get_Count(&updateSize);
if (updateSize == 0)
{
//wcout << L"No updates found" << endl;
}
for (LONG i = 0; i < updateSize; i++)
{
IStringCollection *KBCollection;
BSTR updateName;
LONG KBCount;
updateList->get_Item(i, &updateItem);
updateItem->get_Title(&updateName);
USES_CONVERSION;
//outputFile << W2A(CString(updateName)) << " --- ";
updateItem->get_KBArticleIDs(&KBCollection);
KBCollection->get_Count(&KBCount);
for (int i = 0; i<KBCount; i++)
{
BSTR KBValue;
totalKB += 1;
KBCollection->get_Item(i, &KBValue);
USES_CONVERSION;
//std::string strk = streamkb.str();
file << "{" << endl;
std::stringstream ss;
ss << W2A(CString("KB")) << W2A(CString(KBValue));
std::string s = ss.str();
list2.push_back(s);
file << "\"Correctif" << totalKB << "\": \"" << W2A(CString("KB")) << W2A(CString(KBValue)) << "\"" << endl;
file << "}," << endl;
}
}
::CoUninitialize();
}
catch (const std::exception & ex)
{
}

GetProcessId failed with error 6: The handle is invalid

I posted a little earlier with a sendmessage issue and we came to the conclusion that it would be extremely hard to get the chat window from Xchat. I have now moved to ThrashIRC and using spy++ was able to find the chat window(highlighted):
As you can see it does have a caption which means that it does see the text. Here is the code that I am using to get the HWND's and the text:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
#include <strsafe.h>
using namespace std;
void FindThrash()
{
cout << "[ThrashIRC]" << endl;
cout << "| find ThrashIRC window" << endl;
HWND hwndThrashIRC = FindWindow(L"ThrashIRC", NULL);
if (NULL != hwndThrashIRC)
{
cout << " + found ThrashIRC window" << endl;
cout << "| find MDIClient window" << endl;
HWND hwndMDIClient = FindWindowEx(hwndThrashIRC, NULL, L"MDIClient", NULL);
if (NULL != hwndMDIClient)
{
cout << " + found MDIClient window" << endl;
cout << "| find DefChannel window" << endl;
HWND hwndDefChannel = FindWindowEx(hwndMDIClient, NULL, L"DefChannel", NULL);
if (NULL != hwndDefChannel)
{
cout << " + found MDIClient window" << endl;
cout << "| find RichEdit20W window" << endl;
HWND hwndRichEdit20W = FindWindowEx(hwndDefChannel, NULL, L"RichEdit20W", NULL);
if (NULL != hwndRichEdit20W)
{
cout << " + found RichEdit20W window" << endl << endl;
cout << "- get text " << endl;
const int bufferSize = 32768;
char textBuffer[bufferSize] = "";
SendMessage(hwndRichEdit20W, WM_GETTEXT, (WPARAM)bufferSize, (LPARAM)textBuffer);
cout << "[begin text]" << endl;
cout << textBuffer << endl;
cout << "[end text]" << endl;
}
else
{
cerr << "RichEdit20W not found." << endl;
}
}
else
{
cerr << "DefChannel not found." << endl;
}
}
else
{
cerr << "MDIClient not found." << endl;
}
}
else
{
cerr << "ThrashIRC not open." << endl;
}
}
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
int main()
{
FindThrash();
if (!GetProcessId(NULL))
ErrorExit(TEXT("GetProcessId"));
return 0;
}
The buffer is only that large because 1: I thought it might have been an error where the buffer was to small, and 2: the buffer is going to have to be large because of the amount of text. Any suggestions / code would be greatly appreciated! Thanks!
GetProcessID expects to be passed a valid process handle, as is clearly stated in the MSDN documentation. You're calling it with NULL as the argument:
if (!GetProcessId(NULL))
Why would you expect it to return anything but an invalid handle error when you're clearly providing it an invalid process handle?
Just to make sure you're aware, an HWND is a window handle, not a process handle. FindWindow and FindWindowEx return a window handle.