http://bugs.winehq.org/show_bug.cgi?id=16585
--- Comment #9 from Igor Tarasov tarasov.igor@gmail.com 2009-01-02 16:07:32 --- I think I have figured it out. It's all in dlls/wineps.drv/bitmap.c. This code has a lot of similarities and copypasties from dlls/gdi32/dib.c / dlls/gdi32/bitmap.c. Maybe that code could be somehow combined? AFAIU gdi32 code is much more tested and fixed, and wineps.drv code is pretty buggy. Or it could be at least refactored, esp. in PSDRV_StretchDIBits.
So, I've made it printing and not crashing this way:
As far as I understand it now, PSDRV_StretchDIBits misuses srcHeight and srcWidth. I've been working olny with 32bit image section, and since all other parts have similar code I tend to think that this error is throughout all that function.
http://source.winehq.org/source/dlls/wineps.drv/bitmap.c#L371
I've replaced heightSrc and widthSrc with fullSrcHeight and fullSrcWidth respectevly in all that 'case' section. Since heightSrc sometimes may become negative, and since these heightSrc and widthSrc values are pretty big,
bitmap_size = heightSrc * widthSrc * 3; dst_ptr = bitmap = HeapAlloc(GetProcessHeap(), 0, bitmap_size);
bitmap_size here becomes around -350 000 000, and HeapAlloc just returns 0 and this is one of the reasons for crash.
Also, I've commented out line 375:
src_ptr += (ySrc * widthbytes);
Not sure that this is the most correct way to work this around, but ySrc in my case contains the same value as fullSrcHeight. This means, that pointer gets moved to the end of allocated memory and then in starts iterating it, increasing pointer. Clearly, it leads to crash, since memory manager won't allow getting out of boundaries.
So, there were at least 2 reasons for crash. I post it all here since I am not that good in C and this code to understand why it all works so wrong and how it all should work. So, any help is appreciated. :)