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