merged tag ooo/DEV300_m102
[LibreOffice.git] / vcl / win / source / gdi / salprn.cxx
bloba235d67857065614ddcde3e0fae840ecef24e7b8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <string.h>
32 #include <tools/svwin.h>
34 #ifdef __MINGW32__
35 #include <excpt.h>
36 #endif
38 #ifndef _OSL_MODULE_H
39 #include <osl/module.h>
40 #endif
41 #include <wincomp.hxx>
42 #include <saldata.hxx>
43 #include <salinst.h>
44 #include <salgdi.h>
45 #include <salframe.h>
46 #include <vcl/salptype.hxx>
47 #include <salprn.h>
48 #include <vcl/print.h>
49 #include <vcl/jobset.h>
51 #include <tools/urlobj.hxx>
52 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
53 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
54 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
55 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
56 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
57 #include <com/sun/star/lang/XInitialization.hpp>
58 #include <comphelper/processfactory.hxx>
60 #include <malloc.h>
62 #ifdef __MINGW32__
63 #define CATCH_DRIVER_EX_BEGIN \
64 jmp_buf jmpbuf; \
65 __SEHandler han; \
66 if (__builtin_setjmp(jmpbuf) == 0) \
67 { \
68 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
70 #define CATCH_DRIVER_EX_END(mes, p) \
71 } \
72 han.Reset()
73 #define CATCH_DRIVER_EX_END_2(mes) \
74 } \
75 han.Reset()
76 #else
77 #define CATCH_DRIVER_EX_BEGIN \
78 __try \
80 #define CATCH_DRIVER_EX_END(mes, p) \
81 } \
82 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
83 { \
84 DBG_ERROR( mes ); \
85 p->markInvalid(); \
87 #define CATCH_DRIVER_EX_END_2(mes) \
88 } \
89 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
90 { \
91 DBG_ERROR( mes ); \
93 #endif
96 using namespace com::sun::star;
97 using namespace com::sun::star::uno;
98 using namespace com::sun::star::lang;
99 using namespace com::sun::star::ui::dialogs;
100 using namespace rtl;
102 // =======================================================================
104 static char aImplWindows[] = "windows";
105 static char aImplDevices[] = "devices";
106 static char aImplDevice[] = "device";
108 static LPDEVMODEA SAL_DEVMODE_A( const ImplJobSetup* pSetupData )
110 LPDEVMODEA pRet = NULL;
111 SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
112 if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_A &&
113 pSetupData->mnDriverDataLen >= sizeof(DEVMODEA)+sizeof(SalDriverData)-1
115 pRet = ((LPDEVMODEA)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
116 return pRet;
119 static LPDEVMODEW SAL_DEVMODE_W( const ImplJobSetup* pSetupData )
121 LPDEVMODEW pRet = NULL;
122 SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
123 if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_W &&
124 pSetupData->mnDriverDataLen >= sizeof(DEVMODEW)+sizeof(SalDriverData)-1
126 pRet = ((LPDEVMODEW)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
127 return pRet;
130 // =======================================================================
132 static sal_uLong ImplWinQueueStatusToSal( DWORD nWinStatus )
134 sal_uLong nStatus = 0;
135 if ( nWinStatus & PRINTER_STATUS_PAUSED )
136 nStatus |= QUEUE_STATUS_PAUSED;
137 if ( nWinStatus & PRINTER_STATUS_ERROR )
138 nStatus |= QUEUE_STATUS_ERROR;
139 if ( nWinStatus & PRINTER_STATUS_PENDING_DELETION )
140 nStatus |= QUEUE_STATUS_PENDING_DELETION;
141 if ( nWinStatus & PRINTER_STATUS_PAPER_JAM )
142 nStatus |= QUEUE_STATUS_PAPER_JAM;
143 if ( nWinStatus & PRINTER_STATUS_PAPER_OUT )
144 nStatus |= QUEUE_STATUS_PAPER_OUT;
145 if ( nWinStatus & PRINTER_STATUS_MANUAL_FEED )
146 nStatus |= QUEUE_STATUS_MANUAL_FEED;
147 if ( nWinStatus & PRINTER_STATUS_PAPER_PROBLEM )
148 nStatus |= QUEUE_STATUS_PAPER_PROBLEM;
149 if ( nWinStatus & PRINTER_STATUS_OFFLINE )
150 nStatus |= QUEUE_STATUS_OFFLINE;
151 if ( nWinStatus & PRINTER_STATUS_IO_ACTIVE )
152 nStatus |= QUEUE_STATUS_IO_ACTIVE;
153 if ( nWinStatus & PRINTER_STATUS_BUSY )
154 nStatus |= QUEUE_STATUS_BUSY;
155 if ( nWinStatus & PRINTER_STATUS_PRINTING )
156 nStatus |= QUEUE_STATUS_PRINTING;
157 if ( nWinStatus & PRINTER_STATUS_OUTPUT_BIN_FULL )
158 nStatus |= QUEUE_STATUS_OUTPUT_BIN_FULL;
159 if ( nWinStatus & PRINTER_STATUS_WAITING )
160 nStatus |= QUEUE_STATUS_WAITING;
161 if ( nWinStatus & PRINTER_STATUS_PROCESSING )
162 nStatus |= QUEUE_STATUS_PROCESSING;
163 if ( nWinStatus & PRINTER_STATUS_INITIALIZING )
164 nStatus |= QUEUE_STATUS_INITIALIZING;
165 if ( nWinStatus & PRINTER_STATUS_WARMING_UP )
166 nStatus |= QUEUE_STATUS_WARMING_UP;
167 if ( nWinStatus & PRINTER_STATUS_TONER_LOW )
168 nStatus |= QUEUE_STATUS_TONER_LOW;
169 if ( nWinStatus & PRINTER_STATUS_NO_TONER )
170 nStatus |= QUEUE_STATUS_NO_TONER;
171 if ( nWinStatus & PRINTER_STATUS_PAGE_PUNT )
172 nStatus |= QUEUE_STATUS_PAGE_PUNT;
173 if ( nWinStatus & PRINTER_STATUS_USER_INTERVENTION )
174 nStatus |= QUEUE_STATUS_USER_INTERVENTION;
175 if ( nWinStatus & PRINTER_STATUS_OUT_OF_MEMORY )
176 nStatus |= QUEUE_STATUS_OUT_OF_MEMORY;
177 if ( nWinStatus & PRINTER_STATUS_DOOR_OPEN )
178 nStatus |= QUEUE_STATUS_DOOR_OPEN;
179 if ( nWinStatus & PRINTER_STATUS_SERVER_UNKNOWN )
180 nStatus |= QUEUE_STATUS_SERVER_UNKNOWN;
181 if ( nWinStatus & PRINTER_STATUS_POWER_SAVE )
182 nStatus |= QUEUE_STATUS_POWER_SAVE;
183 if ( !nStatus && !(nWinStatus & PRINTER_STATUS_NOT_AVAILABLE) )
184 nStatus |= QUEUE_STATUS_READY;
185 return nStatus;
188 // -----------------------------------------------------------------------
190 static void getPrinterQueueInfoOldStyle( ImplPrnQueueList* pList )
192 DWORD i;
193 DWORD n;
194 DWORD nBytes = 0;
195 DWORD nInfoPrn2;
196 sal_Bool bFound = FALSE;
197 PRINTER_INFO_2* pWinInfo2 = NULL;
198 PRINTER_INFO_2* pGetInfo2;
199 EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoPrn2 );
200 if ( nBytes )
202 pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
203 if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoPrn2 ) )
205 pGetInfo2 = pWinInfo2;
206 for ( i = 0; i < nInfoPrn2; i++ )
208 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
209 pInfo->maPrinterName = ImplSalGetUniString( pGetInfo2->pPrinterName );
210 pInfo->maDriver = ImplSalGetUniString( pGetInfo2->pDriverName );
211 XubString aPortName;
212 if ( pGetInfo2->pPortName )
213 aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
214 // pLocation can be 0 (the Windows docu doesn't describe this)
215 if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
216 pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
217 else
218 pInfo->maLocation = aPortName;
219 // pComment can be 0 (the Windows docu doesn't describe this)
220 if ( pGetInfo2->pComment )
221 pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
222 pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
223 pInfo->mnJobs = pGetInfo2->cJobs;
224 pInfo->mpSysData = new XubString( aPortName );
225 pList->Add( pInfo );
226 pGetInfo2++;
229 bFound = TRUE;
233 // read printers from win.ini
234 // TODO: MSDN: GetProfileString() should not be called from server
235 // code because it is just there for WIN16 compatibility
236 UINT nSize = 4096;
237 char* pBuf = new char[nSize];
238 UINT nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
239 while ( nRead >= nSize-2 )
241 nSize += 2048;
242 delete []pBuf;
243 pBuf = new char[nSize];
244 nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
247 // extract printer names from buffer and fill list
248 char* pName = pBuf;
249 while ( *pName )
251 char* pPortName;
252 char* pTmp;
253 char aPortBuf[256];
254 GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) );
256 pPortName = aPortBuf;
258 // create name
259 xub_StrLen nNameLen = sal::static_int_cast<xub_StrLen>(strlen( pName ));
260 XubString aName( ImplSalGetUniString( pName, nNameLen ) );
262 // get driver name
263 pTmp = pPortName;
264 while ( *pTmp != ',' )
265 pTmp++;
266 XubString aDriver( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) );
267 pPortName = pTmp;
269 // get port names
272 pPortName++;
273 pTmp = pPortName;
274 while ( *pTmp && (*pTmp != ',') )
275 pTmp++;
277 String aPortName( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) );
279 // create new entry
280 // look up if printer was already found in first loop
281 sal_Bool bAdd = TRUE;
282 if ( pWinInfo2 )
284 pGetInfo2 = pWinInfo2;
285 for ( n = 0; n < nInfoPrn2; n++ )
287 if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) )
289 bAdd = FALSE;
290 break;
292 pGetInfo2++;
295 // if it's a new printer, add it
296 if ( bAdd )
298 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
299 pInfo->maPrinterName = aName;
300 pInfo->maDriver = aDriver;
301 pInfo->maLocation = aPortName;
302 pInfo->mnStatus = 0;
303 pInfo->mnJobs = QUEUE_JOBS_DONTKNOW;
304 pInfo->mpSysData = new XubString( aPortName );
305 pList->Add( pInfo );
308 while ( *pTmp == ',' );
310 pName += nNameLen + 1;
313 delete []pBuf;
314 rtl_freeMemory( pWinInfo2 );
317 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
319 if( ! aSalShlData.mbWPrinter )
321 getPrinterQueueInfoOldStyle( pList );
322 return;
324 DWORD i;
325 DWORD nBytes = 0;
326 DWORD nInfoPrn4 = 0;
327 PRINTER_INFO_4W* pWinInfo4 = NULL;
328 EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 );
329 if ( nBytes )
331 pWinInfo4 = (PRINTER_INFO_4W*) rtl_allocateMemory( nBytes );
332 if ( EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)pWinInfo4, nBytes, &nBytes, &nInfoPrn4 ) )
334 for ( i = 0; i < nInfoPrn4; i++ )
336 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
337 pInfo->maPrinterName = UniString( reinterpret_cast< const sal_Unicode* >(pWinInfo4[i].pPrinterName) );
338 pInfo->mnStatus = 0;
339 pInfo->mnJobs = 0;
340 pInfo->mpSysData = NULL;
341 pList->Add( pInfo );
344 rtl_freeMemory( pWinInfo4 );
348 // -----------------------------------------------------------------------
350 static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo* pInfo )
352 DWORD nBytes = 0;
353 DWORD nInfoRet;
354 PRINTER_INFO_2* pWinInfo2;
355 EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoRet );
356 if ( nBytes )
358 pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
359 if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoRet ) )
361 PRINTER_INFO_2* pGetInfo2 = pWinInfo2;
362 for ( DWORD i = 0; i < nInfoRet; i++ )
364 if ( pInfo->maPrinterName.EqualsAscii( pGetInfo2->pPrinterName ) &&
365 ( pInfo->maDriver.Len() == 0 ||
366 pInfo->maDriver.EqualsAscii( pGetInfo2->pDriverName ) )
369 XubString aPortName;
370 if ( pGetInfo2->pPortName )
371 aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
372 // pLocation can be 0 (the Windows docu doesn't describe this)
373 if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
374 pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
375 else
376 pInfo->maLocation = aPortName;
377 // pComment can be 0 (the Windows docu doesn't describe this)
378 if ( pGetInfo2->pComment )
379 pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
380 pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
381 pInfo->mnJobs = pGetInfo2->cJobs;
382 if( ! pInfo->mpSysData )
383 pInfo->mpSysData = new XubString( aPortName );
384 break;
387 pGetInfo2++;
391 rtl_freeMemory( pWinInfo2 );
395 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
397 if( ! aSalShlData.mbWPrinter )
399 getPrinterQueueStateOldStyle( pInfo );
400 return;
403 HANDLE hPrinter = 0;
404 LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.GetBuffer()));
405 if( OpenPrinterW( pPrnName, &hPrinter, NULL ) )
407 DWORD nBytes = 0;
408 GetPrinterW( hPrinter, 2, NULL, 0, &nBytes );
409 if( nBytes )
411 PRINTER_INFO_2W* pWinInfo2 = (PRINTER_INFO_2W*)rtl_allocateMemory(nBytes);
412 if( GetPrinterW( hPrinter, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes ) )
414 if( pWinInfo2->pDriverName )
415 pInfo->maDriver = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pDriverName) );
416 XubString aPortName;
417 if ( pWinInfo2->pPortName )
418 aPortName = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pPortName) );
419 // pLocation can be 0 (the Windows docu doesn't describe this)
420 if ( pWinInfo2->pLocation && *pWinInfo2->pLocation )
421 pInfo->maLocation = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pLocation) );
422 else
423 pInfo->maLocation = aPortName;
424 // pComment can be 0 (the Windows docu doesn't describe this)
425 if ( pWinInfo2->pComment )
426 pInfo->maComment = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pComment) );
427 pInfo->mnStatus = ImplWinQueueStatusToSal( pWinInfo2->Status );
428 pInfo->mnJobs = pWinInfo2->cJobs;
429 if( ! pInfo->mpSysData )
430 pInfo->mpSysData = new XubString( aPortName );
432 rtl_freeMemory(pWinInfo2);
434 ClosePrinter( hPrinter );
438 // -----------------------------------------------------------------------
440 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
442 delete (String*)(pInfo->mpSysData);
443 delete pInfo;
446 // -----------------------------------------------------------------------
447 XubString WinSalInstance::GetDefaultPrinter()
449 static bool bGetDefPrtAPI = true;
450 static sal_Bool(WINAPI*pGetDefaultPrinter)(LPWSTR,LPDWORD) = NULL;
451 // try to use GetDefaultPrinter API (not available prior to W2000)
452 if( bGetDefPrtAPI )
454 bGetDefPrtAPI = false;
455 // check for W2k and XP
456 if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
458 OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "winspool.drv" ) );
459 oslModule pLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
460 oslGenericFunction pFunc = NULL;
461 if( pLib )
463 OUString queryFuncName( RTL_CONSTASCII_USTRINGPARAM( "GetDefaultPrinterW" ) );
464 pFunc = osl_getFunctionSymbol( pLib, queryFuncName.pData );
467 pGetDefaultPrinter = (sal_Bool(WINAPI*)(LPWSTR,LPDWORD)) pFunc;
470 if( pGetDefaultPrinter )
472 DWORD nChars = 0;
473 pGetDefaultPrinter( NULL, &nChars );
474 if( nChars )
476 LPWSTR pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR));
477 XubString aDefPrt;
478 if( pGetDefaultPrinter( pStr, &nChars ) )
480 aDefPrt = reinterpret_cast<sal_Unicode* >(pStr);
482 rtl_freeMemory( pStr );
483 if( aDefPrt.Len() )
484 return aDefPrt;
488 // get default printer from win.ini
489 char szBuffer[256];
490 GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) );
491 if ( szBuffer[0] )
493 // Printername suchen
494 char* pBuf = szBuffer;
495 char* pTmp = pBuf;
496 while ( *pTmp && (*pTmp != ',') )
497 pTmp++;
498 return ImplSalGetUniString( pBuf, (xub_StrLen)(pTmp-pBuf) );
500 else
501 return XubString();
504 // =======================================================================
506 static DWORD ImplDeviceCaps( WinSalInfoPrinter* pPrinter, WORD nCaps,
507 BYTE* pOutput, const ImplJobSetup* pSetupData )
509 if( aSalShlData.mbWPrinter )
511 DEVMODEW* pDevMode;
512 if ( !pSetupData || !pSetupData->mpDriverData )
513 pDevMode = NULL;
514 else
515 pDevMode = SAL_DEVMODE_W( pSetupData );
517 return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR>(pPrinter->maDeviceName.GetBuffer()),
518 reinterpret_cast<LPCWSTR>(pPrinter->maPortName.GetBuffer()),
519 nCaps, (LPWSTR)pOutput, pDevMode );
521 else
523 DEVMODEA* pDevMode;
524 if ( !pSetupData || !pSetupData->mpDriverData )
525 pDevMode = NULL;
526 else
527 pDevMode = SAL_DEVMODE_A( pSetupData );
529 return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
530 ImplSalGetWinAnsiString( pPrinter->maPortName, TRUE ).GetBuffer(),
531 nCaps, (LPSTR)pOutput, pDevMode );
535 // -----------------------------------------------------------------------
537 static sal_Bool ImplTestSalJobSetup( WinSalInfoPrinter* pPrinter,
538 ImplJobSetup* pSetupData, sal_Bool bDelete )
540 if ( pSetupData && pSetupData->mpDriverData )
542 // signature and size must fit to avoid using
543 // JobSetups from a wrong system
545 // initialize versions from jobsetup
546 // those will be overwritten with driver's version
547 DEVMODEA* pDevModeA = NULL;
548 DEVMODEW* pDevModeW = NULL;
549 LONG dmSpecVersion = -1;
550 LONG dmDriverVersion = -1;
551 SalDriverData* pSalDriverData = (SalDriverData*)pSetupData->mpDriverData;
552 BYTE* pDriverData = ((BYTE*)pSalDriverData) + pSalDriverData->mnDriverOffset;
553 if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_W )
555 if( aSalShlData.mbWPrinter )
556 pDevModeW = (DEVMODEW*)pDriverData;
558 else if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_A )
560 if( ! aSalShlData.mbWPrinter )
561 pDevModeA = (DEVMODEA*)pDriverData;
564 long nSysJobSize = -1;
565 if( pPrinter && ( pDevModeA || pDevModeW ) )
567 // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
568 // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
569 // can avoid potential driver crashes as their jobsetups are often not compatible
570 // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
571 ByteString aPrinterNameA= ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
572 HANDLE hPrn;
573 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
574 if ( ! aSalShlData.mbWPrinter )
576 if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
577 return FALSE;
579 else
580 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
581 return FALSE;
583 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
584 if( hPrn == HGDI_ERROR )
585 return FALSE;
587 if( aSalShlData.mbWPrinter )
589 nSysJobSize = DocumentPropertiesW( 0, hPrn,
590 pPrinterNameW,
591 NULL, NULL, 0 );
593 else
595 nSysJobSize = DocumentPropertiesA( 0, hPrn,
596 (LPSTR)aPrinterNameA.GetBuffer(),
597 NULL, NULL, 0 );
600 if( nSysJobSize < 0 )
602 ClosePrinter( hPrn );
603 return FALSE;
605 BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize );
606 LONG nRet = -1;
607 if( aSalShlData.mbWPrinter )
609 nRet = DocumentPropertiesW( 0, hPrn,
610 pPrinterNameW,
611 (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER );
613 else
615 nRet = DocumentPropertiesA( 0, hPrn,
616 (LPSTR)aPrinterNameA.GetBuffer(),
617 (LPDEVMODEA)pBuffer, NULL, DM_OUT_BUFFER );
619 if( nRet < 0 )
621 ClosePrinter( hPrn );
622 return FALSE;
625 // the spec version differs between the windows platforms, ie 98,NT,2000/XP
626 // this allows us to throw away printer settings from other platforms that might crash a buggy driver
627 // we check the driver version as well
628 dmSpecVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmSpecVersion : ((DEVMODEA*)pBuffer)->dmSpecVersion;
629 dmDriverVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmDriverVersion : ((DEVMODEA*)pBuffer)->dmDriverVersion;
631 ClosePrinter( hPrn );
633 SalDriverData* pSetupDriverData = (SalDriverData*)(pSetupData->mpDriverData);
634 if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) &&
635 (pPrinter->maDriverName == pSetupData->maDriver) &&
636 (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) &&
637 (long)(pSetupData->mnDriverDataLen - pSetupDriverData->mnDriverOffset) == nSysJobSize &&
638 pSetupDriverData->mnSysSignature == SAL_DRIVERDATA_SYSSIGN )
640 if( pDevModeA &&
641 (dmSpecVersion == pDevModeA->dmSpecVersion) &&
642 (dmDriverVersion == pDevModeA->dmDriverVersion) )
643 return TRUE;
644 if( pDevModeW &&
645 (dmSpecVersion == pDevModeW->dmSpecVersion) &&
646 (dmDriverVersion == pDevModeW->dmDriverVersion) )
647 return TRUE;
649 if ( bDelete )
651 rtl_freeMemory( pSetupData->mpDriverData );
652 pSetupData->mpDriverData = NULL;
653 pSetupData->mnDriverDataLen = 0;
657 return FALSE;
660 // -----------------------------------------------------------------------
662 static sal_Bool ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData,
663 sal_Bool bIn, WinSalFrame* pVisibleDlgParent )
665 ByteString aPrinterNameA = ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
666 HANDLE hPrn;
667 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
668 if( aSalShlData.mbWPrinter )
670 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
671 return FALSE;
673 else
675 if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
676 return FALSE;
678 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
679 if( hPrn == HGDI_ERROR )
680 return FALSE;
682 LONG nRet;
683 LONG nSysJobSize = -1;
684 HWND hWnd = 0;
685 DWORD nMode = DM_OUT_BUFFER;
686 sal_uLong nDriverDataLen = 0;
687 SalDriverData* pOutBuffer = NULL;
688 BYTE* pInBuffer = NULL;
690 if( aSalShlData.mbWPrinter )
692 nSysJobSize = DocumentPropertiesW( hWnd, hPrn,
693 pPrinterNameW,
694 NULL, NULL, 0 );
696 else
697 nSysJobSize = DocumentPropertiesA( hWnd, hPrn,
698 (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
699 NULL, NULL, 0 );
700 if ( nSysJobSize < 0 )
702 ClosePrinter( hPrn );
703 return FALSE;
706 // Outputbuffer anlegen
707 nDriverDataLen = sizeof(SalDriverData) + nSysJobSize-1;
708 pOutBuffer = (SalDriverData*)rtl_allocateZeroMemory( nDriverDataLen );
709 pOutBuffer->mnSysSignature = SAL_DRIVERDATA_SYSSIGN;
710 pOutBuffer->mnVersion = aSalShlData.mbWPrinter ? SAL_DRIVERDATA_VERSION_W : SAL_DRIVERDATA_VERSION_A;
711 // calculate driver data offset including structure padding
712 pOutBuffer->mnDriverOffset = sal::static_int_cast<sal_uInt16>(
713 (char*)pOutBuffer->maDriverData -
714 (char*)pOutBuffer );
716 // Testen, ob wir einen geeigneten Inputbuffer haben
717 if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) )
719 pInBuffer = (BYTE*)pSetupData->mpDriverData + ((SalDriverData*)pSetupData->mpDriverData)->mnDriverOffset;
720 nMode |= DM_IN_BUFFER;
723 // Testen, ob Dialog angezeigt werden soll
724 if ( pVisibleDlgParent )
726 hWnd = pVisibleDlgParent->mhWnd;
727 nMode |= DM_IN_PROMPT;
730 // Release mutex, in the other case we don't get paints and so on
731 sal_uLong nMutexCount=0;
732 if ( pVisibleDlgParent )
733 nMutexCount = ImplSalReleaseYieldMutex();
735 BYTE* pOutDevMode = (((BYTE*)pOutBuffer) + pOutBuffer->mnDriverOffset);
736 if( aSalShlData.mbWPrinter )
738 nRet = DocumentPropertiesW( hWnd, hPrn,
739 pPrinterNameW,
740 (LPDEVMODEW)pOutDevMode, (LPDEVMODEW)pInBuffer, nMode );
742 else
744 nRet = DocumentPropertiesA( hWnd, hPrn,
745 (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
746 (LPDEVMODEA)pOutDevMode, (LPDEVMODEA)pInBuffer, nMode );
748 if ( pVisibleDlgParent )
749 ImplSalAcquireYieldMutex( nMutexCount );
750 ClosePrinter( hPrn );
752 if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) )
754 rtl_freeMemory( pOutBuffer );
755 return FALSE;
758 // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
759 if( aSalShlData.mbWPrinter )
761 if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 64 )
763 sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmDeviceName );
764 if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )/sizeof(sal_Unicode) )
765 memset( ((LPDEVMODEW)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )-(nLen*sizeof(sal_Unicode)) );
767 if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 166 )
769 sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmFormName );
770 if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )/sizeof(sal_Unicode) )
771 memset( ((LPDEVMODEW)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )-(nLen*sizeof(sal_Unicode)) );
774 else
776 if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 32 )
778 sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmDeviceName );
779 if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName ) )
780 memset( ((LPDEVMODEA)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName )-nLen );
782 if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 102 )
784 sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmFormName );
785 if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName ) )
786 memset( ((LPDEVMODEA)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName )-nLen );
790 // update data
791 if ( pSetupData->mpDriverData )
792 rtl_freeMemory( pSetupData->mpDriverData );
793 pSetupData->mnDriverDataLen = nDriverDataLen;
794 pSetupData->mpDriverData = (BYTE*)pOutBuffer;
795 pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
797 return TRUE;
800 // -----------------------------------------------------------------------
802 #define DECLARE_DEVMODE( i )\
803 DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\
804 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
805 if( pDevModeA == NULL && pDevModeW == NULL )\
806 return
808 #define CHOOSE_DEVMODE(i)\
809 (pDevModeW ? pDevModeW->i : pDevModeA->i)
811 static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags )
813 if ( !pSetupData || !pSetupData->mpDriverData )
814 return;
816 DECLARE_DEVMODE( pSetupData );
818 // Orientation
819 if ( nFlags & SAL_JOBSET_ORIENTATION )
821 if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_PORTRAIT )
822 pSetupData->meOrientation = ORIENTATION_PORTRAIT;
823 else if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_LANDSCAPE )
824 pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
827 // PaperBin
828 if ( nFlags & SAL_JOBSET_PAPERBIN )
830 sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
832 if ( nCount && (nCount != GDI_ERROR) )
834 WORD* pBins = (WORD*)rtl_allocateZeroMemory( nCount*sizeof(WORD) );
835 ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
836 pSetupData->mnPaperBin = 0;
838 // search the right bin and assign index to mnPaperBin
839 for( sal_uLong i = 0; i < nCount; i++ )
841 if( CHOOSE_DEVMODE(dmDefaultSource) == pBins[ i ] )
843 pSetupData->mnPaperBin = (sal_uInt16)i;
844 break;
848 rtl_freeMemory( pBins );
852 // PaperSize
853 if ( nFlags & SAL_JOBSET_PAPERSIZE )
855 if( (CHOOSE_DEVMODE(dmFields) & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) )
857 pSetupData->mnPaperWidth = CHOOSE_DEVMODE(dmPaperWidth)*10;
858 pSetupData->mnPaperHeight = CHOOSE_DEVMODE(dmPaperLength)*10;
860 else
862 sal_uLong nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
863 WORD* pPapers = NULL;
864 sal_uLong nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
865 POINT* pPaperSizes = NULL;
866 if ( nPaperCount && (nPaperCount != GDI_ERROR) )
868 pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
869 ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
871 if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
873 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
874 ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
876 if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers )
878 for( sal_uLong i = 0; i < nPaperCount; i++ )
880 if( pPapers[ i ] == CHOOSE_DEVMODE(dmPaperSize) )
882 pSetupData->mnPaperWidth = pPaperSizes[ i ].x*10;
883 pSetupData->mnPaperHeight = pPaperSizes[ i ].y*10;
884 break;
888 if( pPapers )
889 rtl_freeMemory( pPapers );
890 if( pPaperSizes )
891 rtl_freeMemory( pPaperSizes );
893 switch( CHOOSE_DEVMODE(dmPaperSize) )
895 case( DMPAPER_LETTER ):
896 pSetupData->mePaperFormat = PAPER_LETTER;
897 break;
898 case( DMPAPER_TABLOID ):
899 pSetupData->mePaperFormat = PAPER_TABLOID;
900 break;
901 case( DMPAPER_LEDGER ):
902 pSetupData->mePaperFormat = PAPER_LEDGER;
903 break;
904 case( DMPAPER_LEGAL ):
905 pSetupData->mePaperFormat = PAPER_LEGAL;
906 break;
907 case( DMPAPER_STATEMENT ):
908 pSetupData->mePaperFormat = PAPER_STATEMENT;
909 break;
910 case( DMPAPER_EXECUTIVE ):
911 pSetupData->mePaperFormat = PAPER_EXECUTIVE;
912 break;
913 case( DMPAPER_A3 ):
914 pSetupData->mePaperFormat = PAPER_A3;
915 break;
916 case( DMPAPER_A4 ):
917 pSetupData->mePaperFormat = PAPER_A4;
918 break;
919 case( DMPAPER_A5 ):
920 pSetupData->mePaperFormat = PAPER_A5;
921 break;
922 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
923 //i.e.
924 //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
925 //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
926 //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
927 //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
928 //matches our Excel filter's belief about the matching XlPaperSize
929 //enumeration.
931 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
932 ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
933 //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
934 //(cmc)
935 case( DMPAPER_B4 ):
936 pSetupData->mePaperFormat = PAPER_B4_JIS;
937 break;
938 case( DMPAPER_B5 ):
939 pSetupData->mePaperFormat = PAPER_B5_JIS;
940 break;
941 case( DMPAPER_QUARTO ):
942 pSetupData->mePaperFormat = PAPER_QUARTO;
943 break;
944 case( DMPAPER_10X14 ):
945 pSetupData->mePaperFormat = PAPER_10x14;
946 break;
947 case( DMPAPER_NOTE ):
948 pSetupData->mePaperFormat = PAPER_LETTER;
949 break;
950 case( DMPAPER_ENV_9 ):
951 pSetupData->mePaperFormat = PAPER_ENV_9;
952 break;
953 case( DMPAPER_ENV_10 ):
954 pSetupData->mePaperFormat = PAPER_ENV_10;
955 break;
956 case( DMPAPER_ENV_11 ):
957 pSetupData->mePaperFormat = PAPER_ENV_11;
958 break;
959 case( DMPAPER_ENV_12 ):
960 pSetupData->mePaperFormat = PAPER_ENV_12;
961 break;
962 case( DMPAPER_ENV_14 ):
963 pSetupData->mePaperFormat = PAPER_ENV_14;
964 break;
965 case( DMPAPER_CSHEET ):
966 pSetupData->mePaperFormat = PAPER_C;
967 break;
968 case( DMPAPER_DSHEET ):
969 pSetupData->mePaperFormat = PAPER_D;
970 break;
971 case( DMPAPER_ESHEET ):
972 pSetupData->mePaperFormat = PAPER_E;
973 break;
974 case( DMPAPER_ENV_DL):
975 pSetupData->mePaperFormat = PAPER_ENV_DL;
976 break;
977 case( DMPAPER_ENV_C5):
978 pSetupData->mePaperFormat = PAPER_ENV_C5;
979 break;
980 case( DMPAPER_ENV_C3):
981 pSetupData->mePaperFormat = PAPER_ENV_C3;
982 break;
983 case( DMPAPER_ENV_C4):
984 pSetupData->mePaperFormat = PAPER_ENV_C4;
985 break;
986 case( DMPAPER_ENV_C6):
987 pSetupData->mePaperFormat = PAPER_ENV_C6;
988 break;
989 case( DMPAPER_ENV_C65):
990 pSetupData->mePaperFormat = PAPER_ENV_C65;
991 break;
992 case( DMPAPER_ENV_ITALY ):
993 pSetupData->mePaperFormat = PAPER_ENV_ITALY;
994 break;
995 case( DMPAPER_ENV_MONARCH ):
996 pSetupData->mePaperFormat = PAPER_ENV_MONARCH;
997 break;
998 case( DMPAPER_ENV_PERSONAL ):
999 pSetupData->mePaperFormat = PAPER_ENV_PERSONAL;
1000 break;
1001 case( DMPAPER_FANFOLD_US ):
1002 pSetupData->mePaperFormat = PAPER_FANFOLD_US;
1003 break;
1004 case( DMPAPER_FANFOLD_STD_GERMAN ):
1005 pSetupData->mePaperFormat = PAPER_FANFOLD_DE;
1006 break;
1007 case( DMPAPER_FANFOLD_LGL_GERMAN ):
1008 pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE;
1009 break;
1010 case( DMPAPER_ISO_B4 ):
1011 pSetupData->mePaperFormat = PAPER_B4_ISO;
1012 break;
1013 case( DMPAPER_JAPANESE_POSTCARD ):
1014 pSetupData->mePaperFormat = PAPER_POSTCARD_JP;
1015 break;
1016 case( DMPAPER_9X11 ):
1017 pSetupData->mePaperFormat = PAPER_9x11;
1018 break;
1019 case( DMPAPER_10X11 ):
1020 pSetupData->mePaperFormat = PAPER_10x11;
1021 break;
1022 case( DMPAPER_15X11 ):
1023 pSetupData->mePaperFormat = PAPER_15x11;
1024 break;
1025 case( DMPAPER_ENV_INVITE ):
1026 pSetupData->mePaperFormat = PAPER_ENV_INVITE;
1027 break;
1028 case( DMPAPER_A_PLUS ):
1029 pSetupData->mePaperFormat = PAPER_A_PLUS;
1030 break;
1031 case( DMPAPER_B_PLUS ):
1032 pSetupData->mePaperFormat = PAPER_B_PLUS;
1033 break;
1034 case( DMPAPER_LETTER_PLUS ):
1035 pSetupData->mePaperFormat = PAPER_LETTER_PLUS;
1036 break;
1037 case( DMPAPER_A4_PLUS ):
1038 pSetupData->mePaperFormat = PAPER_A4_PLUS;
1039 break;
1040 case( DMPAPER_A2 ):
1041 pSetupData->mePaperFormat = PAPER_A2;
1042 break;
1043 case( DMPAPER_DBL_JAPANESE_POSTCARD ):
1044 pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP;
1045 break;
1046 case( DMPAPER_A6 ):
1047 pSetupData->mePaperFormat = PAPER_A6;
1048 break;
1049 case( DMPAPER_B6_JIS ):
1050 pSetupData->mePaperFormat = PAPER_B6_JIS;
1051 break;
1052 case( DMPAPER_12X11 ):
1053 pSetupData->mePaperFormat = PAPER_12x11;
1054 break;
1055 default:
1056 pSetupData->mePaperFormat = PAPER_USER;
1057 break;
1061 if( nFlags & SAL_JOBSET_DUPLEXMODE )
1063 DuplexMode eDuplex = DUPLEX_UNKNOWN;
1064 if( (CHOOSE_DEVMODE(dmFields) & DM_DUPLEX) )
1066 if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_SIMPLEX )
1067 eDuplex = DUPLEX_OFF;
1068 else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_VERTICAL )
1069 eDuplex = DUPLEX_LONGEDGE;
1070 else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_HORIZONTAL )
1071 eDuplex = DUPLEX_SHORTEDGE;
1073 pSetupData->meDuplexMode = eDuplex;
1077 // -----------------------------------------------------------------------
1079 static void ImplJobSetupToDevMode( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags )
1081 if ( !pSetupData || !pSetupData->mpDriverData )
1082 return;
1084 DECLARE_DEVMODE( pSetupData );
1086 // Orientation
1087 if ( nFlags & SAL_JOBSET_ORIENTATION )
1089 CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION;
1090 if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT )
1091 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT;
1092 else
1093 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE;
1096 // PaperBin
1097 if ( nFlags & SAL_JOBSET_PAPERBIN )
1099 sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
1101 if ( nCount && (nCount != GDI_ERROR) )
1103 WORD* pBins = (WORD*)rtl_allocateZeroMemory(nCount*sizeof(WORD));
1104 ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
1105 CHOOSE_DEVMODE(dmFields) |= DM_DEFAULTSOURCE;
1106 CHOOSE_DEVMODE(dmDefaultSource) = pBins[ pSetupData->mnPaperBin ];
1107 rtl_freeMemory( pBins );
1111 // PaperSize
1112 if ( nFlags & SAL_JOBSET_PAPERSIZE )
1114 CHOOSE_DEVMODE(dmFields) |= DM_PAPERSIZE;
1115 CHOOSE_DEVMODE(dmPaperWidth) = 0;
1116 CHOOSE_DEVMODE(dmPaperLength) = 0;
1118 switch( pSetupData->mePaperFormat )
1120 case( PAPER_A2 ):
1121 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2;
1122 break;
1123 case( PAPER_A3 ):
1124 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3;
1125 break;
1126 case( PAPER_A4 ):
1127 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4;
1128 break;
1129 case( PAPER_A5 ):
1130 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5;
1131 break;
1132 case( PAPER_B4_ISO):
1133 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4;
1134 break;
1135 case( PAPER_LETTER ):
1136 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER;
1137 break;
1138 case( PAPER_LEGAL ):
1139 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL;
1140 break;
1141 case( PAPER_TABLOID ):
1142 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID;
1143 break;
1144 #if 0
1145 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
1146 //DMPAPER_ENV_B6 is documented as:
1147 //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
1148 //which is the wrong way around, it is surely 125 x 176, i.e.
1149 //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
1150 //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
1151 //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
1152 case( PAPER_B6_ISO ):
1153 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_B6;
1154 break;
1155 #endif
1156 case( PAPER_ENV_C4 ):
1157 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4;
1158 break;
1159 case( PAPER_ENV_C5 ):
1160 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5;
1161 break;
1162 case( PAPER_ENV_C6 ):
1163 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6;
1164 break;
1165 case( PAPER_ENV_C65 ):
1166 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65;
1167 break;
1168 case( PAPER_ENV_DL ):
1169 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL;
1170 break;
1171 case( PAPER_C ):
1172 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET;
1173 break;
1174 case( PAPER_D ):
1175 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET;
1176 break;
1177 case( PAPER_E ):
1178 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET;
1179 break;
1180 case( PAPER_EXECUTIVE ):
1181 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE;
1182 break;
1183 case( PAPER_FANFOLD_LEGAL_DE ):
1184 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN;
1185 break;
1186 case( PAPER_ENV_MONARCH ):
1187 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH;
1188 break;
1189 case( PAPER_ENV_PERSONAL ):
1190 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL;
1191 break;
1192 case( PAPER_ENV_9 ):
1193 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9;
1194 break;
1195 case( PAPER_ENV_10 ):
1196 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10;
1197 break;
1198 case( PAPER_ENV_11 ):
1199 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11;
1200 break;
1201 case( PAPER_ENV_12 ):
1202 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12;
1203 break;
1204 //See the comments on DMPAPER_B4 above
1205 case( PAPER_B4_JIS ):
1206 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4;
1207 break;
1208 case( PAPER_B5_JIS ):
1209 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5;
1210 break;
1211 case( PAPER_B6_JIS ):
1212 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS;
1213 break;
1214 case( PAPER_LEDGER ):
1215 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER;
1216 break;
1217 case( PAPER_STATEMENT ):
1218 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT;
1219 break;
1220 case( PAPER_10x14 ):
1221 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14;
1222 break;
1223 case( PAPER_ENV_14 ):
1224 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14;
1225 break;
1226 case( PAPER_ENV_C3 ):
1227 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3;
1228 break;
1229 case( PAPER_ENV_ITALY ):
1230 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY;
1231 break;
1232 case( PAPER_FANFOLD_US ):
1233 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US;
1234 break;
1235 case( PAPER_FANFOLD_DE ):
1236 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN;
1237 break;
1238 case( PAPER_POSTCARD_JP ):
1239 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD;
1240 break;
1241 case( PAPER_9x11 ):
1242 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11;
1243 break;
1244 case( PAPER_10x11 ):
1245 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11;
1246 break;
1247 case( PAPER_15x11 ):
1248 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11;
1249 break;
1250 case( PAPER_ENV_INVITE ):
1251 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE;
1252 break;
1253 case( PAPER_A_PLUS ):
1254 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS;
1255 break;
1256 case( PAPER_B_PLUS ):
1257 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS;
1258 break;
1259 case( PAPER_LETTER_PLUS ):
1260 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS;
1261 break;
1262 case( PAPER_A4_PLUS ):
1263 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS;
1264 break;
1265 case( PAPER_DOUBLEPOSTCARD_JP ):
1266 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD;
1267 break;
1268 case( PAPER_A6 ):
1269 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6;
1270 break;
1271 case( PAPER_12x11 ):
1272 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11;
1273 break;
1274 default:
1276 short nPaper = 0;
1277 sal_uLong nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
1278 WORD* pPapers = NULL;
1279 sal_uLong nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
1280 POINT* pPaperSizes = NULL;
1281 DWORD nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, NULL, pSetupData );
1282 if ( nPaperCount && (nPaperCount != GDI_ERROR) )
1284 pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
1285 ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
1287 if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
1289 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
1290 ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1292 if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes )
1294 PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
1295 // compare paper formats and select a good match
1296 for ( sal_uLong i = 0; i < nPaperCount; i++ )
1298 if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)))
1300 nPaper = pPapers[i];
1301 break;
1305 // If the printer supports landscape orientation, check paper sizes again
1306 // with landscape orientation. This is necessary as a printer driver provides
1307 // all paper sizes with portrait orientation only!!
1308 if ( !nPaper && nLandscapeAngle != 0 )
1310 PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
1311 for ( sal_uLong i = 0; i < nPaperCount; i++ )
1313 if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) )
1315 nPaper = pPapers[i];
1316 break;
1321 if ( nPaper )
1322 CHOOSE_DEVMODE(dmPaperSize) = nPaper;
1325 if ( !nPaper )
1327 CHOOSE_DEVMODE(dmFields) |= DM_PAPERLENGTH | DM_PAPERWIDTH;
1328 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_USER;
1329 CHOOSE_DEVMODE(dmPaperWidth) = (short)(pSetupData->mnPaperWidth/10);
1330 CHOOSE_DEVMODE(dmPaperLength) = (short)(pSetupData->mnPaperHeight/10);
1333 if ( pPapers )
1334 rtl_freeMemory(pPapers);
1335 if ( pPaperSizes )
1336 rtl_freeMemory(pPaperSizes);
1338 break;
1342 if( (nFlags & SAL_JOBSET_DUPLEXMODE) )
1344 switch( pSetupData->meDuplexMode )
1346 case DUPLEX_OFF:
1347 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1348 CHOOSE_DEVMODE(dmDuplex) = DMDUP_SIMPLEX;
1349 break;
1350 case DUPLEX_SHORTEDGE:
1351 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1352 CHOOSE_DEVMODE(dmDuplex) = DMDUP_HORIZONTAL;
1353 break;
1354 case DUPLEX_LONGEDGE:
1355 CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1356 CHOOSE_DEVMODE(dmDuplex) = DMDUP_VERTICAL;
1357 break;
1358 case DUPLEX_UNKNOWN:
1359 break;
1364 // -----------------------------------------------------------------------
1366 static HDC ImplCreateICW_WithCatch( LPWSTR pDriver,
1367 LPCWSTR pDevice,
1368 LPDEVMODEW pDevMode )
1370 HDC hDC = 0;
1371 CATCH_DRIVER_EX_BEGIN;
1372 hDC = CreateICW( pDriver, pDevice, 0, pDevMode );
1373 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1374 return hDC;
1377 static HDC ImplCreateICA_WithCatch( char* pDriver,
1378 char* pDevice,
1379 LPDEVMODEA pDevMode )
1381 HDC hDC = 0;
1382 CATCH_DRIVER_EX_BEGIN;
1383 hDC = CreateICA( pDriver, pDevice, 0, pDevMode );
1384 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1385 return hDC;
1389 static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1391 HDC hDC = 0;
1392 if( aSalShlData.mbWPrinter )
1394 LPDEVMODEW pDevMode;
1395 if ( pSetupData && pSetupData->mpDriverData )
1396 pDevMode = SAL_DEVMODE_W( pSetupData );
1397 else
1398 pDevMode = NULL;
1399 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1400 // pl: does this hold true for Unicode functions ?
1401 if( pPrinter->maDriverName.Len() > 2048 || pPrinter->maDeviceName.Len() > 2048 )
1402 return 0;
1403 sal_Unicode pDriverName[ 4096 ];
1404 sal_Unicode pDeviceName[ 4096 ];
1405 rtl_copyMemory( pDriverName, pPrinter->maDriverName.GetBuffer(), pPrinter->maDriverName.Len()*sizeof(sal_Unicode));
1406 memset( pDriverName+pPrinter->maDriverName.Len(), 0, 32 );
1407 rtl_copyMemory( pDeviceName, pPrinter->maDeviceName.GetBuffer(), pPrinter->maDeviceName.Len()*sizeof(sal_Unicode));
1408 memset( pDeviceName+pPrinter->maDeviceName.Len(), 0, 32 );
1409 hDC = ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR >(pDriverName),
1410 reinterpret_cast< LPCWSTR >(pDeviceName),
1411 pDevMode );
1413 else
1415 LPDEVMODEA pDevMode;
1416 if ( pSetupData && pSetupData->mpDriverData )
1417 pDevMode = SAL_DEVMODE_A( pSetupData );
1418 else
1419 pDevMode = NULL;
1420 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1421 ByteString aDriver ( ImplSalGetWinAnsiString( pPrinter->maDriverName, TRUE ) );
1422 ByteString aDevice ( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ) );
1423 int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
1424 // #125813# under some circumstances many printer drivers really
1425 // seem to have a problem with the names and their conversions.
1426 // We need to get on to of this, but haven't been able to reproduce
1427 // the problem yet. Put the names on the stack so we get them
1428 // with an eventual crash report.
1429 if( n >= 2048 )
1430 return 0;
1431 n += 2048;
1432 char lpszDriverName[ 4096 ];
1433 char lpszDeviceName[ 4096 ];
1434 strncpy( lpszDriverName, aDriver.GetBuffer(), n );
1435 strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
1436 // HDU: the crashes usually happen in a MBCS to unicode conversion,
1437 // so I suspect the MBCS string's end is not properly recognized.
1438 // The longest MBCS encoding I'm aware of has six bytes per code
1439 // => add a couple of zeroes...
1440 memset( lpszDriverName+aDriver.Len(), 0, 16 );
1441 memset( lpszDeviceName+aDevice.Len(), 0, 16 );
1442 hDC = ImplCreateICA_WithCatch( lpszDriverName,
1443 lpszDeviceName,
1444 pDevMode );
1446 return hDC;
1449 // -----------------------------------------------------------------------
1451 static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC )
1453 WinSalGraphics* pGraphics = new WinSalGraphics;
1454 pGraphics->SetLayout( 0 );
1455 pGraphics->mhDC = hDC;
1456 pGraphics->mhWnd = 0;
1457 pGraphics->mbPrinter = TRUE;
1458 pGraphics->mbVirDev = FALSE;
1459 pGraphics->mbWindow = FALSE;
1460 pGraphics->mbScreen = FALSE;
1461 ImplSalInitGraphics( pGraphics );
1462 return pGraphics;
1465 // -----------------------------------------------------------------------
1467 static sal_Bool ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1469 HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1470 if ( !hNewDC )
1471 return FALSE;
1473 if ( pPrinter->mpGraphics )
1475 ImplSalDeInitGraphics( pPrinter->mpGraphics );
1476 DeleteDC( pPrinter->mpGraphics->mhDC );
1477 delete pPrinter->mpGraphics;
1480 pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hNewDC );
1481 pPrinter->mhDC = hNewDC;
1483 return TRUE;
1486 // =======================================================================
1488 SalInfoPrinter* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
1489 ImplJobSetup* pSetupData )
1491 WinSalInfoPrinter* pPrinter = new WinSalInfoPrinter;
1492 if( ! pQueueInfo->mpSysData )
1493 GetPrinterQueueState( pQueueInfo );
1494 pPrinter->maDriverName = pQueueInfo->maDriver;
1495 pPrinter->maDeviceName = pQueueInfo->maPrinterName;
1496 pPrinter->maPortName = pQueueInfo->mpSysData ?
1497 *(String*)(pQueueInfo->mpSysData)
1498 : String();
1500 // check if the provided setup data match the actual printer
1501 ImplTestSalJobSetup( pPrinter, pSetupData, TRUE );
1503 HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1504 if ( !hDC )
1506 delete pPrinter;
1507 return NULL;
1510 pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hDC );
1511 pPrinter->mhDC = hDC;
1512 if ( !pSetupData->mpDriverData )
1513 ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL );
1514 ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL );
1515 pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
1517 return pPrinter;
1520 // -----------------------------------------------------------------------
1522 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
1524 delete pPrinter;
1527 // =======================================================================
1529 WinSalInfoPrinter::WinSalInfoPrinter() :
1530 mpGraphics( NULL ),
1531 mhDC( 0 ),
1532 mbGraphics( FALSE )
1534 m_bPapersInit = FALSE;
1537 // -----------------------------------------------------------------------
1539 WinSalInfoPrinter::~WinSalInfoPrinter()
1541 if ( mpGraphics )
1543 ImplSalDeInitGraphics( mpGraphics );
1544 DeleteDC( mpGraphics->mhDC );
1545 delete mpGraphics;
1549 // -----------------------------------------------------------------------
1551 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
1553 m_aPaperFormats.clear();
1555 DWORD nCount = ImplDeviceCaps( this, DC_PAPERSIZE, NULL, pSetupData );
1556 if( nCount == GDI_ERROR )
1557 nCount = 0;
1559 POINT* pPaperSizes = NULL;
1560 if( nCount )
1562 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nCount*sizeof(POINT));
1563 ImplDeviceCaps( this, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1565 if( aSalShlData.mbWPrinter )
1567 sal_Unicode* pNamesBuffer = (sal_Unicode*)rtl_allocateMemory(nCount*64*sizeof(sal_Unicode));
1568 ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1569 for( DWORD i = 0; i < nCount; ++i )
1571 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1572 m_aPaperFormats.push_back( aInfo );
1574 rtl_freeMemory( pNamesBuffer );
1576 else
1578 char* pNamesBuffer = (char*)rtl_allocateMemory(nCount*64);
1579 ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1580 for( DWORD i = 0; i < nCount; ++i )
1582 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1583 m_aPaperFormats.push_back( aInfo );
1585 rtl_freeMemory( pNamesBuffer );
1587 rtl_freeMemory( pPaperSizes );
1590 m_bPapersInit = true;
1593 // -----------------------------------------------------------------------
1595 int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
1597 int nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
1599 if( nRet != GDI_ERROR )
1600 return nRet * 10;
1601 else
1602 return 900; // guess
1605 // -----------------------------------------------------------------------
1607 SalGraphics* WinSalInfoPrinter::GetGraphics()
1609 if ( mbGraphics )
1610 return NULL;
1612 if ( mpGraphics )
1613 mbGraphics = TRUE;
1615 return mpGraphics;
1618 // -----------------------------------------------------------------------
1620 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics* )
1622 mbGraphics = FALSE;
1625 // -----------------------------------------------------------------------
1627 sal_Bool WinSalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData )
1629 if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, static_cast<WinSalFrame*>(pFrame) ) )
1631 ImplDevModeToJobSetup( this, pSetupData, SAL_JOBSET_ALL );
1632 return ImplUpdateSalPrnIC( this, pSetupData );
1635 return FALSE;
1638 // -----------------------------------------------------------------------
1640 sal_Bool WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
1642 if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) )
1643 return FALSE;
1644 return ImplUpdateSalPrnIC( this, pSetupData );
1647 // -----------------------------------------------------------------------
1649 sal_Bool WinSalInfoPrinter::SetData( sal_uLong nFlags, ImplJobSetup* pSetupData )
1651 ImplJobSetupToDevMode( this, pSetupData, nFlags );
1652 if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, NULL ) )
1654 ImplDevModeToJobSetup( this, pSetupData, nFlags );
1655 return ImplUpdateSalPrnIC( this, pSetupData );
1658 return FALSE;
1661 // -----------------------------------------------------------------------
1663 sal_uLong WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData )
1665 DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1666 if ( nRet && (nRet != GDI_ERROR) )
1667 return nRet;
1668 else
1669 return 0;
1672 // -----------------------------------------------------------------------
1674 XubString WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pSetupData, sal_uLong nPaperBin )
1676 XubString aPaperBinName;
1678 DWORD nBins = ImplDeviceCaps( this, DC_BINNAMES, NULL, pSetupData );
1679 if ( (nPaperBin < nBins) && (nBins != GDI_ERROR) )
1681 if( aSalShlData.mbWPrinter )
1683 sal_Unicode* pBuffer = new sal_Unicode[nBins*24];
1684 DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
1685 if ( nRet && (nRet != GDI_ERROR) )
1686 aPaperBinName = pBuffer + (nPaperBin*24);
1687 delete [] pBuffer;
1689 else
1691 char* pBuffer = new char[nBins*24];
1692 DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
1693 if ( nRet && (nRet != GDI_ERROR) )
1694 aPaperBinName = ImplSalGetUniString( (const char*)(pBuffer + (nPaperBin*24)) );
1695 delete [] pBuffer;
1699 return aPaperBinName;
1702 // -----------------------------------------------------------------------
1704 sal_uLong WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, sal_uInt16 nType )
1706 DWORD nRet;
1708 switch ( nType )
1710 case PRINTER_CAPABILITIES_SUPPORTDIALOG:
1711 return TRUE;
1712 case PRINTER_CAPABILITIES_COPIES:
1713 nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
1714 if ( nRet && (nRet != GDI_ERROR) )
1715 return nRet;
1716 return 0;
1717 case PRINTER_CAPABILITIES_COLLATECOPIES:
1718 if ( aSalShlData.mbW40 )
1720 nRet = ImplDeviceCaps( this, DC_COLLATE, NULL, pSetupData );
1721 if ( nRet && (nRet != GDI_ERROR) )
1723 nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
1724 if ( nRet && (nRet != GDI_ERROR) )
1725 return nRet;
1728 return 0;
1730 case PRINTER_CAPABILITIES_SETORIENTATION:
1731 nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
1732 if ( nRet && (nRet != GDI_ERROR) )
1733 return TRUE;
1734 return FALSE;
1736 case PRINTER_CAPABILITIES_SETPAPERBIN:
1737 nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1738 if ( nRet && (nRet != GDI_ERROR) )
1739 return TRUE;
1740 return FALSE;
1742 case PRINTER_CAPABILITIES_SETPAPERSIZE:
1743 case PRINTER_CAPABILITIES_SETPAPER:
1744 nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData );
1745 if ( nRet && (nRet != GDI_ERROR) )
1746 return TRUE;
1747 return FALSE;
1750 return 0;
1753 // -----------------------------------------------------------------------
1755 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
1756 long& rOutWidth, long& rOutHeight,
1757 long& rPageOffX, long& rPageOffY,
1758 long& rPageWidth, long& rPageHeight )
1760 HDC hDC = mhDC;
1762 rOutWidth = GetDeviceCaps( hDC, HORZRES );
1763 rOutHeight = GetDeviceCaps( hDC, VERTRES );
1765 rPageOffX = GetDeviceCaps( hDC, PHYSICALOFFSETX );
1766 rPageOffY = GetDeviceCaps( hDC, PHYSICALOFFSETY );
1767 rPageWidth = GetDeviceCaps( hDC, PHYSICALWIDTH );
1768 rPageHeight = GetDeviceCaps( hDC, PHYSICALHEIGHT );
1771 // =======================================================================
1773 SalPrinter* WinSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
1775 WinSalPrinter* pPrinter = new WinSalPrinter;
1776 pPrinter->mpInfoPrinter = static_cast<WinSalInfoPrinter*>(pInfoPrinter);
1777 return pPrinter;
1780 // -----------------------------------------------------------------------
1782 void WinSalInstance::DestroyPrinter( SalPrinter* pPrinter )
1784 delete pPrinter;
1787 // =======================================================================
1789 BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
1791 SalData* pSalData = GetSalData();
1792 WinSalPrinter* pPrinter;
1793 sal_Bool bWhile = TRUE;
1794 int i = 0;
1798 // Messages verarbeiten
1799 MSG aMsg;
1800 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
1802 if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
1804 TranslateMessage( &aMsg );
1805 ImplDispatchMessage( &aMsg );
1807 i++;
1808 if ( i > 15 )
1809 bWhile = FALSE;
1811 else
1812 bWhile = FALSE;
1814 pPrinter = pSalData->mpFirstPrinter;
1815 while ( pPrinter )
1817 if( pPrinter->mhDC == hPrnDC )
1818 break;
1820 pPrinter = pPrinter->mpNextPrinter;
1823 if ( !pPrinter || pPrinter->mbAbort )
1824 return FALSE;
1826 while ( bWhile );
1828 return TRUE;
1831 // -----------------------------------------------------------------------
1833 static LPDEVMODEA ImplSalSetCopies( LPDEVMODEA pDevMode, sal_uLong nCopies, sal_Bool bCollate )
1835 LPDEVMODEA pNewDevMode = pDevMode;
1836 if ( pDevMode && (nCopies > 1) )
1838 if ( nCopies > 32765 )
1839 nCopies = 32765;
1840 sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1841 pNewDevMode = (LPDEVMODEA)rtl_allocateMemory( nDevSize );
1842 memcpy( pNewDevMode, pDevMode, nDevSize );
1843 pDevMode = pNewDevMode;
1844 pDevMode->dmFields |= DM_COPIES;
1845 pDevMode->dmCopies = (short)(sal_uInt16)nCopies;
1846 if ( aSalShlData.mbW40 )
1848 pDevMode->dmFields |= DM_COLLATE;
1849 if ( bCollate )
1850 pDevMode->dmCollate = DMCOLLATE_TRUE;
1851 else
1852 pDevMode->dmCollate = DMCOLLATE_FALSE;
1856 return pNewDevMode;
1859 static LPDEVMODEW ImplSalSetCopies( LPDEVMODEW pDevMode, sal_uLong nCopies, sal_Bool bCollate )
1861 LPDEVMODEW pNewDevMode = pDevMode;
1862 if ( pDevMode && (nCopies > 1) )
1864 if ( nCopies > 32765 )
1865 nCopies = 32765;
1866 sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1867 pNewDevMode = (LPDEVMODEW)rtl_allocateMemory( nDevSize );
1868 memcpy( pNewDevMode, pDevMode, nDevSize );
1869 pDevMode = pNewDevMode;
1870 pDevMode->dmFields |= DM_COPIES;
1871 pDevMode->dmCopies = (short)(sal_uInt16)nCopies;
1872 if ( aSalShlData.mbW40 )
1874 pDevMode->dmFields |= DM_COLLATE;
1875 if ( bCollate )
1876 pDevMode->dmCollate = DMCOLLATE_TRUE;
1877 else
1878 pDevMode->dmCollate = DMCOLLATE_FALSE;
1882 return pNewDevMode;
1885 // -----------------------------------------------------------------------
1887 WinSalPrinter::WinSalPrinter() :
1888 mpGraphics( NULL ),
1889 mpInfoPrinter( NULL ),
1890 mpNextPrinter( NULL ),
1891 mhDC( 0 ),
1892 mnError( 0 ),
1893 mnCopies( 0 ),
1894 mbCollate( FALSE ),
1895 mbAbort( FALSE ),
1896 mbValid( true )
1898 SalData* pSalData = GetSalData();
1899 // insert printer in printerlist
1900 mpNextPrinter = pSalData->mpFirstPrinter;
1901 pSalData->mpFirstPrinter = this;
1904 // -----------------------------------------------------------------------
1906 WinSalPrinter::~WinSalPrinter()
1908 SalData* pSalData = GetSalData();
1910 // release DC if there is one still around because of AbortJob
1911 HDC hDC = mhDC;
1912 if ( hDC )
1914 if ( mpGraphics )
1916 ImplSalDeInitGraphics( mpGraphics );
1917 delete mpGraphics;
1920 DeleteDC( hDC );
1923 // remove printer from printerlist
1924 if ( this == pSalData->mpFirstPrinter )
1925 pSalData->mpFirstPrinter = mpNextPrinter;
1926 else
1928 WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
1930 while( pTempPrinter->mpNextPrinter != this )
1931 pTempPrinter = pTempPrinter->mpNextPrinter;
1933 pTempPrinter->mpNextPrinter = mpNextPrinter;
1935 mbValid = false;
1938 // -----------------------------------------------------------------------
1940 void WinSalPrinter::markInvalid()
1942 mbValid = false;
1945 // -----------------------------------------------------------------------
1947 // need wrappers for StarTocW/A to use structured exception handling
1948 // since SEH does not mix with standard exception handling's cleanup
1949 static int lcl_StartDocW( HDC hDC, DOCINFOW* pInfo, WinSalPrinter* pPrt )
1951 int nRet = 0;
1952 CATCH_DRIVER_EX_BEGIN;
1953 nRet = ::StartDocW( hDC, pInfo );
1954 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1955 return nRet;
1958 static int lcl_StartDocA( HDC hDC, DOCINFOA* pInfo, WinSalPrinter* pPrt )
1960 int nRet = 0;
1961 CATCH_DRIVER_EX_BEGIN;
1962 nRet = ::StartDocA( hDC, pInfo );
1963 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1964 return nRet;
1967 sal_Bool WinSalPrinter::StartJob( const XubString* pFileName,
1968 const XubString& rJobName,
1969 const XubString&,
1970 sal_uLong nCopies,
1971 bool bCollate,
1972 bool /*bDirect*/,
1973 ImplJobSetup* pSetupData )
1975 mnError = 0;
1976 mbAbort = FALSE;
1977 mnCopies = nCopies;
1978 mbCollate = bCollate;
1980 LPDEVMODEA pOrgDevModeA = NULL;
1981 LPDEVMODEA pDevModeA = NULL;
1982 LPDEVMODEW pOrgDevModeW = NULL;
1983 LPDEVMODEW pDevModeW = NULL;
1984 HDC hDC = 0;
1985 if( aSalShlData.mbWPrinter )
1987 if ( pSetupData && pSetupData->mpDriverData )
1989 pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
1990 pDevModeW = ImplSalSetCopies( pOrgDevModeW, nCopies, bCollate );
1992 else
1993 pDevModeW = NULL;
1995 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1996 sal_Unicode aDrvBuf[4096];
1997 sal_Unicode aDevBuf[4096];
1998 rtl_copyMemory( aDrvBuf, mpInfoPrinter->maDriverName.GetBuffer(), (mpInfoPrinter->maDriverName.Len()+1)*sizeof(sal_Unicode));
1999 rtl_copyMemory( aDevBuf, mpInfoPrinter->maDeviceName.GetBuffer(), (mpInfoPrinter->maDeviceName.Len()+1)*sizeof(sal_Unicode));
2000 hDC = CreateDCW( reinterpret_cast<LPCWSTR>(aDrvBuf),
2001 reinterpret_cast<LPCWSTR>(aDevBuf),
2002 NULL,
2003 pDevModeW );
2005 if ( pDevModeW != pOrgDevModeW )
2006 rtl_freeMemory( pDevModeW );
2008 else
2010 if ( pSetupData && pSetupData->mpDriverData )
2012 pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2013 pDevModeA = ImplSalSetCopies( pOrgDevModeA, nCopies, bCollate );
2015 else
2016 pDevModeA = NULL;
2018 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
2019 ByteString aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter->maDriverName, TRUE ) );
2020 ByteString aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter->maDeviceName, TRUE ) );
2021 int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
2022 n += 2048;
2023 char *lpszDriverName = new char[n];
2024 char *lpszDeviceName = new char[n];
2025 strncpy( lpszDriverName, aDriver.GetBuffer(), n );
2026 strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
2027 hDC = CreateDCA( lpszDriverName,
2028 lpszDeviceName,
2029 NULL,
2030 pDevModeA );
2032 delete [] lpszDriverName;
2033 delete [] lpszDeviceName;
2035 if ( pDevModeA != pOrgDevModeA )
2036 rtl_freeMemory( pDevModeA );
2039 if ( !hDC )
2041 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2042 return FALSE;
2045 // make sure mhDC is set before the printer driver may call our abortproc
2046 mhDC = hDC;
2047 if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
2049 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2050 return FALSE;
2053 mnError = 0;
2054 mbAbort = FALSE;
2056 // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages
2057 // ansonsten oefters schickt, versuchen wir vorher alle
2058 // zu verarbeiten und dann eine Dummy-Message reinstellen
2059 sal_Bool bWhile = TRUE;
2060 int i = 0;
2063 // Messages verarbeiten
2064 MSG aMsg;
2065 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
2067 if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
2069 TranslateMessage( &aMsg );
2070 ImplDispatchMessage( &aMsg );
2073 i++;
2074 if ( i > 15 )
2075 bWhile = FALSE;
2077 else
2078 bWhile = FALSE;
2080 while ( bWhile );
2081 ImplPostMessage( GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0 );
2083 // bring up a file choser if printing to file port but no file name given
2084 OUString aOutFileName;
2085 if( mpInfoPrinter->maPortName.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName && pFileName->Len()) )
2088 uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
2089 if( xFactory.is() )
2091 uno::Reference< XFilePicker > xFilePicker( xFactory->createInstance(
2092 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
2093 UNO_QUERY );
2094 DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" );
2096 uno::Reference< XInitialization > xInit( xFilePicker, UNO_QUERY );
2097 uno::Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY );
2098 if( xInit.is() && xFilePicker.is() && xFilterMgr.is() )
2100 Sequence< Any > aServiceType( 1 );
2101 aServiceType[0] <<= TemplateDescription::FILESAVE_SIMPLE;
2102 xInit->initialize( aServiceType );
2103 if( xFilePicker->execute() == ExecutableDialogResults::OK )
2105 Sequence< OUString > aPathSeq( xFilePicker->getFiles() );
2106 INetURLObject aObj( aPathSeq[0] );
2107 // we're using ansi calls (StartDocA) so convert the string
2108 aOutFileName = aObj.PathToFileName();
2110 else
2112 mnError = SAL_PRINTER_ERROR_ABORT;
2113 return FALSE;
2119 if( aSalShlData.mbWPrinter )
2121 DOCINFOW aInfo;
2122 memset( &aInfo, 0, sizeof( DOCINFOW ) );
2123 aInfo.cbSize = sizeof( aInfo );
2124 aInfo.lpszDocName = (LPWSTR)rJobName.GetBuffer();
2125 if ( pFileName || aOutFileName.getLength() )
2127 if ( (pFileName && pFileName->Len()) || aOutFileName.getLength() )
2129 aInfo.lpszOutput = (LPWSTR)( (pFileName && pFileName->Len()) ? pFileName->GetBuffer() : aOutFileName.getStr());
2131 else
2132 aInfo.lpszOutput = L"FILE:";
2134 else
2135 aInfo.lpszOutput = NULL;
2137 // start Job
2138 int nRet = lcl_StartDocW( hDC, &aInfo, this );
2140 if ( nRet <= 0 )
2142 long nError = GetLastError();
2143 if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2144 mnError = SAL_PRINTER_ERROR_ABORT;
2145 else
2146 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2147 return FALSE;
2150 else
2152 // Both strings must exist, if StartJob() is called
2153 ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) );
2154 ByteString aFileName;
2156 DOCINFOA aInfo;
2157 memset( &aInfo, 0, sizeof( DOCINFOA ) );
2158 aInfo.cbSize = sizeof( aInfo );
2159 aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer();
2160 if ( pFileName || aOutFileName.getLength() )
2162 if ( pFileName->Len() || aOutFileName.getLength() )
2164 aFileName = ImplSalGetWinAnsiString( pFileName ? *pFileName : static_cast<const XubString>(aOutFileName), TRUE );
2165 aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer();
2167 else
2168 aInfo.lpszOutput = "FILE:";
2170 else
2171 aInfo.lpszOutput = NULL;
2173 // start Job
2174 int nRet = lcl_StartDocA( hDC, &aInfo, this );
2175 if ( nRet <= 0 )
2177 long nError = GetLastError();
2178 if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2179 mnError = SAL_PRINTER_ERROR_ABORT;
2180 else
2181 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2182 return FALSE;
2186 return TRUE;
2189 // -----------------------------------------------------------------------
2191 sal_Bool WinSalPrinter::EndJob()
2193 DWORD err = 0;
2194 HDC hDC = mhDC;
2195 if ( isValid() && hDC )
2197 if ( mpGraphics )
2199 ImplSalDeInitGraphics( mpGraphics );
2200 delete mpGraphics;
2201 mpGraphics = NULL;
2204 // #i54419# Windows fax printer brings up a dialog in EndDoc
2205 // which text previously copied in soffice process can be
2206 // pasted to -> deadlock due to mutex not released.
2207 // it should be safe to release the yield mutex over the EndDoc
2208 // call, however the real solution is supposed to be the threading
2209 // framework yet to come.
2210 SalData* pSalData = GetSalData();
2211 sal_uLong nAcquire = pSalData->mpFirstInstance->ReleaseYieldMutex();
2212 CATCH_DRIVER_EX_BEGIN;
2213 if( ::EndDoc( hDC ) <= 0 )
2214 err = GetLastError();
2215 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
2217 pSalData->mpFirstInstance->AcquireYieldMutex( nAcquire );
2218 DeleteDC( hDC );
2219 mhDC = 0;
2222 return TRUE;
2225 // -----------------------------------------------------------------------
2227 sal_Bool WinSalPrinter::AbortJob()
2229 mbAbort = TRUE;
2231 // Abort asyncron ausloesen
2232 HDC hDC = mhDC;
2233 if ( hDC )
2235 SalData* pSalData = GetSalData();
2236 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd,
2237 SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 );
2240 return TRUE;
2243 // -----------------------------------------------------------------------
2245 void ImplSalPrinterAbortJobAsync( HDC hPrnDC )
2247 SalData* pSalData = GetSalData();
2248 WinSalPrinter* pPrinter = pSalData->mpFirstPrinter;
2250 // Feststellen, ob Printer noch existiert
2251 while ( pPrinter )
2253 if ( pPrinter->mhDC == hPrnDC )
2254 break;
2256 pPrinter = pPrinter->mpNextPrinter;
2259 // Wenn Printer noch existiert, dann den Job abbrechen
2260 if ( pPrinter )
2262 HDC hDC = pPrinter->mhDC;
2263 if ( hDC )
2265 if ( pPrinter->mpGraphics )
2267 ImplSalDeInitGraphics( pPrinter->mpGraphics );
2268 delete pPrinter->mpGraphics;
2269 pPrinter->mpGraphics = NULL;
2272 CATCH_DRIVER_EX_BEGIN;
2273 ::AbortDoc( hDC );
2274 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter );
2276 DeleteDC( hDC );
2277 pPrinter->mhDC = 0;
2282 // -----------------------------------------------------------------------
2284 SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, sal_Bool bNewJobData )
2286 if( ! isValid() || mhDC == 0 )
2287 return NULL;
2289 HDC hDC = mhDC;
2290 if ( pSetupData && pSetupData->mpDriverData && bNewJobData )
2292 if( aSalShlData.mbWPrinter )
2294 LPDEVMODEW pOrgDevModeW;
2295 LPDEVMODEW pDevModeW;
2296 pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
2297 pDevModeW = ImplSalSetCopies( pOrgDevModeW, mnCopies, mbCollate );
2298 ResetDCW( hDC, pDevModeW );
2299 if ( pDevModeW != pOrgDevModeW )
2300 rtl_freeMemory( pDevModeW );
2302 else
2304 LPDEVMODEA pOrgDevModeA;
2305 LPDEVMODEA pDevModeA;
2306 pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2307 pDevModeA = ImplSalSetCopies( pOrgDevModeA, mnCopies, mbCollate );
2308 ResetDCA( hDC, pDevModeA );
2309 if ( pDevModeA != pOrgDevModeA )
2310 rtl_freeMemory( pDevModeA );
2313 int nRet = 0;
2314 CATCH_DRIVER_EX_BEGIN;
2315 nRet = ::StartPage( hDC );
2316 CATCH_DRIVER_EX_END( "exception in StartPage", this );
2318 if ( nRet <= 0 )
2320 GetLastError();
2321 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2322 return NULL;
2325 // Hack to work around old PostScript printer drivers optimizing away empty pages
2326 // TODO: move into ImplCreateSalPrnGraphics()?
2327 HPEN hTempPen = SelectPen( hDC, GetStockPen( NULL_PEN ) );
2328 HBRUSH hTempBrush = SelectBrush( hDC, GetStockBrush( NULL_BRUSH ) );
2329 WIN_Rectangle( hDC, -8000, -8000, -7999, -7999 );
2330 SelectPen( hDC, hTempPen );
2331 SelectBrush( hDC, hTempBrush );
2333 mpGraphics = ImplCreateSalPrnGraphics( hDC );
2334 return mpGraphics;
2337 // -----------------------------------------------------------------------
2339 sal_Bool WinSalPrinter::EndPage()
2341 HDC hDC = mhDC;
2342 if ( hDC && mpGraphics )
2344 ImplSalDeInitGraphics( mpGraphics );
2345 delete mpGraphics;
2346 mpGraphics = NULL;
2349 if( ! isValid() )
2350 return FALSE;
2352 int nRet = 0;
2353 CATCH_DRIVER_EX_BEGIN;
2354 nRet = ::EndPage( hDC );
2355 CATCH_DRIVER_EX_END( "exception in EndPage", this );
2357 if ( nRet > 0 )
2358 return TRUE;
2359 else
2361 GetLastError();
2362 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2363 return FALSE;
2367 // -----------------------------------------------------------------------
2369 sal_uLong WinSalPrinter::GetErrorCode()
2371 return mnError;