204 lines
5.2 KiB
C++
204 lines
5.2 KiB
C++
/*****************************************************************************
|
|
*
|
|
* 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;
|
|
}
|