| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #pragma warning(disable : 4995) |
| |
|
| | #include "ThumbnailProvider.h" |
| | #include "Common.h" |
| |
|
| | #include <iostream> |
| | #include <wincodec.h> |
| | #include <wincodecsdk.h> |
| | #include <zipios++/zipfile.h> |
| | #include <zipios++/zipinputstream.h> |
| | #pragma comment(lib, "WindowsCodecs.lib") |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | IStream* CreateStreamOnResource(void* buffer, size_t length) |
| | { |
| | |
| | IStream* ipStream = NULL; |
| |
|
| | |
| | HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, length); |
| | if (hgblResourceData == NULL) { |
| | goto Return; |
| | } |
| |
|
| | |
| | LPVOID pvResourceData = GlobalLock(hgblResourceData); |
| | if (pvResourceData == NULL) { |
| | goto FreeData; |
| | } |
| |
|
| | |
| | CopyMemory(pvResourceData, buffer, length); |
| | GlobalUnlock(hgblResourceData); |
| |
|
| | |
| |
|
| | if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream))) { |
| | goto Return; |
| | } |
| |
|
| | FreeData: |
| | |
| |
|
| | GlobalFree(hgblResourceData); |
| |
|
| | Return: |
| | |
| | return ipStream; |
| | } |
| |
|
| | IWICBitmapSource* LoadBitmapFromStream(IStream* ipImageStream) |
| | { |
| | |
| | IWICBitmapSource* ipBitmap = NULL; |
| |
|
| | |
| | IWICBitmapDecoder* ipDecoder = NULL; |
| | if (FAILED(CoCreateInstance( |
| | CLSID_WICPngDecoder, |
| | NULL, |
| | CLSCTX_INPROC_SERVER, |
| | __uuidof(ipDecoder), |
| | reinterpret_cast<void**>(&ipDecoder) |
| | ))) { |
| | goto Return; |
| | } |
| |
|
| | |
| | if (FAILED(ipDecoder->Initialize(ipImageStream, WICDecodeMetadataCacheOnLoad))) { |
| | goto ReleaseDecoder; |
| | } |
| |
|
| | |
| | UINT nFrameCount = 0; |
| | if (FAILED(ipDecoder->GetFrameCount(&nFrameCount)) || nFrameCount != 1) { |
| | goto ReleaseDecoder; |
| | } |
| |
|
| | |
| | IWICBitmapFrameDecode* ipFrame = NULL; |
| | if (FAILED(ipDecoder->GetFrame(0, &ipFrame))) { |
| | goto ReleaseDecoder; |
| | } |
| |
|
| | |
| | |
| | |
| | WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, ipFrame, &ipBitmap); |
| | ipFrame->Release(); |
| |
|
| | ReleaseDecoder: |
| | ipDecoder->Release(); |
| | Return: |
| | return ipBitmap; |
| | } |
| |
|
| | HBITMAP CreateHBITMAP(IWICBitmapSource* ipBitmap) |
| | { |
| | |
| | HBITMAP hbmp = NULL; |
| |
|
| | |
| | UINT width = 0; |
| | UINT height = 0; |
| | if (FAILED(ipBitmap->GetSize(&width, &height)) || width == 0 || height == 0) { |
| | goto Return; |
| | } |
| |
|
| | |
| | BITMAPINFO bminfo; |
| | ZeroMemory(&bminfo, sizeof(bminfo)); |
| | bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
| | bminfo.bmiHeader.biWidth = width; |
| | bminfo.bmiHeader.biHeight = -((LONG)height); |
| | bminfo.bmiHeader.biPlanes = 1; |
| | bminfo.bmiHeader.biBitCount = 32; |
| | bminfo.bmiHeader.biCompression = BI_RGB; |
| |
|
| | |
| | void* pvImageBits = NULL; |
| | HDC hdcScreen = GetDC(NULL); |
| | hbmp = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0); |
| | ReleaseDC(NULL, hdcScreen); |
| | if (hbmp == NULL) { |
| | goto Return; |
| | } |
| |
|
| | |
| |
|
| | const UINT cbStride = width * 4; |
| | const UINT cbImage = cbStride * height; |
| | if (FAILED(ipBitmap->CopyPixels(NULL, cbStride, cbImage, static_cast<BYTE*>(pvImageBits)))) { |
| | |
| |
|
| | DeleteObject(hbmp); |
| | hbmp = NULL; |
| | } |
| |
|
| | Return: |
| | return hbmp; |
| | } |
| |
|
| | 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, 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 |
| | { |
| | |
| | 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 { |
| | |
| | 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()) { |
| | |
| | std::istream* str = &zipstream; |
| | std::vector<unsigned char> content; |
| | unsigned char c; |
| | while (str->get((char&)c)) { |
| | content.push_back(c); |
| | } |
| |
|
| | |
| | IStream* stream = CreateStreamOnResource(&(content[0]), content.size()); |
| | if (stream) { |
| | IWICBitmapSource* bmpSrc = LoadBitmapFromStream(stream); |
| | stream->Release(); |
| | if (bmpSrc) { |
| | *phbmp = CreateHBITMAP(bmpSrc); |
| | *pdwAlpha = WTSAT_UNKNOWN; |
| | bmpSrc->Release(); |
| | } |
| | } |
| | } |
| | } |
| | catch (...) { |
| | |
| | |
| | } |
| |
|
| | 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; |
| | } |
| |
|