⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dspsprt.cpp

📁 很好用的ftp源码
💻 CPP
字号:
#include "priv.h"
#include "dspsprt.h"
#include "msieftp.h"

#define TF_IDISPATCH 0


/*
 * CImpIDispatch::CImpIDispatch
 * CImpIDispatch::~CImpIDispatch
 *
 * Parameters (Constructor):
 *  piid    guid this IDispatch implementation is for
 *          we call QueryInterface to get the interface
 */

CImpIDispatch::CImpIDispatch(const IID * piid)
{
//    TraceMsg(TF_ALWAYS, "ctor CImpIDispatch %x", this);

    m_piid = piid;

    ASSERT(NULL==m_pITINeutral);
    ASSERT(NULL==m_pdisp);

    return;
}

CImpIDispatch::~CImpIDispatch(void)
{
//    TraceMsg(TF_ALWAYS, "dtor CImpIDispatch %x", this);

    if (m_pITINeutral)
    {
        m_pITINeutral->Release();
        m_pITINeutral = NULL;
    }
    return;
}





/*
 * CImpIDispatch::GetTypeInfoCount
 *
 * Purpose:
 *  Returns the number of type information (ITypeInfo) interfaces
 *  that the object provides (0 or 1).
 *
 * Parameters:
 *  pctInfo         UINT * to the location to receive
 *                  the count of interfaces.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error code.
 */

STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT *pctInfo)
{
    //We implement GetTypeInfo so return 1
    *pctInfo=1;
    return NOERROR;
}


//
// helper function for pulling ITypeInfo out of our typelib
//
HRESULT MSIEFTPGetTypeInfo(LCID lcid, UUID uuid, ITypeInfo **ppITypeInfo)
{
    HRESULT    hr;
    ITypeLib  *pITypeLib;

    // Just in case we can't find the type library anywhere
    *ppITypeInfo = NULL;

    /*
     * The type libraries are registered under 0 (neutral),
     * 7 (German), and 9 (English) with no specific sub-
     * language, which would make them 407 or 409 and such.
     * If you are sensitive to sub-languages, then use the
     * full LCID instead of just the LANGID as done here.
     */
    hr=LoadRegTypeLib(LIBID_MSIEFTPLib, 1, 0, PRIMARYLANGID(lcid), &pITypeLib);

    /*
     * If LoadRegTypeLib fails, try loading directly with
     * LoadTypeLib, which will register the library for us.
     * Note that there's no default case here because the
     * prior switch will have filtered lcid already.
     *
     * NOTE:  You should prepend your DIR registry key to the
     * .TLB name so you don't depend on it being it the PATH.
     * This sample will be updated later to reflect this.
     */
    if (FAILED(hr))
    {
        OLECHAR wszPath[MAX_PATH];
#ifdef UNICODE
        GetModuleFileName(HINST_THISDLL, wszPath, ARRAYSIZE(wszPath));
#else
        TCHAR szPath[MAX_PATH];
        GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
        MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, ARRAYSIZE(wszPath));
#endif

        switch (PRIMARYLANGID(lcid))
        {
        case LANG_NEUTRAL:
        case LANG_ENGLISH:
            hr=LoadTypeLib(wszPath, &pITypeLib);
            break;
        }
    }

    if (SUCCEEDED(hr))
    {
        //Got the type lib, get type info for the interface we want
        hr=pITypeLib->GetTypeInfoOfGuid(uuid, ppITypeInfo);
        pITypeLib->Release();
    }

    return(hr);
}


/*
 * CImpIDispatch::GetTypeInfo
 *
 * Purpose:
 *  Retrieves type information for the automation interface.  This
 *  is used anywhere that the right ITypeInfo interface is needed
 *  for whatever LCID is applicable.  Specifically, this is used
 *  from within GetIDsOfNames and Invoke.
 *
 * Parameters:
 *  itInfo          UINT reserved.  Must be zero.
 *  lcid            LCID providing the locale for the type
 *                  information.  If the object does not support
 *                  localization, this is ignored.
 *  ppITypeInfo     ITypeInfo ** in which to store the ITypeInfo
 *                  interface for the object.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error code.
 */

STDMETHODIMP CImpIDispatch::GetTypeInfo(UINT itInfo, LCID lcid
    , ITypeInfo **ppITypeInfo)
{
    ITypeInfo **ppITI;

    *ppITypeInfo=NULL;

    if (0!=itInfo)
        return(TYPE_E_ELEMENTNOTFOUND);

#if 1
    // docs say we can ignore lcid if we support only one LCID
    // we don't have to return DISP_E_UNKNOWNLCID if we're *ignoring* it
    ppITI = &m_pITINeutral;
#else
    /*
     * Since we returned one from GetTypeInfoCount, this function
     * can be called for a specific locale.  We support English
     * and neutral (defaults to English) locales.  Anything
     * else is an error.
     *
     * After this switch statement, ppITI will point to the proper
     * member pITypeInfo. If *ppITI is NULL, we know we need to
     * load type information, retrieve the ITypeInfo we want, and
     * then store it in *ppITI.
     */
    switch (PRIMARYLANGID(lcid))
    {
    case LANG_NEUTRAL:
    case LANG_ENGLISH:
        ppITI=&m_pITINeutral;
        break;

    default:
        return(DISP_E_UNKNOWNLCID);
    }
#endif

    //Load a type lib if we don't have the information already.
    if (NULL==*ppITI)
    {
        HRESULT    hr;
        ITypeInfo *pITIDisp;

        hr = MSIEFTPGetTypeInfo(lcid, *m_piid, &pITIDisp);

        if (SUCCEEDED(hr))
        {
            HRESULT hrT;
            HREFTYPE hrefType;

            // All our IDispatch implementations are DUAL. GetTypeInfoOfGuid
            // returns the ITypeInfo of the IDispatch-part only. We need to
            // find the ITypeInfo for the dual interface-part.
            //
            hrT = pITIDisp->GetRefTypeOfImplType(0xffffffff, &hrefType);
            if (SUCCEEDED(hrT))
            {
                hrT = pITIDisp->GetRefTypeInfo(hrefType, ppITI);
            }

            ASSERT(SUCCEEDED(hrT));
            if (FAILED(hrT))
            {
                // I suspect GetRefTypeOfImplType may fail if someone uses
                // CImpIDispatch on a non-dual interface. In this case the
                // ITypeInfo we got above is just fine to use.
                //
                *ppITI = pITIDisp;
            }
            else
            {
                pITIDisp->Release();
            }
        }

        if (FAILED(hr))
            return hr;
    }

    /*
     * Note:  the type library is still loaded since we have
     * an ITypeInfo from it.
     */

    (*ppITI)->AddRef();
    *ppITypeInfo=*ppITI;
    return NOERROR;
}


/*
 * CImpIDispatch::GetIDsOfNames
 *
 * Purpose:
 *  Converts text names into DISPIDs to pass to Invoke
 *
 * Parameters:
 *  riid            REFIID reserved.  Must be IID_NULL.
 *  rgszNames       OLECHAR ** pointing to the array of names to be
 *                  mapped.
 *  cNames          UINT number of names to be mapped.
 *  lcid            LCID of the locale.
 *  rgDispID        DISPID * caller allocated array containing IDs
 *                  corresponging to those names in rgszNames.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error code.
 */

STDMETHODIMP CImpIDispatch::GetIDsOfNames(REFIID riid
    , OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID)
{
    HRESULT     hr;
    ITypeInfo  *pTI;

    if (IID_NULL!=riid)
        return(DISP_E_UNKNOWNINTERFACE);

    //Get the right ITypeInfo for lcid.
    hr=GetTypeInfo(0, lcid, &pTI);

    if (SUCCEEDED(hr))
    {
        hr=pTI->GetIDsOfNames(rgszNames, cNames, rgDispID);

        pTI->Release();
    }

#ifdef DEBUG
    char szParam[MAX_PATH] = "";
    if (cNames >= 1)
    {
        WideCharToMultiByte(CP_ACP, 0,
            *rgszNames, -1,
            szParam, ARRAYSIZE(szParam), NULL, NULL);
    }

    TraceMsg(TF_IDISPATCH, "CImpIDispatch::GetIDsOfNames(%s = %x) called hres(%x)",
            szParam, *rgDispID, hr);
#endif

    return hr;
}



/*
 * CImpIDispatch::Invoke
 *
 * Purpose:
 *  Calls a method in the dispatch interface or manipulates a
 *  property.
 *
 * Parameters:
 *  dispID          DISPID of the method or property of interest.
 *  riid            REFIID reserved, must be IID_NULL.
 *  lcid            LCID of the locale.
 *  wFlags          USHORT describing the context of the invocation.
 *  pDispParams     DISPPARAMS * to the array of arguments.
 *  pVarResult      VARIANT * in which to store the result.  Is
 *                  NULL if the caller is not interested.
 *  pExcepInfo      EXCEPINFO * to exception information.
 *  puArgErr        UINT * in which to store the index of an
 *                  invalid parameter if DISP_E_TYPEMISMATCH
 *                  is returned.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error code.
 */

STDMETHODIMP CImpIDispatch::Invoke(DISPID dispID, REFIID riid
    , LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams
    , VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    ITypeInfo  *pTI;
    HRESULT hr;

    //riid is supposed to be IID_NULL always
    if (IID_NULL!=riid)
        return(DISP_E_UNKNOWNINTERFACE);

    // make sure we have an interface to hand off to Invoke
    if (NULL == m_pdisp)
    {
        hr=QueryInterface(*m_piid, (LPVOID*)&m_pdisp);
        
        if (!EVAL(SUCCEEDED(hr)))
            return hr;

        // don't hold a refcount on ourself
        m_pdisp->Release();
    }

    //Get the ITypeInfo for lcid
    hr=GetTypeInfo(0, lcid, &pTI);

    if (SUCCEEDED(hr))
    {
        //Clear exceptions
        SetErrorInfo(0L, NULL);

        //This is exactly what DispInvoke does--so skip the overhead.
        hr=pTI->Invoke(m_pdisp, dispID, wFlags
            , pDispParams, pVarResult, pExcepInfo, puArgErr);

        pTI->Release();
    }

    return hr;
}




/*
 * CImpIDispatch::Exception
 *
 * Purpose:
 *  Raises an exception for CImpIDispatch::Invoke from within
 *  ITypeInfo::Invoke using the CreateErrorInfo API and the
 *  ICreateErrorInfo interface.
 *
 *  Note that this method doesn't allow for deferred filling
 *  of an EXCEPINFO structure.
 *
 * Parameters:
 *  wException      WORD exception code.
 */

void CImpIDispatch::Exception(WORD wException)
{
#if 0 // nobody calls this
    ICreateErrorInfo   *pICreateErr;
    BOOL                fSuccess;
    LPTSTR              psz;
    LPOLESTR            pszHelp;
    UINT                idsSource;
    UINT                idsException;
    DWORD               dwHelpID;


    /*
     * Thread-safe exception handling means that we call
     * CreateErrorInfo which gives us an ICreateErrorInfo pointer
     * that we then use to set the error information (basically
     * to set the fields of an EXCEPINFO structure.  We then
     * call SetErrorInfo to attach this error to the current
     * thread.  ITypeInfo::Invoke will look for this when it
     * returns from whatever function was invokes by calling
     * GetErrorInfo.
     */

    //Not much we can do if this fails.
    if (FAILED(CreateErrorInfo(&pICreateErr)))
        return;

    psz=(LPTSTR)LocalAlloc(LPTR, 1024*sizeof(TCHAR));

    // psz is a buffer to do LoadString()s into -- if we didn't
    // get one then we won't get our error strings, so bail.
    if (NULL==psz)
    {
        pICreateErr->Release();
        return;
    }

    fSuccess=TRUE;

    // typically you'd do a switch here on all the exception ids wException
    // and fill in pszHelp, dwHelpID, idsSource, and idsException.
    // if you mapped the exception id to valid strings, the code
    // below will fill in the ICreateErr interface
    //
    switch (wException)
    {
    default:
        fSuccess = FALSE;
    }

    if (fSuccess)
    {
        HRESULT     hr;
        IErrorInfo *pIErr;

        /*
         * If you have a help file, call the functions
         * ICreateErrorInfo::SetHelpFile and
         * ICreateErrorInfo::SetHelpContext as well.  If you
         * set the help file to NULL the context is ignored.
         */
        pICreateErr->SetHelpFile(pszHelp);
        pICreateErr->SetHelpContext(dwHelpID);

#ifndef UNICODE
        OLECHAR     szTemp[256];

        LoadString(HINST_THISDLL, idsSource, psz, 256);
        MultiByteToWideChar(CP_ACP, 0, psz, -1, szTemp, 256);
        pICreateErr->SetSource(szTemp);

        LoadString(HINST_THISDLL, idsException, psz, 256);
        MultiByteToWideChar(CP_ACP, 0, psz, -1, szTemp, 256);
        pICreateErr->SetDescription(szTemp);
#else
        LoadString(HINST_THISDLL, idsSource, psz, 1024);
        pICreateErr->SetSource(psz);

        LoadString(HINST_THISDLL, idsException, psz, 1024);
        pICreateErr->SetDescription(psz);
#endif

        hr=pICreateErr->QueryInterface(IID_IErrorInfo
            , (LPVOID*)&pIErr);

        if (SUCCEEDED(hr))
        {
            SetErrorInfo(0L, pIErr);
            pIErr->Release();
        }
    }

    LocalFree(psz);

    //SetErrorInfo holds the object's IErrorInfo
    pICreateErr->Release();
#endif
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -