Skip to content

Commit d60f053

Browse files
committed
Initial commit
0 parents  commit d60f053

16 files changed

Lines changed: 851 additions & 0 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
Debug
3+
Release
4+
.vs
5+
*.sdf
6+
*.vcxproj.user

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Radosław Eichler
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+

PsdThumbnailProvider.sln

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio 14
3+
VisualStudioVersion = 14.0.24720.0
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C9250E0E-3B03-4029-ADF0-0FA8B1AEB70A}"
6+
EndProject
7+
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "Setup\Setup.wixproj", "{EA1C995B-28A6-4036-911B-F83B361AC895}"
8+
EndProject
9+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PsdThumbnailProvider", "PsdThumbnailProvider\PsdThumbnailProvider.vcxproj", "{145AB33E-71A1-42C3-8223-E107CFC162F4}"
10+
EndProject
11+
Global
12+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
13+
Debug|Any CPU = Debug|Any CPU
14+
Debug|Mixed Platforms = Debug|Mixed Platforms
15+
Debug|Win32 = Debug|Win32
16+
Debug|x64 = Debug|x64
17+
Debug|x86 = Debug|x86
18+
Release|Any CPU = Release|Any CPU
19+
Release|Mixed Platforms = Release|Mixed Platforms
20+
Release|Win32 = Release|Win32
21+
Release|x64 = Release|x64
22+
Release|x86 = Release|x86
23+
EndGlobalSection
24+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
25+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|Any CPU.ActiveCfg = Debug|x86
26+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
27+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|Mixed Platforms.Build.0 = Debug|x86
28+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|Win32.ActiveCfg = Debug|x86
29+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|Win32.Build.0 = Debug|x86
30+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|x64.ActiveCfg = Debug|x64
31+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|x64.Build.0 = Debug|x64
32+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|x86.ActiveCfg = Debug|x86
33+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Debug|x86.Build.0 = Debug|x86
34+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|Any CPU.ActiveCfg = Release|x86
35+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|Mixed Platforms.ActiveCfg = Release|x86
36+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|Mixed Platforms.Build.0 = Release|x86
37+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|Win32.ActiveCfg = Release|x86
38+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|Win32.Build.0 = Release|x86
39+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|x64.ActiveCfg = Release|x64
40+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|x64.Build.0 = Release|x64
41+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|x86.ActiveCfg = Release|x86
42+
{EA1C995B-28A6-4036-911B-F83B361AC895}.Release|x86.Build.0 = Release|x86
43+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|Any CPU.ActiveCfg = Debug|Win32
44+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
45+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|Mixed Platforms.Build.0 = Debug|Win32
46+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|Win32.ActiveCfg = Debug|Win32
47+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|Win32.Build.0 = Debug|Win32
48+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|x64.ActiveCfg = Debug|x64
49+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|x64.Build.0 = Debug|x64
50+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|x86.ActiveCfg = Debug|Win32
51+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Debug|x86.Build.0 = Debug|Win32
52+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|Any CPU.ActiveCfg = Release|Win32
53+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|Mixed Platforms.ActiveCfg = Release|Win32
54+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|Mixed Platforms.Build.0 = Release|Win32
55+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|Win32.ActiveCfg = Release|Win32
56+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|Win32.Build.0 = Release|Win32
57+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|x64.ActiveCfg = Release|x64
58+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|x64.Build.0 = Release|x64
59+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|x86.ActiveCfg = Release|Win32
60+
{145AB33E-71A1-42C3-8223-E107CFC162F4}.Release|x86.Build.0 = Release|Win32
61+
EndGlobalSection
62+
GlobalSection(SolutionProperties) = preSolution
63+
HideSolutionNode = FALSE
64+
EndGlobalSection
65+
EndGlobal
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "ClassFactory.h"
2+
#include "PsdThumbnailProvider.h"
3+
#include <new>
4+
#include <Shlwapi.h>
5+
#pragma comment(lib, "shlwapi.lib")
6+
7+
extern long g_cDllRef;
8+
9+
ClassFactory::ClassFactory() : m_cRef(1) {
10+
InterlockedIncrement(&g_cDllRef);
11+
}
12+
13+
ClassFactory::~ClassFactory() {
14+
InterlockedDecrement(&g_cDllRef);
15+
}
16+
17+
// IUnknown
18+
19+
IFACEMETHODIMP ClassFactory::QueryInterface(REFIID riid, void **ppv) {
20+
static const QITAB qit[] =
21+
{
22+
QITABENT(ClassFactory, IClassFactory),
23+
{ 0 },
24+
};
25+
return QISearch(this, qit, riid, ppv);
26+
}
27+
28+
IFACEMETHODIMP_(ULONG) ClassFactory::AddRef() {
29+
return InterlockedIncrement(&m_cRef);
30+
}
31+
32+
IFACEMETHODIMP_(ULONG) ClassFactory::Release() {
33+
ULONG cRef = InterlockedDecrement(&m_cRef);
34+
if (0 == cRef) {
35+
delete this;
36+
}
37+
return cRef;
38+
}
39+
40+
// IClassFactory
41+
42+
IFACEMETHODIMP ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) {
43+
HRESULT hr = CLASS_E_NOAGGREGATION;
44+
45+
// pUnkOuter is used for aggregation. We do not support it in the sample.
46+
if (pUnkOuter == NULL) {
47+
hr = E_OUTOFMEMORY;
48+
49+
// Create the COM component.
50+
PsdThumbnailProvider *pExt = new (std::nothrow) PsdThumbnailProvider();
51+
52+
if (pExt) {
53+
// Query the specified interface.
54+
hr = pExt->QueryInterface(riid, ppv);
55+
pExt->Release();
56+
}
57+
}
58+
59+
return hr;
60+
}
61+
62+
IFACEMETHODIMP ClassFactory::LockServer(BOOL fLock) {
63+
if (fLock) {
64+
InterlockedIncrement(&g_cDllRef);
65+
} else {
66+
InterlockedDecrement(&g_cDllRef);
67+
}
68+
return S_OK;
69+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <unknwn.h> // For IClassFactory
4+
#include <windows.h>
5+
6+
class ClassFactory : public IClassFactory {
7+
public:
8+
// IUnknown
9+
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
10+
IFACEMETHODIMP_(ULONG) AddRef();
11+
IFACEMETHODIMP_(ULONG) Release();
12+
13+
// IClassFactory
14+
IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
15+
IFACEMETHODIMP LockServer(BOOL fLock);
16+
17+
ClassFactory();
18+
19+
protected:
20+
~ClassFactory();
21+
22+
private:
23+
long m_cRef;
24+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
LIBRARY "PsdThumbnailProvider"
2+
EXPORTS
3+
DllGetClassObject PRIVATE
4+
DllCanUnloadNow PRIVATE
5+
DllRegisterServer PRIVATE
6+
DllUnregisterServer PRIVATE
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "PsdThumbnailProvider.h"
2+
#include "gdiplus.h"
3+
#include <Shlwapi.h>
4+
5+
#pragma comment(lib, "Shlwapi.lib")
6+
7+
using namespace Gdiplus;
8+
9+
extern HINSTANCE g_hInst;
10+
extern long g_cDllRef;
11+
12+
void ReadData(IStream *pStream, BYTE *data, ULONG length) {
13+
ULONG read, total = 0;
14+
HRESULT hr;
15+
16+
do {
17+
hr = pStream->Read(data + total, length - total, &read);
18+
total += read;
19+
} while (total < length && hr == S_OK);
20+
}
21+
22+
UINT ReadUInt32(IStream *pStream) {
23+
BYTE b[4];
24+
ReadData(pStream, b, 4);
25+
return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
26+
}
27+
28+
USHORT ReadUInt16(IStream *pStream) {
29+
BYTE b[2];
30+
ReadData(pStream, b, 2);
31+
return b[0] << 8 | b[1];
32+
}
33+
34+
BYTE ReadByte(IStream *pStream) {
35+
BYTE b;
36+
ReadData(pStream, &b, 1);
37+
return b;
38+
}
39+
40+
void Seek(IStream *pStream, int offset, DWORD origin) {
41+
LARGE_INTEGER pos;
42+
pos.QuadPart = offset;
43+
pStream->Seek(pos, origin, NULL);
44+
}
45+
46+
PsdThumbnailProvider::PsdThumbnailProvider() : m_cRef(1), m_pStream(NULL) {
47+
InterlockedIncrement(&g_cDllRef);
48+
}
49+
50+
PsdThumbnailProvider::~PsdThumbnailProvider() {
51+
InterlockedDecrement(&g_cDllRef);
52+
}
53+
54+
// IUnknown
55+
56+
IFACEMETHODIMP PsdThumbnailProvider::QueryInterface(REFIID riid, void **ppv) {
57+
static const QITAB qit[] =
58+
{
59+
QITABENT(PsdThumbnailProvider, IThumbnailProvider),
60+
QITABENT(PsdThumbnailProvider, IInitializeWithStream),
61+
{ 0 },
62+
};
63+
return QISearch(this, qit, riid, ppv);
64+
}
65+
66+
IFACEMETHODIMP_(ULONG) PsdThumbnailProvider::AddRef() {
67+
return InterlockedIncrement(&m_cRef);
68+
}
69+
70+
IFACEMETHODIMP_(ULONG) PsdThumbnailProvider::Release() {
71+
ULONG cRef = InterlockedDecrement(&m_cRef);
72+
73+
if (0 == cRef)
74+
delete this;
75+
76+
return cRef;
77+
}
78+
79+
// IInitializeWithStream
80+
81+
IFACEMETHODIMP PsdThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode) {
82+
HRESULT hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
83+
84+
if (m_pStream == NULL)
85+
hr = pStream->QueryInterface(&m_pStream);
86+
87+
return hr;
88+
}
89+
90+
// IThumbnailProvider
91+
92+
IFACEMETHODIMP PsdThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) {
93+
*phbmp = NULL;
94+
*pdwAlpha = WTSAT_ARGB;
95+
96+
Seek(m_pStream, 4 + 2 + 6 + 2 + 4 + 4 + 2 + 2, STREAM_SEEK_SET);
97+
98+
UINT length = ReadUInt32(m_pStream);
99+
100+
if (length > 0)
101+
Seek(m_pStream, length, STREAM_SEEK_CUR);
102+
103+
UINT resourcesLength = ReadUInt32(m_pStream);
104+
UINT resourceAdvanced = 0;
105+
106+
while (resourcesLength > resourceAdvanced) {
107+
Seek(m_pStream, 4, STREAM_SEEK_CUR);
108+
109+
USHORT id = ReadUInt16(m_pStream);
110+
BYTE strl = ReadByte(m_pStream);
111+
112+
Seek(m_pStream, strl % 2 == 0 ? strl + 1 : strl, STREAM_SEEK_CUR);
113+
114+
length = ReadUInt32(m_pStream);
115+
116+
if (id == 1036) {
117+
ULONG_PTR token;
118+
GdiplusStartupInput input;
119+
120+
if (Ok == GdiplusStartup(&token, &input, NULL)) {
121+
Seek(m_pStream, 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2, STREAM_SEEK_CUR);
122+
123+
BYTE *data = new BYTE[length];
124+
125+
ReadData(m_pStream, data, length);
126+
127+
IStream *memory = SHCreateMemStream(data, length);
128+
129+
Seek(memory, 0, STREAM_SEEK_SET);
130+
131+
Bitmap *bitmap = Bitmap::FromStream(memory);
132+
Color color(0, 255, 255, 255);
133+
bitmap->GetHBITMAP(color, phbmp);
134+
delete bitmap;
135+
}
136+
137+
GdiplusShutdown(token);
138+
break;
139+
}
140+
141+
Seek(m_pStream, length % 2 ? length + 1 : length, STREAM_SEEK_CUR);
142+
143+
resourceAdvanced += 6 + 1 + (strl % 2 == 0 ? strl + 1 : strl) +
144+
4 + (length % 2 ? length + 1 : length);
145+
}
146+
147+
return *phbmp != NULL ? NOERROR : E_NOTIMPL;
148+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include <windows.h>
4+
#include <thumbcache.h>
5+
#include <wincodec.h>
6+
7+
#pragma comment(lib, "windowscodecs.lib")
8+
9+
class PsdThumbnailProvider :
10+
public IInitializeWithStream,
11+
public IThumbnailProvider {
12+
public:
13+
// IUnknown
14+
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
15+
IFACEMETHODIMP_(ULONG) AddRef();
16+
IFACEMETHODIMP_(ULONG) Release();
17+
18+
// IInitializeWithStream
19+
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
20+
21+
// IThumbnailProvider
22+
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
23+
24+
PsdThumbnailProvider();
25+
26+
protected:
27+
~PsdThumbnailProvider();
28+
29+
private:
30+
long m_cRef;
31+
IStream *m_pStream;
32+
};

0 commit comments

Comments
 (0)