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
http://bugs.winehq.org/show_bug.cgi?id=30266
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download URL| |ftp://ftp.cygnus-software.c | |om/pub/fxsetup.msi
--- Comment #1 from Anastasius Focht focht@gmx.net 2012-03-25 11:34:58 CDT --- Hello,
filling fields ...
Regards
http://bugs.winehq.org/show_bug.cgi?id=30266
--- Comment #2 from Alexandre Julliard julliard@winehq.org 2012-03-27 05:53:07 CDT --- We have tests that show that GetDIBits returns TRUE in that case. Sounds like an app bug.
http://bugs.winehq.org/show_bug.cgi?id=30266
--- Comment #3 from Anastasius Focht focht@gmx.net 2013-05-03 05:44:49 CDT --- Hello folks,
revisiting, still present. The app version/checksum changed but the crash is the same.
I'm a bit puzzled about the .NET Framework 4.0 client profile requirement for the app because no executable/plugin is managed or mixed code.
Installer refuses without .NET:
--- snip --- err:msi:ITERATE_Actions Execution halted, action L"VSDCA_VsdLaunchConditions" returned 1603 --- snip ---
Peeking with ORCA into _VsdLaunchCondition table:
--- snip --- Condition Description Url s255 l255 s0 _VsdLaunchCondition Condition VSDFXAvailable [VSDNETURLMSG] http://go.microsoft.com/fwlink/?LinkId=131000 --- snip ---
http://go.microsoft.com/fwlink/?LinkId=131000 -> Microsoft .NET Framework 4 Client Profile (Web Installer)
Anyway, the crash analysis still holds.
$ du -sh fxsetup.msi 6.2M fxsetup.msi
$ sha1sum fxsetup.msi 2076761c658b1250c9e9612cfb84d655872b577f fxsetup.msi
$ wine --version wine-1.5.29-107-gb94cfaf
Regards
https://bugs.winehq.org/show_bug.cgi?id=30266
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |INVALID
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello folks,
it seems the author of the software changed related code which makes it work now. I found an unspecific mention of a Wine bugfix in the release notes of version 2.22, May 2013 which might be related to this.
http://www.cygnus-software.com/whybuyfx/releasenotes.htm
--- quote --- Version 2.22, May 2013
A fix was made to correct a bug that prevented Fractal eXtreme from running under Wine. --- quote ---
It seems he saw my comment #3, made a fix and begone. Good guy, how nice of him of putting a notice to this ticket. Wait. What? Its not that he didn't benefit from it ... but well.
For the documentation:
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files (x86)/Cygnus Software/Fractal eXtreme 32-bit
$ WINEDEBUG=+tid,+seh,+relay,+snoop,+bitmap wine ./FractalX.exe >> log.txt 2>&1 ... 002e:Call gdi32.CreateDIBSection(003d00bb,0055de98,00000000,0055de88,00000000,00000000) ret=00452f55 002e:trace:bitmap:CreateDIBSection format (110,110), planes 1, bpp 8, BI_RGB, size 12320 RGB 002e:Ret gdi32.CreateDIBSection() retval=000700ca ret=00452f55 ... 002e:Call msvcr100.fopen_s(0033d44c,0033d510 "C:\users\focht\My Documents\Fractal eXtreme\plugin_stamps\Mandelbrot_Mandelbrot.bmp",0033d450 "wb") ret=0044f07a ... 002e:Call KERNEL32.CreateFileW(0055e2d8 L"C:\users\focht\My Documents\Fractal eXtreme\plugin_stamps\Mandelbrot_Mandelbrot.bmp",40000000,00000003,0033d1fc,00000002,00000080,00000000) ret=7e9acc5e 002e:Ret KERNEL32.CreateFileW() retval=00000258 ret=7e9acc5e ... 002e:Ret msvcr100.fopen_s() retval=00000000 ret=0044f07a 002e:Call gdi32.SetDIBColorTable(003e00bb,00000000,00000100,0055dec0) ret=00453193 002e:Ret gdi32.SetDIBColorTable() retval=00000100 ret=00453193 002e:Call msvcr100.ftell(7ea35700) ret=004476ca 002e:Call KERNEL32.SetFilePointer(00000258,00000000,0033ce14,00000001) ret=7e9aa8b1 002e:Ret KERNEL32.SetFilePointer() retval=00000000 ret=7e9aa8b1 002e:Ret msvcr100.ftell() retval=00000000 ret=004476ca 002e:Call msvcr100.fwrite(0033d400,00000001,0000000e,7ea35700) ret=00447641 002e:Call ntdll.RtlAllocateHeap(00550000,00000008,00001000) ret=7e9b424a 002e:Ret ntdll.RtlAllocateHeap() retval=0055e2d8 ret=7e9b424a 002e:Ret msvcr100.fwrite() retval=0000000e ret=00447641 002e:Call gdi32.GetDIBits(003e00bb,000800ca,00000000,0000006e,00000000,0033cfd4,00000000) ret=0044edc8 002e:Ret gdi32.GetDIBits() retval=00000001 ret=0044edc8 002e:Call msvcr100.malloc(00003020) ret=0044eddd 002e:Call ntdll.RtlAllocateHeap(00550000,00000000,00003020) ret=7e9b424a 002e:Ret ntdll.RtlAllocateHeap() retval=0055f2e0 ret=7e9b424a 002e:Ret msvcr100.malloc() retval=0055f2e0 ret=0044eddd 002e:Call gdi32.GetDIBits(003e00bb,000800ca,00000000,0000006e,0055f2e0,0033cfd4,00000000) ret=0044ee16 002e:Ret gdi32.GetDIBits() retval=00000000 ret=0044ee16 002e:Call msvcr100.fwrite(0033cfd4,00000001,00000028,7ea35700) ret=00447641 002e:Ret msvcr100.fwrite() retval=00000028 ret=00447641 002e:Call gdi32.SetDIBColorTable(003e00bb,00000000,00000100,0055dec0) ret=00453193 002e:Ret gdi32.SetDIBColorTable() retval=00000100 ret=00453193 002e:Call msvcr100.fwrite(0055dec0,00000001,00000400,7ea35700) ret=00447641 002e:Ret msvcr100.fwrite() retval=00000400 ret=00447641 002e:Call msvcr100.fwrite(0055f2e0,00000001,00003020,7ea35700) ret=00447641 002e:Call KERNEL32.WriteFile(00000258,0055e2d8,00001000,0033cdf8,00000000) ret=7e9af862 002e:Ret KERNEL32.WriteFile() retval=00000001 ret=7e9af862 002e:Call KERNEL32.WriteFile(00000258,0055feaa,00002000,0033ce28,00000000) ret=7e9af862 002e:Ret KERNEL32.WriteFile() retval=00000001 ret=7e9af862 002e:Ret msvcr100.fwrite() retval=00003020 ret=00447641 ... --- snip ---
--- snip --- 0044EDBF 8B1D 88C04A00 MOV EBX,DWORD PTR DS:[<&GDI32.GetDIBits>] 0044EDC5 50 PUSH EAX ; hDC 0044EDC6 FFD3 CALL EBX 0044EDC8 85C0 TEST EAX,EAX ; 1 -> TRUE 0044EDCA 74 4F JE SHORT FractalX.0044EE1B 0044EDCC 8B85 D0FBFFFF MOV EAX,DWORD PTR SS:[EBP-430] ; 0x3020 -> 12320 0044EDD2 85C0 TEST EAX,EAX 0044EDD4 74 45 JE SHORT FractalX.0044EE1B 0044EDD6 50 PUSH EAX 0044EDD7 FF15 48C44A00 CALL DWORD PTR DS:[<&MSVCR100.malloc>] 0044EDDD 83C4 04 ADD ESP,4 0044EDE0 8985 B0FBFFFF MOV DWORD PTR SS:[EBP-450],EAX ; lpvBits 0044EDE6 85C0 TEST EAX,EAX 0044EDE8 74 31 JE SHORT FractalX.0044EE1B 0044EDEA 8B95 B0FBFFFF MOV EDX,DWORD PTR SS:[EBP-450] 0044EDF0 8B46 08 MOV EAX,DWORD PTR DS:[ESI+8] 0044EDF3 6A 00 PUSH 0 ; uUsage 0044EDF5 8D8D BCFBFFFF LEA ECX,DWORD PTR SS:[EBP-444] 0044EDFB 51 PUSH ECX ; lpbi 0044EDFC 52 PUSH EDX ; lpvBits 0044EDFD 50 PUSH EAX ; cScanLines = 110 0044EDFE 8B06 MOV EAX,DWORD PTR DS:[ESI] 0044EE00 8B50 14 MOV EDX,DWORD PTR DS:[EAX+14] 0044EE03 6A 00 PUSH 0 ; uStartScan = 0 0044EE05 8BCE MOV ECX,ESI 0044EE07 FFD2 CALL EDX 0044EE09 50 PUSH EAX ; hbmp 0044EE0A 8B06 MOV EAX,DWORD PTR DS:[ESI] 0044EE0C 8B50 10 MOV EDX,DWORD PTR DS:[EAX+10] 0044EE0F 8BCE MOV ECX,ESI 0044EE11 FFD2 CALL EDX 0044EE13 50 PUSH EAX ; hDC 0044EE14 FFD3 CALL EBX ; GDI32.GetDIBits ... --- snip ---
I still think he had Win9x-ish code there that works in native Windows. Unfortunately I didn't save the old app version.
Anyway, further investigation seems wasted time. Resolving 'invalid' here.
$ sha1sum fxsetup.msi 836895f51cd11b0d1d3dee3ba7314ea673268a63 fxsetup.msi
$ du -sh fxsetup.msi 6.2M fxsetup.msi
$ wine --version wine-3.8
Regards
https://bugs.winehq.org/show_bug.cgi?id=30266
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Cygnus Fractal eXtreme |Cygnus Fractal eXtreme |crashes after trial dialog |earlier than version 2.22 |(expects gdi32 GetDIBits() |crashes after trial dialog |returning number of scan |(expects gdi32 GetDIBits() |lines when bits parameter |returning number of scan |is NULL) |lines when bits parameter | |is NULL)
https://bugs.winehq.org/show_bug.cgi?id=30266
Ken Sharp imwellcushtymelike@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #5 from Ken Sharp imwellcushtymelike@gmail.com --- Closing bugs marked as invalid.