windows-nt/Source/XPSP1/NT/shell/cpls/common/propsext.cpp
2020-09-26 16:20:57 +08:00

438 lines
12 KiB
C++

//--------------------------------------------------------------------------------
//
// File: propsext.cpp
//
// General handling of OLE Entry points, CClassFactory and CPropSheetExt
//
// Common Code for all display property sheet extension
//
// Copyright (c) Microsoft Corp. 1992-1998 All Rights Reserved
//
//--------------------------------------------------------------------------------
#include "shfusion.h"
//---------------------------------------------------------------------------
// Globals
//---------------------------------------------------------------------------
//
// Count number of objects and number of locks.
//
HINSTANCE g_hInst = NULL;
BOOL g_RunningOnNT = FALSE;
LPDATAOBJECT g_lpdoTarget = NULL;
ULONG g_cObj = 0;
ULONG g_cLock = 0;
//---------------------------------------------------------------------------
// DllMain()
//---------------------------------------------------------------------------
int APIENTRY DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
if (dwReason == DLL_PROCESS_ATTACH) // Initializing
{
if ((int)GetVersion() >= 0)
{
g_RunningOnNT = TRUE;
}
g_hInst = hInstance;
DisableThreadLibraryCalls(hInstance);
SHFusionInitializeFromModuleID(hInstance, 124);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
SHFusionUninitialize();
}
return 1;
}
//---------------------------------------------------------------------------
// DllGetClassObject()
//
// If someone calls with our CLSID, create an IClassFactory and pass it to
// them, so they can create and use one of our CPropSheetExt objects.
//
//---------------------------------------------------------------------------
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppvOut )
{
*ppvOut = NULL; // Assume Failure
if( IsEqualCLSID( rclsid, g_CLSID_CplExt ) )
{
//
//Check that we can provide the interface
//
if( IsEqualIID( riid, IID_IUnknown) ||
IsEqualIID( riid, IID_IClassFactory )
)
{
//Return our IClassFactory for CPropSheetExt objects
*ppvOut = (LPVOID* )new CClassFactory();
if( NULL != *ppvOut )
{
//AddRef the object through any interface we return
((CClassFactory*)*ppvOut)->AddRef();
return NOERROR;
}
return E_OUTOFMEMORY;
}
return E_NOINTERFACE;
}
else
{
return CLASS_E_CLASSNOTAVAILABLE;
}
}
//---------------------------------------------------------------------------
// DllCanUnloadNow()
//
// If we are not locked, and no objects are active, then we can exit.
//
//---------------------------------------------------------------------------
STDAPI DllCanUnloadNow()
{
SCODE sc;
//
//Our answer is whether there are any object or locks
//
sc = (0L == g_cObj && 0 == g_cLock) ? S_OK : S_FALSE;
return ResultFromScode(sc);
}
//---------------------------------------------------------------------------
// ObjectDestroyed()
//
// Function for the CPropSheetExt object to call when it is destroyed.
// Because we're in a DLL, we only track the number of objects here,
// letting DllCanUnloadNow take care of the rest.
//---------------------------------------------------------------------------
void FAR PASCAL ObjectDestroyed( void )
{
g_cObj--;
return;
}
UINT CALLBACK PropertySheetCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
switch (uMsg) {
case PSPCB_CREATE:
return TRUE; // return TRUE to continue with creation of page
case PSPCB_RELEASE:
if (g_lpdoTarget) {
g_lpdoTarget->Release();
g_lpdoTarget = NULL;
}
return 0; // return value ignored
default:
break;
}
return TRUE;
}
//***************************************************************************
//
// CClassFactory Class
//
//***************************************************************************
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
CClassFactory::CClassFactory()
{
m_cRef = 0L;
return;
}
//---------------------------------------------------------------------------
// Destructor
//---------------------------------------------------------------------------
CClassFactory::~CClassFactory( void )
{
return;
}
//---------------------------------------------------------------------------
// QueryInterface()
//---------------------------------------------------------------------------
STDMETHODIMP CClassFactory::QueryInterface( REFIID riid, LPVOID* ppv )
{
*ppv = NULL;
//Any interface on this object is the object pointer.
if( IsEqualIID( riid, IID_IUnknown ) ||
IsEqualIID( riid, IID_IClassFactory )
)
{
*ppv = (LPVOID)this;
++m_cRef;
return NOERROR;
}
return E_NOINTERFACE;
}
//---------------------------------------------------------------------------
// AddRef()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
return ++m_cRef;
}
//---------------------------------------------------------------------------
// Release()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClassFactory::Release()
{
ULONG cRefT;
cRefT = --m_cRef;
if( 0L == m_cRef )
delete this;
return cRefT;
}
// Allow the caller to specify another class to use. The only requirement
// is that there be a contructore with (punk, void FAR PASCAL pfnObjDes(void) )
#ifndef PROPSHEET_CLASS
#define PROPSHEET_CLASS CPropSheetExt
#endif // PROPSHEET_CLASS
//---------------------------------------------------------------------------
// CreateInstance()
//---------------------------------------------------------------------------
STDMETHODIMP
CClassFactory::CreateInstance( LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID FAR *ppvObj
)
{
CPropSheetExt* pObj;
HRESULT hr = E_OUTOFMEMORY;
*ppvObj = NULL;
// We don't support aggregation at all.
if( pUnkOuter )
{
return CLASS_E_NOAGGREGATION;
}
//Verify that a controlling unknown asks for IShellPropSheetExt
if( IsEqualIID( riid, IID_IShellPropSheetExt ) )
{
//Create the object, passing function to notify on destruction
pObj = new PROPSHEET_CLASS(pUnkOuter, ObjectDestroyed);
if( NULL == pObj )
{
return hr;
}
hr = pObj->QueryInterface( riid, ppvObj );
//Kill the object if initial creation or FInit failed.
if( FAILED(hr) )
{
delete pObj;
}
else
{
g_cObj++;
}
return hr;
}
return E_NOINTERFACE;
}
//---------------------------------------------------------------------------
// LockServer()
//---------------------------------------------------------------------------
STDMETHODIMP CClassFactory::LockServer( BOOL fLock )
{
if( fLock )
{
g_cLock++;
}
else
{
g_cLock--;
}
return NOERROR;
}
//***************************************************************************
//
// CPropSheetExt Class
//
//***************************************************************************
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
CPropSheetExt::CPropSheetExt( LPUNKNOWN pUnkOuter, LPFNDESTROYED pfnDestroy )
{
m_cRef = 0;
m_pUnkOuter = pUnkOuter;
m_pfnDestroy = pfnDestroy;
return;
}
//---------------------------------------------------------------------------
// Destructor
//---------------------------------------------------------------------------
CPropSheetExt::~CPropSheetExt( void )
{
return;
}
//---------------------------------------------------------------------------
// QueryInterface()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::QueryInterface( REFIID riid, LPVOID* ppv )
{
*ppv = NULL;
if (IsEqualIID(riid, IID_IShellExtInit))
{
*ppv = (IShellExtInit *) this;
}
if (IsEqualIID(riid, IID_IShellPropSheetExt))
{
*ppv = (LPVOID)this;
}
if (*ppv)
{
++m_cRef;
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
//---------------------------------------------------------------------------
// AddRef()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CPropSheetExt::AddRef( void )
{
return ++m_cRef;
}
//---------------------------------------------------------------------------
// Release()
//---------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CPropSheetExt::Release( void )
{
ULONG cRefT;
cRefT = --m_cRef;
if( m_cRef == 0 )
{
// Tell the housing that an object is going away so that it
// can shut down if appropriate.
if( NULL != m_pfnDestroy )
{
(*m_pfnDestroy)();
}
delete this;
}
return cRefT;
}
//---------------------------------------------------------------------------
// AddPages()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam )
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpage;
TCHAR szTitle[ 30 ];
LoadString( g_hInst, IDS_PAGE_TITLE, szTitle, ARRAYSIZE(szTitle) );
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hIcon = NULL;
psp.hInstance = g_hInst;
psp.pszTemplate =MAKEINTRESOURCE( PROP_SHEET_DLG );
psp.pfnDlgProc = PropertySheetDlgProc;
psp.pfnCallback = PropertySheetCallback;
psp.pszTitle = szTitle;
psp.lParam = 0;
#ifdef USESLINKCONTROL
LinkWindow_RegisterClass();
#endif
if( ( hpage = CreatePropertySheetPage( &psp ) ) == NULL )
{
return ( E_OUTOFMEMORY );
}
if( !lpfnAddPage(hpage, lParam ) )
{
DestroyPropertySheetPage(hpage );
return ( E_FAIL );
}
return NOERROR;
}
//---------------------------------------------------------------------------
// ReplacePage()
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam )
{
return NOERROR;
}
//---------------------------------------------------------------------------
// IShellExtInit member function- this interface needs only one
//---------------------------------------------------------------------------
STDMETHODIMP CPropSheetExt::Initialize(LPCITEMIDLIST pcidlFolder,
LPDATAOBJECT pdoTarget,
HKEY hKeyID)
{
// The target data object is an HDROP, or list of files from the shell.
if (g_lpdoTarget)
{
g_lpdoTarget->Release();
g_lpdoTarget = NULL;
}
if (pdoTarget)
{
g_lpdoTarget = pdoTarget;
g_lpdoTarget->AddRef();
}
return NOERROR;
}