xref: /AOO41X/main/vcl/win/source/gdi/salprn.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <string.h>
28 
29 #include <osl/module.h>
30 
31 #include <tools/urlobj.hxx>
32 #include <tools/svwin.h>
33 #ifdef __MINGW32__
34 #include <excpt.h>
35 #endif
36 
37 #include <win/wincomp.hxx>
38 #include <win/saldata.hxx>
39 #include <win/salinst.h>
40 #include <win/salgdi.h>
41 #include <win/salframe.h>
42 #include <win/salprn.h>
43 
44 #include <salptype.hxx>
45 #include <print.h>
46 #include <jobset.h>
47 
48 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
49 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
50 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
51 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
52 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
53 #include <com/sun/star/lang/XInitialization.hpp>
54 #include <comphelper/processfactory.hxx>
55 
56 #include <malloc.h>
57 
58 #ifdef __MINGW32__
59 #define CATCH_DRIVER_EX_BEGIN                                               \
60     jmp_buf jmpbuf;                                                         \
61     __SEHandler han;                                                        \
62     if (__builtin_setjmp(jmpbuf) == 0)                                      \
63     {                                                                       \
64         han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER)
65 
66 #define CATCH_DRIVER_EX_END(mes, p)                                         \
67     }                                                                       \
68     han.Reset()
69 #define CATCH_DRIVER_EX_END_2(mes)                                            \
70     }                                                                       \
71     han.Reset()
72 #else
73 #define CATCH_DRIVER_EX_BEGIN                                               \
74     __try                                                                   \
75     {
76 #define CATCH_DRIVER_EX_END(mes, p)                                         \
77     }                                                                       \
78     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
79     {                                                                       \
80         DBG_ERROR( mes );                                                   \
81         p->markInvalid();                                                   \
82     }
83 #define CATCH_DRIVER_EX_END_2(mes)                                         \
84     }                                                                       \
85     __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))\
86     {                                                                       \
87         DBG_ERROR( mes );                                                   \
88     }
89 #endif
90 
91 
92 using namespace com::sun::star;
93 using namespace com::sun::star::uno;
94 using namespace com::sun::star::lang;
95 using namespace com::sun::star::ui::dialogs;
96 using namespace rtl;
97 
98 // =======================================================================
99 
100 static char aImplWindows[] = "windows";
101 static char aImplDevices[] = "devices";
102 static char aImplDevice[]  = "device";
103 
SAL_DEVMODE_A(const ImplJobSetup * pSetupData)104 static LPDEVMODEA SAL_DEVMODE_A( const ImplJobSetup* pSetupData )
105 {
106     LPDEVMODEA pRet = NULL;
107     SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
108     if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_A &&
109         pSetupData->mnDriverDataLen >= sizeof(DEVMODEA)+sizeof(SalDriverData)-1
110         )
111         pRet = ((LPDEVMODEA)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
112     return pRet;
113 }
114 
SAL_DEVMODE_W(const ImplJobSetup * pSetupData)115 static LPDEVMODEW SAL_DEVMODE_W( const ImplJobSetup* pSetupData )
116 {
117     LPDEVMODEW pRet = NULL;
118     SalDriverData* pDrv = (SalDriverData*)pSetupData->mpDriverData;
119     if( pDrv->mnVersion == SAL_DRIVERDATA_VERSION_W &&
120         pSetupData->mnDriverDataLen >= sizeof(DEVMODEW)+sizeof(SalDriverData)-1
121         )
122         pRet = ((LPDEVMODEW)((pSetupData->mpDriverData) + (pDrv->mnDriverOffset)));
123     return pRet;
124 }
125 
126 // =======================================================================
127 
ImplWinQueueStatusToSal(DWORD nWinStatus)128 static sal_uLong ImplWinQueueStatusToSal( DWORD nWinStatus )
129 {
130     sal_uLong nStatus = 0;
131     if ( nWinStatus & PRINTER_STATUS_PAUSED )
132         nStatus |= QUEUE_STATUS_PAUSED;
133     if ( nWinStatus & PRINTER_STATUS_ERROR )
134         nStatus |= QUEUE_STATUS_ERROR;
135     if ( nWinStatus & PRINTER_STATUS_PENDING_DELETION )
136         nStatus |= QUEUE_STATUS_PENDING_DELETION;
137     if ( nWinStatus & PRINTER_STATUS_PAPER_JAM )
138         nStatus |= QUEUE_STATUS_PAPER_JAM;
139     if ( nWinStatus & PRINTER_STATUS_PAPER_OUT )
140         nStatus |= QUEUE_STATUS_PAPER_OUT;
141     if ( nWinStatus & PRINTER_STATUS_MANUAL_FEED )
142         nStatus |= QUEUE_STATUS_MANUAL_FEED;
143     if ( nWinStatus & PRINTER_STATUS_PAPER_PROBLEM )
144         nStatus |= QUEUE_STATUS_PAPER_PROBLEM;
145     if ( nWinStatus & PRINTER_STATUS_OFFLINE )
146         nStatus |= QUEUE_STATUS_OFFLINE;
147     if ( nWinStatus & PRINTER_STATUS_IO_ACTIVE )
148         nStatus |= QUEUE_STATUS_IO_ACTIVE;
149     if ( nWinStatus & PRINTER_STATUS_BUSY )
150         nStatus |= QUEUE_STATUS_BUSY;
151     if ( nWinStatus & PRINTER_STATUS_PRINTING )
152         nStatus |= QUEUE_STATUS_PRINTING;
153     if ( nWinStatus & PRINTER_STATUS_OUTPUT_BIN_FULL )
154         nStatus |= QUEUE_STATUS_OUTPUT_BIN_FULL;
155     if ( nWinStatus & PRINTER_STATUS_WAITING )
156         nStatus |= QUEUE_STATUS_WAITING;
157     if ( nWinStatus & PRINTER_STATUS_PROCESSING )
158         nStatus |= QUEUE_STATUS_PROCESSING;
159     if ( nWinStatus & PRINTER_STATUS_INITIALIZING )
160         nStatus |= QUEUE_STATUS_INITIALIZING;
161     if ( nWinStatus & PRINTER_STATUS_WARMING_UP )
162         nStatus |= QUEUE_STATUS_WARMING_UP;
163     if ( nWinStatus & PRINTER_STATUS_TONER_LOW )
164         nStatus |= QUEUE_STATUS_TONER_LOW;
165     if ( nWinStatus & PRINTER_STATUS_NO_TONER )
166         nStatus |= QUEUE_STATUS_NO_TONER;
167     if ( nWinStatus & PRINTER_STATUS_PAGE_PUNT )
168         nStatus |= QUEUE_STATUS_PAGE_PUNT;
169     if ( nWinStatus & PRINTER_STATUS_USER_INTERVENTION )
170         nStatus |= QUEUE_STATUS_USER_INTERVENTION;
171     if ( nWinStatus & PRINTER_STATUS_OUT_OF_MEMORY )
172         nStatus |= QUEUE_STATUS_OUT_OF_MEMORY;
173     if ( nWinStatus & PRINTER_STATUS_DOOR_OPEN )
174         nStatus |= QUEUE_STATUS_DOOR_OPEN;
175     if ( nWinStatus & PRINTER_STATUS_SERVER_UNKNOWN )
176         nStatus |= QUEUE_STATUS_SERVER_UNKNOWN;
177     if ( nWinStatus & PRINTER_STATUS_POWER_SAVE )
178         nStatus |= QUEUE_STATUS_POWER_SAVE;
179     if ( !nStatus && !(nWinStatus & PRINTER_STATUS_NOT_AVAILABLE) )
180         nStatus |= QUEUE_STATUS_READY;
181     return nStatus;
182 }
183 
184 // -----------------------------------------------------------------------
185 
getPrinterQueueInfoOldStyle(ImplPrnQueueList * pList)186 static void getPrinterQueueInfoOldStyle( ImplPrnQueueList* pList )
187 {
188     DWORD           i;
189     DWORD           n;
190     DWORD           nBytes = 0;
191     DWORD           nInfoPrn2;
192     sal_Bool            bFound = FALSE;
193     PRINTER_INFO_2* pWinInfo2 = NULL;
194     PRINTER_INFO_2* pGetInfo2;
195     EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoPrn2 );
196     if ( nBytes )
197     {
198         pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
199         if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoPrn2 ) )
200         {
201             pGetInfo2 = pWinInfo2;
202             for ( i = 0; i < nInfoPrn2; i++ )
203             {
204                 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
205                 pInfo->maPrinterName = ImplSalGetUniString( pGetInfo2->pPrinterName );
206                 pInfo->maDriver      = ImplSalGetUniString( pGetInfo2->pDriverName );
207                 XubString aPortName;
208                 if ( pGetInfo2->pPortName )
209                     aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
210                 // pLocation can be 0 (the Windows docu doesn't describe this)
211                 if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
212                     pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
213                 else
214                     pInfo->maLocation = aPortName;
215                 // pComment can be 0 (the Windows docu doesn't describe this)
216                 if ( pGetInfo2->pComment )
217                     pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
218                 pInfo->mnStatus      = ImplWinQueueStatusToSal( pGetInfo2->Status );
219                 pInfo->mnJobs        = pGetInfo2->cJobs;
220                 pInfo->mpSysData     = new XubString( aPortName );
221                 pList->Add( pInfo );
222                 pGetInfo2++;
223             }
224 
225             bFound = TRUE;
226         }
227     }
228 
229     // read printers from win.ini
230     // TODO: MSDN: GetProfileString() should not be called from server
231     // code because it is just there for WIN16 compatibility
232     UINT    nSize = 4096;
233     char*   pBuf = new char[nSize];
234     UINT    nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
235     while ( nRead >= nSize-2 )
236     {
237         nSize += 2048;
238         delete []pBuf;
239         pBuf = new char[nSize];
240         nRead = GetProfileStringA( aImplDevices, NULL, "", pBuf, nSize );
241     }
242 
243     // extract printer names from buffer and fill list
244     char* pName = pBuf;
245     while ( *pName )
246     {
247         char*   pPortName;
248         char*   pTmp;
249         char    aPortBuf[256];
250         GetProfileStringA( aImplDevices, pName, "", aPortBuf, sizeof( aPortBuf ) );
251 
252         pPortName = aPortBuf;
253 
254         // create name
255         xub_StrLen nNameLen = sal::static_int_cast<xub_StrLen>(strlen( pName ));
256         XubString aName( ImplSalGetUniString( pName, nNameLen ) );
257 
258         // get driver name
259         pTmp = pPortName;
260         while ( *pTmp != ',' )
261             pTmp++;
262         XubString aDriver( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) );
263         pPortName = pTmp;
264 
265         // get port names
266         do
267         {
268             pPortName++;
269             pTmp = pPortName;
270             while ( *pTmp && (*pTmp != ',') )
271                 pTmp++;
272 
273             String aPortName( ImplSalGetUniString( pPortName, (sal_uInt16)(pTmp-pPortName) ) );
274 
275             // create new entry
276             // look up if printer was already found in first loop
277             sal_Bool bAdd = TRUE;
278             if ( pWinInfo2 )
279             {
280                 pGetInfo2 = pWinInfo2;
281                 for ( n = 0; n < nInfoPrn2; n++ )
282                 {
283                     if ( aName.EqualsIgnoreCaseAscii( pGetInfo2->pPrinterName ) )
284                     {
285                         bAdd = FALSE;
286                         break;
287                     }
288                     pGetInfo2++;
289                 }
290             }
291             // if it's a new printer, add it
292             if ( bAdd )
293             {
294                 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
295                 pInfo->maPrinterName = aName;
296                 pInfo->maDriver      = aDriver;
297                 pInfo->maLocation    = aPortName;
298                 pInfo->mnStatus      = 0;
299                 pInfo->mnJobs        = QUEUE_JOBS_DONTKNOW;
300                 pInfo->mpSysData     = new XubString( aPortName );
301                 pList->Add( pInfo );
302             }
303         }
304         while ( *pTmp == ',' );
305 
306         pName += nNameLen + 1;
307     }
308 
309     delete []pBuf;
310     rtl_freeMemory( pWinInfo2 );
311 }
312 
GetPrinterQueueInfo(ImplPrnQueueList * pList)313 void WinSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList )
314 {
315     if( ! aSalShlData.mbWPrinter )
316     {
317         getPrinterQueueInfoOldStyle( pList );
318         return;
319     }
320     DWORD           i;
321     DWORD           nBytes = 0;
322     DWORD           nInfoPrn4 = 0;
323     PRINTER_INFO_4W* pWinInfo4 = NULL;
324     EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &nBytes, &nInfoPrn4 );
325     if ( nBytes )
326     {
327         pWinInfo4 = (PRINTER_INFO_4W*) rtl_allocateMemory( nBytes );
328         if ( EnumPrintersW( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)pWinInfo4, nBytes, &nBytes, &nInfoPrn4 ) )
329         {
330             for ( i = 0; i < nInfoPrn4; i++ )
331             {
332                 SalPrinterQueueInfo* pInfo = new SalPrinterQueueInfo;
333                 pInfo->maPrinterName = UniString( reinterpret_cast< const sal_Unicode* >(pWinInfo4[i].pPrinterName) );
334                 pInfo->mnStatus      = 0;
335                 pInfo->mnJobs        = 0;
336                 pInfo->mpSysData     = NULL;
337                 pList->Add( pInfo );
338             }
339         }
340         rtl_freeMemory( pWinInfo4 );
341     }
342 }
343 
344 // -----------------------------------------------------------------------
345 
getPrinterQueueStateOldStyle(SalPrinterQueueInfo * pInfo)346 static void getPrinterQueueStateOldStyle( SalPrinterQueueInfo* pInfo )
347 {
348     DWORD               nBytes = 0;
349     DWORD               nInfoRet;
350     PRINTER_INFO_2*     pWinInfo2;
351     EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &nBytes, &nInfoRet );
352     if ( nBytes )
353     {
354         pWinInfo2 = (PRINTER_INFO_2*) rtl_allocateMemory( nBytes );
355         if ( EnumPrintersA( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes, &nInfoRet ) )
356         {
357             PRINTER_INFO_2* pGetInfo2 = pWinInfo2;
358             for ( DWORD i = 0; i < nInfoRet; i++ )
359             {
360                 if ( pInfo->maPrinterName.EqualsAscii( pGetInfo2->pPrinterName ) &&
361                      ( pInfo->maDriver.Len() == 0 ||
362                        pInfo->maDriver.EqualsAscii( pGetInfo2->pDriverName ) )
363                        )
364                 {
365                     XubString aPortName;
366                     if ( pGetInfo2->pPortName )
367                         aPortName = ImplSalGetUniString( pGetInfo2->pPortName );
368                     // pLocation can be 0 (the Windows docu doesn't describe this)
369                     if ( pGetInfo2->pLocation && strlen( pGetInfo2->pLocation ) )
370                         pInfo->maLocation = ImplSalGetUniString( pGetInfo2->pLocation );
371                     else
372                         pInfo->maLocation = aPortName;
373                     // pComment can be 0 (the Windows docu doesn't describe this)
374                     if ( pGetInfo2->pComment )
375                         pInfo->maComment = ImplSalGetUniString( pGetInfo2->pComment );
376                     pInfo->mnStatus      = ImplWinQueueStatusToSal( pGetInfo2->Status );
377                     pInfo->mnJobs        = pGetInfo2->cJobs;
378                     if( ! pInfo->mpSysData )
379                         pInfo->mpSysData     = new XubString( aPortName );
380                     break;
381                 }
382 
383                 pGetInfo2++;
384             }
385         }
386 
387         rtl_freeMemory( pWinInfo2 );
388     }
389 }
390 
GetPrinterQueueState(SalPrinterQueueInfo * pInfo)391 void WinSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* pInfo )
392 {
393     if( ! aSalShlData.mbWPrinter )
394     {
395         getPrinterQueueStateOldStyle( pInfo );
396         return;
397     }
398 
399     HANDLE hPrinter = 0;
400     LPWSTR pPrnName = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pInfo->maPrinterName.GetBuffer()));
401     if( OpenPrinterW( pPrnName, &hPrinter, NULL ) )
402     {
403         DWORD               nBytes = 0;
404         GetPrinterW( hPrinter, 2, NULL, 0, &nBytes );
405         if( nBytes )
406         {
407             PRINTER_INFO_2W* pWinInfo2 = (PRINTER_INFO_2W*)rtl_allocateMemory(nBytes);
408             if( GetPrinterW( hPrinter, 2, (LPBYTE)pWinInfo2, nBytes, &nBytes ) )
409             {
410                 if( pWinInfo2->pDriverName )
411                     pInfo->maDriver = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pDriverName) );
412                 XubString aPortName;
413                 if ( pWinInfo2->pPortName )
414                     aPortName = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pPortName) );
415                 // pLocation can be 0 (the Windows docu doesn't describe this)
416                 if ( pWinInfo2->pLocation && *pWinInfo2->pLocation )
417                     pInfo->maLocation = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pLocation) );
418                 else
419                     pInfo->maLocation = aPortName;
420                 // pComment can be 0 (the Windows docu doesn't describe this)
421                 if ( pWinInfo2->pComment )
422                     pInfo->maComment = String( reinterpret_cast< const sal_Unicode* >(pWinInfo2->pComment) );
423                 pInfo->mnStatus      = ImplWinQueueStatusToSal( pWinInfo2->Status );
424                 pInfo->mnJobs        = pWinInfo2->cJobs;
425                 if( ! pInfo->mpSysData )
426                     pInfo->mpSysData     = new XubString( aPortName );
427             }
428             rtl_freeMemory(pWinInfo2);
429         }
430         ClosePrinter( hPrinter );
431     }
432 }
433 
434 // -----------------------------------------------------------------------
435 
DeletePrinterQueueInfo(SalPrinterQueueInfo * pInfo)436 void WinSalInstance::DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo )
437 {
438     delete (String*)(pInfo->mpSysData);
439     delete pInfo;
440 }
441 
442 // -----------------------------------------------------------------------
GetDefaultPrinter()443 XubString WinSalInstance::GetDefaultPrinter()
444 {
445     static bool bGetDefPrtAPI = true;
446     static sal_Bool(WINAPI*pGetDefaultPrinter)(LPWSTR,LPDWORD) = NULL;
447     // try to use GetDefaultPrinter API (not available prior to W2000)
448     if( bGetDefPrtAPI )
449     {
450         bGetDefPrtAPI = false;
451         // check for W2k and XP
452         if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && aSalShlData.maVersionInfo.dwMajorVersion >= 5 )
453         {
454             oslModule pLib = osl_loadAsciiModule( "winspool.drv", SAL_LOADMODULE_DEFAULT );
455             oslGenericFunction pFunc = NULL;
456             if( pLib )
457                 pFunc = osl_getAsciiFunctionSymbol( pLib, "GetDefaultPrinterW" );
458 
459             pGetDefaultPrinter = (sal_Bool(WINAPI*)(LPWSTR,LPDWORD)) pFunc;
460         }
461     }
462     if( pGetDefaultPrinter )
463     {
464         DWORD   nChars = 0;
465         pGetDefaultPrinter( NULL, &nChars );
466         if( nChars )
467         {
468             LPWSTR  pStr = (LPWSTR)rtl_allocateMemory(nChars*sizeof(WCHAR));
469             XubString aDefPrt;
470             if( pGetDefaultPrinter( pStr, &nChars ) )
471             {
472                 aDefPrt = reinterpret_cast<sal_Unicode* >(pStr);
473             }
474             rtl_freeMemory( pStr );
475             if( aDefPrt.Len() )
476                 return aDefPrt;
477         }
478     }
479 
480     // get default printer from win.ini
481     char szBuffer[256];
482     GetProfileStringA( aImplWindows, aImplDevice, "", szBuffer, sizeof( szBuffer ) );
483     if ( szBuffer[0] )
484     {
485         // Printername suchen
486         char* pBuf = szBuffer;
487         char* pTmp = pBuf;
488         while ( *pTmp && (*pTmp != ',') )
489             pTmp++;
490         return ImplSalGetUniString( pBuf, (xub_StrLen)(pTmp-pBuf) );
491     }
492     else
493         return XubString();
494 }
495 
496 // =======================================================================
497 
ImplDeviceCaps(WinSalInfoPrinter * pPrinter,WORD nCaps,BYTE * pOutput,const ImplJobSetup * pSetupData)498 static DWORD ImplDeviceCaps( WinSalInfoPrinter* pPrinter, WORD nCaps,
499                              BYTE* pOutput, const ImplJobSetup* pSetupData )
500 {
501     if( aSalShlData.mbWPrinter )
502     {
503         DEVMODEW* pDevMode;
504         if ( !pSetupData || !pSetupData->mpDriverData )
505             pDevMode = NULL;
506         else
507             pDevMode = SAL_DEVMODE_W( pSetupData );
508 
509         return DeviceCapabilitiesW( reinterpret_cast<LPCWSTR>(pPrinter->maDeviceName.GetBuffer()),
510                                     reinterpret_cast<LPCWSTR>(pPrinter->maPortName.GetBuffer()),
511                                     nCaps, (LPWSTR)pOutput, pDevMode );
512     }
513     else
514     {
515         DEVMODEA* pDevMode;
516         if ( !pSetupData || !pSetupData->mpDriverData )
517             pDevMode = NULL;
518         else
519             pDevMode = SAL_DEVMODE_A( pSetupData );
520 
521         return DeviceCapabilitiesA( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
522                                 ImplSalGetWinAnsiString( pPrinter->maPortName, TRUE ).GetBuffer(),
523                                 nCaps, (LPSTR)pOutput, pDevMode );
524     }
525 }
526 
527 // -----------------------------------------------------------------------
528 
ImplTestSalJobSetup(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData,sal_Bool bDelete)529 static sal_Bool ImplTestSalJobSetup( WinSalInfoPrinter* pPrinter,
530                                  ImplJobSetup* pSetupData, sal_Bool bDelete )
531 {
532     if ( pSetupData && pSetupData->mpDriverData )
533     {
534         // signature and size must fit to avoid using
535         // JobSetups from a wrong system
536 
537         // initialize versions from jobsetup
538         // those will be overwritten with driver's version
539         DEVMODEA* pDevModeA = NULL;
540         DEVMODEW* pDevModeW = NULL;
541         LONG dmSpecVersion = -1;
542         LONG dmDriverVersion = -1;
543         SalDriverData* pSalDriverData = (SalDriverData*)pSetupData->mpDriverData;
544         BYTE* pDriverData = ((BYTE*)pSalDriverData) + pSalDriverData->mnDriverOffset;
545         if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_W )
546         {
547             if( aSalShlData.mbWPrinter )
548                 pDevModeW = (DEVMODEW*)pDriverData;
549         }
550         else if( pSalDriverData->mnVersion == SAL_DRIVERDATA_VERSION_A )
551         {
552             if( ! aSalShlData.mbWPrinter )
553                 pDevModeA = (DEVMODEA*)pDriverData;
554         }
555 
556         long nSysJobSize = -1;
557         if( pPrinter && ( pDevModeA || pDevModeW ) )
558         {
559             // just too many driver crashes in that area -> check the dmSpecVersion and dmDriverVersion fields always !!!
560             // this prevents using the jobsetup between different Windows versions (eg from XP to 9x) but we
561             // can avoid potential driver crashes as their jobsetups are often not compatible
562             // #110800#, #111151#, #112381#, #i16580#, #i14173# and perhaps #112375#
563             ByteString aPrinterNameA= ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
564             HANDLE hPrn;
565             LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
566             if ( ! aSalShlData.mbWPrinter )
567             {
568                 if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
569                     return FALSE;
570             }
571             else
572                 if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
573                     return FALSE;
574 
575             // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
576             if( hPrn == HGDI_ERROR )
577                 return FALSE;
578 
579             if( aSalShlData.mbWPrinter )
580             {
581                 nSysJobSize = DocumentPropertiesW( 0, hPrn,
582                                                    pPrinterNameW,
583                                                    NULL, NULL, 0 );
584             }
585             else
586             {
587                 nSysJobSize = DocumentPropertiesA( 0, hPrn,
588                                                    (LPSTR)aPrinterNameA.GetBuffer(),
589                                                    NULL, NULL, 0 );
590             }
591 
592             if( nSysJobSize < 0 )
593             {
594                 ClosePrinter( hPrn );
595                 return FALSE;
596             }
597             BYTE *pBuffer = (BYTE*)_alloca( nSysJobSize );
598             LONG nRet = -1;
599             if( aSalShlData.mbWPrinter )
600             {
601                 nRet = DocumentPropertiesW( 0, hPrn,
602                                             pPrinterNameW,
603                                             (LPDEVMODEW)pBuffer, NULL, DM_OUT_BUFFER );
604             }
605             else
606             {
607                 nRet = DocumentPropertiesA( 0, hPrn,
608                                             (LPSTR)aPrinterNameA.GetBuffer(),
609                                             (LPDEVMODEA)pBuffer, NULL, DM_OUT_BUFFER );
610             }
611             if( nRet < 0 )
612             {
613                 ClosePrinter( hPrn );
614                 return FALSE;
615             }
616 
617             // the spec version differs between the windows platforms, ie 98,NT,2000/XP
618             // this allows us to throw away printer settings from other platforms that might crash a buggy driver
619             // we check the driver version as well
620             dmSpecVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmSpecVersion : ((DEVMODEA*)pBuffer)->dmSpecVersion;
621             dmDriverVersion = aSalShlData.mbWPrinter ? ((DEVMODEW*)pBuffer)->dmDriverVersion : ((DEVMODEA*)pBuffer)->dmDriverVersion;
622 
623             ClosePrinter( hPrn );
624         }
625         SalDriverData* pSetupDriverData = (SalDriverData*)(pSetupData->mpDriverData);
626         if ( (pSetupData->mnSystem == JOBSETUP_SYSTEM_WINDOWS) &&
627              (pPrinter->maDriverName == pSetupData->maDriver) &&
628              (pSetupData->mnDriverDataLen > sizeof( SalDriverData )) &&
629              (long)(pSetupData->mnDriverDataLen - pSetupDriverData->mnDriverOffset) == nSysJobSize &&
630              pSetupDriverData->mnSysSignature == SAL_DRIVERDATA_SYSSIGN )
631         {
632             if( pDevModeA &&
633                 (dmSpecVersion == pDevModeA->dmSpecVersion) &&
634                 (dmDriverVersion == pDevModeA->dmDriverVersion) )
635                 return TRUE;
636             if( pDevModeW &&
637                 (dmSpecVersion == pDevModeW->dmSpecVersion) &&
638                 (dmDriverVersion == pDevModeW->dmDriverVersion) )
639                 return TRUE;
640         }
641         if ( bDelete )
642         {
643             rtl_freeMemory( pSetupData->mpDriverData );
644             pSetupData->mpDriverData = NULL;
645             pSetupData->mnDriverDataLen = 0;
646         }
647     }
648 
649     return FALSE;
650 }
651 
652 // -----------------------------------------------------------------------
653 
ImplUpdateSalJobSetup(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData,sal_Bool bIn,WinSalFrame * pVisibleDlgParent)654 static sal_Bool ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData,
655                                    sal_Bool bIn, WinSalFrame* pVisibleDlgParent )
656 {
657     ByteString aPrinterNameA = ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE );
658     HANDLE hPrn;
659     LPWSTR pPrinterNameW = reinterpret_cast<LPWSTR>(const_cast<sal_Unicode*>(pPrinter->maDeviceName.GetBuffer()));
660     if( aSalShlData.mbWPrinter )
661     {
662         if ( !OpenPrinterW( pPrinterNameW, &hPrn, NULL ) )
663             return FALSE;
664     }
665     else
666     {
667         if ( !OpenPrinterA( (LPSTR)aPrinterNameA.GetBuffer(), &hPrn, NULL ) )
668             return FALSE;
669     }
670     // #131642# hPrn==HGDI_ERROR even though OpenPrinter() succeeded!
671     if( hPrn == HGDI_ERROR )
672         return FALSE;
673 
674     LONG            nRet;
675     LONG            nSysJobSize = -1;
676     HWND            hWnd = 0;
677     DWORD           nMode = DM_OUT_BUFFER;
678     sal_uLong           nDriverDataLen = 0;
679     SalDriverData*  pOutBuffer = NULL;
680     BYTE*           pInBuffer = NULL;
681 
682     if( aSalShlData.mbWPrinter )
683     {
684         nSysJobSize = DocumentPropertiesW( hWnd, hPrn,
685                                            pPrinterNameW,
686                                            NULL, NULL, 0 );
687     }
688     else
689         nSysJobSize = DocumentPropertiesA( hWnd, hPrn,
690                                            (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
691                                            NULL, NULL, 0 );
692     if ( nSysJobSize < 0 )
693     {
694         ClosePrinter( hPrn );
695         return FALSE;
696     }
697 
698     // Outputbuffer anlegen
699     nDriverDataLen              = sizeof(SalDriverData) + nSysJobSize-1;
700     pOutBuffer                  = (SalDriverData*)rtl_allocateZeroMemory( nDriverDataLen );
701     pOutBuffer->mnSysSignature  = SAL_DRIVERDATA_SYSSIGN;
702     pOutBuffer->mnVersion       = aSalShlData.mbWPrinter ? SAL_DRIVERDATA_VERSION_W : SAL_DRIVERDATA_VERSION_A;
703     // calculate driver data offset including structure padding
704     pOutBuffer->mnDriverOffset  = sal::static_int_cast<sal_uInt16>(
705                                     (char*)pOutBuffer->maDriverData -
706                                     (char*)pOutBuffer );
707 
708     // Testen, ob wir einen geeigneten Inputbuffer haben
709     if ( bIn && ImplTestSalJobSetup( pPrinter, pSetupData, FALSE ) )
710     {
711         pInBuffer = (BYTE*)pSetupData->mpDriverData + ((SalDriverData*)pSetupData->mpDriverData)->mnDriverOffset;
712         nMode |= DM_IN_BUFFER;
713     }
714 
715     // Testen, ob Dialog angezeigt werden soll
716     if ( pVisibleDlgParent )
717     {
718         hWnd = pVisibleDlgParent->mhWnd;
719         nMode |= DM_IN_PROMPT;
720     }
721 
722     // Release mutex, in the other case we don't get paints and so on
723     sal_uLong nMutexCount=0;
724     if ( pVisibleDlgParent )
725         nMutexCount = ImplSalReleaseYieldMutex();
726 
727     BYTE* pOutDevMode = (((BYTE*)pOutBuffer) + pOutBuffer->mnDriverOffset);
728     if( aSalShlData.mbWPrinter )
729     {
730         nRet = DocumentPropertiesW( hWnd, hPrn,
731                                     pPrinterNameW,
732                                     (LPDEVMODEW)pOutDevMode, (LPDEVMODEW)pInBuffer, nMode );
733     }
734     else
735     {
736         nRet = DocumentPropertiesA( hWnd, hPrn,
737                                     (LPSTR)ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ).GetBuffer(),
738                                     (LPDEVMODEA)pOutDevMode, (LPDEVMODEA)pInBuffer, nMode );
739     }
740     if ( pVisibleDlgParent )
741         ImplSalAcquireYieldMutex( nMutexCount );
742     ClosePrinter( hPrn );
743 
744     if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) )
745     {
746         rtl_freeMemory( pOutBuffer );
747         return FALSE;
748     }
749 
750     // fill up string buffers with 0 so they do not influence a JobSetup's memcmp
751     if( aSalShlData.mbWPrinter )
752     {
753         if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 64 )
754         {
755             sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmDeviceName );
756             if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )/sizeof(sal_Unicode) )
757                 memset( ((LPDEVMODEW)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmDeviceName )-(nLen*sizeof(sal_Unicode)) );
758         }
759         if( ((LPDEVMODEW)pOutDevMode)->dmSize >= 166 )
760         {
761             sal_Int32 nLen = rtl_ustr_getLength( (const sal_Unicode*)((LPDEVMODEW)pOutDevMode)->dmFormName );
762             if ( nLen < sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )/sizeof(sal_Unicode) )
763                 memset( ((LPDEVMODEW)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEW)pOutDevMode)->dmFormName )-(nLen*sizeof(sal_Unicode)) );
764         }
765     }
766     else
767     {
768         if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 32 )
769         {
770             sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmDeviceName );
771             if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName ) )
772                 memset( ((LPDEVMODEA)pOutDevMode)->dmDeviceName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmDeviceName )-nLen );
773         }
774         if( ((LPDEVMODEA)pOutDevMode)->dmSize >= 102 )
775         {
776             sal_Int32 nLen = strlen( (const char*)((LPDEVMODEA)pOutDevMode)->dmFormName );
777             if ( nLen < sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName ) )
778                 memset( ((LPDEVMODEA)pOutDevMode)->dmFormName+nLen, 0, sizeof( ((LPDEVMODEA)pOutDevMode)->dmFormName )-nLen );
779         }
780     }
781 
782     // update data
783     if ( pSetupData->mpDriverData )
784         rtl_freeMemory( pSetupData->mpDriverData );
785     pSetupData->mnDriverDataLen = nDriverDataLen;
786     pSetupData->mpDriverData    = (BYTE*)pOutBuffer;
787     pSetupData->mnSystem        = JOBSETUP_SYSTEM_WINDOWS;
788 
789     return TRUE;
790 }
791 
792 // -----------------------------------------------------------------------
793 
794 #define DECLARE_DEVMODE( i )\
795     DEVMODEA* pDevModeA = SAL_DEVMODE_A(i);\
796     DEVMODEW* pDevModeW = SAL_DEVMODE_W(i);\
797     if( pDevModeA == NULL && pDevModeW == NULL )\
798         return
799 
800 #define CHOOSE_DEVMODE(i)\
801     (pDevModeW ? pDevModeW->i : pDevModeA->i)
802 
ImplDevModeToJobSetup(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData,sal_uLong nFlags)803 static void ImplDevModeToJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags )
804 {
805     if ( !pSetupData || !pSetupData->mpDriverData )
806         return;
807 
808     DECLARE_DEVMODE( pSetupData );
809 
810     // Orientation
811     if ( nFlags & SAL_JOBSET_ORIENTATION )
812     {
813         if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_PORTRAIT )
814             pSetupData->meOrientation = ORIENTATION_PORTRAIT;
815         else if ( CHOOSE_DEVMODE(dmOrientation) == DMORIENT_LANDSCAPE )
816             pSetupData->meOrientation = ORIENTATION_LANDSCAPE;
817     }
818 
819     // PaperBin
820     if ( nFlags & SAL_JOBSET_PAPERBIN )
821     {
822         sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
823 
824         if ( nCount && (nCount != GDI_ERROR) )
825         {
826             WORD* pBins = (WORD*)rtl_allocateZeroMemory( nCount*sizeof(WORD) );
827             ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
828             pSetupData->mnPaperBin = 0;
829 
830             // search the right bin and assign index to mnPaperBin
831             for( sal_uLong i = 0; i < nCount; i++ )
832             {
833                 if( CHOOSE_DEVMODE(dmDefaultSource) == pBins[ i ] )
834                 {
835                     pSetupData->mnPaperBin = (sal_uInt16)i;
836                     break;
837                 }
838             }
839 
840             rtl_freeMemory( pBins );
841         }
842     }
843 
844     // PaperSize
845     if ( nFlags & SAL_JOBSET_PAPERSIZE )
846     {
847         if( (CHOOSE_DEVMODE(dmFields) & (DM_PAPERWIDTH|DM_PAPERLENGTH)) == (DM_PAPERWIDTH|DM_PAPERLENGTH) )
848         {
849             pSetupData->mnPaperWidth  = CHOOSE_DEVMODE(dmPaperWidth)*10;
850             pSetupData->mnPaperHeight = CHOOSE_DEVMODE(dmPaperLength)*10;
851         }
852         else
853         {
854             sal_uLong   nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
855             WORD*   pPapers = NULL;
856             sal_uLong   nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
857             POINT*  pPaperSizes = NULL;
858             if ( nPaperCount && (nPaperCount != GDI_ERROR) )
859             {
860                 pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
861                 ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
862             }
863             if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
864             {
865                 pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
866                 ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
867             }
868             if( nPaperSizeCount == nPaperCount && pPaperSizes && pPapers )
869             {
870                 for( sal_uLong i = 0; i < nPaperCount; i++ )
871                 {
872                     if( pPapers[ i ] == CHOOSE_DEVMODE(dmPaperSize) )
873                     {
874                         pSetupData->mnPaperWidth  = pPaperSizes[ i ].x*10;
875                         pSetupData->mnPaperHeight = pPaperSizes[ i ].y*10;
876                         break;
877                     }
878                 }
879             }
880             if( pPapers )
881                 rtl_freeMemory( pPapers );
882             if( pPaperSizes )
883                 rtl_freeMemory( pPaperSizes );
884         }
885         switch( CHOOSE_DEVMODE(dmPaperSize) )
886         {
887             case( DMPAPER_LETTER ):
888                 pSetupData->mePaperFormat = PAPER_LETTER;
889                 break;
890             case( DMPAPER_TABLOID ):
891                 pSetupData->mePaperFormat = PAPER_TABLOID;
892                 break;
893             case( DMPAPER_LEDGER ):
894                 pSetupData->mePaperFormat = PAPER_LEDGER;
895                 break;
896             case( DMPAPER_LEGAL ):
897                 pSetupData->mePaperFormat = PAPER_LEGAL;
898                 break;
899             case( DMPAPER_STATEMENT ):
900                 pSetupData->mePaperFormat = PAPER_STATEMENT;
901                 break;
902             case( DMPAPER_EXECUTIVE ):
903                 pSetupData->mePaperFormat = PAPER_EXECUTIVE;
904                 break;
905             case( DMPAPER_A3 ):
906                 pSetupData->mePaperFormat = PAPER_A3;
907                 break;
908             case( DMPAPER_A4 ):
909                 pSetupData->mePaperFormat = PAPER_A4;
910                 break;
911             case( DMPAPER_A5 ):
912                 pSetupData->mePaperFormat = PAPER_A5;
913                 break;
914             //See http://wiki.services.openoffice.org/wiki/DefaultPaperSize
915             //i.e.
916             //http://msdn.microsoft.com/en-us/library/dd319099(VS.85).aspx
917             //DMPAPER_B4    12  B4 (JIS) 257 x 364 mm
918             //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf
919             //also says that the MS DMPAPER_B4 is JIS, which makes most sense. And
920             //matches our Excel filter's belief about the matching XlPaperSize
921             //enumeration.
922             //
923             //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx said
924             ////"DMPAPER_B4     12  B4 (JIS) 250 x 354"
925             //which is bogus as it's either JIS 257 × 364 or ISO 250 × 353
926             //(cmc)
927             case( DMPAPER_B4 ):
928                 pSetupData->mePaperFormat = PAPER_B4_JIS;
929                 break;
930             case( DMPAPER_B5 ):
931                 pSetupData->mePaperFormat = PAPER_B5_JIS;
932                 break;
933             case( DMPAPER_QUARTO ):
934                 pSetupData->mePaperFormat = PAPER_QUARTO;
935                 break;
936             case( DMPAPER_10X14 ):
937                 pSetupData->mePaperFormat = PAPER_10x14;
938                 break;
939             case( DMPAPER_NOTE ):
940                 pSetupData->mePaperFormat = PAPER_LETTER;
941                 break;
942             case( DMPAPER_ENV_9 ):
943                 pSetupData->mePaperFormat = PAPER_ENV_9;
944                 break;
945             case( DMPAPER_ENV_10 ):
946                 pSetupData->mePaperFormat = PAPER_ENV_10;
947                 break;
948             case( DMPAPER_ENV_11 ):
949                 pSetupData->mePaperFormat = PAPER_ENV_11;
950                 break;
951             case( DMPAPER_ENV_12 ):
952                 pSetupData->mePaperFormat = PAPER_ENV_12;
953                 break;
954             case( DMPAPER_ENV_14 ):
955                 pSetupData->mePaperFormat = PAPER_ENV_14;
956                 break;
957             case( DMPAPER_CSHEET ):
958                 pSetupData->mePaperFormat = PAPER_C;
959                 break;
960             case( DMPAPER_DSHEET ):
961                 pSetupData->mePaperFormat = PAPER_D;
962                 break;
963             case( DMPAPER_ESHEET ):
964                 pSetupData->mePaperFormat = PAPER_E;
965                 break;
966             case( DMPAPER_ENV_DL):
967                 pSetupData->mePaperFormat = PAPER_ENV_DL;
968                 break;
969             case( DMPAPER_ENV_C5):
970                 pSetupData->mePaperFormat = PAPER_ENV_C5;
971                 break;
972             case( DMPAPER_ENV_C3):
973                 pSetupData->mePaperFormat = PAPER_ENV_C3;
974                 break;
975             case( DMPAPER_ENV_C4):
976                 pSetupData->mePaperFormat = PAPER_ENV_C4;
977                 break;
978             case( DMPAPER_ENV_C6):
979                 pSetupData->mePaperFormat = PAPER_ENV_C6;
980                 break;
981             case( DMPAPER_ENV_C65):
982                 pSetupData->mePaperFormat = PAPER_ENV_C65;
983                 break;
984             case( DMPAPER_ENV_ITALY ):
985                 pSetupData->mePaperFormat = PAPER_ENV_ITALY;
986                 break;
987             case( DMPAPER_ENV_MONARCH ):
988                 pSetupData->mePaperFormat = PAPER_ENV_MONARCH;
989                 break;
990             case( DMPAPER_ENV_PERSONAL ):
991                 pSetupData->mePaperFormat = PAPER_ENV_PERSONAL;
992                 break;
993             case( DMPAPER_FANFOLD_US ):
994                 pSetupData->mePaperFormat = PAPER_FANFOLD_US;
995                 break;
996             case( DMPAPER_FANFOLD_STD_GERMAN ):
997                 pSetupData->mePaperFormat = PAPER_FANFOLD_DE;
998                 break;
999             case( DMPAPER_FANFOLD_LGL_GERMAN ):
1000                 pSetupData->mePaperFormat = PAPER_FANFOLD_LEGAL_DE;
1001                 break;
1002             case( DMPAPER_ISO_B4 ):
1003                 pSetupData->mePaperFormat = PAPER_B4_ISO;
1004                 break;
1005             case( DMPAPER_JAPANESE_POSTCARD ):
1006                 pSetupData->mePaperFormat = PAPER_POSTCARD_JP;
1007                 break;
1008             case( DMPAPER_9X11 ):
1009                 pSetupData->mePaperFormat = PAPER_9x11;
1010                 break;
1011             case( DMPAPER_10X11 ):
1012                 pSetupData->mePaperFormat = PAPER_10x11;
1013                 break;
1014             case( DMPAPER_15X11 ):
1015                 pSetupData->mePaperFormat = PAPER_15x11;
1016                 break;
1017             case( DMPAPER_ENV_INVITE ):
1018                 pSetupData->mePaperFormat = PAPER_ENV_INVITE;
1019                 break;
1020             case( DMPAPER_A_PLUS ):
1021                 pSetupData->mePaperFormat = PAPER_A_PLUS;
1022                 break;
1023             case( DMPAPER_B_PLUS ):
1024                 pSetupData->mePaperFormat = PAPER_B_PLUS;
1025                 break;
1026             case( DMPAPER_LETTER_PLUS ):
1027                 pSetupData->mePaperFormat = PAPER_LETTER_PLUS;
1028                 break;
1029             case( DMPAPER_A4_PLUS ):
1030                 pSetupData->mePaperFormat = PAPER_A4_PLUS;
1031                 break;
1032             case( DMPAPER_A2 ):
1033                 pSetupData->mePaperFormat = PAPER_A2;
1034                 break;
1035             case( DMPAPER_DBL_JAPANESE_POSTCARD ):
1036                 pSetupData->mePaperFormat = PAPER_DOUBLEPOSTCARD_JP;
1037                 break;
1038             case( DMPAPER_A6 ):
1039                 pSetupData->mePaperFormat = PAPER_A6;
1040                 break;
1041             case( DMPAPER_B6_JIS ):
1042                 pSetupData->mePaperFormat = PAPER_B6_JIS;
1043                 break;
1044             case( DMPAPER_12X11 ):
1045                 pSetupData->mePaperFormat = PAPER_12x11;
1046                 break;
1047             default:
1048                 pSetupData->mePaperFormat = PAPER_USER;
1049                 break;
1050         }
1051     }
1052 
1053     if( nFlags & SAL_JOBSET_DUPLEXMODE )
1054     {
1055         DuplexMode eDuplex = DUPLEX_UNKNOWN;
1056         if( (CHOOSE_DEVMODE(dmFields) & DM_DUPLEX) )
1057         {
1058             if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_SIMPLEX )
1059                 eDuplex = DUPLEX_OFF;
1060             else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_VERTICAL )
1061                 eDuplex = DUPLEX_LONGEDGE;
1062             else if( CHOOSE_DEVMODE(dmDuplex) == DMDUP_HORIZONTAL )
1063                 eDuplex = DUPLEX_SHORTEDGE;
1064         }
1065         pSetupData->meDuplexMode = eDuplex;
1066     }
1067 }
1068 
1069 // -----------------------------------------------------------------------
1070 
ImplJobSetupToDevMode(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData,sal_uLong nFlags)1071 static void ImplJobSetupToDevMode( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData, sal_uLong nFlags )
1072 {
1073     if ( !pSetupData || !pSetupData->mpDriverData )
1074         return;
1075 
1076     DECLARE_DEVMODE( pSetupData );
1077 
1078     // Orientation
1079     if ( nFlags & SAL_JOBSET_ORIENTATION )
1080     {
1081         CHOOSE_DEVMODE(dmFields) |= DM_ORIENTATION;
1082         if ( pSetupData->meOrientation == ORIENTATION_PORTRAIT )
1083             CHOOSE_DEVMODE(dmOrientation) = DMORIENT_PORTRAIT;
1084         else
1085             CHOOSE_DEVMODE(dmOrientation) = DMORIENT_LANDSCAPE;
1086     }
1087 
1088     // PaperBin
1089     if ( nFlags & SAL_JOBSET_PAPERBIN )
1090     {
1091         sal_uLong nCount = ImplDeviceCaps( pPrinter, DC_BINS, NULL, pSetupData );
1092 
1093         if ( nCount && (nCount != GDI_ERROR) )
1094         {
1095             WORD* pBins = (WORD*)rtl_allocateZeroMemory(nCount*sizeof(WORD));
1096             ImplDeviceCaps( pPrinter, DC_BINS, (BYTE*)pBins, pSetupData );
1097             CHOOSE_DEVMODE(dmFields) |= DM_DEFAULTSOURCE;
1098             CHOOSE_DEVMODE(dmDefaultSource) = pBins[ pSetupData->mnPaperBin ];
1099             rtl_freeMemory( pBins );
1100         }
1101     }
1102 
1103     // PaperSize
1104     if ( nFlags & SAL_JOBSET_PAPERSIZE )
1105     {
1106         CHOOSE_DEVMODE(dmFields)        |= DM_PAPERSIZE;
1107         CHOOSE_DEVMODE(dmPaperWidth)     = 0;
1108         CHOOSE_DEVMODE(dmPaperLength)    = 0;
1109 
1110         switch( pSetupData->mePaperFormat )
1111         {
1112             case( PAPER_A2 ):
1113                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A2;
1114                 break;
1115             case( PAPER_A3 ):
1116                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A3;
1117                 break;
1118             case( PAPER_A4 ):
1119                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4;
1120                 break;
1121             case( PAPER_A5 ):
1122                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A5;
1123                 break;
1124             case( PAPER_B4_ISO):
1125                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ISO_B4;
1126                 break;
1127             case( PAPER_LETTER ):
1128                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER;
1129                 break;
1130             case( PAPER_LEGAL ):
1131                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEGAL;
1132                 break;
1133             case( PAPER_TABLOID ):
1134                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_TABLOID;
1135                 break;
1136 #if 0
1137             //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx
1138             //DMPAPER_ENV_B6 is documented as:
1139             //"DMPAPER_ENV_B6   35  Envelope B6 176 x 125 mm"
1140             //which is the wrong way around, it is surely 125 x 176, i.e.
1141             //compare DMPAPER_ENV_B4 and DMPAPER_ENV_B4 as
1142             //DMPAPER_ENV_B4    33  Envelope B4 250 x 353 mm
1143             //DMPAPER_ENV_B5    34  Envelope B5 176 x 250 mm
1144             case( PAPER_B6_ISO ):
1145                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_B6;
1146                 break;
1147 #endif
1148             case( PAPER_ENV_C4 ):
1149                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C4;
1150                 break;
1151             case( PAPER_ENV_C5 ):
1152                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C5;
1153                 break;
1154             case( PAPER_ENV_C6 ):
1155                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C6;
1156                 break;
1157             case( PAPER_ENV_C65 ):
1158                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C65;
1159                 break;
1160             case( PAPER_ENV_DL ):
1161                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_DL;
1162                 break;
1163             case( PAPER_C ):
1164                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_CSHEET;
1165                 break;
1166             case( PAPER_D ):
1167                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DSHEET;
1168                 break;
1169             case( PAPER_E ):
1170                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ESHEET;
1171                 break;
1172             case( PAPER_EXECUTIVE ):
1173                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_EXECUTIVE;
1174                 break;
1175             case( PAPER_FANFOLD_LEGAL_DE ):
1176                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_LGL_GERMAN;
1177                 break;
1178             case( PAPER_ENV_MONARCH ):
1179                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_MONARCH;
1180                 break;
1181             case( PAPER_ENV_PERSONAL ):
1182                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_PERSONAL;
1183                 break;
1184             case( PAPER_ENV_9 ):
1185                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_9;
1186                 break;
1187             case( PAPER_ENV_10 ):
1188                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_10;
1189                 break;
1190             case( PAPER_ENV_11 ):
1191                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_11;
1192                 break;
1193             case( PAPER_ENV_12 ):
1194                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_12;
1195                 break;
1196             //See the comments on DMPAPER_B4 above
1197             case( PAPER_B4_JIS ):
1198                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B4;
1199                 break;
1200             case( PAPER_B5_JIS ):
1201                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B5;
1202                 break;
1203             case( PAPER_B6_JIS ):
1204                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B6_JIS;
1205                 break;
1206             case( PAPER_LEDGER ):
1207                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LEDGER;
1208                 break;
1209             case( PAPER_STATEMENT ):
1210                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_STATEMENT;
1211                 break;
1212             case( PAPER_10x14 ):
1213                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X14;
1214                 break;
1215             case( PAPER_ENV_14 ):
1216                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_14;
1217                 break;
1218             case( PAPER_ENV_C3 ):
1219                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_C3;
1220                 break;
1221             case( PAPER_ENV_ITALY ):
1222                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_ITALY;
1223                 break;
1224             case( PAPER_FANFOLD_US ):
1225                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_US;
1226                 break;
1227             case( PAPER_FANFOLD_DE ):
1228                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_FANFOLD_STD_GERMAN;
1229                 break;
1230             case( PAPER_POSTCARD_JP ):
1231                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_JAPANESE_POSTCARD;
1232                 break;
1233             case( PAPER_9x11 ):
1234                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_9X11;
1235                 break;
1236             case( PAPER_10x11 ):
1237                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_10X11;
1238                 break;
1239             case( PAPER_15x11 ):
1240                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_15X11;
1241                 break;
1242             case( PAPER_ENV_INVITE ):
1243                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_ENV_INVITE;
1244                 break;
1245             case( PAPER_A_PLUS ):
1246                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A_PLUS;
1247                 break;
1248             case( PAPER_B_PLUS ):
1249                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_B_PLUS;
1250                 break;
1251             case( PAPER_LETTER_PLUS ):
1252                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_LETTER_PLUS;
1253                 break;
1254             case( PAPER_A4_PLUS ):
1255                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A4_PLUS;
1256                 break;
1257             case( PAPER_DOUBLEPOSTCARD_JP ):
1258                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_DBL_JAPANESE_POSTCARD;
1259                 break;
1260             case( PAPER_A6 ):
1261                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_A6;
1262                 break;
1263             case( PAPER_12x11 ):
1264                 CHOOSE_DEVMODE(dmPaperSize) = DMPAPER_12X11;
1265                 break;
1266             default:
1267             {
1268                 short   nPaper = 0;
1269                 sal_uLong   nPaperCount = ImplDeviceCaps( pPrinter, DC_PAPERS, NULL, pSetupData );
1270                 WORD*   pPapers = NULL;
1271                 sal_uLong   nPaperSizeCount = ImplDeviceCaps( pPrinter, DC_PAPERSIZE, NULL, pSetupData );
1272                 POINT*  pPaperSizes = NULL;
1273                 DWORD   nLandscapeAngle = ImplDeviceCaps( pPrinter, DC_ORIENTATION, NULL, pSetupData );
1274                 if ( nPaperCount && (nPaperCount != GDI_ERROR) )
1275                 {
1276                     pPapers = (WORD*)rtl_allocateZeroMemory(nPaperCount*sizeof(WORD));
1277                     ImplDeviceCaps( pPrinter, DC_PAPERS, (BYTE*)pPapers, pSetupData );
1278                 }
1279                 if ( nPaperSizeCount && (nPaperSizeCount != GDI_ERROR) )
1280                 {
1281                     pPaperSizes = (POINT*)rtl_allocateZeroMemory(nPaperSizeCount*sizeof(POINT));
1282                     ImplDeviceCaps( pPrinter, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1283                 }
1284                 if ( (nPaperSizeCount == nPaperCount) && pPapers && pPaperSizes )
1285                 {
1286                     PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
1287                     // compare paper formats and select a good match
1288                     for ( sal_uLong i = 0; i < nPaperCount; i++ )
1289                     {
1290                         if ( aInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)))
1291                         {
1292                             nPaper = pPapers[i];
1293                             break;
1294                         }
1295                     }
1296 
1297                     // If the printer supports landscape orientation, check paper sizes again
1298                     // with landscape orientation. This is necessary as a printer driver provides
1299                     // all paper sizes with portrait orientation only!!
1300                     if ( !nPaper && nLandscapeAngle != 0 )
1301                     {
1302                         PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
1303                         for ( sal_uLong i = 0; i < nPaperCount; i++ )
1304                         {
1305                             if ( aRotatedInfo.sloppyEqual(PaperInfo(pPaperSizes[i].x*10, pPaperSizes[i].y*10)) )
1306                             {
1307                                 nPaper = pPapers[i];
1308                                 break;
1309                             }
1310                         }
1311                     }
1312 
1313                     if ( nPaper )
1314                         CHOOSE_DEVMODE(dmPaperSize) = nPaper;
1315                 }
1316 
1317                 if ( !nPaper )
1318                 {
1319                     CHOOSE_DEVMODE(dmFields)       |= DM_PAPERLENGTH | DM_PAPERWIDTH;
1320                     CHOOSE_DEVMODE(dmPaperSize)     = DMPAPER_USER;
1321                     CHOOSE_DEVMODE(dmPaperWidth)    = (short)(pSetupData->mnPaperWidth/10);
1322                     CHOOSE_DEVMODE(dmPaperLength)   = (short)(pSetupData->mnPaperHeight/10);
1323                 }
1324 
1325                 if ( pPapers )
1326                     rtl_freeMemory(pPapers);
1327                 if ( pPaperSizes )
1328                     rtl_freeMemory(pPaperSizes);
1329 
1330                 break;
1331             }
1332         }
1333     }
1334     if( (nFlags & SAL_JOBSET_DUPLEXMODE) )
1335     {
1336         switch( pSetupData->meDuplexMode )
1337         {
1338         case DUPLEX_OFF:
1339             CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1340             CHOOSE_DEVMODE(dmDuplex) = DMDUP_SIMPLEX;
1341             break;
1342         case DUPLEX_SHORTEDGE:
1343             CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1344             CHOOSE_DEVMODE(dmDuplex) = DMDUP_HORIZONTAL;
1345             break;
1346         case DUPLEX_LONGEDGE:
1347             CHOOSE_DEVMODE(dmFields) |= DM_DUPLEX;
1348             CHOOSE_DEVMODE(dmDuplex) = DMDUP_VERTICAL;
1349             break;
1350         case DUPLEX_UNKNOWN:
1351             break;
1352         }
1353     }
1354 }
1355 
1356 // -----------------------------------------------------------------------
1357 
ImplCreateICW_WithCatch(LPWSTR pDriver,LPCWSTR pDevice,LPDEVMODEW pDevMode)1358 static HDC ImplCreateICW_WithCatch( LPWSTR pDriver,
1359                                     LPCWSTR pDevice,
1360                                     LPDEVMODEW pDevMode )
1361 {
1362     HDC hDC = 0;
1363     CATCH_DRIVER_EX_BEGIN;
1364     hDC = CreateICW( pDriver, pDevice, 0, pDevMode );
1365     CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1366     return hDC;
1367 }
1368 
ImplCreateICA_WithCatch(char * pDriver,char * pDevice,LPDEVMODEA pDevMode)1369 static HDC ImplCreateICA_WithCatch( char* pDriver,
1370                                     char* pDevice,
1371                                     LPDEVMODEA pDevMode )
1372 {
1373     HDC hDC = 0;
1374     CATCH_DRIVER_EX_BEGIN;
1375     hDC = CreateICA( pDriver, pDevice, 0, pDevMode );
1376     CATCH_DRIVER_EX_END_2( "exception in CreateICW" );
1377     return hDC;
1378 }
1379 
1380 
ImplCreateSalPrnIC(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData)1381 static HDC ImplCreateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1382 {
1383     HDC hDC = 0;
1384     if( aSalShlData.mbWPrinter )
1385     {
1386         LPDEVMODEW pDevMode;
1387         if ( pSetupData && pSetupData->mpDriverData )
1388             pDevMode = SAL_DEVMODE_W( pSetupData );
1389         else
1390             pDevMode = NULL;
1391         // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1392         // pl: does this hold true for Unicode functions ?
1393         if( pPrinter->maDriverName.Len() > 2048 || pPrinter->maDeviceName.Len() > 2048 )
1394             return 0;
1395         sal_Unicode pDriverName[ 4096 ];
1396         sal_Unicode pDeviceName[ 4096 ];
1397         rtl_copyMemory( pDriverName, pPrinter->maDriverName.GetBuffer(), pPrinter->maDriverName.Len()*sizeof(sal_Unicode));
1398         memset( pDriverName+pPrinter->maDriverName.Len(), 0, 32 );
1399         rtl_copyMemory( pDeviceName, pPrinter->maDeviceName.GetBuffer(), pPrinter->maDeviceName.Len()*sizeof(sal_Unicode));
1400         memset( pDeviceName+pPrinter->maDeviceName.Len(), 0, 32 );
1401         hDC = ImplCreateICW_WithCatch( reinterpret_cast< LPWSTR >(pDriverName),
1402                                        reinterpret_cast< LPCWSTR >(pDeviceName),
1403                                        pDevMode );
1404     }
1405     else
1406     {
1407         LPDEVMODEA pDevMode;
1408         if ( pSetupData && pSetupData->mpDriverData )
1409             pDevMode = SAL_DEVMODE_A( pSetupData );
1410         else
1411             pDevMode = NULL;
1412         // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateIC, although declared const - so provide some space
1413         ByteString aDriver ( ImplSalGetWinAnsiString( pPrinter->maDriverName, TRUE ) );
1414         ByteString aDevice ( ImplSalGetWinAnsiString( pPrinter->maDeviceName, TRUE ) );
1415         int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
1416             // #125813# under some circumstances many printer drivers really
1417         // seem to have a problem with the names and their conversions.
1418         // We need to get on to of this, but haven't been able to reproduce
1419         // the problem yet. Put the names on the stack so we get them
1420         // with an eventual crash report.
1421         if( n >= 2048 )
1422             return 0;
1423         n += 2048;
1424         char lpszDriverName[ 4096 ];
1425         char lpszDeviceName[ 4096 ];
1426         strncpy( lpszDriverName, aDriver.GetBuffer(), n );
1427         strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
1428         // HDU: the crashes usually happen in a MBCS to unicode conversion,
1429         // so I suspect the MBCS string's end is not properly recognized.
1430         // The longest MBCS encoding I'm aware of has six bytes per code
1431         // => add a couple of zeroes...
1432         memset( lpszDriverName+aDriver.Len(), 0, 16 );
1433         memset( lpszDeviceName+aDevice.Len(), 0, 16 );
1434         hDC = ImplCreateICA_WithCatch( lpszDriverName,
1435                                        lpszDeviceName,
1436                                        pDevMode );
1437     }
1438     return hDC;
1439 }
1440 
1441 // -----------------------------------------------------------------------
1442 
ImplCreateSalPrnGraphics(HDC hDC)1443 static WinSalGraphics* ImplCreateSalPrnGraphics( HDC hDC )
1444 {
1445     WinSalGraphics* pGraphics = new WinSalGraphics;
1446     pGraphics->SetLayout( 0 );
1447     pGraphics->setHDC(hDC);
1448     pGraphics->mhWnd    = 0;
1449     pGraphics->mbPrinter = TRUE;
1450     pGraphics->mbVirDev = FALSE;
1451     pGraphics->mbWindow = FALSE;
1452     pGraphics->mbScreen = FALSE;
1453     ImplSalInitGraphics( pGraphics );
1454     return pGraphics;
1455 }
1456 
1457 // -----------------------------------------------------------------------
1458 
ImplUpdateSalPrnIC(WinSalInfoPrinter * pPrinter,ImplJobSetup * pSetupData)1459 static sal_Bool ImplUpdateSalPrnIC( WinSalInfoPrinter* pPrinter, ImplJobSetup* pSetupData )
1460 {
1461     HDC hNewDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1462     if ( !hNewDC )
1463         return FALSE;
1464 
1465     if ( pPrinter->mpGraphics )
1466     {
1467         ImplSalDeInitGraphics( pPrinter->mpGraphics );
1468         DeleteDC( pPrinter->mpGraphics->getHDC() );
1469         delete pPrinter->mpGraphics;
1470     }
1471 
1472     pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hNewDC );
1473     pPrinter->mhDC      = hNewDC;
1474 
1475     return TRUE;
1476 }
1477 
1478 // =======================================================================
1479 
CreateInfoPrinter(SalPrinterQueueInfo * pQueueInfo,ImplJobSetup * pSetupData)1480 SalInfoPrinter* WinSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo,
1481                                                    ImplJobSetup* pSetupData )
1482 {
1483     WinSalInfoPrinter* pPrinter = new WinSalInfoPrinter;
1484     if( ! pQueueInfo->mpSysData )
1485         GetPrinterQueueState( pQueueInfo );
1486     pPrinter->maDriverName  = pQueueInfo->maDriver;
1487     pPrinter->maDeviceName  = pQueueInfo->maPrinterName;
1488     pPrinter->maPortName    = pQueueInfo->mpSysData ?
1489                                 *(String*)(pQueueInfo->mpSysData)
1490                               : String();
1491 
1492     // check if the provided setup data match the actual printer
1493     ImplTestSalJobSetup( pPrinter, pSetupData, TRUE );
1494 
1495     HDC hDC = ImplCreateSalPrnIC( pPrinter, pSetupData );
1496     if ( !hDC )
1497     {
1498         delete pPrinter;
1499         return NULL;
1500     }
1501 
1502     pPrinter->mpGraphics = ImplCreateSalPrnGraphics( hDC );
1503     pPrinter->mhDC      = hDC;
1504     if ( !pSetupData->mpDriverData )
1505         ImplUpdateSalJobSetup( pPrinter, pSetupData, FALSE, NULL );
1506     ImplDevModeToJobSetup( pPrinter, pSetupData, SAL_JOBSET_ALL );
1507     pSetupData->mnSystem = JOBSETUP_SYSTEM_WINDOWS;
1508 
1509     return pPrinter;
1510 }
1511 
1512 // -----------------------------------------------------------------------
1513 
DestroyInfoPrinter(SalInfoPrinter * pPrinter)1514 void WinSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter )
1515 {
1516     delete pPrinter;
1517 }
1518 
1519 // =======================================================================
1520 
WinSalInfoPrinter()1521 WinSalInfoPrinter::WinSalInfoPrinter() :
1522     mpGraphics( NULL ),
1523     mhDC( 0 ),
1524     mbGraphics( FALSE )
1525 {
1526     m_bPapersInit = FALSE;
1527 }
1528 
1529 // -----------------------------------------------------------------------
1530 
~WinSalInfoPrinter()1531 WinSalInfoPrinter::~WinSalInfoPrinter()
1532 {
1533     if ( mpGraphics )
1534     {
1535         ImplSalDeInitGraphics( mpGraphics );
1536         DeleteDC( mpGraphics->getHDC() );
1537         delete mpGraphics;
1538     }
1539 }
1540 
1541 // -----------------------------------------------------------------------
1542 
InitPaperFormats(const ImplJobSetup * pSetupData)1543 void WinSalInfoPrinter::InitPaperFormats( const ImplJobSetup* pSetupData )
1544 {
1545     m_aPaperFormats.clear();
1546 
1547     DWORD nCount = ImplDeviceCaps( this, DC_PAPERSIZE, NULL, pSetupData );
1548     if( nCount == GDI_ERROR )
1549         nCount = 0;
1550 
1551     POINT* pPaperSizes = NULL;
1552     if( nCount )
1553     {
1554         pPaperSizes = (POINT*)rtl_allocateZeroMemory(nCount*sizeof(POINT));
1555         ImplDeviceCaps( this, DC_PAPERSIZE, (BYTE*)pPaperSizes, pSetupData );
1556 
1557         if( aSalShlData.mbWPrinter )
1558         {
1559             sal_Unicode* pNamesBuffer = (sal_Unicode*)rtl_allocateMemory(nCount*64*sizeof(sal_Unicode));
1560             ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1561             for( DWORD i = 0; i < nCount; ++i )
1562             {
1563                 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1564                 m_aPaperFormats.push_back( aInfo );
1565             }
1566             rtl_freeMemory( pNamesBuffer );
1567         }
1568         else
1569         {
1570             char* pNamesBuffer = (char*)rtl_allocateMemory(nCount*64);
1571             ImplDeviceCaps( this, DC_PAPERNAMES, (BYTE*)pNamesBuffer, pSetupData );
1572             for( DWORD i = 0; i < nCount; ++i )
1573             {
1574                 PaperInfo aInfo(pPaperSizes[i].x * 10, pPaperSizes[i].y * 10);
1575                 m_aPaperFormats.push_back( aInfo );
1576             }
1577             rtl_freeMemory( pNamesBuffer );
1578         }
1579         rtl_freeMemory( pPaperSizes );
1580     }
1581 
1582     m_bPapersInit = true;
1583 }
1584 
1585 // -----------------------------------------------------------------------
1586 
GetLandscapeAngle(const ImplJobSetup * pSetupData)1587 int WinSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* pSetupData )
1588 {
1589     int nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
1590 
1591     if( nRet != GDI_ERROR )
1592         return nRet * 10;
1593     else
1594         return 900; // guess
1595 }
1596 
1597 // -----------------------------------------------------------------------
1598 
GetGraphics()1599 SalGraphics* WinSalInfoPrinter::GetGraphics()
1600 {
1601     if ( mbGraphics )
1602         return NULL;
1603 
1604     if ( mpGraphics )
1605         mbGraphics = TRUE;
1606 
1607     return mpGraphics;
1608 }
1609 
1610 // -----------------------------------------------------------------------
1611 
ReleaseGraphics(SalGraphics *)1612 void WinSalInfoPrinter::ReleaseGraphics( SalGraphics* )
1613 {
1614     mbGraphics = FALSE;
1615 }
1616 
1617 // -----------------------------------------------------------------------
1618 
Setup(SalFrame * pFrame,ImplJobSetup * pSetupData)1619 sal_Bool WinSalInfoPrinter::Setup( SalFrame* pFrame, ImplJobSetup* pSetupData )
1620 {
1621     if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, static_cast<WinSalFrame*>(pFrame) ) )
1622     {
1623         ImplDevModeToJobSetup( this, pSetupData, SAL_JOBSET_ALL );
1624         return ImplUpdateSalPrnIC( this, pSetupData );
1625     }
1626 
1627     return FALSE;
1628 }
1629 
1630 // -----------------------------------------------------------------------
1631 
SetPrinterData(ImplJobSetup * pSetupData)1632 sal_Bool WinSalInfoPrinter::SetPrinterData( ImplJobSetup* pSetupData )
1633 {
1634     if ( !ImplTestSalJobSetup( this, pSetupData, FALSE ) )
1635         return FALSE;
1636     return ImplUpdateSalPrnIC( this, pSetupData );
1637 }
1638 
1639 // -----------------------------------------------------------------------
1640 
SetData(sal_uLong nFlags,ImplJobSetup * pSetupData)1641 sal_Bool WinSalInfoPrinter::SetData( sal_uLong nFlags, ImplJobSetup* pSetupData )
1642 {
1643     ImplJobSetupToDevMode( this, pSetupData, nFlags );
1644     if ( ImplUpdateSalJobSetup( this, pSetupData, TRUE, NULL ) )
1645     {
1646         ImplDevModeToJobSetup( this, pSetupData, nFlags );
1647         return ImplUpdateSalPrnIC( this, pSetupData );
1648     }
1649 
1650     return FALSE;
1651 }
1652 
1653 // -----------------------------------------------------------------------
1654 
GetPaperBinCount(const ImplJobSetup * pSetupData)1655 sal_uLong WinSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* pSetupData )
1656 {
1657     DWORD nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1658     if ( nRet && (nRet != GDI_ERROR) )
1659         return nRet;
1660     else
1661         return 0;
1662 }
1663 
1664 // -----------------------------------------------------------------------
1665 
GetPaperBinName(const ImplJobSetup * pSetupData,sal_uLong nPaperBin)1666 XubString WinSalInfoPrinter::GetPaperBinName( const ImplJobSetup* pSetupData, sal_uLong nPaperBin )
1667 {
1668     XubString aPaperBinName;
1669 
1670     DWORD nBins = ImplDeviceCaps( this, DC_BINNAMES, NULL, pSetupData );
1671     if ( (nPaperBin < nBins) && (nBins != GDI_ERROR) )
1672     {
1673         if( aSalShlData.mbWPrinter )
1674         {
1675             sal_Unicode* pBuffer = new sal_Unicode[nBins*24];
1676             DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
1677             if ( nRet && (nRet != GDI_ERROR) )
1678                 aPaperBinName = pBuffer + (nPaperBin*24);
1679             delete [] pBuffer;
1680         }
1681         else
1682         {
1683             char* pBuffer = new char[nBins*24];
1684             DWORD nRet = ImplDeviceCaps( this, DC_BINNAMES, (BYTE*)pBuffer, pSetupData );
1685             if ( nRet && (nRet != GDI_ERROR) )
1686                 aPaperBinName = ImplSalGetUniString( (const char*)(pBuffer + (nPaperBin*24)) );
1687             delete [] pBuffer;
1688         }
1689     }
1690 
1691     return aPaperBinName;
1692 }
1693 
1694 // -----------------------------------------------------------------------
1695 
GetCapabilities(const ImplJobSetup * pSetupData,sal_uInt16 nType)1696 sal_uLong WinSalInfoPrinter::GetCapabilities( const ImplJobSetup* pSetupData, sal_uInt16 nType )
1697 {
1698     DWORD nRet;
1699 
1700     switch ( nType )
1701     {
1702         case PRINTER_CAPABILITIES_SUPPORTDIALOG:
1703             return TRUE;
1704         case PRINTER_CAPABILITIES_COPIES:
1705             nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
1706             if ( nRet && (nRet != GDI_ERROR) )
1707                 return nRet;
1708             return 0;
1709         case PRINTER_CAPABILITIES_COLLATECOPIES:
1710             if ( aSalShlData.mbW40 )
1711             {
1712                 nRet = ImplDeviceCaps( this, DC_COLLATE, NULL, pSetupData );
1713                 if ( nRet && (nRet != GDI_ERROR) )
1714                 {
1715                     nRet = ImplDeviceCaps( this, DC_COPIES, NULL, pSetupData );
1716                     if ( nRet && (nRet != GDI_ERROR) )
1717                          return nRet;
1718                 }
1719             }
1720             return 0;
1721 
1722         case PRINTER_CAPABILITIES_SETORIENTATION:
1723             nRet = ImplDeviceCaps( this, DC_ORIENTATION, NULL, pSetupData );
1724             if ( nRet && (nRet != GDI_ERROR) )
1725                 return TRUE;
1726             return FALSE;
1727 
1728         case PRINTER_CAPABILITIES_SETPAPERBIN:
1729             nRet = ImplDeviceCaps( this, DC_BINS, NULL, pSetupData );
1730             if ( nRet && (nRet != GDI_ERROR) )
1731                 return TRUE;
1732             return FALSE;
1733 
1734         case PRINTER_CAPABILITIES_SETPAPERSIZE:
1735         case PRINTER_CAPABILITIES_SETPAPER:
1736             nRet = ImplDeviceCaps( this, DC_PAPERS, NULL, pSetupData );
1737             if ( nRet && (nRet != GDI_ERROR) )
1738                 return TRUE;
1739             return FALSE;
1740     }
1741 
1742     return 0;
1743 }
1744 
1745 // -----------------------------------------------------------------------
1746 
GetPageInfo(const ImplJobSetup *,long & rOutWidth,long & rOutHeight,long & rPageOffX,long & rPageOffY,long & rPageWidth,long & rPageHeight)1747 void WinSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
1748                                   long& rOutWidth, long& rOutHeight,
1749                                   long& rPageOffX, long& rPageOffY,
1750                                   long& rPageWidth, long& rPageHeight )
1751 {
1752     HDC hDC = mhDC;
1753 
1754     rOutWidth   = GetDeviceCaps( hDC, HORZRES );
1755     rOutHeight  = GetDeviceCaps( hDC, VERTRES );
1756 
1757     rPageOffX   = GetDeviceCaps( hDC, PHYSICALOFFSETX );
1758     rPageOffY   = GetDeviceCaps( hDC, PHYSICALOFFSETY );
1759     rPageWidth  = GetDeviceCaps( hDC, PHYSICALWIDTH );
1760     rPageHeight = GetDeviceCaps( hDC, PHYSICALHEIGHT );
1761 }
1762 
1763 // =======================================================================
1764 
CreatePrinter(SalInfoPrinter * pInfoPrinter)1765 SalPrinter* WinSalInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter )
1766 {
1767     WinSalPrinter* pPrinter = new WinSalPrinter;
1768     pPrinter->mpInfoPrinter = static_cast<WinSalInfoPrinter*>(pInfoPrinter);
1769     return pPrinter;
1770 }
1771 
1772 // -----------------------------------------------------------------------
1773 
DestroyPrinter(SalPrinter * pPrinter)1774 void WinSalInstance::DestroyPrinter( SalPrinter* pPrinter )
1775 {
1776     delete pPrinter;
1777 }
1778 
1779 // =======================================================================
1780 
SalPrintAbortProc(HDC hPrnDC,int)1781 BOOL CALLBACK SalPrintAbortProc( HDC hPrnDC, int /* nError */ )
1782 {
1783     SalData*    pSalData = GetSalData();
1784     WinSalPrinter* pPrinter;
1785     sal_Bool        bWhile = TRUE;
1786     int         i = 0;
1787 
1788     do
1789     {
1790         // Messages verarbeiten
1791         MSG aMsg;
1792         if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
1793         {
1794             if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
1795             {
1796                 TranslateMessage( &aMsg );
1797                 ImplDispatchMessage( &aMsg );
1798             }
1799             i++;
1800             if ( i > 15 )
1801                 bWhile = FALSE;
1802         }
1803         else
1804             bWhile = FALSE;
1805 
1806         pPrinter = pSalData->mpFirstPrinter;
1807         while ( pPrinter )
1808         {
1809             if( pPrinter->mhDC == hPrnDC )
1810                 break;
1811 
1812             pPrinter = pPrinter->mpNextPrinter;
1813         }
1814 
1815         if ( !pPrinter || pPrinter->mbAbort )
1816             return FALSE;
1817     }
1818     while ( bWhile );
1819 
1820     return TRUE;
1821 }
1822 
1823 // -----------------------------------------------------------------------
1824 
ImplSalSetCopies(LPDEVMODEA pDevMode,sal_uLong nCopies,sal_Bool bCollate)1825 static LPDEVMODEA ImplSalSetCopies( LPDEVMODEA pDevMode, sal_uLong nCopies, sal_Bool bCollate )
1826 {
1827     LPDEVMODEA pNewDevMode = pDevMode;
1828     if ( pDevMode && (nCopies > 1) )
1829     {
1830         if ( nCopies > 32765 )
1831             nCopies = 32765;
1832         sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1833         pNewDevMode = (LPDEVMODEA)rtl_allocateMemory( nDevSize );
1834         memcpy( pNewDevMode, pDevMode, nDevSize );
1835         pDevMode = pNewDevMode;
1836         pDevMode->dmFields |= DM_COPIES;
1837         pDevMode->dmCopies  = (short)(sal_uInt16)nCopies;
1838         if ( aSalShlData.mbW40 )
1839         {
1840             pDevMode->dmFields |= DM_COLLATE;
1841             if ( bCollate )
1842                 pDevMode->dmCollate = DMCOLLATE_TRUE;
1843             else
1844                 pDevMode->dmCollate = DMCOLLATE_FALSE;
1845         }
1846     }
1847 
1848     return pNewDevMode;
1849 }
1850 
ImplSalSetCopies(LPDEVMODEW pDevMode,sal_uLong nCopies,sal_Bool bCollate)1851 static LPDEVMODEW ImplSalSetCopies( LPDEVMODEW pDevMode, sal_uLong nCopies, sal_Bool bCollate )
1852 {
1853     LPDEVMODEW pNewDevMode = pDevMode;
1854     if ( pDevMode && (nCopies > 1) )
1855     {
1856         if ( nCopies > 32765 )
1857             nCopies = 32765;
1858         sal_uLong nDevSize = pDevMode->dmSize+pDevMode->dmDriverExtra;
1859         pNewDevMode = (LPDEVMODEW)rtl_allocateMemory( nDevSize );
1860         memcpy( pNewDevMode, pDevMode, nDevSize );
1861         pDevMode = pNewDevMode;
1862         pDevMode->dmFields |= DM_COPIES;
1863         pDevMode->dmCopies  = (short)(sal_uInt16)nCopies;
1864         if ( aSalShlData.mbW40 )
1865         {
1866             pDevMode->dmFields |= DM_COLLATE;
1867             if ( bCollate )
1868                 pDevMode->dmCollate = DMCOLLATE_TRUE;
1869             else
1870                 pDevMode->dmCollate = DMCOLLATE_FALSE;
1871         }
1872     }
1873 
1874     return pNewDevMode;
1875 }
1876 
1877 // -----------------------------------------------------------------------
1878 
WinSalPrinter()1879 WinSalPrinter::WinSalPrinter() :
1880     mpGraphics( NULL ),
1881     mpInfoPrinter( NULL ),
1882     mpNextPrinter( NULL ),
1883     mhDC( 0 ),
1884     mnError( 0 ),
1885     mnCopies( 0 ),
1886     mbCollate( FALSE ),
1887     mbAbort( FALSE ),
1888     mbValid( true )
1889 {
1890     SalData* pSalData = GetSalData();
1891     // insert printer in printerlist
1892     mpNextPrinter = pSalData->mpFirstPrinter;
1893     pSalData->mpFirstPrinter = this;
1894 }
1895 
1896 // -----------------------------------------------------------------------
1897 
~WinSalPrinter()1898 WinSalPrinter::~WinSalPrinter()
1899 {
1900     SalData* pSalData = GetSalData();
1901 
1902     // release DC if there is one still around because of AbortJob
1903     HDC hDC = mhDC;
1904     if ( hDC )
1905     {
1906         if ( mpGraphics )
1907         {
1908             ImplSalDeInitGraphics( mpGraphics );
1909             delete mpGraphics;
1910         }
1911 
1912         DeleteDC( hDC );
1913     }
1914 
1915     // remove printer from printerlist
1916     if ( this == pSalData->mpFirstPrinter )
1917         pSalData->mpFirstPrinter = mpNextPrinter;
1918     else
1919     {
1920         WinSalPrinter* pTempPrinter = pSalData->mpFirstPrinter;
1921 
1922         while( pTempPrinter->mpNextPrinter != this )
1923             pTempPrinter = pTempPrinter->mpNextPrinter;
1924 
1925         pTempPrinter->mpNextPrinter = mpNextPrinter;
1926     }
1927     mbValid = false;
1928 }
1929 
1930 // -----------------------------------------------------------------------
1931 
markInvalid()1932 void WinSalPrinter::markInvalid()
1933 {
1934     mbValid = false;
1935 }
1936 
1937 // -----------------------------------------------------------------------
1938 
1939 // need wrappers for StarTocW/A to use structured exception handling
1940 // since SEH does not mix with standard exception handling's cleanup
lcl_StartDocW(HDC hDC,DOCINFOW * pInfo,WinSalPrinter * pPrt)1941 static int lcl_StartDocW( HDC hDC, DOCINFOW* pInfo, WinSalPrinter* pPrt )
1942 {
1943     int nRet = 0;
1944     CATCH_DRIVER_EX_BEGIN;
1945     nRet = ::StartDocW( hDC, pInfo );
1946     CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1947     return nRet;
1948 }
1949 
lcl_StartDocA(HDC hDC,DOCINFOA * pInfo,WinSalPrinter * pPrt)1950 static int lcl_StartDocA( HDC hDC, DOCINFOA* pInfo, WinSalPrinter* pPrt )
1951 {
1952     int nRet = 0;
1953     CATCH_DRIVER_EX_BEGIN;
1954     nRet = ::StartDocA( hDC, pInfo );
1955     CATCH_DRIVER_EX_END( "exception in StartDocW", pPrt );
1956     return nRet;
1957 }
1958 
StartJob(const XubString * pFileName,const XubString & rJobName,const XubString &,sal_uLong nCopies,bool bCollate,bool,ImplJobSetup * pSetupData)1959 sal_Bool WinSalPrinter::StartJob( const XubString* pFileName,
1960                            const XubString& rJobName,
1961                            const XubString&,
1962                            sal_uLong nCopies,
1963                            bool bCollate,
1964                            bool /*bDirect*/,
1965                            ImplJobSetup* pSetupData )
1966 {
1967     mnError     = 0;
1968     mbAbort     = FALSE;
1969     mnCopies        = nCopies;
1970     mbCollate   = bCollate;
1971 
1972     LPDEVMODEA  pOrgDevModeA = NULL;
1973     LPDEVMODEA  pDevModeA = NULL;
1974     LPDEVMODEW  pOrgDevModeW = NULL;
1975     LPDEVMODEW  pDevModeW = NULL;
1976     HDC hDC = 0;
1977     if( aSalShlData.mbWPrinter )
1978     {
1979         if ( pSetupData && pSetupData->mpDriverData )
1980         {
1981             pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
1982             pDevModeW = ImplSalSetCopies( pOrgDevModeW, nCopies, bCollate );
1983         }
1984         else
1985             pDevModeW = NULL;
1986 
1987         // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
1988         sal_Unicode aDrvBuf[4096];
1989         sal_Unicode aDevBuf[4096];
1990         rtl_copyMemory( aDrvBuf, mpInfoPrinter->maDriverName.GetBuffer(), (mpInfoPrinter->maDriverName.Len()+1)*sizeof(sal_Unicode));
1991         rtl_copyMemory( aDevBuf, mpInfoPrinter->maDeviceName.GetBuffer(), (mpInfoPrinter->maDeviceName.Len()+1)*sizeof(sal_Unicode));
1992         hDC = CreateDCW( reinterpret_cast<LPCWSTR>(aDrvBuf),
1993                          reinterpret_cast<LPCWSTR>(aDevBuf),
1994                          NULL,
1995                          pDevModeW );
1996 
1997         if ( pDevModeW != pOrgDevModeW )
1998             rtl_freeMemory( pDevModeW );
1999     }
2000     else
2001     {
2002         if ( pSetupData && pSetupData->mpDriverData )
2003         {
2004             pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2005             pDevModeA = ImplSalSetCopies( pOrgDevModeA, nCopies, bCollate );
2006         }
2007         else
2008             pDevModeA = NULL;
2009 
2010         // #95347 some buggy drivers (eg, OKI) write to those buffers in CreateDC, although declared const - so provide some space
2011         ByteString aDriver ( ImplSalGetWinAnsiString( mpInfoPrinter->maDriverName, TRUE ) );
2012         ByteString aDevice ( ImplSalGetWinAnsiString( mpInfoPrinter->maDeviceName, TRUE ) );
2013         int n = aDriver.Len() > aDevice.Len() ? aDriver.Len() : aDevice.Len();
2014         n += 2048;
2015         char *lpszDriverName = new char[n];
2016         char *lpszDeviceName = new char[n];
2017         strncpy( lpszDriverName, aDriver.GetBuffer(), n );
2018         strncpy( lpszDeviceName, aDevice.GetBuffer(), n );
2019         hDC = CreateDCA( lpszDriverName,
2020                          lpszDeviceName,
2021                          NULL,
2022                          pDevModeA );
2023 
2024         delete [] lpszDriverName;
2025         delete [] lpszDeviceName;
2026 
2027         if ( pDevModeA != pOrgDevModeA )
2028             rtl_freeMemory( pDevModeA );
2029     }
2030 
2031     if ( !hDC )
2032     {
2033         mnError = SAL_PRINTER_ERROR_GENERALERROR;
2034         return FALSE;
2035     }
2036 
2037     // make sure mhDC is set before the printer driver may call our abortproc
2038     mhDC = hDC;
2039     if ( SetAbortProc( hDC, SalPrintAbortProc ) <= 0 )
2040     {
2041         mnError = SAL_PRINTER_ERROR_GENERALERROR;
2042         return FALSE;
2043     }
2044 
2045     mnError = 0;
2046     mbAbort = FALSE;
2047 
2048     // Wegen Telocom Balloon Fax-Treiber, der uns unsere Messages
2049     // ansonsten oefters schickt, versuchen wir vorher alle
2050     // zu verarbeiten und dann eine Dummy-Message reinstellen
2051     sal_Bool bWhile = TRUE;
2052     int  i = 0;
2053     do
2054     {
2055         // Messages verarbeiten
2056         MSG aMsg;
2057         if ( ImplPeekMessage( &aMsg, 0, 0, 0, PM_REMOVE ) )
2058         {
2059             if ( !ImplInterceptChildWindowKeyDown( aMsg ) )
2060             {
2061                 TranslateMessage( &aMsg );
2062                 ImplDispatchMessage( &aMsg );
2063             }
2064 
2065             i++;
2066             if ( i > 15 )
2067                 bWhile = FALSE;
2068         }
2069         else
2070             bWhile = FALSE;
2071     }
2072     while ( bWhile );
2073     ImplPostMessage( GetSalData()->mpFirstInstance->mhComWnd, SAL_MSG_DUMMY, 0, 0 );
2074 
2075     // bring up a file choser if printing to file port but no file name given
2076     OUString aOutFileName;
2077     if( mpInfoPrinter->maPortName.EqualsIgnoreCaseAscii( "FILE:" ) && !(pFileName && pFileName->Len()) )
2078     {
2079 
2080         uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
2081         if( xFactory.is() )
2082         {
2083             uno::Reference< XFilePicker > xFilePicker( xFactory->createInstance(
2084                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ) ),
2085                 UNO_QUERY );
2086             DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" );
2087 
2088             uno::Reference< XInitialization > xInit( xFilePicker, UNO_QUERY );
2089             uno::Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY );
2090             if( xInit.is() && xFilePicker.is() && xFilterMgr.is() )
2091             {
2092                 Sequence< Any > aServiceType( 1 );
2093                 aServiceType[0] <<= TemplateDescription::FILESAVE_SIMPLE;
2094                 xInit->initialize( aServiceType );
2095                 if( xFilePicker->execute() == ExecutableDialogResults::OK )
2096                 {
2097                     Sequence< OUString > aPathSeq( xFilePicker->getFiles() );
2098                     INetURLObject aObj( aPathSeq[0] );
2099                     // we're using ansi calls (StartDocA) so convert the string
2100                     aOutFileName = aObj.PathToFileName();
2101                 }
2102                 else
2103                 {
2104                     mnError = SAL_PRINTER_ERROR_ABORT;
2105                     return FALSE;
2106                 }
2107             }
2108         }
2109     }
2110 
2111     if( aSalShlData.mbWPrinter )
2112     {
2113         DOCINFOW aInfo;
2114         memset( &aInfo, 0, sizeof( DOCINFOW ) );
2115         aInfo.cbSize = sizeof( aInfo );
2116         aInfo.lpszDocName = (LPWSTR)rJobName.GetBuffer();
2117         if ( pFileName || aOutFileName.getLength() )
2118         {
2119             if ( (pFileName && pFileName->Len()) || aOutFileName.getLength() )
2120             {
2121                 aInfo.lpszOutput = (LPWSTR)( (pFileName && pFileName->Len()) ? pFileName->GetBuffer() : aOutFileName.getStr());
2122             }
2123             else
2124                 aInfo.lpszOutput = L"FILE:";
2125         }
2126         else
2127             aInfo.lpszOutput = NULL;
2128 
2129         // start Job
2130         int nRet = lcl_StartDocW( hDC, &aInfo, this );
2131 
2132         if ( nRet <= 0 )
2133         {
2134             long nError = GetLastError();
2135             if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2136                 mnError = SAL_PRINTER_ERROR_ABORT;
2137             else
2138                 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2139             return FALSE;
2140         }
2141     }
2142     else
2143     {
2144         // Both strings must exist, if StartJob() is called
2145         ByteString aJobName( ImplSalGetWinAnsiString( rJobName, TRUE ) );
2146         ByteString aFileName;
2147 
2148         DOCINFOA aInfo;
2149         memset( &aInfo, 0, sizeof( DOCINFOA ) );
2150         aInfo.cbSize = sizeof( aInfo );
2151         aInfo.lpszDocName = (LPCSTR)aJobName.GetBuffer();
2152         if ( pFileName || aOutFileName.getLength() )
2153         {
2154             if ( pFileName->Len() || aOutFileName.getLength() )
2155             {
2156                 aFileName = ImplSalGetWinAnsiString( pFileName ? *pFileName : static_cast<const XubString>(aOutFileName), TRUE );
2157                 aInfo.lpszOutput = (LPCSTR)aFileName.GetBuffer();
2158             }
2159             else
2160                 aInfo.lpszOutput = "FILE:";
2161         }
2162         else
2163             aInfo.lpszOutput = NULL;
2164 
2165         // start Job
2166         int nRet = lcl_StartDocA( hDC, &aInfo, this );
2167         if ( nRet <= 0 )
2168         {
2169             long nError = GetLastError();
2170             if ( (nRet == SP_USERABORT) || (nRet == SP_APPABORT) || (nError == ERROR_PRINT_CANCELLED) || (nError == ERROR_CANCELLED) )
2171                 mnError = SAL_PRINTER_ERROR_ABORT;
2172             else
2173                 mnError = SAL_PRINTER_ERROR_GENERALERROR;
2174             return FALSE;
2175         }
2176     }
2177 
2178     return TRUE;
2179 }
2180 
2181 // -----------------------------------------------------------------------
2182 
EndJob()2183 sal_Bool WinSalPrinter::EndJob()
2184 {
2185     DWORD err = 0;
2186     HDC hDC = mhDC;
2187     if ( isValid() && hDC )
2188     {
2189         if ( mpGraphics )
2190         {
2191             ImplSalDeInitGraphics( mpGraphics );
2192             delete mpGraphics;
2193             mpGraphics = NULL;
2194         }
2195 
2196         // #i54419# Windows fax printer brings up a dialog in EndDoc
2197         // which text previously copied in soffice process can be
2198         // pasted to -> deadlock due to mutex not released.
2199         // it should be safe to release the yield mutex over the EndDoc
2200         // call, however the real solution is supposed to be the threading
2201         // framework yet to come.
2202         SalData* pSalData = GetSalData();
2203         sal_uLong nAcquire = pSalData->mpFirstInstance->ReleaseYieldMutex();
2204         CATCH_DRIVER_EX_BEGIN;
2205         if( ::EndDoc( hDC ) <= 0 )
2206             err = GetLastError();
2207         CATCH_DRIVER_EX_END( "exception in EndDoc", this );
2208 
2209         pSalData->mpFirstInstance->AcquireYieldMutex( nAcquire );
2210         DeleteDC( hDC );
2211         mhDC = 0;
2212     }
2213 
2214     return TRUE;
2215 }
2216 
2217 // -----------------------------------------------------------------------
2218 
AbortJob()2219 sal_Bool WinSalPrinter::AbortJob()
2220 {
2221     mbAbort = TRUE;
2222 
2223     // Abort asyncron ausloesen
2224     HDC hDC = mhDC;
2225     if ( hDC )
2226     {
2227         SalData* pSalData = GetSalData();
2228         ImplPostMessage( pSalData->mpFirstInstance->mhComWnd,
2229                          SAL_MSG_PRINTABORTJOB, (WPARAM)hDC, 0 );
2230     }
2231 
2232     return TRUE;
2233 }
2234 
2235 // -----------------------------------------------------------------------
2236 
ImplSalPrinterAbortJobAsync(HDC hPrnDC)2237 void ImplSalPrinterAbortJobAsync( HDC hPrnDC )
2238 {
2239     SalData*    pSalData = GetSalData();
2240     WinSalPrinter* pPrinter = pSalData->mpFirstPrinter;
2241 
2242     // Feststellen, ob Printer noch existiert
2243     while ( pPrinter )
2244     {
2245         if ( pPrinter->mhDC == hPrnDC )
2246             break;
2247 
2248         pPrinter = pPrinter->mpNextPrinter;
2249     }
2250 
2251     // Wenn Printer noch existiert, dann den Job abbrechen
2252     if ( pPrinter )
2253     {
2254         HDC hDC = pPrinter->mhDC;
2255         if ( hDC )
2256         {
2257             if ( pPrinter->mpGraphics )
2258             {
2259                 ImplSalDeInitGraphics( pPrinter->mpGraphics );
2260                 delete pPrinter->mpGraphics;
2261                 pPrinter->mpGraphics = NULL;
2262             }
2263 
2264             CATCH_DRIVER_EX_BEGIN;
2265             ::AbortDoc( hDC );
2266             CATCH_DRIVER_EX_END( "exception in AbortDoc", pPrinter );
2267 
2268             DeleteDC( hDC );
2269             pPrinter->mhDC = 0;
2270         }
2271     }
2272 }
2273 
2274 // -----------------------------------------------------------------------
2275 
StartPage(ImplJobSetup * pSetupData,sal_Bool bNewJobData)2276 SalGraphics* WinSalPrinter::StartPage( ImplJobSetup* pSetupData, sal_Bool bNewJobData )
2277 {
2278     if( ! isValid() || mhDC == 0 )
2279         return NULL;
2280 
2281     HDC hDC = mhDC;
2282     if ( pSetupData && pSetupData->mpDriverData && bNewJobData )
2283     {
2284         if( aSalShlData.mbWPrinter )
2285         {
2286             LPDEVMODEW  pOrgDevModeW;
2287             LPDEVMODEW  pDevModeW;
2288             pOrgDevModeW = SAL_DEVMODE_W( pSetupData );
2289             pDevModeW = ImplSalSetCopies( pOrgDevModeW, mnCopies, mbCollate );
2290             ResetDCW( hDC, pDevModeW );
2291             if ( pDevModeW != pOrgDevModeW )
2292                 rtl_freeMemory( pDevModeW );
2293         }
2294         else
2295         {
2296             LPDEVMODEA  pOrgDevModeA;
2297             LPDEVMODEA  pDevModeA;
2298             pOrgDevModeA = SAL_DEVMODE_A( pSetupData );
2299             pDevModeA = ImplSalSetCopies( pOrgDevModeA, mnCopies, mbCollate );
2300             ResetDCA( hDC, pDevModeA );
2301             if ( pDevModeA != pOrgDevModeA )
2302                 rtl_freeMemory( pDevModeA );
2303         }
2304     }
2305     int nRet = 0;
2306     CATCH_DRIVER_EX_BEGIN;
2307     nRet = ::StartPage( hDC );
2308     CATCH_DRIVER_EX_END( "exception in StartPage", this );
2309 
2310     if ( nRet <= 0 )
2311     {
2312         GetLastError();
2313         mnError = SAL_PRINTER_ERROR_GENERALERROR;
2314         return NULL;
2315     }
2316 
2317     // Hack to work around old PostScript printer drivers optimizing away empty pages
2318     // TODO: move into ImplCreateSalPrnGraphics()?
2319     HPEN    hTempPen = SelectPen( hDC, GetStockPen( NULL_PEN ) );
2320     HBRUSH  hTempBrush = SelectBrush( hDC, GetStockBrush( NULL_BRUSH ) );
2321     WIN_Rectangle( hDC, -8000, -8000, -7999, -7999 );
2322     SelectPen( hDC, hTempPen );
2323     SelectBrush( hDC, hTempBrush );
2324 
2325     mpGraphics = ImplCreateSalPrnGraphics( hDC );
2326     return mpGraphics;
2327 }
2328 
2329 // -----------------------------------------------------------------------
2330 
EndPage()2331 sal_Bool WinSalPrinter::EndPage()
2332 {
2333     HDC hDC = mhDC;
2334     if ( hDC && mpGraphics )
2335     {
2336         ImplSalDeInitGraphics( mpGraphics );
2337         delete mpGraphics;
2338         mpGraphics = NULL;
2339     }
2340 
2341     if( ! isValid() )
2342         return FALSE;
2343 
2344     int nRet = 0;
2345     CATCH_DRIVER_EX_BEGIN;
2346     nRet = ::EndPage( hDC );
2347     CATCH_DRIVER_EX_END( "exception in EndPage", this );
2348 
2349     if ( nRet > 0 )
2350         return TRUE;
2351     else
2352     {
2353         GetLastError();
2354         mnError = SAL_PRINTER_ERROR_GENERALERROR;
2355         return FALSE;
2356     }
2357 }
2358 
2359 // -----------------------------------------------------------------------
2360 
GetErrorCode()2361 sal_uLong WinSalPrinter::GetErrorCode()
2362 {
2363     return mnError;
2364 }
2365