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 ?
mpfbk@free.fr wrote:
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
Sounds like a good bug.
While the manual test you wrote looks useful for exploring, could you please convert it to a compliance test and send it in as a patch before you fix the bug? - Dan