Укажите отработанное время

Отработанное время:
Продуктивное время:
Bug 11938 - Регресс исправления проблемы формирования баркода | wine-etersoft 2.1.4   Make a simular bug
Summary: Регресс исправления проблемы формирования баркода | wine-etersoft 2.1.4
Status: CLOSED FIXED
Alias: None
Product: WINE@Etersoft
Classification: Продукты (Products)
Component: Общее (show other bugs)
Version: unspecified
Hardware: PC Linux
: P4 normal
Target Milestone: ---
Deadline: 2017-09-13
Assignee: Dmitry Timoshkov
QA Contact: Konstantin Artyushkin
URL:
Whiteboard:
Keywords:
Depends on: 12297
Blocks:
  Show dependency treegraph
 
In work:
Reported: 2017-09-05 16:45 MSK by Konstantin Artyushkin
Modified: 2018-02-02 15:09 MSK (History)
3 users (show)

See Also:
Заявки RT: 47665
Связано с:
Дата напоминания:


Attachments
патч для тестирования в задаче 10868 (461 bytes, text/plain)
2017-09-11 17:58 MSK, Dmitry Timoshkov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin Artyushkin 2017-09-05 16:45:51 MSK
Снова воспроизводится проблема https://bugs.etersoft.ru/show_bug.cgi?id=10620

При формировании баркода всегда используется значение по умолчанию.

Воспроизведение:
Бутылка swine 2.1 rt/47665
1) Запускаем 1cv7l.exe
2) Файл -> открыть -> c:/Program Files/1Cv77/BIN/etersoft.ert
3) Вводим любое число и нажимаем "Сформировать"
4) Получаем окно "предварительным просмотром" в котором сам баркод всегда имеет вид "/ 106  675  /13635.4/s/s". Это же значение всегда печатается на принтер.

В windows xp в пункте 4 значение баркода меняется на вводимое значение из пункта 3.

Сама компонента лежит по адресу /c:/Program Files/1Cv77/BIN/BARCODE1.OCX.
Установка компоненты как в wine, так и в windows xp выполнялась командой regsvr32 BARCODE1.OCX
Comment 1 Dmitry Timoshkov 2017-09-05 16:53:59 MSK
Пожалуйста создайте архив с подготовленный префиксом.

Так же непонятно, с какой версией wine проводилось тестирование и
соответственно относительно какой версии wine произошла регрессия?
Comment 2 Konstantin Artyushkin 2017-09-06 14:11:25 MSK
md5sum server:/net/wine/eter-2.1/bottles/rt/wine-47665.tar.gz 9c24b9eb66bf567a252f7019fd6ed81a 

wine --version
WINE@Etersoft SQL 2.1.4-eter29/7
Product: WINE@Etersoft 2.0 SQL Local Network CAD School
Licensed for ООО "Этерсофт" with registration number EEEE-EAEA
Contact person: Системный администратор
License expired at 16/11/2018

wine-etersoft-gl-2.1.4-alt29.i586
wine-etersoft-2.1.4-alt29.i586
wine-etersoft-sql-2.1.4-alt7.i586

Такие патчи были бэкпортированы из vanilla в прошлый раз https://bugs.etersoft.ru/show_bug.cgi?id=10620#c4 

* Пн июл 06 2015 Etersoft Builder <builder@etersoft.ru> 2.1.3-alt21
- ole32: Read the class id from the top-level storage object. (eterbug #10620)
- ole32: A cache entry should hold the stream its data is from, not the top-level storage. (eterbug #10620)
- ole32: Split the data loading into a couple of helpers. (eterbug #10620)
- ole32: Add support for parsing the 'CONTENTS' stream. (eterbug #10620)
Comment 3 Dmitry Timoshkov 2017-09-07 17:48:26 MSK
Насколько я могу судить в задаче 10620 использовалась другая версия
генератора баркодов - barcode.ocx. Здесь же используется BARCODE1.OCX.
Так префикс из задачи 10620 у меня не сохранился, то я не могу проверить,
как работает генератор баркодов в том префисе и на самом ли деле произошла
регрессия.

Константин, почему Вы решили, что это регрессия? С какой версий eter-2.1
генерация баркодов в обработке etersoft.ert работает корректно? Вы можете
протестировать генерацию баркодов в префиксе из задачи 10620 и сообщить
результаты?
Comment 4 Konstantin Artyushkin 2017-09-07 18:36:22 MSK
(Ответ Dmitry Timoshkov на комментарий3)
> Насколько я могу судить в задаче 10620 использовалась другая версия
> генератора баркодов - barcode.ocx. Здесь же используется BARCODE1.OCX.
> Так префикс из задачи 10620 у меня не сохранился, то я не могу проверить,
> как работает генератор баркодов в том префисе и на самом ли деле произошла
> регрессия.
> 
> Константин, почему Вы решили, что это регрессия? С какой версий eter-2.1
> генерация баркодов в обработке etersoft.ert работает корректно? Вы можете
> протестировать генерацию баркодов в префиксе из задачи 10620 и сообщить
> результаты?

Интересная информация. Я просто опирался на контрольные суммы, потому как определить версию ocx не знаю.

$ md5sum /var/ftp/pvt/Windows/Testing/RT/39711/DB/BARCODE.OCX
ae73bcf080e366d21214e3c481b35bb6  /var/ftp/pvt/Windows/Testing/RT/39711/DB/BARCODE.OCX

<wine@eter-2 bottle rt/47665>$ md5sum 1Cv77/BIN/BARCODE1.OCX 
ae73bcf080e366d21214e3c481b35bb6  1Cv77/BIN/BARCODE1.OCX

Создал новую бутылку swine 2.1 rt/47665-2. Зарегистрировал там баркод из 10620 var/ftp/pvt/Windows/Testing/RT/39711/DB/BARCODE.OCX - проблема воспроизводится.

Осталась бутылка swine 2.1 bugs/10620. Но там какая-то проблема с правами на каталог с базой. Пока разбираюсь.
Comment 5 Dmitry Timoshkov 2017-09-11 08:19:28 MSK
Согласно логам данная проблема связана с работой с потоками в OLE Compound
Storage. Замена ole32.dll на версию из Windows 98 делает генерирование и
отображение цифр на баркоде соответствующим вводимым. Это поведение аналогично
тому, что было зафиксировано при исследовании задачи 10620.

(In reply to Konstantin Artyushkin from comment #4)
> Осталась бутылка swine 2.1 bugs/10620. Но там какая-то проблема с правами на
> каталог с базой. Пока разбираюсь.

Константин, как разберетесь - пожалуйста создайте архив для префикса 10620,
мне хотелось бы поэкспериментировать с ним.

По прежнему остался неотвеченным вопрос в какой версии eter-2.1 проблема
не воспроизводится и соответственно почему это регрессия.
Comment 6 Konstantin Artyushkin 2017-09-11 16:36:06 MSK
(Ответ Dmitry Timoshkov на комментарий5)
> Константин, как разберетесь - пожалуйста создайте архив для префикса 10620,
> мне хотелось бы поэкспериментировать с ним.
> 
Проблема с файлами, к сожалению, всё ещё присутствует. Разобраться не удалось

> По прежнему остался неотвеченным вопрос в какой версии eter-2.1 проблема
> не воспроизводится и соответственно почему это регрессия.

  Рабочей версией можно считать ту что описана в комментарии №2, так как она несёт в себе исправление проблемы из задания 10620
* Пн июл 06 2015 Etersoft Builder <builder@etersoft.ru> 2.1.3-alt21

  "...соответственно почему это регрессия?" - была проблем, её решили. Спустя некоторое время проблема снова появилась. Может, конечно, термин "регрессия не подходящий, тогда просто скажите подходящий термин и я заменю заглавие.

  Раз проблему с файлами преодолеть не получилось, то я решил пойти другим путём и собрал wine-etersoft 2.1.3-alt21. Затем запустил через эту версию 1С в бутылке swine 2.1 rt/47665. Проблема с неправильным формированием штрих-кода исчезла - предпросмотр и печать отображают то что написано в форме ввода.

С помощью git bisect удалось выяснить что проблема появляется в wine-etersoft-alt27 с появлением коммита
 
commit 76f01029ae602cf0f287ed71a07c8e28f409fa2d
Author: Dmitry Timoshkov <dtimoshkov@etersoft.ru>
Date:   Tue Oct 20 18:06:21 2015 +0800

    ole32: Do not fail to load data in unknown format. (eterbug #10868).
    
    This is just a quick hack, a proper investigation is needed.
Comment 7 Dmitry Timoshkov 2017-09-11 17:09:36 MSK
(In reply to Konstantin Artyushkin from comment #6)

> С помощью git bisect удалось выяснить что проблема появляется в
> wine-etersoft-alt27 с появлением коммита
>  
> commit 76f01029ae602cf0f287ed71a07c8e28f409fa2d
> Author: Dmitry Timoshkov <dtimoshkov@etersoft.ru>
> Date:   Tue Oct 20 18:06:21 2015 +0800
> 
>     ole32: Do not fail to load data in unknown format. (eterbug #10868).
>     
>     This is just a quick hack, a proper investigation is needed.

Большое спасибо Константин. Хотя этого коммита сейчас нет ни в ветке eter-2.1
ни в winehq/wine-staging (он был заменен портированными патчами из winehq,
которые содержали более корректное исправление), но тем не менее 1С ни в
одной из этих веток не может правильно показать баркод, везде вместо 123...
показывается абракадабра.

Однако найденный коммит указал на кусок кода, который ведет к проблеме с
генерированием баркода. До моего коммита проблема была вызвана загрузкой
потока "Contents" в неизвесном формате, теперь проблема вызвана загрузкой
потока "Presentation" в неизвестном формате. Быстрый хак, запрещающий
загрузку потока "Presentation" позволяет исправить генерирование баркода.

Я добавил небольшой хак, сохраняющий содержимое куска памяти с данными,
загружаемыми ole32 и попробую выяснить, что с ним не так и написать тест.
Comment 8 Dmitry Timoshkov 2017-09-11 17:58:02 MSK
дополнительное исследование показало, что откат исправления для задачи
https://bugs.etersoft.ru/show_bug.cgi?id=10868 в ветке eter-2.1 а так же
в wine-staging решает проблему с отображением сгенерированного баркода.

Так как исправление для задачи 10868 позволяло загрузить OLE документ с
неизвестным потоком, то необходимо протестировать откат патча с префиксом
из той задачи, принимая во внимание, что патчи, портированные из winehq,
могут уже исправить проблему в задаче 10868.

Константин, Вы не могли бы либо подготовить префикс для задачи 10868 для
меня либо протестировать патч, который я сейчас приложу с префиксом из
задачи 10868 и сообщить результат?
Comment 9 Dmitry Timoshkov 2017-09-11 17:58:37 MSK
Created attachment 3504 [details]
патч для тестирования в задаче 10868
Comment 10 Konstantin Artyushkin 2017-09-13 14:51:03 MSK
(Ответ Dmitry Timoshkov на комментарий9)
> Создано attachment 3504 [details]
> патч для тестирования в задаче 10868

Протестировал этот патч в бутылке swine 2.1 rt/40375 из задания 10868.
Получаем "Ошибка открытия документа".

При этом данный патч исправляет проблему из данного задания. 

Создал архив server:/net/wine/eter-2.1/bottles/rt/wine-40375.tar.gz
$ md5sum wine-40375.tar.gz 
f8d7f4e25b03d06cb255dd32e9735de8  wine-40375.tar.gz
Comment 11 Konstantin Artyushkin 2017-09-13 14:52:36 MSK
(Ответ Konstantin Artyushkin на комментарий10)
> 
> Протестировал этот патч в бутылке swine 2.1 rt/40375 из задания 10868.
> Получаем "Ошибка открытия документа".
> 
> При этом данный патч исправляет проблему из данного задания. 

Другими словами патч правит текущую проблему, но вновь появляется проблема из задания 10868
Comment 12 Dmitry Timoshkov 2017-09-20 15:01:42 MSK
После многочисленных попыток найти источник проблемы, написания различных
тестов и прочих хаков я думаю, что нашел причину регрессии. После моего
патча, позволяющего загружать потоки Presentation в неизвестном формате,
не работает сохранение загруженных потоков методом ::Save когда приложение
устанавливает флаг fSameAsLoad = FALSE. До моего патча из OLE storage не
загружалось ничего, ::Save ничего не сохранял и баркоды генерировались
снова, так как storage оказывался пустым. После моего патча ::Save сохранял
мусор и вместо баркода показывался мусор.

Отправил патчи для принятия в wine-patches.
Comment 13 Dmitry Timoshkov 2017-09-20 16:36:49 MSK
(In reply to Dmitry Timoshkov from comment #12)
> После многочисленных попыток найти источник проблемы, написания различных
> тестов и прочих хаков я думаю, что нашел причину регрессии. После моего
> патча, позволяющего загружать потоки Presentation в неизвестном формате,
> не работает сохранение загруженных потоков методом ::Save когда приложение
> устанавливает флаг fSameAsLoad = FALSE. До моего патча из OLE storage не
> загружалось ничего, ::Save ничего не сохранял и баркоды генерировались
> снова, так как storage оказывался пустым. После моего патча ::Save сохранял
> мусор и вместо баркода показывался мусор.
> 
> Отправил патчи для принятия в wine-patches.

Хью довольно оперативно отреагировал на мой патч:
---------------
>      /* this is a shortcut if nothing changed */
> -    if (!dirty && !fSameAsLoad && This->presentationStorage)
> +    if (!dirty && fSameAsLoad && This->presentationStorage)
>      {
>          return IStorage_CopyTo(This->presentationStorage, 0, NULL, NULL, pStg);
>      }

No, this isn't a typo.  The idea is to copy the loaded storage to a
fresh storage that is passed when fSameAsLoad is FALSE.

I'm aware that there are issues related to the storage handling
in both the cache and the default handler.  That's on my list
of things to look into, but feel free to investigate further.
---------------

Т.е. он в курсе, что текущий код wine работает неправильно, но тем не менее
считает мое исправление неверным без объяснения каких-либо причин.

Я полагаю, что мой патч вполне работоспособен, и так как он исправляет
реальную проблему, то его можно включить в ветку eter-2.1.
Comment 14 Dmitry Timoshkov 2017-09-20 16:45:54 MSK
(In reply to Dmitry Timoshkov from comment #13)
> Я полагаю, что мой патч вполне работоспособен, и так как он исправляет
> реальную проблему, то его можно включить в ветку eter-2.1.

Отправил патч для включения в ветку eter-2.1, отмечаю эту задачу как решенную.

Константин, пожалуйста проверьте исправление после принятия патча.
Comment 15 Dmitry Timoshkov 2017-09-22 18:00:39 MSK
(In reply to Dmitry Timoshkov from comment #13)
> (In reply to Dmitry Timoshkov from comment #12)
> > После многочисленных попыток найти источник проблемы, написания различных
> > тестов и прочих хаков я думаю, что нашел причину регрессии. После моего
> > патча, позволяющего загружать потоки Presentation в неизвестном формате,
> > не работает сохранение загруженных потоков методом ::Save когда приложение
> > устанавливает флаг fSameAsLoad = FALSE. До моего патча из OLE storage не
> > загружалось ничего, ::Save ничего не сохранял и баркоды генерировались
> > снова, так как storage оказывался пустым. После моего патча ::Save сохранял
> > мусор и вместо баркода показывался мусор.
> > 
> > Отправил патчи для принятия в wine-patches.
> 
> Хью довольно оперативно отреагировал на мой патч:
> ---------------
> >      /* this is a shortcut if nothing changed */
> > -    if (!dirty && !fSameAsLoad && This->presentationStorage)
> > +    if (!dirty && fSameAsLoad && This->presentationStorage)
> >      {
> >          return IStorage_CopyTo(This->presentationStorage, 0, NULL, NULL, pStg);
> >      }
> 
> No, this isn't a typo.  The idea is to copy the loaded storage to a
> fresh storage that is passed when fSameAsLoad is FALSE.
> 
> I'm aware that there are issues related to the storage handling
> in both the cache and the default handler.  That's on my list
> of things to look into, but feel free to investigate further.
> ---------------
> 
> Т.е. он в курсе, что текущий код wine работает неправильно, но тем не менее
> считает мое исправление неверным без объяснения каких-либо причин.

Полагаю, что я сейчас лучше понимаю, что имел в виду Хью. Переоткрываю эту
задачу для создания теста, воспроизводящего действия barcode.ocx. Согласно
логу barcode.ocx написан с помощью MFC, я нашел исходники MFC и создал
последовательность вызовов ole32, которые делает ocx. ole32 в wine содержит
какой-то тест для ILockBytes+IStorage, но barcode.ocx создает свой собственный
обработчик для записи содержимого IStorage, а wine тесты не содержат кода
для проверки содержимого созданного IStorage. Начал писать свою реализацию.
Comment 16 Dmitry Timoshkov 2017-10-03 13:05:28 MSK
Долго не мог понять как формируется содержимое, которое barcode.ocx
передает в OleLoad() и из которого создается и загружется проблемый
OLE storage. Пришлось сдампить кусок памяти, передаваемый в ole32.
CreateILockBytesOnHGlpbal() для изучения. Оказалось, что это кусок файла
etersoft.ert. По содержимому куска памяти + etersoft.ert я могу предположить,
что этот файл был создан под Windows (так там присутствует строка D:\WINDOWS,
а под wine это всегда c:\windows), но хотелось бы убедиться, что это
действительно так, чтобы отбросить предположение, что содержимое этого
файла может быть создано со старой версией wine и быть как-то несовместимым
с новым кодом работы с OLE storage.

Константин, Вы можете сообщить, где и как был создан файл etersoft.ert?
Comment 17 Konstantin Artyushkin 2017-10-03 16:16:02 MSK
(Ответ Dmitry Timoshkov на комментарий16)
> Константин, Вы можете сообщить, где и как был создан файл etersoft.ert?

Данный файл был прислан клиентом. Что именно мне нужно узнать у клиента?
Comment 18 Dmitry Timoshkov 2017-10-03 16:20:40 MSK
(In reply to Konstantin Artyushkin from comment #17)
> Данный файл был прислан клиентом. Что именно мне нужно узнать у клиента?

У клиента нужно уточнить, где и как был создан файл etersoft.ert.
Comment 19 Dmitry Timoshkov 2017-10-06 08:59:49 MSK
(In reply to Dmitry Timoshkov from comment #16)
> Долго не мог понять как формируется содержимое, которое barcode.ocx
> передает в OleLoad() и из которого создается и загружется проблемый
> OLE storage. Пришлось сдампить кусок памяти, передаваемый в ole32.
> CreateILockBytesOnHGlpbal() для изучения. Оказалось, что это кусок файла
> etersoft.ert. По содержимому куска памяти + etersoft.ert я могу предположить,
> что этот файл был создан под Windows (так там присутствует строка D:\WINDOWS,
> а под wine это всегда c:\windows)

Пришлось повозиться с тестом, так как MFC использует множество собственных
реализаций IStorage + IClientSite и как следствие вызовы OleLoad/OleSave
ведут к вызовам кода MFC, в свою очередь вызывающим ole32 для сохранения
данных в собственном формате в руками созданные потоки. В результате
я получил тест, загружающий содержимое сдампленного файла, и затем
из этого содержимого по максимально упрощенной схеме создает объект
и затем сохраняет его в новый IStorage. При этом выводится подробная
информация о потоках, присутствующих в оригинальном IStorage из файла
и нового IStorage. Оказалось, что в оригинале содержатся потоки
"Contents", "OlePres000" и "OlePres001", Wine сохраняет все эти потоки
как есть в новый IStorage, однако под Windows (или в Wine с ole32=n)
в новый IStorage сохраняются только потоки "OlePres000" и "OlePres001",
поток "Contents" не сохраняется. С моим патчем (включенным в eter-2.1)
сохраняется только поток "OlePres000", и баркод формируется корректно,
видимо присутствие потока "Contents" ломает какую-то логику внутри MFC.
Comment 20 Dmitry Timoshkov 2017-10-09 13:10:52 MSK
(In reply to Dmitry Timoshkov from comment #19)
> Пришлось повозиться с тестом, так как MFC использует множество собственных
> реализаций IStorage + IClientSite и как следствие вызовы OleLoad/OleSave
> ведут к вызовам кода MFC, в свою очередь вызывающим ole32 для сохранения
> данных в собственном формате в руками созданные потоки. В результате
> я получил тест, загружающий содержимое сдампленного файла, и затем
> из этого содержимого по максимально упрощенной схеме создает объект
> и затем сохраняет его в новый IStorage. При этом выводится подробная
> информация о потоках, присутствующих в оригинальном IStorage из файла
> и нового IStorage.

Написал генератор для создания потоков "Contents" и "OlePres000", чтобы
не тащить в тесте бинарный блоб, созданный непонятно кем и непонятно в
каком формате. Пришлось использовать данные из исходников Wine, хотя
была надежда, что опубликованные pdf в Miscrosoft Protocols содержат
описания форматов потоков "Contents" и "OlePres000". Даже упоминаемый
во многих источниках kb186898 не доступен на сайте MS, хотя поиск
его находит: https://support.microsoft.com/en-us/search?query=kb186898
Зато копия этого KB есть в другом месте:
"HOWTO: Read Compound Document Properties Directly with VC++":
https://stuff.mit.edu/afs/sipb/user/zacheiss/wv/notes/summaryinfo/kb98.html

Теперь надо написать комбинированный тест, создающий потоки "Contents" и
"OlePres000"+"OlePres001" с известным и неизвестным CLSID, и проверяющий
оригинальный и финальный IStorage. Нужно определить, всегда ли поток
"Contents" не сохраняется OleSave(), или это происходит только если
формат потока неизвестен.

> Оказалось, что в оригинале содержатся потоки
> "Contents", "OlePres000" и "OlePres001", Wine сохраняет все эти потоки
> как есть в новый IStorage, однако под Windows (или в Wine с ole32=n)
> в новый IStorage сохраняются только потоки "OlePres000" и "OlePres001",
> поток "Contents" не сохраняется. С моим патчем (включенным в eter-2.1)
> сохраняется только поток "OlePres000", и баркод формируется корректно,
> видимо присутствие потока "Contents" ломает какую-то логику внутри MFC.

Судя по исходникам MFC код OLE контрола сохраняет свои данные в потоке
"Contents", и если создание потока "Contents" завершется неудачей (что
естественно происходит, если поток с таким именем уже существует), то
данные и не сохраняются. Видимо barcode.ocx сохраняет какие-то данные,
относящиеся к численному представлению баркода в потоке "Contents".
Comment 21 Dmitry Timoshkov 2017-10-09 13:11:34 MSK
Корректировка фактически потраченного времени: +3 часа.
Comment 22 Dmitry Timoshkov 2017-10-11 12:30:09 MSK
(In reply to Dmitry Timoshkov from comment #20)
> Теперь надо написать комбинированный тест, создающий потоки "Contents" и
> "OlePres000"+"OlePres001" с известным и неизвестным CLSID, и проверяющий
> оригинальный и финальный IStorage. Нужно определить, всегда ли поток
> "Contents" не сохраняется OleSave(), или это происходит только если
> формат потока неизвестен.

Написал пачку тестов, которые создают IStorage, устанавливают ему
заданный CLSID и затем создают несколько потоков в различных форматах
и с разными именами ("Contents", "\2OlePres000", "\2OlePres001", "MyStream").

Снова пришлось экспериментировать и разбираться с поведением OleLoad()
при загрузке потоков из IStorage и последующим сохранением OleSave().

Оказалось, что поведение OleSave() кардинально меняется, если CLSID
загруженного IStorage совпадает с одним из CLSID_Picture_Metafile,
CLSID_Picture_EnhMetafile или CLSID_Picture_Dib. В этом случае OleSave()
сохраняет только самый первый встреченный поток с именем, начинающимся с
"\2OlePres", например если первый встреченный поток имеет имя "\2OlePres001"
он при сохранении будет переименован в "\2OlePres000", а все другие потоки
будут просто проигнорированы. Если же загруженный IStorage не совпадает
с выше перечисленными классами, то OleSave() сохранит все загруженные
"OlePres" потоки. При этом во всех случаях все остальные потоки ("Contents",
"MyStream") никогда не сохраняются.

Я постараюсь подчистить написанные тесты и отправить их в wine-patches.
Comment 23 Dmitry Timoshkov 2017-10-11 12:30:30 MSK
Корректировка фактически потраченного времени: +3 часа.
Comment 24 Dmitry Timoshkov 2017-10-12 14:22:45 MSK
(In reply to Dmitry Timoshkov from comment #22)
> Написал пачку тестов, которые создают IStorage, устанавливают ему
> заданный CLSID и затем создают несколько потоков в различных форматах
> и с разными именами ("Contents", "\2OlePres000", "\2OlePres001", "MyStream").
> 
> Снова пришлось экспериментировать и разбираться с поведением OleLoad()
> при загрузке потоков из IStorage и последующим сохранением OleSave().
> 
> Оказалось, что поведение OleSave() кардинально меняется, если CLSID
> загруженного IStorage совпадает с одним из CLSID_Picture_Metafile,
> CLSID_Picture_EnhMetafile или CLSID_Picture_Dib. В этом случае OleSave()
> сохраняет только самый первый встреченный поток с именем, начинающимся с
> "\2OlePres", например если первый встреченный поток имеет имя "\2OlePres001"
> он при сохранении будет переименован в "\2OlePres000", а все другие потоки
> будут просто проигнорированы. Если же загруженный IStorage не совпадает
> с выше перечисленными классами, то OleSave() сохранит все загруженные
> "OlePres" потоки. При этом во всех случаях все остальные потоки ("Contents",
> "MyStream") никогда не сохраняются.
> 
> Я постараюсь подчистить написанные тесты и отправить их в wine-patches.

Написал универсальный генератор IStorage, который берет на входе структуру
с описанием основных характеристик создаваемого IStorage и описаниями потоков
в этом IStorage. В процессе находится создание кода, проверяющего созданный
IStorage с заданным описанием, этот же код будет проверять результирующий
IStorage, созданный OleSave().
Comment 25 Dmitry Timoshkov 2017-10-12 14:23:02 MSK
Корректировка фактически потраченного времени: +3 часа.
Comment 26 Dmitry Timoshkov 2017-10-14 06:19:05 MSK
(In reply to Dmitry Timoshkov from comment #24)
> Написал универсальный генератор IStorage, который берет на входе структуру
> с описанием основных характеристик создаваемого IStorage и описаниями потоков
> в этом IStorage. В процессе находится создание кода, проверяющего созданный
> IStorage с заданным описанием, этот же код будет проверять результирующий
> IStorage, созданный OleSave().

В процессе написания кода, проверяющего созданный IStorage, выяснилось, что
под Windows формат заголовка потока \2OlePres000 зависит от того, какой тип
CLIPFORMAT указан. Похоже, что длина заголовка у CF_DIB немного короче, чем
у CF_METAFILEPICT, из-за этого длина блока записанных и прочитанных данных
потока не совпадает. Чтобы избежать несоответствия проверяемых данных потока
пока решил просто не проверять их. Нужно либо постараться выснить различия
формата заголовка, либо проверять записанные и прочитанные данные как-то
по-другому.
Comment 27 Dmitry Timoshkov 2017-10-17 14:02:05 MSK
(In reply to Dmitry Timoshkov from comment #26)
> В процессе написания кода, проверяющего созданный IStorage, выяснилось, что
> под Windows формат заголовка потока \2OlePres000 зависит от того, какой тип
> CLIPFORMAT указан. Похоже, что длина заголовка у CF_DIB немного короче, чем
> у CF_METAFILEPICT, из-за этого длина блока записанных и прочитанных данных
> потока не совпадает. Чтобы избежать несоответствия проверяемых данных потока
> пока решил просто не проверять их. Нужно либо постараться выснить различия
> формата заголовка, либо проверять записанные и прочитанные данные как-то
> по-другому.

Переделал проверку данных потоков, теперь данные потока проверяются
частично, если ожидаемый размер данных отличается от фактического,
сравнивается минимальный размер. Это неидеальное решение, но пока
у меня других идей нет.

Написал новый тест для проверки вызываемых методов IStorage из OleSave().
Этот тест показывает, что оптимизированный код в DataCache_Save(), который
и является источником всех проблем, и который вызывает IStorage_CopyTo()
не должен этого делать: согласно моему новому тесту IStorage_CopyTo()
не должен вызываться.
Comment 28 Dmitry Timoshkov 2017-10-18 13:27:06 MSK
(In reply to Dmitry Timoshkov from comment #27)
> > В процессе написания кода, проверяющего созданный IStorage, выяснилось, что
> > под Windows формат заголовка потока \2OlePres000 зависит от того, какой тип
> > CLIPFORMAT указан. Похоже, что длина заголовка у CF_DIB немного короче, чем
> > у CF_METAFILEPICT, из-за этого длина блока записанных и прочитанных данных
> > потока не совпадает. Чтобы избежать несоответствия проверяемых данных потока
> > пока решил просто не проверять их. Нужно либо постараться выснить различия
> > формата заголовка, либо проверять записанные и прочитанные данные как-то
> > по-другому.
> 
> Переделал проверку данных потоков, теперь данные потока проверяются
> частично, если ожидаемый размер данных отличается от фактического,
> сравнивается минимальный размер. Это неидеальное решение, но пока
> у меня других идей нет.

Проблема с несоответствием данных потоков была вызвана ошибкой в коде
формирования содержимого IStorage. После исправления ошибки проблема
исчезла. Добавил пачку новых тестовых данных для проверки содержимого
IStorage.

Начал исследование вопроса о возможности исправить генерирование IStorage
в коде Wine. Если у меня не получится достаточно быстро найти приемлемое
исправление, то я просто отправлю тесты в wine-patches.
Comment 29 Dmitry Timoshkov 2017-10-19 08:18:20 MSK
(In reply to Dmitry Timoshkov from comment #28)
> Проблема с несоответствием данных потоков была вызвана ошибкой в коде
> формирования содержимого IStorage. После исправления ошибки проблема
> исчезла. Добавил пачку новых тестовых данных для проверки содержимого
> IStorage.
> 
> Начал исследование вопроса о возможности исправить генерирование IStorage
> в коде Wine. Если у меня не получится достаточно быстро найти приемлемое
> исправление, то я просто отправлю тесты в wine-patches.

После начального исследования и поиска простого исправления стало понятно,
что это будет небыстрый процесс. Поэтому после адаптации тестов для Wine
(а это оказалось очень даже нетривиальной задачей) отправил все тесты в
wine-patches.
Comment 30 Dmitry Timoshkov 2017-10-19 13:33:06 MSK
(In reply to Dmitry Timoshkov from comment #29)
> > Проблема с несоответствием данных потоков была вызвана ошибкой в коде
> > формирования содержимого IStorage. После исправления ошибки проблема
> > исчезла. Добавил пачку новых тестовых данных для проверки содержимого
> > IStorage.
> > 
> > Начал исследование вопроса о возможности исправить генерирование IStorage
> > в коде Wine. Если у меня не получится достаточно быстро найти приемлемое
> > исправление, то я просто отправлю тесты в wine-patches.
> 
> После начального исследования и поиска простого исправления стало понятно,
> что это будет небыстрый процесс. Поэтому после адаптации тестов для Wine
> (а это оказалось очень даже нетривиальной задачей) отправил все тесты в
> wine-patches.

Хью попрсил немного переделать тесты чтобы вместо OleSave() вызывался
напрямую IPersistStorage_Save().

Так же я создал предварительную версию патча с исправлением, которая
убирает оптимизацию с вызовом IStorage_CopyTo() и несколько других вещей.
Поэтому я написал новое письмо Хью с указанием на новые тесты, приложил
мой предварительный патч и спросил его мнение об этом. Хью ответил, что
он в принципе не против удаления IStorage_CopyTo(), но указал, что патч
требует разбивки на логические куски.
Comment 31 Dmitry Timoshkov 2017-10-23 12:04:03 MSK
По непонятной мне причине следующий статус за пятницу не был отправлен:

(In reply to Dmitry Timoshkov from comment #30)
> Хью попрсил немного переделать тесты чтобы вместо OleSave() вызывался
> напрямую IPersistStorage_Save().
> 
> Так же я создал предварительную версию патча с исправлением, которая
> убирает оптимизацию с вызовом IStorage_CopyTo() и несколько других вещей.
> Поэтому я написал новое письмо Хью с указанием на новые тесты, приложил
> мой предварительный патч и спросил его мнение об этом. Хью ответил, что
> он в принципе не против удаления IStorage_CopyTo(), но указал, что патч
> требует разбивки на логические куски.

Отправил в wine-patches исправленные патчи с тестами + патч, удаляющий
IStorage_CopyTo() из кода DataCache_Save(). Все патчи приняты.

Постараюсь выбрать время и портировать мое новое исправление из winehq
в eter-2.1, предварительно откатив старое, и после этого протестировать
обе задачи еще раз.
Comment 32 Dmitry Timoshkov 2017-10-24 05:08:20 MSK
(In reply to Dmitry Timoshkov from comment #31)
> Постараюсь выбрать время и портировать мое новое исправление из winehq
> в eter-2.1, предварительно откатив старое, и после этого протестировать
> обе задачи еще раз.

Откатил старый вариант исправления регрессии и портировал новое исправление
для eter-2.1. Отправил оба патча для включения в ветку eter-2.1.
Comment 33 Dmitry Timoshkov 2017-10-24 05:09:07 MSK
Отмечаю задачу как решенную.
Comment 34 Konstantin Artyushkin 2018-02-02 15:09:06 MSK
wine-etersoft 2.1.4-alt31

Патчи приняты, проблема больше не воспроизводится.