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"
32 #include <tools/svwin.h>
39 #include <osl/module.h>
41 #include <wincomp.hxx>
42 #include <saldata.hxx>
46 #include <vcl/salptype.hxx>
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>
63 #define CATCH_DRIVER_EX_BEGIN \
66 if (__builtin_setjmp(jmpbuf) == 0) \
68 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
70 #define CATCH_DRIVER_EX_END(mes, p) \
73 #define CATCH_DRIVER_EX_END_2(mes) \
77 #define CATCH_DRIVER_EX_BEGIN \
80 #define CATCH_DRIVER_EX_END(mes, p) \
82 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
87 #define CATCH_DRIVER_EX_END_2(mes) \
89 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
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
;
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
)));
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
)));
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
;
188 // -----------------------------------------------------------------------
190 static void getPrinterQueueInfoOldStyle( ImplPrnQueueList
* pList
)
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
);
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
);
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
);
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
);
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
237 char* pBuf
= new char[nSize
];
238 UINT nRead
= GetProfileStringA( aImplDevices
, NULL
, "", pBuf
, nSize
);
239 while ( nRead
>= nSize
-2 )
243 pBuf
= new char[nSize
];
244 nRead
= GetProfileStringA( aImplDevices
, NULL
, "", pBuf
, nSize
);
247 // extract printer names from buffer and fill list
254 GetProfileStringA( aImplDevices
, pName
, "", aPortBuf
, sizeof( aPortBuf
) );
256 pPortName
= aPortBuf
;
259 xub_StrLen nNameLen
= sal::static_int_cast
<xub_StrLen
>(strlen( pName
));
260 XubString
aName( ImplSalGetUniString( pName
, nNameLen
) );
264 while ( *pTmp
!= ',' )
266 XubString
aDriver( ImplSalGetUniString( pPortName
, (sal_uInt16
)(pTmp
-pPortName
) ) );
274 while ( *pTmp
&& (*pTmp
!= ',') )
277 String
aPortName( ImplSalGetUniString( pPortName
, (sal_uInt16
)(pTmp
-pPortName
) ) );
280 // look up if printer was already found in first loop
281 sal_Bool bAdd
= TRUE
;
284 pGetInfo2
= pWinInfo2
;
285 for ( n
= 0; n
< nInfoPrn2
; n
++ )
287 if ( aName
.EqualsIgnoreCaseAscii( pGetInfo2
->pPrinterName
) )
295 // if it's a new printer, add it
298 SalPrinterQueueInfo
* pInfo
= new SalPrinterQueueInfo
;
299 pInfo
->maPrinterName
= aName
;
300 pInfo
->maDriver
= aDriver
;
301 pInfo
->maLocation
= aPortName
;
303 pInfo
->mnJobs
= QUEUE_JOBS_DONTKNOW
;
304 pInfo
->mpSysData
= new XubString( aPortName
);
308 while ( *pTmp
== ',' );
310 pName
+= nNameLen
+ 1;
314 rtl_freeMemory( pWinInfo2
);
317 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList
* pList
)
319 if( ! aSalShlData
.mbWPrinter
)
321 getPrinterQueueInfoOldStyle( pList
);
327 PRINTER_INFO_4W
* pWinInfo4
= NULL
;
328 EnumPrintersW( PRINTER_ENUM_LOCAL
| PRINTER_ENUM_CONNECTIONS
, NULL
, 4, NULL
, 0, &nBytes
, &nInfoPrn4
);
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
) );
340 pInfo
->mpSysData
= NULL
;
344 rtl_freeMemory( pWinInfo4
);
348 // -----------------------------------------------------------------------
350 static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo
* pInfo
)
354 PRINTER_INFO_2
* pWinInfo2
;
355 EnumPrintersA( PRINTER_ENUM_LOCAL
, NULL
, 2, NULL
, 0, &nBytes
, &nInfoRet
);
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
) )
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
);
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
);
391 rtl_freeMemory( pWinInfo2
);
395 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo
* pInfo
)
397 if( ! aSalShlData
.mbWPrinter
)
399 getPrinterQueueStateOldStyle( pInfo
);
404 LPWSTR pPrnName
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pInfo
->maPrinterName
.GetBuffer()));
405 if( OpenPrinterW( pPrnName
, &hPrinter
, NULL
) )
408 GetPrinterW( hPrinter
, 2, NULL
, 0, &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
) );
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
) );
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
);
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)
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
;
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
)
473 pGetDefaultPrinter( NULL
, &nChars
);
476 LPWSTR pStr
= (LPWSTR
)rtl_allocateMemory(nChars
*sizeof(WCHAR
));
478 if( pGetDefaultPrinter( pStr
, &nChars
) )
480 aDefPrt
= reinterpret_cast<sal_Unicode
* >(pStr
);
482 rtl_freeMemory( pStr
);
488 // get default printer from win.ini
490 GetProfileStringA( aImplWindows
, aImplDevice
, "", szBuffer
, sizeof( szBuffer
) );
493 // Printername suchen
494 char* pBuf
= szBuffer
;
496 while ( *pTmp
&& (*pTmp
!= ',') )
498 return ImplSalGetUniString( pBuf
, (xub_StrLen
)(pTmp
-pBuf
) );
504 // =======================================================================
506 static DWORD
ImplDeviceCaps( WinSalInfoPrinter
* pPrinter
, WORD nCaps
,
507 BYTE
* pOutput
, const ImplJobSetup
* pSetupData
)
509 if( aSalShlData
.mbWPrinter
)
512 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
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
);
524 if ( !pSetupData
|| !pSetupData
->mpDriverData
)
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
);
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
) )
580 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
583 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
584 if( hPrn
== HGDI_ERROR
)
587 if( aSalShlData
.mbWPrinter
)
589 nSysJobSize
= DocumentPropertiesW( 0, hPrn
,
595 nSysJobSize
= DocumentPropertiesA( 0, hPrn
,
596 (LPSTR
)aPrinterNameA
.GetBuffer(),
600 if( nSysJobSize
< 0 )
602 ClosePrinter( hPrn
);
605 BYTE
*pBuffer
= (BYTE
*)_alloca( nSysJobSize
);
607 if( aSalShlData
.mbWPrinter
)
609 nRet
= DocumentPropertiesW( 0, hPrn
,
611 (LPDEVMODEW
)pBuffer
, NULL
, DM_OUT_BUFFER
);
615 nRet
= DocumentPropertiesA( 0, hPrn
,
616 (LPSTR
)aPrinterNameA
.GetBuffer(),
617 (LPDEVMODEA
)pBuffer
, NULL
, DM_OUT_BUFFER
);
621 ClosePrinter( hPrn
);
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
)
641 (dmSpecVersion
== pDevModeA
->dmSpecVersion
) &&
642 (dmDriverVersion
== pDevModeA
->dmDriverVersion
) )
645 (dmSpecVersion
== pDevModeW
->dmSpecVersion
) &&
646 (dmDriverVersion
== pDevModeW
->dmDriverVersion
) )
651 rtl_freeMemory( pSetupData
->mpDriverData
);
652 pSetupData
->mpDriverData
= NULL
;
653 pSetupData
->mnDriverDataLen
= 0;
660 // -----------------------------------------------------------------------
662 static sal_Bool
ImplUpdateSalJobSetup( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
,
663 sal_Bool bIn
, WinSalFrame
* pVisibleDlgParent
)
665 ByteString aPrinterNameA
= ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
);
667 LPWSTR pPrinterNameW
= reinterpret_cast<LPWSTR
>(const_cast<sal_Unicode
*>(pPrinter
->maDeviceName
.GetBuffer()));
668 if( aSalShlData
.mbWPrinter
)
670 if ( !OpenPrinterW( pPrinterNameW
, &hPrn
, NULL
) )
675 if ( !OpenPrinterA( (LPSTR
)aPrinterNameA
.GetBuffer(), &hPrn
, NULL
) )
678 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
679 if( hPrn
== HGDI_ERROR
)
683 LONG nSysJobSize
= -1;
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
,
697 nSysJobSize
= DocumentPropertiesA( hWnd
, hPrn
,
698 (LPSTR
)ImplSalGetWinAnsiString( pPrinter
->maDeviceName
, TRUE
).GetBuffer(),
700 if ( nSysJobSize
< 0 )
702 ClosePrinter( hPrn
);
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
-
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
,
740 (LPDEVMODEW
)pOutDevMode
, (LPDEVMODEW
)pInBuffer
, nMode
);
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
);
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
)) );
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
);
791 if ( pSetupData
->mpDriverData
)
792 rtl_freeMemory( pSetupData
->mpDriverData
);
793 pSetupData
->mnDriverDataLen
= nDriverDataLen
;
794 pSetupData
->mpDriverData
= (BYTE
*)pOutBuffer
;
795 pSetupData
->mnSystem
= JOBSETUP_SYSTEM_WINDOWS
;
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 )\
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
)
816 DECLARE_DEVMODE( pSetupData
);
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
;
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
;
848 rtl_freeMemory( pBins
);
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;
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;
889 rtl_freeMemory( pPapers
);
891 rtl_freeMemory( pPaperSizes
);
893 switch( CHOOSE_DEVMODE(dmPaperSize
) )
895 case( DMPAPER_LETTER
):
896 pSetupData
->mePaperFormat
= PAPER_LETTER
;
898 case( DMPAPER_TABLOID
):
899 pSetupData
->mePaperFormat
= PAPER_TABLOID
;
901 case( DMPAPER_LEDGER
):
902 pSetupData
->mePaperFormat
= PAPER_LEDGER
;
904 case( DMPAPER_LEGAL
):
905 pSetupData
->mePaperFormat
= PAPER_LEGAL
;
907 case( DMPAPER_STATEMENT
):
908 pSetupData
->mePaperFormat
= PAPER_STATEMENT
;
910 case( DMPAPER_EXECUTIVE
):
911 pSetupData
->mePaperFormat
= PAPER_EXECUTIVE
;
914 pSetupData
->mePaperFormat
= PAPER_A3
;
917 pSetupData
->mePaperFormat
= PAPER_A4
;
920 pSetupData
->mePaperFormat
= PAPER_A5
;
922 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
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
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
936 pSetupData
->mePaperFormat
= PAPER_B4_JIS
;
939 pSetupData
->mePaperFormat
= PAPER_B5_JIS
;
941 case( DMPAPER_QUARTO
):
942 pSetupData
->mePaperFormat
= PAPER_QUARTO
;
944 case( DMPAPER_10X14
):
945 pSetupData
->mePaperFormat
= PAPER_10x14
;
947 case( DMPAPER_NOTE
):
948 pSetupData
->mePaperFormat
= PAPER_LETTER
;
950 case( DMPAPER_ENV_9
):
951 pSetupData
->mePaperFormat
= PAPER_ENV_9
;
953 case( DMPAPER_ENV_10
):
954 pSetupData
->mePaperFormat
= PAPER_ENV_10
;
956 case( DMPAPER_ENV_11
):
957 pSetupData
->mePaperFormat
= PAPER_ENV_11
;
959 case( DMPAPER_ENV_12
):
960 pSetupData
->mePaperFormat
= PAPER_ENV_12
;
962 case( DMPAPER_ENV_14
):
963 pSetupData
->mePaperFormat
= PAPER_ENV_14
;
965 case( DMPAPER_CSHEET
):
966 pSetupData
->mePaperFormat
= PAPER_C
;
968 case( DMPAPER_DSHEET
):
969 pSetupData
->mePaperFormat
= PAPER_D
;
971 case( DMPAPER_ESHEET
):
972 pSetupData
->mePaperFormat
= PAPER_E
;
974 case( DMPAPER_ENV_DL
):
975 pSetupData
->mePaperFormat
= PAPER_ENV_DL
;
977 case( DMPAPER_ENV_C5
):
978 pSetupData
->mePaperFormat
= PAPER_ENV_C5
;
980 case( DMPAPER_ENV_C3
):
981 pSetupData
->mePaperFormat
= PAPER_ENV_C3
;
983 case( DMPAPER_ENV_C4
):
984 pSetupData
->mePaperFormat
= PAPER_ENV_C4
;
986 case( DMPAPER_ENV_C6
):
987 pSetupData
->mePaperFormat
= PAPER_ENV_C6
;
989 case( DMPAPER_ENV_C65
):
990 pSetupData
->mePaperFormat
= PAPER_ENV_C65
;
992 case( DMPAPER_ENV_ITALY
):
993 pSetupData
->mePaperFormat
= PAPER_ENV_ITALY
;
995 case( DMPAPER_ENV_MONARCH
):
996 pSetupData
->mePaperFormat
= PAPER_ENV_MONARCH
;
998 case( DMPAPER_ENV_PERSONAL
):
999 pSetupData
->mePaperFormat
= PAPER_ENV_PERSONAL
;
1001 case( DMPAPER_FANFOLD_US
):
1002 pSetupData
->mePaperFormat
= PAPER_FANFOLD_US
;
1004 case( DMPAPER_FANFOLD_STD_GERMAN
):
1005 pSetupData
->mePaperFormat
= PAPER_FANFOLD_DE
;
1007 case( DMPAPER_FANFOLD_LGL_GERMAN
):
1008 pSetupData
->mePaperFormat
= PAPER_FANFOLD_LEGAL_DE
;
1010 case( DMPAPER_ISO_B4
):
1011 pSetupData
->mePaperFormat
= PAPER_B4_ISO
;
1013 case( DMPAPER_JAPANESE_POSTCARD
):
1014 pSetupData
->mePaperFormat
= PAPER_POSTCARD_JP
;
1016 case( DMPAPER_9X11
):
1017 pSetupData
->mePaperFormat
= PAPER_9x11
;
1019 case( DMPAPER_10X11
):
1020 pSetupData
->mePaperFormat
= PAPER_10x11
;
1022 case( DMPAPER_15X11
):
1023 pSetupData
->mePaperFormat
= PAPER_15x11
;
1025 case( DMPAPER_ENV_INVITE
):
1026 pSetupData
->mePaperFormat
= PAPER_ENV_INVITE
;
1028 case( DMPAPER_A_PLUS
):
1029 pSetupData
->mePaperFormat
= PAPER_A_PLUS
;
1031 case( DMPAPER_B_PLUS
):
1032 pSetupData
->mePaperFormat
= PAPER_B_PLUS
;
1034 case( DMPAPER_LETTER_PLUS
):
1035 pSetupData
->mePaperFormat
= PAPER_LETTER_PLUS
;
1037 case( DMPAPER_A4_PLUS
):
1038 pSetupData
->mePaperFormat
= PAPER_A4_PLUS
;
1041 pSetupData
->mePaperFormat
= PAPER_A2
;
1043 case( DMPAPER_DBL_JAPANESE_POSTCARD
):
1044 pSetupData
->mePaperFormat
= PAPER_DOUBLEPOSTCARD_JP
;
1047 pSetupData
->mePaperFormat
= PAPER_A6
;
1049 case( DMPAPER_B6_JIS
):
1050 pSetupData
->mePaperFormat
= PAPER_B6_JIS
;
1052 case( DMPAPER_12X11
):
1053 pSetupData
->mePaperFormat
= PAPER_12x11
;
1056 pSetupData
->mePaperFormat
= PAPER_USER
;
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
)
1084 DECLARE_DEVMODE( pSetupData
);
1087 if ( nFlags
& SAL_JOBSET_ORIENTATION
)
1089 CHOOSE_DEVMODE(dmFields
) |= DM_ORIENTATION
;
1090 if ( pSetupData
->meOrientation
== ORIENTATION_PORTRAIT
)
1091 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_PORTRAIT
;
1093 CHOOSE_DEVMODE(dmOrientation
) = DMORIENT_LANDSCAPE
;
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
);
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
)
1121 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A2
;
1124 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A3
;
1127 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4
;
1130 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A5
;
1132 case( PAPER_B4_ISO
):
1133 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ISO_B4
;
1135 case( PAPER_LETTER
):
1136 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER
;
1138 case( PAPER_LEGAL
):
1139 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEGAL
;
1141 case( PAPER_TABLOID
):
1142 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_TABLOID
;
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
;
1156 case( PAPER_ENV_C4
):
1157 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C4
;
1159 case( PAPER_ENV_C5
):
1160 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C5
;
1162 case( PAPER_ENV_C6
):
1163 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C6
;
1165 case( PAPER_ENV_C65
):
1166 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C65
;
1168 case( PAPER_ENV_DL
):
1169 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_DL
;
1172 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_CSHEET
;
1175 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DSHEET
;
1178 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ESHEET
;
1180 case( PAPER_EXECUTIVE
):
1181 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_EXECUTIVE
;
1183 case( PAPER_FANFOLD_LEGAL_DE
):
1184 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_LGL_GERMAN
;
1186 case( PAPER_ENV_MONARCH
):
1187 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_MONARCH
;
1189 case( PAPER_ENV_PERSONAL
):
1190 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_PERSONAL
;
1192 case( PAPER_ENV_9
):
1193 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_9
;
1195 case( PAPER_ENV_10
):
1196 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_10
;
1198 case( PAPER_ENV_11
):
1199 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_11
;
1201 case( PAPER_ENV_12
):
1202 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_12
;
1204 //See the comments on DMPAPER_B4 above
1205 case( PAPER_B4_JIS
):
1206 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B4
;
1208 case( PAPER_B5_JIS
):
1209 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B5
;
1211 case( PAPER_B6_JIS
):
1212 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B6_JIS
;
1214 case( PAPER_LEDGER
):
1215 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LEDGER
;
1217 case( PAPER_STATEMENT
):
1218 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_STATEMENT
;
1220 case( PAPER_10x14
):
1221 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X14
;
1223 case( PAPER_ENV_14
):
1224 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_14
;
1226 case( PAPER_ENV_C3
):
1227 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_C3
;
1229 case( PAPER_ENV_ITALY
):
1230 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_ITALY
;
1232 case( PAPER_FANFOLD_US
):
1233 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_US
;
1235 case( PAPER_FANFOLD_DE
):
1236 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_FANFOLD_STD_GERMAN
;
1238 case( PAPER_POSTCARD_JP
):
1239 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_JAPANESE_POSTCARD
;
1242 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_9X11
;
1244 case( PAPER_10x11
):
1245 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_10X11
;
1247 case( PAPER_15x11
):
1248 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_15X11
;
1250 case( PAPER_ENV_INVITE
):
1251 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_ENV_INVITE
;
1253 case( PAPER_A_PLUS
):
1254 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A_PLUS
;
1256 case( PAPER_B_PLUS
):
1257 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_B_PLUS
;
1259 case( PAPER_LETTER_PLUS
):
1260 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_LETTER_PLUS
;
1262 case( PAPER_A4_PLUS
):
1263 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A4_PLUS
;
1265 case( PAPER_DOUBLEPOSTCARD_JP
):
1266 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_DBL_JAPANESE_POSTCARD
;
1269 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_A6
;
1271 case( PAPER_12x11
):
1272 CHOOSE_DEVMODE(dmPaperSize
) = DMPAPER_12X11
;
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
];
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
];
1322 CHOOSE_DEVMODE(dmPaperSize
) = 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);
1334 rtl_freeMemory(pPapers
);
1336 rtl_freeMemory(pPaperSizes
);
1342 if( (nFlags
& SAL_JOBSET_DUPLEXMODE
) )
1344 switch( pSetupData
->meDuplexMode
)
1347 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1348 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_SIMPLEX
;
1350 case DUPLEX_SHORTEDGE
:
1351 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1352 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_HORIZONTAL
;
1354 case DUPLEX_LONGEDGE
:
1355 CHOOSE_DEVMODE(dmFields
) |= DM_DUPLEX
;
1356 CHOOSE_DEVMODE(dmDuplex
) = DMDUP_VERTICAL
;
1358 case DUPLEX_UNKNOWN
:
1364 // -----------------------------------------------------------------------
1366 static HDC
ImplCreateICW_WithCatch( LPWSTR pDriver
,
1368 LPDEVMODEW pDevMode
)
1371 CATCH_DRIVER_EX_BEGIN
;
1372 hDC
= CreateICW( pDriver
, pDevice
, 0, pDevMode
);
1373 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1377 static HDC
ImplCreateICA_WithCatch( char* pDriver
,
1379 LPDEVMODEA pDevMode
)
1382 CATCH_DRIVER_EX_BEGIN
;
1383 hDC
= CreateICA( pDriver
, pDevice
, 0, pDevMode
);
1384 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1389 static HDC
ImplCreateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1392 if( aSalShlData
.mbWPrinter
)
1394 LPDEVMODEW pDevMode
;
1395 if ( pSetupData
&& pSetupData
->mpDriverData
)
1396 pDevMode
= SAL_DEVMODE_W( pSetupData
);
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 )
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
),
1415 LPDEVMODEA pDevMode
;
1416 if ( pSetupData
&& pSetupData
->mpDriverData
)
1417 pDevMode
= SAL_DEVMODE_A( pSetupData
);
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.
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
,
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
);
1465 // -----------------------------------------------------------------------
1467 static sal_Bool
ImplUpdateSalPrnIC( WinSalInfoPrinter
* pPrinter
, ImplJobSetup
* pSetupData
)
1469 HDC hNewDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
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
;
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
)
1500 // check if the provided setup data match the actual printer
1501 ImplTestSalJobSetup( pPrinter
, pSetupData
, TRUE
);
1503 HDC hDC
= ImplCreateSalPrnIC( pPrinter
, pSetupData
);
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
;
1520 // -----------------------------------------------------------------------
1522 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter
* pPrinter
)
1527 // =======================================================================
1529 WinSalInfoPrinter::WinSalInfoPrinter() :
1534 m_bPapersInit
= FALSE
;
1537 // -----------------------------------------------------------------------
1539 WinSalInfoPrinter::~WinSalInfoPrinter()
1543 ImplSalDeInitGraphics( mpGraphics
);
1544 DeleteDC( mpGraphics
->mhDC
);
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
)
1559 POINT
* pPaperSizes
= NULL
;
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
);
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
)
1602 return 900; // guess
1605 // -----------------------------------------------------------------------
1607 SalGraphics
* WinSalInfoPrinter::GetGraphics()
1618 // -----------------------------------------------------------------------
1620 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics
* )
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
);
1638 // -----------------------------------------------------------------------
1640 sal_Bool
WinSalInfoPrinter::SetPrinterData( ImplJobSetup
* pSetupData
)
1642 if ( !ImplTestSalJobSetup( this, pSetupData
, 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
);
1661 // -----------------------------------------------------------------------
1663 sal_uLong
WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup
* pSetupData
)
1665 DWORD nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1666 if ( nRet
&& (nRet
!= GDI_ERROR
) )
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);
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)) );
1699 return aPaperBinName
;
1702 // -----------------------------------------------------------------------
1704 sal_uLong
WinSalInfoPrinter::GetCapabilities( const ImplJobSetup
* pSetupData
, sal_uInt16 nType
)
1710 case PRINTER_CAPABILITIES_SUPPORTDIALOG
:
1712 case PRINTER_CAPABILITIES_COPIES
:
1713 nRet
= ImplDeviceCaps( this, DC_COPIES
, NULL
, pSetupData
);
1714 if ( nRet
&& (nRet
!= GDI_ERROR
) )
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
) )
1730 case PRINTER_CAPABILITIES_SETORIENTATION
:
1731 nRet
= ImplDeviceCaps( this, DC_ORIENTATION
, NULL
, pSetupData
);
1732 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1736 case PRINTER_CAPABILITIES_SETPAPERBIN
:
1737 nRet
= ImplDeviceCaps( this, DC_BINS
, NULL
, pSetupData
);
1738 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1742 case PRINTER_CAPABILITIES_SETPAPERSIZE
:
1743 case PRINTER_CAPABILITIES_SETPAPER
:
1744 nRet
= ImplDeviceCaps( this, DC_PAPERS
, NULL
, pSetupData
);
1745 if ( nRet
&& (nRet
!= GDI_ERROR
) )
1753 // -----------------------------------------------------------------------
1755 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup
*,
1756 long& rOutWidth
, long& rOutHeight
,
1757 long& rPageOffX
, long& rPageOffY
,
1758 long& rPageWidth
, long& rPageHeight
)
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
);
1780 // -----------------------------------------------------------------------
1782 void WinSalInstance::DestroyPrinter( SalPrinter
* pPrinter
)
1787 // =======================================================================
1789 BOOL CALLBACK
SalPrintAbortProc( HDC hPrnDC
, int /* nError */ )
1791 SalData
* pSalData
= GetSalData();
1792 WinSalPrinter
* pPrinter
;
1793 sal_Bool bWhile
= TRUE
;
1798 // Messages verarbeiten
1800 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
1802 if ( !ImplInterceptChildWindowKeyDown( aMsg
) )
1804 TranslateMessage( &aMsg
);
1805 ImplDispatchMessage( &aMsg
);
1814 pPrinter
= pSalData
->mpFirstPrinter
;
1817 if( pPrinter
->mhDC
== hPrnDC
)
1820 pPrinter
= pPrinter
->mpNextPrinter
;
1823 if ( !pPrinter
|| pPrinter
->mbAbort
)
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 )
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
;
1850 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1852 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
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 )
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
;
1876 pDevMode
->dmCollate
= DMCOLLATE_TRUE
;
1878 pDevMode
->dmCollate
= DMCOLLATE_FALSE
;
1885 // -----------------------------------------------------------------------
1887 WinSalPrinter::WinSalPrinter() :
1889 mpInfoPrinter( NULL
),
1890 mpNextPrinter( NULL
),
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
1916 ImplSalDeInitGraphics( mpGraphics
);
1923 // remove printer from printerlist
1924 if ( this == pSalData
->mpFirstPrinter
)
1925 pSalData
->mpFirstPrinter
= mpNextPrinter
;
1928 WinSalPrinter
* pTempPrinter
= pSalData
->mpFirstPrinter
;
1930 while( pTempPrinter
->mpNextPrinter
!= this )
1931 pTempPrinter
= pTempPrinter
->mpNextPrinter
;
1933 pTempPrinter
->mpNextPrinter
= mpNextPrinter
;
1938 // -----------------------------------------------------------------------
1940 void WinSalPrinter::markInvalid()
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
)
1952 CATCH_DRIVER_EX_BEGIN
;
1953 nRet
= ::StartDocW( hDC
, pInfo
);
1954 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1958 static int lcl_StartDocA( HDC hDC
, DOCINFOA
* pInfo
, WinSalPrinter
* pPrt
)
1961 CATCH_DRIVER_EX_BEGIN
;
1962 nRet
= ::StartDocA( hDC
, pInfo
);
1963 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt
);
1967 sal_Bool
WinSalPrinter::StartJob( const XubString
* pFileName
,
1968 const XubString
& rJobName
,
1973 ImplJobSetup
* pSetupData
)
1978 mbCollate
= bCollate
;
1980 LPDEVMODEA pOrgDevModeA
= NULL
;
1981 LPDEVMODEA pDevModeA
= NULL
;
1982 LPDEVMODEW pOrgDevModeW
= NULL
;
1983 LPDEVMODEW pDevModeW
= NULL
;
1985 if( aSalShlData
.mbWPrinter
)
1987 if ( pSetupData
&& pSetupData
->mpDriverData
)
1989 pOrgDevModeW
= SAL_DEVMODE_W( pSetupData
);
1990 pDevModeW
= ImplSalSetCopies( pOrgDevModeW
, nCopies
, bCollate
);
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
),
2005 if ( pDevModeW
!= pOrgDevModeW
)
2006 rtl_freeMemory( pDevModeW
);
2010 if ( pSetupData
&& pSetupData
->mpDriverData
)
2012 pOrgDevModeA
= SAL_DEVMODE_A( pSetupData
);
2013 pDevModeA
= ImplSalSetCopies( pOrgDevModeA
, nCopies
, bCollate
);
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();
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
,
2032 delete [] lpszDriverName
;
2033 delete [] lpszDeviceName
;
2035 if ( pDevModeA
!= pOrgDevModeA
)
2036 rtl_freeMemory( pDevModeA
);
2041 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2045 // make sure mhDC is set before the printer driver may call our abortproc
2047 if ( SetAbortProc( hDC
, SalPrintAbortProc
) <= 0 )
2049 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
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
;
2063 // Messages verarbeiten
2065 if ( ImplPeekMessage( &aMsg
, 0, 0, 0, PM_REMOVE
) )
2067 if ( !ImplInterceptChildWindowKeyDown( aMsg
) )
2069 TranslateMessage( &aMsg
);
2070 ImplDispatchMessage( &aMsg
);
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() );
2091 uno::Reference
< XFilePicker
> xFilePicker( xFactory
->createInstance(
2092 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
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();
2112 mnError
= SAL_PRINTER_ERROR_ABORT
;
2119 if( aSalShlData
.mbWPrinter
)
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());
2132 aInfo
.lpszOutput
= L
"FILE:";
2135 aInfo
.lpszOutput
= NULL
;
2138 int nRet
= lcl_StartDocW( hDC
, &aInfo
, this );
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
;
2146 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2152 // Both strings must exist, if StartJob() is called
2153 ByteString
aJobName( ImplSalGetWinAnsiString( rJobName
, TRUE
) );
2154 ByteString aFileName
;
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();
2168 aInfo
.lpszOutput
= "FILE:";
2171 aInfo
.lpszOutput
= NULL
;
2174 int nRet
= lcl_StartDocA( hDC
, &aInfo
, this );
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
;
2181 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2189 // -----------------------------------------------------------------------
2191 sal_Bool
WinSalPrinter::EndJob()
2195 if ( isValid() && hDC
)
2199 ImplSalDeInitGraphics( mpGraphics
);
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
);
2225 // -----------------------------------------------------------------------
2227 sal_Bool
WinSalPrinter::AbortJob()
2231 // Abort asyncron ausloesen
2235 SalData
* pSalData
= GetSalData();
2236 ImplPostMessage( pSalData
->mpFirstInstance
->mhComWnd
,
2237 SAL_MSG_PRINTABORTJOB
, (WPARAM
)hDC
, 0 );
2243 // -----------------------------------------------------------------------
2245 void ImplSalPrinterAbortJobAsync( HDC hPrnDC
)
2247 SalData
* pSalData
= GetSalData();
2248 WinSalPrinter
* pPrinter
= pSalData
->mpFirstPrinter
;
2250 // Feststellen, ob Printer noch existiert
2253 if ( pPrinter
->mhDC
== hPrnDC
)
2256 pPrinter
= pPrinter
->mpNextPrinter
;
2259 // Wenn Printer noch existiert, dann den Job abbrechen
2262 HDC hDC
= pPrinter
->mhDC
;
2265 if ( pPrinter
->mpGraphics
)
2267 ImplSalDeInitGraphics( pPrinter
->mpGraphics
);
2268 delete pPrinter
->mpGraphics
;
2269 pPrinter
->mpGraphics
= NULL
;
2272 CATCH_DRIVER_EX_BEGIN
;
2274 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter
);
2282 // -----------------------------------------------------------------------
2284 SalGraphics
* WinSalPrinter::StartPage( ImplJobSetup
* pSetupData
, sal_Bool bNewJobData
)
2286 if( ! isValid() || mhDC
== 0 )
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
);
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
);
2314 CATCH_DRIVER_EX_BEGIN
;
2315 nRet
= ::StartPage( hDC
);
2316 CATCH_DRIVER_EX_END( "exception in StartPage", this );
2321 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
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
);
2337 // -----------------------------------------------------------------------
2339 sal_Bool
WinSalPrinter::EndPage()
2342 if ( hDC
&& mpGraphics
)
2344 ImplSalDeInitGraphics( mpGraphics
);
2353 CATCH_DRIVER_EX_BEGIN
;
2354 nRet
= ::EndPage( hDC
);
2355 CATCH_DRIVER_EX_END( "exception in EndPage", this );
2362 mnError
= SAL_PRINTER_ERROR_GENERALERROR
;
2367 // -----------------------------------------------------------------------
2369 sal_uLong
WinSalPrinter::GetErrorCode()