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