Bug 527

Summary: Проблемы с печатью напрямую (raw-печать)
Product: WINE@Etersoft Reporter: Vitaly Lipatov <lav>
Component: ОбщееAssignee: Виталий Перов <vitperov>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P5    
Version: 1.0.6   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 384, 443, 777    

Description Vitaly Lipatov 2007-03-23 01:15:05 MSK
Существуют проблемы с печатью напрямую на принтер, но через WinAPI-функции спулера. Такой способ печати реализован в файловом менеджере FAR по Alt-F5 - можно проверить.

Вот информация по использованию из MSDN: 

Sending Data Directly to a Printer
 
It is sometimes necessary to bypass the driver and send printer-specific data directly to a printer. The following code shows how this can be done for both local and networked printers. This method can be used to replace the PASSTHROUGH escape and SpoolFile methods. 
 
// RawDataToPrinter - sends binary data directly to a printer
// 
// szPrinterName: NULL-terminated string specifying printer name
// lpData: Pointer to raw data bytes
// dwCount Length of lpData in bytes
// 
// Returns: TRUE for success, FALSE for failure.
// 
BOOL RawDataToPrinter(LPSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;

// Need a handle to the printer.
if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
return FALSE;

// Fill in the structure with info about this "document."
DocInfo.pDocName = "My Document";
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = "RAW";
// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPSTR)&DocInfo )) == 0 )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Start a page.
if( ! StartPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Send the data to the printer.
if( !WritePrinter( hPrinter, lpData, dwCount, &dwBytesWritten ) )
{
EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// End the page.
if( ! EndPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Inform the spooler that the document is ending.
if( ! EndDocPrinter( hPrinter ) )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Tidy up the printer handle.
ClosePrinter( hPrinter );
// Check to see if correct number of bytes were written.
if( dwBytesWritten != dwCount )
return FALSE;
return TRUE;
}
Comment 1 Vitaly Lipatov 2007-05-26 13:44:06 MSD
Надо создать тест и проверить что получается. Желательно в автоматическом режиме печатью в файл.
Comment 2 Виталий Перов 2008-05-29 19:12:26 MSD
При попытке распечатать FAR зависает
Comment 3 Виталий Перов 2008-05-29 19:19:40 MSD
fixme:winspool:OpenPrinterW PRINTER_DEFAULTS ignored => L"RAW",(nil),0x000f000c
Comment 4 Виталий Перов 2008-05-29 20:17:37 MSD
trace:winspool:OpenPrinterW (L"TestPrinter", 0x338804, 0x338354)
fixme:winspool:OpenPrinterW PRINTER_DEFAULTS ignored => L"RAW",(nil),0x000f000c
trace:winspool:OpenPrinterW returning 1 with 0 and 0x1
trace:winspool:StartDocPrinterW (hPrinter = 0x1, Level = 1, pDocInfo = 0x338754 {pDocName = L"test.txt", pOutputFile = (null), pDatatype = L"RAW"}):
trace:winspool:AddJobW (0x1,1,0x338500,528,0x3384d4)
Comment 5 Виталий Перов 2008-05-29 20:33:08 MSD
При печати в файл ошибки не возникает. В этом случае в выходной файл записывается всё, что было во входном буфере
Comment 6 Виталий Перов 2008-05-29 20:52:14 MSD
ошибка возникает, когда spool пишется не в заданный файл, а файл, определённый в filename = addjob->Path;
там содержится filename = 'L"C:\\windows\\system32\\spool\\PRINTERS\\00002.SPL"
при открытии(создании) файла
hf = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
получаем hf = INVALID_HANDLE_VALUE
Comment 7 Виталий Перов 2008-05-29 20:55:25 MSD
директории PRINTERS в C:\\windows\\system32\\spool\\ не существует
Comment 8 Vitaly Lipatov 2008-05-29 20:58:51 MSD
(In reply to comment #6)
...
> 'L"C:\\windows\\system32\\spool\\PRINTERS\\00002.SPL"
> при открытии(создании) файла
> hf = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
> FILE_ATTRIBUTE_NORMAL, NULL);
> получаем hf = INVALID_HANDLE_VALUE
Если это в коде Wine, то надо исправить, чтобы такая ситуация не приводила к зависанию. Но с какой стати пишется именно в этот каталог?

Comment 9 Виталий Перов 2008-05-29 21:12:28 MSD
при создании указанной директории печать проходит без проблем.

Директория задани в функции AddJobW
static const WCHAR spool_path[] = {'s','p','o','o','l','\\','P','R','I','N','T','E','R','S','\\',0};
Comment 10 Vitaly Lipatov 2008-05-29 21:14:08 MSD
(In reply to comment #6)
...
> 'L"C:\\windows\\system32\\spool\\PRINTERS\\00002.SPL"
> при открытии(создании) файла
> hf = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
> FILE_ATTRIBUTE_NORMAL, NULL);
> получаем hf = INVALID_HANDLE_VALUE
Если это в коде Wine, то надо исправить, чтобы такая ситуация не приводила к зависанию. Но с какой стати пишется именно в этот каталог?

Comment 11 Vitaly Lipatov 2008-05-29 21:14:31 MSD
Согласно статье
http://www.ghacks.net/2008/02/24/change-the-print-spooler-directory/
каталог хранится в ключе DefaultSpoolDirectory в ветке
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers
Comment 12 Виталий Перов 2008-05-29 21:46:35 MSD
Изменение стандартной директории печати как правило производится только с целью ускорения (если она находится на более быстром диске).
Было принято решение, что нет смысла реализовывать чтение этой директории из реестра.
Теперь она автоматически будет создаваться при установке Wine.