1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_shell.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include "internal/global.hxx" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #ifndef INFOTIPS_HXX_INCLUDED 34*cdf0e10cSrcweir #include "internal/thumbviewer.hxx" 35*cdf0e10cSrcweir #endif 36*cdf0e10cSrcweir #include "internal/shlxthdl.hxx" 37*cdf0e10cSrcweir #include "internal/registry.hxx" 38*cdf0e10cSrcweir #include "internal/fileextensions.hxx" 39*cdf0e10cSrcweir #include "internal/config.hxx" 40*cdf0e10cSrcweir #include "internal/zipfile.hxx" 41*cdf0e10cSrcweir #include "internal/utilities.hxx" 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include "internal/resource.h" 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <stdio.h> 46*cdf0e10cSrcweir #include <utility> 47*cdf0e10cSrcweir #include <stdlib.h> 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #if defined _MSC_VER 50*cdf0e10cSrcweir #pragma warning(push, 1) 51*cdf0e10cSrcweir #endif 52*cdf0e10cSrcweir #include <shellapi.h> 53*cdf0e10cSrcweir #if defined _MSC_VER 54*cdf0e10cSrcweir #pragma warning(pop) 55*cdf0e10cSrcweir #endif 56*cdf0e10cSrcweir #include <memory> 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir extern HINSTANCE g_hModule; 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir namespace internal 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir /* The signet.png used for thumbnails of signed documents 63*cdf0e10cSrcweir is contained as resource in this module, the resource 64*cdf0e10cSrcweir id is 2000 */ 65*cdf0e10cSrcweir void LoadSignetImageFromResource(ZipFile::ZipContentBuffer_t& buffer) 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir HRSRC hrc = FindResource(g_hModule, TEXT("#2000"), RT_RCDATA); 68*cdf0e10cSrcweir DWORD size = SizeofResource(g_hModule, hrc); 69*cdf0e10cSrcweir HGLOBAL hglob = LoadResource(g_hModule, hrc); 70*cdf0e10cSrcweir char* data = reinterpret_cast<char*>(LockResource(hglob)); 71*cdf0e10cSrcweir buffer = ZipFile::ZipContentBuffer_t(data, data + size); 72*cdf0e10cSrcweir } 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir bool IsSignedDocument(const ZipFile* zipfile) 75*cdf0e10cSrcweir { 76*cdf0e10cSrcweir return zipfile->HasContent("META-INF/documentsignatures.xml"); 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir bool IsWindowsXP() 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir OSVERSIONINFO osvi; 82*cdf0e10cSrcweir ZeroMemory(&osvi, sizeof(osvi)); 83*cdf0e10cSrcweir osvi.dwOSVersionInfoSize = sizeof(osvi); 84*cdf0e10cSrcweir GetVersionEx(&osvi); 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir return ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && 87*cdf0e10cSrcweir ((osvi.dwMajorVersion >= 5) && (osvi.dwMinorVersion >= 1))); 88*cdf0e10cSrcweir } 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir /* Calculate where to position the signet image. 91*cdf0e10cSrcweir On Windows ME we need to shift the signet a 92*cdf0e10cSrcweir little bit to the left because Windows ME 93*cdf0e10cSrcweir puts an overlay icon to the lower right 94*cdf0e10cSrcweir corner of a thumbnail image so that our signet 95*cdf0e10cSrcweir we be hidden. */ 96*cdf0e10cSrcweir Gdiplus::Point CalcSignetPosition( 97*cdf0e10cSrcweir const Gdiplus::Rect& canvas, const Gdiplus::Rect& thumbnail_border, const Gdiplus::Rect& signet) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir int x = 0; 100*cdf0e10cSrcweir int y = 0; 101*cdf0e10cSrcweir int hoffset = canvas.GetRight() - thumbnail_border.GetRight(); 102*cdf0e10cSrcweir int voffset = canvas.GetBottom() - thumbnail_border.GetBottom(); 103*cdf0e10cSrcweir 104*cdf0e10cSrcweir if (hoffset > voffset) 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir x = thumbnail_border.GetRight() - signet.GetRight() + min(signet.GetRight() / 2, hoffset); 107*cdf0e10cSrcweir y = thumbnail_border.GetBottom() - signet.GetBottom(); 108*cdf0e10cSrcweir } 109*cdf0e10cSrcweir else 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir x = thumbnail_border.GetRight() - signet.GetRight(); 112*cdf0e10cSrcweir y = thumbnail_border.GetBottom() - signet.GetBottom() + min(signet.GetBottom() / 2, voffset); 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir if (!IsWindowsXP()) 116*cdf0e10cSrcweir x -= 15; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir return Gdiplus::Point(x,y); 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir } 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir class StreamOnZipBuffer : public IStream 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir public: 125*cdf0e10cSrcweir StreamOnZipBuffer(const ZipFile::ZipContentBuffer_t& zip_buffer); 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir // IUnknown 128*cdf0e10cSrcweir virtual ULONG STDMETHODCALLTYPE AddRef(); 129*cdf0e10cSrcweir virtual ULONG STDMETHODCALLTYPE Release( void); 130*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject); 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir // IStream 133*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead); 134*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Write(void const *pv, ULONG cb, ULONG *pcbWritten); 135*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); 136*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize); 137*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); 138*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags); 139*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Revert(void); 140*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); 141*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); 142*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag); 143*cdf0e10cSrcweir virtual HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm); 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir private: 146*cdf0e10cSrcweir LONG ref_count_; 147*cdf0e10cSrcweir const ZipFile::ZipContentBuffer_t& ref_zip_buffer_; 148*cdf0e10cSrcweir size_t pos_; 149*cdf0e10cSrcweir }; 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir StreamOnZipBuffer::StreamOnZipBuffer(const ZipFile::ZipContentBuffer_t& zip_buffer) : 152*cdf0e10cSrcweir ref_count_(1), 153*cdf0e10cSrcweir ref_zip_buffer_(zip_buffer), 154*cdf0e10cSrcweir pos_(0) 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir 158*cdf0e10cSrcweir // IUnknown methods 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir ULONG STDMETHODCALLTYPE StreamOnZipBuffer::AddRef(void) 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir return InterlockedIncrement(&ref_count_); 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir ULONG STDMETHODCALLTYPE StreamOnZipBuffer::Release( void) 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir long refcnt = InterlockedDecrement(&ref_count_); 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir if (0 == ref_count_) 170*cdf0e10cSrcweir delete this; 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir return refcnt; 173*cdf0e10cSrcweir } 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir *ppvObject = 0; 178*cdf0e10cSrcweir IUnknown* pUnk = 0; 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir if ((IID_IUnknown == riid) || (IID_IStream == riid)) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir pUnk = static_cast<IStream*>(this); 183*cdf0e10cSrcweir pUnk->AddRef(); 184*cdf0e10cSrcweir *ppvObject = pUnk; 185*cdf0e10cSrcweir return S_OK; 186*cdf0e10cSrcweir } 187*cdf0e10cSrcweir return E_NOINTERFACE; 188*cdf0e10cSrcweir } 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Read(void *pv, ULONG cb, ULONG *pcbRead) 191*cdf0e10cSrcweir { 192*cdf0e10cSrcweir if (pv == NULL) 193*cdf0e10cSrcweir return STG_E_INVALIDPOINTER; 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir size_t size = ref_zip_buffer_.size(); 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir if (pos_ > size) 198*cdf0e10cSrcweir return S_FALSE; 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir char* p = reinterpret_cast<char*>(pv); 201*cdf0e10cSrcweir ULONG read = 0; 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir for ( ;(pos_ < size) && (cb > 0); pos_++, cb--, read++) 204*cdf0e10cSrcweir *p++ = ref_zip_buffer_[pos_]; 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir if (pcbRead) 207*cdf0e10cSrcweir *pcbRead = read; 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir return S_OK; 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *) 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir __int64 size = (__int64) ref_zip_buffer_.size(); 215*cdf0e10cSrcweir __int64 p = 0; 216*cdf0e10cSrcweir 217*cdf0e10cSrcweir switch (dwOrigin) 218*cdf0e10cSrcweir { 219*cdf0e10cSrcweir case STREAM_SEEK_SET: 220*cdf0e10cSrcweir break; 221*cdf0e10cSrcweir case STREAM_SEEK_CUR: 222*cdf0e10cSrcweir p = (__int64) pos_; 223*cdf0e10cSrcweir break; 224*cdf0e10cSrcweir case STREAM_SEEK_END: 225*cdf0e10cSrcweir p = size - 1; 226*cdf0e10cSrcweir break; 227*cdf0e10cSrcweir } 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir HRESULT hr = STG_E_INVALIDFUNCTION; 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir p += dlibMove.QuadPart; 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir if ( ( p >= 0 ) && (p < size) ) 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir pos_ = (size_t) p; 236*cdf0e10cSrcweir hr = S_OK; 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir return hr; 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Stat(STATSTG *pstatstg, DWORD grfStatFlag) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir if (pstatstg == NULL) 244*cdf0e10cSrcweir return STG_E_INVALIDPOINTER; 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir ZeroMemory(pstatstg, sizeof(STATSTG)); 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir if (grfStatFlag == STATFLAG_DEFAULT) 249*cdf0e10cSrcweir { 250*cdf0e10cSrcweir size_t sz = 4 * sizeof(wchar_t); 251*cdf0e10cSrcweir wchar_t* name = reinterpret_cast<wchar_t*>(CoTaskMemAlloc(sz)); 252*cdf0e10cSrcweir ZeroMemory(name, sz); 253*cdf0e10cSrcweir memcpy(name, L"png", 3 * sizeof(wchar_t)); 254*cdf0e10cSrcweir pstatstg->pwcsName = name; 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir pstatstg->type = STGTY_LOCKBYTES; 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir ULARGE_INTEGER uli; 260*cdf0e10cSrcweir uli.LowPart = ref_zip_buffer_.size(); 261*cdf0e10cSrcweir uli.HighPart = 0; 262*cdf0e10cSrcweir 263*cdf0e10cSrcweir pstatstg->cbSize = uli; 264*cdf0e10cSrcweir 265*cdf0e10cSrcweir return S_OK; 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Write(void const *, ULONG, ULONG *) 269*cdf0e10cSrcweir { return E_NOTIMPL; } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::SetSize(ULARGE_INTEGER) 272*cdf0e10cSrcweir { return E_NOTIMPL; } 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::CopyTo(IStream *, ULARGE_INTEGER, ULARGE_INTEGER *, ULARGE_INTEGER *) 275*cdf0e10cSrcweir { return E_NOTIMPL; } 276*cdf0e10cSrcweir 277*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Commit(DWORD) 278*cdf0e10cSrcweir { return E_NOTIMPL; } 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Revert(void) 281*cdf0e10cSrcweir { return E_NOTIMPL; } 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) 284*cdf0e10cSrcweir { return E_NOTIMPL; } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) 287*cdf0e10cSrcweir { return E_NOTIMPL; } 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Clone(IStream **) 290*cdf0e10cSrcweir { return E_NOTIMPL; } 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir //######################################### 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir CThumbviewer::CThumbviewer(long RefCnt) : 297*cdf0e10cSrcweir ref_count_(RefCnt) 298*cdf0e10cSrcweir { 299*cdf0e10cSrcweir InterlockedIncrement(&g_DllRefCnt); 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir thumbnail_size_.cx = 0; 302*cdf0e10cSrcweir thumbnail_size_.cy = 0; 303*cdf0e10cSrcweir 304*cdf0e10cSrcweir Gdiplus::GdiplusStartupInput gdiplusStartupInput; 305*cdf0e10cSrcweir Gdiplus::GdiplusStartup(&gdiplus_token_, &gdiplusStartupInput, NULL); 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir ZipFile::ZipContentBuffer_t img_data; 308*cdf0e10cSrcweir internal::LoadSignetImageFromResource(img_data); 309*cdf0e10cSrcweir IStream* stream = new StreamOnZipBuffer(img_data); 310*cdf0e10cSrcweir signet_ = new Gdiplus::Bitmap(stream, TRUE); 311*cdf0e10cSrcweir stream->Release(); 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir CThumbviewer::~CThumbviewer() 315*cdf0e10cSrcweir { 316*cdf0e10cSrcweir delete signet_; 317*cdf0e10cSrcweir Gdiplus::GdiplusShutdown(gdiplus_token_); 318*cdf0e10cSrcweir InterlockedDecrement(&g_DllRefCnt); 319*cdf0e10cSrcweir } 320*cdf0e10cSrcweir 321*cdf0e10cSrcweir // IUnknown methods 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir *ppvObject = 0; 326*cdf0e10cSrcweir IUnknown* pUnk = 0; 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir if ((IID_IUnknown == riid) || (IID_IPersistFile == riid)) 329*cdf0e10cSrcweir { 330*cdf0e10cSrcweir pUnk = static_cast<IPersistFile*>(this); 331*cdf0e10cSrcweir pUnk->AddRef(); 332*cdf0e10cSrcweir *ppvObject = pUnk; 333*cdf0e10cSrcweir return S_OK; 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir else if (IID_IExtractImage == riid) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir pUnk = static_cast<IExtractImage*>(this); 338*cdf0e10cSrcweir pUnk->AddRef(); 339*cdf0e10cSrcweir *ppvObject = pUnk; 340*cdf0e10cSrcweir return S_OK; 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir return E_NOINTERFACE; 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir ULONG STDMETHODCALLTYPE CThumbviewer::AddRef(void) 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir return InterlockedIncrement(&ref_count_); 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir ULONG STDMETHODCALLTYPE CThumbviewer::Release( void) 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir long refcnt = InterlockedDecrement(&ref_count_); 353*cdf0e10cSrcweir 354*cdf0e10cSrcweir if (0 == ref_count_) 355*cdf0e10cSrcweir delete this; 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir return refcnt; 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir // IExtractImage2 methods 361*cdf0e10cSrcweir 362*cdf0e10cSrcweir const std::string THUMBNAIL_CONTENT = "Thumbnails/thumbnail.png"; 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::Extract(HBITMAP *phBmpImage) 365*cdf0e10cSrcweir { 366*cdf0e10cSrcweir HRESULT hr = E_FAIL; 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir try 369*cdf0e10cSrcweir { 370*cdf0e10cSrcweir std::wstring fname = getShortPathName( filename_ ); 371*cdf0e10cSrcweir std::auto_ptr<ZipFile> zipfile( new ZipFile( WStringToString( fname ) ) ); 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir if (zipfile->HasContent(THUMBNAIL_CONTENT)) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir ZipFile::ZipContentBuffer_t thumbnail; 376*cdf0e10cSrcweir zipfile->GetUncompressedContent(THUMBNAIL_CONTENT, thumbnail); 377*cdf0e10cSrcweir IStream* stream = new StreamOnZipBuffer(thumbnail); 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir Gdiplus::Bitmap thumbnail_png(stream, TRUE); 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir if ((thumbnail_png.GetHeight() == 0) || (thumbnail_png.GetWidth() == 0)) 382*cdf0e10cSrcweir { 383*cdf0e10cSrcweir stream->Release(); 384*cdf0e10cSrcweir return E_FAIL; 385*cdf0e10cSrcweir } 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir HWND hwnd = GetDesktopWindow(); 388*cdf0e10cSrcweir HDC hdc = GetDC(hwnd); 389*cdf0e10cSrcweir HDC memDC = CreateCompatibleDC(hdc); 390*cdf0e10cSrcweir 391*cdf0e10cSrcweir if (memDC) 392*cdf0e10cSrcweir { 393*cdf0e10cSrcweir UINT offset = 3; // reserve a little border space 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir Gdiplus::Rect canvas(0, 0, thumbnail_size_.cx, thumbnail_size_.cy); 396*cdf0e10cSrcweir Gdiplus::Rect canvas_thumbnail(offset, offset, thumbnail_size_.cx - 2 * offset, thumbnail_size_.cy - 2 * offset); 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir Gdiplus::Rect scaledRect = CalcScaledAspectRatio( 399*cdf0e10cSrcweir Gdiplus::Rect(0, 0, thumbnail_png.GetWidth(), thumbnail_png.GetHeight()), canvas_thumbnail); 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir struct { 402*cdf0e10cSrcweir BITMAPINFOHEADER bi; 403*cdf0e10cSrcweir DWORD ct[256]; 404*cdf0e10cSrcweir } dib; 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir ZeroMemory(&dib, sizeof(dib)); 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir dib.bi.biSize = sizeof(BITMAPINFOHEADER); 409*cdf0e10cSrcweir dib.bi.biWidth = thumbnail_size_.cx; 410*cdf0e10cSrcweir dib.bi.biHeight = thumbnail_size_.cy; 411*cdf0e10cSrcweir dib.bi.biPlanes = 1; 412*cdf0e10cSrcweir dib.bi.biBitCount = static_cast<WORD>(color_depth_); 413*cdf0e10cSrcweir dib.bi.biCompression = BI_RGB; 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir LPVOID lpBits; 416*cdf0e10cSrcweir HBITMAP hMemBmp = CreateDIBSection(memDC, (LPBITMAPINFO)&dib, DIB_RGB_COLORS, &lpBits, NULL, 0); 417*cdf0e10cSrcweir HGDIOBJ hOldObj = SelectObject(memDC, hMemBmp); 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir Gdiplus::Graphics graphics(memDC); 420*cdf0e10cSrcweir Gdiplus::Pen blackPen(Gdiplus::Color(255, 0, 0, 0), 1); 421*cdf0e10cSrcweir 422*cdf0e10cSrcweir Gdiplus::SolidBrush whiteBrush(Gdiplus::Color(255, 255, 255, 255)); 423*cdf0e10cSrcweir graphics.FillRectangle(&whiteBrush, canvas); 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir scaledRect.X = (canvas.Width - scaledRect.Width) / 2; 426*cdf0e10cSrcweir scaledRect.Y = (canvas.Height - scaledRect.Height) / 2; 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir Gdiplus::Rect border_rect(scaledRect.X, scaledRect.Y, scaledRect.Width, scaledRect.Height); 429*cdf0e10cSrcweir graphics.DrawRectangle(&blackPen, border_rect); 430*cdf0e10cSrcweir 431*cdf0e10cSrcweir scaledRect.X += 1; 432*cdf0e10cSrcweir scaledRect.Y += 1; 433*cdf0e10cSrcweir scaledRect.Width -= 1; 434*cdf0e10cSrcweir scaledRect.Height -= 1; 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic); 437*cdf0e10cSrcweir Gdiplus::Status stat = graphics.DrawImage( 438*cdf0e10cSrcweir &thumbnail_png, scaledRect, 0 , 0, 439*cdf0e10cSrcweir thumbnail_png.GetWidth(), thumbnail_png.GetHeight(), Gdiplus::UnitPixel); 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir /* Add a signet sign to the thumbnail of signed documents */ 442*cdf0e10cSrcweir if (internal::IsSignedDocument(zipfile.get())) 443*cdf0e10cSrcweir { 444*cdf0e10cSrcweir double SCALING_FACTOR = 0.6; 445*cdf0e10cSrcweir Gdiplus::Rect signet_scaled( 446*cdf0e10cSrcweir 0, 0, static_cast<INT>(signet_->GetWidth() * SCALING_FACTOR), static_cast<INT>(signet_->GetHeight() * SCALING_FACTOR)); 447*cdf0e10cSrcweir Gdiplus::Point pos_signet = internal::CalcSignetPosition(canvas_thumbnail, border_rect, signet_scaled); 448*cdf0e10cSrcweir Gdiplus::Rect dest(pos_signet.X, pos_signet.Y, signet_scaled.GetRight(), signet_scaled.GetBottom()); 449*cdf0e10cSrcweir 450*cdf0e10cSrcweir stat = graphics.DrawImage( 451*cdf0e10cSrcweir signet_, dest, 452*cdf0e10cSrcweir 0, 0, signet_->GetWidth(), signet_->GetHeight(), 453*cdf0e10cSrcweir Gdiplus::UnitPixel); 454*cdf0e10cSrcweir } 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir if (stat == Gdiplus::Ok) 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir *phBmpImage = hMemBmp; 459*cdf0e10cSrcweir hr = NOERROR; 460*cdf0e10cSrcweir } 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir SelectObject(memDC, hOldObj); 463*cdf0e10cSrcweir DeleteDC(memDC); 464*cdf0e10cSrcweir } 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir ReleaseDC(hwnd, hdc); 467*cdf0e10cSrcweir stream->Release(); 468*cdf0e10cSrcweir } 469*cdf0e10cSrcweir } 470*cdf0e10cSrcweir catch(std::exception&) 471*cdf0e10cSrcweir { 472*cdf0e10cSrcweir OutputDebugStringFormat( "CThumbviewer Extract ERROR!\n" ); 473*cdf0e10cSrcweir hr = E_FAIL; 474*cdf0e10cSrcweir } 475*cdf0e10cSrcweir return hr; 476*cdf0e10cSrcweir } 477*cdf0e10cSrcweir 478*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::GetLocation( 479*cdf0e10cSrcweir LPWSTR pszPathBuffer, DWORD cchMax, DWORD *pdwPriority, const SIZE *prgSize, DWORD dwRecClrDepth, DWORD *pdwFlags) 480*cdf0e10cSrcweir { 481*cdf0e10cSrcweir if ((prgSize == NULL) || (pdwFlags == NULL) || ((*pdwFlags & IEIFLAG_ASYNC) && (pdwPriority == NULL))) 482*cdf0e10cSrcweir return E_INVALIDARG; 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir thumbnail_size_ = *prgSize; 485*cdf0e10cSrcweir color_depth_ = dwRecClrDepth; 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir *pdwFlags = IEIFLAG_CACHE; // we don't cache the image 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir wcsncpy(pszPathBuffer, filename_.c_str(), cchMax); 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir return NOERROR; 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir // IPersist methods 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::GetClassID(CLSID* pClassID) 497*cdf0e10cSrcweir { 498*cdf0e10cSrcweir pClassID = const_cast<CLSID*>(&CLSID_THUMBVIEWER_HANDLER); 499*cdf0e10cSrcweir return S_OK; 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir 502*cdf0e10cSrcweir // IPersistFile methods 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::Load(LPCOLESTR pszFileName, DWORD) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir filename_ = pszFileName; 507*cdf0e10cSrcweir return S_OK; 508*cdf0e10cSrcweir } 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::IsDirty() 511*cdf0e10cSrcweir { return E_NOTIMPL; } 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::Save(LPCOLESTR, BOOL) 514*cdf0e10cSrcweir { return E_NOTIMPL; } 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::SaveCompleted(LPCOLESTR) 517*cdf0e10cSrcweir { return E_NOTIMPL; } 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir HRESULT STDMETHODCALLTYPE CThumbviewer::GetCurFile(LPOLESTR __RPC_FAR*) 520*cdf0e10cSrcweir { return E_NOTIMPL; } 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir Gdiplus::Rect CThumbviewer::CalcScaledAspectRatio(Gdiplus::Rect src, Gdiplus::Rect dest) 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir Gdiplus::Rect result; 526*cdf0e10cSrcweir if (src.Width >= src.Height) 527*cdf0e10cSrcweir result = Gdiplus::Rect(0, 0, dest.Width, src.Height * dest.Width / src.Width); 528*cdf0e10cSrcweir else 529*cdf0e10cSrcweir result = Gdiplus::Rect(0, 0, src.Width * dest.Height / src.Height, dest.Height); 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir return result; 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir 534