Skip to content

Instantly share code, notes, and snippets.

@m13253
Last active July 24, 2019 08:44
Show Gist options
  • Save m13253/092b94c7bd526a9a4e57 to your computer and use it in GitHub Desktop.
Save m13253/092b94c7bd526a9a4e57 to your computer and use it in GitHub Desktop.
The program that crashes Wine 1.7.42 https://bugs.winehq.org/show_bug.cgi?id=38598
// Compile with:
// i686-w64-mingw32-gcc -g -mwindows -o badwine.exe badwine.c
#include <assert.h>
#include <stdint.h>
#include <windows.h>
HINSTANCE g_hInstance;
HWND g_hWnd;
HDC screen_dc, window_dc, buffer_dc;
HBITMAP dib_handle;
uint32_t *dib_buffer;
uint32_t top, left, right, bottom;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int main(void) {
g_hInstance = GetModuleHandleW(NULL);
WNDCLASSEXW wnd_class;
wnd_class.cbSize = sizeof wnd_class;
wnd_class.style = CS_HREDRAW | CS_VREDRAW;
wnd_class.lpfnWndProc = WndProc;
wnd_class.cbClsExtra = 0;
wnd_class.cbWndExtra = 0;
wnd_class.hInstance = g_hInstance;
wnd_class.hIcon = (HICON) LoadImageW(NULL, (LPCWSTR) IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
wnd_class.hCursor = (HCURSOR) LoadImageW(NULL, (LPCWSTR) IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
wnd_class.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wnd_class.lpszMenuName = NULL;
wnd_class.lpszClassName = L"com.starbrilliant.badwine";
wnd_class.hIconSm = NULL;
ATOM wnd_class_atom = RegisterClassExW(&wnd_class);
assert(wnd_class_atom);
CreateWindowExW(
WS_EX_LAYERED | WS_EX_TOPMOST,
(LPCWSTR) (intptr_t) wnd_class_atom,
L"Bad Wine Test",
WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
g_hInstance,
NULL
);
assert(g_hWnd);
MSG message;
while(GetMessageW(&message, NULL, 0, 0)) {
TranslateMessage(&message);
DispatchMessageW(&message);
}
DestroyWindow(g_hWnd);
ReleaseDC(NULL, screen_dc);
ReleaseDC(g_hWnd, window_dc);
DeleteDC(buffer_dc);
DeleteObject(dib_handle);
return 0;
}
void create_buffer(void) {
HMONITOR monitor = MonitorFromWindow(g_hWnd, MONITOR_DEFAULTTOPRIMARY);
assert(monitor);
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof monitor_info;
BOOL res_GetMonitorInfo = GetMonitorInfoW(monitor, &monitor_info);
assert(res_GetMonitorInfo);
top = monitor_info.rcWork.top;
left = monitor_info.rcWork.right - 480;
//left = monitor_info.rcWork.right - 240; // NOTE: Change window size may affect the crashing X11 opcode
right = monitor_info.rcWork.right;
bottom = monitor_info.rcWork.bottom;
assert(right >= left && bottom >= top);
screen_dc = GetDC(NULL);
assert(screen_dc);
assert(g_hWnd);
window_dc = GetDC(g_hWnd);
assert(window_dc);
buffer_dc = CreateCompatibleDC(screen_dc);
assert(buffer_dc);
dib_buffer = NULL;
BITMAPINFO bitmap_info;
bitmap_info.bmiHeader.biSize = sizeof bitmap_info.bmiHeader;
bitmap_info.bmiHeader.biWidth = right-left;
bitmap_info.bmiHeader.biHeight = bottom-top;
bitmap_info.bmiHeader.biPlanes = 1;
bitmap_info.bmiHeader.biBitCount = 32;
bitmap_info.bmiHeader.biCompression = BI_RGB;
bitmap_info.bmiHeader.biSizeImage = 0;
bitmap_info.bmiHeader.biXPelsPerMeter = 96;
bitmap_info.bmiHeader.biYPelsPerMeter = 96;
bitmap_info.bmiHeader.biClrUsed = 0;
bitmap_info.bmiHeader.biClrImportant = 0;
dib_handle = CreateDIBSection(screen_dc, &bitmap_info, DIB_RGB_COLORS, (void **) &dib_buffer, NULL, 0);
assert(dib_handle);
SelectObject(buffer_dc, dib_handle);
}
void paint_frame(void) {
uint32_t width = right-left;
uint32_t height = bottom-top;
uint32_t i, j;
uint32_t *bitmap = malloc(width * height * sizeof (uint32_t));
assert(bitmap);
for(i = 0; i < height; i++)
for(j = 0; j < width; j++) {
switch((i & 1) | (j & 1) << 1) {
case 0:
bitmap[i*width + j] = 0xffffffff;
break;
case 1:
bitmap[i*width + j] = 0x00000000;
break;
case 2:
bitmap[i*width + j] = 0xff000000;
break;
case 3:
bitmap[i*width + j] = 0x8066ccff;
break;
}
}
/* Windows DIB requires bottom-to-top, alpha-premultiplied data */
for(i = 0; i < height; i++)
for(j = 0; j < width; j++) {
uint8_t alpha = (uint8_t) (bitmap[i*width + j] >> 24);
uint32_t red = ((bitmap[i*width + j] & 0xff0000) * alpha / 255) & 0xff0000;
uint32_t green = ((bitmap[i*width + j] & 0xff00) * alpha / 255) & 0xff00;
uint32_t blue = ((bitmap[i*width + j] & 0xff) * alpha / 255) & 0xff;
dib_buffer[(height-i-1)*width + j] = (((uint32_t) alpha) << 24) | red | green | blue;
}
free(bitmap);
POINT window_pos;
window_pos.x = left;
window_pos.y = top;
SIZE window_size;
window_size.cx = right-left;
window_size.cy = bottom-top;
POINT buffer_pos;
buffer_pos.x = 0;
buffer_pos.y = 0;
BLENDFUNCTION blend_function;
blend_function.BlendOp = AC_SRC_OVER;
blend_function.BlendFlags = 0;
blend_function.SourceConstantAlpha = 255; // Set the SourceConstantAlpha value to 255 (opaque) when you only want to use per-pixel alpha values. --MSDN
blend_function.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(g_hWnd, window_dc, &window_pos, &window_size, buffer_dc, &buffer_pos, 0, &blend_function, ULW_ALPHA);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
g_hWnd = hWnd;
create_buffer();
ShowWindow(hWnd, SW_SHOW);
paint_frame();
break;
}
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment