Существуют проблемы с печатью напрямую на принтер, но через 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; }
Надо создать тест и проверить что получается. Желательно в автоматическом режиме печатью в файл.
При попытке распечатать FAR зависает
fixme:winspool:OpenPrinterW PRINTER_DEFAULTS ignored => L"RAW",(nil),0x000f000c
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)
При печати в файл ошибки не возникает. В этом случае в выходной файл записывается всё, что было во входном буфере
ошибка возникает, когда 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
директории PRINTERS в C:\\windows\\system32\\spool\\ не существует
(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, то надо исправить, чтобы такая ситуация не приводила к зависанию. Но с какой стати пишется именно в этот каталог?
при создании указанной директории печать проходит без проблем. Директория задани в функции AddJobW static const WCHAR spool_path[] = {'s','p','o','o','l','\\','P','R','I','N','T','E','R','S','\\',0};
Согласно статье http://www.ghacks.net/2008/02/24/change-the-print-spooler-directory/ каталог хранится в ключе DefaultSpoolDirectory в ветке HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers
Изменение стандартной директории печати как правило производится только с целью ускорения (если она находится на более быстром диске). Было принято решение, что нет смысла реализовывать чтение этой директории из реестра. Теперь она автоматически будет создаваться при установке Wine.