Last active
July 24, 2019 08:44
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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