windows-nt/Source/XPSP1/NT/shell/ext/ftp/ftpcf.cpp

204 lines
5.2 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************
*
* ftpcf.cpp - IClassFactory interface
*
*****************************************************************************/
#include "priv.h"
#include "ftpwebvw.h"
#include "msieftp.h"
// msieftp.dll is unexpectedly getting unloaded and I believe the cause is defview not obaying threading rules.
// Therefore I hold an extra ref to keep our instance in process. This will not be an issue since the amount
// of global state msieftp uses in a process is very small. The problem comes from shell32!CCallBack::CallCB(),
// which is called by CDefView::OnDeactivate.
HINSTANCE g_hInstanceThisLeak = NULL;
/*****************************************************************************
*
* CFtpFactory
*
*
*****************************************************************************/
class CFtpFactory : public IClassFactory
{
public:
//////////////////////////////////////////////////////
// Public Interfaces
//////////////////////////////////////////////////////
// *** IUnknown ***
virtual STDMETHODIMP_(ULONG) AddRef(void);
virtual STDMETHODIMP_(ULONG) Release(void);
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
// *** IClassFactory ***
virtual STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
virtual STDMETHODIMP LockServer(BOOL fLock);
public:
CFtpFactory(REFCLSID rclsid);
~CFtpFactory(void);
// Friend Functions
friend HRESULT CFtpFactory_Create(REFCLSID rclsid, REFIID riid, LPVOID * ppvObj);
protected:
int m_cRef;
CLSID m_rclsid;
};
/*****************************************************************************
* IClassFactory::CreateInstance
*****************************************************************************/
HRESULT CFtpFactory::CreateInstance(IUnknown * punkOuter, REFIID riid, LPVOID * ppvObj)
{
HRESULT hres = ResultFromScode(REGDB_E_CLASSNOTREG);
if (!g_hInstanceThisLeak)
{
g_hInstanceThisLeak = LoadLibrary(TEXT("msieftp.dll"));
}
if (!punkOuter)
{
if (IsEqualIID(m_rclsid, CLSID_FtpFolder))
hres = CFtpFolder_Create(riid, ppvObj);
else if (IsEqualIID(m_rclsid, CLSID_FtpWebView))
hres = CFtpWebView_Create(riid, ppvObj);
else if (IsEqualIID(m_rclsid, CLSID_FtpInstaller))
hres = CFtpInstaller_Create(riid, ppvObj);
else if (IsEqualIID(m_rclsid, CLSID_FtpDataObject))
hres = CFtpObj_Create(riid, ppvObj);
else
ASSERT(0); // What are you looking for?
}
else
{ // Does anybody support aggregation any more?
hres = ResultFromScode(CLASS_E_NOAGGREGATION);
}
if (FAILED(hres) && ppvObj)
{
*ppvObj = NULL; // Be Robust. NT #355186
}
return hres;
}
/*****************************************************************************
*
* IClassFactory::LockServer
*
* Locking the server is identical to
* creating an object and not releasing it until you want to unlock
* the server.
*
*****************************************************************************/
HRESULT CFtpFactory::LockServer(BOOL fLock)
{
if (fLock)
DllAddRef();
else
DllRelease();
return S_OK;
}
/*****************************************************************************
*
* CFtpFactory_Create
*
*****************************************************************************/
HRESULT CFtpFactory_Create(REFCLSID rclsid, REFIID riid, LPVOID * ppvObj)
{
HRESULT hres;
if (GetShdocvwVersion() < 5)
{
// Check if we are running under older IE's and fail so that
// side by side IE4, IE5 can work
hres = ResultFromScode(E_NOINTERFACE);
}
else if (IsEqualIID(riid, IID_IClassFactory))
{
*ppvObj = (LPVOID) new CFtpFactory(rclsid);
hres = (*ppvObj) ? S_OK : E_OUTOFMEMORY;
}
else
hres = ResultFromScode(E_NOINTERFACE);
return hres;
}
/****************************************************\
Constructor
\****************************************************/
CFtpFactory::CFtpFactory(REFCLSID rclsid) : m_cRef(1)
{
m_rclsid = rclsid;
DllAddRef();
LEAK_ADDREF(LEAK_CFtpFactory);
}
/****************************************************\
Destructor
\****************************************************/
CFtpFactory::~CFtpFactory()
{
DllRelease();
LEAK_DELREF(LEAK_CFtpFactory);
}
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CFtpFactory::AddRef()
{
m_cRef++;
return m_cRef;
}
ULONG CFtpFactory::Release()
{
ASSERT(m_cRef > 0);
m_cRef--;
if (m_cRef > 0)
return m_cRef;
delete this;
return 0;
}
HRESULT CFtpFactory::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
{
*ppvObj = SAFECAST(this, IClassFactory *);
}
else
{
TraceMsg(TF_FTPQI, "CFtpFactory::QueryInterface() failed.");
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}