Blender  V2.93
Dll.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include <new>
18 #include <objbase.h>
19 #include <shlobj.h> // For SHChangeNotify
20 #include <shlwapi.h>
21 #include <thumbcache.h> // For IThumbnailProvider.
22 
23 extern HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv);
24 
25 #define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
26 #define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler"
27 const CLSID CLSID_BlendThumbHandler = {
28  0xd45f043d, 0xf17f, 0x4e8a, {0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d}};
29 
30 typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject);
32  const CLSID *pClsid;
34 };
35 
36 // add classes supported by this module here
39 
40 long g_cRefModule = 0;
41 
42 // Handle the DLL's module
43 HINSTANCE g_hInst = NULL;
44 
45 // Standard DLL functions
46 STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
47 {
48  if (dwReason == DLL_PROCESS_ATTACH) {
49  g_hInst = hInstance;
50  DisableThreadLibraryCalls(hInstance);
51  }
52  return TRUE;
53 }
54 
56 {
57  // Only allow the DLL to be unloaded after all outstanding references have been released
58  return (g_cRefModule == 0) ? S_OK : S_FALSE;
59 }
60 
61 void DllAddRef()
62 {
63  InterlockedIncrement(&g_cRefModule);
64 }
65 
66 void DllRelease()
67 {
68  InterlockedDecrement(&g_cRefModule);
69 }
70 
71 class CClassFactory : public IClassFactory {
72  public:
73  static HRESULT CreateInstance(REFCLSID clsid,
74  const CLASS_OBJECT_INIT *pClassObjectInits,
75  size_t cClassObjectInits,
76  REFIID riid,
77  void **ppv)
78  {
79  *ppv = NULL;
80  HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
81  for (size_t i = 0; i < cClassObjectInits; i++) {
82  if (clsid == *pClassObjectInits[i].pClsid) {
83  IClassFactory *pClassFactory = new (std::nothrow)
84  CClassFactory(pClassObjectInits[i].pfnCreate);
85  hr = pClassFactory ? S_OK : E_OUTOFMEMORY;
86  if (SUCCEEDED(hr)) {
87  hr = pClassFactory->QueryInterface(riid, ppv);
88  pClassFactory->Release();
89  }
90  break; // match found
91  }
92  }
93  return hr;
94  }
95 
96  CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate)
97  {
98  DllAddRef();
99  }
100 
101  // IUnknown
102  IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
103  {
104  static const QITAB qit[] = {QITABENT(CClassFactory, IClassFactory), {0}};
105  return QISearch(this, qit, riid, ppv);
106  }
107 
108  IFACEMETHODIMP_(ULONG) AddRef()
109  {
110  return InterlockedIncrement(&_cRef);
111  }
112 
113  IFACEMETHODIMP_(ULONG) Release()
114  {
115  long cRef = InterlockedDecrement(&_cRef);
116  if (cRef == 0) {
117  delete this;
118  }
119  return cRef;
120  }
121 
122  // IClassFactory
123  IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
124  {
125  return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv);
126  }
127 
128  IFACEMETHODIMP LockServer(BOOL fLock)
129  {
130  if (fLock) {
131  DllAddRef();
132  }
133  else {
134  DllRelease();
135  }
136  return S_OK;
137  }
138 
139  private:
140  ~CClassFactory()
141  {
142  DllRelease();
143  }
144 
145  long _cRef;
146  PFNCREATEINSTANCE _pfnCreate;
147 };
148 
149 STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
150 {
152  clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv);
153 }
154 
155 // A struct to hold the information required for a registry entry
156 
158  HKEY hkeyRoot;
159  PCWSTR pszKeyName;
160  PCWSTR pszValueName;
161  DWORD dwValueType;
162  PCWSTR pszData; // These two fields could/should have been a union, but C++
163  DWORD dwData; // only lets you initialize the first field in a union.
164 };
165 
166 // Creates a registry key (if needed) and sets the default value of the key
167 
168 HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
169 {
170  HKEY hKey;
171  HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot,
172  pRegistryEntry->pszKeyName,
173  0,
174  NULL,
175  REG_OPTION_NON_VOLATILE,
176  KEY_SET_VALUE,
177  NULL,
178  &hKey,
179  NULL));
180  if (SUCCEEDED(hr)) {
181  // All this just to support REG_DWORD...
182  DWORD size;
183  DWORD data;
184  BYTE *lpData = (LPBYTE)pRegistryEntry->pszData;
185  switch (pRegistryEntry->dwValueType) {
186  case REG_SZ:
187  size = ((DWORD)wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR);
188  break;
189  case REG_DWORD:
190  size = sizeof(DWORD);
191  data = pRegistryEntry->dwData;
192  lpData = (BYTE *)&data;
193  break;
194  default:
195  return E_INVALIDARG;
196  }
197 
198  hr = HRESULT_FROM_WIN32(RegSetValueExW(
199  hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType, lpData, size));
200  RegCloseKey(hKey);
201  }
202  return hr;
203 }
204 
205 //
206 // Registers this COM server
207 //
209 {
210  HRESULT hr;
211 
212  WCHAR szModuleName[MAX_PATH];
213 
214  if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName))) {
215  hr = HRESULT_FROM_WIN32(GetLastError());
216  }
217  else {
218  const REGISTRY_ENTRY rgRegistryEntries[] = {
219  // RootKey KeyName ValueName ValueType Data
220  {HKEY_CURRENT_USER,
221  L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
222  NULL,
223  REG_SZ,
225  {HKEY_CURRENT_USER,
226  L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
227  NULL,
228  REG_SZ,
229  szModuleName},
230  {HKEY_CURRENT_USER,
231  L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
232  L"ThreadingModel",
233  REG_SZ,
234  L"Apartment"},
235  {HKEY_CURRENT_USER,
236  L"Software\\Classes\\.blend\\",
237  L"Treatment",
238  REG_DWORD,
239  0,
240  0}, // doesn't appear to do anything...
241  {HKEY_CURRENT_USER,
242  L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}",
243  NULL,
244  REG_SZ,
246  };
247 
248  hr = S_OK;
249  for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++) {
250  hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]);
251  }
252  }
253  if (SUCCEEDED(hr)) {
254  // This tells the shell to invalidate the thumbnail cache. This is important because any
255  // .blend files viewed before registering this handler would otherwise show cached blank
256  // thumbnails.
257  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
258  }
259  return hr;
260 }
261 
262 //
263 // Unregisters this COM server
264 //
266 {
267  HRESULT hr = S_OK;
268 
269  const PCWSTR rgpszKeys[] = {
270  L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
271  L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"};
272 
273  // Delete the registry entries
274  for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++) {
275  hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i]));
276  if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
277  // If the registry entry has already been deleted, say S_OK.
278  hr = S_OK;
279  }
280  }
281  return hr;
282 }
#define SZ_CLSID_BLENDTHUMBHANDLER
Definition: Dll.cpp:25
#define SZ_BLENDTHUMBHANDLER
Definition: Dll.cpp:26
long g_cRefModule
Definition: Dll.cpp:40
STDAPI DllRegisterServer()
Definition: Dll.cpp:208
STDAPI DllUnregisterServer()
Definition: Dll.cpp:265
void DllAddRef()
Definition: Dll.cpp:61
const CLASS_OBJECT_INIT c_rgClassObjectInit[]
Definition: Dll.cpp:37
DWORD dwReason
Definition: Dll.cpp:46
void DllRelease()
Definition: Dll.cpp:66
HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
Definition: Dll.cpp:168
STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
Definition: Dll.cpp:149
DWORD void *STDAPI DllCanUnloadNow()
Definition: Dll.cpp:55
const CLSID CLSID_BlendThumbHandler
Definition: Dll.cpp:27
STDAPI_(BOOL) DllMain(HINSTANCE hInstance
HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
HINSTANCE g_hInst
Definition: Dll.cpp:43
HRESULT(* PFNCREATEINSTANCE)(REFIID riid, void **ppvObject)
Definition: Dll.cpp:30
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
IFACEMETHODIMP LockServer(BOOL fLock)
Definition: Dll.cpp:128
IFACEMETHODIMP_(ULONG) AddRef()
Definition: Dll.cpp:108
IFACEMETHODIMP_(ULONG) Release()
Definition: Dll.cpp:113
IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
Definition: Dll.cpp:123
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
Definition: Dll.cpp:102
static HRESULT CreateInstance(REFCLSID clsid, const CLASS_OBJECT_INIT *pClassObjectInits, size_t cClassObjectInits, REFIID riid, void **ppv)
Definition: Dll.cpp:73
CClassFactory(PFNCREATEINSTANCE pfnCreate)
Definition: Dll.cpp:96
#define L
PFNCREATEINSTANCE pfnCreate
Definition: Dll.cpp:33
const CLSID * pClsid
Definition: Dll.cpp:32
Definition: Dll.cpp:157
PCWSTR pszKeyName
Definition: Dll.cpp:159
DWORD dwData
Definition: Dll.cpp:163
DWORD dwValueType
Definition: Dll.cpp:161
HKEY hkeyRoot
Definition: Dll.cpp:158
PCWSTR pszValueName
Definition: Dll.cpp:160
PCWSTR pszData
Definition: Dll.cpp:162