|
|
/* File: D:\wacker\ext\pageext.c (Created: 01-Mar-1994)
* * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 3 $ * $Date: 3/25/02 3:52p $ */
#define _INC_OLE // WIN32, get ole2 from windows.h
#define CONST_VTABLE
#define INITGUID
#include <windows.h>
#pragma hdrstop
//
// 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*);
//
// Global variables
//
UINT g_cRefThisDll = 0; // Reference count of this DLL.
//---------------------------------------------------------------------------
// 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_SamplePageExt). If a DLL supports
// multiple classes, it should have either multiple if-statements or
// efficient table lookup code.
//
// We need to put the icon handler in a separate DLL so when CAB32.EXE
// calls it we don't implicitly link to TAPI and other system DLL's.
// This is mostly for speed and to work around a bug in the Chicago
// beta 1. Of course, we want to keep one source. So the main DLL
// will link to the icon DLL to get icons, and the SHCreateDefClassObject(),
// etc. Sorry for the complexity but its in the interest of system
// performance. - mrw
if (IsEqualIID(rclsid, &CLSID_SamplePageExt)) { //
// 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 (PageExt_CreateInstance).
//
return SHCreateDefClassObject( riid, ppvOut, PageExt_CreateInstance, // callback function
&g_cRefThisDll, // reference count of this DLL
&IID_IShellExtInit // init interface
);
}
return ResultFromScode(CLASS_E_CLASSNOTAVAILABLE); }
//---------------------------------------------------------------------------
//
// CSamplePageExt class
//
// In C++:
// class CSamplePageExt : protected IShellPropSheetExt, protected IShellExtInit
// {
// protected:
// UINT _cRef;
// LPDATAOBJECT _pdtobj;
// HKEY _hkeyProgID;
// public:
// CSamplePageExt() _cRef(1), _pdtobj(NULL), _hkeyProgID(NULL) {};
// ...
// };
//
//---------------------------------------------------------------------------
typedef struct _CSamplePageExt // smx
{ IShellPropSheetExt _spx; // 1st base class
IShellExtInit _sxi; // 2nd base class
UINT _cRef; // reference count
LPDATAOBJECT _pdtobj; // data object
HKEY _hkeyProgID; // reg. database key to ProgID
} CSamplePageExt, * PSAMPLEPAGEEXT;
//
// Useful macros, which casts interface pointers to class pointers.
//
#define SMX_OFFSETOF(x) ((UINT_PTR)(&((PSAMPLEPAGEEXT)0)->x))
#define PVOID2PSMX(pv,offset) ((PSAMPLEPAGEEXT)(((LPBYTE)pv)-offset))
#define PSPX2PSMX(pspx) PVOID2PSMX(pspx, SMX_OFFSETOF(_spx))
#define PSXI2PSMX(psxi) PVOID2PSMX(psxi, SMX_OFFSETOF(_sxi))
//
// Vtable prototype
//
extern IShellPropSheetExtVtbl c_SamplePageExt_SPXVtbl; extern IShellExtInitVtbl c_SamplePageExt_SXIVtbl;
//---------------------------------------------------------------------------
//
// PageExt_CreateInstance
//
// This function is called back from within IClassFactory::CreateInstance()
// of the default class factory object, which is created by Shell_CreateClassObject.
//
//---------------------------------------------------------------------------
HRESULT CALLBACK PageExt_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, LPVOID FAR* ppvOut) { HRESULT hres; PSAMPLEPAGEEXT psmx;
//
// Shell extentions typically does not support aggregation.
//
if (punkOuter) return ResultFromScode(CLASS_E_NOAGGREGATION);
//
// in C++:
// psmx = new CSamplePageExt();
//
psmx = LocalAlloc(LPTR, sizeof(CSamplePageExt));
if (!psmx) return ResultFromScode(E_OUTOFMEMORY);
psmx->_spx.lpVtbl = &c_SamplePageExt_SPXVtbl; psmx->_sxi.lpVtbl = &c_SamplePageExt_SXIVtbl; psmx->_cRef = 1; psmx->_pdtobj = NULL; psmx->_hkeyProgID = NULL; 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_SamplePageExt_SPXVtbl.QueryInterface(&psmx->_spx, riid, ppvOut); c_SamplePageExt_SPXVtbl.Release(&psmx->_spx);
return hres; // S_OK or E_NOINTERFACE
}
//---------------------------------------------------------------------------
// CSamplePageExt::Initialize (IShellExtInit override)
//
// The shell always calls this member function to initialize this object
// immediately after creating it (by calling CoCreateInstance).
//
// Arguments:
// pdtobj -- Specifies one or more objects for which the shell is about to
// open the property sheet. Typically, they are selected objects
// in the explorer. If they are file system objects, it supports
// CF_FILELIST; if they are network resource objects, it supports
// "Net Resource" clipboard format.
// hkeyProgID -- Specifies the program ID of the primary object (typically
// the object which has the focus in the explorer's content pane).
//
// Comments:
// The extension should "duplicate" the parameters if it needs them later.
// Call AddRef() member function for the pdtobj and RegOpenKeyEx() API for the
// hkeyProgID.
//---------------------------------------------------------------------------
STDMETHODIMP PageExt_Initialize(LPSHELLEXTINIT psxi, LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj, HKEY hkeyProgID) { PSAMPLEPAGEEXT this = PSXI2PSMX(psxi);
//
// Initialize can be called more than once.
//
if (this->_pdtobj) { this->_pdtobj->lpVtbl->Release(this->_pdtobj); this->_pdtobj = NULL; }
if (this->_hkeyProgID) { RegCloseKey(this->_hkeyProgID); this->_hkeyProgID = NULL; }
//
// Duplicate the pdtobj pointer
//
if (pdtobj) { this->_pdtobj = pdtobj; pdtobj->lpVtbl->AddRef(pdtobj); }
//
// Duplicate the handle (althogh we don't use it in this sample)
//
if (hkeyProgID) RegOpenKeyEx(hkeyProgID, 0, 0, KEY_READ, &this->_hkeyProgID);
return NOERROR; }
//---------------------------------------------------------------------------
// CSamplePageExt::AddPages (IShellPropSheetExt override)
//---------------------------------------------------------------------------
STDMETHODIMP PageExt_AddPages(LPSHELLPROPSHEETEXT pspx, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) { PSAMPLEPAGEEXT this = PSPX2PSMX(pspx); //
// This is the place where this extension may add pages to the property
// sheet the shell is about to create. In this example, we add the
// "FSPage" if the selected objects are file system objects and add
// the "NETPage" if the selected objects are file system objects.
//
// Typically, a shell extension is registered either file system object
// class or network resource classe, and does not need to deal with two
// different kinds of objects.
//
FSPage_AddPages(this->_pdtobj, lpfnAddPage, lParam); //NETPage_AddPages(this->_pdtobj, lpfnAddPage, lParam);
return NOERROR; }
//---------------------------------------------------------------------------
// CSamplePageExt::AddRef (IShellPropSheetExt override)
//---------------------------------------------------------------------------
STDMETHODIMP_(UINT) PageExt_SPX_AddRef(LPSHELLPROPSHEETEXT pspx) { PSAMPLEPAGEEXT this = PSPX2PSMX(pspx); return ++this->_cRef; }
//---------------------------------------------------------------------------
// CSamplePageExt::AddRef (IShellExtInit override)
//---------------------------------------------------------------------------
STDMETHODIMP_(UINT) PageExt_SXI_AddRef(LPSHELLEXTINIT psxi) { PSAMPLEPAGEEXT this = PSXI2PSMX(psxi); return ++this->_cRef; }
//---------------------------------------------------------------------------
// CSamplePageExt::Release (IShellPropSheetExt override)
//---------------------------------------------------------------------------
STDMETHODIMP_(UINT) PageExt_SPX_Release(LPSHELLPROPSHEETEXT pspx) { PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
if (--this->_cRef) return this->_cRef;
if (this->_pdtobj) this->_pdtobj->lpVtbl->Release(this->_pdtobj);
if (this->_hkeyProgID) RegCloseKey(this->_hkeyProgID);
LocalFree((HLOCAL)this); g_cRefThisDll--;
return 0; }
//---------------------------------------------------------------------------
// CSamplePageExt::Release (IShellExtInit thunk)
//---------------------------------------------------------------------------
STDMETHODIMP_(UINT) PageExt_SXI_Release(LPSHELLEXTINIT psxi) { PSAMPLEPAGEEXT this = PSXI2PSMX(psxi); return PageExt_SPX_Release(&this->_spx); }
//---------------------------------------------------------------------------
// CSamplePageExt::QueryInterface (IShellPropSheetExt override)
//---------------------------------------------------------------------------
STDMETHODIMP PageExt_SPX_QueryInterface(LPSHELLPROPSHEETEXT pspx, REFIID riid, LPVOID FAR* ppvOut) { PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
if (IsEqualIID(riid, &IID_IShellPropSheetExt) || IsEqualIID(riid, &IID_IUnknown)) { (LPSHELLPROPSHEETEXT)*ppvOut=pspx; this->_cRef++; return NOERROR; }
if (IsEqualIID(riid, &IID_IShellExtInit)) { (LPSHELLEXTINIT)*ppvOut=&this->_sxi; this->_cRef++; return NOERROR; }
*ppvOut=NULL; return ResultFromScode(E_NOINTERFACE); }
//---------------------------------------------------------------------------
// CSamplePageExt::QueryInterface (IShellExtInit thunk)
//---------------------------------------------------------------------------
STDMETHODIMP PageExt_SXI_QueryInterface(LPSHELLEXTINIT psxi, REFIID riid, LPVOID FAR* ppv) { PSAMPLEPAGEEXT this = PSXI2PSMX(psxi); return PageExt_SPX_QueryInterface(&this->_spx, riid, ppv); }
//---------------------------------------------------------------------------
// CSamplePageExt class : Vtables
//
// VTables should be placed in the read only section unless we need to alter
// them at runtime.
//---------------------------------------------------------------------------
#pragma data_seg(".text")
IShellPropSheetExtVtbl c_SamplePageExt_SPXVtbl = { PageExt_SPX_QueryInterface, PageExt_SPX_AddRef, PageExt_SPX_Release, PageExt_AddPages };
IShellExtInitVtbl c_SamplePageExt_SXIVtbl = { PageExt_SXI_QueryInterface, PageExt_SXI_AddRef, PageExt_SXI_Release, PageExt_Initialize }; #pragma data_seg()
|