1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_dtrans.hxx" 30 #include "FmtFilter.hxx" 31 #include <osl/diagnose.h> 32 #include <comphelper/sequence.hxx> 33 34 #if defined _MSC_VER 35 #pragma warning(push,1) 36 #pragma warning(disable:4917) 37 #endif 38 #include <Shobjidl.h> 39 #include <shlguid.h> 40 #include <ObjIdl.h> 41 #include <shellapi.h> 42 #if defined _MSC_VER 43 #pragma warning(pop) 44 #endif 45 46 #include <string> 47 #include <sstream> 48 #include <vector> 49 #include <iomanip> 50 51 #include <systools/win32/comtools.hxx> 52 53 using namespace com::sun::star::uno; 54 using rtl::OString; 55 56 #pragma pack(2) 57 struct METAFILEHEADER 58 { 59 DWORD key; 60 short hmf; 61 SMALL_RECT bbox; 62 WORD inch; 63 DWORD reserved; 64 WORD checksum; 65 }; 66 #pragma pack() 67 68 //------------------------------------------------------------------------ 69 // convert a windows metafile picture to a openoffice metafile picture 70 //------------------------------------------------------------------------ 71 72 Sequence< sal_Int8 > SAL_CALL WinMFPictToOOMFPict( Sequence< sal_Int8 >& aMetaFilePict ) 73 { 74 OSL_ASSERT( aMetaFilePict.getLength( ) == sizeof( METAFILEPICT ) ); 75 76 Sequence< sal_Int8 > mfpictStream; 77 METAFILEPICT* pMFPict = reinterpret_cast< METAFILEPICT* >( aMetaFilePict.getArray( ) ); 78 HMETAFILE hMf = pMFPict->hMF; 79 sal_uInt32 nCount = GetMetaFileBitsEx( hMf, 0, NULL ); 80 81 if ( nCount > 0 ) 82 { 83 mfpictStream.realloc( nCount + sizeof( METAFILEHEADER ) ); 84 85 METAFILEHEADER* pMFHeader = reinterpret_cast< METAFILEHEADER* >( mfpictStream.getArray( ) ); 86 SMALL_RECT aRect = { 0, 87 0, 88 static_cast< short >( pMFPict->xExt ), 89 static_cast< short >( pMFPict->yExt ) }; 90 USHORT nInch; 91 92 switch( pMFPict->mm ) 93 { 94 case MM_TEXT: 95 nInch = 72; 96 break; 97 98 case MM_LOMETRIC: 99 nInch = 100; 100 break; 101 102 case MM_HIMETRIC: 103 nInch = 1000; 104 break; 105 106 case MM_LOENGLISH: 107 nInch = 254; 108 break; 109 110 case MM_HIENGLISH: 111 case MM_ISOTROPIC: 112 case MM_ANISOTROPIC: 113 nInch = 2540; 114 break; 115 116 case MM_TWIPS: 117 nInch = 1440; 118 break; 119 120 default: 121 nInch = 576; 122 } 123 124 pMFHeader->key = 0x9AC6CDD7L; 125 pMFHeader->hmf = 0; 126 pMFHeader->bbox = aRect; 127 pMFHeader->inch = nInch; 128 pMFHeader->reserved = 0; 129 pMFHeader->checksum = 0; 130 131 char* pMFBuff = reinterpret_cast< char* >( mfpictStream.getArray( ) ); 132 133 nCount = GetMetaFileBitsEx( pMFPict->hMF, nCount, pMFBuff + sizeof( METAFILEHEADER ) ); 134 OSL_ASSERT( nCount > 0 ); 135 } 136 137 return mfpictStream; 138 } 139 140 //------------------------------------------------------------- 141 // convert a windows enhanced metafile to a openoffice metafile 142 //------------------------------------------------------------- 143 144 Sequence< sal_Int8 > SAL_CALL WinENHMFPictToOOMFPict( HENHMETAFILE hEnhMetaFile ) 145 { 146 Sequence< sal_Int8 > aRet; 147 UINT nSize = 0; 148 149 if( hEnhMetaFile && 150 ( ( nSize = GetEnhMetaFileBits( hEnhMetaFile, 0, NULL ) ) != 0 ) ) 151 { 152 aRet.realloc( nSize ); 153 154 if( GetEnhMetaFileBits( hEnhMetaFile, nSize, (sal_uChar*) aRet.getArray() ) != nSize ) 155 aRet.realloc( 0 ); 156 } 157 158 return aRet; 159 } 160 161 //------------------------------------------------------------------------ 162 // convert a openoffice metafile picture to a windows metafile picture 163 //------------------------------------------------------------------------ 164 165 HMETAFILEPICT SAL_CALL OOMFPictToWinMFPict( Sequence< sal_Int8 >& aOOMetaFilePict ) 166 { 167 HMETAFILEPICT hPict = NULL; 168 HMETAFILE hMtf = SetMetaFileBitsEx( aOOMetaFilePict.getLength(), (sal_uChar*) aOOMetaFilePict.getConstArray() ); 169 170 if( hMtf ) 171 { 172 METAFILEPICT* pPict = (METAFILEPICT*) GlobalLock( hPict = GlobalAlloc( GHND, sizeof( METAFILEPICT ) ) ); 173 174 pPict->mm = 8; 175 pPict->xExt = 0; 176 pPict->yExt = 0; 177 pPict->hMF = hMtf; 178 179 GlobalUnlock( hPict ); 180 } 181 182 return hPict; 183 } 184 185 //----------------------------------------------------------------------------- 186 // convert a openoffice metafile picture to a windows enhanced metafile picture 187 //----------------------------------------------------------------------------- 188 189 HENHMETAFILE SAL_CALL OOMFPictToWinENHMFPict( Sequence< sal_Int8 >& aOOMetaFilePict ) 190 { 191 HENHMETAFILE hEnhMtf = SetEnhMetaFileBits( aOOMetaFilePict.getLength(), (sal_uChar*) aOOMetaFilePict.getConstArray() ); 192 193 return hEnhMtf; 194 } 195 196 //------------------------------------------------------------------------ 197 // convert a windows device independent bitmap into a openoffice bitmap 198 //------------------------------------------------------------------------ 199 200 Sequence< sal_Int8 > SAL_CALL WinDIBToOOBMP( const Sequence< sal_Int8 >& aWinDIB ) 201 { 202 OSL_ASSERT( aWinDIB.getLength( ) > sizeof( BITMAPINFOHEADER ) ); 203 204 Sequence< sal_Int8 > ooBmpStream; 205 206 ooBmpStream.realloc( aWinDIB.getLength( ) + sizeof(BITMAPFILEHEADER) ); 207 208 const BITMAPINFOHEADER *pBmpInfoHdr = (const BITMAPINFOHEADER*)aWinDIB.getConstArray(); 209 BITMAPFILEHEADER *pBmpFileHdr = reinterpret_cast< BITMAPFILEHEADER* >( ooBmpStream.getArray() ); 210 DWORD nOffset = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ); 211 212 rtl_copyMemory( pBmpFileHdr + 1, pBmpInfoHdr, aWinDIB.getLength( ) ); 213 214 if( pBmpInfoHdr->biBitCount <= 8 ) 215 nOffset += ( pBmpInfoHdr->biClrUsed ? pBmpInfoHdr->biClrUsed : ( 1 << pBmpInfoHdr->biBitCount ) ) << 2; 216 else if( ( BI_BITFIELDS == pBmpInfoHdr->biCompression ) && ( ( 16 == pBmpInfoHdr->biBitCount ) || ( 32 == pBmpInfoHdr->biBitCount ) ) ) 217 nOffset += 12; 218 219 pBmpFileHdr->bfType = 'MB'; 220 pBmpFileHdr->bfSize = 0; // maybe: nMemSize + sizeof(BITMAPFILEHEADER) 221 pBmpFileHdr->bfReserved1 = 0; 222 pBmpFileHdr->bfReserved2 = 0; 223 pBmpFileHdr->bfOffBits = nOffset; 224 225 return ooBmpStream; 226 } 227 228 //------------------------------------------------------------------------ 229 // convert a openoffice bitmap into a windows device independent bitmap 230 //------------------------------------------------------------------------ 231 232 Sequence< sal_Int8 > SAL_CALL OOBmpToWinDIB( Sequence< sal_Int8 >& aOOBmp ) 233 { 234 OSL_ASSERT( aOOBmp.getLength( ) > 235 ( sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ) ); 236 237 Sequence< sal_Int8 > winDIBStream( aOOBmp.getLength( ) - sizeof( BITMAPFILEHEADER ) ); 238 239 rtl_copyMemory( winDIBStream.getArray( ), 240 aOOBmp.getArray( ) + sizeof( BITMAPFILEHEADER ), 241 aOOBmp.getLength( ) - sizeof( BITMAPFILEHEADER ) ); 242 243 return winDIBStream; 244 } 245 246 //------------------------------------------------------------------------------ 247 // converts the openoffice text/html clipboard format to the HTML Format 248 // well known under MS Windows 249 // the MS HTML Format has a header before the real html data 250 // 251 // Version:1.0 Version number of the clipboard. Staring is 0.9 252 // StartHTML: Byte count from the beginning of the clipboard to the start 253 // of the context, or -1 if no context 254 // EndHTML: Byte count from the beginning of the clipboard to the end 255 // of the context, or -1 if no context 256 // StartFragment: Byte count from the beginning of the clipboard to the 257 // start of the fragment 258 // EndFragment: Byte count from the beginning of the clipboard to the 259 // end of the fragment 260 // StartSelection: Byte count from the beginning of the clipboard to the 261 // start of the selection 262 // EndSelection: Byte count from the beginning of the clipboard to the 263 // end of the selection 264 // 265 // StartSelection and EndSelection are optional 266 // The fragment should be preceded and followed by the HTML comments 267 // <!--StartFragment--> and <!--EndFragment--> (no space between !-- and the 268 // text 269 //------------------------------------------------------------------------------ 270 /* 271 Sequence< sal_Int8 > SAL_CALL TextHtmlToHTMLFormat( Sequence< sal_Int8 >& aTextHtml ) 272 { 273 OSL_ASSERT( aTextHtml.getLength( ) > 0 ); 274 275 // check parameter 276 if ( !(aTextHtml.getLength( ) > 0) ) 277 return Sequence< sal_Int8 >( ); 278 279 // we create a buffer with the approximated size of 280 // the HTML Format header 281 char aHTMLFmtHdr[120]; 282 283 rtl_zeroMemory( aHTMLFmtHdr, sizeof( aHTMLFmtHdr ) ); 284 285 // fill the buffer with dummy values to calc the 286 // exact length 287 288 wsprintf( 289 aHTMLFmtHdr, 290 "Version:1.0\nStartHTML:%010d\r\nnEndHTML:%010d\r\nStartFragment:%010\r\nnEndFragment:%010d\r\n", 0, 0, 0, 0 ); 291 292 sal_uInt32 lHTMLFmtHdr = rtl_str_getLength( aHTMLFmtHdr ); 293 294 // the office allways writes the start 295 // and end html tag in upper cases and 296 // without spaces 297 // both tags don't allow parameters 298 OString startHtmlTag( "<HTML>" ); 299 OString endHtmlTag( "</HTML>" ); 300 301 // we don't include '>' into the search 302 // because the body tag allows parameters 303 // e.g. <BODY param> 304 // #92840# 305 OString startBodyTag( "<BODY" ); 306 OString endBodyTag( "</BODY" ); 307 308 OString textHtml( 309 reinterpret_cast< const sal_Char* >( aTextHtml.getConstArray( ) ), 310 aTextHtml.getLength( ) ); 311 312 sal_Int32 nStartHtml = textHtml.indexOf( startHtmlTag ); 313 sal_Int32 nEndHtml = textHtml.indexOf( endHtmlTag ); 314 sal_Int32 nStartFrgmt = textHtml.indexOf( startBodyTag ); 315 sal_Int32 nEndFrgmt = textHtml.indexOf( endBodyTag ); 316 317 OSL_ASSERT( (nStartHtml >= 0) && (nEndHtml > nStartHtml) && (nStartFrgmt > nStartHtml) && (nEndFrgmt > nStartFrgmt) ); 318 319 Sequence< sal_Int8 > aHTMLFmtSequence; 320 321 if ( (nStartHtml > -1) && (nEndHtml > -1) && (nStartFrgmt > -1) && (nEndFrgmt > -1) ) 322 { 323 nStartHtml = nStartHtml + lHTMLFmtHdr - 1; // we start one before <HTML> Word 2000 does also so 324 nEndHtml = nEndHtml + lHTMLFmtHdr + endHtmlTag.getLength( ) + 1; // our SOffice 5.2 wants 2 behind </HTML>? 325 nStartFrgmt = nStartFrgmt + startBodyTag.getLength( ) + lHTMLFmtHdr; // after the <BODY> tag 326 nEndFrgmt = nEndFrgmt + lHTMLFmtHdr; 327 328 // fill the html header 329 rtl_zeroMemory( aHTMLFmtHdr, sizeof( aHTMLFmtHdr ) ); 330 331 wsprintf( 332 aHTMLFmtHdr, 333 "Version:1.0\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n", 334 nStartHtml, nEndHtml, nStartFrgmt, nEndFrgmt ); 335 336 // we add space for a trailing \0 337 aHTMLFmtSequence.realloc( lHTMLFmtHdr + aTextHtml.getLength( ) + 1 ); 338 rtl_zeroMemory( aHTMLFmtSequence.getArray( ), aHTMLFmtSequence.getLength( ) ); 339 340 // copy the HTML Format header 341 rtl_copyMemory( 342 static_cast< LPVOID >( aHTMLFmtSequence.getArray( ) ), 343 static_cast< LPVOID >( aHTMLFmtHdr ), lHTMLFmtHdr ); 344 345 // concat the text/html 346 rtl_copyMemory( 347 static_cast< LPVOID >( aHTMLFmtSequence.getArray( ) + lHTMLFmtHdr ), 348 static_cast< LPVOID >( aTextHtml.getArray( ) ), 349 aTextHtml.getLength( ) ); 350 } 351 352 return aHTMLFmtSequence; 353 } 354 */ 355 356 std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, size_t endFragment) 357 { 358 std::ostringstream htmlHeader; 359 htmlHeader << "Version:1.0" << '\r' << '\n'; 360 htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml << '\r' << '\n'; 361 htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' << '\n'; 362 htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec << startFragment << '\r' << '\n'; 363 htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment << '\r' << '\n'; 364 return htmlHeader.str(); 365 } 366 367 // the office allways writes the start and end html tag in upper cases and 368 // without spaces both tags don't allow parameters 369 const std::string TAG_HTML = std::string("<HTML>"); 370 const std::string TAG_END_HTML = std::string("</HTML>"); 371 372 // The body tag may have parameters so we need to search for the 373 // closing '>' manually e.g. <BODY param> #92840# 374 const std::string TAG_BODY = std::string("<BODY"); 375 const std::string TAG_END_BODY = std::string("</BODY"); 376 377 Sequence<sal_Int8> SAL_CALL TextHtmlToHTMLFormat(Sequence<sal_Int8>& aTextHtml) 378 { 379 OSL_ASSERT(aTextHtml.getLength() > 0); 380 381 if (!(aTextHtml.getLength() > 0)) 382 return Sequence<sal_Int8>(); 383 384 // fill the buffer with dummy values to calc the exact length 385 std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); 386 size_t lHtmlFormatHeader = dummyHtmlHeader.length(); 387 388 std::string textHtml( 389 reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()), 390 reinterpret_cast<const sal_Char*>(aTextHtml.getConstArray()) + aTextHtml.getLength()); 391 392 std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader - 1; // we start one before '<HTML>' Word 2000 does also so 393 std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + TAG_END_HTML.length() + 1; // our SOffice 5.2 wants 2 behind </HTML>? 394 395 // The body tag may have parameters so we need to search for the 396 // closing '>' manually e.g. <BODY param> #92840# 397 std::string::size_type nStartFragment = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; 398 std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; 399 400 std::string htmlFormat = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); 401 htmlFormat += textHtml; 402 403 Sequence<sal_Int8> byteSequence(htmlFormat.length() + 1); // space the trailing '\0' 404 rtl_zeroMemory(byteSequence.getArray(), byteSequence.getLength()); 405 406 rtl_copyMemory( 407 static_cast<void*>(byteSequence.getArray()), 408 static_cast<const void*>(htmlFormat.c_str()), 409 htmlFormat.length()); 410 411 return byteSequence; 412 } 413 414 std::wstring getFileExtension(const std::wstring& aFilename) 415 { 416 std::wstring::size_type idx = aFilename.rfind(L"."); 417 if ((idx != std::wstring::npos)) 418 { 419 return std::wstring(aFilename, idx); 420 } 421 return std::wstring(); 422 } 423 424 const std::wstring SHELL_LINK_FILE_EXTENSION = L".lnk"; 425 426 bool isShellLink(const std::wstring& aFilename) 427 { 428 std::wstring ext = getFileExtension(aFilename); 429 return (_wcsicmp(ext.c_str(), SHELL_LINK_FILE_EXTENSION.c_str()) == 0); 430 } 431 432 /** Resolve a Windows Shell Link (lnk) file. If a resolution 433 is not possible simply return the provided name of the 434 lnk file. */ 435 std::wstring getShellLinkTarget(const std::wstring& aLnkFile) 436 { 437 OSL_ASSERT(isShellLink(aLnkFile)); 438 439 std::wstring target = aLnkFile; 440 441 try 442 { 443 sal::systools::COMReference<IShellLinkA> pIShellLink; 444 HRESULT hr = CoCreateInstance( 445 CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<LPVOID*>(&pIShellLink)); 446 if (FAILED(hr)) 447 return target; 448 449 sal::systools::COMReference<IPersistFile> pIPersistFile = 450 pIShellLink.QueryInterface<IPersistFile>(IID_IPersistFile); 451 452 hr = pIPersistFile->Load(aLnkFile.c_str(), STGM_READ); 453 if (FAILED(hr)) 454 return target; 455 456 hr = pIShellLink->Resolve(NULL, SLR_UPDATE | SLR_NO_UI); 457 if (FAILED(hr)) 458 return target; 459 460 char pathA[MAX_PATH]; 461 WIN32_FIND_DATA wfd; 462 hr = pIShellLink->GetPath(pathA, MAX_PATH, &wfd, SLGP_RAWPATH); 463 if (FAILED(hr)) 464 return target; 465 466 wchar_t pathW[MAX_PATH]; 467 MultiByteToWideChar(CP_ACP, 0, pathA, -1, pathW, MAX_PATH); 468 target = pathW; 469 } 470 catch(sal::systools::ComError& ex) 471 { 472 OSL_ENSURE(false, ex.what()); 473 ex = ex; 474 } 475 return target; 476 } 477 478 typedef std::vector<std::wstring> FileList_t; 479 typedef FileList_t::value_type FileList_ValueType_t; 480 typedef Sequence<sal_Int8> ByteSequence_t; 481 482 /* Calculate the size required for turning a string list into 483 a double '\0' terminated string buffer */ 484 size_t CalcSizeForStringListBuffer(const FileList_t& fileList) 485 { 486 if (fileList.size() == 0) 487 return 0; 488 489 size_t size = 1; // one for the very final '\0' 490 FileList_t::const_iterator iter_end = fileList.end(); 491 for (FileList_t::const_iterator iter = fileList.begin(); iter != iter_end; ++iter) 492 { 493 size += iter->length() + 1; // length including terminating '\0' 494 } 495 return (size * sizeof(FileList_ValueType_t::value_type)); 496 } 497 498 ByteSequence_t FileListToByteSequence(const FileList_t& fileList) 499 { 500 ByteSequence_t bseq; 501 size_t size = CalcSizeForStringListBuffer(fileList); 502 503 if (size > 0) 504 { 505 bseq.realloc(size); 506 wchar_t* p = reinterpret_cast<wchar_t*>(bseq.getArray()); 507 ZeroMemory(p, size); 508 509 FileList_t::const_iterator iter; 510 FileList_t::const_iterator iter_end = fileList.end(); 511 for (iter = fileList.begin(); iter != iter_end; ++iter) 512 { 513 wcsncpy(p, iter->c_str(), iter->length()); 514 p += (iter->length() + 1); 515 } 516 } 517 return bseq; 518 } 519 520 ByteSequence_t CF_HDROPToFileList(HGLOBAL hGlobal) 521 { 522 UINT nFiles = DragQueryFileW((HDROP)hGlobal, 0xFFFFFFFF, NULL, 0); 523 FileList_t files; 524 525 for (UINT i = 0; i < nFiles; i++) 526 { 527 wchar_t buff[MAX_PATH]; 528 /*UINT size =*/ DragQueryFileW((HDROP)hGlobal, i, buff, MAX_PATH); 529 std::wstring filename = buff; 530 if (isShellLink(filename)) 531 filename = getShellLinkTarget(filename); 532 files.push_back(filename); 533 } 534 return FileListToByteSequence(files); 535 } 536 537 //------------------------------------------------------------------------ 538 // convert a windows bitmap handle into a openoffice bitmap 539 //------------------------------------------------------------------------ 540 541 Sequence< sal_Int8 > SAL_CALL WinBITMAPToOOBMP( HBITMAP aHBMP ) 542 { 543 Sequence< sal_Int8 > ooBmpStream; 544 545 SIZE aBmpSize; 546 if( GetBitmapDimensionEx( aHBMP, &aBmpSize ) ) 547 { 548 // fill bitmap info header 549 size_t nDataBytes = 4 * aBmpSize.cy * aBmpSize.cy; 550 Sequence< sal_Int8 > aBitmapStream( 551 sizeof(BITMAPINFO) + 552 nDataBytes 553 ); 554 PBITMAPINFOHEADER pBmp = (PBITMAPINFOHEADER)aBitmapStream.getArray(); 555 pBmp->biSize = sizeof( BITMAPINFOHEADER ); 556 pBmp->biWidth = aBmpSize.cx; 557 pBmp->biHeight = aBmpSize.cy; 558 pBmp->biPlanes = 1; 559 pBmp->biBitCount = 32; 560 pBmp->biCompression = BI_RGB; 561 pBmp->biSizeImage = (DWORD)nDataBytes; 562 pBmp->biXPelsPerMeter = 1000; 563 pBmp->biYPelsPerMeter = 1000; 564 pBmp->biClrUsed = 0; 565 pBmp->biClrImportant = 0; 566 if( GetDIBits( 0, // DC, 0 is a default GC, basically that of the desktop 567 aHBMP, 568 0, aBmpSize.cy, 569 aBitmapStream.getArray() + sizeof(BITMAPINFO), 570 (LPBITMAPINFO)pBmp, 571 DIB_RGB_COLORS ) ) 572 { 573 ooBmpStream = WinDIBToOOBMP( aBitmapStream ); 574 } 575 } 576 577 return ooBmpStream; 578 } 579 580