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, i.e. 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 https://wiki.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 (e.g. 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 (e.g. 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 chooser 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