i just wanted to make sure i don't lose my mind here. I wanted to build a simple Direct3D 11 application and had a basic window running. I now wanted to add some actual rendering but unfortunately my compiler won't recognize the DXGI_FORMAT enum type from dxgiformat.h. I tried many thinks of one was to literally copy the content of the header manually but no luck. Also i checked the output of the preprocessor and confirmed that gcc actually draws its resources from the right places and that the content of the header was in there correctly. Furthermore this is the only dxgiformat.h header on this machine. I'm aware of the unused variable since this is what i was going to use before this problem occured. I now just wanted to be save this is not a user problem before trying to report any bugs. As i stated i'm using the MinGW-w64 toolchain from the installer. These are my Error messages:
$ make
[BUILD] D3D11App.o
In file included from D3D11App.cpp:4:
D3D11App.hpp:11:2: error: 'DXGI_FORMAT_R32G32B32_FLOAT' does not name a type
DXGI_FORMAT_R32G32B32_FLOAT position;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
D3D11App.hpp:12:2: error: 'DXGI_FORMAT_R8G8B8_UNORM' does not name a type; did you mean 'DXGI_FORMAT_R8G8_UNORM'?
DXGI_FORMAT_R8G8B8_UNORM color;
^~~~~~~~~~~~~~~~~~~~~~~~
DXGI_FORMAT_R8G8_UNORM
D3D11App.cpp: In constructor 'D3D11App::D3D11App(HWND)':
D3D11App.cpp:103:20: warning: unused variable 'bufferDesc' [-Wunused-variable]
D3D11_BUFFER_DESC bufferDesc = {
^~~~~~~~~~
make: *** [makefile:15: D3D11App.o] Fehler 1
and my code:
main.cpp
#include <iostream>
#include <d3d11.h>
#include <windows.h>
#include <windowsx.h>
#include "D3D11App.hpp"
using namespace std;
HWND init(HINSTANCE hInstance, const int x, const int y, const int w, const int h);
LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
D3D11App *d3d11;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow) {
cout << "Reslution: " << GetSystemMetrics(SM_CXSCREEN) << "x" << GetSystemMetrics(SM_CYSCREEN) << endl;
HWND window = init(hInstance, 0, 0, 800, 600);
if (window == NULL) {
cout << "Error while initializing: " << GetLastError() << endl;
return GetLastError();
}
d3d11 = new D3D11App(window);
ShowWindow(window, cmdShow);
UpdateWindow(window);
MSG msg;
while (msg.message != WM_QUIT) {
if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
d3d11->render();
}
}
return 0;
}
HWND init(HINSTANCE hInstance, const int x, const int y, const int w, const int h) {
WNDCLASSEX windowClass = {
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW,
windowProc,
0,
0,
hInstance,
NULL,
NULL,
(HBRUSH)COLOR_WINDOW,
"Window",
"windowClass",
NULL
};
if(RegisterClassEx(&windowClass) == 0) {
cout << "Error while registering class: " << GetLastError() << endl;
return NULL;
}
return CreateWindowEx (
WS_EX_TOPMOST,
"windowClass",
"D3D11",
WS_POPUP,
x, y,
w, h,
NULL,
NULL,
hInstance,
NULL
);
}
LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
switch(wParam) {
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
}
case WM_MOUSEMOVE:
cout << "x :" << GET_X_LPARAM(lParam) << ", y: " << GET_Y_LPARAM(lParam) << endl;
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
D3DApp11.hpp
#ifndef D3D11APP_HPP
#define D3D11APP_HPP
#include <d3d11.h>
#include <dxgiformat.h>
#include <vector>
struct customVertex {
DXGI_FORMAT_R32G32B32_FLOAT position;
DXGI_FORMAT_R8G8B8_UNORM color;
};
class D3D11App {
ID3D11Device *device;
ID3D11DeviceContext *devcon;
IDXGISwapChain *swapChain;
ID3D11RenderTargetView *backbuffer;
ID3D11Buffer *vertexBuffer;
public:
D3D11App(HWND hWnd);
~D3D11App();
void render();
};
#endif /* D3D11APP_HPP */
D3D11App.cpp
#include <iostream>
#include <dxgiformat.h>
#include <memory>
#include "D3D11App.hpp"
using namespace std;
D3D11App::D3D11App(HWND hWnd) {
HRESULT status;
WINDOWINFO windowInfo;
IDXGIAdapter * pAdapter;
IDXGIFactory * pFactory;
status = CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pFactory));
for(int i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) {
DXGI_ADAPTER_DESC adapterDesc;
pAdapter->GetDesc(&adapterDesc);
cout << "Video Adapter " << i << ":" << endl
<< "Description: " << adapterDesc.Description << endl
<< "VendorId: 0x" << hex << adapterDesc.VendorId << endl
<< "DeviceID: 0x" << adapterDesc.DeviceId << endl
<< "SubSysId: 0x" << adapterDesc.SubSysId << endl
<< "Revision: " << adapterDesc.Revision << endl
<< dec << endl;
}
if(status != S_OK) {
cout << "Error while creating factory Error(0x" << hex << status << dec << ")" << endl;
}
if( ! GetWindowInfo(hWnd, &windowInfo) ) {
cout << "Error while retreiving window informattion" << endl;
}
cout << "client width: " << windowInfo.rcClient.right << " client height: " << windowInfo.rcClient.bottom << endl;
DXGI_SWAP_CHAIN_DESC scd = {
/* BufferDesc */
{
static_cast<UINT>(windowInfo.rcClient.right),
static_cast<UINT>(windowInfo.rcClient.bottom),
60,
DXGI_MODE_SCALING_UNSPECIFIED,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE
},
/* SampleDesc */
{
8,
0
},
DXGI_USAGE_RENDER_TARGET_OUTPUT,
1,
hWnd,
true,
DXGI_SWAP_EFFECT_DISCARD
};
status = D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_SINGLETHREADED,
NULL,
0,
D3D11_SDK_VERSION,
&scd,
&(this->swapChain),
&(this->device),
NULL,
&(this->devcon)
);
if(status != S_OK) {
cout << "Error while creating device and swap chain Error(0x" << hex << status << dec << ")" << endl;
return;
}
ID3D11Texture2D *pBackBuffer;
status = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
if (status != S_OK) {
cout << "Error while getting backbuffer adress Error(0x" << hex << status << dec << ")" << endl;
return;
}
status = device->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
if (status != S_OK) {
cout << "Error while creating render target view Error(0x" << hex << status << dec << ")" << endl;
return;
}
pBackBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
D3D11_VIEWPORT viewPort;
ZeroMemory(&viewPort, sizeof(D3D11_VIEWPORT));
viewPort.TopLeftX = (FLOAT)0.0;
viewPort.TopLeftY = (FLOAT)0.0;
viewPort.Width = static_cast<FLOAT>(windowInfo.rcClient.right);
viewPort.Height = static_cast<FLOAT>(windowInfo.rcClient.bottom);
devcon->RSSetViewports(1, &viewPort);
D3D11_BUFFER_DESC bufferDesc = {
3 * sizeof(customVertex),
D3D11_USAGE_DYNAMIC,
D3D11_BIND_VERTEX_BUFFER,
D3D11_CPU_ACCESS_WRITE,
0,
sizeof(customVertex)
};
}
D3D11App::~D3D11App() {
this->swapChain->Release();
this->backbuffer->Release();
this->device->Release();
this->devcon->Release();
}
void D3D11App::render() {
devcon->ClearRenderTargetView(backbuffer, (const FLOAT[]){0.0,0.2,0.5,1.0});
if(swapChain->Present(0, 0) != S_OK) {
cout << "Error while presenting" << endl;
}
}
DXGI_FORMAT_R32G32B32_FLOAT is an enum that describes a particular memory layout, but is not itself a C++ structure you can declare in your vertex type.
You can use float position[3], but many DirectX C++ programs use the various DirectXMath types such as DirectX::XMFLOAT3 position;. There's a fairly complete list of equivalents here.
Related
I decided to create my own dll injector but the problem is that almost when I finished my code a problem occurs, in the following code my dll does not inject correctly, I tried everything like checking if my dll was good or even my code in general but nothing works. (I want to specify that for my processId if I use GetCurrentProcessId() my dll is injected correctly but not where I want so it is imperative for me to use GetProcessIdByName.) Thank you to all those who will help me!
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <string>
#include <iostream>
using namespace std;
DWORD GetProcessIdByName(const char* processName)
{
DWORD processId = 0;
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(snap, &pe))
{
do
{
if (!_stricmp(pe.szExeFile, processName))
{
processId = pe.th32ProcessID;
break;
}
} while (Process32Next(snap, &pe));
}
CloseHandle(snap);
}
return processId;
}
int main()
{
const char* processName = "OLLYDBG.exe";
DWORD processId = GetProcessIdByName(processName);
LPCSTR dllPath = "C:\\Users\\Alban\\source\\repos\\Cheat\\Cheat\\testdll.dll";
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL)
{
cout << "Error with 'OpenProcess', error code : " << GetLastError() << endl;
return 1;
}
cout << "process id : " << processId << endl;
LPVOID pdllPath = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pdllPath == NULL)
{
cout << "failed to allocate dll path, error code : " << GetLastError() << endl;
return 1;
}
cout << "path to memory : " << hex << pdllPath << endl;
BOOL writedMemory = WriteProcessMemory(hProcess, pdllPath, LPVOID(dllPath), strlen(dllPath) + 1, NULL);
if (writedMemory == 0)
{
cout << "failed to write memory, error code : " << GetLastError() << endl;
return 1;
}
HANDLE hloadThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "LoadLibraryA"), pdllPath, 0, NULL);
if (hloadThread == NULL)
{
cout << "Can not create remote thread, error code : " << GetLastError() << endl;
return 1;
}
WaitForSingleObject(hloadThread, INFINITE);
BOOL virtualFree = VirtualFreeEx(hProcess, pdllPath, 0, MEM_RELEASE);
if (virtualFree == 0)
{
cout << "Can not release memory, error code : " << GetLastError() << endl;
}
CloseHandle(hProcess);
}
I want to get messages when a window is moving.
I started to write a simple c++ console application that hooks into the default notepad application of windows.
One part of it contains the following code to set the hook (not all three, only one)
_hook = SetWindowsHookEx(WH_MOUSE, CallWndProc, _dllInstance, tid); //WORKS
_hook = SetWindowsHookEx(WH_KEYBOARD, CallWndProc, _dllInstance, tid); //WORKS
_hook = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, _dllInstance, tid); //DOESNT WORK
So basically the procedure of the hooking is the same and every hook type works with the same callback function.
Why does it not work with the WH_CALLWNDPROC?
When applying WH_CALLWNDPROC the hook is successful like the others but it simply doesn't work.
This is the callback function
// The callback function
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
std::cout << "callback " << counter++ << "\n";
//This is a must
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
But CallWndProc is never called when setting this hook.
I even tried to call the CallWndProc function inside of the DLL but this also didn't work so I removed it entirely from the DLL and now it's an empty DLL. Even if it worked, it would be of no use to me because I need to handle the messages in my application not on the target thread.
Any Tips? Here is the full code
#include "Main.h"
#include <Windows.h>
#include <iostream>
/* Variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
or you will get problems since every function uses this variable. */
HHOOK _hook;
// the dll instance
HINSTANCE _dllInstance;
//HOOKPROC _dllCallback;
int counter = 0;
// The callback function
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
std::cout << "callback " << counter++ << "\n";
//This is a must
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
// This functions installs a hook to a window with given title
int InstallHook(const wchar_t* title) {
/* 1. Get window handle of given title */
std::wcout << "INFO: Getting window handle for \"" << title << "\"...\n";
HWND hwnd = FindWindow(NULL, title);
if (hwnd == NULL) {
std::cout << "ERROR: Could not find target window.\n";
return -1;
}
/* 2. Get ThreadID (TID) of the window handle */
std::wcout << "INFO: Getting TheadID (TID) of \"" << title << "\"...\n";
DWORD pid = NULL; // If we dont know -> NULL
DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
if (tid == NULL) {
std::cout << "ERROR: Could not find target window.\n";
return -2;
}
/* 3. Load in the DLL */
std::wcout << "INFO: Loading the DLL\n";
_dllInstance = LoadLibrary(TEXT("winhooks_dll.dll"));
if (_dllInstance == NULL) {
std::cout << "ERROR: Could not load DLL...\n";
return -3;
}
/* 3.5 Get Callback function from dll*/
//_dllCallback = (HOOKPROC)GetProcAddress(_dllInstance, "_wmProcCallback#12");
//if (_dllCallback == NULL) {
// std::cout << "ERROR: Could not get Callback function from dll instance\n";
// return -4;
//}
/* 4. Install the hook and set the handle */
std::wcout << "INFO: Setting the hook...\n";
_hook = SetWindowsHookEx(WH_MOUSE, CallWndProc, _dllInstance, tid); // The local callback version
//_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, _dllCallback, _dllInstance, tid); // The dll callback function
if (_dllInstance == NULL) {
std::cout << "ERROR: Could not set hook handle\n";
return -5;
}
return 0;
}
int main() {
const wchar_t* title = L"Untitled - Notepad";
if (InstallHook(title) != 0) {
std::wcout << "ERROR: Could not install hook on " << title << " last error -> " << GetLastError() << "\n";
system("pause");
return 1;
}
std::wcout << "SUCCESS: Hook is successfully installed on " << title << "\n";
std::wcout << "Running message loop..." << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0,0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Firstly, source platform (32bit or 64bit) must be matched to destination platform.(In my 64bit machine, notepad is 64bit.)
Secondly,for a hook procedure in DLL, Don’t verify whether it works or not by print, the same as std::out. The DLL has nowhere to print its content. The following code uses a file stream.
// The callback function
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION)
{
if (wParam > 0)
{
std::cout << "sent by the current thread wParam=" << wParam;
}
CWPSTRUCT* s = (CWPSTRUCT*)lParam;
//have no
std::cout << " Index=" << nwinhooksdll++ << " s->message=" << s->message << " s->hwnd=" << s->hwnd << " s->wParam=" << s->wParam << " s->lParam=" << s->lParam << "\n";
//MessageBox(NULL,L"CallWndProc",L"CALLBACK",0);
//works
myfile << " Index=" << nwinhooksdll++ << " s->message=" << s->message << " s->hwnd=" << s->hwnd << " s->wParam=" << s->wParam << " s->lParam=" << s->lParam << "\n";
}
//This is a must
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
#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;
}
I am trying to read values from the joystick using simple C++ techniques and Windows.
My aim is to write a program that sends a keyboard command whenever the joystick signal exceeds a predefined threshold. The keyboard command will be picked up by whichever window would be active at the time.
My C++ coding skills are limited so I wish to do this in the simplest way, preferably within one main().
Up to now I have managed to register the joystick.
But I stumbled across the first problem, which is how to use GetRawInputData(). I found a lot of examples about this within a win32 structure, but am struggling to translate this to a simple main().
My code till now is the following:
#include <windows.h>
#include <iostream>
RAWINPUTDEVICE Rid[1];
int main()
{
UINT bufferSize;
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x05;
Rid[0].dwFlags = 0;
Rid[0].hwndTarget = 0;
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE)
{
std::cout << "Registration failed" << std::endl;
return 1;
}
else
{
std::cout << "Registration OK" << std::endl;
while (1)
{
// This is the part in which I would like to read the joystick values
// and determine whether to send a keyboard event or not.
}
}
return 0;
}
Can you help?
Thanks.
UPDATE
Following the suggestion to use joyGetInput(), here is the updated code:
#include<Windows.h>
#include<iostream>
#include<time.h>
using namespace std;
#define mid 32767
#define trig 1804
#define reset 1475
int main()
{
JOYINFO pos;
UINT result;
SYSTEMTIME st;
INPUT xi, yi, zi;
int i = 0;
int state[6] = { 0,0,0,0,0,0 };
int uu = mid + trig;
int ul = mid + reset;
xi.type = INPUT_KEYBOARD;
yi.type = INPUT_KEYBOARD;
zi.type = INPUT_KEYBOARD;
while (1)
{
result = joyGetPos(i, &pos);
if (result != JOYERR_NOERROR)
{
cout << "JoyID " << i << " returned an error. Trying the next one." << endl;
i++;
if (i > 15)
{
cout << "Reached the maximum allowed attempts. Exiting." << endl;
return 1;
}
}
else
{
//GetSystemTime(&st);
//cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
if (pos.wXpos > uu && state[0] == 0)
{
xi.ki.wVk = 0x30;
xi.ki.dwFlags = 0;
SendInput(1, &xi, sizeof(INPUT));
state[0] = 1;
GetSystemTime(&st);
cout << "Key down - X axis" << endl;
cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
}
if (pos.wXpos < ul && state[0] == 1)
{
xi.ki.wVk = 0x30;
xi.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &xi, sizeof(INPUT));
state[0] = 0;
GetSystemTime(&st);
cout << "Key up - X axis" << endl;
cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << ":" << st.wMilliseconds << "\tX: " << pos.wXpos << "\tY: " << pos.wYpos << "\tZ: " << pos.wZpos << endl;
}
}
}
return 0;
}
My new question now is:
How do you simulate a long key press? I would like the target window to behave just like a user kept pressing on the key. With the above code, the key is issued only once.
GetRawInputData() takes an HRAWINPUT handle as input. The only place you can get that handle is from the LPARAM parameter of the WM_INPUT window message.
Your main() function needs to use CreateWindow/Ex() to create a window (if you don't want the user to see it, consider making a message-only window), specify that window in the joystick's RAWINPUTDEVICE::hwndTarget field when you call RegisterRawInputDevices(), and then run a message loop so the window can receive messages. For example:
#include <windows.h>
#include <iostream>
int main()
{
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = DefWindowProc;
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = TEXT("MyRawInputWndClass");
if (!RegisterClassEx(&wx))
{
std::cout << "Window Class Registration failed" << std::endl;
return 1;
}
HWND hWnd = CreateWindowEx(0, wx.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wx.hInstance, NULL);
if (!hWnd)
{
std::cout << "Window Creation failed" << std::endl;
return 1;
}
RAWINPUTDEVICE Rid = {};
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x05;
Rid.dwFlags = 0;
Rid.hwndTarget = hWnd;
if (!RegisterRawInputDevices(&Rid, 1, sizeof(RAWINPUTDEVICE)))
{
std::cout << "Device Registration failed" << std::endl;
return 1;
}
std::cout << "Device Registration OK" << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_INPUT)
{
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(msg.lParam);
// retrieve and process data from hRawInput as needed...
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
Alternatively:
#include <windows.h>
#include <iostream>
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_INPUT)
{
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(lParam);
// retrieve and process data from hRawInput as needed...
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int main()
{
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = &MyWndProc;
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = TEXT("MyRawInputWndClass");
if (!RegisterClassEx(&wx))
{
std::cout << "Window Class Registration failed" << std::endl;
return 1;
}
HWND hWnd = CreateWindowEx(0, wx.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, wx.hInstance, NULL);
if (!hWnd)
{
std::cout << "Window Creation failed" << std::endl;
return 1;
}
RAWINPUTDEVICE Rid = {};
Rid.usUsagePage = 0x01;
Rid.usUsage = 0x05;
Rid.dwFlags = 0;
Rid.hwndTarget = hWnd;
if (!RegisterRawInputDevices(&Rid, 1, sizeof(RAWINPUTDEVICE)))
{
std::cout << "Device Registration failed" << std::endl;
return 1;
}
std::cout << "Device Registration OK" << std::endl;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I suggest you read the Raw Input documentation more carefully. This is all explained in detail. If you don't specify a window to RegisterRawInputDevices(), the OS will send the WM_INPUT messages to whichever window currently has the keyboard focus, which is not what you want.
That being said, if you want something simplier, you might consider using joyGetPosEx() instead of Raw Input.
My goal is to capture keystrokes of the user when he is interacting with Internet Explorer (iexplore.exe).
This is my DLL code for a DLL called hook.dll.
#include <iostream>
#include <windows.h>
extern "C" __declspec(dllexport)
LRESULT keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0) {
std::cout << "nCode: " << nCode << "; wParam: " << wParam
<<" (" << char(wParam) << "); scan code: "
<< ((lParam & 0xFF0000) >> 16)
<< "; transition state: " << ((lParam & 0x80000000) >> 31)
<< std::endl;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
std::cout << "hinstDLL: " << hinstDLL
<< "; fdwReason: " << fdwReason
<< "; lpvReserved: " << lpvReserved << std::endl;
return TRUE;
}
Here is the main program code for main.exe:
#include <iostream>
#include <windows.h>
int main(int argc, char **argv)
{
HMODULE dll = LoadLibrary("hook.dll");
if (dll == NULL) {
std::cerr << "LoadLibrary error " << GetLastError() << std::endl;
return 1;
}
HOOKPROC callback = (HOOKPROC) GetProcAddress(dll, "keyboardHook");
if (callback == NULL) {
std::cerr << "GetProcAddress error " << GetLastError() << std::endl;
return 1;
}
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, callback, dll, NULL);
if (hook == NULL) {
std::cerr << "SetWindowsHookEx error " << GetLastError() << std::endl;
return 1;
}
MSG messages;
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
UnhookWindowsHookEx(hook);
}
I compile this project with these commands:
vcvars32.bat
cl /LD hook.cc /link user32.lib
cl main.cc /link user32.lib
When I execute the program, and press the keys A, B and C, I see the following output.
C:\>main
hinstDLL: 10000000; fdwReason: 1; lpvReserved: 00000000
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 0
nCode: 0; wParam: 65 (A); scan code: 30; transition state: 1
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 0
nCode: 0; wParam: 66 (B); scan code: 48; transition state: 1
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 0
nCode: 0; wParam: 67 (C); scan code: 46; transition state: 1
This is all good so far, but this program captures keystrokes made anywhere on the desktop. But I want to capture only those keystrokes that are made on Internet Explorer. I believe I need to modify the SetWindowsHookEx(WH_KEYBOARD, callback, dll, NULL); call in main program and pass the thread ID of the Internet Explorer as the fourth argument to this call. Could you please help me to solve this problem?
You have two solutions:
1 Use SetWindowsHookEx WH_KEYBOARD with TIDs. That's not easy, as you'll have to imlement a mechanism for detecting new threads.
2 Use SetWindowsHookEx WH_GETMESSAGE for all threads. You'll have to filter for KeyBoard messages and for the process name. That's much simpler (except that you'll miss the 64 bits process if your EXE is 32, or the other way arround, unless you build and run two EXEs and two DLLs (32/64). Bonus point: you will be able to easily keylog Chrome and Firefox.
Here is a solution code based on manuell's suggestion of using WH_GETMESSAGE.
DLL code in hook.cc:
#include <iostream>
#include <fstream>
#include <windows.h>
#include <psapi.h>
extern "C" __declspec(dllexport)
LRESULT myHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
std::ofstream outputTxt("C:\\out.txt",
std::ofstream::out | std::ofstream::app);
PMSG msg = (PMSG) lParam;
// Get PID of process
DWORD pid;
GetWindowThreadProcessId(msg->hwnd, &pid);
// Get process name
char filename[1024];
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
GetModuleBaseName(h, NULL, filename, sizeof filename);
// Log details only if it is Internet Explorer
if (msg->message == WM_KEYUP && strcmp(filename, "iexplore.exe") == 0) {
outputTxt << "nCode: " << nCode << "; wParam: " << wParam
<< "; message: " << msg->message
<< "; keycode: " << msg->wParam << " '"
<< char(msg->wParam) << "'"
<< "; filename: " << filename << std::endl;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
std::cout << "hinstDLL: " << hinstDLL
<< "; fdwReason: " << fdwReason
<< "; lpvReserved: " << lpvReserved << std::endl;
return TRUE;
}
Main program code in main.cc:
#include <iostream>
#include <windows.h>
int main(int argc, char **argv)
{
HMODULE dll = LoadLibrary("hook.dll");
if (dll == NULL) {
std::cerr << "LoadLibrary error " << GetLastError() << std::endl;
return 1;
}
HOOKPROC callback = (HOOKPROC) GetProcAddress(dll, "myHook");
if (callback == NULL) {
std::cerr << "GetProcAddress error " << GetLastError() << std::endl;
return 1;
}
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE, callback, dll, NULL);
if (hook == NULL) {
std::cerr << "SetWindowsHookEx error " << GetLastError() << std::endl;
return 1;
}
MSG messages;
while (GetMessage(&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
UnhookWindowsHookEx(hook);
}
Compiled this project as follows.
vcvars32.bat
cl /D_WIN32_WINNT=0x0401 /LD hook.cc /link user32.lib /link psapi.lib
cl main.cc /link user32.lib
Since my EXE was 32-bit, I launched 32-bit Internet Explorer, clicked on the address bar and pressed the keys A, B and C. This is the result I found in C:\out.txt.
nCode: 0; wParam: 1; message: 257; keycode: 65 'A'; filename: iexplore.exe
nCode: 0; wParam: 1; message: 257; keycode: 66 'B'; filename: iexplore.exe
nCode: 0; wParam: 1; message: 257; keycode: 67 'C'; filename: iexplore.exe
Launching 64-bit Internet Explorer, and doing the same thing yielded no results in C:\out.txt.