/*************************************************************************** * Copyright (c) 2011 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #pragma warning(disable : 4995) #include "Common.h" #include "ThumbnailProvider.h" #include #include #include #include #include CThumbnailProvider::CThumbnailProvider() { DllAddRef(); m_cRef = 1; m_pSite = NULL; } CThumbnailProvider::~CThumbnailProvider() { if (m_pSite) { m_pSite->Release(); m_pSite = NULL; } DllRelease(); } STDMETHODIMP CThumbnailProvider::QueryInterface(REFIID riid, void** ppvObject) { static const QITAB qit[] = { //QITABENT(CThumbnailProvider, IInitializeWithStream), QITABENT(CThumbnailProvider, IInitializeWithFile), QITABENT(CThumbnailProvider, IThumbnailProvider), QITABENT(CThumbnailProvider, IObjectWithSite), {0}, }; return QISearch(this, qit, riid, ppvObject); } STDMETHODIMP_(ULONG) CThumbnailProvider::AddRef() { LONG cRef = InterlockedIncrement(&m_cRef); return (ULONG)cRef; } STDMETHODIMP_(ULONG) CThumbnailProvider::Release() { LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return (ULONG)cRef; } STDMETHODIMP CThumbnailProvider::Initialize(IStream *pstm, DWORD grfMode) { return S_OK; } STDMETHODIMP CThumbnailProvider::Initialize(LPCWSTR pszFilePath, DWORD grfMode) { wcscpy_s(m_szFile, pszFilePath); return S_OK; } bool CThumbnailProvider::CheckZip() const { // open file and check magic number (PK\x03\x04) std::ifstream zip(m_szFile, std::ios::in | std::ios::binary); unsigned char pk[4] = {0x50, 0x4b, 0x03, 0x04}; for (int i=0; i<4; i++) { unsigned char c; if (!zip.get((char&)c)) return false; if (c != pk[i]) return false; } return true; } STDMETHODIMP CThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) { try { // first make sure we have a zip file but that might still be invalid if (!CheckZip()) return NOERROR; std::ifstream file(m_szFile, std::ios::in | std::ios::binary); zipios::ZipInputStream zipstream(file); zipios::ConstEntryPointer entry; entry = zipstream.getNextEntry(); while (entry->isValid() && entry->getName() != "thumbnails/Thumbnail.png") entry = zipstream.getNextEntry(); if (entry && entry->isValid()) { // ok, we have found the file. Now, read it in byte for byte std::istream *str = &zipstream; std::vector content; unsigned char c; while (str->get((char&)c)) { content.push_back(c); } // pass the memory buffer to CxImage library to create the bitmap handle CxMemFile mem(&(content[0]),content.size()); CxImagePNG png; png.Decode(&mem); *phbmp = png.MakeBitmap(); *pdwAlpha = WTSAT_UNKNOWN; } } catch(...) { // This may happen if the file is corrupted, not a valid zip file // or whatever could go wrong } return NOERROR; } STDMETHODIMP CThumbnailProvider::GetSite(REFIID riid, void** ppvSite) { if (m_pSite) { return m_pSite->QueryInterface(riid, ppvSite); } return E_NOINTERFACE; } STDMETHODIMP CThumbnailProvider::SetSite(IUnknown* pUnkSite) { if (m_pSite) { m_pSite->Release(); m_pSite = NULL; } m_pSite = pUnkSite; if (m_pSite) { m_pSite->AddRef(); } return S_OK; } STDAPI CThumbnailProvider_CreateInstance(REFIID riid, void** ppvObject) { *ppvObject = NULL; CThumbnailProvider* ptp = new CThumbnailProvider(); if (!ptp) { return E_OUTOFMEMORY; } HRESULT hr = ptp->QueryInterface(riid, ppvObject); ptp->Release(); return hr; }