Bug 8689

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: Связано с:
Дата напоминания:

Description Дмитрий Галочкин 2012-08-30 20:31:14 MSK
возникает ошибка при экспорте в тестовый офис 2003 в wine 2.0.2-eter15/3 из 1С 
конфигурация 1С - /var/ftp/pvt/Windows/Testing/RT/25718/ladoga.tar.gz
пользователь: Администратор

последовательность действий:

"Основное меню" - "Справочники" - "Предприятие" - "Шаблоны документов". В открывшемся справочнике создать новый элемент (или берешь существующий без разницы), жмешь "Загрузить" (по этой кнопке загружается word-шаблон).

Используется какой-то шаблон (занесены некоторые переменные) лежат /var/ftp/pvt/Windows/Testing/RT/25718/templates.tar.gz (win_c\1c_pic\Шаблоны)
Comment 1 Svetlana Zhukova 2012-09-05 11:17:22 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/

Ошибка воспроизводится.
Comment 2 Роман Дадьков 2012-09-06 11:21:12 MSK
у нас уже была подобная бага 6096.
Comment 3 Роман Дадьков 2012-09-06 12:02:47 MSK
на wwo такое же поведение. если верить, баге 6096 на wine-2.0 загрузка шаблона все-таки происходила, но на данный момент, к сожалению, на wine-2.0 наблюдается то же поведение, что и на eterhack и wwo.
00000112-0000-0000-c000-000000000046 это IOleObject Interface
Comment 4 Роман Дадьков 2012-09-06 12:45:12 MSK
oleaut32,ole32=n не помогли. 
{ОбщийМодуль.ШаблоныДокументов.Модуль(84)}: Ошибка при вызове конструктора (COMОбъект)
	Word = Новый COMОбъект("Word.Application");
по причине:
Unknown error 0x80070078
Comment 5 Роман Дадьков 2012-09-06 16:19:17 MSK
ошибка в заявке 0x800401F3 CO_E_CLASSSTRING
ошибка при воспроизведении у нас 0x80004002 E_NOINTERFACE
Comment 6 Роман Дадьков 2012-09-06 19:27:26 MSK
Интерфейс IOleObject реализован. Трудно сказать на сколько целиком.
Видимо, не удается на определенном этапе создать объект.
Comment 7 Роман Дадьков 2012-09-07 13:43:13 MSK
trace:ole:IClassFactory_CreateInstance_Proxy ((nil), {00000112-0000-0000-c000-000000000046}, 0x1d171c)
Comment 8 Роман Дадьков 2012-09-07 18:00:47 MSK
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}"
Comment 9 Роман Дадьков 2012-09-12 13:17:53 MSK
Заполнение буфера есть в NdrProxyGetBuffer, NdrSimpleStructMarshall, NdrProxySendReceive. Однако нельзя сказать, что код ошибки заносится именно здесь.
NdrConvert вызывается, не реализовно.
Comment 10 Роман Дадьков 2012-09-12 14:30:21 MSK
NdrConvert в настоящем случае не при чем.
Comment 11 Роман Дадьков 2012-09-12 18:27:36 MSK
NdrPointerUnmarshall 
PointerUnmarshall
NdrInterfacePointerUnmarshall
Comment 12 Роман Дадьков 2012-09-13 12:47:42 MSK
в NdrInterfacePointerUnmarshall, когда RpcStream_Create создает поток. его size берется из pStubMsg->Buffer. size получается равен 0.
Comment 13 Роман Дадьков 2012-09-14 19:45:59 MSK
Поменял заполнение буфера в IClassFactory_RemoteCreateInstance_Proxy.
Поток после создания, стал направляться на COM_UnmarshalInterface (CoUnmarshalInterface). Однако в последствии при чтении (get_unmarshaler_from_stream) из него в объект, сигнатура не совпадала с OBJREF_SIGNATURE.
Comment 14 Роман Дадьков 2012-09-20 21:07:11 MSK
написал тест воспроизводящий вызов CoCreateInstance с теми же параметрами, что и в 1с. В бутылке с установленным MSO2007 ошибка воспроизвелась. На windows - ошибка воспроизвелась.
тест на vbs сработал и на windows, и на wine
Comment 15 Роман Дадьков 2012-09-21 21:07:18 MSK
OleRun
DefaultHandler_Run
Comment 16 Роман Дадьков 2012-09-26 20:10:51 MSK
Удалось воспроизвести поведние 1с в тесте. Тест на Windows проходит без ошибок. В NdrDllGetClassObject поиск в FindProxyInfo, оканчивается безрезультатно, вследствие чего IPSFactoryBuffer_QueryInterface не выполняется и возвращается CLASS_E_CLASSNOTAVAILABLE. Однако обрабатывается как-то странно, в результате CoCreateInstance заканчивается S_OK. Недоделанный объект отправляется в OleRun, где и происходит недопустимый вызов, который, в свою очередь, приводит к падению.
Comment 17 Роман Дадьков 2012-10-05 22:44:58 MSK
в 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
Comment 18 Роман Дадьков 2012-10-06 19:03:28 MSK
Происходит следующее:
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, которая завершается успешно.
Comment 19 Роман Дадьков 2012-10-08 17:58:02 MSK
делаю тест
Comment 20 Роман Дадьков 2012-10-09 16:02:12 MSK
Выявляющий проблему тест приводит к падению, поэтому добавить его в Wine проблематично.
Comment 21 Роман Дадьков 2012-10-12 14:19:46 MSK
Патч для ole2.c принат на winehq@. 
Отправил еще и тест.
Comment 22 Роман Дадьков 2012-10-12 14:21:52 MSK
Пока не ясна причина генерации сообщения из 1с.
Comment 23 Роман Дадьков 2012-10-12 17:39:48 MSK
В результате очередного вызова 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 24 Роман Дадьков 2012-10-13 22:05:47 MSK
(В ответ на comment #23)
> В результате очередного вызова DefaultHandler_NDIUnknown_QueryInterface не
> удается выяснить какого типа объект по переданному
> riid(00020400-0000-0000-c000-000000000046). Возвращается E_NOINTERFACE
> (0ч80004002).
Дописал тест для воспроизведения настоящей ситуации. winedebug  по ole и relay ничего интересного не дали.
Comment 26 Роман Дадьков 2012-10-18 22:32:46 MSK
С нашими исправлениями в 1с77 с установленным vcrun2010 (и естественно officee) работает создание COM объектов.
С нашими исправлениями в 1с82 с установленным vcrun2010 и officee по-прежнему работает создание COM объектов.
Макрос в Excel (Office 2007) создающий объект Word.Application на Windows работает правильно, на wine не срабатывает.
Comment 27 Роман Дадьков 2012-10-19 21:29:21 MSK
(В ответ на 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
Comment 28 Роман Дадьков 2012-10-22 17:02:14 MSK
Сравнение логов 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, не помогло, поведение то же самое.
Comment 29 Роман Дадьков 2012-10-30 22:39:49 MSK
Стоит проверить IDispatch. Кроме этих интерфейсов проблемы возникали только, когда 1с дергает его.
Comment 30 Роман Дадьков 2012-11-01 21:26:00 MSK
работаю над багой
Comment 31 Роман Дадьков 2012-11-02 17:08:53 MSK
Внес изменения в DefaultHandler_NDIUnknown_QueryInterface, обработку IID_IDispatch. Кроме того, при создании COM-объекта в дальнейшем 1с дергает 2 собственных интерфейса, на что получает E_NOINTERFACE даже на windows, IUnknown - удачно, интерфейс IDispatchEx {a6ef9860-c720-11d0-9337-00a0c90dcaa9} - неудачно. Однако создание объекта завершается нормально.
Comment 33 Роман Дадьков 2012-11-02 21:54:00 MSK
STORAGE_CreateOleStream
printf("Таблицы  %p--->%p", storage->lpVtbl->CreateStream, StorageBaseImpl_CreateStream);
Comment 34 Роман Дадьков 2012-11-03 20:42:34 MSK
у storage, который передается в STORAGE_CreateOleStream, указатель на таблицу виртуальных функций null. Поэтому попытка вызова функции создания потока приводит к зависанию. Этот storage хранится статически в dll-ке 1с core82 с адресом 0x10223b1c. Проинициализирован 0. Написал тест, вызывающий InitNew с подобным объектом, на windows он, естественно, не прошел. Видимо при запуске не windows этот объект инициализируется нормально и в него заносится адрес таблицы виртуальных функций, а в wine такого не происходит.
Comment 35 Роман Дадьков 2012-11-05 21:29:16 MSK
grep 0x10223b1c по логам relay показал, что этот адрес передается только единожды в InitNew как раз-таки.
Частично удалась идея создания экземпляра сторэджа вручную. Нужно выяснить, на сколько дальше он используется.
Comment 36 Роман Дадьков 2012-11-06 21:02:36 MSK
работаю над багой
Comment 37 Роман Дадьков 2012-11-09 21:04:08 MSK
работаю над багой
Comment 38 Роман Дадьков 2012-11-24 20:51:14 MSK
На windows данные по адресу 0x10223b1c не изменяются.
Comment 39 Роман Дадьков 2012-11-27 18:33:01 MSK
1c 8.2.14.540 адрес содержащий нулевой сторадж pStg, который передается в InitNew, 0x1021fb0c. В windows этот адрес после загрузки заполнен нулями. Потом он заполняется данными.
Comment 41 Svetlana Zhukova 2012-12-21 17:15:48 MSK
что касается
https://bugs.etersoft.ru/show_bug.cgi?id=7371#c18
обновила локальную eter-2.0,проверила наличие указанных  патчей.
Ошибка не появилась,программа при нажатии "загрузить" просто остается в "думающем" состоянии (без зависания-можно переключаться между окнами и работать дяльше).
Comment 42 Роман Дадьков 2012-12-21 17:26:08 MSK
(В ответ на comment #41)

> Ошибка не появилась,программа при нажатии "загрузить" просто остается в
> "думающем" состоянии 
Это продолжение проблемы, загрузка не происходит до конца.
Comment 43 Роман Дадьков 2012-12-24 21:09:09 MSK
Неясно зачем в InitNew делать STORAGE_CreateOleStream и в Load load_ole_stream. Потом указателя на поток не возвращается, больше с потоком ничего не делается. Попытался убрать некоторые вызовы, в том числе и рекурсивные, не помогло. Попытался сделать функцию для создания storage, по типу создания потока STORAGE_CreateOleStream, нужно еще доделать.
Comment 44 Роман Дадьков 2012-12-25 18:04:37 MSK
После StgCreateStorageEx выполнение без каких-либо условий IStorage_AddRef помогло решить проблему с зависанием, однако открыть Documents в Word по прежнему не удается. "Поле Documents не обнаружено"
Comment 45 Роман Дадьков 2012-12-28 20:25:52 MSK
В DefaultHandler_NDIUnknown_QueryInterface не хватает обработки IID_IDispatchEx, который также запрашивается при создании COM-объекта в 1c. Описывается IID_IDispatchEx в библиотеке dispex. Протащить его в oleaut32 пока не удалось.
Comment 46 Роман Дадьков 2013-01-03 18:34:13 MSK
Добавил IID_IDispatchEx, вызовы InitNew и Load с неверными параметрами перестали происходить, однако после выполнения QueryInterface на все необходимые iid, Documents.Open не выполняется до конца, при этом 1c не зависает.
Comment 47 Роман Дадьков 2013-01-05 20:54:31 MSK
После перебора интерфейсов 
Выполняется попытка 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
Comment 49 Роман Дадьков 2013-01-16 16:39:35 MSK
После выполнения DefaultHandler_NDIUnknown_QueryInterface для IID_IDispatchEx управление возвращается 1с. Попадания в критическую секцию, из котоой не удается выбраться, обнаружить не удалось.
Comment 50 Роман Дадьков 2013-01-22 21:14:09 MSK
Тестовая обработка срабатывает только с таким сочетанием
WINEDLLOVERRIDES=ole32=n,kernel32=n ww 1cv8.exe
Сама конфигурация, запущенная таким образом, при воспроизведении баги валится с ошибкой 80070078. http://www.almuseo.com/0x80070078.php
По всей видимости, проблема комплексная.
Comment 51 Роман Дадьков 2013-02-08 20:09:09 MSK
В связи с 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);
Comment 52 Роман Дадьков 2013-02-12 17:03:22 MSK
DefaultHandler_SetClientSite вызывается из core82. Почему не работает IOleClientSite_AddRef пока не ясно.
Comment 53 Роман Дадьков 2013-02-13 17:42:24 MSK
Отправил тест на SetClientSite, он проходит нормально. По всей видимости должно работать, вообще без добавления других интерфейсов в DefaultHandler_NDIUnknown_QueryInterface, поскольку тест, который проходит для wine с этим хаком на windows падает.
Comment 54 Роман Дадьков 2013-03-05 21:05:41 MSK
Поскольку вызов DefaultHandler_NDIUnknown_QueryInterface для IID_IDispatch, тестовая программка на wine ведет себя так же как и windows, осуществляется из core32, значит объект создан не так как это делает windows. Попробовал дописать в DefaultHandler_Run (функция, кторая работала до возвращения управления core32) вызов IOleObject_GetMiscStatus, IOleObject_GetMoniker, IOleCache_OnRun. Не помогло.
Comment 59 Svetlana Zhukova 2013-06-10 15:41:57 MSK
Я думаю,ч/RT/25718/то это абсолютно то же самое,что и 
https://bugs.etersoft.ru/show_bug.cgi?id=8689
но все же действия:
http://bugs.etersoft.ru/show_bug.cgi?id=8689#c0
выполняются также корректно.
бутылка 1c82/1c82 бд ладога
Comment 60 Svetlana Zhukova 2013-06-10 15:43:46 MSK
(В ответ на comment #59)
это с приложенным вышеуказанным патчем
Comment 62 Svetlana Zhukova 2013-06-11 12:26:00 MSK
WINE@Etersoft SQL 2.1.2/2.1.0-eter19/3
Проблемы нет.Проверено тут: https://bugs.etersoft.ru/show_bug.cgi?id=9349