here is code.
char* getURL() {
char* urlstr;
if FAILED(CoInitialize(nullptr))
cout << "something error..." << endl;
struct coinit { ~coinit() { CoUninitialize(); } } cleanup;
//find the first visible window in firefox
HWND hwnd = NULL;
while (true)
{
hwnd = FindWindowEx(0, hwnd, (LPCSTR)"MozillaWindowClass", NULL);
if (!hwnd)
return 0;
if (IsWindowVisible(hwnd))
break;
}
//initialize UIAutomation
CComPtr<IUIAutomation> uia;
if FAILED(uia.CoCreateInstance(CLSID_CUIAutomation))
cout << "something error." << endl;
CComPtr<IUIAutomationElement> root, navigation, editbox;
CComPtr<IUIAutomationCondition> c1, c2;
//find root from hwnd handle
if FAILED(uia->ElementFromHandle(hwnd, &root))
cout << "something error." << endl;
//find navigation bar as child of root
uia->CreatePropertyCondition(UIA_AutomationIdPropertyId,
CComVariant(L"nav-bar"), &c1);
if FAILED(root->FindFirst(TreeScope_Children, c1, &navigation))
cout << "something error." << endl;
//find editbox under as descendant of navigation
uia->CreatePropertyCondition(UIA_AutomationIdPropertyId,
CComVariant(L"urlbar-input"), &c2);
if FAILED(navigation->FindFirst(TreeScope_Descendants, c2, &editbox))
cout << "something error." << endl;
//get the string in editbox
CComVariant url;
if FAILED(editbox->GetCurrentPropertyValue(UIA_ValueValuePropertyId, &url))
cout << "something error." << endl;
//if (url.bstrVal) {
// wprintf(L"[%s]\n", url.bstrVal);
//}
if (url.bstrVal == NULL) urlstr = (char*)"None";
else urlstr = _com_util::ConvertBSTRToString(url.bstrVal);
return urlstr;
i wanna get url from firefox tab.
I tried __try, but Cannot use __try in functions that require object unwinding.
I do not know where the error is coming from.
Can anyone tell me how I can prevent this error?
environments: Windows11, Visual Studio 2019
When I changed the library to not throw exceptions, I found that I was getting an error here.
if FAILED(navigation->FindFirst(TreeScope_Descendants, c2, &editbox))
This debugging error might happen when you pass a smart pointer (CComPtr) to COM like so:
CComPtr<IUIAutomationElement> root, navigation, editbox;
CComPtr<IUIAutomationCondition> c1, c2;
// Find root from hwnd handle
if (FAILED(uia->ElementFromHandle(hwnd, &root))) // Here, we pass an IUIAutomationElement as input.
cout << "Something Error." << endl;
When you pass a CComPtr as an input, you must release that smart pointer before using it again like so:
root.Release();
Not only for that smart pointer, but for any smart pointer you pass as an input you should release it before using again.
See this MSDN link: Debug Assertion Error when debugging CComPtr
Learn more about CComPtr and smart pointers here: COM Coding Practices
Related
I am trying to change the value of minerals in Starcraft II to learn win32.
I am not into gaming at all. but chose my childhood game to leearn win32 and operating systems.
Here is my code.
everything works, I can get the handle and its process id.
however reading the value does not work.
From cheat engine, I can change the value of minerals to whatever I like.
Here is the memory address of the minerals.
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
int newMineral = 2000;
int readMineral = 0;
HWND hwnd = FindWindowA(NULL, "Brood War");
if (hwnd == NULL)
{
cout << "Cannot find window." << endl;
Sleep(30000);
exit(-1);
}
else
{
DWORD procID;
GetWindowThreadProcessId(hwnd, &procID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
if (procID == NULL)
{
cout << "Cannot find procssID." << endl;
Sleep(30000);
exit(-1);
}
else
{
cout << "process exists." << endl;
cout << procID << endl;
//WriteProcessMemory(handle, (LPVOID)0x57F0F0, &newMineral, sizeof(newMineral), 0);
ReadProcessMemory(handle, (PBYTE*)0x57F0F0, &readMineral, sizeof(int), 0);
cout << readMineral << endl;
}
}
return 0;
I think it is the format of my memory address maybe since the handle and processID are obtainable.
I have a problem with opening clipboard multiple times. It opens up fine on the first call, however, my program needs to access the clipboard several times, but shuts down on the second call of OpenClipboard(NULL) with the CLIPBRD_E_CANT_OPEN error).
This is a function that opens the clipboard
void Translator::process_copied()
{
//cout << "processing" << endl;
if (OpenClipboard(NULL))
{
HANDLE clip;
clip = GetClipboardData(CF_UNICODETEXT);
Relayout((WCHAR*)clip);
HANDLE res = GlobalAlloc(GMEM_FIXED, sizeof(WCHAR)*wcslen((WCHAR*)clip)+1);
res = clip;
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, res);
CloseClipboard();
}
else
{
std::cout << GetLastError();
//throw clipboard_did_not_open;
//cout << "error in opening clipboard" << endl;
}
}
I suspect that the problem appears in the SetClipboardData() function, because if I remove it, clipboard doesn't have any problem opening multiple times. The same goes to res = clip; line.
I am new to WinAPI and C++ in general, so I apologize if my question is silly.
When storing a memory block on the clipboard, the HANDLE given to SetClipboardData() must be allocated with the GMEM_MOVEABLE flag, per the SetClipboardData() documentation:
If the hMem parameter identifies a memory object, the object must have been allocated using the [GlobalAlloc] function with the GMEM_MOVEABLE flag.
As such, you must call GlobalLock() on the HANDLE returned by GetClipboardData() in order to access the data, per the GlobalAlloc() documentation:
GMEM_MOVEABLE
0x0002
Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap.
The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function.
Don't just type-cast the HANDLE as-is, like you can for a memory object allocated with the GMEM_FIXED flag.
You are also not putting any character data in the res memory that you allocate with GlobalAlloc(). Which is moot, since you are not putting your allocated memory on the clipboard at all, you are actually putting the original HANDLE from GetClipboardData() back onto the Clipboard, and then leaking your res memory.
Try something more like this instead:
void Translator::process_copied()
{
//cout << "processing" << endl;
HWND hwnd = ...; // a window that YOU own
if (OpenClipboard(hwnd))
{
HANDLE clip = GetClipboardData(CF_UNICODETEXT);
if (clip)
{
WCHAR *text = (WCHAR*) GlobalLock(clip);
Relayout(text);
HANDLE res = GlobalAlloc(GMEM_MOVABLE, (wcslen(text)+1) * sizeof(WCHAR));
if (res)
{
WCHAR *newText = (WCHAR*) GlobalLock(res);
// put characters in newText as needed...
wcscpy(newText, text);
GlobalUnlock(res);
GlobalUnlock(clip);
EmptyClipboard();
if (!SetClipboardData(CF_UNICODETEXT, res))
{
std::cout << GetLastError();
GlobalFree(res);
//throw clipboard_did_not_set;
//cout << "error in setting clipboard data" << endl;
}
}
else
{
std::cout << GetLastError();
//throw global_memory_not_allocated;
//cout << "error in allocating memory" << endl;
GlobalUnlock(clip);
}
}
else
{
std::cout << GetLastError();
//throw clipboard_data_not_get;
//cout << "error in getting clipboard data" << endl;
}
CloseClipboard();
}
else
{
std::cout << GetLastError();
//throw clipboard_did_not_open;
//cout << "error in opening clipboard" << endl;
}
}
I'm Korean student.
Now this is my first question after signing up.
DWORD getProcessId() {
PROCESSENTRY32 process_infor;
process_infor.dwSize = sizeof(PROCESSENTRY32);
HANDLE snap_handle = CreateToolhelp32Snapshot(
TH32CS_SNAPALL, //스냅 단계
NULL //스냅할 pid
);
if (snap_handle != INVALID_HANDLE_VALUE) {
Process32First(snap_handle, &process_infor);
do {
wchar_t* temp = process_infor.szExeFile;
wstring ws(temp);
string name(ws.begin(), ws.end());
if (name == "notepad.exe") {
cout << name << " : " << process_infor.th32ProcessID << endl;
return process_infor.th32ProcessID;
}
} while (Process32Next(snap_handle, &process_infor));
}
CloseHandle(snap_handle);
return FALSE;
}
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
func = (HOOKPROC) GetProcAddress(dll_handle, "injectSuccess");
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
getProcessId()
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
FreeLibrary(dll_handle);
return FALSE;
}
There seems to be a problem with SetWindowsHookEx of the inject function in this case. The dll file loads well, and the injectSuccess function inside is well fetched. (I tried running it, but it worked)
And I wondered if the argument values of SetWindowsHookEx were entered incorrectly, so I compared them and checked them continuously, but I couldn't find any difference. So, I tried GetLastError() with the return value of SetWindowsHookEx below, but the return value is 0 and the error code is 87 ("the parameter is incorrect").
So I searched, but I can't speak English well and I'm a beginner, so I'm not sure.
According to the SetWindowsHookExW:
dwThreadId
A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
So what SetWindowsHookExW needs is the thread ID, and you pass in the process ID of notepad.exe, so the parameter is wrong.
I creat a sample and test the following code:
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
if (dll_handle) func = (HOOKPROC)GetProcAddress(dll_handle, "injectSuccess");
else return FALSE;
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
HWND h = FindWindow(L"notepad", NULL);
DWORD pid;
threadID = GetWindowThreadProcessId(h, NULL);
cout << "threadID = " << threadID << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
threadID
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
if(dll_handle) FreeLibrary(dll_handle);
return FALSE;
}
This example worked for me, and you can see the difference between pid and threadID:
Edit
According to the document:
An application installs the hook procedure by specifying the
WH_KEYBOARD hook type and a pointer to the hook procedure in a call to
the SetWindowsHookEx function. This hook may be called in the context
of the thread that installed it. The call is made by sending a message
to the thread that installed the hook. Therefore, the thread that
installed the hook must have a message loop. So if you want to run
this func, you need to add a message loop.
You can refer to the following code:
int main()
{
inject();
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
When you press the button, the message box will pop up:
Because there are two messages for each key press and release, func is triggered twice each time.If you only want to trigger every time a button is pressed, you can modify the following code:
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}
You can refer to KeyboardProc to view the messages for each value in lParam.
So I would like to use the DLL that I created, and I have this really weird warning I didn't see anyone has this one. I checked if LoadLibray returns "NULL", and this is not the case.
typedef DATA_BLOB(*encryption_decryption)(DATA_BLOB, bool*);
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if (dll_file != NULL) {
cout << "Library loaded!" << endl;
}
else {
failed();
}
encryption_decryption encryption = (encryption_decryption)GetProcAddress(dll_file,"encryption");
if(encryption != NULL)
{
cout << "Workded!" << endl;
}
else
{
failed();
}
void failed() {
cout << GetLastError() << endl;
cout << "Faild!" << endl;
}
Warning at the 8th line: "'dll_file' could be '0': this does not adhere to the specification for the function 'GetProcAddress'."
Everything works, it doesn't write any errors when I run it.
If anything goes wrong in LoadLibrary you call failed() that prints the error code and returns.
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if (dll_file != NULL) {
cout << "Library loaded!" << endl;
}
else {
failed(); // returns even when dll_file is NULL
}
// so, here you don't know if it's NULL or a valid handle which is why you get the warning
encryption_decryption encryption = (encryption_decryption)GetProcAddress(dll_file,"encryption");
If LoadLibrary fails, you shold not use that dll_file to call GetProcAddress.
encryption_decryption encryption = nullptr;
HINSTANCE dll_file = LoadLibrary(L"dllForEncryptionNDecryptionn.dll");
if(dll_file) {
encryption_decryption encryption =
(encryption_decryption)GetProcAddress(dll_file,"encryption");
} else {
// do NOT call GetProcAddress
}
if(encryption) {
// function successfully loaded
}
I have two Libraries: IDA and XIDA.
XIDA handles the event loop, and there is for each application/process, one single event loop.
And these libraries are "connected" via an callback function.
This is working with events inside one single app/process...
Now I noticed that I could send an event from one app to an other. What it needs was a window handle from another app. So I coded a DBus message, with what I can receive one...
This is working too, but it looks like that the receiver of XSendEvent() can only use functions and its parameters, no member variables!
In the hpp:
Window mSection;
Window Section(){
return 0; // This is working
}
Window Section_A(){
return this->mSection; // This raises a memory access error
}
int CheckEvents( IDA_A *vIDA_A, XEvent vEvent);
static int Section_EventCallback(void* this_ptr, XEvent vEvent){
IDA_A* nIDA_A = NULL;
int nRet = 1;
try{
nIDA_A = static_cast < IDA_A* > (this_ptr);
} catch (...) { return 0; }
cout << "TEST " << nIDA_A->Section() << endl; // This is working, also with any other function
cout << "TEST " << nIDA_A->mSection << endl; // This raises a memory access error, also with any other member variable
cout << "TEST " << nIDA_A->Section_A() << endl; // This also raises a memory access error
nRet = nIDA_A->CheckEvents(nIDA_A, vEvent);
nIDA_A = NULL;
return nRet;
}
In the cpp:
int IDA_A::CheckEvents(IDA_A *vIDA_A, XEvent vEvent) {
Window nWindow = vEvent.xany.window;
cout << "TEST " << " -- " << nWindow << endl; // This is working
cout << "TEST " << " -- " << this->mSection << endl; // This raises a memory access error
return 1;
}
What does it needs to use also member variables?
Regards
Earlybite
------------------------ EDIT: ----------------------------
This is the part of XIDA where XSendEvents() arrives (after calling from inside the event loop):
int XIDA_A::Send_To_Callback(XEvent vEvent){
for(int i = 0; i < (int) this->mVecEvCallback.size(); i++){
if( *this->mVecEvCallback[i].pWindow == vEvent.xany.window ){
if( vEvent.type == ClientMessage ) {
cout << "THIS XIDA CLIENT " << this->mIdent << endl;
}
s_EventCallback nEvCallback;
nEvCallback = this->mVecEvCallback[i];
nEvCallback.Callback (nEvCallback.this_Ptr, vEvent);
return 1;
}
}
return 0;
}
And to this point, it is working, also member variables. But nevermore in IDA, where the Callback is going to.
But it is the same process!
And e.g. with DBus it is working...
I really would like to know the reason!
SOLVED.
I found the error...
This
cIDAMessage nMsg;
nMsg.Msg_Type = IDAMsg_EventCallback;
nMsg.Lng_Send[0] = 0;
nMsg.Para_Void[0] = (void*) &this->mSection;
nMsg.Para_ThisPtr = (void*) this;
nMsg.Para_CallbackPtr = (void*) &this->Section_EventCallback;
this->XIDA_Callback(this->mXIDA_A_Ptr, &nMsg);
is a part of the init.
And I had forgotten to set
nMsg.Para_ThisPtr = (void*) this;
But what I still do not understand...
static int Section_EventCallback(void* this_ptr, XEvent vEvent){
IDA_A* nIDA_A = NULL;
int nRet = 1;
try{
nIDA_A = static_cast < IDA_A* > (this_ptr);
} catch (...) { return 0; }
nRet = nIDA_A->CheckEvents(nIDA_A, vEvent);
nIDA_A = NULL;
return nRet;
}
Here comes/came the pointer with NULL.
Why wasn't nIDA_A not NULL, or why wasn't there raised an error, because static_cast cannot cast with NULL?
And why were functions working, but not member variables?
You know what I mean?