http://bugs.winehq.org/show_bug.cgi?id=30266
Bug #: 30266 Summary: Cygnus Fractal eXtreme crashes after trial dialog (expects gdi32 GetDIBits() returning number of scan lines when bits parameter is NULL) Product: Wine Version: 1.5.0 Platform: x86 OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: gdi32 AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net Classification: Unclassified
Hello,
I sometimes peek into Winehq forum to look for interesting bugs :-)
http://forum.winehq.org/viewtopic.php?t=15117 (no answer)
--- quote --- i cannot seem to get this app to run properly in wine.
Bruce, who is the programmer of it, told me he would be happy to make whatever changes are necessary to make it work with wine, so if it's something on his end, could somebody on the team reach out to him and help him get it going?
his website is:
I love fractals, and want to take full advantage of my i7 on my imac and would really love to use his software but i absolutely will not go running windows to do so... --- quote ---
Download: ftp://ftp.cygnus-software.com/pub/fxsetup.msi
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/Cygnus Software/Fractal eXtreme 32-bit
$ WINEDEBUG=+tid,+seh,+relay,+snoop,+bitmap wine ./FractalX.exe >> log.txt 2>&1 --- snip ---
Trace log reveals:
--- snip --- ... 0024:Call KERNEL32.CreateFileA(0032d3b8 "C:\Program Files\Cygnus Software\Fractal eXtreme 32-bit\Plugins\Mandelbrot.dll",80000000,00000001,00000000,00000003,00000080,00000000) ret=0044ebc4 0024:Ret KERNEL32.CreateFileA() retval=000001c8 ret=0044ebc4 0024:Call KERNEL32.CreateFileA(0032cfd0 "C:\users\focht\My Documents\Fractal eXtreme\plugin_stamps\Mandelbrot_Mandelbrot.bmp",80000000,00000001,00000000,00000003,00000080,00000000) ret=0044ebde 0024:Ret KERNEL32.CreateFileA() retval=ffffffff ret=0044ebde 0024:Call KERNEL32.CloseHandle(000001c8) ret=0044ec2c 0024:Ret KERNEL32.CloseHandle() retval=00000001 ret=0044ec2c 0024:CALL MSVCR100.memset() ret=004529bd 0024:RET MSVCR100.memset() retval=00557be0 ret=004529bd 0024:Call gdi32.CreateDCA(004b80f8 "Display",00000000,00000000,00000000) ret=00452a23 0024:Ret gdi32.CreateDCA() retval=0000119c ret=00452a23 0024:Call gdi32.CreateDIBSection(0000119c,00557be0,00000000,00557bd0,00000000,00000000) ret=00452a45 0024:trace:bitmap:CreateDIBSection format (110,110), planes 1, bpp 8, BI_RGB, size 12320 RGB 0024:Ret gdi32.CreateDIBSection() retval=000011a0 ret=00452a45 0024:Call gdi32.CreateCompatibleDC(0000119c) ret=00452a59 0024:Ret gdi32.CreateCompatibleDC() retval=000011a4 ret=00452a59 0024:Call gdi32.SelectObject(000011a4,000011a0) ret=00452a6b 0024:Ret gdi32.SelectObject() retval=0000006c ret=00452a6b 0024:Call gdi32.DeleteDC(0000119c) ret=00452a75 0024:Ret gdi32.DeleteDC() retval=00000001 ret=00452a75 0024:CALL Mandelbrot.CalcPointFloat(00000000,0032cf88) ret=0040449a 0024:RET Mandelbrot.CalcPointFloat() retval=00000000 ret=0040449a ... 0024:CALL MSVCR100.fopen_s(<unknown, check return>) ret=0044f90a ... 0024:Call KERNEL32.CreateFileA(0032cfd0 "C:\users\focht\My Documents\Fractal eXtreme\plugin_stamps\Mandelbrot_Mandelbrot.bmp",40000000,00000000,0032cdb4,00000002,00000080,00000000) ret=78b27359 0024:Ret KERNEL32.CreateFileA() retval=000001c8 ret=78b27359 ... 0024:RET MSVCR100.fopen_s() retval=00000000 ret=0044f90a 0024:Call gdi32.SetDIBColorTable(000011a4,00000000,00000100,00557c08) ret=00452c83 0024:Ret gdi32.SetDIBColorTable() retval=00000100 ret=00452c83 0024:CALL MSVCR100.fwrite(0032ced0,00000001,0000000e,78b53068) ret=00448091 0024:Call ntdll.RtlAllocateHeap(00547000,00000000,00001000) ret=78ab0269 0024:Ret ntdll.RtlAllocateHeap() retval=00558020 ret=78ab0269 0024:RET MSVCR100.fwrite() retval=0000000e ret=00448091 0024:Call gdi32.GetDIBits(000011a4,000011a0,00000000,0000006e,00000000,0032caa4,00000000) ret=0044f6b6 0024:Ret gdi32.GetDIBits() retval=00000001 ret=0044f6b6 0024:CALL MSVCR100.fwrite(0032caa4,00000001,00000028,78b53068) ret=00448091 0024:RET MSVCR100.fwrite() retval=00000028 ret=00448091 0024:Call gdi32.SetDIBColorTable(000011a4,00000000,00000100,00557c08) ret=00452c83 0024:Ret gdi32.SetDIBColorTable() retval=00000100 ret=00452c83 0024:CALL MSVCR100.fwrite(00557c08,00000001,00000400,78b53068) ret=00448091 0024:RET MSVCR100.fwrite() retval=00000400 ret=00448091 0024:CALL MSVCR100.fwrite(00000000,00000001,00003020,78b53068) ret=00448091 0024:Call KERNEL32.GetLastError() ret=78ab0706 0024:Ret KERNEL32.GetLastError() retval=00000000 ret=78ab0706 0024:Call ntdll.RtlDecodePointer(fdf9bfb0) ret=78b2af62 0024:Ret ntdll.RtlDecodePointer() retval=00000000 ret=78b2af62 0024:Call KERNEL32.IsDebuggerPresent() ret=78b2aee6 0024:Ret KERNEL32.IsDebuggerPresent() retval=00000000 ret=78b2aee6 0024:Call KERNEL32.SetUnhandledExceptionFilter(00000000) ret=78b2aef0 0024:Ret KERNEL32.SetUnhandledExceptionFilter() retval=004a62b6 ret=78b2aef0 0024:Call KERNEL32.UnhandledExceptionFilter(0032c690) ret=78b2aefd wine: Unhandled exception 0xc0000417 at address 0x320023:0x78b2af3e (thread 0024), starting debugger... --- snip ---
The second fwrite() has a NULL ptr which causes the page fault.
Relevant app code leading to failure, annotated:
--- snip --- ... 0044F6B0 FF15 88C04A00 CALL DWORD PTR DS:[<&GDI32.GetDIBits>] 0044F6B6 8B7E 08 MOV EDI,DWORD PTR DS:[ESI+8] ; bmi.bmiHeader.biHeight 0044F6B9 3BC7 CMP EAX,EDI 0044F6BB 75 4C JNE SHORT 0044F709 0044F6BD 8B85 D0FBFFFF MOV EAX,DWORD PTR SS:[LOCAL.268] ; bmi.bmiHeader.biSizeImage 0044F6C3 85C0 TEST EAX,EAX 0044F6C5 74 42 JE SHORT 0044F709 0044F6C7 50 PUSH EAX 0044F6C8 FF15 48C44A00 CALL DWORD PTR DS:[<&MSVCR100.malloc> 0044F6CE 83C4 04 ADD ESP,4 0044F6D1 8985 B0FBFFFF MOV DWORD PTR SS:[LOCAL.276],EAX 0044F6D7 85C0 TEST EAX,EAX 0044F6D9 74 2E JE SHORT 0044F709 ... --- snip ---
The problem seems to be that the app expects GetDIBits() to return the number of scan lines (comparison of return value against bmi.bmiHeader.biHeight).
MSDN: http://msdn.microsoft.com/en-us/library/dd144879%28v=vs.85%29.aspx
--- quote --- int GetDIBits( __in HDC hdc, __in HBITMAP hbmp, __in UINT uStartScan, __in UINT cScanLines, __out LPVOID lpvBits, __inout LPBITMAPINFO lpbi, __in UINT uUsage );
... Return value
If the lpvBits parameter is non-NULL and the function succeeds, the return value is the number of scan lines copied from the bitmap.
If the lpvBits parameter is NULL and GetDIBits successfully fills the BITMAPINFO structure, the return value is nonzero.
If the function fails, the return value is zero.
This function can return the following value. --- quote ---
"return value is nonzero" Ah how precise. Roll a dice?
Digging further it seems Microsoft dropped the Win9x part of API documentation. Some websites carry the "old" API documentation that states:
--- quote --- If the lpvBits parameter is non-NULL and the function succeeds, the return value is the number of scan lines copied from the bitmap.
Windows 95:
If the lpvBits parameter is NULL and GetDIBits successfully fills the BITMAPINFO structure, the return value is the total number of scan lines in the bitmap.
Windows NT:
If the lpvBits parameter is NULL and GetDIBits successfully fills the BITMAPINFO structure, the return value is non-zero.
If the function fails, the return value is zero. --- quote ---
Source: http://source.winehq.org/git/wine.git/blob/71ea68b65727a7abac8f179035fe895f8...
--- snip --- 1187 INT WINAPI GetDIBits( 1188 HDC hdc, /* [in] Handle to device context */ 1189 HBITMAP hbitmap, /* [in] Handle to bitmap */ 1190 UINT startscan, /* [in] First scan line to set in dest bitmap */ 1191 UINT lines, /* [in] Number of scan lines to copy */ 1192 LPVOID bits, /* [out] Address of array for bitmap bits */ 1193 BITMAPINFO * info, /* [out] Address of structure with bitmap data */ 1194 UINT coloruse) /* [in] RGB or palette index */ 1195 { ... 1380 if (bits) 1381 { 1382 if(dst_info->bmiHeader.biHeight > 0) 1383 dst_info->bmiHeader.biHeight = src.height; 1384 else 1385 dst_info->bmiHeader.biHeight = -src.height; 1386 1387 convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits, FALSE ); 1388 if (src_bits.free) src_bits.free( &src_bits ); 1389 ret = lines; 1390 } 1391 else 1392 ret = empty_rect ? FALSE : TRUE; 1393 1394 if (coloruse == DIB_PAL_COLORS) 1395 { 1396 WORD *index = (WORD *)dst_info->bmiColors; 1397 for (i = 0; i < dst_info->bmiHeader.biClrUsed; i++, index++) 1398 *index = i; 1399 } 1400 1401 copy_color_info( info, dst_info, coloruse ); 1402 if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) info->bmiHeader.biClrUsed = 0; 1403 1404 done: 1405 release_dc_ptr( dc ); 1406 GDI_ReleaseObj( hbitmap ); 1407 return ret; 1408 } --- snip ---
For testing I changed the code for line 1392 to also return the number of scan lines in case of "NULL" bits parameter. It lets the app successfully render/save fractals and the crash is gone.
$ du -sh fxsetup.msi 6.0M fxsetup.msi
$ sha1sum fxsetup.msi 44a9ff9779596205f25d6d00051f594a4cc599b0 fxsetup.msi
$ wine --version wine-1.5.0
Regards