/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// signature and size must fit to avoid using // JobSetups from a wrong system
// initialize versions from jobsetup // those will be overwritten with driver's version
DEVMODEW const * pDevModeW = nullptr; LONG dmSpecVersion = -1; LONG dmDriverVersion = -1;
SalDriverData const * pSalDriverData = reinterpret_cast<SalDriverData const *>(pSetupData->GetDriverData());
BYTE const * pDriverData = reinterpret_cast<BYTE const *>(pSalDriverData) + pSalDriverData->mnDriverOffset;
pDevModeW = reinterpret_cast<DEVMODEW const *>(pDriverData);
LONG nSysJobSize = -1; if( pPrinter && pDevModeW )
{ // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!! // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we // can avoid potential driver crashes as their jobsetups are often not compatible // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
HANDLE hPrn;
LPWSTR pPrinterNameW = const_cast<LPWSTR>(o3tl::toW(pPrinter->maDeviceName.getStr())); if ( !OpenPrinterW( pPrinterNameW, &hPrn, nullptr ) ) returnfalse;
// #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded! if( hPrn == HGDI_ERROR ) returnfalse;
// the spec version differs between the windows platforms, ie 98,NT,2000/XP // this allows us to throw away printer settings from other platforms that might crash a buggy driver // we check the driver version as well
dmSpecVersion = pBuffer->dmSpecVersion;
dmDriverVersion = pBuffer->dmDriverVersion;
// check if we have a suitable input buffer if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, false ) )
{
pInBuffer = pSetupData->GetDriverData() + reinterpret_cast<SalDriverData const *>(pSetupData->GetDriverData())->mnDriverOffset;
nMode |= DM_IN_BUFFER;
}
// check if the dialog should be shown if ( pVisibleDlgParent )
{
hWnd = pVisibleDlgParent->get_system_data().hWnd;
nMode |= DM_IN_PROMPT;
}
// Release mutex, in the other case we don't get paints and so on
sal_uInt32 nMutexCount = 0;
WinSalInstance* pInst = GetSalData()->mpInstance; if ( pInst && pVisibleDlgParent )
nMutexCount = pInst->ReleaseYieldMutex(true);
// search the right bin and assign index to mnPaperBin for( DWORD i = 0; i < nCount; ++i )
{ if( pDevModeW->dmDefaultSource == pBins[ i ] )
{
pSetupData->SetPaperBin( static_cast<sal_uInt16>(i) ); break;
}
}
std::free( pBins );
}
}
// PaperSize if ( nFlags & JobSetFlags::PAPERSIZE )
{ if( (pDevModeW->dmFields & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) )
{
pSetupData->SetPaperWidth( pDevModeW->dmPaperWidth*10 );
pSetupData->SetPaperHeight( pDevModeW->dmPaperLength*10 );
} else
{ const DWORD nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, nullptr, pSetupData );
WORD* pPapers = nullptr; const DWORD nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, nullptr, pSetupData );
POINT* pPaperSizes = nullptr; if ( nPaperCount && (nPaperCount != GDI_ERROR) )
{
pPapers = static_cast<WORD*>(rtl_allocateZeroMemory(nPaperCount*sizeof(WORD)));
ImplDeviceCaps( pPrinter, DC_PAPERS, reinterpret_cast<BYTE*>(pPapers), pSetupData );
} if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
{
pPaperSizes = static_cast<POINT*>(rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT)));
ImplDeviceCaps( pPrinter, DC_PAPERSIZE, reinterpret_cast<BYTE*>(pPaperSizes), pSetupData );
} if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers )
{ for( DWORD i = 0; i < nPaperCount; ++i )
{ if( pPapers[ i ] == pDevModeW->dmPaperSize )
{
pSetupData->SetPaperWidth( pPaperSizes[ i ].x*10 );
pSetupData->SetPaperHeight( pPaperSizes[ i ].y*10 ); break;
}
}
} if( pPapers )
std::free( pPapers ); if( pPaperSizes )
std::free( pPaperSizes );
} switch( pDevModeW->dmPaperSize )
{ case DMPAPER_LETTER:
pSetupData->SetPaperFormat( PAPER_LETTER ); break; case DMPAPER_TABLOID:
pSetupData->SetPaperFormat( PAPER_TABLOID ); break; case DMPAPER_LEDGER:
pSetupData->SetPaperFormat( PAPER_LEDGER ); break; case DMPAPER_LEGAL:
pSetupData->SetPaperFormat( PAPER_LEGAL ); break; case DMPAPER_STATEMENT:
pSetupData->SetPaperFormat( PAPER_STATEMENT ); break; case DMPAPER_EXECUTIVE:
pSetupData->SetPaperFormat( PAPER_EXECUTIVE ); break; case DMPAPER_A3:
pSetupData->SetPaperFormat( PAPER_A3 ); break; case DMPAPER_A4:
pSetupData->SetPaperFormat( PAPER_A4 ); break; case DMPAPER_A5:
pSetupData->SetPaperFormat( PAPER_A5 ); break; //See http://wiki.openoffice.org/wiki/DefaultPaperSize //i.e. //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And //matches our Excel filter's belief about the matching XlPaperSize //enumeration.
//http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said ////"DMPAPER_B4 12 B4 (JIS) 250 x 354" //which is bogus as it's either JIS 257 x 364 or ISO 250 x 353 //(cmc) case DMPAPER_B4:
pSetupData->SetPaperFormat( PAPER_B4_JIS ); break; case DMPAPER_B5:
pSetupData->SetPaperFormat( PAPER_B5_JIS ); break; case DMPAPER_QUARTO:
pSetupData->SetPaperFormat( PAPER_QUARTO ); break; case DMPAPER_10X14:
pSetupData->SetPaperFormat( PAPER_10x14 ); break; case DMPAPER_NOTE:
pSetupData->SetPaperFormat( PAPER_LETTER ); break; case DMPAPER_ENV_9:
pSetupData->SetPaperFormat( PAPER_ENV_9 ); break; case DMPAPER_ENV_10:
pSetupData->SetPaperFormat( PAPER_ENV_10 ); break; case DMPAPER_ENV_11:
pSetupData->SetPaperFormat( PAPER_ENV_11 ); break; case DMPAPER_ENV_12:
pSetupData->SetPaperFormat( PAPER_ENV_12 ); break; case DMPAPER_ENV_14:
pSetupData->SetPaperFormat( PAPER_ENV_14 ); break; case DMPAPER_CSHEET:
pSetupData->SetPaperFormat( PAPER_C ); break; case DMPAPER_DSHEET:
pSetupData->SetPaperFormat( PAPER_D ); break; case DMPAPER_ESHEET:
pSetupData->SetPaperFormat( PAPER_E ); break; case DMPAPER_ENV_DL:
pSetupData->SetPaperFormat( PAPER_ENV_DL ); break; case DMPAPER_ENV_C5:
pSetupData->SetPaperFormat( PAPER_ENV_C5 ); break; case DMPAPER_ENV_C3:
pSetupData->SetPaperFormat( PAPER_ENV_C3 ); break; case DMPAPER_ENV_C4:
pSetupData->SetPaperFormat( PAPER_ENV_C4 ); break; case DMPAPER_ENV_C6:
pSetupData->SetPaperFormat( PAPER_ENV_C6 ); break; case DMPAPER_ENV_C65:
pSetupData->SetPaperFormat( PAPER_ENV_C65 ); break; case DMPAPER_ENV_ITALY:
pSetupData->SetPaperFormat( PAPER_ENV_ITALY ); break; case DMPAPER_ENV_MONARCH:
pSetupData->SetPaperFormat( PAPER_ENV_MONARCH ); break; case DMPAPER_ENV_PERSONAL:
pSetupData->SetPaperFormat( PAPER_ENV_PERSONAL ); break; case DMPAPER_FANFOLD_US:
pSetupData->SetPaperFormat( PAPER_FANFOLD_US ); break; case DMPAPER_FANFOLD_STD_GERMAN:
pSetupData->SetPaperFormat( PAPER_FANFOLD_DE ); break; case DMPAPER_FANFOLD_LGL_GERMAN:
pSetupData->SetPaperFormat( PAPER_FANFOLD_LEGAL_DE ); break; case DMPAPER_ISO_B4:
pSetupData->SetPaperFormat( PAPER_B4_ISO ); break; case DMPAPER_JAPANESE_POSTCARD:
pSetupData->SetPaperFormat( PAPER_POSTCARD_JP ); break; case DMPAPER_9X11:
pSetupData->SetPaperFormat( PAPER_9x11 ); break; case DMPAPER_10X11:
pSetupData->SetPaperFormat( PAPER_10x11 ); break; case DMPAPER_15X11:
pSetupData->SetPaperFormat( PAPER_15x11 ); break; case DMPAPER_ENV_INVITE:
pSetupData->SetPaperFormat( PAPER_ENV_INVITE ); break; case DMPAPER_A_PLUS:
pSetupData->SetPaperFormat( PAPER_A_PLUS ); break; case DMPAPER_B_PLUS:
pSetupData->SetPaperFormat( PAPER_B_PLUS ); break; case DMPAPER_LETTER_PLUS:
pSetupData->SetPaperFormat( PAPER_LETTER_PLUS ); break; case DMPAPER_A4_PLUS:
pSetupData->SetPaperFormat( PAPER_A4_PLUS ); break; case DMPAPER_A2:
pSetupData->SetPaperFormat( PAPER_A2 ); break; case DMPAPER_DBL_JAPANESE_POSTCARD:
pSetupData->SetPaperFormat( PAPER_DOUBLEPOSTCARD_JP ); break; case DMPAPER_A6:
pSetupData->SetPaperFormat( PAPER_A6 ); break; case DMPAPER_B6_JIS:
pSetupData->SetPaperFormat( PAPER_B6_JIS ); break; case DMPAPER_12X11:
pSetupData->SetPaperFormat( PAPER_12x11 ); break; default:
pSetupData->SetPaperFormat( PAPER_USER ); break;
}
}
switch( pSetupData->GetPaperFormat() )
{ case PAPER_A2:
pDevModeW->dmPaperSize = DMPAPER_A2; break; case PAPER_A3:
pDevModeW->dmPaperSize = DMPAPER_A3; break; case PAPER_A4:
pDevModeW->dmPaperSize = DMPAPER_A4; break; case PAPER_A5:
pDevModeW->dmPaperSize = DMPAPER_A5; break; case PAPER_B4_ISO:
pDevModeW->dmPaperSize = DMPAPER_ISO_B4; break; case PAPER_LETTER:
pDevModeW->dmPaperSize = DMPAPER_LETTER; break; case PAPER_LEGAL:
pDevModeW->dmPaperSize = DMPAPER_LEGAL; break; case PAPER_TABLOID:
pDevModeW->dmPaperSize = DMPAPER_TABLOID; break;
// http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx // DMPAPER_ENV_B6 is documented as: // "DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm" // which is the wrong way around, it is surely 125 x 176, i.e. // compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as // DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm // DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
case PAPER_ENV_C4:
pDevModeW->dmPaperSize = DMPAPER_ENV_C4; break; case PAPER_ENV_C5:
pDevModeW->dmPaperSize = DMPAPER_ENV_C5; break; case PAPER_ENV_C6:
pDevModeW->dmPaperSize = DMPAPER_ENV_C6; break; case PAPER_ENV_C65:
pDevModeW->dmPaperSize = DMPAPER_ENV_C65; break; case PAPER_ENV_DL:
pDevModeW->dmPaperSize = DMPAPER_ENV_DL; break; case PAPER_C:
pDevModeW->dmPaperSize = DMPAPER_CSHEET; break; case PAPER_D:
pDevModeW->dmPaperSize = DMPAPER_DSHEET; break; case PAPER_E:
pDevModeW->dmPaperSize = DMPAPER_ESHEET; break; case PAPER_EXECUTIVE:
pDevModeW->dmPaperSize = DMPAPER_EXECUTIVE; break; case PAPER_FANFOLD_LEGAL_DE:
pDevModeW->dmPaperSize = DMPAPER_FANFOLD_LGL_GERMAN; break; case PAPER_ENV_MONARCH:
pDevModeW->dmPaperSize = DMPAPER_ENV_MONARCH; break; case PAPER_ENV_PERSONAL:
pDevModeW->dmPaperSize = DMPAPER_ENV_PERSONAL; break; case PAPER_ENV_9:
pDevModeW->dmPaperSize = DMPAPER_ENV_9; break; case PAPER_ENV_10:
pDevModeW->dmPaperSize = DMPAPER_ENV_10; break; case PAPER_ENV_11:
pDevModeW->dmPaperSize = DMPAPER_ENV_11; break; case PAPER_ENV_12:
pDevModeW->dmPaperSize = DMPAPER_ENV_12; break; //See the comments on DMPAPER_B4 above case PAPER_B4_JIS:
pDevModeW->dmPaperSize = DMPAPER_B4; break; case PAPER_B5_JIS:
pDevModeW->dmPaperSize = DMPAPER_B5; break; case PAPER_B6_JIS:
pDevModeW->dmPaperSize = DMPAPER_B6_JIS; break; case PAPER_LEDGER:
pDevModeW->dmPaperSize = DMPAPER_LEDGER; break; case PAPER_STATEMENT:
pDevModeW->dmPaperSize = DMPAPER_STATEMENT; break; case PAPER_10x14:
pDevModeW->dmPaperSize = DMPAPER_10X14; break; case PAPER_ENV_14:
pDevModeW->dmPaperSize = DMPAPER_ENV_14; break; case PAPER_ENV_C3:
pDevModeW->dmPaperSize = DMPAPER_ENV_C3; break; case PAPER_ENV_ITALY:
pDevModeW->dmPaperSize = DMPAPER_ENV_ITALY; break; case PAPER_FANFOLD_US:
pDevModeW->dmPaperSize = DMPAPER_FANFOLD_US; break; case PAPER_FANFOLD_DE:
pDevModeW->dmPaperSize = DMPAPER_FANFOLD_STD_GERMAN; break; case PAPER_POSTCARD_JP:
pDevModeW->dmPaperSize = DMPAPER_JAPANESE_POSTCARD; break; case PAPER_9x11:
pDevModeW->dmPaperSize = DMPAPER_9X11; break; case PAPER_10x11:
pDevModeW->dmPaperSize = DMPAPER_10X11; break; case PAPER_15x11:
pDevModeW->dmPaperSize = DMPAPER_15X11; break; case PAPER_ENV_INVITE:
pDevModeW->dmPaperSize = DMPAPER_ENV_INVITE; break; case PAPER_A_PLUS:
pDevModeW->dmPaperSize = DMPAPER_A_PLUS; break; case PAPER_B_PLUS:
pDevModeW->dmPaperSize = DMPAPER_B_PLUS; break; case PAPER_LETTER_PLUS:
pDevModeW->dmPaperSize = DMPAPER_LETTER_PLUS; break; case PAPER_A4_PLUS:
pDevModeW->dmPaperSize = DMPAPER_A4_PLUS; break; case PAPER_DOUBLEPOSTCARD_JP:
pDevModeW->dmPaperSize = DMPAPER_DBL_JAPANESE_POSTCARD; break; case PAPER_A6:
pDevModeW->dmPaperSize = DMPAPER_A6; break; case PAPER_12x11:
pDevModeW->dmPaperSize = DMPAPER_12X11; break; default:
{ short nPaper = 0; const DWORD nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, nullptr, pSetupData );
WORD* pPapers = nullptr; const DWORD nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, nullptr, pSetupData );
POINT* pPaperSizes = nullptr;
DWORD nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, nullptr, pSetupData ); if ( nPaperCount && (nPaperCount != GDI_ERROR) )
{
pPapers = static_cast<WORD*>(rtl_allocateZeroMemory(nPaperCount*sizeof(WORD)));
ImplDeviceCaps( pPrinter, DC_PAPERS, reinterpret_cast<BYTE*>(pPapers), pSetupData );
} if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
{
pPaperSizes = static_cast<POINT*>(rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT)));
ImplDeviceCaps( pPrinter, DC_PAPERSIZE, reinterpret_cast<BYTE*>(pPaperSizes), pSetupData );
} if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes )
{
PaperInfo aInfo(pSetupData->GetPaperWidth(), pSetupData->GetPaperHeight()); // compare paper formats and select a good match for ( DWORD i = 0; i < nPaperCount; ++i )
{ if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)))
{
nPaper = pPapers[i]; break;
}
}
// If the printer supports landscape orientation, check paper sizes again // with landscape orientation. This is necessary as a printer driver provides // all paper sizes with portrait orientation only!! if ( !nPaper && nLandscapeAngle != 0 )
{
PaperInfo aRotatedInfo(pSetupData->GetPaperHeight(), pSetupData->GetPaperWidth()); for ( DWORD i = 0; i < nPaperCount; ++i )
{ if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) )
{
nPaper = pPapers[i]; break;
}
}
}
// Ensure we handle the mutex which will be released in WinSalInstance::DoYield
SolarMutexGuard aSolarMutexGuard; do
{ // process messages
bWhile = Application::Reschedule( true ); if (i > 15)
bWhile = false; else
++i;
// release DC if there is one still around because of AbortJob
HDC hDC = mhDC; if ( hDC )
{ // explicitly reset(), so the mxGraphics's borrowed HDC defaults are // restored and WinSalGraphics's destructor won't work on a deleted HDC.
mxGraphics.reset();
DeleteDC( hDC );
}
// remove printer from printerlist if ( this == pSalData->mpFirstPrinter )
pSalData->mpFirstPrinter = mpNextPrinter; else
{
WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
while( pTempPrinter->mpNextPrinter != this )
pTempPrinter = pTempPrinter->mpNextPrinter;
// need wrappers for StarTocW/A to use structured exception handling // since SEH does not mix with standard exception handling's cleanup staticint lcl_StartDocW1( HDC hDC, DOCINFOW const * pInfo, WinSalPrinter* pPrt )
{ int nRet = 0;
CATCH_DRIVER_EX_BEGIN;
nRet = ::StartDocW( hDC, pInfo );
CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt ); return nRet;
}
staticint lcl_StartDocW( HDC hDC, DOCINFOW const * pInfo, WinSalPrinter* pPrt )
{ //tdf#127547 - Freeze/crash in Microsoft Print to PDF dialog, if we try to paste while // executing the StartDocW method, Windows will call back into us on a separate thread, // where we will attempt to take the SolarMutex.
SolarMutexReleaser aReleaser;
// #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
sal_Unicode aDrvBuf[4096];
sal_Unicode aDevBuf[4096];
memcpy( aDrvBuf, mpInfoPrinter->maDriverName.getStr(), (mpInfoPrinter->maDriverName.getLength()+1)*sizeof(sal_Unicode));
memcpy( aDevBuf, mpInfoPrinter->maDeviceName.getStr(), (mpInfoPrinter->maDeviceName.getLength()+1)*sizeof(sal_Unicode));
hDC = CreateDCW( o3tl::toW(aDrvBuf),
o3tl::toW(aDevBuf),
nullptr,
pDevModeW );
if ( pDevModeW != pOrgDevModeW )
std::free( const_cast<DEVMODEW *>(pDevModeW) );
if ( !hDC )
{
mnError = SalPrinterError::General; returnfalse;
}
// make sure mhDC is set before the printer driver may call our abortproc
mhDC = hDC; if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
{
mnError = SalPrinterError::General; returnfalse;
}
mnError = SalPrinterError::NONE;
mbAbort = false;
// As the Telecom Balloon Fax driver tends to send messages repeatedly // we try to process first all, and then insert a dummy message for (int i = 0; Application::Reschedule( true ) && i <= 15; ++i); boolconst ret = PostMessageW(GetSalData()->mpInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0);
SAL_WARN_IF(!ret, "vcl", "ERROR: PostMessage() failed!");
// bring up a file chooser if printing to file port but no file name given
OUString aOutFileName; if( mpInfoPrinter->maPortName.equalsIgnoreAsciiCase( "FILE:" ) && (!pFileName || pFileName->isEmpty()) )
{
void WinSalPrinter::DoEndDoc(HDC hDC)
{
CATCH_DRIVER_EX_BEGIN; if( ::EndDoc( hDC ) <= 0 )
GetLastError();
CATCH_DRIVER_EX_END( "exception in EndDoc", this );
}
bool WinSalPrinter::EndJob()
{
HDC hDC = mhDC; if (!isValid()) returntrue;
mxGraphics.reset();
// #i54419# Windows fax printer brings up a dialog in EndDoc // which text previously copied in soffice process can be // pasted to -> deadlock due to mutex not released. // it should be safe to release the yield mutex over the EndDoc // call, however the real solution is supposed to be the threading // framework yet to come.
{
SolarMutexReleaser aReleaser;
DoEndDoc( hDC );
}
DeleteDC( hDC );
mhDC = nullptr;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.