701 lines
14 KiB
C++
701 lines
14 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1995.
|
|
//
|
|
// File: ole.cxx
|
|
//
|
|
// Contents: IUnknown & IClassFactory for all OLE objects
|
|
//
|
|
// History: 13-Dec-95 BruceFo Created
|
|
//
|
|
// Note: There are three types of IUnknown implementations here. The first
|
|
// is for the "Shared Folders" COM objects. Each of these interfaces can be
|
|
// QueryInterface'd from the others, and all return the same IUnknown. There
|
|
// is a single shared object reference count (not interface reference count).
|
|
// These interfaces include: IShellFolder, IPersistFolder, IRemoteComputer.
|
|
//
|
|
// The second type is standard, separate interfaces that get interface-specific
|
|
// reference counts. This includes: IShellDetails, IEnumIDList,
|
|
// IExtractIcon, IExtractIconA.
|
|
//
|
|
// The third type is the IUnknown implementation for the "Shared Folders"
|
|
// COM object class factory. This object is a global static object, so it
|
|
// never gets destructed.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include <initguid.h>
|
|
#include "guids.h"
|
|
|
|
#include "ole.hxx"
|
|
#include "shares.h"
|
|
#include "shares.hxx"
|
|
#include "sdetails.hxx"
|
|
#include "sfolder.hxx"
|
|
#include "pfolder.hxx"
|
|
#include "rcomp.hxx"
|
|
#include "menu.hxx"
|
|
#include "menusp.hxx"
|
|
#include "menubg.hxx"
|
|
#include "enum.hxx"
|
|
#include "xicon.hxx"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG g_ulcInstances = 0;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CShares::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IUnknown*) this;
|
|
hr = S_OK;
|
|
}
|
|
else if (IsEqualIID(IID_IShellFolder, riid))
|
|
{
|
|
hr = m_ShellFolder.QueryInterface(riid, ppvObj);
|
|
}
|
|
else if (IsEqualIID(IID_IPersistFolder, riid))
|
|
{
|
|
hr = m_PersistFolder.QueryInterface(riid, ppvObj);
|
|
}
|
|
else if (IsEqualIID(IID_IRemoteComputer, riid))
|
|
{
|
|
hr = m_RemoteComputer.QueryInterface(riid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CShares::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CShares::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesSF::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (IsEqualIID(IID_IShellFolder, riid))
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IShellFolder*) this;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
CShares* This = IMPL(CShares,m_ShellFolder,this);
|
|
hr = This->QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesSF::AddRef()
|
|
{
|
|
CShares* This = IMPL(CShares,m_ShellFolder,this);
|
|
return This->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesSF::Release()
|
|
{
|
|
CShares* This = IMPL(CShares,m_ShellFolder,this);
|
|
return This->Release();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesPF::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (IsEqualIID(IID_IPersistFolder, riid))
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IPersistFolder*) this;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
CShares* This = IMPL(CShares,m_PersistFolder,this);
|
|
hr = This->QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesPF::AddRef()
|
|
{
|
|
CShares* This = IMPL(CShares,m_PersistFolder,this);
|
|
return This->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesPF::Release()
|
|
{
|
|
CShares* This = IMPL(CShares,m_PersistFolder,this);
|
|
return This->Release();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesRC::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (IsEqualIID(IID_IRemoteComputer, riid))
|
|
{
|
|
AddRef();
|
|
*ppvObj = (IRemoteComputer*) this;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
CShares* This = IMPL(CShares,m_RemoteComputer,this);
|
|
hr = This->QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesRC::AddRef()
|
|
{
|
|
CShares* This = IMPL(CShares,m_RemoteComputer,this);
|
|
return This->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesRC::Release()
|
|
{
|
|
CShares* This = IMPL(CShares,m_RemoteComputer,this);
|
|
return This->Release();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesSD::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IShellDetails*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IShellDetails, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IShellDetails*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesSD::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesSD::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesCM::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IContextMenu, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCM::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCM::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef WIZARDS
|
|
|
|
STDMETHODIMP
|
|
CSharesCMSpecial::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IContextMenu, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCMSpecial::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCMSpecial::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
#endif // WIZARDS
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesCMBG::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IContextMenu, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IContextMenu*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCMBG::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCMBG::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesEnum::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IEnumIDList*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IEnumIDList, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IEnumIDList*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEnum::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEnum::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesEI::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IExtractIcon*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IExtractIcon, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IExtractIcon*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEI::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEI::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef UNICODE
|
|
|
|
STDMETHODIMP
|
|
CSharesEIA::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IExtractIconA*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IExtractIcon, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IExtractIconA*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEIA::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
InterlockedIncrement((LONG*)&m_ulRefs);
|
|
return m_ulRefs;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesEIA::Release()
|
|
{
|
|
ULONG cRef = InterlockedDecrement((LONG*)&m_ulRefs);
|
|
if (0 == cRef)
|
|
{
|
|
delete this;
|
|
}
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return cRef;
|
|
}
|
|
|
|
#endif // UNICODE
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP
|
|
CSharesCF::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
IUnknown* pUnkTemp = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsEqualIID(IID_IUnknown, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IClassFactory*) this;
|
|
}
|
|
else if (IsEqualIID(IID_IClassFactory, riid))
|
|
{
|
|
pUnkTemp = (IUnknown*)(IClassFactory*) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (pUnkTemp != NULL)
|
|
{
|
|
pUnkTemp->AddRef();
|
|
}
|
|
|
|
*ppvObj = pUnkTemp;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCF::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances);
|
|
return g_ulcInstances;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CSharesCF::Release()
|
|
{
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return g_ulcInstances;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSharesCF::CreateInstance(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObj)
|
|
{
|
|
if (pUnkOuter != NULL)
|
|
{
|
|
// don't support aggregation
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
CShares* pShare = new CShares();
|
|
if (NULL == pShare)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT hr = pShare->QueryInterface(riid, ppvObj);
|
|
pShare->Release();
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSharesCF::LockServer(BOOL fLock)
|
|
{
|
|
return S_OK; // FEATURE: Whats supposed to happen here?
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI
|
|
DllCanUnloadNow(
|
|
VOID
|
|
)
|
|
{
|
|
if (0 == g_ulcInstances
|
|
&& 0 == g_NonOLEDLLRefs)
|
|
{
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
|
|
CSharesCF cfCShares;
|
|
|
|
STDAPI
|
|
DllGetClassObject(
|
|
REFCLSID cid,
|
|
REFIID iid,
|
|
LPVOID* ppvObj
|
|
)
|
|
{
|
|
InterlockedIncrement((LONG*)&g_ulcInstances); // don't nuke me now!
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if (IsEqualCLSID(cid, CLSID_CShares))
|
|
{
|
|
hr = cfCShares.QueryInterface(iid, ppvObj);
|
|
}
|
|
|
|
InterlockedDecrement((LONG*)&g_ulcInstances);
|
|
return hr;
|
|
}
|