231 lines
5.1 KiB
C++
231 lines
5.1 KiB
C++
//==============================================================;
|
|
//
|
|
// This source code is only intended as a supplement to existing Microsoft documentation.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//
|
|
//
|
|
//==============================================================;
|
|
|
|
#include <objbase.h>
|
|
#include <olectl.h>
|
|
#include <initguid.h>
|
|
#include "globals.h"
|
|
#include "resource.h"
|
|
#include "guids.h"
|
|
#include "basesnap.h"
|
|
#include "CMenuExt.h"
|
|
#include "About.h"
|
|
#include "Registry.h"
|
|
#include "Extend.h"
|
|
|
|
// our globals
|
|
HINSTANCE g_hinst;
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
|
DWORD fdwReason,
|
|
void* lpvReserved)
|
|
{
|
|
|
|
if (fdwReason == DLL_PROCESS_ATTACH) {
|
|
g_hinst = hinstDLL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvObj)
|
|
{
|
|
if ((rclsid != CLSID_CContextMenuExtension) && (rclsid != CLSID_CSnapinAbout))
|
|
return CLASS_E_CLASSNOTAVAILABLE;
|
|
|
|
|
|
if (!ppvObj)
|
|
return E_FAIL;
|
|
|
|
*ppvObj = NULL;
|
|
|
|
// We can only hand out IUnknown and IClassFactory pointers. Fail
|
|
// if they ask for anything else.
|
|
if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
|
|
return E_NOINTERFACE;
|
|
|
|
CClassFactory *pFactory = NULL;
|
|
|
|
// make the factory passing in the creation function for the type of object they want
|
|
if (rclsid == CLSID_CContextMenuExtension)
|
|
pFactory = new CClassFactory(CClassFactory::CONTEXTEXTENSION);
|
|
else if (rclsid == CLSID_CSnapinAbout)
|
|
pFactory = new CClassFactory(CClassFactory::ABOUT);
|
|
|
|
if (NULL == pFactory)
|
|
return E_OUTOFMEMORY;
|
|
|
|
HRESULT hr = pFactory->QueryInterface(riid, ppvObj);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDAPI DllCanUnloadNow(void)
|
|
{
|
|
if (g_uObjects == 0 && g_uSrvLock == 0)
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
CClassFactory::CClassFactory(FACTORY_TYPE factoryType)
|
|
: m_cref(0), m_factoryType(factoryType)
|
|
{
|
|
OBJECT_CREATED
|
|
}
|
|
|
|
CClassFactory::~CClassFactory()
|
|
{
|
|
OBJECT_DESTROYED
|
|
}
|
|
|
|
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
if (!ppv)
|
|
return E_FAIL;
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppv = static_cast<IClassFactory *>(this);
|
|
else
|
|
if (IsEqualIID(riid, IID_IClassFactory))
|
|
*ppv = static_cast<IClassFactory *>(this);
|
|
|
|
if (*ppv)
|
|
{
|
|
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
|
|
{
|
|
return InterlockedIncrement((LONG *)&m_cref);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CClassFactory::Release()
|
|
{
|
|
if (InterlockedDecrement((LONG *)&m_cref) == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cref;
|
|
}
|
|
|
|
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
void* pObj;
|
|
|
|
if (!ppvObj)
|
|
return E_FAIL;
|
|
|
|
*ppvObj = NULL;
|
|
|
|
// Our object does does not support aggregation, so we need to
|
|
// fail if they ask us to do aggregation.
|
|
if (pUnkOuter)
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
if (CONTEXTEXTENSION == m_factoryType) {
|
|
pObj = new CContextMenuExtension();
|
|
} else {
|
|
pObj = new CSnapinAbout();
|
|
}
|
|
|
|
if (!pObj)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// QueryInterface will do the AddRef() for us, so we do not
|
|
// do it in this function
|
|
hr = ((LPUNKNOWN)pObj)->QueryInterface(riid, ppvObj);
|
|
|
|
if (FAILED(hr))
|
|
delete pObj;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
|
|
{
|
|
if (fLock)
|
|
InterlockedIncrement((LONG *)&g_uSrvLock);
|
|
else
|
|
InterlockedDecrement((LONG *)&g_uSrvLock);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Exported functions
|
|
//
|
|
|
|
|
|
//
|
|
// Server registration
|
|
//
|
|
STDAPI DllRegisterServer()
|
|
{
|
|
HRESULT hr = SELFREG_E_CLASS;
|
|
|
|
_TCHAR szName[256];
|
|
_TCHAR szSnapInName[256];
|
|
|
|
LoadString(g_hinst, IDS_NAME, szName, sizeof(szName));
|
|
LoadString(g_hinst, IDS_SNAPINNAME, szSnapInName, sizeof(szSnapInName));
|
|
|
|
_TCHAR szAboutName[256];
|
|
|
|
LoadString(g_hinst, IDS_ABOUTNAME, szAboutName, sizeof(szAboutName));
|
|
|
|
|
|
// register our CoClasses
|
|
hr = RegisterServer(g_hinst,
|
|
CLSID_CContextMenuExtension,
|
|
szName);
|
|
|
|
if SUCCEEDED(hr)
|
|
hr = RegisterServer(g_hinst,
|
|
CLSID_CSnapinAbout,
|
|
szAboutName);
|
|
|
|
// place the registry information for SnapIns
|
|
if SUCCEEDED(hr)
|
|
hr = RegisterSnapin(CLSID_CContextMenuExtension, szSnapInName, CLSID_CSnapinAbout);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDAPI DllUnregisterServer()
|
|
{
|
|
if (UnregisterServer(CLSID_CContextMenuExtension) == S_OK)
|
|
return UnregisterSnapin(CLSID_CContextMenuExtension);
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|