Update ooo320-m1
[ooovba.git] / vcl / win / source / gdi / salprn.cxx
blob0aaa7d709c480eafb3a5807b5f4a9022db056301
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salprn.cxx,v $
10 * $Revision: 1.36 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <string.h>
35 #include <tools/svwin.h>
37 #ifdef __MINGW32__
38 #include <excpt.h>
39 #endif
41 #ifndef _OSL_MODULE_H
42 #include <osl/module.h>
43 #endif
44 #include <wincomp.hxx>
45 #include <saldata.hxx>
46 #include <salinst.h>
47 #include <salgdi.h>
48 #include <salframe.h>
49 #include <vcl/salptype.hxx>
50 #include <salprn.h>
51 #include <vcl/print.h>
52 #include <vcl/jobset.h>
54 #include <tools/urlobj.hxx>
55 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
56 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
57 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
58 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
59 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
60 #include <com/sun/star/lang/XInitialization.hpp>
61 #include <comphelper/processfactory.hxx>
63 #include <malloc.h>
65 #ifdef __MINGW32__
66 #define CATCH_DRIVER_EX_BEGIN \
67 jmp_buf jmpbuf; \
68 __SEHandler han; \
69 if (__builtin_setjmp(jmpbuf) == 0) \
70 { \
71 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
73 #define CATCH_DRIVER_EX_END(mes, p) \
74 } \
75 han.Reset()
76 #define CATCH_DRIVER_EX_END_2(mes) \
77 } \
78 han.Reset()
79 #else
80 #define CATCH_DRIVER_EX_BEGIN \
81 __try \
83 #define CATCH_DRIVER_EX_END(mes, p) \
84 } \
85 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
86 { \
87 DBG_ERROR( mes ); \
88 p->markInvalid(); \
90 #define CATCH_DRIVER_EX_END_2(mes) \
91 } \
92 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
93 { \
94 DBG_ERROR( mes ); \
96 #endif
99 using namespace com::sun::star::uno;
100 using namespace com::sun::star::lang;
101 using namespace com::sun::star::ui::dialogs;
102 using namespace rtl;
104 // =======================================================================
106 static char aImplWindows[] = "windows";
107 static char aImplDevices[] = "devices";
108 static char aImplDevice[] = "device";
110 static LPDEVMODEA SAL_DEVMODE_A( const ImplJobSetup* pSetupData )
112 LPDEVMODEA pRet = NULL;
113 SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
114 if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_A &&
115 pSetupData->mnDriverDataLen >= sizeof(DEVMODEA)+sizeof(SalDriverData)-1
117 pRet = ((LPDEVMODEA)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
118 return pRet;
121 static LPDEVMODEW SAL_DEVMODE_W( const ImplJobSetup* pSetupData )
123 LPDEVMODEW pRet = NULL;
124 SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
125 if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_W &&
126 pSetupData->mnDriverDataLen >= sizeof(DEVMODEW)+sizeof(SalDriverData)-1
128 pRet = ((LPDEVMODEW)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
129 return pRet;
132 // =======================================================================
134 static ULONG ImplWinQueueStatusToSal( DWORD nWinStatus )
136 ULONG nStatus = 0;
137 if ( nWinStatus & PRINTER_STATUS_PAUSED )
138 nStatus |= QUEUE_STATUS_PAUSED;
139 if ( nWinStatus & PRINTER_STATUS_ERROR )
140 nStatus |= QUEUE_STATUS_ERROR;
141 if ( nWinStatus & PRINTER_STATUS_PENDING_DELETION )
142 nStatus |= QUEUE_STATUS_PENDING_DELETION;
143 if ( nWinStatus & PRINTER_STATUS_PAPER_JAM )
144 nStatus |= QUEUE_STATUS_PAPER_JAM;
145 if ( nWinStatus & PRINTER_STATUS_PAPER_OUT )
146 nStatus |= QUEUE_STATUS_PAPER_OUT;
147 if ( nWinStatus & PRINTER_STATUS_MANUAL_FEED )
148 nStatus |= QUEUE_STATUS_MANUAL_FEED;
149 if ( nWinStatus & PRINTER_STATUS_PAPER_PROBLEM )
150 nStatus |= QUEUE_STATUS_PAPER_PROBLEM;
151 if ( nWinStatus & PRINTER_STATUS_OFFLINE )
152 nStatus |= QUEUE_STATUS_OFFLINE;
153 if ( nWinStatus & PRINTER_STATUS_IO_ACTIVE )
154 nStatus |= QUEUE_STATUS_IO_ACTIVE;
155 if ( nWinStatus & PRINTER_STATUS_BUSY )
156 nStatus |= QUEUE_STATUS_BUSY;
157 if ( nWinStatus & PRINTER_STATUS_PRINTING )
158 nStatus |= QUEUE_STATUS_PRINTING;
159 if ( nWinStatus & PRINTER_STATUS_OUTPUT_BIN_FULL )
160 nStatus |= QUEUE_STATUS_OUTPUT_BIN_FULL;
161 if ( nWinStatus & PRINTER_STATUS_WAITING )
162 nStatus |= QUEUE_STATUS_WAITING;
163 if ( nWinStatus & PRINTER_STATUS_PROCESSING )
164 nStatus |= QUEUE_STATUS_PROCESSING;
165 if ( nWinStatus & PRINTER_STATUS_INITIALIZING )
166 nStatus |= QUEUE_STATUS_INITIALIZING;
167 if ( nWinStatus & PRINTER_STATUS_WARMING_UP )
168 nStatus |= QUEUE_STATUS_WARMING_UP;
169 if ( nWinStatus & PRINTER_STATUS_TONER_LOW )
170 nStatus |= QUEUE_STATUS_TONER_LOW;
171 if ( nWinStatus & PRINTER_STATUS_NO_TONER )
172 nStatus |= QUEUE_STATUS_NO_TONER;
173 if ( nWinStatus & PRINTER_STATUS_PAGE_PUNT )
174 nStatus |= QUEUE_STATUS_PAGE_PUNT;
175 if ( nWinStatus & PRINTER_STATUS_USER_INTERVENTION )
176 nStatus |= QUEUE_STATUS_USER_INTERVENTION;
177 if ( nWinStatus & PRINTER_STATUS_OUT_OF_MEMORY )
178 nStatus |= QUEUE_STATUS_OUT_OF_MEMORY;
179 if ( nWinStatus & PRINTER_STATUS_DOOR_OPEN )
180 nStatus |= QUEUE_STATUS_DOOR_OPEN;
181 if ( nWinStatus & PRINTER_STATUS_SERVER_UNKNOWN )
182 nStatus |= QUEUE_STATUS_SERVER_UNKNOWN;
183 if ( nWinStatus & PRINTER_STATUS_POWER_SAVE )
184 nStatus |= QUEUE_STATUS_POWER_SAVE;
185 if ( !nStatus && !(nWinStatus & PRINTER_STATUS_NOT_AVAILABLE) )
186 nStatus |= QUEUE_STATUS_READY;
187 return nStatus;
190 // -----------------------------------------------------------------------
192 static void getPrinterQueueInfoOldStyle( ImplPrnQueueList* pList )
194 DWORD i;
195 DWORD n;
196 DWORD nBytes = 0;
197 DWORD nInfoPrn2;
198 BOOL bFound = FALSE;
199 PRINTER_INFO_2* pWinInfo2 = NULL;
200 PRINTER_INFO_2* pGetInfo2;
201 EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoPrn2 );
202 if ( nBytes )
204 pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
205 if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoPrn2 ) )
207 pGetInfo2 = pWinInfo2;
208 for ( i = 0; i < nInfoPrn2; i++ )
210 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
211 pInfo->maPrinterName = ImplSalGetUniString( pGetInfo2->pPrinterName );
212 pInfo->maDriver = ImplSalGetUniString( pGetInfo2->pDriverName );
213 XubString aPortName;
214 if ( pGetInfo2->pPortName )
215 aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
216 // pLocation can be 0 (the Windows docu doesn't describe this)
217 if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
218 pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
219 else
220 pInfo->maLocation = aPortName;
221 // pComment can be 0 (the Windows docu doesn't describe this)
222 if ( pGetInfo2->pComment )
223 pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
224 pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
225 pInfo->mnJobs = pGetInfo2->cJobs;
226 pInfo->mpSysData = new XubString( aPortName );
227 pList->Add( pInfo );
228 pGetInfo2++;
231 bFound = TRUE;
235 // read printers from win.ini
236 // TODO: MSDN: GetProfileString() should not be called from server
237 // code because it is just there for WIN16 compatibility
238 UINT nSize = 4096;
239 char* pBuf = new char[nSize];
240 UINT nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
241 while ( nRead >= nSize-2 )
243 nSize += 2048;
244 delete []pBuf;
245 pBuf = new char[nSize];
246 nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
249 // extract printer names from buffer and fill list
250 char* pName = pBuf;
251 while ( *pName )
253 char* pPortName;
254 char* pTmp;
255 char aPortBuf[256];
256 GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) );
258 pPortName = aPortBuf;
260 // create name
261 xub_StrLen nNameLen = sal::static_int_cast<xub_StrLen>(strlen( pName ));
262 XubString aName( ImplSalGetUniString( pName, nNameLen ) );
264 // get driver name
265 pTmp = pPortName;
266 while ( *pTmp != ',' )
267 pTmp++;
268 XubString aDriver( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) );
269 pPortName = pTmp;
271 // get port names
274 pPortName++;
275 pTmp = pPortName;
276 while ( *pTmp && (*pTmp != ',') )
277 pTmp++;
279 String aPortName( ImplSalGetUniString( pPortName, (USHORT)(pTmp-pPortName) ) );
281 // create new entry
282 // look up if printer was already found in first loop
283 BOOL bAdd = TRUE;
284 if ( pWinInfo2 )
286 pGetInfo2 = pWinInfo2;
287 for ( n = 0; n < nInfoPrn2; n++ )
289 if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) )
291 bAdd = FALSE;
292 break;
294 pGetInfo2++;
297 // if it's a new printer, add it
298 if ( bAdd )
300 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
301 pInfo->maPrinterName = aName;
302 pInfo->maDriver = aDriver;
303 pInfo->maLocation = aPortName;
304 pInfo->mnStatus = 0;
305 pInfo->mnJobs = QUEUE_JOBS_DONTKNOW;
306 pInfo->mpSysData = new XubString( aPortName );
307 pList->Add( pInfo );
310 while ( *pTmp == ',' );
312 pName += nNameLen + 1;
315 delete []pBuf;
316 rtl_freeMemory( pWinInfo2 );
319 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
321 if( ! aSalShlData.mbWPrinter )
323 getPrinterQueueInfoOldStyle( pList );
324 return;
326 DWORD i;
327 DWORD nBytes = 0;
328 DWORD nInfoPrn4 = 0;
329 PRINTER_INFO_4W* pWinInfo4 = NULL;
330 EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 );
331 if ( nBytes )
333 pWinInfo4 = (PRINTER_INFO_4W*) rtl_allocateMemory( nBytes );
334 if ( EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)pWinInfo4, nBytes, &nBytes, &nInfoPrn4 ) )
336 for ( i = 0; i < nInfoPrn4; i++ )
338 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
339 pInfo->maPrinterName = UniString( reinterpret_cast< const sal_Unicode* >(pWinInfo4[i].pPrinterName) );
340 pInfo->mnStatus = 0;
341 pInfo->mnJobs = 0;
342 pInfo->mpSysData = NULL;
343 pList->Add( pInfo );
346 rtl_freeMemory( pWinInfo4 );
350 // -----------------------------------------------------------------------
352 static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo* pInfo )
354 DWORD nBytes = 0;
355 DWORD nInfoRet;
356 PRINTER_INFO_2* pWinInfo2;
357 EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoRet );
358 if ( nBytes )
360 pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
361 if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoRet ) )
363 PRINTER_INFO_2* pGetInfo2 = pWinInfo2;
364 for ( DWORD i = 0; i < nInfoRet; i++ )
366 if ( pInfo->maPrinterName.EqualsAscii( pGetInfo2->pPrinterName ) &&
367 ( pInfo->maDriver.Len() == 0 ||
368 pInfo->maDriver.EqualsAscii( pGetInfo2->pDriverName ) )
371 XubString aPortName;
372 if ( pGetInfo2->pPortName )
373 aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
374 // pLocation can be 0 (the Windows docu doesn't describe this)
375 if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
376 pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
377 else
378 pInfo->maLocation = aPortName;
379 // pComment can be 0 (the Windows docu doesn't describe this)
380 if ( pGetInfo2->pComment )
381 pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
382 pInfo->mnStatus = ImplWinQueueStatusToSal( pGetInfo2->Status );
383 pInfo->mnJobs = pGetInfo2->cJobs;
384 if( ! pInfo->mpSysData )
385 pInfo->mpSysData = new XubString( aPortName );
386 break;
389 pGetInfo2++;
393 rtl_freeMemory( pWinInfo2 );
397 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
399 if( ! aSalShlData.mbWPrinter )
401 getPrinterQueueStateOldStyle( pInfo );
402 return;
405 HANDLE hPrinter = 0;
406 LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.GetBuffer()));
407 if( OpenPrinterW( pPrnName, &hPrinter, NULL ) )
409 DWORD nBytes = 0;
410 GetPrinterW( hPrinter, 2, NULL, 0, &nBytes );
411 if( nBytes )
413 PRINTER_INFO_2W* pWinInfo2 = (PRINTER_INFO_2W*)rtl_allocateMemory(nBytes);
414 if( GetPrinterW( hPrinter, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes ) )
416 if( pWinInfo2->pDriverName )
417 pInfo->maDriver = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pDriverName) );
418 XubString aPortName;
419 if ( pWinInfo2->pPortName )
420 aPortName = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pPortName) );
421 // pLocation can be 0 (the Windows docu doesn't describe this)
422 if ( pWinInfo2->pLocation && *pWinInfo2->pLocation )
423 pInfo->maLocation = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pLocation) );
424 else
425 pInfo->maLocation = aPortName;
426 // pComment can be 0 (the Windows docu doesn't describe this)
427 if ( pWinInfo2->pComment )
428 pInfo->maComment = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pComment) );
429 pInfo->mnStatus = ImplWinQueueStatusToSal( pWinInfo2->Status );
430 pInfo->mnJobs = pWinInfo2->cJobs;
431 if( ! pInfo->mpSysData )
432 pInfo->mpSysData = new XubString( aPortName );
434 rtl_freeMemory(pWinInfo2);
436 ClosePrinter( hPrinter );
440 // -----------------------------------------------------------------------
442 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
444 delete (String*)(pInfo->mpSysData);
445 delete pInfo;
448 // -----------------------------------------------------------------------
449 XubString WinSalInstance::GetDefaultPrinter()
451 static bool bGetDefPrtAPI = true;
452 static BOOL(WINAPI*pGetDefaultPrinter)(LPWSTR,LPDWORD) = NULL;
453 // try to use GetDefaultPrinter API (not available prior to W2000)
454 if( bGetDefPrtAPI )
456 bGetDefPrtAPI = false;
457 // check for W2k and XP
458 if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
460 OUString aLibraryName( RTL_CONSTASCII_USTRINGPARAM( "winspool.drv" ) );
461 oslModule pLib = osl_loadModule( aLibraryName.pData, SAL_LOADMODULE_DEFAULT );
462 oslGenericFunction pFunc = NULL;
463 if( pLib )
465 OUString queryFuncName( RTL_CONSTASCII_USTRINGPARAM( "GetDefaultPrinterW" ) );
466 pFunc = osl_getFunctionSymbol( pLib, queryFuncName.pData );
469 pGetDefaultPrinter = (BOOL(WINAPI*)(LPWSTR,LPDWORD)) pFunc;
472 if( pGetDefaultPrinter )
474 DWORD nChars = 0;
475 pGetDefaultPrinter( NULL, &nChars );
476 if( nChars )
478 LPWSTR pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR));
479 XubString aDefPrt;
480 if( pGetDefaultPrinter( pStr, &nChars ) )
482 aDefPrt = reinterpret_cast<sal_Unicode* >(pStr);
484 rtl_freeMemory( pStr );
485 if( aDefPrt.Len() )
486 return aDefPrt;
490 // get default printer from win.ini
491 char szBuffer[256];
492 GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) );
493 if ( szBuffer[0] )
495 // Printername suchen
496 char* pBuf = szBuffer;
497 char* pTmp = pBuf;
498 while ( *pTmp && (*pTmp != ',') )
499 pTmp++;
500 return ImplSalGetUniString( pBuf, (xub_StrLen)(pTmp-pBuf) );
502 else
503 return XubString();
506 // =======================================================================
508 static DWORD ImplDeviceCaps( WinSalInfoPrinter* pPrinter, WORD nCaps,
509 BYTE* pOutput, const ImplJobSetup* pSetupData )
511 if( aSalShlData.mbWPrinter )
513 DEVMODEW* pDevMode;
514 if ( !pSetupData || !pSetupData->mpDriverData )
515 pDevMode = NULL;
516 else
517 pDevMode = SAL_DEVMODE_W( pSetupData );
519 return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR>(pPrinter->maDeviceName.GetBuffer()),
520 reinterpret_cast<LPCWSTR>(pPrinter->maPortName.GetBuffer()),
521 nCaps, (LPWSTR)pOutput, pDevMode );
523 else
525 DEVMODEA* pDevMode;
526 if ( !pSetupData || !pSetupData->mpDriverData )
527 pDevMode = NULL;
528 else
529 pDevMode = SAL_DEVMODE_A( pSetupData );
531 return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
532 ImplSalGetWinAnsiString( pPrinter->maPortName, TRUE ).GetBuffer(),
533 nCaps, (LPSTR)pOutput, pDevMode );
537 // -----------------------------------------------------------------------
539 static BOOL ImplTestSalJobSetup( WinSalInfoPrinter* pPrinter,
540 ImplJobSetup* pSetupData, BOOL bDelete )
542 if ( pSetupData && pSetupData->mpDriverData )
544 // signature and size must fit to avoid using
545 // JobSetups from a wrong system
547 // initialize versions from jobsetup
548 // those will be overwritten with driver's version
549 DEVMODEA* pDevModeA = NULL;
550 DEVMODEW* pDevModeW = NULL;
551 LONG dmSpecVersion = -1;
552 LONG dmDriverVersion = -1;
553 SalDriverData* pSalDriverData = (SalDriverData*)pSetupData->mpDriverData;
554 BYTE* pDriverData = ((BYTE*)pSalDriverData) + pSalDriverData->mnDriverOffset;
555 if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_W )
557 if( aSalShlData.mbWPrinter )
558 pDevModeW = (DEVMODEW*)pDriverData;
560 else if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_A )
562 if( ! aSalShlData.mbWPrinter )
563 pDevModeA = (DEVMODEA*)pDriverData;
566 long nSysJobSize = -1;
567 if( pPrinter && ( pDevModeA || pDevModeW ) )
569 // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
570 // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
571 // can avoid potential driver crashes as their jobsetups are often not compatible
572 // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
573 ByteString aPrinterNameA= ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
574 HANDLE hPrn;
575 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
576 if ( ! aSalShlData.mbWPrinter )
578 if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
579 return FALSE;
581 else
582 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
583 return FALSE;
585 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
586 if( hPrn == HGDI_ERROR )
587 return FALSE;
589 if( aSalShlData.mbWPrinter )
591 nSysJobSize = DocumentPropertiesW( 0, hPrn,
592 pPrinterNameW,
593 NULL, NULL, 0 );
595 else
597 nSysJobSize = DocumentPropertiesA( 0, hPrn,
598 (LPSTR)aPrinterNameA.GetBuffer(),
599 NULL, NULL, 0 );
602 if( nSysJobSize < 0 )
604 ClosePrinter( hPrn );
605 return FALSE;
607 BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize );
608 LONG nRet = -1;
609 if( aSalShlData.mbWPrinter )
611 nRet = DocumentPropertiesW( 0, hPrn,
612 pPrinterNameW,
613 (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER );
615 else
617 nRet = DocumentPropertiesA( 0, hPrn,
618 (LPSTR)aPrinterNameA.GetBuffer(),
619 (LPDEVMODEA)pBuffer, NULL, DM_OUT_BUFFER );
621 if( nRet < 0 )
623 ClosePrinter( hPrn );
624 return FALSE;
627 // the spec version differs between the windows platforms, ie 98,NT,2000/XP
628 // this allows us to throw away printer settings from other platforms that might crash a buggy driver
629 // we check the driver version as well
630 dmSpecVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmSpecVersion : ((DEVMODEA*)pBuffer)->dmSpecVersion;
631 dmDriverVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmDriverVersion : ((DEVMODEA*)pBuffer)->dmDriverVersion;
633 ClosePrinter( hPrn );
635 SalDriverData* pSetupDriverData = (SalDriverData*)(pSetupData->mpDriverData);
636 if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) &&
637 (pPrinter->maDriverName == pSetupData->maDriver) &&
638 (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) &&
639 (long)(pSetupData->mnDriverDataLen - pSetupDriverData->mnDriverOffset) == nSysJobSize &&
640 pSetupDriverData->mnSysSignature == SAL_DRIVERDATA_SYSSIGN )
642 if( pDevModeA &&
643 (dmSpecVersion == pDevModeA->dmSpecVersion) &&
644 (dmDriverVersion == pDevModeA->dmDriverVersion) )
645 return TRUE;
646 if( pDevModeW &&
647 (dmSpecVersion == pDevModeW->dmSpecVersion) &&
648 (dmDriverVersion == pDevModeW->dmDriverVersion) )
649 return TRUE;
651 if ( bDelete )
653 rtl_freeMemory( pSetupData->mpDriverData );
654 pSetupData->mpDriverData = NULL;
655 pSetupData->mnDriverDataLen = 0;
659 return FALSE;
662 // -----------------------------------------------------------------------
664 static BOOL ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData,
665 BOOL bIn, WinSalFrame* pVisibleDlgParent )
667 ByteString aPrinterNameA = ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
668 HANDLE hPrn;
669 LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
670 if( aSalShlData.mbWPrinter )
672 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
673 return FALSE;
675 else
677 if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
678 return FALSE;
680 // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
681 if( hPrn == HGDI_ERROR )
682 return FALSE;
684 LONG nRet;
685 LONG nSysJobSize = -1;
686 HWND hWnd = 0;
687 DWORD nMode = DM_OUT_BUFFER;
688 ULONG nDriverDataLen = 0;
689 SalDriverData* pOutBuffer = NULL;
690 BYTE* pInBuffer = NULL;
692 if( aSalShlData.mbWPrinter )
694 nSysJobSize = DocumentPropertiesW( hWnd, hPrn,
695 pPrinterNameW,
696 NULL, NULL, 0 );
698 else
699 nSysJobSize = DocumentPropertiesA( hWnd, hPrn,
700 (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
701 NULL, NULL, 0 );
702 if ( nSysJobSize < 0 )
704 ClosePrinter( hPrn );
705 return FALSE;
708 // Outputbuffer anlegen
709 nDriverDataLen = sizeof(SalDriverData) + nSysJobSize-1;
710 pOutBuffer = (SalDriverData*)rtl_allocateZeroMemory( nDriverDataLen );
711 pOutBuffer->mnSysSignature = SAL_DRIVERDATA_SYSSIGN;
712 pOutBuffer->mnVersion = aSalShlData.mbWPrinter ? SAL_DRIVERDATA_VERSION_W : SAL_DRIVERDATA_VERSION_A;
713 // calculate driver data offset including structure padding
714 pOutBuffer->mnDriverOffset = sal::static_int_cast<USHORT>(
715 (char*)pOutBuffer->maDriverData -
716 (char*)pOutBuffer );
718 // Testen, ob wir einen geeigneten Inputbuffer haben
719 if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) )
721 pInBuffer = (BYTE*)pSetupData->mpDriverData + ((SalDriverData*)pSetupData->mpDriverData)->mnDriverOffset;
722 nMode |= DM_IN_BUFFER;
725 // Testen, ob Dialog angezeigt werden soll
726 if ( pVisibleDlgParent )
728 hWnd = pVisibleDlgParent->mhWnd;
729 nMode |= DM_IN_PROMPT;
732 // Release mutex, in the other case we don't get paints and so on
733 ULONG nMutexCount=0;
734 if ( pVisibleDlgParent )
735 nMutexCount = ImplSalReleaseYieldMutex();
737 BYTE* pOutDevMode = (((BYTE*)pOutBuffer) + pOutBuffer->mnDriverOffset);
738 if( aSalShlData.mbWPrinter )
740 nRet = DocumentPropertiesW( hWnd, hPrn,
741 pPrinterNameW,
742 (LPDEVMODEW)pOutDevMode, (LPDEVMODEW)pInBuffer, nMode );
744 else
746 nRet = DocumentPropertiesA( hWnd, hPrn,
747 (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
748 (LPDEVMODEA)pOutDevMode, (LPDEVMODEA)pInBuffer, nMode );
750 if ( pVisibleDlgParent )
751 ImplSalAcquireYieldMutex( nMutexCount );
752 ClosePrinter( hPrn );
754 if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) )
756 rtl_freeMemory( pOutBuffer );
757 return FALSE;
760 // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
761 if( aSalShlData.mbWPrinter )
763 if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 64 )
765 sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmDeviceName );
766 if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )/sizeof(sal_Unicode) )
767 memset( ((LPDEVMODEW)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )-(nLen*sizeof(sal_Unicode)) );
769 if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 166 )
771 sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmFormName );
772 if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )/sizeof(sal_Unicode) )
773 memset( ((LPDEVMODEW)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )-(nLen*sizeof(sal_Unicode)) );
776 else
778 if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 32 )
780 sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmDeviceName );
781 if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName ) )
782 memset( ((LPDEVMODEA)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName )-nLen );
784 if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 102 )
786 sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmFormName );
787 if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName ) )
788 memset( ((LPDEVMODEA)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName )-nLen );
792 // update data
793 if ( pSetupData->mpDriverData )
794 rtl_freeMemory( pSetupData->mpDriverData );
795 pSetupData->mnDriverDataLen = nDriverDataLen;
796 pSetupData->mpDriverData = (BYTE*)pOutBuffer;
797 pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
799 return TRUE;
802 // -----------------------------------------------------------------------
804 #define DECLARE_DEVMODE( i )\
805 DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\
806 DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
807 if( pDevModeA == NULL && pDevModeW == NULL )\
808 return
810 #define CHOOSE_DEVMODE(i)\
811 (pDevModeW ? pDevModeW->i : pDevModeA->i)
813 static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags )
815 if ( !pSetupData || !pSetupData->mpDriverData )
816 return;
818 DECLARE_DEVMODE( pSetupData );
820 // Orientation
821 if ( nFlags & SAL_JOBSET_ORIENTATION )
823 if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_PORTRAIT )
824 pSetupData->meOrientation = ORIENTATION_PORTRAIT;
825 else if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_LANDSCAPE )
826 pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
829 // PaperBin
830 if ( nFlags & SAL_JOBSET_PAPERBIN )
832 ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
834 if ( nCount && (nCount != GDI_ERROR) )
836 WORD* pBins = (WORD*)rtl_allocateZeroMemory( nCount*sizeof(WORD) );
837 ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
838 pSetupData->mnPaperBin = 0;
840 // search the right bin and assign index to mnPaperBin
841 for( ULONG i = 0; i < nCount; i++ )
843 if( CHOOSE_DEVMODE(dmDefaultSource) == pBins[ i ] )
845 pSetupData->mnPaperBin = (USHORT)i;
846 break;
850 rtl_freeMemory( pBins );
854 // PaperSize
855 if ( nFlags & SAL_JOBSET_PAPERSIZE )
857 if( (CHOOSE_DEVMODE(dmFields) & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) )
859 pSetupData->mnPaperWidth = CHOOSE_DEVMODE(dmPaperWidth)*10;
860 pSetupData->mnPaperHeight = CHOOSE_DEVMODE(dmPaperLength)*10;
862 else
864 ULONG nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
865 WORD* pPapers = NULL;
866 ULONG nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
867 POINT* pPaperSizes = NULL;
868 if ( nPaperCount && (nPaperCount != GDI_ERROR) )
870 pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
871 ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
873 if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
875 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
876 ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
878 if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers )
880 for( ULONG i = 0; i < nPaperCount; i++ )
882 if( pPapers[ i ] == CHOOSE_DEVMODE(dmPaperSize) )
884 pSetupData->mnPaperWidth = pPaperSizes[ i ].x*10;
885 pSetupData->mnPaperHeight = pPaperSizes[ i ].y*10;
886 break;
890 if( pPapers )
891 rtl_freeMemory( pPapers );
892 if( pPaperSizes )
893 rtl_freeMemory( pPaperSizes );
895 switch( CHOOSE_DEVMODE(dmPaperSize) )
897 case( DMPAPER_LETTER ):
898 pSetupData->mePaperFormat = PAPER_LETTER;
899 break;
900 case( DMPAPER_TABLOID ):
901 pSetupData->mePaperFormat = PAPER_TABLOID;
902 break;
903 case( DMPAPER_LEDGER ):
904 pSetupData->mePaperFormat = PAPER_LEDGER;
905 break;
906 case( DMPAPER_LEGAL ):
907 pSetupData->mePaperFormat = PAPER_LEGAL;
908 break;
909 case( DMPAPER_STATEMENT ):
910 pSetupData->mePaperFormat = PAPER_STATEMENT;
911 break;
912 case( DMPAPER_EXECUTIVE ):
913 pSetupData->mePaperFormat = PAPER_EXECUTIVE;
914 break;
915 case( DMPAPER_A3 ):
916 pSetupData->mePaperFormat = PAPER_A3;
917 break;
918 case( DMPAPER_A4 ):
919 pSetupData->mePaperFormat = PAPER_A4;
920 break;
921 case( DMPAPER_A5 ):
922 pSetupData->mePaperFormat = PAPER_A5;
923 break;
924 //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
925 //i.e.
926 //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
927 //DMPAPER_B4 12 B4 (JIS) 257 x 364 mm
928 //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
929 //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
930 //matches our Excel filter's belief about the matching XlPaperSize
931 //enumeration.
933 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
934 ////"DMPAPER_B4 12 B4 (JIS) 250 x 354"
935 //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
936 //(cmc)
937 case( DMPAPER_B4 ):
938 pSetupData->mePaperFormat = PAPER_B4_JIS;
939 break;
940 case( DMPAPER_B5 ):
941 pSetupData->mePaperFormat = PAPER_B5_JIS;
942 break;
943 case( DMPAPER_QUARTO ):
944 pSetupData->mePaperFormat = PAPER_QUARTO;
945 break;
946 case( DMPAPER_10X14 ):
947 pSetupData->mePaperFormat = PAPER_10x14;
948 break;
949 case( DMPAPER_NOTE ):
950 pSetupData->mePaperFormat = PAPER_LETTER;
951 break;
952 case( DMPAPER_ENV_9 ):
953 pSetupData->mePaperFormat = PAPER_ENV_9;
954 break;
955 case( DMPAPER_ENV_10 ):
956 pSetupData->mePaperFormat = PAPER_ENV_10;
957 break;
958 case( DMPAPER_ENV_11 ):
959 pSetupData->mePaperFormat = PAPER_ENV_11;
960 break;
961 case( DMPAPER_ENV_12 ):
962 pSetupData->mePaperFormat = PAPER_ENV_12;
963 break;
964 case( DMPAPER_ENV_14 ):
965 pSetupData->mePaperFormat = PAPER_ENV_14;
966 break;
967 case( DMPAPER_CSHEET ):
968 pSetupData->mePaperFormat = PAPER_C;
969 break;
970 case( DMPAPER_DSHEET ):
971 pSetupData->mePaperFormat = PAPER_D;
972 break;
973 case( DMPAPER_ESHEET ):
974 pSetupData->mePaperFormat = PAPER_E;
975 break;
976 case( DMPAPER_ENV_DL):
977 pSetupData->mePaperFormat = PAPER_ENV_DL;
978 break;
979 case( DMPAPER_ENV_C5):
980 pSetupData->mePaperFormat = PAPER_ENV_C5;
981 break;
982 case( DMPAPER_ENV_C3):
983 pSetupData->mePaperFormat = PAPER_ENV_C3;
984 break;
985 case( DMPAPER_ENV_C4):
986 pSetupData->mePaperFormat = PAPER_ENV_C4;
987 break;
988 case( DMPAPER_ENV_C6):
989 pSetupData->mePaperFormat = PAPER_ENV_C6;
990 break;
991 case( DMPAPER_ENV_C65):
992 pSetupData->mePaperFormat = PAPER_ENV_C65;
993 break;
994 case( DMPAPER_ENV_ITALY ):
995 pSetupData->mePaperFormat = PAPER_ENV_ITALY;
996 break;
997 case( DMPAPER_ENV_MONARCH ):
998 pSetupData->mePaperFormat = PAPER_ENV_MONARCH;
999 break;
1000 case( DMPAPER_ENV_PERSONAL ):
1001 pSetupData->mePaperFormat = PAPER_ENV_PERSONAL;
1002 break;
1003 case( DMPAPER_FANFOLD_US ):
1004 pSetupData->mePaperFormat = PAPER_FANFOLD_US;
1005 break;
1006 case( DMPAPER_FANFOLD_STD_GERMAN ):
1007 pSetupData->mePaperFormat = PAPER_FANFOLD_DE;
1008 break;
1009 case( DMPAPER_FANFOLD_LGL_GERMAN ):
1010 pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE;
1011 break;
1012 case( DMPAPER_ISO_B4 ):
1013 pSetupData->mePaperFormat = PAPER_B4_ISO;
1014 break;
1015 case( DMPAPER_JAPANESE_POSTCARD ):
1016 pSetupData->mePaperFormat = PAPER_POSTCARD_JP;
1017 break;
1018 case( DMPAPER_9X11 ):
1019 pSetupData->mePaperFormat = PAPER_9x11;
1020 break;
1021 case( DMPAPER_10X11 ):
1022 pSetupData->mePaperFormat = PAPER_10x11;
1023 break;
1024 case( DMPAPER_15X11 ):
1025 pSetupData->mePaperFormat = PAPER_15x11;
1026 break;
1027 case( DMPAPER_ENV_INVITE ):
1028 pSetupData->mePaperFormat = PAPER_ENV_INVITE;
1029 break;
1030 case( DMPAPER_A_PLUS ):
1031 pSetupData->mePaperFormat = PAPER_A_PLUS;
1032 break;
1033 case( DMPAPER_B_PLUS ):
1034 pSetupData->mePaperFormat = PAPER_B_PLUS;
1035 break;
1036 case( DMPAPER_LETTER_PLUS ):
1037 pSetupData->mePaperFormat = PAPER_LETTER_PLUS;
1038 break;
1039 case( DMPAPER_A4_PLUS ):
1040 pSetupData->mePaperFormat = PAPER_A4_PLUS;
1041 break;
1042 case( DMPAPER_A2 ):
1043 pSetupData->mePaperFormat = PAPER_A2;
1044 break;
1045 case( DMPAPER_DBL_JAPANESE_POSTCARD ):
1046 pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP;
1047 break;
1048 case( DMPAPER_A6 ):
1049 pSetupData->mePaperFormat = PAPER_A6;
1050 break;
1051 case( DMPAPER_B6_JIS ):
1052 pSetupData->mePaperFormat = PAPER_B6_JIS;
1053 break;
1054 case( DMPAPER_12X11 ):
1055 pSetupData->mePaperFormat = PAPER_12x11;
1056 break;
1057 default:
1058 pSetupData->mePaperFormat = PAPER_USER;
1059 break;
1064 // -----------------------------------------------------------------------
1066 static void ImplJobSetupToDevMode( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, ULONG nFlags )
1068 if ( !pSetupData || !pSetupData->mpDriverData )
1069 return;
1071 DECLARE_DEVMODE( pSetupData );
1073 // Orientation
1074 if ( nFlags & SAL_JOBSET_ORIENTATION )
1076 CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION;
1077 if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT )
1078 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT;
1079 else
1080 CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE;
1083 // PaperBin
1084 if ( nFlags & SAL_JOBSET_PAPERBIN )
1086 ULONG nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
1088 if ( nCount && (nCount != GDI_ERROR) )
1090 WORD* pBins = (WORD*)rtl_allocateZeroMemory(nCount*sizeof(WORD));
1091 ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
1092 CHOOSE_DEVMODE(dmFields) |= DM_DEFAULTSOURCE;
1093 CHOOSE_DEVMODE(dmDefaultSource) = pBins[ pSetupData->mnPaperBin ];
1094 rtl_freeMemory( pBins );
1098 // PaperSize
1099 if ( nFlags & SAL_JOBSET_PAPERSIZE )
1101 CHOOSE_DEVMODE(dmFields) |= DM_PAPERSIZE;
1102 CHOOSE_DEVMODE(dmPaperWidth) = 0;
1103 CHOOSE_DEVMODE(dmPaperLength) = 0;
1105 switch( pSetupData->mePaperFormat )
1107 case( PAPER_A2 ):
1108 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2;
1109 break;
1110 case( PAPER_A3 ):
1111 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3;
1112 break;
1113 case( PAPER_A4 ):
1114 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4;
1115 break;
1116 case( PAPER_A5 ):
1117 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5;
1118 break;
1119 case( PAPER_B4_ISO):
1120 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4;
1121 break;
1122 case( PAPER_LETTER ):
1123 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER;
1124 break;
1125 case( PAPER_LEGAL ):
1126 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL;
1127 break;
1128 case( PAPER_TABLOID ):
1129 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID;
1130 break;
1131 #if 0
1132 //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
1133 //DMPAPER_ENV_B6 is documented as:
1134 //"DMPAPER_ENV_B6 35 Envelope B6 176 x 125 mm"
1135 //which is the wrong way around, it is surely 125 x 176, i.e.
1136 //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
1137 //DMPAPER_ENV_B4 33 Envelope B4 250 x 353 mm
1138 //DMPAPER_ENV_B5 34 Envelope B5 176 x 250 mm
1139 case( PAPER_B6_ISO ):
1140 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_B6;
1141 break;
1142 #endif
1143 case( PAPER_ENV_C4 ):
1144 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4;
1145 break;
1146 case( PAPER_ENV_C5 ):
1147 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5;
1148 break;
1149 case( PAPER_ENV_C6 ):
1150 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6;
1151 break;
1152 case( PAPER_ENV_C65 ):
1153 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65;
1154 break;
1155 case( PAPER_ENV_DL ):
1156 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL;
1157 break;
1158 case( PAPER_C ):
1159 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET;
1160 break;
1161 case( PAPER_D ):
1162 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET;
1163 break;
1164 case( PAPER_E ):
1165 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET;
1166 break;
1167 case( PAPER_EXECUTIVE ):
1168 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE;
1169 break;
1170 case( PAPER_FANFOLD_LEGAL_DE ):
1171 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN;
1172 break;
1173 case( PAPER_ENV_MONARCH ):
1174 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH;
1175 break;
1176 case( PAPER_ENV_PERSONAL ):
1177 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL;
1178 break;
1179 case( PAPER_ENV_9 ):
1180 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9;
1181 break;
1182 case( PAPER_ENV_10 ):
1183 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10;
1184 break;
1185 case( PAPER_ENV_11 ):
1186 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11;
1187 break;
1188 case( PAPER_ENV_12 ):
1189 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12;
1190 break;
1191 //See the comments on DMPAPER_B4 above
1192 case( PAPER_B4_JIS ):
1193 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4;
1194 break;
1195 case( PAPER_B5_JIS ):
1196 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5;
1197 break;
1198 case( PAPER_B6_JIS ):
1199 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS;
1200 break;
1201 case( PAPER_LEDGER ):
1202 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER;
1203 break;
1204 case( PAPER_STATEMENT ):
1205 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT;
1206 break;
1207 case( PAPER_10x14 ):
1208 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14;
1209 break;
1210 case( PAPER_ENV_14 ):
1211 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14;
1212 break;
1213 case( PAPER_ENV_C3 ):
1214 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3;
1215 break;
1216 case( PAPER_ENV_ITALY ):
1217 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY;
1218 break;
1219 case( PAPER_FANFOLD_US ):
1220 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US;
1221 break;
1222 case( PAPER_FANFOLD_DE ):
1223 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN;
1224 break;
1225 case( PAPER_POSTCARD_JP ):
1226 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD;
1227 break;
1228 case( PAPER_9x11 ):
1229 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11;
1230 break;
1231 case( PAPER_10x11 ):
1232 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11;
1233 break;
1234 case( PAPER_15x11 ):
1235 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11;
1236 break;
1237 case( PAPER_ENV_INVITE ):
1238 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE;
1239 break;
1240 case( PAPER_A_PLUS ):
1241 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS;
1242 break;
1243 case( PAPER_B_PLUS ):
1244 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS;
1245 break;
1246 case( PAPER_LETTER_PLUS ):
1247 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS;
1248 break;
1249 case( PAPER_A4_PLUS ):
1250 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS;
1251 break;
1252 case( PAPER_DOUBLEPOSTCARD_JP ):
1253 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD;
1254 break;
1255 case( PAPER_A6 ):
1256 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6;
1257 break;
1258 case( PAPER_12x11 ):
1259 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11;
1260 break;
1261 default:
1263 short nPaper = 0;
1264 ULONG nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
1265 WORD* pPapers = NULL;
1266 ULONG nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
1267 POINT* pPaperSizes = NULL;
1268 DWORD nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, NULL, pSetupData );
1269 if ( nPaperCount && (nPaperCount != GDI_ERROR) )
1271 pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
1272 ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
1274 if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
1276 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
1277 ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1279 if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes )
1281 PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
1282 // compare paper formats and select a good match
1283 for ( ULONG i = 0; i < nPaperCount; i++ )
1285 if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)))
1287 nPaper = pPapers[i];
1288 break;
1292 // If the printer supports landscape orientation, check paper sizes again
1293 // with landscape orientation. This is necessary as a printer driver provides
1294 // all paper sizes with portrait orientation only!!
1295 if ( !nPaper && nLandscapeAngle != 0 )
1297 PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
1298 for ( ULONG i = 0; i < nPaperCount; i++ )
1300 if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) )
1302 nPaper = pPapers[i];
1303 break;
1308 if ( nPaper )
1309 CHOOSE_DEVMODE(dmPaperSize) = nPaper;
1312 if ( !nPaper )
1314 CHOOSE_DEVMODE(dmFields) |= DM_PAPERLENGTH | DM_PAPERWIDTH;
1315 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_USER;
1316 CHOOSE_DEVMODE(dmPaperWidth) = (short)(pSetupData->mnPaperWidth/10);
1317 CHOOSE_DEVMODE(dmPaperLength) = (short)(pSetupData->mnPaperHeight/10);
1320 if ( pPapers )
1321 rtl_freeMemory(pPapers);
1322 if ( pPaperSizes )
1323 rtl_freeMemory(pPaperSizes);
1325 break;
1331 // -----------------------------------------------------------------------
1333 static HDC ImplCreateICW_WithCatch( LPWSTR pDriver,
1334 LPCWSTR pDevice,
1335 LPDEVMODEW pDevMode )
1337 HDC hDC = 0;
1338 CATCH_DRIVER_EX_BEGIN;
1339 hDC = CreateICW( pDriver, pDevice, 0, pDevMode );
1340 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1341 return hDC;
1344 static HDC ImplCreateICA_WithCatch( char* pDriver,
1345 char* pDevice,
1346 LPDEVMODEA pDevMode )
1348 HDC hDC = 0;
1349 CATCH_DRIVER_EX_BEGIN;
1350 hDC = CreateICA( pDriver, pDevice, 0, pDevMode );
1351 CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1352 return hDC;
1356 static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1358 HDC hDC = 0;
1359 if( aSalShlData.mbWPrinter )
1361 LPDEVMODEW pDevMode;
1362 if ( pSetupData && pSetupData->mpDriverData )
1363 pDevMode = SAL_DEVMODE_W( pSetupData );
1364 else
1365 pDevMode = NULL;
1366 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1367 // pl: does this hold true for Unicode functions ?
1368 if( pPrinter->maDriverName.Len() > 2048 || pPrinter->maDeviceName.Len() > 2048 )
1369 return 0;
1370 sal_Unicode pDriverName[ 4096 ];
1371 sal_Unicode pDeviceName[ 4096 ];
1372 rtl_copyMemory( pDriverName, pPrinter->maDriverName.GetBuffer(), pPrinter->maDriverName.Len()*sizeof(sal_Unicode));
1373 memset( pDriverName+pPrinter->maDriverName.Len(), 0, 32 );
1374 rtl_copyMemory( pDeviceName, pPrinter->maDeviceName.GetBuffer(), pPrinter->maDeviceName.Len()*sizeof(sal_Unicode));
1375 memset( pDeviceName+pPrinter->maDeviceName.Len(), 0, 32 );
1376 hDC = ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR >(pDriverName),
1377 reinterpret_cast< LPCWSTR >(pDeviceName),
1378 pDevMode );
1380 else
1382 LPDEVMODEA pDevMode;
1383 if ( pSetupData && pSetupData->mpDriverData )
1384 pDevMode = SAL_DEVMODE_A( pSetupData );
1385 else
1386 pDevMode = NULL;
1387 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1388 ByteString aDriver ( ImplSalGetWinAnsiString( pPrinter->maDriverName, TRUE ) );
1389 ByteString aDevice ( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ) );
1390 int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
1391 // #125813# under some circumstances many printer drivers really
1392 // seem to have a problem with the names and their conversions.
1393 // We need to get on to of this, but haven't been able to reproduce
1394 // the problem yet. Put the names on the stack so we get them
1395 // with an eventual crash report.
1396 if( n >= 2048 )
1397 return 0;
1398 n += 2048;
1399 char lpszDriverName[ 4096 ];
1400 char lpszDeviceName[ 4096 ];
1401 strncpy( lpszDriverName, aDriver.GetBuffer(), n );
1402 strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
1403 // HDU: the crashes usually happen in a MBCS to unicode conversion,
1404 // so I suspect the MBCS string's end is not properly recognized.
1405 // The longest MBCS encoding I'm aware of has six bytes per code
1406 // => add a couple of zeroes...
1407 memset( lpszDriverName+aDriver.Len(), 0, 16 );
1408 memset( lpszDeviceName+aDevice.Len(), 0, 16 );
1409 hDC = ImplCreateICA_WithCatch( lpszDriverName,
1410 lpszDeviceName,
1411 pDevMode );
1413 return hDC;
1416 // -----------------------------------------------------------------------
1418 static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC )
1420 WinSalGraphics* pGraphics = new WinSalGraphics;
1421 pGraphics->SetLayout( 0 );
1422 pGraphics->mhDC = hDC;
1423 pGraphics->mhWnd = 0;
1424 pGraphics->mbPrinter = TRUE;
1425 pGraphics->mbVirDev = FALSE;
1426 pGraphics->mbWindow = FALSE;
1427 pGraphics->mbScreen = FALSE;
1428 ImplSalInitGraphics( pGraphics );
1429 return pGraphics;
1432 // -----------------------------------------------------------------------
1434 static BOOL ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1436 HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1437 if ( !hNewDC )
1438 return FALSE;
1440 if ( pPrinter->mpGraphics )
1442 ImplSalDeInitGraphics( pPrinter->mpGraphics );
1443 DeleteDC( pPrinter->mpGraphics->mhDC );
1444 delete pPrinter->mpGraphics;
1447 pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hNewDC );
1448 pPrinter->mhDC = hNewDC;
1450 return TRUE;
1453 // =======================================================================
1455 SalInfoPrinter* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
1456 ImplJobSetup* pSetupData )
1458 WinSalInfoPrinter* pPrinter = new WinSalInfoPrinter;
1459 if( ! pQueueInfo->mpSysData )
1460 GetPrinterQueueState( pQueueInfo );
1461 pPrinter->maDriverName = pQueueInfo->maDriver;
1462 pPrinter->maDeviceName = pQueueInfo->maPrinterName;
1463 pPrinter->maPortName = pQueueInfo->mpSysData ?
1464 *(String*)(pQueueInfo->mpSysData)
1465 : String();
1467 // check if the provided setup data match the actual printer
1468 ImplTestSalJobSetup( pPrinter, pSetupData, TRUE );
1470 HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1471 if ( !hDC )
1473 delete pPrinter;
1474 return NULL;
1477 pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hDC );
1478 pPrinter->mhDC = hDC;
1479 if ( !pSetupData->mpDriverData )
1480 ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL );
1481 ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL );
1482 pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
1484 return pPrinter;
1487 // -----------------------------------------------------------------------
1489 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
1491 delete pPrinter;
1494 // =======================================================================
1496 WinSalInfoPrinter::WinSalInfoPrinter() :
1497 mpGraphics( NULL ),
1498 mhDC( 0 ),
1499 mbGraphics( FALSE )
1501 m_bPapersInit = FALSE;
1504 // -----------------------------------------------------------------------
1506 WinSalInfoPrinter::~WinSalInfoPrinter()
1508 if ( mpGraphics )
1510 ImplSalDeInitGraphics( mpGraphics );
1511 DeleteDC( mpGraphics->mhDC );
1512 delete mpGraphics;
1516 // -----------------------------------------------------------------------
1518 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
1520 m_aPaperFormats.clear();
1522 DWORD nCount = ImplDeviceCaps( this, DC_PAPERSIZE, NULL, pSetupData );
1523 if( nCount == GDI_ERROR )
1524 nCount = 0;
1526 POINT* pPaperSizes = NULL;
1527 if( nCount )
1529 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nCount*sizeof(POINT));
1530 ImplDeviceCaps( this, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1532 if( aSalShlData.mbWPrinter )
1534 sal_Unicode* pNamesBuffer = (sal_Unicode*)rtl_allocateMemory(nCount*64*sizeof(sal_Unicode));
1535 ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1536 for( DWORD i = 0; i < nCount; ++i )
1538 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1539 m_aPaperFormats.push_back( aInfo );
1541 rtl_freeMemory( pNamesBuffer );
1543 else
1545 char* pNamesBuffer = (char*)rtl_allocateMemory(nCount*64);
1546 ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1547 for( DWORD i = 0; i < nCount; ++i )
1549 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1550 m_aPaperFormats.push_back( aInfo );
1552 rtl_freeMemory( pNamesBuffer );
1554 rtl_freeMemory( pPaperSizes );
1557 m_bPapersInit = true;
1560 // -----------------------------------------------------------------------
1562 DuplexMode WinSalInfoPrinter::GetDuplexMode( const ImplJobSetup* pSetupData )
1564 DuplexMode nRet = DUPLEX_UNKNOWN;
1565 if ( pSetupData &&pSetupData->mpDriverData )
1567 if( aSalShlData.mbWPrinter )
1569 DEVMODEW* pDevMode = SAL_DEVMODE_W( pSetupData );
1570 if ( pDevMode && (pDevMode->dmFields & DM_DUPLEX ))
1572 if ( pDevMode->dmDuplex == DMDUP_SIMPLEX )
1573 nRet = DUPLEX_OFF;
1574 else
1575 nRet = DUPLEX_ON;
1578 else
1580 DEVMODEA* pDevMode = SAL_DEVMODE_A( pSetupData );
1581 if ( pDevMode && (pDevMode->dmFields & DM_DUPLEX ))
1583 if ( pDevMode->dmDuplex == DMDUP_SIMPLEX )
1584 nRet = DUPLEX_OFF;
1585 else
1586 nRet = DUPLEX_ON;
1590 return nRet;
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 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 BOOL WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
1642 if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) )
1643 return FALSE;
1644 return ImplUpdateSalPrnIC( this, pSetupData );
1647 // -----------------------------------------------------------------------
1649 BOOL WinSalInfoPrinter::SetData( 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 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, 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 ULONG WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, USHORT 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 WIN_BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
1791 SalData* pSalData = GetSalData();
1792 WinSalPrinter* pPrinter;
1793 BOOL bWhile = TRUE;
1794 int i = 0;
1798 // Messages verarbeiten
1799 MSG aMsg;
1800 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
1802 TranslateMessage( &aMsg );
1803 ImplDispatchMessage( &aMsg );
1804 i++;
1805 if ( i > 15 )
1806 bWhile = FALSE;
1808 else
1809 bWhile = FALSE;
1811 pPrinter = pSalData->mpFirstPrinter;
1812 while ( pPrinter )
1814 if( pPrinter->mhDC == hPrnDC )
1815 break;
1817 pPrinter = pPrinter->mpNextPrinter;
1820 if ( !pPrinter || pPrinter->mbAbort )
1821 return FALSE;
1823 while ( bWhile );
1825 return TRUE;
1828 // -----------------------------------------------------------------------
1830 static LPDEVMODEA ImplSalSetCopies( LPDEVMODEA pDevMode, ULONG nCopies, BOOL bCollate )
1832 LPDEVMODEA pNewDevMode = pDevMode;
1833 if ( pDevMode && (nCopies > 1) )
1835 if ( nCopies > 32765 )
1836 nCopies = 32765;
1837 ULONG nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1838 pNewDevMode = (LPDEVMODEA)rtl_allocateMemory( nDevSize );
1839 memcpy( pNewDevMode, pDevMode, nDevSize );
1840 pDevMode = pNewDevMode;
1841 pDevMode->dmFields |= DM_COPIES;
1842 pDevMode->dmCopies = (short)(USHORT)nCopies;
1843 if ( aSalShlData.mbW40 )
1845 pDevMode->dmFields |= DM_COLLATE;
1846 if ( bCollate )
1847 pDevMode->dmCollate = DMCOLLATE_TRUE;
1848 else
1849 pDevMode->dmCollate = DMCOLLATE_FALSE;
1853 return pNewDevMode;
1856 static LPDEVMODEW ImplSalSetCopies( LPDEVMODEW pDevMode, ULONG nCopies, BOOL bCollate )
1858 LPDEVMODEW pNewDevMode = pDevMode;
1859 if ( pDevMode && (nCopies > 1) )
1861 if ( nCopies > 32765 )
1862 nCopies = 32765;
1863 ULONG nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1864 pNewDevMode = (LPDEVMODEW)rtl_allocateMemory( nDevSize );
1865 memcpy( pNewDevMode, pDevMode, nDevSize );
1866 pDevMode = pNewDevMode;
1867 pDevMode->dmFields |= DM_COPIES;
1868 pDevMode->dmCopies = (short)(USHORT)nCopies;
1869 if ( aSalShlData.mbW40 )
1871 pDevMode->dmFields |= DM_COLLATE;
1872 if ( bCollate )
1873 pDevMode->dmCollate = DMCOLLATE_TRUE;
1874 else
1875 pDevMode->dmCollate = DMCOLLATE_FALSE;
1879 return pNewDevMode;
1882 // -----------------------------------------------------------------------
1884 WinSalPrinter::WinSalPrinter() :
1885 mpGraphics( NULL ),
1886 mpInfoPrinter( NULL ),
1887 mpNextPrinter( NULL ),
1888 mhDC( 0 ),
1889 mnError( 0 ),
1890 mnCopies( 0 ),
1891 mbCollate( FALSE ),
1892 mbAbort( FALSE ),
1893 mbValid( true )
1895 SalData* pSalData = GetSalData();
1896 // insert printer in printerlist
1897 mpNextPrinter = pSalData->mpFirstPrinter;
1898 pSalData->mpFirstPrinter = this;
1901 // -----------------------------------------------------------------------
1903 WinSalPrinter::~WinSalPrinter()
1905 SalData* pSalData = GetSalData();
1907 // release DC if there is one still around because of AbortJob
1908 HDC hDC = mhDC;
1909 if ( hDC )
1911 if ( mpGraphics )
1913 ImplSalDeInitGraphics( mpGraphics );
1914 delete mpGraphics;
1917 DeleteDC( hDC );
1920 // remove printer from printerlist
1921 if ( this == pSalData->mpFirstPrinter )
1922 pSalData->mpFirstPrinter = mpNextPrinter;
1923 else
1925 WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
1927 while( pTempPrinter->mpNextPrinter != this )
1928 pTempPrinter = pTempPrinter->mpNextPrinter;
1930 pTempPrinter->mpNextPrinter = mpNextPrinter;
1932 mbValid = false;
1935 // -----------------------------------------------------------------------
1937 void WinSalPrinter::markInvalid()
1939 mbValid = false;
1942 // -----------------------------------------------------------------------
1944 // need wrappers for StarTocW/A to use structured exception handling
1945 // since SEH does not mix with standard exception handling's cleanup
1946 static int lcl_StartDocW( HDC hDC, DOCINFOW* pInfo, WinSalPrinter* pPrt )
1948 int nRet = 0;
1949 CATCH_DRIVER_EX_BEGIN;
1950 nRet = ::StartDocW( hDC, pInfo );
1951 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1952 return nRet;
1955 static int lcl_StartDocA( HDC hDC, DOCINFOA* pInfo, WinSalPrinter* pPrt )
1957 int nRet = 0;
1958 CATCH_DRIVER_EX_BEGIN;
1959 nRet = ::StartDocA( hDC, pInfo );
1960 CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1961 return nRet;
1964 BOOL WinSalPrinter::StartJob( const XubString* pFileName,
1965 const XubString& rJobName,
1966 const XubString&,
1967 ULONG nCopies, BOOL bCollate,
1968 ImplJobSetup* pSetupData )
1970 mnError = 0;
1971 mbAbort = FALSE;
1972 mnCopies = nCopies;
1973 mbCollate = bCollate;
1975 LPDEVMODEA pOrgDevModeA = NULL;
1976 LPDEVMODEA pDevModeA = NULL;
1977 LPDEVMODEW pOrgDevModeW = NULL;
1978 LPDEVMODEW pDevModeW = NULL;
1979 HDC hDC = 0;
1980 if( aSalShlData.mbWPrinter )
1982 if ( pSetupData && pSetupData->mpDriverData )
1984 pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
1985 pDevModeW = ImplSalSetCopies( pOrgDevModeW, nCopies, bCollate );
1987 else
1988 pDevModeW = NULL;
1990 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1991 sal_Unicode aDrvBuf[4096];
1992 sal_Unicode aDevBuf[4096];
1993 rtl_copyMemory( aDrvBuf, mpInfoPrinter->maDriverName.GetBuffer(), (mpInfoPrinter->maDriverName.Len()+1)*sizeof(sal_Unicode));
1994 rtl_copyMemory( aDevBuf, mpInfoPrinter->maDeviceName.GetBuffer(), (mpInfoPrinter->maDeviceName.Len()+1)*sizeof(sal_Unicode));
1995 hDC = CreateDCW( reinterpret_cast<LPCWSTR>(aDrvBuf),
1996 reinterpret_cast<LPCWSTR>(aDevBuf),
1997 NULL,
1998 pDevModeW );
2000 if ( pDevModeW != pOrgDevModeW )
2001 rtl_freeMemory( pDevModeW );
2003 else
2005 if ( pSetupData && pSetupData->mpDriverData )
2007 pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2008 pDevModeA = ImplSalSetCopies( pOrgDevModeA, nCopies, bCollate );
2010 else
2011 pDevModeA = NULL;
2013 // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
2014 ByteString aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter->maDriverName, TRUE ) );
2015 ByteString aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter->maDeviceName, TRUE ) );
2016 int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
2017 n += 2048;
2018 char *lpszDriverName = new char[n];
2019 char *lpszDeviceName = new char[n];
2020 strncpy( lpszDriverName, aDriver.GetBuffer(), n );
2021 strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
2022 hDC = CreateDCA( lpszDriverName,
2023 lpszDeviceName,
2024 NULL,
2025 pDevModeA );
2027 delete [] lpszDriverName;
2028 delete [] lpszDeviceName;
2030 if ( pDevModeA != pOrgDevModeA )
2031 rtl_freeMemory( pDevModeA );
2034 if ( !hDC )
2036 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2037 return FALSE;
2040 // make sure mhDC is set before the printer driver may call our abortproc
2041 mhDC = hDC;
2042 if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
2044 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2045 return FALSE;
2048 mnError = 0;
2049 mbAbort = FALSE;
2051 // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages
2052 // ansonsten oefters schickt, versuchen wir vorher alle
2053 // zu verarbeiten und dann eine Dummy-Message reinstellen
2054 BOOL bWhile = TRUE;
2055 int i = 0;
2058 // Messages verarbeiten
2059 MSG aMsg;
2060 if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
2062 TranslateMessage( &aMsg );
2063 ImplDispatchMessage( &aMsg );
2064 i++;
2065 if ( i > 15 )
2066 bWhile = FALSE;
2068 else
2069 bWhile = FALSE;
2071 while ( bWhile );
2072 ImplPostMessage( GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0 );
2074 // bring up a file choser if printing to file port but no file name given
2075 OUString aOutFileName;
2076 if( mpInfoPrinter->maPortName.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName && pFileName->Len()) )
2079 Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
2080 if( xFactory.is() )
2082 Reference< XFilePicker > xFilePicker( xFactory->createInstance(
2083 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
2084 UNO_QUERY );
2085 DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" );
2087 Reference< XInitialization > xInit( xFilePicker, UNO_QUERY );
2088 Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY );
2089 if( xInit.is() && xFilePicker.is() && xFilterMgr.is() )
2091 Sequence< Any > aServiceType( 1 );
2092 aServiceType[0] <<= TemplateDescription::FILESAVE_SIMPLE;
2093 xInit->initialize( aServiceType );
2094 if( xFilePicker->execute() == ExecutableDialogResults::OK )
2096 Sequence< OUString > aPathSeq( xFilePicker->getFiles() );
2097 INetURLObject aObj( aPathSeq[0] );
2098 // we're using ansi calls (StartDocA) so convert the string
2099 aOutFileName = aObj.PathToFileName();
2101 else
2103 mnError = SAL_PRINTER_ERROR_ABORT;
2104 return FALSE;
2110 if( aSalShlData.mbWPrinter )
2112 DOCINFOW aInfo;
2113 memset( &aInfo, 0, sizeof( DOCINFOW ) );
2114 aInfo.cbSize = sizeof( aInfo );
2115 aInfo.lpszDocName = (LPWSTR)rJobName.GetBuffer();
2116 if ( pFileName || aOutFileName.getLength() )
2118 if ( (pFileName && pFileName->Len()) || aOutFileName.getLength() )
2120 aInfo.lpszOutput = (LPWSTR)( (pFileName && pFileName->Len()) ? pFileName->GetBuffer() : aOutFileName.getStr());
2122 else
2123 aInfo.lpszOutput = L"FILE:";
2125 else
2126 aInfo.lpszOutput = NULL;
2128 // start Job
2129 int nRet = lcl_StartDocW( hDC, &aInfo, this );
2131 if ( nRet <= 0 )
2133 long nError = GetLastError();
2134 if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2135 mnError = SAL_PRINTER_ERROR_ABORT;
2136 else
2137 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2138 return FALSE;
2141 else
2143 // Both strings must exist, if StartJob() is called
2144 ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) );
2145 ByteString aFileName;
2147 DOCINFOA aInfo;
2148 memset( &aInfo, 0, sizeof( DOCINFOA ) );
2149 aInfo.cbSize = sizeof( aInfo );
2150 aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer();
2151 if ( pFileName || aOutFileName.getLength() )
2153 if ( pFileName->Len() || aOutFileName.getLength() )
2155 aFileName = ImplSalGetWinAnsiString( pFileName ? *pFileName : static_cast<const XubString>(aOutFileName), TRUE );
2156 aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer();
2158 else
2159 aInfo.lpszOutput = "FILE:";
2161 else
2162 aInfo.lpszOutput = NULL;
2164 // start Job
2165 int nRet = lcl_StartDocA( hDC, &aInfo, this );
2166 if ( nRet <= 0 )
2168 long nError = GetLastError();
2169 if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2170 mnError = SAL_PRINTER_ERROR_ABORT;
2171 else
2172 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2173 return FALSE;
2177 return TRUE;
2180 // -----------------------------------------------------------------------
2182 BOOL WinSalPrinter::EndJob()
2184 DWORD err = 0;
2185 HDC hDC = mhDC;
2186 if ( isValid() && hDC )
2188 if ( mpGraphics )
2190 ImplSalDeInitGraphics( mpGraphics );
2191 delete mpGraphics;
2192 mpGraphics = NULL;
2195 // #i54419# Windows fax printer brings up a dialog in EndDoc
2196 // which text previously copied in soffice process can be
2197 // pasted to -> deadlock due to mutex not released.
2198 // it should be safe to release the yield mutex over the EndDoc
2199 // call, however the real solution is supposed to be the threading
2200 // framework yet to come.
2201 SalData* pSalData = GetSalData();
2202 ULONG nAcquire = pSalData->mpFirstInstance->ReleaseYieldMutex();
2203 CATCH_DRIVER_EX_BEGIN;
2204 if( ::EndDoc( hDC ) <= 0 )
2205 err = GetLastError();
2206 CATCH_DRIVER_EX_END( "exception in EndDoc", this );
2208 pSalData->mpFirstInstance->AcquireYieldMutex( nAcquire );
2209 DeleteDC( hDC );
2210 mhDC = 0;
2213 return TRUE;
2216 // -----------------------------------------------------------------------
2218 BOOL WinSalPrinter::AbortJob()
2220 mbAbort = TRUE;
2222 // Abort asyncron ausloesen
2223 HDC hDC = mhDC;
2224 if ( hDC )
2226 SalData* pSalData = GetSalData();
2227 ImplPostMessage( pSalData->mpFirstInstance->mhComWnd,
2228 SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 );
2231 return TRUE;
2234 // -----------------------------------------------------------------------
2236 void ImplSalPrinterAbortJobAsync( HDC hPrnDC )
2238 SalData* pSalData = GetSalData();
2239 WinSalPrinter* pPrinter = pSalData->mpFirstPrinter;
2241 // Feststellen, ob Printer noch existiert
2242 while ( pPrinter )
2244 if ( pPrinter->mhDC == hPrnDC )
2245 break;
2247 pPrinter = pPrinter->mpNextPrinter;
2250 // Wenn Printer noch existiert, dann den Job abbrechen
2251 if ( pPrinter )
2253 HDC hDC = pPrinter->mhDC;
2254 if ( hDC )
2256 if ( pPrinter->mpGraphics )
2258 ImplSalDeInitGraphics( pPrinter->mpGraphics );
2259 delete pPrinter->mpGraphics;
2260 pPrinter->mpGraphics = NULL;
2263 CATCH_DRIVER_EX_BEGIN;
2264 ::AbortDoc( hDC );
2265 CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter );
2267 DeleteDC( hDC );
2268 pPrinter->mhDC = 0;
2273 // -----------------------------------------------------------------------
2275 SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, BOOL bNewJobData )
2277 if( ! isValid() || mhDC == 0 )
2278 return NULL;
2280 HDC hDC = mhDC;
2281 if ( pSetupData && pSetupData->mpDriverData && bNewJobData )
2283 if( aSalShlData.mbWPrinter )
2285 LPDEVMODEW pOrgDevModeW;
2286 LPDEVMODEW pDevModeW;
2287 pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
2288 pDevModeW = ImplSalSetCopies( pOrgDevModeW, mnCopies, mbCollate );
2289 ResetDCW( hDC, pDevModeW );
2290 if ( pDevModeW != pOrgDevModeW )
2291 rtl_freeMemory( pDevModeW );
2293 else
2295 LPDEVMODEA pOrgDevModeA;
2296 LPDEVMODEA pDevModeA;
2297 pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2298 pDevModeA = ImplSalSetCopies( pOrgDevModeA, mnCopies, mbCollate );
2299 ResetDCA( hDC, pDevModeA );
2300 if ( pDevModeA != pOrgDevModeA )
2301 rtl_freeMemory( pDevModeA );
2304 int nRet = 0;
2305 CATCH_DRIVER_EX_BEGIN;
2306 nRet = ::StartPage( hDC );
2307 CATCH_DRIVER_EX_END( "exception in StartPage", this );
2309 if ( nRet <= 0 )
2311 GetLastError();
2312 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2313 return NULL;
2316 // Hack to work around old PostScript printer drivers optimizing away empty pages
2317 // TODO: move into ImplCreateSalPrnGraphics()?
2318 HPEN hTempPen = SelectPen( hDC, GetStockPen( NULL_PEN ) );
2319 HBRUSH hTempBrush = SelectBrush( hDC, GetStockBrush( NULL_BRUSH ) );
2320 WIN_Rectangle( hDC, -8000, -8000, -7999, -7999 );
2321 SelectPen( hDC, hTempPen );
2322 SelectBrush( hDC, hTempBrush );
2324 mpGraphics = ImplCreateSalPrnGraphics( hDC );
2325 return mpGraphics;
2328 // -----------------------------------------------------------------------
2330 BOOL WinSalPrinter::EndPage()
2332 HDC hDC = mhDC;
2333 if ( hDC && mpGraphics )
2335 ImplSalDeInitGraphics( mpGraphics );
2336 delete mpGraphics;
2337 mpGraphics = NULL;
2340 if( ! isValid() )
2341 return FALSE;
2343 int nRet = 0;
2344 CATCH_DRIVER_EX_BEGIN;
2345 nRet = ::EndPage( hDC );
2346 CATCH_DRIVER_EX_END( "exception in EndPage", this );
2348 if ( nRet > 0 )
2349 return TRUE;
2350 else
2352 GetLastError();
2353 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2354 return FALSE;
2358 // -----------------------------------------------------------------------
2360 ULONG WinSalPrinter::GetErrorCode()
2362 return mnError;