Basic Windows Programming question in VS2005 - windows

I created a win32 console application (without enable precompiled header option).
And now my source code as this, there is two compiler errors.
// AFormattingMsgBox.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include "stdafx.h"
//int _tmain(int argc, _TCHAR* argv[])
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
int cxScreen, cyScreen;
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
MessageBoxPrintf(TEXT("ScrnSize"), TEXT("The screen is %i pixels wide by %i pixels high."), cxScreen, cyScreen);
return 0;
}
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, int x, int y)
{
TCHAR szBuffer [1024];
va_list pArgList;
va_start(pArgList, szFormat);
_vsntprintf(szBuffer, sizeof(szBuffer) / sizeof(TCHAR),
szFormat, pArgList);
va_end(pArgList);
return MessageBox(NULL, szBuffer, szCaption, 0);
}
Compiler Errors.
error C3861: 'MessageBoxPrintf': identifier not found
error C2365: 'MessageBoxPrintf' : redefinition; previous definition was 'formerly
unknown identifier
How can I fix the errors. Thanks for your reading and replies.

Either put the function MessageBoxPrintf before the WinMain function or add a prototype before winMain. You add a prototype by entering the following line:
int CDECL MessageBoxPrintf(TCHAR * szCaption, TCHAR * szFormat, int x, int y);

Related

I cant print a number inside a formatted MessageBox

The following code does not work as it should. %i does not connect with its variable.
#include<Windows.h>
#include<stdio.h>
#include<tchar.h>
/* SCREENSIZE.C
This project contains the code that Programming Windows
book by Charles Petzold is using.
*/
int cdecl MessageBoxPrintfW(TCHAR *msgBoxTitle, TCHAR *msgBoxFormat, ...)
{
//define buffer
TCHAR msgBoxBuffer[1024];
//define iteration pointer
va_list argPtr;
//start iteration
va_start(argPtr, msgBoxFormat);
/*int _vsnwprintf_s(
wchar_t *const _Buffer,
const size_t _BufferCount,
const size_t _MaxCount,
const wchar_t *const _Format,
va_list _ArgList)
*/
_vsntprintf_s(msgBoxBuffer, sizeof(msgBoxBuffer) / sizeof(TCHAR), (sizeof(msgBoxBuffer) / sizeof(TCHAR)) - 1, msgBoxFormat, argPtr);
//end iteration
va_end(argPtr);
//Use return type to pass preconfigured MessageBox(0,"Text","Title",MB_OKCANCEL);
//Whe we use L before a string example: L"text" it is considered UNICODE format.
return(MessageBox(0, msgBoxFormat, msgBoxTitle, MB_OKCANCEL));
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR pCmdLine,
int iCmdShow)
{
int cxScreen, cyScreen;
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
MessageBoxPrintfW(TEXT ("SCREENSIZE"), TEXT("The screen is %i pixels wide by %i pixels high."), cxScreen, cyScreen);
return(0);
}
Why does this happen?
Below is the output that I get:
TCHAR msgBoxBuffer[1024];
_vsntprintf_s(msgBoxBuffer,...
...
return(MessageBox(0, msgBoxFormat, msgBoxTitle, MB_OKCANCEL));
Note that you are writting to msgBoxBuffer, but you never use msgBoxBuffer. So your message box doesn't change anything. Try the following instead:
int MessageBoxPrintfW(const TCHAR *msgBoxTitle, const TCHAR* msgBoxFormat, ...)
{
va_list args;
va_start(args, msgBoxFormat);
int len = _vsctprintf(msgBoxFormat, args) + 1; // add terminating '\0'
TCHAR *buf = new TCHAR[len];
_vstprintf_s(buf, len, msgBoxFormat, args);
int result = MessageBox(0, buf, msgBoxTitle, MB_OKCANCEL);
delete[]buf;
return result;
}
For C version use malloc(len * sizeof(TCHAR)) instead of new, and use free instead of delete[]

How to detour the main instance of a function?

I'm trying to detour ::DrawText() (and other draw text functions) for an application that has a lot of DLLs, some of which also use those functions.
I would have thought that if I detoured the main function using DetourFindFunction(), this would capture all cases from all functions in all DLLs, such that I could solve this question as there is text being displayed on the window.
Unfortunately, either CDHtmalDialog is somehow getting around the detour, or it is using some other function to draw the text on the window.
Could someone confirm that if I were to do this:
int (WINAPI *pDrawTextExW)(
_In_ HDC hdc,
_Inout_ LPWSTR lpchText,
_In_ int cchText,
_Inout_ LPRECT lprc,
_In_ UINT dwDTFormat,
_In_ LPDRAWTEXTPARAMS lpDTParams
) = 0;
int WINAPI MyDrawTextExW(
_In_ HDC hdc,
_Inout_ LPWSTR lpchText,
_In_ int cchText,
_Inout_ LPRECT lprc,
_In_ UINT dwDTFormat,
_In_ LPDRAWTEXTPARAMS lpDTParams
)
{
return (*pDrawTextExW)(hdc, lpchText, cchText, lprc, dwDTFormat, lpDTParams);
}
CCalcDrillDownDlg::CCalcDrillDownDlg(/* bunch of parameters */, CWnd *pParent)
: CDHtmlDialog(CCalcDrillDownDlg::IDD, 0, pParent)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
pDrawTextExW = decltype(pDrawTextExW)(DetourFindFunction("user32.dll", "DrawTextExW"));
DetourAttach(&(PVOID&)pDrawTextExW, MyDrawTextExW);
if (DetourTransactionCommit() == NO_ERROR)
OutputDebugString("DrawTextExW() detoured successfully\n");
for each of DrawTextA, DrawTextW, DrawTextExA, DrawTextExW that if CDHtmlDialog were to use one of these functions to draw the text with, it would get detoured? And perhaps someone would know how that class outputs text on the window's DC?
One funny thing that I did notice is that DrawTextExW() is getting detoured, trying to print the OK text on a button that is actually not displayed on the window. Not sure what that's about.
> cv32.dll!MyDrawTextExW(HDC__ * hdc=0x940111a2, wchar_t * lpchText=0x04925128, int cchText=2, tagRECT * lprc=0x012eb314, unsigned int dwDTFormat=1048613, tagDRAWTEXTPARAMS * lpDTParams=0x00000000) Line 4186 C++
uxtheme.dll!CTextDraw::DrawTextW() Unknown
uxtheme.dll!DrawThemeText() Unknown
comctl32.dll!Button_DrawThemed() Unknown
comctl32.dll!Button_DrawPush() Unknown
comctl32.dll!Button_PaintImpl() Unknown
comctl32.dll!Button_WndProc() Unknown
user32.dll!__InternalCallWinProc#20() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchClientMessage() Unknown
user32.dll!___fnDWORD#4() Unknown
ntdll.dll!_KiUserCallbackDispatcher#12() Unknown
user32.dll!_DispatchMessageA#4() Unknown
mfc120d.dll!AfxInternalPumpMessage() Line 181 C++
mfc120d.dll!CWinThread::PumpMessage() Line 900 C++
mfc120d.dll!AfxPumpMessage() Line 190 C++
mfc120d.dll!CWnd::RunModalLoop(unsigned long dwFlags=4) Line 4644 C++
mfc120d.dll!CWnd::CreateRunDlgIndirect(const DLGTEMPLATE * lpDialogTemplate=0x7216cc28, CWnd * pParentWnd=0x012ecd60, HINSTANCE__ * hInst=0x6f730000) Line 470 C++
mfc120d.dll!CDialog::DoModal() Line 633 C++

How to hide the console window in a Win32 project using Visual Studio 2010

I need to create an exe application with no console window or (any other window) during the start up of the application.
I tried the below for this:
Using Visual Studio 2010, created a Win32 Console Application as an Empty Project.
Added a header file "stdafx.h" to the project
Added a cpp file to the project and added the below code.
The project settings are visual stduio default.
#include "stdafx.h"
#include <windows.h>
#include "TlHelp32.h"
#include <iostream>
#include <string>
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
return 0;
}
The above code compiles good.
But if I change the Character Set to "Use Unicode Character Set", I am getting the following compilation error.
error C2731: 'WinMain' : function cannot be overloaded
I am building the application on a Windows 7 64 bit computer and Visual Studio Build platform as x64.
Thanks in advance for your help.
Yes, when you build with UNICODE in effect then the entrypoint takes a Unicode string for the command line argument. So that requires a different declaration:
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nShowCmd)
Or you can use #include <tchar.h> so it works either way, not much point to it these days:
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
Create Windows service instead console app.
In Visual Studio, create a new "EMPTY Project". Add a new source file named "main.cpp". Use the following template (assumes you want to build with Unicode):
/************
main.cpp
************/
#define UNICODE 1
#include <windows.h>
int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nShowCmd)
{
// Process Return Codes
const int SUCCESS=0, FAILURE=1;
return SUCCESS;
}

Segmentation fault when changing default gateway

I wrote a simple application on Qt4 that modifier network adapter parameters, for that I have a slot called setInterfaceParams, implemented as so:
DWORD WinNetInterface::setInterfaceParams(QString index, QString ip, QString netmask, QString gateway)
{
DWORD res = NULL;
HINSTANCE lib = (HINSTANCE) LoadLibrary((WCHAR *)"iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
//char *szGUID = (char *)index.toStdString().c_str();
QByteArray a = index.toLocal8Bit();
char *szGUID = a.data();
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
// Method 01
res = SetAdapterIpAddress(szGUID,
0,
inet_addr(ip.toStdString().c_str()),
inet_addr(netmask.toStdString().c_str()),
inet_addr(gateway.toStdString().c_str()));
// End of method 01
// Method 02
/*res = SetAdapterIpAddress("{422C5689-A17B-402D-A6A2-22CE13E857B5}",
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));*/
// End of method 02
return res;
}
When I click on button that connected to slot setInterfaceParams, I get segmentation fault. If I comment method01, nothing happen, the some thing happen when I use method02.
I tried this function on a simple c++ application and it is work fine, test on Windows XP SP3.
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <iostream>
typedef DWORD (WINAPI *_SetAdapterIpAddress )(char *szAdapterGUID,
DWORD dwDHCP,
DWORD dwIP,
DWORD dwMask,
DWORD dwGateway);
int main()
{
HINSTANCE lib = (HINSTANCE) LoadLibrary("iphlpapi.dll");
_SetAdapterIpAddress SetAdapterIpAddress = (_SetAdapterIpAddress) GetProcAddress(lib, "SetAdapterIpAddress");
PWSTR pszGUID = NULL;
char szGUID[] = "{422C5689-A17B-402D-A6A2-22CE13E857B5}";
DWORD dwSize = 0;
WideCharToMultiByte(CP_ACP, 0, pszGUID, -1, szGUID, sizeof(szGUID), NULL, NULL);
DWORD res = SetAdapterIpAddress(szGUID,
0,
inet_addr("192.168.1.10"),
inet_addr("255.255.255.0"),
inet_addr("192.168.1.1"));
std::cout << res;
return 0;
}
LoadLibrary((WCHAR *)"iphlpapi.dll");
That can't work, the literal string is in 8-bits, casting it without real conversion doesn't make it wide, so the dll loading probably failed.
You should use the TEXT or _T macro around most of the literal strings passed to WinAPI functions to make them regular or wide depending on the compilation options:
LoadLibrary(_T("iphlpapi.dll"));
which will translate to either LoadLibrary("iphlpapi.dll"); or LoadLibrary(L"iphlpapi.dll");.
Also you should always check the value returned by the LoadLibrary and GetProcAddress functions, which return NULL if the call is unsuccessful.

How to execute another program from a Visual C++ Application

I am doing a software project with Visual Studio Professional 2010.
In the form that I am making, I would like to put a link to open Microsoft Paint. How can I execute another application (MSPaint) from mine?
Call ShellExecute() passing open as the verb and mspaint.exe as the filename.
ShellExecute(
MainFormWindowHandle,
"open",
"mspaint.exe",
NULL,
NULL,
SW_SHOW
);
My contribution a complete example:
Go to Visual Studio, create a new Win32 C++ Project (not console), and paste the following code in the source file will appear:
// Win32Project1.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Win32Project1.h"
#include "shellapi.h"
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
ShellExecuteA ( NULL, "open",
"your.exe",
"your params",
"working dir", SW_SHOW);
return TRUE;
}
Myself I contribute the following code which can be used in Windows
#include <iostream>
#include<Windows.h>
using namespace std;
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD dwProcessId = 0;
DWORD dwThreadId = 0;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
bool bCreateProcess = NULL;
bCreateProcess = CreateProcess((Location of Paint path),0,0,0,0,0,0,0,&si, pi);
//Instead of 0 NULL can also be used
if (bCreateProcess == FALSE)
cout << " Creation Process Failed ";
else
cout << " Process Executedd ";
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}

Resources