Created attachment 972 [details] Лог падения Вылетает в дебаг сразу после создания html.
Первый запрашиваемый интерфейс - IMarshal http://msdn.microsoft.com/en-us/library/ms688712(VS.85).aspx Почти уверен, что в итоге падает из-за него, как 1с 8.1 падает из-за IMarkupServices в баге #2105 В любом случае, слишком много ошибок с корнем marshal Виталик, что с твоим IMarshal? Имеет ли смысл опираться на него в решении баги? Судя по логу, интерфейс запрашивается у HTMLDocument. 1) подтверждено ли тестом всё-таки? 2) у нас есть патч на добавление реализации (без всяких тестов)?
IMarshal реализован. Только при его добавлении падало где-то oleaut32 или shdocvw. Точно не помню. Т.е после его добавления придётся ещё что-то править. Тестов для него нет (потому, что я пока не представляю как их можно написать). Эта проблема может подождать до пятницы? У меня сейчас со временем проблемы. Планирую появиться на работе только в пятницу ( и то возможно не получится). Если срочно, то попробуй поискать в winehq-devel рассылке сообщене от меня с примерным заголовком "need advice". Там должен быть приложен этот патч Если не получится, то пиши, попробую зайти через NX.
Вполне может подождать и до следующей недели. Вообще, нужно собраться и понять, как всё-таки написать этот тест.
IMarshal не должен быть реализован в mshtml. Подробности см. в баге 3137 с тестом. Если проблема в IMarshal, то нужно копать именно в ole32.
Нужно понять, что происходит при маршаллинге через ole32. Судя по логу, проблемы начинаются в marshal_object: hr = IPSFactoryBuffer_CreateStub(psfb, riid, iobject, &stub); IPSFactoryBuffer_Release(psfb); if (hr != S_OK) { ERR("Failed to create an IRpcStubBuffer from IPSFactory for %s with error 0x%08x\n", debugstr_guid(riid), hr); IUnknown_Release(iobject); return hr; }
Created attachment 1060 [details] Новый лог падения Теперь падает так
сообщения вида: fixme:mshtml:HTMLDocument_QueryInterface (0x31fc7e0)->({00000003-0000-0000-c000-000000000046} 0x32ede0) interface not supported исчезлили. Очевидно, что падение внутри маршаллинга в ole
Подозрительным кажется сообщение err:ole:marshal_object Failed to create an IRpcStubBuffer from IPSFactory for {b722bccb-4e68-101b-a2bc-00aa00404770} with error 0x80004002 код ошибки соответствует NS_NOINTERFACE
Что касается функции marshal_object: Интересно то, что данное сообщение появлиется в консоле несколько раз. Т.е падает не сразу. Можно предположить, что проблема связана с порчей/нехваткой памяти. Проверил, при ошибке перед выходом единственный используемый интерфейс корректо освобождается. Сообщение выводится после неудачного запуска IPSFactoryBuffer_CreateStub По MSDN функция может возвращать только E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, E_FAIL, S_OK. Никакого упоминания о NS_NOINTERFACE нет
при использовании нативной ole32.dll падает совсем по-другому: fixme:shdocvw:WebBrowser_QueryInterface (0x1a35d8)->({0000001b-0000-0000-c000-000000000046} 0x32f09c) interface not supported fixme:rpc:alloc_serverprotoseq protseq "mswmsg" not supported fixme:shdocvw:WebBrowser_QueryInterface (0x1a35d8)->({0000001b-0000-0000-c000-000000000046} 0x32f09c) interface not supported fixme:rpc:alloc_serverprotoseq protseq "mswmsg" not supported wine: Unhandled page fault on read access to 0x00000004 at address 0x103eecd0 (thread 0009), starting debugger...
пробовал найти иходники функции IPSFactoryBuffer_CreateStub. В коде такой функции нет. Вместо этого вызывается функция с названием CStdPSFactory_CreateStub. Ошибка 0x80004002 ещё соответствует E_NOINTERFACE; И врзвращается она в CStdPSFactory_CreateStub при неудачном вызове: if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index)) return E_NOINTERFACE; FindProxyInfo ищет в списке требуемый интерфейс. на всякий случай проверил riid = b722bccb-4e68-101b-a2bc-00aa00404770, это IOleCommandTarget, и он реализован в wine
Возможно для каждого интерфейса надо отдельно реализовывать stub и proxy функции. По примеру IClassFactory2_CreateInstanceLic_Proxy и IClassFactory2_CreateInstanceLic_Stub в docobj.h объявлены stub и prox для интерфейса IOleCommandTarget, но их реализации в wine нет. В качестве примера хорошо помогает патч: Dan Hipschman : oleaut32: Add a widl-generated proxy file for ocidl.idl. в частности файл /dlls/oleaut32/oleaut32_ocidl_p.c как-раз содержит статические списки stub и proxy, принадлежащие к данной dll.
Для начала необходимо проверить работает ли маршаллинг IOleCommandTarget на винде. Тесты на маршаллинг находятся в /dlls/ole32/tests/marshal.c Только они падают при запуске. Как в "чистом" вайне, так и в нашем
Падение было из-за использования сторонней ole32.dll нашёл похожие сообщения (такое же как при падении в 1с) при запуске test_no_marshaler. добавил свой тест. Возникла ещё проблема: ошибка при компиляции crosstest.
crosstest компилируется. Необходимо было предварительно собрать libole32.a Добавленный тест: hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); hr = CoMarshalInterface(pStream, &IID_IOleCommandTarget, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); Проходит как в wine, так и в винде. Интересно то, что вызывается функция marshal_object, но она возвращает ошибку на условии: hr = IUnknown_QueryInterface(object, riid, (void **)&iobject); if (hr != S_OK) { ERR("object doesn't expose interface %s, failing with error 0x%08x\n", debugstr_guid(riid), hr); return E_NOINTERFACE; } т.е раньше чем ошибка возвращается в 1С. В 1с marshal_object вызывается из StdMarshalImpl_MarshalInterface. Видимо есть разница откуда вызывать marshal_object. Функция ведёт себя совсем по-другому при вызове из CoMarshalInterface. Думаю необходимо переписать тест с использованием IMarshal_MarshalInterface
Написал тест с использованием IMarshal_MarshalInterface Тест не проходит как в wine, так в винде: marshal.c:2128: Test failed: IMarshal_MarshalInterface failed with error 0x80004002 marshal.c:2130: Test failed: Number of locks should be > 0, but actually is 0 marshal.c:2071: got guid data: {00000000-0000-0000-0000-000000000000} marshal.c:2140: Test failed: Number of locks should be 0, but actually is -1 при этом появляется сообщение: err:ole:marshal_object object doesn't expose interface {b722bccb-4e68-101b-a2bc-00aa00404770}, failing with error 0x80004002 err:ole:StdMarshalImpl_MarshalInterface Failed to create ifstub, hres=0x80004002 то же, что и при вызове с помощью CoMarshalInterface. Искомое сообщение при падении 1с: err:ole:marshal_object Failed to create an IRpcStubBuffer from IPSFactory for {b722bccb-4e68-101b-a2bc-00aa00404770} with error 0x80004002 получить не удаётся
Как показывают тесты, должен срабатывать участок кода: hr = IUnknown_QueryInterface(object, riid, (void **)&iobject); if (hr != S_OK) { ERR("object doesn't expose interface %s, failing with error 0x%08x\n", debugstr_guid(riid), hr); return E_NOINTERFACE; } но при запуске из 1с он почему-то не срабатывает.
Если я правильно понимаю, то IUnknown_QueryInterface - виртуальный метод. Реально вызывается метод того класса, адрес кототорого был передан в параметрах. Этим и объясниются различия в поведении.
Разобрался в добавлении реализации _Stub и _Proxy функций. 1) Необходимо создать файл ole32_docobj.idl по примеру ole32_objidl.idl. 2) Добавить его в Makefile.in 3) в файле ole32/usmarshal.c необходимо реализовать заглушки для всех [local] функций. Возникла проблема в том, что заглушки надо реализовавать именно для ВСЕХ функций. Иначе невозможно скомпилировать ole32.dll
необходимо ещё реализовать функции: VARIANT_UserSize VARIANT_UserMarshal VARIANT_UserUnmarshal VARIANT_UserFree Для начала сделал заглушки. Компиллируется! Проверил на 1с то же самое сообщение: err:ole:marshal_object Failed to create an IRpcStubBuffer from IPSFactory for {b722bccb-4e68-101b-a2bc-00aa00404770} with error 0x80004002 Вообще для функций IOleCommandTarget заглушки реализоваывать не потребовалось. В .idl файле они отмечены как [local], ни как [call_as(Fn)]
Попробовал переделать тест. В качестве первого параметра при вызове IMarshal_MarshalInterface передавать не указатель на IMarshal, а указатель на IOleCommandTarget. Падает на запросе IUnknown_QueryInterface(... IID_IOleCommandTarget). Очевидно, что первым параметром должен всё же идти указатель на объект IMarshall
Проверил на новой версии wine 1.0.10 Ничего не изменилось. Зато увидел то, что не видел раньше: вызов методов fixme:shdocvw:ClServiceProvider_QueryService (0x1fa1390)->({3050f842-98b5-11cf-bb82-00aa00bdce0b} {3050f842-98b5-11cf-bb82-00aa00bdce0b} 0x32c5d8) fixme:shdocvw:ClOleCommandTarget_Exec (0x1fa1390)->((null) 25 2 0x32c578 (nil)) Интерфейс IOleCommandTarget как-раз содержит методы Exec и QueryService. Думаю они как-раз и вызываются. только почему-то из shdocvw.dll
последняя строчка перед падением: fixme:shdocvw:ClOleCommandTarget_Exec (0x1fa1370)->((null) 28 2 0x32ebf8 (nil)) комманда 28 соответствует OLECMDID_SETTITLE. Нашёл возможное место падения. Если попробовать получать строку из передаваемого входного параметра VARIANT *pvaIn, то при этом происходит падение. Можно предположить, что функции передаётся неверный адрес pvaIn. Попробовал вызвать искуственное падение в функции ClOleCommandTarget_Exec. В результате, как странно это не звучит, но программа перестала падать! Можно перемещать окно - не падает. Можно щёлкнуть на Просмотр - не падает. Правда, падает при выборе Редактировать. Объясняется очень просто срабатывает обработчик исключений более верхнего уровня, и исключение проходит. Но в решении баги это ничем не помогает. Найти то место, откуда передаётся (предположительно) неверный указатель на переменную.
Попробовал со встроенным mshtml: Программа идёт немного дальше. Падает после: fixme:shdocvw:ClOleCommandTarget_Exec (0x3086b00)->((null) 35 0 (nil) (nil)) 35 это OLECMDID_HTTPEQUIV_DONE. Если выводить и trace сообщения, то: fixme:shdocvw:ClOleCommandTarget_Exec (0x2ef4ad0)->((null) 35 0 (nil) (nil)) stub, but return S_OK trace:shdocvw:WebBrowser_Release (0x2ef4a30) ref=14 trace:mshtml:DocDispatchEx_Invoke (0x2ef7970)->(-525 {00000000-0000-0000-0000-000000000000} 2048 2 0x32f09c 0x32f08c 0x32f0ac 0x32f088) trace:mshtml:DocDispatchEx_Invoke DISPID_READYSTATE trace:ole:CoRegisterMessageFilter ((nil), (nil)) wine: Unhandled page fault on read access to 0x00000000 at address 0x1cc0c436 (thread 0009), starting debugger...
Нашёл примерное место проблемы. Если в функции DocDispatchEx_Invoke сразу возвращать S_OK, ничего не делая, то программа перестаёт падать!!!! Отображается, конечно не правильно, но не падает!!! Проблема ещё в том, что эта функция mshtml.dll, сейчас стоит встроенная, а должна быть сторонняя. Так что надо искать проблему выше. Падение происходит при втором выхове функции. Пробовал в этом месте устроить искуственное падение, чтобы определить откуда она вызывается - не получилось: падение происходит, но бактрейс совсем бесполезный.
с помощью отладчика был получен бактрейс с искуственного места падения в функции DocDispatchEx_Invoke: Backtrace: =>0 0x7db9d195 DocDispatchEx_Invoke+0x111(iface=0x2ee25dc, dispIdMember=-525, riid=0x1cc5f180, lcid=2048, wFlags=2, pDispParams=0x32f09c, pVarResult=0x32f08c, pExcepInfo=0x32f0ac, puArgErr=0x32f088) [/home/vitperov/Projects/wine-dev/dlls/mshtml/htmldoc.c:1685] in mshtml (0x0032f028) 1 0x7db97b52 HTMLDocument_Invoke+0x4f(iface=0x2ee2590, dispIdMember=-525, riid=0x1cc5f180, lcid=2048, wFlags=<is not available>, pDispParams=0x32f09c, pVarResult=0x32f08c, pExcepInfo=0x32f0ac, puArgErr=0x32f088) [/home/vitperov/Projects/wine-dev/dlls/mshtml/htmldoc.c:272] in mshtml (0x0032f058) 2 0x1cbe916a in html (+0x2916a) (0x0032f158) 3 0x7dbefa43 hidden_proc+0x4c6(hwnd=0x1004c, msg=32776, wParam=0, lParam=0) [/srv/vitperov/Projects/wine-dev/dlls/mshtml/task.c:295] in mshtml (0x0032f248) fixme:dbghelp_dwarf:dwarf2_parse_variable Unsupported form for const value System (a) 4 0x7eddd2da WINPROC_wrapper+0x1a() in user32 (0x0032f278) 5 0x7eddd6bf call_window_proc+0x61(hwnd=<register EDI not in topmost frame>, msg=<register ESI not in topmost frame>, wp=0, lp=0, result=0x32f7f8, arg=0x7dbef57d) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:461] in user32 (0x0032f2b8) 6 0x7ede13c2 WINPROC_CallProcAtoW+0xb9(callback=0x7eddd65e, hwnd=0x1004c, msg=32776, wParam=0, lParam=0, result=0x32f7f8, arg=0x7dbef57d, mapping=WMCHAR_MAP_DISPATCHMESSAGE) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:1015] in user32 (0x0032f788) 7 0x7ede2720 WINPROC_call_window+0x14b(hwnd=<register EDI not in topmost frame>, msg=32776, wParam=0, lParam=0, result=0x32f7f8, unicode=0, mapping=WMCHAR_MAP_DISPATCHMESSAGE) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:2217] in user32 (0x0032f7c8) 8 0x7eda31b3 DispatchMessageA+0x96(msg=<register EDI not in topmost frame>) [/srv/vitperov/Projects/wine-dev/dlls/user32/message.c:3072] in user32 (0x0032f808) 9 0x11c58d30 in wbase (+0x8d30) (0x006ad20c) 10 0x17796c98 in frame (+0x7d6c98) (0x17796cac) 11 0x17621020 in frame (+0x661020) (0x17621040) 12 0x8b20408b (0x0424448b) 13 0x00000000 (0x00000000)
Нашёл косвенную причину проблемы. Падение происходит при вызове user32/winproc.c:1015 ret = callback( hwnd, msg, wParam, lParam, result, arg ); А конкретно при передаче сообщения 0x8002, что соответствует EVENT_OBJECT_SHOW. Если это соообщение пропускать, то 1с не падает!
хак можно сделать уже сейчас, но хотелось бы всё-таки разобраться в источнике проблемы. 1) насколько я понял из документации, сообщение EVENT_OBJECT_SHOW посылается сервером элементам caret, cursor, and window object когда показывается скрытый объект. 2) если всё-таки вызвать callback функцию, то настараживают сообщения перед падением: rr:ole:COMPOBJ_DllList_Add couldn't load in-process dll L"msimtf.dll" err:ole:CoGetClassObject no class object {4955dd33-b159-11d0-8fcf-00aa006bcc59} could be created for context 0x1
Разобраться в проблеме так и не удалось. Можно потратить ещё кучу времени а существенного продвижения так и не добится. Думаю лучше пока сделать хак, и вернутся к баге позже (если возникнет необходимость). Сделал хак.