Bug 6009

Summary: Продвижение нашей системы печати в WINE
Product: WINE@Etersoft Reporter: Виталий Перов <vitperov>
Component: Печать ; Диалог печатиAssignee: Евгений <evcalipt>
Status: DEFERRED --- QA Contact:
Severity: major    
Priority: P3 CC: kondratyuk, lav
Version: 2.0Keywords: TO_WINEHQ
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on: 6087, 1686, 2843, 3146, 4111    
Bug Blocks: 443, 3000    

Description Виталий Перов 2010-09-13 17:16:01 MSD
В последнее время в wine усиленно дорабатывается система печати. В связи с этим приходится постоянно переписывать нашу реализацию.
Хотелось бы хотя бы частично продвинуть в wine нашу реализацию печати.
Comment 1 Виталий Перов 2010-09-13 17:38:06 MSD
Для начала нужно реализовать поддержку получения имени принтера через функцию GetJob
Comment 2 Виталий Перов 2010-09-13 19:47:29 MSD
Написал патч. Отправил.
Comment 3 Виталий Перов 2010-09-15 15:00:14 MSD
Патч принят.
Следующий шаг - реализация поддержки получения структуры DevMode через функцию GetJob.
В этом случае всё немного сложнее:
1)Хорошо бы записывать поле DevMode при вызове AddJob (как это сделано с PrinterName). Но проблема в том, что для функции AddJob структура DevMode не доступна.
2)Даже если как-то удастся передать структуру при вызове AddJob, нет гарантии, что на момент вызова EndDoc там будет нужное количество копий. Возможно в процессе формирования задания создаётся промежуточная структура DevMode, в этом случае во внутренней структуре job_t будет ссылка на первую структуру DevMode с незаполненными полями. Надо проверить возможность такого варианта
Comment 4 Виталий Перов 2010-09-15 15:06:10 MSD
DevMode можно получать из структуры PRINTER_INFO_2 с помощью GetPrinter.
Но, как написано в баге 4111, к моменту отправки задания на печать DevMode, который мы получаем относится не к конкретному заданию, а скорее к это к настройкам по умолчанию, и извлечь оттуда необходимые параметры не удаётся.

Надо проверить что мы получим при вызове GetPrinter из AddJob, возможно в этом случае структура будет относится именно к текущему заданию.
Comment 5 Виталий Перов 2010-09-15 15:19:51 MSD
Проверил.
GetPrinter проверяет есть ли структуру DevMode в реестре, если нет, то возвращает структуру по умолчанию. Для этого вызывается функция WINSPOOL_GetDefaultDevMode.
Таким образом, через GetPrinter ничего полезного не получить.
Comment 6 Виталий Перов 2010-09-15 15:49:19 MSD
Из PSDRV_StartDocA вызывается StartDocPrinter, из которого вызывается AddJob.

В функции PSDRV_StartDocA доступна структура PSDRV_PDEVICE, где находится правильный DevMode. Передать её в AddJob нет никакой возможности.

К внутренним структурам job_t и printer_t из PSDRV_StartDocA тоже не достучаться.

Возможно из PSDRV_StartDocA вызывать SetJob, и таким образом сохранять значение DevMode, но на первый взгляд выглядит немного кривовато...

Самым правильным решением было бы написать тест на функцию AddJob, а затем вызвать GetJob и проверить заполняет ли винда поле DevMode.
Затем, вторым тестом проверить добавляется ли DevMode после вызова PSDRV_StartDocA. Если изначально DevMode отсутствует, но при вызове PSDRV_StartDocA присутствует, значит предложенный алгоритм правильный.
Comment 7 Виталий Перов 2010-09-15 16:55:04 MSD
Начал писать тест. Оказалось всё немного по-другому.
Функция AddJobW не получает структуру JOB_INFO_1, а наоборот - возвращает заполненную.
Последующее заполнение полей структуры делается при помощи SetJob (заполняется только поле с именем документа, всё остальное - нули)
Comment 8 Виталий Перов 2010-09-15 17:57:42 MSD
Написал простой тест:
Сначала вызывается AddJob, затем вызывается GetJob.

Поля структуры на винде:
pPrinterName - непонятная строка 'Hy$'
pMachineName = Null
pUserName - не Null, но при обращении происходит падение
pDocumentName = Null
pDevMode = Null
Comment 9 Виталий Перов 2010-09-15 18:39:14 MSD
Написал тест на функцию StartDocPrinter. После её вызова GetJob возвращает:

Результаты в wine:
info.c:2946: job_id = 2
info.c:2952: ------------------
info.c:2953: printer_name='hp'
info.c:2954: machine_name='(null)'
info.c:2955: user_name='(null)'
info.c:2956: document_name='winetest'
info.c:2957: DevMode='0'

На винде:
info.c:2928: default_printer: 'Microsoft XPS Document Writer'
info.c:2946: job_id = 15
info.c:2952: ------------------
info.c:2953: printer_name='Microsoft XPS Document Writer'
info.c:2954: machine_name='\\WINXPOFFICE'
info.c:2955: user_name='└фьшэшёЄЁрЄюЁ'
info.c:2956: document_name='winetest'
info.c:2957: DevMode='2420608'

Т.е заполнение имени принтера и DevMode происходит именно внутри StartDocPrinter

Написанный тест скорее всего отправить не получится т.к он оставляет после себя следы: Задание добавляется, но никак не удаляется. Для удаления задания нет специальной функции, задание само должно удалятся после отправки на печать.
Comment 10 Виталий Перов 2010-09-15 19:18:10 MSD
Ещё одно возможное решение - вызов функции DocumentPropertiesA.
Она получает DevMode напрямую из драйвера gdi32.

Проблема в том, что функция возвращает саму структуру, а не указатель на неё.

т.е в функции ScheduleJob для печати через lpr можно получить структуру DevMode,
но сделать так, указатель на структуру был бы доступен через GetJob - наверное не получится.
Comment 11 Виталий Перов 2010-09-20 17:05:04 MSD
Как вариант - вызывать DocumentPropertiesA из GetJob, при этом получить полную структуру DEVMODE, и дописать её к концу структуры JOB_INFO_2.

Ещё замечания по поводу SetJob.
Функции передаётся указатель на DevMode, но не известно где лежит сама структура: возможно она также дописывается к концу JOB_INFO_2, и в это случае SetJob обязана её копировать. Надо проверить в винде.
Comment 12 Виталий Перов 2010-09-20 17:25:10 MSD
Проверил в винде: структура, действительно хранится внутри выделяемого буфера.
Comment 13 Виталий Перов 2010-09-20 18:43:12 MSD
Реализовал поддержу pDevMode в SetJob и GetJob.
Перед отправкой патча хотелось бы его проверить вместе с патчем к баге #4111
Comment 14 Виталий Перов 2010-09-20 19:37:19 MSD
Проверил. Работает. Патч отправил.
Comment 15 Виталий Перов 2010-09-20 19:45:19 MSD
Следующая проверка на винде:
С помощью SetJob установить pDevMode = NULL;
Затем прочитать полученное значение с помощью GetJob. Возможно винда всё-таки возвращает DevMode в этом случае
Comment 16 Виталий Перов 2010-09-22 17:49:03 MSD
(In reply to comment #14)
> Проверил. Работает. Патч отправил.
> 

Переделал патч. Проверил совместно с патчем 4111.
При печати происходит падение. Где-то ошибка
Comment 17 Виталий Перов 2010-09-22 18:23:39 MSD
Переделал. Проверил. Отправил.
Comment 18 Виталий Перов 2010-09-23 15:34:55 MSD
Патч не принимают. Можно пока зайти с другой стороны - посмотреть отличие наших диалогов печати от диалогов в официальном релизе. Там тоже должны быть исправления, касающиеся количества копий и раскладки по копиям.
Comment 19 Виталий Перов 2010-09-29 17:05:47 MSD
Наши патчи в printdlg.c:

1) 19adc737        (Константин Кондратюк   2008-04-08 comdlg32: Fix eterbugs #225, #985  - завёл отдельную багу №6087

2) 1af0303e        (Vitaly Perov   2009-05-24 14:58:14 comdlg32/printdlg: Let printer manage multiple copies if it can (fix duplex printing) (eterbugs #1686 and #3146)
3) 312c1f3c        (Vitaly Perov   2009-07-08 18:20:15
4) 90197619        (Vitaly Lipatov 2009-02-11 Some changes for print dialog

Из них к дуплексу и разбивке по копиям относятся патчи 2 и 3.

 
Comment 20 Виталий Перов 2010-09-29 17:33:54 MSD
Хотелось бы как-то объединить патчи 2 и 3. Один для функции PRINTDLG_UpdatePrintDlgA, другой для W.
Общую часть - определение возможности принтера печатать много копий хотелось бы вынести в отдельную функцию.
Comment 21 Виталий Перов 2010-09-29 18:37:26 MSD
Проверил. Написать универсальную функцию не получится. Придётся дублировать.

В нашем патче количество поддерживаемых копий определяется с помощью вызова DeviceCapabilities. В коде winehq для этого используется конструкция
if (lpdm->dmFields & DM_COPIES.
Надо проверить работает ли это у нас, если да, то это существенно упрощает патч.

Ещё один нехороший момент:
Патч направлен на то, чтобы по умолчанию драйвер принтера занимался дуплексом, формированием нужного количества копий и разбивкой.
В winehq по умолчанию это делает приложение.
Соответственно возникают проблемы с разбивкой по копиям: Раньше в некоторых приложениях это работало (за счёт того, что разбивку поддерживало приложение), после принятия патча она работать перестанет.
Comment 22 Виталий Перов 2010-09-30 17:09:28 MSD
Решением проблемы будет - исправить настройки принтера по умолчанию так, чтобы он возвращал, что он умеет производить разбивку по копиям.

Сделал патч для PRINTDLG_UpdatePrintDlgA.
В блокноте вызывается W-функция. Проверял в 1с80.

Для печати используется драйвер принтера, но разбивка по копиям не работает
Comment 23 Виталий Перов 2010-09-30 17:42:12 MSD
Пробовал wine --removeprinters - не помогло.

Согласно баге #2843 работать и не должно. Поддержка разбивки появилась у нас только тогда, когда мы начали использовать опции команды lpr.

Видимо придётся делать всё одним большим патчем: сразу исправлять порядок обработки в printdlg и сразу добавлять опции комманды lpr.
Comment 24 Виталий Перов 2010-09-30 19:03:11 MSD
В winehq нашёл только одну багу, относящуюся к раскладке по копиям и дуплексу:
http://bugs.winehq.org/show_bug.cgi?id=23634

Судя по обсуждению никто не знает как на самом деле работает наша система печати, но все видят, что она работает.
Comment 25 Виталий Перов 2010-10-01 12:59:45 MSD
lpr - обёртка, ссылающаяся на lpr-cups, которая использует всё те же функции библиотеки cups.
Поступило предложение вместо lpr функции библиотеки cups.
Когда-то пробовал печатать через функции cups - всё работало, но не поддерживался дуплекс и разбивка по копиям.

Можно попробовать посмотреть в исходниках lpr-cups как парсятся параметры командной строки, и как задаются необходимые опции.

Исходники можно взять на:
1)/srv/lav/Projects/git-alt/other-owners/cups

2)http://sisyphus.ru/ru/srpm/Sisyphus/cups/gear

3)http://git.altlinux.org/gears/c/cups.git
Comment 26 Виталий Перов 2010-10-01 15:46:59 MSD
Нашёл исходники.
Парсингом занимается функция cupsParseOptions.
Она доступна и в wine
Comment 27 Виталий Перов 2010-10-01 16:40:22 MSD
Проверил. Не работает.
Добавляются 2 опции, но при печати они почему-то не работают.

Возможно потому, что в опциях стоит одна копия. А нужное количество задано внутри выходного файла.
Comment 28 Виталий Перов 2010-10-01 16:55:13 MSD
Теперь всё работает.

Думаю первым делом нужно отправить патч, который убирает выставление нужного количества копий внутри PostScript файла, и переносит это на этап отправки задания.
Comment 29 Виталий Перов 2010-10-01 19:22:44 MSD
Сделал патч. Проверил.
Пока не работает.
Почему-то GetJobW не может получить структуру DEVMODE, из которой берётся нужное количество копий.
Comment 30 Виталий Перов 2010-10-01 19:26:43 MSD
Разобрался.
GetJobW сначала требует одного количества байт, а затем уже другого:

fixme:winspool:ScheduleJob needed = 366
trace:winspool:get_job_info 0x1 2 2 0x20a898 366 0x32def8
fixme:winspool:get_job_info_2 Devmode found
fixme:winspool:get_job_info_2 Devmode is to be copied
fixme:winspool:ScheduleJob needed = 368

поэтому запись в выделенный буфер не происходит.

Виновато выравнивание. Думаю в случае отсутствия указателя на буфер следует возвращать максимально возможное количество байт (с учётом максимального выравнивания)
Comment 31 Виталий Перов 2010-10-04 13:55:18 MSD
выравнивание добавлял по примеру внутренней функции convert_printerinfo_W_to_A. Эта функция не сообщает о длине требуемого буфера, поэтому этот код работает.

Надо сделать тес и посмотреть на винде: есть выравнивание или нет.
Если есть, то при запросе размера выделять больший размер.
Comment 32 Виталий Перов 2010-10-04 15:35:02 MSD
Проверил. В винде выравнивание есть.

Сделал патч, исправляющий ошибку. Отправил в winehq.

Проверил предыдущий патч (через LPR:). Всё работает!
На всякий случай следует ещё проверить через CUPS:
Comment 33 Виталий Перов 2011-02-23 19:44:45 MSK
Патч был приложен не к тому месту, поэтому и правда был бесполезен. Непонятно почему так получилось, ведь патч проверялся: без него бага была, а с ним исчезала.
Переделал патч. Отправил в Winehq
Comment 34 Виталий Перов 2011-02-25 16:58:35 MSK
Дополнил патч. Отправил повторно
Comment 35 Виталий Перов 2011-06-29 17:40:29 MSK
Отправил повторно первый патч, исправляющий увеличение указателя.
Comment 36 Виталий Перов 2011-07-01 16:52:40 MSK
Переделал патч.
Теперь выравнивание происходит не относительно значения указателя, а относительно начала данных. Таким образом, значение выравнивания никак не зависит от передаваемого адреса буфера.

Отправил патч в winehq.
Comment 37 Виталий Перов 2011-07-02 18:01:39 MSK
Посмотрел статус патча на http://source.winehq.org/patches/

Патч требует тестов.
Comment 38 Виталий Перов 2011-07-02 19:10:46 MSK
Для написания теста можно воспользоваться последовательностью вызовов из StartDocPrinterW.

Начал реализовывать
Comment 39 Vitaly Lipatov 2012-01-09 18:10:50 MSK
Откладываем, на bugs@lists.etersoft.ru не должно висеть багов.
Comment 40 Vitaly Lipatov 2013-04-16 17:05:31 MSK
Выяснилось, что текущая наша система печати имеет проблемы.
https://bugs.etersoft.ru/show_bug.cgi?id=9230
Comment 41 Vitaly Lipatov 2014-09-11 18:39:41 MSK
Откладываем задачи, к которым не обращались более 100 дней.