How does ShowWindow report failure? - windows

Reading the documentation it looks like the ShowWindow function has no notion of failure. This surprises me since it seems that pretty much any non-trivial code can fail.
The window handle might be invalid. Clearly, that's a contact violation committed by the caller but is this case simply "undefined" or "don't care", then?
I wonder if SetLastError is supported.

While ShowWindow() indeed has no notion of error, we can use SetWindowPos() as an alternative that is documented to support GetLastError().
In the following I provide an example that shows how to wrap SetWindowPos() into a function to bridge the gap between C-style error reporting and the C++ way of doing it by throwing and handling an exception.
Example:
#include <windows.h>
#include <iostream>
#include <sstream>
#include <system_error>
// Show or hide the given window by calling SetWindowPos().
//
// \exception Reports any error by throwing std::sytem_error exception.
void MyShowWindow( HWND hwnd, bool show ) {
DWORD flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER;
if( show )
flags |= SWP_SHOWWINDOW;
else
flags |= SWP_HIDEWINDOW;
if( !::SetWindowPos( hwnd, nullptr, 0, 0, 0, 0, flags ) ) {
// NOTE: Call GetLastError() IMMEDIATELY when a function's return value indicates
// failure and it is documented that said function supports GetLastError().
// ANY other code (be it your own or library code) before the next line must be
// avoided as it may invalidate the last error value.
DWORD err = ::GetLastError();
std::ostringstream msg;
msg << "Could not change visibility of window (HWND 0x" << hwnd << ")";
throw std::system_error( static_cast<int>( err ), std::system_category(), msg.str() );
}
}
Usage:
When using the wrapper function MyShowWindow() you must make sure to catch the exceptions thrown by it. The following example shows how to do that.
int main(){
try{
// Passing an invalid handle to MyShowWindow() will throw
// std::system_error exception. There may be other reasons for the
// function to fail, for instance if you pass the window handle of
// another process to which you don't have access as an argument
// to the function.
HWND anInvalidHandle = 0;
MyShowWindow( anInvalidHandle, true );
}
catch( std::system_error& e ){
// Catch the exception thrown by MyShowWindow() and report all
// available error details.
// e.code() outputs the error code retrieved via GetLastError().
std::cout << "Error: " << e.what() << std::endl
<< "Error code: " << e.code() << std::endl;
}
return 0;
}
Output:
Error: Could not change visibility of window (HWND 0x00000000): Ung³ltiges Fensterhandle
Error code: system:1400
The message says "invalid window handle", the error code corresponds to ERROR_INVALID_WINDOW_HANDLE.
Note:
Although the provided MyShowWindow() function only supports SW_HIDE and SW_SHOW functionality of ShowWindow, the remaining functionality could propably be provided by using additional SetWindowPos flags (e. g. SW_SHOWNA maps to SWP_SHOWWINDOW | SWP_NOACTIVATE) or calling other Windows API functions that provide this functionality and are documented to support GetLastError().

ShowWindowAsync while asynchronous in nature, it does however tell you if the operation was started successfully or not. Depending on what you are doing, it might be a usable alternative.

ShowWindow does not have any error-awareness. If the window provided does not exist (or is not accessible), it just returns false.
ShowWindow in fact does not do much more than sending a WM_SHOW message to the targeted window. Because of the nature of the windows message queue, ShowWindow has no knowledge about its completion status. Although, as pointed out in the comments, WM_SHOW is handled synchronously, the message queue itself has no built-in error reporting mechanism aside from sending error messages back to the sender.
[edit]
It seems that GetLastError reports an invalid window handle when trying to access a non-existing window. To me, this is an unknown behaviour as normally a return value should indicate whether to use GetLastError or not. However, this can be easily avoided by testing for the window manually in advance (see: IsWindow)

Related

Weird case of AccessViolation while using overlapped IO in Windows

I've been experimenting with Overlapped IO feature of Win32 API, namely ReadFileEx and WriteFileEx functions.
Here is a simplest example:
#include <iostream>
#include <string>
#include <Windows.h>
const DWORD blockSize = 512;
char buffer[blockSize];
bool done = false;
OVERLAPPED overlapped;
void Completion(DWORD error, DWORD read, LPOVERLAPPED overlapped) {
}
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring fileName;
std::wcout << "Enter file name: ";
std::getline(std::wcin, fileName);
HANDLE file = CreateFile(
fileName.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (file == INVALID_HANDLE_VALUE) {
std::wcout << "Error while opening file: " << GetLastError() << std::endl;
std::cin.get();
return -1;
}
overlapped.Offset = overlapped.OffsetHigh = 0;
ReadFileEx(file, buffer, blockSize, &overlapped, (LPOVERLAPPED_COMPLETION_ROUTINE) &Completion);
while (!done)
SleepEx(1000, TRUE);
return 0;
}
As you can see, I'm starting overlapped reading with ReadFileEx and waiting for it to finish using SleepEx. Although Completion has empty body and the program should hang forever after reading first block, it does something completely different. In fact, it raises AccessViolation with code 0xC0000005 on the first call to SleepEx. This happens on Windows machines with Win 7 and Win Vista I've tried, including fresh 64 bit virtual machine with Windows 7. But, curiously, it does not fail on one Windows 8.1 machine and runs just as expected. This was compiled with Visual Studio 2010, but I don't think it matters.
I can not understand what have I done wrong, so if anyone knows the answer, please help me.
The callback must be of the following form, as stated clearly in the documentation:
VOID CALLBACK FileIOCompletionRoutine(
_In_    DWORD        dwErrorCode,
_In_    DWORD        dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
);
Your function has the wrong calling convention. Your cast does not change that. It is simply a way for you to stop the compiler rejecting your ill-formed program. Don't lie to the compiler. Correct the function declaration by adding the CALLBACK calling convention.

Easiest way to pop up a progress bar dialog from C++ dll (windows)

I am writing a dll which is a COM wrapper for another dll (the inner dll) without COM support. The inner dll performs a lengthy computation and lets the outer dll know how progress is going via a callback function. The outer dll just makes the functions visible over COM.
However, I need the outer dll to pop up a progress bar dialog (the COM client I'm serving can't do this itself for various reasons). So how do I go about doing that? All examples I have seen so far revolve around Win32 apps which have a WinMain entry point; what can be done if we're already in a dll call when the dialog is needed?
I'm new to windows GUI programming, so quite out of my depth here. The existing code is included below - specific suggestions on what to call where would be appreciated. I'm guessing I may need to fire off a second thread to refresh the progress dialog.
Inner dll .h file (for implicit linking):
#define INNER_API extern "C" __declspec(dllimport)
//create calculation, passing callbacks for warning messages and progress bar
INNER_API Calculation* __stdcall calc_create(...blah...,
int (__cdecl *set_progressor_callback)(long),
int (__cdecl *print_warning_callback)(const char*));
INNER_API void __stdcall calc_run(Calculation *c);
Then in the outer dll, the com wrapper, ComWrapperObject.cpp:
int my_progressor_callback(long progress)
{
//set progressor to equal progress, but how?
return 0;
}
STDMETHODIMP ComWrapperObject::do_calculation()
{
//fire up progress bar and message window here, but how?
Calculation *calc = calc_create(...blah..., &my_progressor_callback);
calc_run(calc);
//wait for user to dismiss message window, but how?
return S_OK;
}
I'm posting a new answer which is more relevant to your updated question (and in order to be eligible for the bounty). Consider first this minimal source for a regular executable which contains a progress bar:
#include <Windows.h>
#include <CommCtrl.h>
#pragma comment(lib, "Comctl32.lib")
#include "resource.h"
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define PROGRESSBAR_TIMER_ID 1
/*
* This callback is invoked each time the main window receives a message.
*/
INT_PTR CALLBACK DialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_INITDIALOG: {
/*
* Fire a timer event each second.
*/
SetTimer(hwndDlg, PROGRESSBAR_TIMER_ID, 1000, NULL);
break;
}
case WM_TIMER: {
/*
* Catch the timer event that is fired each second. Increment the progress
* bar by 10% each time.
*/
HWND hwndProgressBar = GetDlgItem(hwndDlg, IDC_PROGRESS1);
UINT iPos = SendMessage(hwndProgressBar, PBM_GETPOS, 0, 0);
/*
* If the position is already full then kill the timer. Else increment the
* progress bar.
*/
if(iPos >= 100) {
KillTimer(hwndDlg, PROGRESSBAR_TIMER_ID);
} else {
SendMessage(hwndProgressBar, PBM_SETPOS, iPos + 10, 0);
}
break;
}
case WM_CLOSE:
EndDialog(hwndDlg, 0);
break;
default:
return FALSE;
}
return TRUE;
}
BOOL LaunchGUI(HINSTANCE hInstance)
{
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogFunc) == 0;
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
/*
* Initialise the common controls DLL.
*/
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(iccex);
iccex.dwICC = ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES;
if(!InitCommonControlsEx(&iccex)) {
MessageBox(NULL, L"Problem initialising common controls DLL.", NULL, MB_OK);
return -1;
}
/*
* Launches the main GUI window.
*/
LaunchGUI(hInstance);
return ERROR_SUCCESS;
}
If you like, I can post the relevant .rc resource file for this program although the code is mostly for you to gain the correct conceptual understanding. So to quickly summarise, this program:
Contains a single dialog containing a single progress bar
Sets a timer to fire each second
Each time the timer fires, the timer message triggers the progress bar to be updated
Graphically, it looks like this:
Your question is how to increment this bar from a DLL instead. What you need to do is to allow some way for the DLL to communicate with the window containing the progress bar. I'm not quite sure how you are loading the DLL, but this is the approach I would take assuming it is done through DLL injection:
Load/inject the DLL into the target
Have the DLL export some initialisation routine allowing it to receive information about the injector/client process.
Use GetProcAddress and CreateRemoteThread from the client to invoke this initialisation routine.
In the DLL, use the received information to get the HWND of the client.
Concretely, the intialisation routine would look like this:
HWND hwndClient = NULL;
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if(dwPID == lParam) {
hwndClient = hwnd;
}
}
/*
* This code assumes the client has only one window. Given a PID, it populates
* a global to hold the window handle associated with the PID.
*/
DWORD WINAPI ReceiveClientPID(LPVOID dwPID)
{
EnumWindows(EnumProc, (LPARAM)dwPID);
}
The client code might be something like this:
/*
* Depending on your method of injection, you should have a handle to the
* target process as well as a HMODULE of the injected DLL.
*/
void InitDLL(HANDLE hProcess, HMODULE hModule)
{
FARPROC lpInit = GetProcAddress(hModule, "ReceiveClientPID");
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL,
(LPTHREAD_START_ROUTINE)lpInit, (LPVOID)GetCurrentProcessId(), NULL, NULL);
if(hThread == NULL) {
MessageBox(NULL, L"Problem calling init routine in DLL", NULL, MB_OK);
} else {
CloseHandle(hThread);
}
}
So now you have the HWND of the client in the DLL and hence a way for you to do the communication. You can then specify a custom message in the client to change the progress bar:
/*
* The new progress position can be passed in wParam.
*/
#define WM_UPDATE_PROGRESS_BAR (WM_APP + 1)
Also add the corresponding case in the DialogFunc (we can remove the WM_TIMER code now because that was only there to demonstrate how to interact with progress bars):
case WM_UPDATE_PROGRESS_BAR:
SendMessage(GetDlgItem(hwndDlg, IDC_PROGRESS1), PBM_SETPOS, wParam, 0);
break;
And now to trigger changes in the progress bar of the client, the DLL simply has to do:
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, ..., 0);
Note that WM_UPDATE_PROGRESS_BAR needs to be redefined in the DLL as well.
To fit this all in with your current code:
/*
* Assumed progress is between 0 and 100. Otherwise it has to be
* normalised so this is the case (or the range of the progress bar
* in the client has to be changed).
*/
int my_progressor_callback(long progress)
{
SendMessage(hwndClient, WM_UPDATE_PROGRESS_BAR, progress, 0);
return 0;
}
Since you state that the DLL has no GUI and the client handles all the user interaction, why don't you send the progress information to the client instead and have it displayed there?
If you want to display the dialog in the DLL, you do so in exactly the same way as you would within a regular executable. There is absolutely no difference. If you want the DLL to continue working while it updates the progress bar, you can just kick off a new thread with CreateThread.
If you show some code, we'll be able to help you more directly.

Detecting to which process a MessageBox belongs

Is it possible to find out to which process a MessageBox belongs? If yes, how?
You want to use GetWindowThreadProcessId. Here is an example.
#include <windows.h>
static const TCHAR g_cszClass = TEXT("#32770"); // dialog box class
// returned handle must be closed with CloseHandle() when no longer used
HANDLE GetMessageBoxProcess(__in_z LPCTSTR lpcszTitle, __in DWORD dwAccess)
{
HWND hWnd;
DWORD dwProcessId = 0;
HANDLE hRET;
hWnd = FindWindow(g_cszClass, lpcszTitle);
if (hWnd != NULL)
{
GetWindowThreadProcessId(hWnd, &dwProcessId);
if (dwProcessId != 0)
hRET = OpenProcess(dwAccess, FALSE, dwProcessId);
}
return hRET;
}
Not sure why you'd want the process though. Reasons I can think of:
terminating the message box completely
detecting a process
detecting a certain message box
all of which have superior & more optimal alternative solutions.
Another answer gives the programmatic solution. If this is a one-off thing for debugging, you can choose the window with Spy++, get the process ID from the properties window, and then look up the process in Task Manager.

C++ - Window Message loop is freezing

I have this class here that I made based on another one I had. It is supposed to handle the whole creating windows and stuff, but it seems to be getting into a hang now. The older version used to work fine, I don't know WHAT I may have forgotten to add to this one that might be causing it to hang like this.
This is the message loop:
int Window::HandleMessages()
{
while(GetMessage(&this->windat.msgs, NULL, 0, 0))
{
TranslateMessage(&this->windat.msgs);
DispatchMessage(&this->windat.msgs);
}
return this->windat.msgs.wParam;
}
Pretty basic stuff, I don't know why, but it will simply hang... When I run the program, it'll just show me an empty prompt window, and by testing, I got it to show a message box if I used it before the while loop, but inside it doesn't work. I've been trying to compare both this class and the older one and haven't figured out what might be wrong with this. Could anyone tell me what could possibly trigger this behaviour?
Thanks
OK, now this left me pretty confused. By messing around with GetLastError, it seems that it is returning error 2 (file not found) ANYWHERE I put it, even if right at the start of the Main, before I instantiate my Window class. If I call GetLastError anytime after CreateWindowEx, it'll return an error like 1047 or something, about class not found or something. HWND becomes NULL too
Here is the code for the main.cpp:
#include "SimpWin/SimpWin.h"
#include <stdio.h>
// Make the class name into a global variable
char szClassName[] = "WindowsApp";
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
sprintf((char*)lpDisplayBuf,
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
ErrorExit(TEXT("CreateWindowEx"));
Window* win = Window::CreateWindowClass(hThisInstance, szClassName, WindowProcedure);
if(!win->Register())
{
return 0;
}
win->Show(nFunsterStil);
int res = win->HandleMessages();
delete win;
return res;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc (hwnd, message, wParam, lParam);
}
This here, is the code for the Window::Register function:
int Window::Register()
{
if(this->windat.wincl.hIcon == NULL)
{
this->windat.wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
}
if(this->windat.wincl.hIconSm == NULL)
{
this->windat.wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
}
if(!RegisterClassEx(&this->windat.wincl))
{
return 0;
}
this->windat.hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
(char*) this->windat.sName, /* Classname */
(char*) this->windat.sTitle, /* Title Text */
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
this->windat.cDimension.width, /* The programs width */
this->windat.cDimension.height, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
this->windat.hInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
return 1;
}
I'm lost here, I don't know why the eff this is going on... :/
Use PeekMessage instead of GetMessage.
Check the return value to GetMessage() - your while loop won't exit if there are errors. It should look like this:
while (GetMessage(&this->windat.msgs, NULL, 0, 0) > 0)
{
...
}
Well, I finally got it working! :D
It actually had to do with a completely unrelated class I had here. It is a String class (which descended from Array) which I made, and the copy function had a bug, it would copy the character array I passed to it, but would not update the length field of the class...
That copy function would be called whenever I had to set the class to a value through operator=. The length is required for the operator char* to convert the class to c-format string. I'd use that cast when passing the ClassName and Title values to CreateWindowEx, and it would return me an array of 0 chars, and that's where hell happened.
Now I fixed that lib up, and it's working fine now. Thanks :D
Even though it's pretty old... from MSDN on GetMessage:
Unlike GetMessage, the PeekMessage function does not wait for a message to be posted before returning.
That is, GetMessage waits for next message to become available. You treat this wait in progress as a freeze, supposedly because you did not actually have the intention to wait for messages.
Note that you can attach debugger at the time of supposed freeze, pause the execution and inspect the call stacks of the threads. Once you find your thread and its call stack and its GetMessage in progress on the stack - you isolate the problem well enough to know where to read on documented behavior.

How to handle seg faults under Windows?

How can a Windows application handle segmentation faults? By 'handle' I mean intercept them and perhaps output a descriptive message. Also, the ability to recover from them would be nice too, but I assume that is too complicated.
Let them crash and let the Windows Error Reporting handle it - under Vista+, you should also consider registering with Restart Manager (http://msdn.microsoft.com/en-us/library/aa373347(VS.85).aspx), so that you have a chance to save out the user's work and restart the application (like what Word/Excel/etc.. does)
Use SEH for early exception handling,
and use SetUnhandledExceptionFilter to show a descriptive message.
If you add the /EHa compiler argument then try {} catch(...) will catch all exceptions for you, including SEH exceptions.
You can also use __try {} __except {} which gives you more flexibility on what to do when an exception is caught. putting an __try {} __except {} on your entire main() function is somewhat equivalent to using SetUnhandeledExceptionFilter().
That being said, you should also use the proper terminology: "seg-fault" is a UNIX term. There are no segmentation faults on Windows. On Windows they are called "Access Violation Exceptions"
C++ self-contained example on how to use SetUnhandledExceptionFilter, triggering a write fault and displaying a nice error message:
#include <windows.h>
#include <sstream>
LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
std::stringstream s;
s << "Fatal: Unhandled exception 0x" << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode
<< std::endl;
MessageBoxA(NULL, s.str().c_str(), "my application", MB_OK | MB_ICONSTOP);
exit(1);
return EXCEPTION_CONTINUE_SEARCH;
}
int main()
{
SetUnhandledExceptionFilter(TopLevelExceptionHandler);
int *v=0;
v[12] = 0; // should trigger the fault
return 0;
}
Tested successfully with g++ (and should work OK with MSVC++ as well)
What you want to do here depends on what sort of faults you are concerned with. If you have sloppy code that is prone to more or less random General Protection Violations, then #Paul Betts answer is what you need.
If you have code that has a good reason to deference bad pointers, and you want to recover, start from #whunmr's suggestion about SEH. You can handle and indeed recover, if you have clear enough control of your code to know exactly what state it is in at the point of the fault and how to go about recovering.
Similar to Jean-François Fabre solution, but with Posix code in MinGW-w64. But note that the program must exit - it can't recover from the SIGSEGV and continue.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sigHandler(int s)
{
printf("signal %d\n", s);
exit(1);
}
int main()
{
signal(SIGSEGV, sigHandler);
int *v=0;
*v = 0; // trigger the fault
return 0;
}

Resources