//-------------------------------------------------------------------------------- // // 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; }