I want to use Windows API to realize the line by line printing of the printer.
For example, if there is only one message at present, print one message. Then the printer waits and the paper stops printing. When there is information next time, continue printing on the same paper.
With windows API, I can only print by page in the following way. I don't know how to print by line. After one line is finished, the printing is suspended and the next line continues to be printed after waiting for a new task.
bool CMFCApplication1Dlg::printTicket(CString& szPrinter, CString&
szContent)
{
static DOCINFO di = { sizeof(DOCINFO), (LPTSTR)TEXT("printer"),NULL };
HDC hdcPrint = CreateDC(nullptr, szPrinter.GetBuffer(), nullptr, nullptr);
if (hdcPrint != 0)
{
if (StartDoc(hdcPrint, &di) > 0)
{
StartPage(hdcPrint);
SaveDC(hdcPrint);
int xDistance = 20;
int yDistance = 20;
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
logFont.lfWeight = FW_NORMAL;
logFont.lfHeight = 60;
logFont.lfWeight = 36;
HFONT hFont = CreateFontIndirect(&logFont);
SelectObject(hdcPrint, hFont);
TextOut(hdcPrint, xDistance, yDistance, szContent.GetBuffer(), szContent.GetLength());
RestoreDC(hdcPrint, -1);
EndPage(hdcPrint);
EndDoc(hdcPrint);
}
else
{
cout << "StartDoc failed!" << endl;
string errorCode = to_string(GetLastError());
cout << "Error code is:" << errorCode << endl;
return false;
}
DeleteDC(hdcPrint);
}
else
{
cout << "CreateDC failed!" << endl;
string errorCode = to_string(GetLastError());
cout << "Error code is :" << errorCode << endl;
return false;
}
return true;
}
bool CMFCApplication1Dlg::SetPrinterParameters(CString& szPrinter)
{
HANDLE hPrinter = nullptr;
PRINTER_INFO_2* pi2 = nullptr;
DEVMODE* pDevMode = nullptr;
PRINTER_DEFAULTS pd;
DWORD dwNeeded = 0;
BOOL bFlag;
LONG lFlag;
WCHAR szDevName[MAX_PATH] = L"";
DWORD dwLength = MAX_PATH;
if (!GetDefaultPrinter(szDevName, &dwLength))
{
return false;
}
szPrinter = szDevName;
return true;
}
Maybe this has something to do with the printer driver?
I use C# winspool library and can't meet this requirement too, maybe I don't know how to use them.
Hope your help.
Related
I am currently searching for a way to set a fully custom resolution on a Windows Server 2019 VM with GPU (T4, with grid licence, and virtual workstation grid drivers) with C++.
I have tried different way to achieve this, I can make this work on my laptop, but seems to have some limitations on GCP VMs (or Windows Server limitation).
I have tried to do this with ChangeDisplaySettings/ChangeDisplaySettingsEx (winuser.h), I can change to a known resolution, but can't make it works with a custom one (not even with CDS_ENABLE_UNSAFE_MODE).
DWORD deviceIndex = 0;
DISPLAY_DEVICE displayDevice = { 0 };
displayDevice.cb = sizeof(DISPLAY_DEVICE);
while (EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)) {
deviceIndex++;
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
DEVMODE finalDm = { 0 };
finalDm.dmSize = sizeof(DEVMODE);
//Check if able to retrieve current settings
if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
continue;
}
//Check if there is a difference in resolution list if UNSAFE_MODE is enabled or not (it seems to not change anything)
int result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, 0, CDS_DISABLE_UNSAFE_MODES, NULL);
std::cout << "CDS_DISABLE_UNSAFE_MODE" << std::endl;
if (result == DISP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumDisplaySettings(displayDevice.DeviceName, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " # " << dm.dmDisplayFrequency << std::endl;
}
}
}
result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, 0, CDS_ENABLE_UNSAFE_MODES, NULL);
std::cout << "CDS_ENABLE_UNSAFE_MODE" << std::endl;
if (result == DISP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumDisplaySettings(displayDevice.DeviceName, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " # " << dm.dmDisplayFrequency << std::endl;
}
}
}
std::cout << "Please enter width : ";
int width, height;
std::cin >> width;
std::cout << "Please enter height : ";
std::cin >> height;
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
if (width > height) {
dm.dmDisplayOrientation = DMDO_DEFAULT;
}
else {
dm.dmDisplayOrientation = DMDO_90;
}
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYORIENTATION;
//result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_TEST, NULL);
result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, 0, NULL);
if (result != DISP_CHANGE_SUCCESSFUL) {
std::cout << "Impossible to ChangeDisplaySettings" << endl;
}
else {
std::cout << "OK" << endl;
}
break;
}
I then take a look at NVAPI, and same here, I can make it works on my PC but still nothing on the GCP VMs... I have found a way to make NVAPI create and use custom resolution on my local PC, but can't make it works on GCP VM once again... (Code example found here)
NvAPI_Status result = NVAPI_ERROR;
NvU32 primaryDisplayId = 0;
//Testing resolution
int horizontal = 1920, vertical = 1090;
result = NvAPI_Initialize();
if (result != NVAPI_OK) {
printf("Could not initialize NvAPI");
return false;
}
MONITORINFOEX monInfo;
HMONITOR hMon;
const POINT ptZero = { 0, 0 };
// determine the location of the primary monitor
hMon = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
ZeroMemory(&monInfo, sizeof(monInfo));
monInfo.cbSize = sizeof(monInfo);
GetMonitorInfo(hMon, &monInfo);
result = NvAPI_DISP_GetGDIPrimaryDisplayId(&primaryDisplayId);
if (result != NVAPI_OK) {
printf("Could not get display ID from device");
NvAPI_Unload();
return false;
}
NvU32 deviceCount = 0;
NV_CUSTOM_DISPLAY cd[NVAPI_MAX_DISPLAYS] = { 0 };
float refreshRate = 60;
// timing computation (to get timing that suits the changes made)
NV_TIMING_FLAG flag = { 0 };
NV_TIMING_INPUT timing = { 0 };
timing.version = NV_TIMING_INPUT_VER;
timing.height = vertical;
timing.width = horizontal;
timing.rr = refreshRate;
timing.flag = flag;
timing.type = NV_TIMING_OVERRIDE_CVT_RB;
result = NvAPI_DISP_GetTiming(primaryDisplayId, &timing, &cd[0].timing);
if (result != NVAPI_OK) {
printf("Failed to get timing for display"); // failed to get custom display timing
NvAPI_Unload();
return false;
}
cd[0].width = horizontal;
cd[0].height = vertical;
cd[0].xRatio = 1;
cd[0].yRatio = 1;
cd[0].srcPartition = { 0, 0, 1.0, 1.0 };
cd[0].depth = 32;
cd[0].version = NV_CUSTOM_DISPLAY_VER;
cd[0].colorFormat = NV_FORMAT_A8R8G8B8;
//Returns NVAPI_ERROR on GCP but NVAPI_OK on my laptop
result = NvAPI_DISP_TryCustomDisplay(&primaryDisplayId, 1, cd);
if (result != NVAPI_OK) {
printf("Could not set custom resolution");
NvAPI_DISP_RevertCustomDisplayTrial(&primaryDisplayId, 1);
NvAPI_Unload();
return false;
}
else {
NvAPI_DISP_SaveCustomDisplay(&primaryDisplayId, 1, true, true);
}
This part works perfectly well on my laptop, I can use a new dynamic resolution (It works with 1920x400, 1920x500, 1920x600), but not on my GCP VM, this parts :
NvAPI_DISP_TryCustomDisplay(&primaryDisplayId, 1, cd);
always returns NVAPI_ERROR
I have found another trick, I can edit this registry entry : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video{RANDOM_ID}\0001\NV_Modes
(Here is an old pdf, after some testing, it seems it is still working this way)
If I add some resolution using NVAPI, I can then set through ChangeDisplaySettingsEx function this resolution (it needs GPU driver restart, or Windows restart be able to change to a fresh new added resolution).
But I need to be able to rotate screen, playing with "dmDisplayOrientation", and it does not seem to work on GCP VM once again, if I authorize for example 1920x1090 I can set resolution to this, but cannot set 1090x1920 with a "dmDisplayOrientation = DMDO_90" (even if I authorize 1090x1920 too...)
So if anyone found a way, or have any idea on how to do this, it would be great, I am running out of idea right now...
I'm trying to attach a Hardware breakpoint to a game process and I succed. Then I'm trying to loop through the Exceptions and wait for the one that I've put in there, which is also working fine. The problem is that after it happens it goes into infinite loop that I cannot brake. Can you advise?
The reason for me doing that is that I want to stop the thread at this point, read the EAX value with the use of Context and then proceed with the process.
Header.h includes the functions that are called here and they all work fine, thus Im not including it at this point.
#include "Header.h"
#include
int main() {
SetDebugPrivilege(TRUE);
DWORD dwProcessID = 0;
DWORD dwGame = 0;
printf("Looking for game process...\n");
while (dwProcessID == 0) {
dwProcessID = GetProcessID(L"PathOfExile.exe");
if (dwProcessID != 0)
dwGame = 1;
Sleep(100);
}
printf("dwProcessID = %p\n", dwProcessID);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
MODULEENTRY32 module;
module.dwSize = sizeof(MODULEENTRY32);
Module32First(snapshot, &module);
printf("PoE base address = %p\n", module.modBaseAddr);
hpChangeBreakpoint = (DWORD*)((char *)module.modBaseAddr + 0x1AAD20);
std::cout << hpChangeBreakpoint << std::endl;
//hpChangeBreakpoint = 0x013FB279;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);
BOOL bDebugging = DebugActiveProcess(dwProcessID);
printf("bDebugging = %d\n", bDebugging);
DWORD dwThreadID = GetProcessThreadID(dwProcessID);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
CONTEXT parentCtx;
parentCtx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (GetThreadContext(hThread, &parentCtx))
{
parentCtx.Dr0 = (DWORD)hpChangeBreakpoint;
parentCtx.Dr7 = 0x00000001;
std::cout << "GetThreadContext successful" << std::endl;
SetThreadContext(hThread, &parentCtx);
}
DEBUG_EVENT DebugEvent;
DWORD dbgFlag = DBG_CONTINUE;
DWORD *currentHpPointerAddress = nullptr;
DWORD *maxHpPointerAddress = nullptr;
BOOLEAN bQuit = FALSE;
while (!bQuit && WaitForDebugEvent(&DebugEvent, INFINITE))
{
dbgFlag = DBG_CONTINUE;
switch (DebugEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP:
if (DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress == (void*)hpChangeBreakpoint)
{
#define RESUME_FLAG 0x10000
CONTEXT childContext;
childContext.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(hThread, &childContext))
{
childContext.EFlags |= RESUME_FLAG;
SetThreadContext(hThread, &childContext);
std::cout << "current HP: " << childContext.Ecx << std::endl;
currentHpPointerAddress = (DWORD*)((char *)childContext.Edi + 0x8E0);
maxHpPointerAddress = (DWORD*)((char *)childContext.Edi + 0x8E4);
}
if (GetThreadContext(hThread, &parentCtx))
{
parentCtx.Dr0 = 0;
parentCtx.Dr7 = 0x400;
SetThreadContext(hThread, &parentCtx);
bQuit = TRUE;
}
}
else
dbgFlag = DBG_EXCEPTION_NOT_HANDLED;
break;
default:
dbgFlag = DBG_EXCEPTION_NOT_HANDLED;
}
break;
case LOAD_DLL_DEBUG_EVENT:
{
CloseHandle(DebugEvent.u.LoadDll.hFile);
break;
}
case CREATE_PROCESS_DEBUG_EVENT:
{
CloseHandle(DebugEvent.u.CreateProcessInfo.hFile);
break;
}
case EXIT_PROCESS_DEBUG_EVENT:
break;
default:
__nop();
}
if (!ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, dbgFlag))
{
break;
}
if (bQuit)
DebugActiveProcessStop(dwProcessID);
}
while (1)
{
WORD currentHP = 0;
WORD maxHP = 0;
if (
ReadProcessMemory(hProcess, currentHpPointerAddress, ¤tHP, sizeof(currentHP), NULL) == 0
|| ReadProcessMemory(hProcess, maxHpPointerAddress, &maxHP, sizeof(maxHP), NULL) == 0
)
{
printf("Failed to read memory: %u\n", GetLastError());
}
else {
std::cout << "HP: " << currentHP << " / " << maxHP << std::endl;
}
Sleep(1000);
}
system("pause>nul");
return 0;
}
When I run it, the game works fine until the breakpoint happens, when it does, i get infinite "breakpoint" cout's spam and when I debug it, this line:
if (DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress == (void*)hpChangeBreakpoint)
is always true, but the dwFirstChance flag is 1, so its always a new exception? The only thing that changes in this infinite loop is the hThread, is always different. I feel like im missing something because of my lack of knowledge, thus would appreciate any help or hints to right direction. thank you!
are you listen/know about Resume Flag (RF) ? you need set it for step over DrX brealpoint
so code must be next
#define RESUME_FLAG 0x10000
CONTEXT Context = {};
Context.ContextFlags = CONTEXT_CONTROL;// not need CONTEXT_FULL here;
if (GetThreadContext(hThread, &Context))
{
Context.EFlags |= RESUME_FLAG; // !!! this line is key point
SetThreadContext(hThread, &Context);
}
this will be work begin from win2003 or windows vista. unfortunately XP not let you set this flag in CONTEXT. so here you need remove Dr0 breakpoint for step over it ( or patch XP kernel - search for 0x003E0DD7 DWORD in ntoskrnl code and replace it to 0x003F0DD7 - this is Eflags mask - different in RESUME_FLAG )
also let some optimization advice - you not need call OpenThread every time when EXCEPTION_DEBUG_EVENT.
at first you already have this thread handle
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
simply not close it, after you call SetThreadContext
and exception can occur only in context of this thread, all other threads not affected by this.
at second you never close thread handle, opened in EXCEPTION_DEBUG_EVENT - so you already have resource leaks.
debugger got thread handles on CREATE_THREAD_DEBUG_EVENT and CREATE_PROCESS_DEBUG_EVENT and MUST close it (or just or usual maintain it and close on EXIT_THREAD_DEBUG_EVENT and EXIT_PROCESS_DEBUG_EVENT )
you not handle LOAD_DLL_DEBUG_EVENT and as result not close file handle.
your code have HUGE handle leaks !
SuspendThread / ResumeThread - for what ?! absolute senseless - thread (and all threads in process) already suspended in this point
struct CThread : LIST_ENTRY
{
HANDLE _hThread;
ULONG _dwThreadId;
CThread(HANDLE hThread, ULONG dwThreadId)
{
_hThread = hThread;
_dwThreadId = dwThreadId;
}
~CThread()
{
//CloseHandle(_hThread);// will be closed in ContinueDebugEvent
}
static CThread* get(ULONG dwThreadId, PLIST_ENTRY ThreadListHead, CThread* pHintThread)
{
if (pHintThread && pHintThread->_dwThreadId == dwThreadId)
{
return pHintThread;
}
PLIST_ENTRY entry = ThreadListHead;
while ((entry = entry->Flink) != ThreadListHead)
{
pHintThread = static_cast<CThread*>(entry);
if (pHintThread->_dwThreadId == dwThreadId)
{
return pHintThread;
}
}
return 0;//??
}
static void DeleteAll(PLIST_ENTRY ThreadListHead)
{
PLIST_ENTRY entry = ThreadListHead->Flink;
while (entry != ThreadListHead)
{
CThread* pThread = static_cast<CThread*>(entry);
entry = entry->Flink;
delete pThread;
}
}
};
void RunDebuggerLoop()
{
BOOL bQuit = FALSE;
LIST_ENTRY ThreadListHead = { &ThreadListHead, &ThreadListHead };
CThread* pThread = 0;
DEBUG_EVENT de;
BOOLEAN bFirst = TRUE;
while (!bQuit && WaitForDebugEvent(&de, INFINITE))
{
NTSTATUS status = DBG_CONTINUE;
switch(de.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
if (
!de.u.Exception.dwFirstChance
||
!(pThread = CThread::get(de.dwThreadId, &ThreadListHead, pThread))
)
{
bQuit = TRUE;
continue;
}
status = DBG_EXCEPTION_NOT_HANDLED;
switch (de.u.Exception.ExceptionRecord.ExceptionCode)
{
case STATUS_BREAKPOINT:
case STATUS_WX86_BREAKPOINT:
if (bFirst)
{
bFirst = FALSE;
status = DBG_CONTINUE;
}
break;
case STATUS_SINGLE_STEP:
case STATUS_WX86_SINGLE_STEP:
{
::CONTEXT ctx = {};
ctx.ContextFlags = CONTEXT_CONTROL;
if (GetThreadContext(pThread->_hThread, &ctx))
{
ctx.EFlags |= RESUME_FLAG;
SetThreadContext(pThread->_hThread, &ctx);
}
}
break;
case STATUS_ACCESS_VIOLATION:
if (de.u.Exception.ExceptionRecord.NumberParameters > 1)
{
ULONG_PTR ptr = de.u.Exception.ExceptionRecord.ExceptionInformation[1];
}
break;
}
break;
case CREATE_PROCESS_DEBUG_EVENT:
CloseHandle(de.u.CreateProcessInfo.hFile);
//CloseHandle(de.u.CreateProcessInfo.hProcess);// will be auto closed in ContinueDebugEvent
de.u.CreateThread.hThread = de.u.CreateProcessInfo.hThread;
case CREATE_THREAD_DEBUG_EVENT:
if (pThread = new CThread(de.u.CreateThread.hThread, de.dwThreadId))
{
InsertHeadList(&ThreadListHead, pThread);
}
break;
case EXIT_THREAD_DEBUG_EVENT:
if (pThread = CThread::get(de.dwThreadId, &ThreadListHead, pThread))
{
RemoveEntryList(pThread);
delete pThread;
pThread = 0;
}
break;
case LOAD_DLL_DEBUG_EVENT:
CloseHandle(de.u.LoadDll.hFile);
break;
case EXIT_PROCESS_DEBUG_EVENT:
bQuit = TRUE;
break;
case OUTPUT_DEBUG_STRING_EVENT:
case UNLOAD_DLL_DEBUG_EVENT:
__nop();
break;
default:
__nop();
}
if (!ContinueDebugEvent(de.dwProcessId, de.dwThreadId, status))
{
break;
}
}
CThread::DeleteAll(&ThreadListHead);
}
void Ep()
{
// tag by * in begin of CommandLine
PWSTR CommandLine = GetCommandLine();
if (!CommandLine || *CommandLine != '*')
{
// debugger case
WCHAR FileName[MAX_PATH];
if (ULONG n = GetModuleFileName(0, FileName, RTL_NUMBER_OF(FileName)))
{
if (n < MAX_PATH)
{
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
PWSTR newCommandLine = (PWSTR)alloca((wcslen(CommandLine) + 2)*sizeof(WCHAR));
*newCommandLine = '*';
wcscpy(newCommandLine + 1, CommandLine);
if (CreateProcessW(FileName, newCommandLine, 0, 0, 0, DEBUG_PROCESS, 0, 0, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
RunDebuggerLoop();
}
}
}
ExitProcess(0);
}
else
{
// main case
wcscpy(CommandLine, CommandLine + 1);
OutputDebugStringA("AAAAAA\n");
if (MessageBoxW(0, L"xxx", CommandLine, MB_YESNO) == IDYES)
{
OutputDebugStringW(L"WWWWWWWW\n");
}
ExitProcess(0);
}
}
Big thanks for the time you've spent answering me. I'm sorry if some of the questions are weird, but Im a JS dev and what I'm doing here is my hobby. What i know is that it feels like a different and way deeper world then my JS.. ;)
I did edit the code, also removed what you've mentioned is redundant. The suspend/resume of the thread was there because between them I had some memory modyfications, but based on what you said, that the thread is suspended at this point anyway, even if I would modify the memory, there's no need for them?
Going back to the subject, the infinite loop is still here. Ive added the RF flag, but I'm just starting to read through the articles on that so apart from just adding it, I also understand why. Meanwhile, would you be so kind to give me another hint on why it might still not be working?
Also, I've added LOAD_DLL_DEBUG_EVENT handling and I'm closing the handler straight away as I don't need to do anything else with that at this point(do i?). What I dont entirely get is to when excatly should I close the handlers received from CREATE_PROCESS and CREATE_THREAD debug event? I'm trying to wrap my mind of how the debugger works, its my 4th day with it so far, but as i see it, this is what happens:
WaitForDebugEvent receives a debug event, as long as its not mine, its being handled by ContinueDebugEvent with DBG_EXCEPTION_NOT_HANDLED, so its being passed back and the game handles it.
Finally WaitForDebugEvent receives my debug event, which is EXCEPTION_SINGLE_STEP, I do my stuff in there and then makes it continue with DBG_CONTINUE - that flags the exception as handled by me, and system just keeps going after it. Is that correct?
My actual code that still loops and prints "Breakpoint" in infinite loop:
#include "Header.h"
#include <iostream>
int main() {
hpChangeBreakpoint = 0x013FB279;
SetDebugPrivilege(TRUE);
DWORD dwProcessID = 0;
DWORD dwGame = 0;
printf("Looking for game process...\n");
while (dwProcessID == 0) {
dwProcessID = GetProcessID(L"PathOfExile.exe");
if (dwProcessID != 0)
dwGame = 1;
Sleep(100);
}
printf("dwProcessID = %p\n", dwProcessID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessID);
BOOL bDebugging = DebugActiveProcess(dwProcessID);
printf("bDebugging = %d\n", bDebugging);
DWORD dwThreadID = GetProcessThreadID(dwProcessID);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
CONTEXT context;
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if (GetThreadContext(hThread, &context))
{
context.Dr0 = hpChangeBreakpoint;
context.Dr7 = 0x00000001;
std::cout << "GetThreadContext successful" << std::endl;
SetThreadContext(hThread, &context);
}
DEBUG_EVENT DebugEvent;
BOOL bContinueDebugging = false;
for(;;)
{
WaitForDebugEvent(&DebugEvent, INFINITE);
switch (DebugEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP:
if (DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress == (void*)hpChangeBreakpoint)
{
#define RESUME_FLAG 0x10000
CONTEXT Context;
Context.ContextFlags = CONTEXT_CONTROL;
Context.EFlags |= RESUME_FLAG;
std::cout << "Breakpoint" << std::endl;
bContinueDebugging = true;
}
if (bContinueDebugging)
{
// DBG_CONTINUE to tell the program we have handled the exception
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_CONTINUE);
bContinueDebugging = false;
}
else // if the exception was not handled by our exception-handler, we want the program to handle it, so..
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
break;
default:
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
}
break;
case LOAD_DLL_DEBUG_EVENT:
{
std::cout << "load dll debug event" << std::endl;
CloseHandle(DebugEvent.u.LoadDll.hFile);
break;
}
default:
ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
}
}
system("pause>nul");
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am pretty new to C++ and I am making a trainer(Plants vs Zombies) I tried to make a trainer for that game before but it failed the memory writing didn't work so I tried another method but with this method it gives me a couple of errors:
54|error: invalid conversion from 'DWORD {aka long unsigned int}' to 'PDWORD
{aka long unsigned int*}' [-fpermissive]|
1780|error: initializing argument 2 of >'DWORDGetWindowThreadProcessId(HWND,PDWORD)' [-fpermissive]|
I just don't get it, but even more strange are these three:
62|error: expected '}' before 'else'|
70|error: 'else' without a previous 'if'|
76|error: 'else' without a previous 'if'|
I know what those mean but there is clearly a } before else. and there are if statements before the else
Here is the code:
/*
Plants vs Zombies Game of the year edition trainer
*/
#include <iostream>
#include <Windows.h>
#include <string>
#include <ctime>
DWORD FindDmaAddy(int PointerLevel, HANDLE hProcHandle, DWORD Offsets[],DWORD BaseAddress);
void WriteToMemory(HANDLE hProcHandle);
std::string GameName = "PlantsVsZombies";
LPCSTR LGameWindow = "Plants vs. Zombies";
std::string GameStatus;
bool IsGameAvail;
bool UpdateOnNextRun;
//Zon var.
bool SunStatus;
BYTE SunValue[] = {0xA3, 0X1C, 0X0, 0X0};
DWORD SunBaseAddress = {0x025A9E00};
DWORD SunOffsets[] = {0x5560, 0x768, 0x0};
//Geld var.
bool MoneyStatus;
BYTE MoneyValue[] = {0xA3, 0X1C, 0X0, 0X0};
DWORD MoneyBaseAddress = {0x02589E00};
DWORD MoneyOffsets[] = {0x28, 0x82C, 0x0};
int main()
{
HWND hGameWindow = NULL;
int timeSinceLastUpdate = clock();
int GameAvailTMR = clock();
int OnePressTMR = clock();
DWORD dwProcID = NULL;
HANDLE hProcHandle = NULL;
UpdateOnNextRun = true;
std::string sSunStatus = "UIT";
std::string sMoneyStatus = "UIT";
while(!GetAsyncKeyState(VK_NUMPAD0));
{
if(clock() - GameAvailTMR > 100);
{
GameAvailTMR = clock();
IsGameAvail = false;
hGameWindow = FindWindow(NULL, LGameWindow);
if(hGameWindow)
{
GetWindowThreadProcessId( hGameWindow, dwProcID);
if(dwProcID != 0)
{
hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
if(hProcHandle == INVALID_HANDLE_VALUE || hProcHandle == NULL);
{
GameStatus = "Plants vs. Zombies.exe kon niet worden geopend";
}
else
{
GameStatus = "Plants vs. Zombies.exe is geopend en klaar om gehackt te worden";
IsGameAvail = true;
system("color 0A");
}
}
}
else
{
GameStatus = "Kon het process ID niet vinden";
system("color 0C");
}
}
else
{
GameStatus = "Plants vs. Zombies is niet gevonden";
system("color 0C");
}
if(UpdateOnNextRun || clock() - timeSinceLastUpdate > 5000)
{
system("cls");
std::cout << "---------------------------------------------------------------------------" << std::endl;
std::cout << " Plants vs Zombies Trainer" << std::endl;
std::cout << "---------------------------------------------------------------------------" << std::endl << std::endl;
std::cout << "Game Status: " << GameStatus << std::endl << std::endl;
std::cout <<"[NUMPAD1] Oneindig Zon: " << sSunStatus << std::endl;
std::cout <<"[NUMPAD2] Oneindig Geld: " << sMoneyStatus << std::endl;
std::cout <<"[NUMPAD0] Sluit de trainer";
}
if(IsGameAvail)
{
if(GetAsyncKeyState(VK_NUMPAD1))
{
OnePressTMR = clock();
SunStatus = !SunStatus;
UpdateOnNextRun = true;
if(SunStatus)sSunStatus = "ON";
else sSunStatus = "OFF";
}
else if(GetAsyncKeyState(VK_NUMPAD2))
{
OnePressTMR = clock();
MoneyStatus = !MoneyStatus;
UpdateOnNextRun = true;
if(MoneyStatus)sMoneyStatus = "ON";
else sMoneyStatus = "OFF";
}
}
if(clock() - OnePressTMR > 400)
{
if(IsGameAvail)
{
//Zon
if(GetAsyncKeyState(VK_NUMPAD1))
{
OnePressTMR = clock ();
SunStatus = !SunStatus;
UpdateOnNextRun = true;
if(SunStatus)sSunStatus = "AAN";
else sSunStatus = "UIT";
}
//Geld
else if(GetAsyncKeyState(VK_NUMPAD2))
{
OnePressTMR = clock ();
MoneyStatus = !MoneyStatus;
UpdateOnNextRun = true;
if(MoneyStatus)sMoneyStatus = "AAN";
else sMoneyStatus = "UIT";
}
}
}
CloseHandle(hProcHandle);
CloseHandle(hGameWindow);
return ERROR_SUCCESS;
}
DWORD FindDmaAddy(int PointerLevel, HANDLE hProcHandle, DWORD Offsets[], DWORD BaseAddress)
{
DWORD pointer = BaseAddress;
DWORD pTemp;
DWORD pointerAddr;
for(int i = 0; i <PointerLevel; i++)
{
if(i == 0)
{
ReadProcessMemory(hProcHandle, (LPCVOID)pointer, &pTemp, sizeof(pTemp), NULL);
}
pointerAddr = pTemp + Offsets[i];
ReadProcessMemory(hProcHandle, (LPCVOID)pointerAddr, &pTemp, sizeof(pTemp), NULL);
}
}
void WriteToMemory(HANDLE hProcHandle)
{
DWORD AddressToWrite;
if(SunStatus)
{
AddressToWrite = FindDmaAddy(2, hProcHandle, SunOffsets, SunBaseAddress);
WriteProcessMemory(hProcHandle,(BYTE*)AddressToWrite, &SunValue, sizeof(SunValue), NULL);
}
if(MoneyStatus)
{
AddressToWrite = FindDmaAddy(2, hProcHandle, MoneyOffsets, MoneyBaseAddress);
WriteProcessMemory(hProcHandle,(BYTE*)AddressToWrite, &MoneyValue, sizeof(MoneyValue), NULL);
}
}
Thanks in advance
The compiler is generally right in its messages, and you should also read its warnings. You code is actually full of silly little mistakes.
if(clock() - GameAvailTMR > 100);
the ending ; closes the if here so the else will not be attached to it
GetWindowThreadProcessId( hGameWindow, dwProcID);
dwProcID is a DWORD when the function signature needs a LPDWORD, that is a DWORD *. Just write GetWindowThreadProcessId( hGameWindow, &dwProcID);
Don't forget, when you see an error on one line, also read the above one. Just fix all the errors and warning and come back here if you still have problems
I'd like to write a c++ program(windows console application) to print receipts from a server (via websocket) to a locally connected(via rs-232) receipt printer(NCR 7197 rev 1.0).
I got both the websocket connection and the serial handle operating and ready.
My problem is, that I can't find any example to guide me through the process of printing, or how to even begin. I mean, do I have to write some bytes or read any before I start passing the "document" to the printer, or do I need to write any config bytes, or anything.
If someone has any suggestions to where to start, or any example preferably in c++, I will be thankful.
I came across the solution that I developed way back than, while cleaning my old projects folder. Seeing the multiple hundred of views on this question, I wanted to post an answer. Here is my solution, but it might be outdated:
The function to connect to a device through a COM port:
// Serial port connection handle connect method
HANDLE connect_h(wchar_t* s_port, int s_flowcontrol, int s_baudrate, int s_bytesize, int s_stopbits, int s_parity) {
wchar_t* port = s_port;
std::wstring ws(port);
std::string port_w(ws.begin(), ws.end());
// Open serial port
HANDLE hSerial;
hSerial = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hSerial == INVALID_HANDLE_VALUE) {
if(GetLastError() == ERROR_FILE_NOT_FOUND) {
// Serial port does not exist. Inform user.
std::cout << "Error: Serial port does not exists. Port: " << std::endl;
}
// Some other error occurred. Inform user.
std::cout << "Error: Cannot connect to port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
// Do some basic settings
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if(!GetCommState(hSerial, &dcbSerialParams)) {
// Error getting state
std::cout << "Error: Cannot get port state. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
dcbSerialParams.BaudRate = s_baudrate;
dcbSerialParams.ByteSize = s_bytesize;
dcbSerialParams.StopBits = s_stopbits;
dcbSerialParams.Parity = s_parity;
// If flowcontrol set to XON/XOFF
if(s_flowcontrol == 1) {
dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.fOutX = true;
dcbSerialParams.fInX = true;
dcbSerialParams.XonChar = 0x11;
dcbSerialParams.XoffChar = 0x16;
}
if(!SetCommState(hSerial, &dcbSerialParams)) {
// error setting serial port state
std::cout << "Error: Cannot set port state. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
// Set timeouts
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts)) {
// Error occureed. Inform user
std::cout << "Error: Cannot set port timeouts. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
return hSerial;
}
Closing the serial port connection:
// Serial port connection handle close method
void close_h(const HANDLE &hSerial) {
CloseHandle(hSerial);
}
The function to print through the connected COM port:
// Printing recipe via serial port handle
std::string set_print(const HANDLE &hSerial, std::string &document) {
std::string result = "";
std::string printable = "";
// Format flags
bool _bold_flag = false;
bool _underline_flag = false;
bool _italic_flag = false;
// Process document for printing
for(int i = 0; i < (int)document.length(); ++i) {
if(document[i] == '\\') {
switch (document[i + 1]) {
// new line
case 'n':
printable.push_back((char)(0x0A));
i++;
break;
// underline format begin/end
case 'u':
if(!_underline_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x2D));
printable.push_back('1');
_underline_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x2D));
printable.push_back('0');
_underline_flag = false;
}
i++;
break;
// bold format begin/end
case 'b':
if (!_bold_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x47));
printable.push_back('1');
_bold_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x47));
printable.push_back('0');
_bold_flag = false;
}
i++;
break;
// italic format begin/end
case 'i':
if (!_italic_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x49));
printable.push_back('1');
_italic_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x49));
printable.push_back('0');
_italic_flag = false;
}
i++;
break;
// if not recognized
default:
printable.push_back(document[i]);
break;
}
}
else {
printable.push_back(document[i]);
}
}
// Additional push
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
// Add EOF bytes
printable.push_back((char)(0x03));
printable.push_back((char)(0x04));
// Add knife cut command
printable.push_back((char)(0x19));
printable.push_back((char)(0x1B));
printable.push_back((char)(0x76));
// Convert to hexadecimal
int* hex_print = new int[printable.length()];
for(int i = 0; i < (int)printable.length(); ++i) {
hex_print[i] = (int)printable[i];
}
// Print
for(int i = 0; i < (int)printable.length(); ++i) {
int rq[1] = { hex_print[i] };
DWORD rqBytesWritten = 0;
if(!WriteFile(hSerial, rq, 1, &rqBytesWritten, NULL)) {
// error occurred. Report to user.
std::cout << "Error: Can't write byte. written: " + rqBytesWritten << std::endl;
}
}
// return status
return result;
}
And a test main function, to demonstrate the usage of these functions:
// MAIN()
int main(int argc, char* argv[]) {
// Create connection on COM port 1
HANDLE sh_printer = connect_h(L"COM1", 0, 38400);
// Print a string povided in first argument
set_print(sh_printer, args[1]);
// Close the COM port connection
close_h(sh_printer);
return 0;
}
I hope I could be of any help to anyone, who tires to use this ancient way of printing a receipt. :)
I am trying to enable a secondary monitor in C++. What I have seems to try and change the display settings but nothing really happens, can anyone tell me where I am going wrong?
std::wstring devName( L"Intel(R) HD Graphics Family" );
std::wstring dispName( L"\\\\.\\DISPLAY3" );
DISPLAY_DEVICE theDisplay;
theDisplay.cb = sizeof(theDisplay);
DWORD dev = 0;
while(EnumDisplayDevices(0, dev, &theDisplay, 0))
{
if (devName.compare(theDisplay.DeviceString) == 0 && dispName.compare(theDisplay.DeviceName) == 0)
{
// found display adapter we're looking for
if (theDisplay.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
{
// Display is part of desktop, turn al other monitors off
cout << "Display is part of desktop\n";
}
else
{
// Display is off, turn it on
DEVMODE dm;
memset(&dm,0,sizeof(DEVMODE));
dm.dmSize = sizeof (DEVMODE);
dm.dmFields = DM_POSITION;
dm.dmPosition.x = 3361;
dm.dmPosition.y = 0;
dm.dmPelsWidth = 1920;
dm.dmPelsHeight = 1080;
LONG ret = ChangeDisplaySettingsEx (theDisplay.DeviceName, &dm, NULL, CDS_UPDATEREGISTRY, NULL);
if (ret != DISP_CHANGE_SUCCESSFUL)
{
cout << "failed";
}
}
}
dev++;
}
system ("pause");
return 0;