Cleanup: clang-format

This commit is contained in:
Ray molenkamp 2019-08-30 13:33:49 -06:00
parent 6c16c2c233
commit 6726e98fe2
Notes: blender-bot 2023-02-14 07:25:46 +01:00
Referenced by issue #69372, blender 2.8 crashes when zooming out in "Animation -> Graph Editor" window.
Referenced by issue #69339, Surface Deform Modifier is Not Binding or Updating
Referenced by issue #69346, Undo doesn't work with paint mask selection (texture paint vs. vertex/weightpaint)
2 changed files with 422 additions and 422 deletions

View File

@ -15,7 +15,7 @@
*/
#include <shlwapi.h>
#include <thumbcache.h> // For IThumbnailProvider.
#include <thumbcache.h> // For IThumbnailProvider.
#include <new>
#pragma comment(lib, "shlwapi.lib")
@ -23,298 +23,291 @@
// this thumbnail provider implements IInitializeWithStream to enable being hosted
// in an isolated process for robustness
class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider
{
public:
CBlendThumb() : _cRef(1), _pStream(NULL) {}
class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider {
public:
CBlendThumb() : _cRef(1), _pStream(NULL)
{
}
virtual ~CBlendThumb()
{
if (_pStream)
{
_pStream->Release();
}
}
virtual ~CBlendThumb()
{
if (_pStream) {
_pStream->Release();
}
}
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CBlendThumb, IInitializeWithStream),
QITABENT(CBlendThumb, IThumbnailProvider),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = {
QITABENT(CBlendThumb, IInitializeWithStream),
QITABENT(CBlendThumb, IThumbnailProvider),
{0},
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) Release()
{
ULONG cRef = InterlockedDecrement(&_cRef);
if (!cRef)
{
delete this;
}
return cRef;
}
IFACEMETHODIMP_(ULONG) Release()
{
ULONG cRef = InterlockedDecrement(&_cRef);
if (!cRef) {
delete this;
}
return cRef;
}
// IInitializeWithStream
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
// IInitializeWithStream
IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
// IThumbnailProvider
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
// IThumbnailProvider
IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
private:
long _cRef;
IStream *_pStream; // provided during initialization.
private:
long _cRef;
IStream *_pStream; // provided during initialization.
};
HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
{
CBlendThumb *pNew = new (std::nothrow) CBlendThumb();
HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = pNew->QueryInterface(riid, ppv);
pNew->Release();
}
return hr;
CBlendThumb *pNew = new (std::nothrow) CBlendThumb();
HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) {
hr = pNew->QueryInterface(riid, ppv);
pNew->Release();
}
return hr;
}
// IInitializeWithStream
IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD)
{
HRESULT hr = E_UNEXPECTED; // can only be inited once
if (_pStream == NULL)
{
// take a reference to the stream if we have not been inited yet
hr = pStream->QueryInterface(&_pStream);
}
return hr;
HRESULT hr = E_UNEXPECTED; // can only be inited once
if (_pStream == NULL) {
// take a reference to the stream if we have not been inited yet
hr = pStream->QueryInterface(&_pStream);
}
return hr;
}
#include <math.h>
#include <zlib.h>
#include "Wincodec.h"
const unsigned char gzip_magic[3] = { 0x1f, 0x8b, 0x08 };
const unsigned char gzip_magic[3] = {0x1f, 0x8b, 0x08};
// IThumbnailProvider
IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
{
ULONG BytesRead;
HRESULT hr = S_FALSE;
LARGE_INTEGER SeekPos;
ULONG BytesRead;
HRESULT hr = S_FALSE;
LARGE_INTEGER SeekPos;
// Compressed?
unsigned char in_magic[3];
_pStream->Read(&in_magic,3,&BytesRead);
bool gzipped = true;
for ( int i=0; i < 3; i++ )
if ( in_magic[i] != gzip_magic[i] )
{
gzipped = false;
break;
}
// Compressed?
unsigned char in_magic[3];
_pStream->Read(&in_magic, 3, &BytesRead);
bool gzipped = true;
for (int i = 0; i < 3; i++)
if (in_magic[i] != gzip_magic[i]) {
gzipped = false;
break;
}
if (gzipped)
{
// Zlib inflate
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
if (gzipped) {
// Zlib inflate
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
// Get compressed file length
SeekPos.QuadPart = 0;
_pStream->Seek(SeekPos,STREAM_SEEK_END,NULL);
// Get compressed file length
SeekPos.QuadPart = 0;
_pStream->Seek(SeekPos, STREAM_SEEK_END, NULL);
// Get compressed and uncompressed size
uLong source_size;
uLongf dest_size;
//SeekPos.QuadPart = -4; // last 4 bytes define size of uncompressed file
//ULARGE_INTEGER Tell;
//_pStream->Seek(SeekPos,STREAM_SEEK_END,&Tell);
//source_size = (uLong)Tell.QuadPart + 4; // src
//_pStream->Read(&dest_size,4,&BytesRead); // dest
dest_size = 1024*70; // thumbnail is currently always inside the first 65KB...if it moves or enlargens this line will have to change or go!
source_size = (uLong)max(SeekPos.QuadPart,dest_size); // for safety, assume no compression
// Input
Bytef* src = new Bytef[source_size];
stream.next_in = (Bytef*)src;
stream.avail_in = (uInt)source_size;
// Output
Bytef* dest = new Bytef[dest_size];
stream.next_out = (Bytef*)dest;
stream.avail_out = dest_size;
// Get compressed and uncompressed size
uLong source_size;
uLongf dest_size;
// SeekPos.QuadPart = -4; // last 4 bytes define size of uncompressed file
// ULARGE_INTEGER Tell;
//_pStream->Seek(SeekPos,STREAM_SEEK_END,&Tell);
// source_size = (uLong)Tell.QuadPart + 4; // src
//_pStream->Read(&dest_size,4,&BytesRead); // dest
dest_size = 1024 * 70; // thumbnail is currently always inside the first 65KB...if it moves or
// enlargens this line will have to change or go!
source_size = (uLong)max(SeekPos.QuadPart, dest_size); // for safety, assume no compression
// IStream to src
SeekPos.QuadPart = 0;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
_pStream->Read(src,source_size,&BytesRead);
// Do the inflation
int err;
err = inflateInit2(&stream,16); // 16 means "gzip"...nice!
err = inflate(&stream, Z_FINISH);
err = inflateEnd(&stream);
// Replace the IStream, which is read-only
_pStream->Release();
_pStream = SHCreateMemStream(dest,dest_size);
delete[] src;
delete[] dest;
}
// Input
Bytef *src = new Bytef[source_size];
stream.next_in = (Bytef *)src;
stream.avail_in = (uInt)source_size;
// Blender version, early out if sub 2.5
SeekPos.QuadPart = 9;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
char version[4];
version[3] = '\0';
_pStream->Read(&version,3,&BytesRead);
if ( BytesRead != 3)
return E_UNEXPECTED;
int iVersion = atoi(version);
if ( iVersion < 250 )
return S_FALSE;
// 32 or 64 bit blend?
SeekPos.QuadPart = 7;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
// Output
Bytef *dest = new Bytef[dest_size];
stream.next_out = (Bytef *)dest;
stream.avail_out = dest_size;
char _PointerSize;
_pStream->Read(&_PointerSize,1,&BytesRead);
// IStream to src
SeekPos.QuadPart = 0;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
_pStream->Read(src, source_size, &BytesRead);
int PointerSize = _PointerSize == '_' ? 4 : 8;
int HeaderSize = 16 + PointerSize;
// Do the inflation
int err;
err = inflateInit2(&stream, 16); // 16 means "gzip"...nice!
err = inflate(&stream, Z_FINISH);
err = inflateEnd(&stream);
// Find and read thumbnail ("TEST") block
SeekPos.QuadPart = 12;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
int BlockOffset = 12;
while ( _pStream )
{
// Scan current block
char BlockName[5];
BlockName[4] = '\0';
int BlockSize = 0;
// Replace the IStream, which is read-only
_pStream->Release();
_pStream = SHCreateMemStream(dest, dest_size);
if (_pStream->Read(BlockName,4,&BytesRead) == S_OK && _pStream->Read((void*)&BlockSize,4,&BytesRead) == S_OK)
{
if ( strcmp (BlockName,"TEST") != 0 )
{
SeekPos.QuadPart = BlockOffset += HeaderSize + BlockSize;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
continue;
}
}
else break; // eof
delete[] src;
delete[] dest;
}
// Found the block
SeekPos.QuadPart = BlockOffset + HeaderSize;
_pStream->Seek(SeekPos,STREAM_SEEK_SET,NULL);
// Blender version, early out if sub 2.5
SeekPos.QuadPart = 9;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
char version[4];
version[3] = '\0';
_pStream->Read(&version, 3, &BytesRead);
if (BytesRead != 3)
return E_UNEXPECTED;
int iVersion = atoi(version);
if (iVersion < 250)
return S_FALSE;
int width, height;
_pStream->Read((char*)&width,4,&BytesRead);
_pStream->Read((char*)&height,4,&BytesRead);
BlockSize -= 8;
// 32 or 64 bit blend?
SeekPos.QuadPart = 7;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
// Isolate RGBA data
char* pRGBA = new char[BlockSize];
_pStream->Read(pRGBA,BlockSize,&BytesRead);
char _PointerSize;
_pStream->Read(&_PointerSize, 1, &BytesRead);
if (BytesRead != (ULONG)BlockSize)
return E_UNEXPECTED;
int PointerSize = _PointerSize == '_' ? 4 : 8;
int HeaderSize = 16 + PointerSize;
// Convert to BGRA for Windows
for (int i=0; i < BlockSize; i+=4 )
{
#define RED_BYTE pRGBA[i]
#define BLUE_BYTE pRGBA[i+2]
// Find and read thumbnail ("TEST") block
SeekPos.QuadPart = 12;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
int BlockOffset = 12;
while (_pStream) {
// Scan current block
char BlockName[5];
BlockName[4] = '\0';
int BlockSize = 0;
char red = RED_BYTE;
RED_BYTE = BLUE_BYTE;
BLUE_BYTE = red;
}
// Flip vertically (Blender stores it upside-down)
unsigned int LineSize = width*4;
char* FlippedImage = new char[BlockSize];
for (int i=0; i<height; i++)
{
if ( 0 != memcpy_s(&FlippedImage[ (height - i - 1)*LineSize ],LineSize,&pRGBA[ i*LineSize ],LineSize))
return E_UNEXPECTED;
}
delete[] pRGBA;
pRGBA = FlippedImage;
if (_pStream->Read(BlockName, 4, &BytesRead) == S_OK &&
_pStream->Read((void *)&BlockSize, 4, &BytesRead) == S_OK) {
if (strcmp(BlockName, "TEST") != 0) {
SeekPos.QuadPart = BlockOffset += HeaderSize + BlockSize;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
continue;
}
}
else
break; // eof
// Create image
*phbmp = CreateBitmap(width,height,1,32,pRGBA);
if (!*phbmp)
return E_FAIL;
*pdwAlpha = WTSAT_ARGB; // it's actually BGRA, not sure why this works
// Found the block
SeekPos.QuadPart = BlockOffset + HeaderSize;
_pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
// Scale down if required
if ( (unsigned)width > cx || (unsigned)height > cx )
{
float scale = 1.0f / (max(width,height) / (float)cx);
LONG NewWidth = (LONG)(width *scale);
LONG NewHeight = (LONG)(height *scale);
int width, height;
_pStream->Read((char *)&width, 4, &BytesRead);
_pStream->Read((char *)&height, 4, &BytesRead);
BlockSize -= 8;
// Isolate RGBA data
char *pRGBA = new char[BlockSize];
_pStream->Read(pRGBA, BlockSize, &BytesRead);
if (BytesRead != (ULONG)BlockSize)
return E_UNEXPECTED;
// Convert to BGRA for Windows
for (int i = 0; i < BlockSize; i += 4) {
#define RED_BYTE pRGBA[i]
#define BLUE_BYTE pRGBA[i + 2]
char red = RED_BYTE;
RED_BYTE = BLUE_BYTE;
BLUE_BYTE = red;
}
// Flip vertically (Blender stores it upside-down)
unsigned int LineSize = width * 4;
char *FlippedImage = new char[BlockSize];
for (int i = 0; i < height; i++) {
if (0 != memcpy_s(&FlippedImage[(height - i - 1) * LineSize],
LineSize,
&pRGBA[i * LineSize],
LineSize))
return E_UNEXPECTED;
}
delete[] pRGBA;
pRGBA = FlippedImage;
// Create image
*phbmp = CreateBitmap(width, height, 1, 32, pRGBA);
if (!*phbmp)
return E_FAIL;
*pdwAlpha = WTSAT_ARGB; // it's actually BGRA, not sure why this works
// Scale down if required
if ((unsigned)width > cx || (unsigned)height > cx) {
float scale = 1.0f / (max(width, height) / (float)cx);
LONG NewWidth = (LONG)(width * scale);
LONG NewHeight = (LONG)(height * scale);
#ifdef _DEBUG
#if 0
# if 0
MessageBox(0,"Attach now","Debugging",MB_OK);
# endif
#endif
#endif
IWICImagingFactory *pImgFac;
hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
IWICBitmap* WICBmp;
hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp,0,WICBitmapUseAlpha,&WICBmp);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = NewWidth;
bmi.bmiHeader.biHeight = -NewHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
IWICImagingFactory *pImgFac;
hr = CoCreateInstance(
CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
BYTE *pBits;
HBITMAP ResizedHBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
IWICBitmapScaler* pIScaler;
hr = pImgFac->CreateBitmapScaler(&pIScaler);
hr = pIScaler->Initialize(WICBmp,NewWidth,NewHeight,WICBitmapInterpolationModeFant);
WICRect rect = {0, 0, NewWidth, NewHeight};
hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
IWICBitmap *WICBmp;
hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp, 0, WICBitmapUseAlpha, &WICBmp);
if (SUCCEEDED(hr))
{
DeleteObject(*phbmp);
*phbmp = ResizedHBmp;
}
else
DeleteObject(ResizedHBmp);
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = NewWidth;
bmi.bmiHeader.biHeight = -NewHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
pIScaler->Release();
}
WICBmp->Release();
pImgFac->Release();
}
else
hr = S_OK;
break;
}
return hr;
BYTE *pBits;
HBITMAP ResizedHBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) {
IWICBitmapScaler *pIScaler;
hr = pImgFac->CreateBitmapScaler(&pIScaler);
hr = pIScaler->Initialize(WICBmp, NewWidth, NewHeight, WICBitmapInterpolationModeFant);
WICRect rect = {0, 0, NewWidth, NewHeight};
hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
if (SUCCEEDED(hr)) {
DeleteObject(*phbmp);
*phbmp = ResizedHBmp;
}
else
DeleteObject(ResizedHBmp);
pIScaler->Release();
}
WICBmp->Release();
pImgFac->Release();
}
else
hr = S_OK;
break;
}
return hr;
}

View File

@ -16,29 +16,26 @@
#include <objbase.h>
#include <shlwapi.h>
#include <thumbcache.h> // For IThumbnailProvider.
#include <shlobj.h> // For SHChangeNotify
#include <thumbcache.h> // For IThumbnailProvider.
#include <shlobj.h> // For SHChangeNotify
#include <new>
extern HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv);
#define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
#define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler"
const CLSID CLSID_BlendThumbHandler = { 0xd45f043d, 0xf17f, 0x4e8a, { 0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d } };
#define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
#define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler"
const CLSID CLSID_BlendThumbHandler = {
0xd45f043d, 0xf17f, 0x4e8a, {0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d}};
typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject);
struct CLASS_OBJECT_INIT
{
const CLSID *pClsid;
PFNCREATEINSTANCE pfnCreate;
struct CLASS_OBJECT_INIT {
const CLSID *pClsid;
PFNCREATEINSTANCE pfnCreate;
};
// add classes supported by this module here
const CLASS_OBJECT_INIT c_rgClassObjectInit[] =
{
{ &CLSID_BlendThumbHandler, CBlendThumb_CreateInstance }
};
const CLASS_OBJECT_INIT c_rgClassObjectInit[] = {
{&CLSID_BlendThumbHandler, CBlendThumb_CreateInstance}};
long g_cRefModule = 0;
@ -48,162 +45,160 @@ HINSTANCE g_hInst = NULL;
// Standard DLL functions
STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInst = hInstance;
DisableThreadLibraryCalls(hInstance);
}
return TRUE;
if (dwReason == DLL_PROCESS_ATTACH) {
g_hInst = hInstance;
DisableThreadLibraryCalls(hInstance);
}
return TRUE;
}
STDAPI DllCanUnloadNow()
{
// Only allow the DLL to be unloaded after all outstanding references have been released
return (g_cRefModule == 0) ? S_OK : S_FALSE;
// Only allow the DLL to be unloaded after all outstanding references have been released
return (g_cRefModule == 0) ? S_OK : S_FALSE;
}
void DllAddRef()
{
InterlockedIncrement(&g_cRefModule);
InterlockedIncrement(&g_cRefModule);
}
void DllRelease()
{
InterlockedDecrement(&g_cRefModule);
InterlockedDecrement(&g_cRefModule);
}
class CClassFactory : public IClassFactory
{
public:
static HRESULT CreateInstance(REFCLSID clsid, const CLASS_OBJECT_INIT *pClassObjectInits, size_t cClassObjectInits, REFIID riid, void **ppv)
{
*ppv = NULL;
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
for (size_t i = 0; i < cClassObjectInits; i++)
{
if (clsid == *pClassObjectInits[i].pClsid)
{
IClassFactory *pClassFactory = new (std::nothrow) CClassFactory(pClassObjectInits[i].pfnCreate);
hr = pClassFactory ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = pClassFactory->QueryInterface(riid, ppv);
pClassFactory->Release();
}
break; // match found
}
class CClassFactory : public IClassFactory {
public:
static HRESULT CreateInstance(REFCLSID clsid,
const CLASS_OBJECT_INIT *pClassObjectInits,
size_t cClassObjectInits,
REFIID riid,
void **ppv)
{
*ppv = NULL;
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
for (size_t i = 0; i < cClassObjectInits; i++) {
if (clsid == *pClassObjectInits[i].pClsid) {
IClassFactory *pClassFactory = new (std::nothrow)
CClassFactory(pClassObjectInits[i].pfnCreate);
hr = pClassFactory ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) {
hr = pClassFactory->QueryInterface(riid, ppv);
pClassFactory->Release();
}
return hr;
break; // match found
}
}
return hr;
}
CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate)
{
DllAddRef();
CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate)
{
DllAddRef();
}
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = {QITABENT(CClassFactory, IClassFactory), {0}};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) Release()
{
long cRef = InterlockedDecrement(&_cRef);
if (cRef == 0) {
delete this;
}
return cRef;
}
// IUnknown
IFACEMETHODIMP QueryInterface(REFIID riid, void ** ppv)
{
static const QITAB qit[] =
{
QITABENT(CClassFactory, IClassFactory),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
// IClassFactory
IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
{
return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv);
}
IFACEMETHODIMP LockServer(BOOL fLock)
{
if (fLock) {
DllAddRef();
}
IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
else {
DllRelease();
}
return S_OK;
}
IFACEMETHODIMP_(ULONG) Release()
{
long cRef = InterlockedDecrement(&_cRef);
if (cRef == 0)
{
delete this;
}
return cRef;
}
private:
~CClassFactory()
{
DllRelease();
}
// IClassFactory
IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
{
return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv);
}
IFACEMETHODIMP LockServer(BOOL fLock)
{
if (fLock)
{
DllAddRef();
}
else
{
DllRelease();
}
return S_OK;
}
private:
~CClassFactory()
{
DllRelease();
}
long _cRef;
PFNCREATEINSTANCE _pfnCreate;
long _cRef;
PFNCREATEINSTANCE _pfnCreate;
};
STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
{
return CClassFactory::CreateInstance(clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv);
return CClassFactory::CreateInstance(
clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv);
}
// A struct to hold the information required for a registry entry
struct REGISTRY_ENTRY
{
HKEY hkeyRoot;
PCWSTR pszKeyName;
PCWSTR pszValueName;
DWORD dwValueType;
PCWSTR pszData;
struct REGISTRY_ENTRY {
HKEY hkeyRoot;
PCWSTR pszKeyName;
PCWSTR pszValueName;
DWORD dwValueType;
PCWSTR pszData;
};
// Creates a registry key (if needed) and sets the default value of the key
HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
{
HKEY hKey;
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot, pRegistryEntry->pszKeyName,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL));
if (SUCCEEDED(hr))
{
// All this just to support REG_DWORD...
DWORD size;
DWORD data;
BYTE* lpData = (LPBYTE) pRegistryEntry->pszData;
switch (pRegistryEntry->dwValueType)
{
case REG_SZ:
size = ((DWORD) wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR);
break;
case REG_DWORD:
size = sizeof(DWORD);
data = (DWORD)pRegistryEntry->pszData;
lpData = (BYTE*)&data;
break;
default:
return E_INVALIDARG;
}
hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType,
lpData, size ));
RegCloseKey(hKey);
HKEY hKey;
HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot,
pRegistryEntry->pszKeyName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE,
NULL,
&hKey,
NULL));
if (SUCCEEDED(hr)) {
// All this just to support REG_DWORD...
DWORD size;
DWORD data;
BYTE *lpData = (LPBYTE)pRegistryEntry->pszData;
switch (pRegistryEntry->dwValueType) {
case REG_SZ:
size = ((DWORD)wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR);
break;
case REG_DWORD:
size = sizeof(DWORD);
data = (DWORD)pRegistryEntry->pszData;
lpData = (BYTE *)&data;
break;
default:
return E_INVALIDARG;
}
return hr;
hr = HRESULT_FROM_WIN32(RegSetValueExW(
hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType, lpData, size));
RegCloseKey(hKey);
}
return hr;
}
//
@ -211,39 +206,55 @@ HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
//
STDAPI DllRegisterServer()
{
HRESULT hr;
HRESULT hr;
WCHAR szModuleName[MAX_PATH];
WCHAR szModuleName[MAX_PATH];
if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName)))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
const REGISTRY_ENTRY rgRegistryEntries[] =
{
// RootKey KeyName ValueName ValueType Data
{HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER, NULL, REG_SZ, SZ_BLENDTHUMBHANDLER},
{HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", NULL, REG_SZ, szModuleName},
{HKEY_CURRENT_USER, L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32", L"ThreadingModel", REG_SZ, L"Apartment"},
{HKEY_CURRENT_USER, L"Software\\Classes\\.blend\\", L"Treatment", REG_DWORD, 0}, // doesn't appear to do anything...
{HKEY_CURRENT_USER, L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}", NULL, REG_SZ, SZ_CLSID_BLENDTHUMBHANDLER},
};
if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName))) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
else {
const REGISTRY_ENTRY rgRegistryEntries[] = {
// RootKey KeyName ValueName ValueType Data
{HKEY_CURRENT_USER,
L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
NULL,
REG_SZ,
SZ_BLENDTHUMBHANDLER},
{HKEY_CURRENT_USER,
L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
NULL,
REG_SZ,
szModuleName},
{HKEY_CURRENT_USER,
L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
L"ThreadingModel",
REG_SZ,
L"Apartment"},
{HKEY_CURRENT_USER,
L"Software\\Classes\\.blend\\",
L"Treatment",
REG_DWORD,
0}, // doesn't appear to do anything...
{HKEY_CURRENT_USER,
L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}",
NULL,
REG_SZ,
SZ_CLSID_BLENDTHUMBHANDLER},
};
hr = S_OK;
for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++)
{
hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]);
}
hr = S_OK;
for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++) {
hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]);
}
if (SUCCEEDED(hr))
{
// This tells the shell to invalidate the thumbnail cache. This is important because any .blend files
// viewed before registering this handler would otherwise show cached blank thumbnails.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
return hr;
}
if (SUCCEEDED(hr)) {
// This tells the shell to invalidate the thumbnail cache. This is important because any
// .blend files viewed before registering this handler would otherwise show cached blank
// thumbnails.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
return hr;
}
//
@ -251,23 +262,19 @@ STDAPI DllRegisterServer()
//
STDAPI DllUnregisterServer()
{
HRESULT hr = S_OK;
HRESULT hr = S_OK;
const PCWSTR rgpszKeys[] =
{
L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"
};
const PCWSTR rgpszKeys[] = {
L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"};
// Delete the registry entries
for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++)
{
hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i]));
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
// If the registry entry has already been deleted, say S_OK.
hr = S_OK;
}
// Delete the registry entries
for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++) {
hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i]));
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
// If the registry entry has already been deleted, say S_OK.
hr = S_OK;
}
return hr;
}
return hr;
}