GetSystemMetrics return wrong value for my screen - c++

I have a sample code to get the hight and width in pixels.
But it shows the wrong resolution for my screen.
I have 3840 x 2160.
But the application says: 1920 x 1080.
Code:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, int in, int in2)
{
TCHAR szBuffer[1024];
va_list pArgList;
// The va_start macro (defined in STDARG.H) is usually equivalent to
// pArgList = (char *) &szFormat + sizeof (szFormat) ;
va_start(pArgList, szFormat);
// The last argument to wvsprintf points to the arguments
_vsntprintf_s(szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
szFormat, pArgList);
// The va_end macro just zeroes out pArgList for no good reason
va_end(pArgList);
return MessageBox(NULL, szBuffer, szCaption, 0);
}
int WINAPI WinMain(HINSTANCE hTnstance, HINSTANCE hPreVInStane,PSTR szCmdLine, int iCmdShow)
{
int cxScreen=0, cyScreen=0;
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
MessageBoxPrintf(TEXT("ScrnSize"), TEXT("Wide %i High %i"), cxScreen, cyScreen);
return 0;
}
Is this funtion outdated (GetSystemMetrics) or im i doing something wrong?

The issue is due to your display DPI/scailing settings
Please see GetSystemMetrics() returns wrong value for SM_CXSCREEN
And also SetProcessDPIAware and SetProcessDpiAwareness API

Related

How to get address of user-defined function?

I am trying to hook a user-defined function. (via DLL injection and inline function hooking)
To do that, I need to get the address of the function to hook in process memory.
I tried various methods to find the address, and finally came up with the equation below.
(offset) = (Address of function in EXE file) - (Image base of EXE file)
(Address of function in process memory) = (GetModuleHandle(NULL)) + (offset)
However, I am not sure if this equation always holds. (For example, when DLL Relocation occurs, I am worried that this equation may be wrong.)
In conclusion, I want to know whether this equation always holds. And if not, I'd like to know how to fix this equation.
(This article has been translated by Google Translate.)
< testwinapi / main.cpp >
#include <stdio.h>
#include <Windows.h>
void capture(HBITMAP* canvas);
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
while(1) {
HBITMAP canvas;
capture(&canvas);
Sleep(2000);
}
return 0;
}
void capture(HBITMAP* canvas) {
RECT srcRect;
HWND hSrcWnd;
HDC hSrcDC, hDestDC;
hSrcWnd = GetDesktopWindow();
hSrcDC = GetDC(hSrcWnd);
GetWindowRect(hSrcWnd, &srcRect);
int SrceenWidth = srcRect.right - srcRect.left;
int SrceenHeight = srcRect.bottom - srcRect.top;
hDestDC = CreateCompatibleDC(hSrcDC);
*canvas = CreateCompatibleBitmap(hSrcDC, SrceenWidth, SrceenHeight);
SelectObject(hDestDC, *canvas);
for (int y = 0; y < SrceenHeight; y += 50) {
BitBlt(hDestDC, 0, y, SrceenWidth, 50, hSrcDC, 0, y, SRCCOPY);
Sleep(2);
}
ReleaseDC(hSrcWnd, hSrcDC);
DeleteDC(hDestDC);
}
< testdll / dllmain.cpp >
#include "pch.h"
DWORD WriteLog(LPCTSTR format, ...);
void MyCapture(HBITMAP* canvas);
void(*originFunc)(HBITMAP*) = reinterpret_cast<void(*)(HBITMAP*)>(0x941880); //Address of function in process memory
DWORD WriteLog(LPCTSTR lpszFormat, ...) {
TCHAR szLog[512];
DWORD dwCharsWritten;
va_list args;
va_start(args, lpszFormat);
_vstprintf_s(szLog, 512, lpszFormat, args);
va_end(args);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), szLog, _tcslen(szLog), &dwCharsWritten, NULL);
return dwCharsWritten;
}
void MyCapture(HBITMAP* canvas) {
WriteLog(TEXT("Function called : capture(0x%X)\n"), (DWORD)canvas);
return originFunc(canvas);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (DetourIsHelperProcess())
return TRUE;
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
AllocConsole();
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)originFunc, MyCapture);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
FreeConsole();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)originFunc, MyCapture);
DetourTransactionCommit();
break;
}
return TRUE;
}
< testdll / pch.cpp >
#include "pch.h"
< testdll / pch.h >
#ifndef PCH_H
#define PCH_H
#include "framework.h"
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <detours.h>
//MS Detours library
//Can be downloaded from NuGet Package Manager
#endif
< testdll / framework.h >
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
< DLL Injector >
https://github.com/DarthTon/Xenos/releases/latest
After injecting 'testdll.dll' into 'testwinapi.exe', I want to be able to monitor the 'capture' function call. (Because the 'capture' function is reconstructed by reverse engineering, it is assumed that there is no source code for 'testwinapi.exe')
Module relocation occurs as a whole. Individual sections are never moved with respect to the image base. The offsets (RVA) of each section are hardcoded in the module header.
For example:
# Name VirtSize RVA PhysSize Offset
1 .text 000C44C1 00001000 000C4600 00000800
2 .data 00000FEC 000C6000 00000E00 000C4E00
3 .rsrc 00000520 000C7000 00000600 000C5C00
4 .reloc 0000B098 000C8000 0000B200 000C6200
These sections are loaded at specified RVA offsets, regardless of image base address. There's also the implicit "header" section with RVA 0 and size 0x1000, which is why the first section starts at 0x1000. Note that RVA offset != file offset.
So yes, given some known image base and an address inside of it, the offset of that address from the image base will remain constant.
This allows 64-bit code to employ RIP-relative addressing into the .data section, for example, which saves a fixup.

use the #include <windows.h> make my console crash on windows 10

I have a program which includes <windows.h> and it works in computers that run windows 7 or 8, but crashes in a computer that runs windows 10. Can you help me?
This is the part of the code that makes my console crash:
#include <cstdlib>
#include <iostream>
#include <conio.h>
#include <ctime>
#include <windows.h>
using namespace std;
void sposta_tu(posizione pos, char cosa){
HANDLE handle = GetStdHandle ( STD_OUTPUT_HANDLE );
COORD coordinate = {pos.y,pos.x};
FillConsoleOutputCharacter ( handle, cosa ,1, coordinate, 0 );
}
void ellimina_tu(posizione pos){
HANDLE handle = GetStdHandle ( STD_OUTPUT_HANDLE );
COORD coordinate = {pos.y,pos.x};
FillConsoleOutputCharacter ( handle,' ',1, coordinate, 0 );
}
BOOL WINAPI FillConsoleOutputCharacter(
_In_ HANDLE hConsoleOutput,
_In_ TCHAR cCharacter,
_In_ DWORD nLength,
_In_ COORD dwWriteCoord,
_Out_ LPDWORD lpNumberOfCharsWritten
);
Last parameter is out parameter, you can't pass 0.
DWORD numberOfCharsWritten;
FillConsoleOutputCharacter(handle, ' ', 1, coordinate, &numberOfCharsWritten);

Getting a/d converter example program to work in a C++ windows program

I got the following example code for a C windows programm from the developer of my analog to digital converter and want to make it run as a windows c++ project in Visual Studio 2016.
As a beginner in C++, windows API and this universal library for the converter I'm overwhelmed with the troubleshooting right now. The plan was to learn by making the code work but right now it's really hard to find out where the problems are and there's not the time to learn everything from scratch (though I try next to it)
This is my setup: Windows 7 64bit, MS Visual Studio Community 2017, USB 1608fs plus a/d converter with its universal library
These are the errors I'm currently getting:
a value of type "HANDLE" cannot be used to initialize an entity of type "HINSTANCE" (row 83)
a value of type "HGDIOBJ" cannot be used to initialize an entity of type "HBRUSH"(row 86)
the argument of type "HANDLE" is incompatible with parameter type "HINSTANCE" (row 93)
Actions I took until now:
creating a new empty win32 project in MS Visual Studio
copying the example code
copying the header file and the library from the converter into the same folder
switching the character set from unicode to multibyte
switching off the precompiled header
include the missing headers from the precompiled header
Here is the code:
#include <windows.h> /* Compiler's include files's */
#include <string.h>
#include <stdio.h>
#include "cbw.h" /* Universal Library's include file */
#include "targetver.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#define BOARD_NUM 0 /* Number of A/D board as defined with InstaCal */
#define ADRANGE BIP5VOLTS /* A/D voltage range */
#define TIMER_NUM 1 /* Windows timer used by this program */
HWND hWndMain; /* handle for main window */
LONG FAR PASCAL MainMessageHandler(HWND, UINT, WPARAM, LPARAM);
/************************************************************************
*
* Name: WinMain
*
* Arguments: hInstance - the instance handle for the program
* hPrevInstance - the class name of the application (not used)
* CmndLine - command line was called with (not used)
* CmndShow - indicates how to display window
*
* This is the entry point to the program. It gets called by Windows
* to start the program up. This routine creates the main window,
* initializes a timer, and then falls into the main Windows Get
* message/Dispatch message loop.
*
************************************************************************/
int PASCAL
WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR CmdLine, int nCmdShow)
{
MSG msg; /* MSG structure to pass to windows proc */
WNDCLASS wndclass;
char *AppName; /* Name for the window */
cbErrHandling(PRINTALL, STOPALL); /* Set library's error handling */
CmdLine = NULL; /* Not used */
AppName = "WINCDEMO"; /* The name of this application */
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = MainMessageHandler;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, AppName);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = AppName;
wndclass.lpszClassName = AppName;
RegisterClass(&wndclass);
}
/* create application's Main window */
hWndMain = CreateWindow(AppName, /* Window class name */
"AIn Demo",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, /* Use default X, Y */
CW_USEDEFAULT, /* Use default X, Y */
GetSystemMetrics(SM_CXSIZE) * 12, /* x - fit text */
GetSystemMetrics(SM_CYSIZE) * 10, /* y - fit text */
NULL, /* Parent window's handle */
NULL, /* Default to Class Menu */
hInstance, /* Instance of window */
NULL); /* Create struct for WM_CREATE */
if (hWndMain == NULL)
{
MessageBox(NULL, "Could not create window in WinMain", NULL, MB_ICONEXCLAMATION);
return (1);
}
ShowWindow(hWndMain, nCmdShow); /* Display main window */
UpdateWindow(hWndMain);
// /* Start a 500ms timer to update display */
if (!SetTimer(hWndMain, TIMER_NUM, 50, NULL))
{
MessageBox(NULL, "Error starting Windows timer", NULL, MB_OK |
MB_ICONEXCLAMATION);
return (1);
}
while (GetMessage(&msg, NULL, 0, 0)) /* Main message loop */
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(AppName, hInstance);
return (msg.wParam);
}
/************************************************************************
*
* Name: MainMessageHandler
*
* Arguments: hWnd - handle to the window
* Message - message that needs to be handled
* hParam - message parameter
* lParam - message parameter
*
* This is the message dispatcher that gets called whenever Windows
* sends a message to this window. WinMain started up a timer that
* sends a message every 1/2 sec. When the message (WM_TIMER)is received
* by this routine, it reads the A/D.
* It also causes a screen update which will automatically generate a
* WM_PAINT message. The WM_PAINT handler takes care of converting the
* raw A/D values to voltages and printing them in the Window.
*
************************************************************************/
LONG FAR PASCAL
MainMessageHandler(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
HDC hDC; /* handle for the display device */
PAINTSTRUCT ps; /* holds PAINT information */
TEXTMETRIC tm; /* holds TEXT information */
static HRGN hRgn; /* Rectangle region Handles */
static int CharWidth, CharHeight;
static unsigned short DataVal;
int x, y;
char OutString[80], *str;
float Voltage;
switch (Message) /* Windows Message Loop */
{
case WM_CREATE:
hDC = GetDC(hWndMain); /* Get the device context for window */
GetTextMetrics(hDC, &tm); /* From context, get size of font */
CharWidth = tm.tmAveCharWidth;
CharHeight = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hWndMain, hDC);
hRgn = CreateRectRgn(0, 0, CharWidth * 30, CharHeight * 12);
break;
case WM_TIMER: /* All Timer Events Processed Here */
InvalidateRgn(hWndMain, hRgn, FALSE); /* Force screen update */
break;
case WM_PAINT: /* Repaint client area of window */
hDC = BeginPaint(hWndMain, &ps);
x = CharWidth * 2; /* Position cursor within window */
y = CharHeight; /* One line down and 2 chars in */
str = " A/D Info"; /* Print title */
TextOut(hDC, x, y, str, strlen(str));
y += CharHeight; /* Print current index */
cbAIn(BOARD_NUM, 0, ADRANGE, &DataVal);
y += CharHeight * 2; /* Print raw data value */
sprintf(OutString, "Raw A/D value = %u ", DataVal);
TextOut(hDC, x, y, OutString, strlen(OutString));
y += CharHeight; /* Convert raw A/D to volts and print */
cbToEngUnits(BOARD_NUM, ADRANGE, DataVal, &Voltage);
sprintf(OutString, "Voltage = %.2f ", Voltage);
TextOut(hDC, x, y, OutString, strlen(OutString));
SetTextAlign(hDC, TA_LEFT | TA_TOP);
EndPaint(hWndMain, &ps);
break;
case WM_CLOSE: /* Close the window */
DestroyWindow(hWnd);
if (hWnd == hWndMain)
PostQuitMessage(0); /* Send message to Quit application */
break;
default:
return (DefWindowProc(hWnd, Message, wParam, lParam));
}
return (0l);
}
Instead of randomly roaming around copypasting staff and switching things on and off you should first understand the errors you are facing. For example first error: You should lookup on MSDN what HANDLE and HINSTANCE are and figure out where are you getting them from. You get hInstance from WinMain. You should lookup on MSDN for WinMain and figure out that signature you used is somewhat wrong and you are supposed to use
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
So the error with wndclass.hInstance = hInstance; assignment of HANDLE to HINSTANCE should be gone (assuming that I've pointed the correct line of this error because you only specified row).
And so on.

Get processID using part of WINDOW heading

i use the following program in c++ ,in Visual C++ 6.0, to inform me with message box when the MS Paint program is opened. It uses the exact name of the WINDOW of MS Paint,which is "Untitled - Paint" . However now i need to make the program inform me with message box when i know only a part of the name of the actual WINDOW , for example , if the window is "Abcdefgh - Paint" and i set the string name in this way - std::wstring windowName(L"Paint"); - the program to work again. Using the following 3 rows of code the program works fine when the actual WINDOW name is the exact name of the MS Paint window:
HWND windowHandle = FindWindowW(NULL, windowName.c_str());
DWORD* processID = new DWORD;
GetWindowThreadProcessId(windowHandle, processID);
But it will not work if the string windowName is just part of the name, i mean if it is "Paint".
Can someone show me how to do this? I thought to take a list of the names of all opened WINDOWS and to compare them with my part of the real name, i mean to search match of the substring "Paint" in their names, but i don't know how to get all opened windows.
Also, this is very important, my computer is old and i am using Visual C++ 6.0, so i can not use all the evolution features of C++ and the program environments nowadays, i mean , i can not use code which is compiled correctly in .NET but does not compiles in Visual C++ 6.0.
Thanks
#include "stdafx.h"
#include < iostream>
#include < string>
#include < windows.h>
#include < sstream>
#include < ctime>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
std::wstring windowName(L"Untitled - Paint");
while(true)
{
Sleep(1000*5);
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
int tday = now->tm_mday;
int tmin = now->tm_min;
int thour = now->tm_hour;
HWND windowHandle = FindWindowW(NULL, windowName.c_str());
DWORD* processID = new DWORD;
GetWindowThreadProcessId(windowHandle, processID);
char probaintstr[20];
sprintf(probaintstr,"%d",*processID);
if(strlen(probaintstr) <=5 )
{
Sleep(1000*10);
MessageBox(NULL,"niama go Notepad ili Wordpad","zaglavie",MB_OK);
}
else {
}
}
return 0;
}
You can use EnumWindows, for example
BOOL CALLBACK enumWindow(HWND hwnd, LPARAM lp)
{
std::string str(512, 0);
int len = GetWindowText(hwnd, &str[0], str.size());
if (str.find("Paint") != std::string::npos)
{
MessageBox(0, str.c_str(), 0, 0);
}
return true;
}
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
EnumWindows(enumWindow, 0);
return 0;
}
Or you can use FindWindowEx and look for classname. The classname for MS Paint is "MSPaintApp". You can find this information from "Spy" utility for windows.
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
for (HWND hwnd = NULL;;)
{
hwnd = FindWindowExA(NULL, hwnd, "MSPaintApp", 0);
if (!hwnd)
break;
std::string str(512, 0);
int len = GetWindowText(hwnd, &str[0], 512);
str.resize(len);
if (str.find("Paint") != std::string::npos)
MessageBox(0, str.c_str(), 0, 0);
}
return 0;
}
For process id you don't need to allocate memory. Just use a reference:
DWORD processID;
GetWindowThreadProcessId(windowHandle, &processID);

WinMain arguments

My issue is that the arguments are only retrieving the first letter in each of the parameters, for this i do not know why..
Could someone elaborate?
#include <Windows.h>
#include <string>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hpInstance, LPSTR nCmdLine, int iCmdShow){
LPWSTR *szArglist;
int nArgs = 0;
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
std::string a;
for(int i=0; i<nArgs; i++){
a += (LPCSTR)szArglist[i];
}
MessageBox(NULL, (LPCSTR)a.c_str(), (LPCSTR)a.c_str(), MB_OK);
LocalFree(szArglist);
return 0;
}
I believe the issue lies within CommandLineToArgvW(GetCommandLineW(), &nArgs);
LPWSTR is typedefed to wchar_t *, szArglist is an array of wchar_t *s. A wide character is 2 bytes instead of of 1, so a letter might be represented as:
0x0038 0x0000
However, if you take those bytes and say 'hey, pretend I'm a char *, this looks like a C-string with one letter (0x0038), because the 2nd char (0x0000) is null, which in C style strings represents the end of the string.
The problem you have is that you are trying to fit wide characters (wchar_t) into a non-wide (char) string, which is a much more complicated opperation.
The solution: either use wstring/wchar_t everywhere (corresponding to LPWSTR/LPCWSTR), or use string/char everywhere (corresponding to LPSTR and LPCSTR I believe). Note that your project setting for 'use unicode' should match your decision. Try not to mix these!
Shouldn't this just be
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hpInstance, LPSTR nCmdLine, int iCmdShow)
{
MessageBoxA(NULL, nCmdLine, nCmdLine, MB_OK);
return 0;
}
or
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hpInstance, LPSTR nCmdLine, int iCmdShow)
{
MessageBoxW(NULL, GetCommandLineW(), GetCommandLineW(), MB_OK);
return 0;
}
?