Wine and Windows error code

mpfbk at free.fr mpfbk at free.fr
Tue Jan 14 09:38:23 CST 2003


Tests of win32 API returned error codes inside Wine

This subject has maybe been treated before, sorry if it has already been
discussed and closed.

Running the following simple and standard program, nothing special happens: the
windows opens itself, it can be closed with the close  button, and the message
box is displayed when the left mouse button is pressed inside the window.

/*
 * testbed1_ref.c
 * 
 */

#define STRICT
#include <windows.h>

const char g_szClassName[] = "testbed1WindowClass";

/* ============================================================ */

static void ErrorBox(LPCSTR msg)
{
    LPVOID error_msg;
    DWORD error_code;
    char error_buffer[256];

    error_code = GetLastError();
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		  NULL,
		  error_code,
		  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		  (LPTSTR) &error_msg,
		  0,
		  NULL 
		  );

    /* TBC: should be snprintf */
    sprintf(error_buffer, "%s: %d:%s", msg, error_code, error_msg);	  
    MessageBox(NULL, error_buffer, "Error!", MB_ICONEXCLAMATION | MB_OK);   
    LocalFree( error_msg );
}

/* ============================================================ */
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg) {
     case WM_LBUTTONDOWN:    
	{
	    char szFileName[MAX_PATH];
	    HINSTANCE hInstance;	   

	    if(IsDebuggerPresent()) {
		MessageBox(NULL, "Running under debugger control", "Debug!",
MB_ICONINFORMATION | MB_OK);		  
	    } else {
		OutputDebugString(TEXT("No debugger, but 'OutputDebugString' works, since you
see this (in DBWin32 for instance)"));
	    }
            hInstance = GetModuleHandle(NULL);
            GetModuleFileName(hInstance, szFileName, MAX_PATH);
            MessageBox(hwnd, szFileName, "This program is:", MB_OK |
MB_ICONINFORMATION);
        }	
	break;
     case WM_CLOSE:
	DestroyWindow(hwnd);
	break;
     case WM_DESTROY:
	PostQuitMessage(0);
	break;
     default:
	return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}



/* ============================================================ */

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
		   LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    /* Register the Window Class */
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;    
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc)) {	
	ErrorBox("Window Class Registration Failed!");
	return 0;
    }

    /* Create the Window */
    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
			  g_szClassName,
			  "The title of my window",
			  WS_OVERLAPPEDWINDOW,
			  CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
			  NULL, NULL, hInstance, NULL);    

    if(hwnd == NULL) {	 
	ErrorBox("Window Creation Failed");
	return 0;
    }
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    
    /* Run Message Loop */
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
	TranslateMessage(&Msg);
	DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

What is a little bit unusual is the ErrorBox function : often, a message box
simply reports the error and aborts the program. ErrorBox uses GetLastError()
and FormatMessage() to provide somewhat more information.

By accident, let's make an error, commenting out the RegisterClassEx() call :
#if 0
    if(!RegisterClassEx(&wc)) {	
	ErrorBox("Window Class Registration Failed!");
	return 0;
    }
#endif

Under Windows (tested with NT4 and XP), the displayed message (by ErrorBox) is:
== Window Creation Failed: 1407: Can't find window class ==
But, under wine (20021219), the displayed message is, unfortunately :
== Window Creation Failed: 0: No error ==
While looking inside the wine sources, it appears that no error code is set in
the functions 'CreateWindowExA' in windows/win.c file when the window's class is
not found : an error message is printed and 0 is returned. The following adds
the appropriate error code in function CreateWindowExA :
around line 1291 and 1301:
SetLastError(ERROR_CANNOT_FIND_WND_CLASS);
before the return 0;

Questions : does it have any interest for wine to add these error codes ? If
yes, according to DLL separation, is it allowed to call SetLastError() in any
context ? Should I submit a patch ? Any other feedback ?



More information about the wine-devel mailing list