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