You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
458 lines
12 KiB
458 lines
12 KiB
/* File: D:\WACKER\ext\iconext.c (Created: 11-Mar-1994)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 3 $
|
|
* $Date: 11/07/00 10:44a $
|
|
*/
|
|
|
|
|
|
#define _INC_OLE // WIN32, get ole2 from windows.h
|
|
#define CONST_VTABLE
|
|
#define INITGUID
|
|
|
|
#include <windows.h>
|
|
#pragma hdrstop
|
|
|
|
#include <term\res.h>
|
|
//
|
|
// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
|
|
//
|
|
#pragma data_seg(".text")
|
|
#include <objbase.h>
|
|
#include <initguid.h>
|
|
//#include <coguid.h>
|
|
//#include <oleguid.h>
|
|
#include <shlguid.h>
|
|
#include <shlobj.h>
|
|
#include "pageext.hh"
|
|
#pragma data_seg()
|
|
|
|
//
|
|
// Function prototypes
|
|
//
|
|
HRESULT CALLBACK PageExt_CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
|
|
BOOL WINAPI TDllEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved);
|
|
BOOL WINAPI _CRT_INIT(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved);
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
UINT g_cRefThisDll = 0; // Reference count of this DLL.
|
|
HINSTANCE hInstanceDll;
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* IconEntry
|
|
*
|
|
* DESCRIPTION:
|
|
* Currently, just initializes the C-Runtime library but may be used
|
|
* for other things later.
|
|
*
|
|
* ARGUMENTS:
|
|
* hInstDll - Instance of this DLL
|
|
* fdwReason - Why this entry point is called
|
|
* lpReserved - reserved
|
|
*
|
|
* RETURNS:
|
|
* BOOL
|
|
*
|
|
*/
|
|
BOOL WINAPI IconEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved)
|
|
{
|
|
hInstanceDll = hInstDll;
|
|
|
|
// You need to initialize the C runtime if you use any C-Runtime
|
|
// functions. Currently this is not the case execpt for memcmp
|
|
// used in IsEqualGUID(). However, if we're compiling for release
|
|
// we get the inline version of memcmp and so we don't need the
|
|
// C-Runtime.
|
|
|
|
#if defined(NDEBUG)
|
|
return TRUE;
|
|
#else
|
|
return _CRT_INIT(hInstDll, fdwReason, lpReserved);
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// DllCanUnloadNow
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDAPI DllCanUnloadNow(void)
|
|
{
|
|
return ResultFromScode((g_cRefThisDll==0) ? S_OK : S_FALSE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// DllGetClassObject
|
|
//
|
|
// This is the entry of this DLL, which all the In-Proc server DLLs should
|
|
// export. See the description of "DllGetClassObject" of OLE 2.0 reference
|
|
// manual for detail.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppvOut)
|
|
{
|
|
//
|
|
// This DLL has only one class (CLSID_SampleIconExt). If a DLL supports
|
|
// multiple classes, it should have either multiple if-statements or
|
|
// efficient table lookup code.
|
|
//
|
|
|
|
if (IsEqualIID(rclsid, &CLSID_SampleIconExt))
|
|
{
|
|
//
|
|
// We are supposed return the class object for this class. Instead
|
|
// of fully implementing it in this DLL, we just call a helper
|
|
// function in the shell DLL which creates a default class factory
|
|
// object for us. When its CreateInstance member is called, it
|
|
// will call back our create instance function (IconExt_CreateInstance).
|
|
//
|
|
return SHCreateDefClassObject(
|
|
riid,
|
|
ppvOut,
|
|
IconExt_CreateInstance, // callback function
|
|
&g_cRefThisDll, // reference count of this DLL
|
|
&IID_IPersistFile // init interface
|
|
);
|
|
}
|
|
|
|
return ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// CSampleIconExt class
|
|
//
|
|
// In C++:
|
|
// class CSampleIconExt : protected IExtractIcon, protected IPersistFile
|
|
// {
|
|
// protected:
|
|
// int _cRef;
|
|
// LPDATAOBJECT _pdtobj;
|
|
// HKEY _hkeyProgID;
|
|
// public:
|
|
// CSampleIconExt() _cRef(1), _pdtobj(NULL), _hkeyProgID(NULL) {};
|
|
// ...
|
|
// };
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
typedef struct _CSampleIconExt // smx
|
|
{
|
|
IExtractIcon _ctm; // 1st base class
|
|
IPersistFile _sxi; // 2nd base class
|
|
int _cRef; // reference count
|
|
char _szFile[MAX_PATH]; //
|
|
} CSampleIconExt, * PSAMPLEICONEXT;
|
|
|
|
#define SMX_OFFSETOF(x) ((UINT_PTR)(&((PSAMPLEICONEXT)0)->x))
|
|
#define PVOID2PSMX(pv,offset) ((PSAMPLEICONEXT)(((LPBYTE)pv)-offset))
|
|
#define PCTM2PSMX(pctm) PVOID2PSMX(pctm, SMX_OFFSETOF(_ctm))
|
|
#define PSXI2PSMX(psxi) PVOID2PSMX(psxi, SMX_OFFSETOF(_sxi))
|
|
|
|
//
|
|
// Vtable prototype
|
|
//
|
|
extern IExtractIconVtbl c_SampleIconExt_CTMVtbl;
|
|
extern IPersistFileVtbl c_SampleIconExt_SXIVtbl;
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// IconExt_CreateInstance
|
|
//
|
|
// This function is called back from within IClassFactory::CreateInstance()
|
|
// of the default class factory object, which is created by SHCreateClassObject.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT CALLBACK IconExt_CreateInstance(LPUNKNOWN punkOuter,
|
|
REFIID riid, LPVOID FAR* ppvOut)
|
|
{
|
|
HRESULT hres;
|
|
PSAMPLEICONEXT psmx;
|
|
|
|
//
|
|
// Shell extentions typically does not support aggregation.
|
|
//
|
|
if (punkOuter)
|
|
return ResultFromScode(CLASS_E_NOAGGREGATION);
|
|
|
|
//
|
|
// in C++:
|
|
// psmx = new CSampleIconExt();
|
|
//
|
|
psmx = LocalAlloc(LPTR, sizeof(CSampleIconExt));
|
|
|
|
if (!psmx)
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
|
|
psmx->_ctm.lpVtbl = &c_SampleIconExt_CTMVtbl;
|
|
psmx->_sxi.lpVtbl = &c_SampleIconExt_SXIVtbl;
|
|
psmx->_cRef = 1;
|
|
g_cRefThisDll++;
|
|
|
|
//
|
|
// in C++:
|
|
// hres = psmx->QueryInterface(riid, ppvOut);
|
|
// psmx->Release();
|
|
//
|
|
// Note that the Release member will free the object, if QueryInterface
|
|
// failed.
|
|
//
|
|
hres = c_SampleIconExt_CTMVtbl.QueryInterface(&psmx->_ctm, riid, ppvOut);
|
|
c_SampleIconExt_CTMVtbl.Release(&psmx->_ctm);
|
|
|
|
return hres; // S_OK or E_NOINTERFACE
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::Load (IPersistFile override)
|
|
//---------------------------------------------------------------------------
|
|
STDMETHODIMP IconExt_GetClassID(LPPERSISTFILE pPersistFile, LPCLSID lpClassID)
|
|
{
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP IconExt_IsDirty(LPPERSISTFILE pPersistFile)
|
|
{
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP IconExt_Load(LPPERSISTFILE pPersistFile, LPCOLESTR lpszFileName, DWORD grfMode)
|
|
{
|
|
PSAMPLEICONEXT this = PSXI2PSMX(pPersistFile);
|
|
int iRet = 0;
|
|
|
|
#if 1
|
|
iRet = WideCharToMultiByte(
|
|
CP_ACP, // CodePage
|
|
0, // dwFlags
|
|
lpszFileName, // lpWideCharStr
|
|
-1, // cchWideChar
|
|
this->_szFile, // lpMultiByteStr
|
|
sizeof(this->_szFile), // cchMultiByte,
|
|
NULL, // lpDefaultChar,
|
|
NULL // lpUsedDefaultChar
|
|
);
|
|
#endif
|
|
//
|
|
// WideCharToMultiByte does not work on build 84.
|
|
//
|
|
#if 1
|
|
if (iRet==0)
|
|
{
|
|
LPSTR psz=this->_szFile;
|
|
while(*psz++ = (char)*lpszFileName++);
|
|
}
|
|
#endif
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP IconExt_Save(LPPERSISTFILE pPersistFile, LPCOLESTR lpszFileName, BOOL fRemember)
|
|
{
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP IconExt_SaveCompleted(LPPERSISTFILE pPersistFile, LPCOLESTR lpszFileName)
|
|
{
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP IconExt_GetCurFile(LPPERSISTFILE pPersistFile, LPOLESTR FAR* lplpszFileName)
|
|
{
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
|
|
/*
|
|
* At the time I write this, the only known documentation for these next two
|
|
* functions is in SHLOBJ.H. Please take the time to read it.
|
|
*/
|
|
|
|
STDMETHODIMP IconExt_GetIconLocation(LPEXTRACTICON pexic,
|
|
UINT uFlags,
|
|
LPSTR szIconFile,
|
|
UINT cchMax,
|
|
int FAR * piIndex,
|
|
UINT FAR * pwFlags)
|
|
{
|
|
PSAMPLEICONEXT this = PCTM2PSMX(pexic);
|
|
|
|
if (this->_szFile[0])
|
|
{
|
|
HANDLE hFile;
|
|
DWORD dw;
|
|
DWORD dwSize;
|
|
DWORD dwIdx;
|
|
int nIndex = 0;
|
|
int nRet = 0;
|
|
|
|
GetModuleFileName(hInstanceDll, szIconFile, cchMax);
|
|
|
|
hFile = CreateFile(this->_szFile, GENERIC_READ, FILE_SHARE_READ,
|
|
0, OPEN_EXISTING, 0, 0);
|
|
|
|
if ( hFile != INVALID_HANDLE_VALUE ) //mpt:4-29-98 we weren't checking for failure here
|
|
{
|
|
// Skip past header. First ID will be the icon number.
|
|
// (IDs are shorts). Size field follows (DWORD)
|
|
|
|
if (SetFilePointer(hFile, 256+sizeof(SHORT), 0,
|
|
FILE_BEGIN) != (DWORD)-1)
|
|
{
|
|
if (ReadFile(hFile, &dwSize, sizeof(DWORD), &dw, 0))
|
|
{
|
|
dwIdx = 0;
|
|
|
|
if (ReadFile(hFile, &dwIdx, min(sizeof(DWORD), dwSize),
|
|
&dw, 0))
|
|
{
|
|
nIndex = (int)dwIdx;
|
|
nIndex -= IDI_PROG;
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
*piIndex = nIndex;
|
|
}
|
|
|
|
*pwFlags = 0;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP IconExt_Extract(LPEXTRACTICON pexic,
|
|
LPCSTR pszFile,
|
|
UINT nIconIndex,
|
|
HICON FAR *phiconLarge,
|
|
HICON FAR *phiconSmall,
|
|
UINT nIcons)
|
|
{
|
|
// Force default extraction.
|
|
return ResultFromScode(S_FALSE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::AddRef (IExtractIcon override)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(UINT) IconExt_CTM_AddRef(LPEXTRACTICON pctm)
|
|
{
|
|
PSAMPLEICONEXT this = PCTM2PSMX(pctm);
|
|
return ++this->_cRef;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::AddRef (IPersistFile override)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(UINT) IconExt_SXI_AddRef(LPPERSISTFILE psxi)
|
|
{
|
|
PSAMPLEICONEXT this = PSXI2PSMX(psxi);
|
|
return ++this->_cRef;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::Release (IExtractIcon override)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(UINT) IconExt_CTM_Release(LPEXTRACTICON pctm)
|
|
{
|
|
UINT cRef;
|
|
PSAMPLEICONEXT this = PCTM2PSMX(pctm);
|
|
|
|
#if DBG==1
|
|
if( 0 == this->_cRef )
|
|
{
|
|
DebugBreak(); // ref counting problem
|
|
}
|
|
#endif
|
|
cRef = InterlockedDecrement(&this->_cRef);
|
|
if ( 0 == cRef )
|
|
{
|
|
LocalFree((HLOCAL)this);
|
|
g_cRefThisDll--;
|
|
}
|
|
return cRef;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::Release (IPersistFile thunk)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(UINT) IconExt_SXI_Release(LPPERSISTFILE psxi)
|
|
{
|
|
PSAMPLEICONEXT this = PSXI2PSMX(psxi);
|
|
return IconExt_CTM_Release(&this->_ctm);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::QueryInterface (IExtractIcon override)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP IconExt_CTM_QueryInterface(LPEXTRACTICON pctm, REFIID riid, LPVOID FAR* ppvOut)
|
|
{
|
|
PSAMPLEICONEXT this = PCTM2PSMX(pctm);
|
|
|
|
if (IsEqualIID(riid, &IID_IExtractIcon) ||
|
|
IsEqualIID(riid, &IID_IUnknown))
|
|
{
|
|
(LPEXTRACTICON)*ppvOut=pctm;
|
|
this->_cRef++;
|
|
return NOERROR;
|
|
}
|
|
|
|
if (IsEqualIID(riid, &IID_IPersistFile))
|
|
{
|
|
(LPPERSISTFILE)*ppvOut=&this->_sxi;
|
|
this->_cRef++;
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt::QueryInterface (IPersistFile thunk)
|
|
//---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP IconExt_SXI_QueryInterface(LPPERSISTFILE psxi, REFIID riid, LPVOID FAR* ppv)
|
|
{
|
|
PSAMPLEICONEXT this = PSXI2PSMX(psxi);
|
|
return IconExt_CTM_QueryInterface(&this->_ctm, riid, ppv);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CSampleIconExt class : Vtables
|
|
//---------------------------------------------------------------------------
|
|
|
|
#pragma data_seg(".text")
|
|
IExtractIconVtbl c_SampleIconExt_CTMVtbl =
|
|
{
|
|
IconExt_CTM_QueryInterface,
|
|
IconExt_CTM_AddRef,
|
|
IconExt_CTM_Release,
|
|
IconExt_GetIconLocation,
|
|
IconExt_Extract,
|
|
};
|
|
|
|
IPersistFileVtbl c_SampleIconExt_SXIVtbl =
|
|
{
|
|
IconExt_SXI_QueryInterface,
|
|
IconExt_SXI_AddRef,
|
|
IconExt_SXI_Release,
|
|
IconExt_GetClassID,
|
|
IconExt_IsDirty,
|
|
IconExt_Load,
|
|
IconExt_Save,
|
|
IconExt_SaveCompleted,
|
|
IconExt_GetCurFile
|
|
};
|
|
#pragma data_seg()
|