функция BITMAP_SetOwnerDC служит для связывания bitmap с таблицей функций. в случае если bitmap->funcs == 0 она берёт функции из из DC: bitmap->funcs = dc->funcs; Но, если там уже что-то есть, то остаются старые функции обработки изображения. Необходимо выяснить (создать тест) как в этом случае ( когда bitmap->funcs не равны 0) поступает Windows.
В ходе написания нужного теста был получен случай, когда wine однозначно и постоянно падает. Это происходит в функции SetDIBits на вызове dc->funcs->pSetDIBits: if (!bitmap->funcs && !BITMAP_SetOwnerDC( hbitmap, dc )) goto done; result = lines; if (bitmap->funcs) { if (bitmap->funcs != dc->funcs) ERR( "not supported: DDB bitmap %p not belonging to device %p\n", hbitmap, hdc ); else if (dc->funcs->pSetDIBits) { result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines, bits, info, coloruse ); } } wine: Unhandled page fault on read access to 0x00000000 at address 0x7e91365b (thread 0009), starting debugger... В WINDOWS тест проходит нормально.
Если я правильно понял, то падает на: result = dc->funcs->pSetDIBits( dc->physDev, hbitmap, startscan, lines, bits, info, coloruse ); А функции точно передаются не нулевые параметры?
Я думаю, что в первую очередь надо проверить - заполняется ли указатель pSetDIBits, затем - указатель dc->funcs и только затем dc и нулевые параметры.
Имеется ввиду - pSetDIBits - действительно ли необходимая функция...
По dc->physDev так же возможны падения - я наталкивался пару раз, когда physDev заполнялся только NULL.
В результате проверки получилось: dc = 0x0011bd30 dc->funcs = 0x001183b0 dc->funcs->pSetDIBits = 0x7e91c7b0 Из переданных в функцию параметров, некоторые действительно имели нулевое значение: dc->physDev = 0x0011bf00 hbitmap = 0x000001d4 startscan = 0x00000000 lines = 0x00000064 bits = 0x00000000 info = 0x00000000 coloruse = 0x00000000
(In reply to comment #6) > В результате проверки получилось: > > dc = 0x0011bd30 > dc->funcs = 0x001183b0 > dc->funcs->pSetDIBits = 0x7e91c7b0 > > Из переданных в функцию параметров, > некоторые действительно имели нулевое > значение: > > dc->physDev = 0x0011bf00 hbitmap = 0x000001d4 startscan = 0x00000000 lines = > 0x00000064 bits = 0x00000000 info = 0x00000000 coloruse = 0x00000000 > Тогда похоже, что pSetDIBits падала из-за нулевого const BITMAPINFO *info Надеюсь я не обижу уточнением, что pSetDIBits == X11DRV_SetDIBits ?
Случайно не туда нажал, извините..
Понятно, что тест нужно писать для функции SetOwnerDC, которой передаётся объект типа BITMAP. Также поскольку ошибка - read access, значит проблема не в нулевом указателе на функцию (был бы exec access), а в указателе на какие-то данные. Также при каждом падении выводится backtrace, из которого понятно, в каком месте программы (и в какой строчке) произошло падение. С ним можно было бы меньше гадать, где именно падаем.
В общем я разобрался почему происходит падение wine. Все из-за вызова ф-ции CreateDIBitmap и передачи ей CBM_INIT, с одновременным BITMAPINFO *data равным NULL. Что-нибудь вроде такого вызова: hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, &pixel, NULL, DIB_RGB_COLORS); После чего в ходе выполнения этот NULL передается ф-ции DIB_GetBitmapInfo. Она делает header->biSize, а header и есть этот параметр равный NULL. Все падает. Конечно вряд ли кто-нибудь допустит такой вызов с CBM_INIT и NULL. Но можно на всякий случай сделать патч с праверкой header на NULL? В винде, все-таки, такой вызов проходит нормально.
(In reply to comment #10) > Конечно вряд ли кто-нибудь допустит такой > вызов с CBM_INIT и NULL. Но можно на всякий случай > сделать патч с праверкой header на NULL? В винде, > все-таки, такой вызов проходит нормально. > Отлично! Наверное правильным будет сделать исправление к функции и сразу тест, показывающий, что функция что-то возвращает при таком сочетании параметров и не падает. То есть даже не надо todo_wine для таких случаев ставить и сразу его убирать. Надо сделать исправление с тестом и отослать одним файлом.
С тестом для BITMAP_SetOwnerDC у меня ничего не получается. Практически все вызовы сопровождаются проверкой: if (!bitmap->funcs && !BITMAP_SetOwnerDC( handle, dc )) т.е. если bitmap->funcs уже есть то ф-ция даже не вызывается. Есть еще вызов в CreateDIBitmap, но перед ним handle создается заново, т.е. bitmap->funcs тоже 0. Один вызов есть в BRUSH_SelectObject: BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc ); но заранее задать brush->logbrush.lbHatch нельзя - объект внутренний. Опять же bitmap->funcs оказывается равен 0.
Проверить требуется только то, как ведёт себя функция BITMAP_SetOwnerDC Думаю можно создать bitmap, даже с пустым набором функций. А затем присвоить bitmap->funcs какое-нибудь значение. А затем проверить перезапишется ли оно после вызова BITMAP_SetOwnerDC. Даже не обязательно "правильно" создавать bitmap и DC. Можно просто посмотреть код BITMAP_SetOwnerDC и вручную заполнить те поля, которые она использует
Ой! что-то я не то написал. Известно, что использует BITMAP_SetOwnerDC в wine, но не извесно как она устоена в винде. Так что вручную заполнять bitmap и DC всё же не стоит
(In reply to comment #14) > Ой! что-то я не то написал. Известно, что > использует BITMAP_SetOwnerDC в wine, но не извесно как > она устоена в винде. Т.к. она не маркирована WINAPI, то с 90% вероятностью такой функции в Win API нет. > Так что вручную > заполнять bitmap и DC всё же не стоит >
(In reply to comment #15) > (In reply to comment #14) > > Ой! что-то я не то написал. Известно, что > > использует BITMAP_SetOwnerDC в wine, но не извесно как > > она устоена в винде. > > Т.к. она не маркирована WINAPI, то с 90% > вероятностью такой функции в Win API нет. Ну WINAPI это макрос, определяющий соглашение о вызове (calling convention) этой функции. В основном конечно все внешние функции его используют, но прямой связи с WinAPI таки нет. Ну и конечно никой BITMAP_SetOwnerDC в Windows нет Тестировать её можно через CreateDIBitmap или SelectObject, из которых она вызывается. Но в общем оставим пока эту задачу.
(In reply to comment #16) > > Т.к. она не маркирована WINAPI, то с 90% > > вероятностью такой функции в Win API нет. > Ну WINAPI это макрос, определяющий соглашение > о вызове (calling convention) этой функции. В > основном конечно все внешние функции его > используют, но прямой связи с WinAPI таки нет. :))) Конечно и ёжику понятно, что это соглашение о вызове. Я просто отметил закономерность, которую ты и указал: >В > основном конечно все внешние функции его > используют, но прямой связи с WinAPI таки нет. С таким же успехом я мог написать, что это название функции не соответствует принятому стилю именования функций Win32 API.
(In reply to comment #17) > С таким же успехом я мог написать, что это > название функции не соответствует > принятому стилю именования функций Win32 API. Ну скорее даже можно однозначно утверждать что функции с подобными префиксами - внутренние для библиотек проекта Wine и не экспортируются.
> Ну и конечно никой BITMAP_SetOwnerDC в Windows нет > Тестировать её можно через CreateDIBitmap или > SelectObject, из которых она вызывается. > Да, действительно! Я как-то сразу не заметил :(
Да, тут я с самого начала был неправ: Нельзя писать тест на не winapi-шную функцию