Bug 3130

Summary: Вылет при создании html-документа в 1С 8.0
Product: WINE@Etersoft Reporter: Константин Кондратюк <kondratyuk>
Component: Internet Explorer / GeckoAssignee: Виталий Перов <vitperov>
Status: CLOSED FIXED QA Contact:
Severity: major    
Priority: P2 CC: baraka, lav, vitperov
Version: 1.0.9   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on: 2105, 3137    
Bug Blocks: 147, 1217, 5293, 7199    
Attachments: Лог падения
Новый лог падения

Description Константин Кондратюк 2008-12-17 11:07:09 MSK
Created attachment 972 [details]
Лог падения

Вылетает в дебаг сразу после создания html.
Comment 1 Константин Кондратюк 2008-12-17 11:10:17 MSK
Первый запрашиваемый интерфейс - IMarshal
http://msdn.microsoft.com/en-us/library/ms688712(VS.85).aspx

Почти уверен, что в итоге падает из-за него, как 1с 8.1 падает из-за IMarkupServices в баге #2105
В любом случае, слишком много ошибок с корнем marshal

Виталик, что с твоим IMarshal? Имеет ли смысл опираться на него в решении баги? Судя по логу, интерфейс запрашивается у HTMLDocument. 
1) подтверждено ли тестом всё-таки?
2) у нас есть патч на добавление реализации (без всяких тестов)?
Comment 2 Виталий Перов 2008-12-17 17:54:11 MSK
IMarshal реализован. Только при его добавлении падало где-то oleaut32 или shdocvw. Точно не помню. Т.е после его добавления придётся ещё что-то править.
Тестов для него нет (потому, что я пока не представляю как их можно написать).

Эта проблема может подождать до пятницы? У меня сейчас со временем проблемы. Планирую появиться на работе только в пятницу ( и то возможно не получится).

Если срочно, то попробуй поискать в winehq-devel рассылке сообщене от меня с примерным заголовком "need advice". Там должен быть приложен этот патч

Если не получится, то пиши, попробую зайти через NX.
Comment 3 Константин Кондратюк 2008-12-17 22:03:16 MSK
Вполне может подождать и до следующей недели. Вообще, нужно собраться и понять, как всё-таки написать этот тест.
Comment 4 Константин Кондратюк 2008-12-21 00:16:56 MSK
IMarshal не должен быть реализован в mshtml. Подробности см. в баге 3137 с тестом.
Если проблема в IMarshal, то нужно копать именно в ole32.
Comment 5 Константин Кондратюк 2009-01-21 13:09:54 MSK
Нужно понять, что происходит при маршаллинге через 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;
  }
Comment 6 Виталий Перов 2009-02-11 15:49:50 MSK
Created attachment 1060 [details]
Новый лог падения

Теперь падает так
Comment 7 Виталий Перов 2009-02-11 15:52:51 MSK
сообщения вида:
fixme:mshtml:HTMLDocument_QueryInterface (0x31fc7e0)->({00000003-0000-0000-c000-000000000046} 0x32ede0) interface not supported

исчезлили.

Очевидно, что падение внутри маршаллинга в ole
Comment 8 Виталий Перов 2009-02-11 17:18:04 MSK
Подозрительным кажется сообщение
err:ole:marshal_object Failed to create an IRpcStubBuffer from IPSFactory for {b722bccb-4e68-101b-a2bc-00aa00404770} with error 0x80004002

код ошибки соответствует NS_NOINTERFACE
Comment 9 Виталий Перов 2009-02-11 17:48:20 MSK
Что касается функции marshal_object:
Интересно то, что данное сообщение появлиется в консоле несколько раз. Т.е падает не сразу. Можно предположить, что проблема связана с порчей/нехваткой памяти.
Проверил, при ошибке перед выходом единственный используемый интерфейс корректо освобождается.

Сообщение выводится после неудачного запуска IPSFactoryBuffer_CreateStub
По MSDN функция может возвращать только E_INVALIDARG, E_OUTOFMEMORY, E_UNEXPECTED, E_FAIL, S_OK. Никакого упоминания о NS_NOINTERFACE нет
Comment 10 Виталий Перов 2009-02-11 18:25:23 MSK
при использовании нативной 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...
Comment 11 Виталий Перов 2009-02-11 18:52:21 MSK
пробовал найти иходники функции 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
Comment 12 Виталий Перов 2009-02-11 20:10:30 MSK
Возможно для каждого интерфейса надо отдельно реализовывать 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.
Comment 13 Виталий Перов 2009-02-13 12:57:43 MSK
Для начала необходимо проверить работает ли маршаллинг IOleCommandTarget на винде.

Тесты на маршаллинг находятся в /dlls/ole32/tests/marshal.c

Только они падают при запуске. Как в "чистом" вайне, так и в нашем
Comment 14 Виталий Перов 2009-02-13 13:53:42 MSK
Падение было из-за использования сторонней ole32.dll

нашёл похожие сообщения (такое же как при падении в 1с) при запуске test_no_marshaler.

добавил свой тест.

Возникла ещё проблема: ошибка при компиляции crosstest.

Comment 15 Виталий Перов 2009-02-13 15:44:40 MSK
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 
Comment 16 Виталий Перов 2009-02-13 17:03:41 MSK
Написал тест с использованием 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

получить не удаётся
Comment 17 Виталий Перов 2009-02-13 18:07:06 MSK
Как показывают тесты, должен срабатывать участок кода:

    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с он почему-то не срабатывает.
Comment 18 Виталий Перов 2009-02-13 20:32:26 MSK
Если я правильно понимаю, то IUnknown_QueryInterface - виртуальный метод. Реально вызывается метод того класса, адрес кототорого был передан в параметрах.
Этим и объясниются различия в поведении.
Comment 19 Виталий Перов 2009-02-14 14:56:43 MSK
Разобрался в добавлении реализации _Stub и _Proxy функций.

1) Необходимо создать файл ole32_docobj.idl по примеру ole32_objidl.idl.
2) Добавить его в Makefile.in
3) в файле ole32/usmarshal.c необходимо реализовать заглушки для всех [local] функций.

Возникла проблема в том, что заглушки надо реализовавать именно для ВСЕХ функций.
Иначе невозможно скомпилировать ole32.dll
Comment 20 Виталий Перов 2009-02-14 16:20:20 MSK
необходимо ещё реализовать функции:
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)]
Comment 21 Виталий Перов 2009-02-17 18:38:02 MSK
Попробовал переделать тест.
В качестве первого параметра при вызове IMarshal_MarshalInterface
передавать не указатель на IMarshal, а указатель на IOleCommandTarget.

Падает на запросе IUnknown_QueryInterface(... IID_IOleCommandTarget).

Очевидно, что первым параметром должен всё же идти указатель на объект IMarshall
Comment 22 Виталий Перов 2009-02-17 19:04:26 MSK
Проверил на новой версии 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



Comment 23 Виталий Перов 2009-02-17 20:55:16 MSK
последняя строчка перед падением:
fixme:shdocvw:ClOleCommandTarget_Exec (0x1fa1370)->((null) 28 2 0x32ebf8 (nil))

комманда 28 соответствует OLECMDID_SETTITLE.

Нашёл возможное место падения.
Если попробовать получать строку из передаваемого входного параметра VARIANT *pvaIn, то при этом происходит падение.
Можно предположить, что функции передаётся неверный адрес pvaIn.

Попробовал вызвать искуственное падение в функции ClOleCommandTarget_Exec.

В результате, как странно это не звучит, но программа перестала падать!

Можно перемещать окно - не падает. Можно щёлкнуть на Просмотр - не падает.
Правда, падает при выборе Редактировать.

Объясняется очень просто срабатывает обработчик исключений более верхнего уровня, и исключение проходит.

Но в решении баги это ничем не помогает. Найти то место, откуда передаётся   (предположительно) неверный указатель на переменную.
Comment 24 Виталий Перов 2009-02-17 21:43:30 MSK
Попробовал со встроенным 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...


Comment 25 Виталий Перов 2009-02-17 22:13:06 MSK
Нашёл примерное место проблемы.
Если в функции DocDispatchEx_Invoke сразу возвращать S_OK, ничего не делая, то программа перестаёт падать!!!!
Отображается, конечно не правильно, но не падает!!!

Проблема ещё в том, что эта функция mshtml.dll, сейчас стоит встроенная, а должна быть сторонняя. Так что надо искать проблему выше.


Падение происходит при втором выхове функции. Пробовал в этом месте устроить искуственное падение, чтобы определить откуда она вызывается - не получилось: падение происходит, но бактрейс совсем бесполезный.
Comment 26 Виталий Перов 2009-02-24 18:16:21 MSK
с помощью отладчика был получен бактрейс с искуственного места падения в функции 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)
Comment 27 Виталий Перов 2009-02-24 18:55:24 MSK
Нашёл косвенную причину проблемы.

Падение происходит при вызове user32/winproc.c:1015

ret = callback( hwnd, msg, wParam, lParam, result, arg );

А конкретно при передаче сообщения 0x8002, что соответствует EVENT_OBJECT_SHOW.

Если это соообщение пропускать, то 1с не падает!
Comment 28 Виталий Перов 2009-02-24 20:20:31 MSK
хак можно сделать уже сейчас, но хотелось бы всё-таки разобраться в источнике проблемы.

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
Comment 29 Виталий Перов 2009-02-24 21:18:09 MSK
Разобраться в проблеме так и не удалось. Можно потратить ещё кучу времени а существенного продвижения так и не добится.

Думаю лучше пока сделать хак, и вернутся к баге позже (если возникнет необходимость).

Сделал хак.