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