Summary: | 1С 8.2: проблема экспорта документов в MS Word через COM-объекты | ||
---|---|---|---|
Product: | [Сторонние программы (Other programs)] 1С:Предприятие 8 | Reporter: | Дмитрий Галочкин <dm> |
Component: | Общая | Assignee: | Dmitry Timoshkov <dtimoshkov> |
Status: | CLOSED FIXED | QA Contact: | Svetlana Zhukova <svzhu> |
Severity: | normal | ||
Priority: | P4 | CC: | dm, kopilo4ka, lav, svzhu |
Version: | 8.2 | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All | ||
Whiteboard: | |||
Заявки RT: | Связано с: | 7371, 9006 | |
Дата напоминания: |
Description
Дмитрий Галочкин
2012-08-30 20:31:14 MSK
судя по ошибке,описанной в заявке: {ОбщийМодуль.ШаблоныДокументов.Модуль(84)}: Ошибка при вызове конструктора (COMОбъект) Word = Новый COMОбъект("Word.Application"); по причине: Unknown error 0x800401F3 это бага https://bugs.etersoft.ru/show_bug.cgi?id=7371 но там упоминается exel. проверим на word. WINE@Etersoft SQL 2.0.2-eter15/3 wine@eter-2 bottle bugs/8689 установлены 1с82, MSO2007, UniOffice@Etersoft-v0.5.exe (из testing), БД и шаблон из /RT/25718/ Ошибка воспроизводится. у нас уже была подобная бага 6096. на wwo такое же поведение. если верить, баге 6096 на wine-2.0 загрузка шаблона все-таки происходила, но на данный момент, к сожалению, на wine-2.0 наблюдается то же поведение, что и на eterhack и wwo. 00000112-0000-0000-c000-000000000046 это IOleObject Interface oleaut32,ole32=n не помогли. {ОбщийМодуль.ШаблоныДокументов.Модуль(84)}: Ошибка при вызове конструктора (COMОбъект) Word = Новый COMОбъект("Word.Application"); по причине: Unknown error 0x80070078 ошибка в заявке 0x800401F3 CO_E_CLASSSTRING ошибка при воспроизведении у нас 0x80004002 E_NOINTERFACE Интерфейс IOleObject реализован. Трудно сказать на сколько целиком. Видимо, не удается на определенном этапе создать объект. trace:ole:IClassFactory_CreateInstance_Proxy ((nil), {00000112-0000-0000-c000-000000000046}, 0x1d171c) IClassFactory_CreateInstance_Proxy создается для класса {000209ff-0000-0000-C000-000000000046} и в результате не может создать интерфейс IOleObject. вряд ли дело в ней самой, поскольку для других интерфейсов она все же работает хорошо. в реестре прописан и интерфейс IOleObject и класс {000209ff-0000-0000-C000-000000000046} при этом [HKEY_CLASSES_ROOT\Word.Application\CLSID] "{000209ff-0000-0000-C000-000000000046}" Заполнение буфера есть в NdrProxyGetBuffer, NdrSimpleStructMarshall, NdrProxySendReceive. Однако нельзя сказать, что код ошибки заносится именно здесь. NdrConvert вызывается, не реализовно. NdrConvert в настоящем случае не при чем. NdrPointerUnmarshall PointerUnmarshall NdrInterfacePointerUnmarshall в NdrInterfacePointerUnmarshall, когда RpcStream_Create создает поток. его size берется из pStubMsg->Buffer. size получается равен 0. Поменял заполнение буфера в IClassFactory_RemoteCreateInstance_Proxy. Поток после создания, стал направляться на COM_UnmarshalInterface (CoUnmarshalInterface). Однако в последствии при чтении (get_unmarshaler_from_stream) из него в объект, сигнатура не совпадала с OBJREF_SIGNATURE. написал тест воспроизводящий вызов CoCreateInstance с теми же параметрами, что и в 1с. В бутылке с установленным MSO2007 ошибка воспроизвелась. На windows - ошибка воспроизвелась. тест на vbs сработал и на windows, и на wine OleRun DefaultHandler_Run Удалось воспроизвести поведние 1с в тесте. Тест на Windows проходит без ошибок. В NdrDllGetClassObject поиск в FindProxyInfo, оканчивается безрезультатно, вследствие чего IPSFactoryBuffer_QueryInterface не выполняется и возвращается CLASS_E_CLASSNOTAVAILABLE. Однако обрабатывается как-то странно, в результате CoCreateInstance заканчивается S_OK. Недоделанный объект отправляется в OleRun, где и происходит недопустимый вызов, который, в свою очередь, приводит к падению. в DefaultHandler_Run при вызове CoCreateInstance используется в качестве параметра dwClsContext CLSCTX_LOCAL_SERVER, а необходимо CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER| CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER. Это исправляет падение. Однако по всей видимости создание происходит все-равно неправильно. Не удается получить clsid trace:ole:CoCreateInstance (rclsid={000209ff-0000-0000-c000-000000000046}, pUnkOuter=(nil), dwClsContext=00000017, riid={00000112-0000-0000-c000-000000000046}, ppv=0x13534c) fixme:ole:CoCreateInstance return address 0x7e78f04b trace:ole:CoGetClassObject CLSID: {000209ff-0000-0000-c000-000000000046},IID: {00000001-0000-0000-c000-000000000046} warn:ole:get_inproc_class_object class {000209ff-0000-0000-c000-000000000046} not registered inproc trace:ole:apartment_getclassobject calling ole32!DllGetClassObject trace:ole:NdrDllGetClassObject ({000209ff-0000-0000-c000-000000000046}, {00000001-0000-0000-c000-000000000046}, 0x60fcec, 0x7e871d98, {00000320-0000-0000-c000-000000000046}, 0x7e871ed4) trace:ole:FindProxyInfo not found warn:ole:NdrDllGetClassObject class {000209ff-0000-0000-c000-000000000046} not available Происходит следующее: 1- CoGetClassObject передается clsid Word.Application. 2- Вызов get_inproc_class_object для dwClsContext имеющего значение CLSCTX_INPROC_SERVER завершается неудачей, поскольку не удается найти информацию об этом clsid. (not registered inproc) 3- Происходит вызов get_inproc_class_object для dwClsContext имеющего значение CLSCTX_INPROC_HANDLER, перед этим удается получить hkey. Далее вызывается apartment_getclassobject. 4- Вызов NdrDllGetClassObject завершается неудачей, поскольку FindProxyInfo не удается обнаружить описания для запрашиваемого clsid. 5- Тогда вызывается Handler_DllGetClassObject, которая завершается успешно. делаю тест Выявляющий проблему тест приводит к падению, поэтому добавить его в Wine проблематично. Патч для ole2.c принат на winehq@. Отправил еще и тест. Пока не ясна причина генерации сообщения из 1с. В результате очередного вызова DefaultHandler_NDIUnknown_QueryInterface не удается выяснить какого типа объект по переданному riid(00020400-0000-0000-c000-000000000046). Возвращается E_NOINTERFACE (0ч80004002). В реестре запись HKCR\Interface\{00020400-0000-0000-C000-000000000046} есть. Если включить обработку IDispatch, то DefaultHandler_NDIUnknown_QueryInterface завершается успешно, обращение к ole библиотекам прекращается, однако заполнения полей не происходит. Приложение не висит. Но в kernel32 начинается обработка ошибки. (В ответ на comment #23) > В результате очередного вызова DefaultHandler_NDIUnknown_QueryInterface не > удается выяснить какого типа объект по переданному > riid(00020400-0000-0000-c000-000000000046). Возвращается E_NOINTERFACE > (0ч80004002). Дописал тест для воспроизведения настоящей ситуации. winedebug по ole и relay ничего интересного не дали. С нашими исправлениями в 1с77 с установленным vcrun2010 (и естественно officee) работает создание COM объектов. С нашими исправлениями в 1с82 с установленным vcrun2010 и officee по-прежнему работает создание COM объектов. Макрос в Excel (Office 2007) создающий объект Word.Application на Windows работает правильно, на wine не срабатывает. (В ответ на comment #26) 1 - Проверил заново > Макрос в Excel (Office 2007) создающий объект Word.Application на Windows > работает правильно, на wine не срабатывает. В Word 2007 создан макрос Set WordApp = New Word.Application WordApp.Visible = True Set DocWord = WordApp.Documents.Add DocWord.Activate Выполняется на Windows, wwo и eterhack успешно от начала до конца. 2 - В 1с82 создание простого объекта, не связанного с офисом SimpleObj = Новый COMОбъект("Scripting.FileSystemObject"); проходит успешно. 3 - В 1с83 создание Word = Новый COMОбъект("Word.Application"); не удается как и в 1с82 4- При При создании Word.Application в office trace:ole:RPC_RegisterInterface ({00000122-0000-0000-c000-000000000046}) trace:ole:RPC_RegisterInterface Creating new interface .... trace:rpc:RPCRT4_start_listen trace:ole:stub_manager_int_release after 1 При создании в 1с trace:ole:RPC_RegisterInterface ({00000122-0000-0000-c000-000000000046}) trace:ole:stub_manager_int_release after 1 Сравнение логов 1с77 и 1с82 показало, что в 82 при создании COM объекта запрашиваются еще два дополнительных интерфейса: warn:ole:DefaultHandler_NDIUnknown_QueryInterface () : asking for un supported interface {e7210190-61f4-11d4-941d-008048da11f9} warn:ole:DefaultHandler_NDIUnknown_QueryInterface () : asking for un supported interface {fd7b6cc3-dc8e-11d2-b8d0-008048da0335} В реестре их нет ни в wine, ни в windows. Однако windows каким-то образом с этим справляется. Сделал заглушку в wine, не помогло, поведение то же самое. Стоит проверить IDispatch. Кроме этих интерфейсов проблемы возникали только, когда 1с дергает его. работаю над багой Внес изменения в DefaultHandler_NDIUnknown_QueryInterface, обработку IID_IDispatch. Кроме того, при создании COM-объекта в дальнейшем 1с дергает 2 собственных интерфейса, на что получает E_NOINTERFACE даже на windows, IUnknown - удачно, интерфейс IDispatchEx {a6ef9860-c720-11d0-9337-00a0c90dcaa9} - неудачно. Однако создание объекта завершается нормально. STORAGE_CreateOleStream printf("Таблицы %p--->%p", storage->lpVtbl->CreateStream, StorageBaseImpl_CreateStream); у storage, который передается в STORAGE_CreateOleStream, указатель на таблицу виртуальных функций null. Поэтому попытка вызова функции создания потока приводит к зависанию. Этот storage хранится статически в dll-ке 1с core82 с адресом 0x10223b1c. Проинициализирован 0. Написал тест, вызывающий InitNew с подобным объектом, на windows он, естественно, не прошел. Видимо при запуске не windows этот объект инициализируется нормально и в него заносится адрес таблицы виртуальных функций, а в wine такого не происходит. grep 0x10223b1c по логам relay показал, что этот адрес передается только единожды в InitNew как раз-таки. Частично удалась идея создания экземпляра сторэджа вручную. Нужно выяснить, на сколько дальше он используется. работаю над багой работаю над багой На windows данные по адресу 0x10223b1c не изменяются. 1c 8.2.14.540 адрес содержащий нулевой сторадж pStg, который передается в InitNew, 0x1021fb0c. В windows этот адрес после загрузки заполнен нулями. Потом он заполняется данными. что касается https://bugs.etersoft.ru/show_bug.cgi?id=7371#c18 обновила локальную eter-2.0,проверила наличие указанных патчей. Ошибка не появилась,программа при нажатии "загрузить" просто остается в "думающем" состоянии (без зависания-можно переключаться между окнами и работать дяльше). (В ответ на comment #41) > Ошибка не появилась,программа при нажатии "загрузить" просто остается в > "думающем" состоянии Это продолжение проблемы, загрузка не происходит до конца. Неясно зачем в InitNew делать STORAGE_CreateOleStream и в Load load_ole_stream. Потом указателя на поток не возвращается, больше с потоком ничего не делается. Попытался убрать некоторые вызовы, в том числе и рекурсивные, не помогло. Попытался сделать функцию для создания storage, по типу создания потока STORAGE_CreateOleStream, нужно еще доделать. После StgCreateStorageEx выполнение без каких-либо условий IStorage_AddRef помогло решить проблему с зависанием, однако открыть Documents в Word по прежнему не удается. "Поле Documents не обнаружено" В DefaultHandler_NDIUnknown_QueryInterface не хватает обработки IID_IDispatchEx, который также запрашивается при создании COM-объекта в 1c. Описывается IID_IDispatchEx в библиотеке dispex. Протащить его в oleaut32 пока не удалось. Добавил IID_IDispatchEx, вызовы InitNew и Load с неверными параметрами перестали происходить, однако после выполнения QueryInterface на все необходимые iid, Documents.Open не выполняется до конца, при этом 1c не зависает. После перебора интерфейсов Выполняется попытка trace:ole:RegisterDragDrop (0x30162,0x405e950) Затем снова вызывается trace:ole:CoMarshalInterface (0x1e3990, {00000122-0000-0000-c000-000000000046}, 0x35aa540, 0, (nil), MSHLFLAGS_TABLESTRONG) Также не ясно, зачем происходит обращение trace:ole:apartment_getclassobject found L"C:\\windows\\system32\\ole32.dll" already loaded После выполнения DefaultHandler_NDIUnknown_QueryInterface для IID_IDispatchEx управление возвращается 1с. Попадания в критическую секцию, из котоой не удается выбраться, обнаружить не удалось. Тестовая обработка срабатывает только с таким сочетанием WINEDLLOVERRIDES=ole32=n,kernel32=n ww 1cv8.exe Сама конфигурация, запущенная таким образом, при воспроизведении баги валится с ошибкой 80070078. http://www.almuseo.com/0x80070078.php По всей видимости, проблема комплексная. В связи с https://bugs.etersoft.ru/show_bug.cgi?id=9006 попытался найти причину зависания. Судя по трэйсу +ole, виснет уже после того как выполнен набор вызовов DefaultHandler_NDIUnknown_QueryInterface. Установил, что зависание получается в функции DefaultHandler_SetClientSite при попытке добавить client site (IOleClientSite_AddRef). При этом перед AddRef проводится release, если проверка на то, что client site уже была. Написал тестовую программку, воспроизводящую проблему. Сделал wine-тест воспроизводящий проблему с нехваткой IDispatch. Было бы неплохо в него добавить еще и часть про SetClientSite. hr = IOleObject_SetClientSite((IOleObject *)dispatch, clientsite); todo_wine ok(hr == S_OK, "got %08x\n", hr); DefaultHandler_SetClientSite вызывается из core82. Почему не работает IOleClientSite_AddRef пока не ясно. Отправил тест на SetClientSite, он проходит нормально. По всей видимости должно работать, вообще без добавления других интерфейсов в DefaultHandler_NDIUnknown_QueryInterface, поскольку тест, который проходит для wine с этим хаком на windows падает. Поскольку вызов DefaultHandler_NDIUnknown_QueryInterface для IID_IDispatch, тестовая программка на wine ведет себя так же как и windows, осуществляется из core32, значит объект создан не так как это делает windows. Попробовал дописать в DefaultHandler_Run (функция, кторая работала до возвращения управления core32) вызов IOleObject_GetMiscStatus, IOleObject_GetMoniker, IOleCache_OnRun. Не помогло. Я думаю,ч/RT/25718/то это абсолютно то же самое,что и https://bugs.etersoft.ru/show_bug.cgi?id=8689 но все же действия: http://bugs.etersoft.ru/show_bug.cgi?id=8689#c0 выполняются также корректно. бутылка 1c82/1c82 бд ладога (В ответ на comment #59) это с приложенным вышеуказанным патчем WINE@Etersoft SQL 2.1.2/2.1.0-eter19/3 Проблемы нет.Проверено тут: https://bugs.etersoft.ru/show_bug.cgi?id=9349 |