util.cpp

来自「很好用的ftp源码」· C++ 代码 · 共 1,997 行 · 第 1/5 页

CPP
1,997
字号
        hmenuRet = mii.hSubMenu;

    return hmenuRet;
}


/*****************************************************************************\
    MergeMenuHierarchy

    Swiped from defcm.c in the shell.            ;Internal
                                ;Internal
    Given an actual menu (hmenuDst), iterate over its submenus
    and merge corresponding submenus whose IDs match the IDs of
    actuals.

    hmenuDst - menu being adjusted
    hmenuSrc - template menu
    idcMin     - first available index
    idcMax     - first unavailable index
\*****************************************************************************/
UINT MergeMenuHierarchy(HMENU hmenuDst, HMENU hmenuSrc, UINT idcMin, UINT idcMax)
{
    int imi;
    UINT idcMaxUsed = idcMin;

    imi = GetMenuItemCount(hmenuSrc);
    while (--imi >= 0)
    {
        UINT idcT;
        MENUITEMINFO mii;

        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_ID|MIIM_SUBMENU;
        mii.cch = 0;     /* just in case */

        if (GetMenuItemInfo(hmenuSrc, imi, 1, &mii))
        {
            idcT = Shell_MergeMenus(GetMenuFromID(hmenuDst, mii.wID),
                mii.hSubMenu, (UINT)0, idcMin, idcMax,
                MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
            idcMaxUsed = max(idcMaxUsed, idcT);
        }
    }

    return idcMaxUsed;
}


HRESULT _SetStatusBarZone(CStatusBar * psb, CFtpSite * pfs)
{
    if (EVAL(psb && pfs))
    {
        LPITEMIDLIST pidl = pfs->GetPidl();

        if (pidl)
        {
            TCHAR szUrl[MAX_URL_STRING];

            UrlCreateFromPidl(pidl, SHGDN_FORPARSING, szUrl, ARRAYSIZE(szUrl), 0, TRUE);
            psb->UpdateZonesPane(szUrl);
            ILFree(pidl);
        }
    }

    return S_OK;
}


/*****************************************************************************\

    Misc_CopyPidl

    I wrote this on my own, and discovered months later    ;Internal
    that this is the same as SHILClone...            ;Internal
                                ;Internal
\*****************************************************************************/
HRESULT Misc_CopyPidl(LPCITEMIDLIST pidl, LPITEMIDLIST * ppidlOut)
{
    *ppidlOut = ILClone(pidl);
    return *ppidlOut ? S_OK : E_OUTOFMEMORY;
}


/*****************************************************************************\

    Misc_CloneHglobal

\*****************************************************************************/
HRESULT Misc_CloneHglobal(HGLOBAL hglob, HGLOBAL *phglob)
{
    LPVOID pv;
    HRESULT hres;

    ASSERT(hglob);
    *phglob = 0;            /* Rules are rules */
    pv = GlobalLock(hglob);
    if (EVAL(pv))
    {
        hres = Misc_CreateHglob(GlobalSize(hglob), pv, phglob);
        GlobalUnlock(hglob);
    }
    else
    {                /* Not a valid global handle */
        hres = E_INVALIDARG;
    }
    return hres;
}


#define FTP_PROPPAGES_FROM_INETCPL          (INET_PAGE_SECURITY | INET_PAGE_CONTENT | INET_PAGE_CONNECTION)

HRESULT AddFTPPropertyPages(LPFNADDPROPSHEETPAGE pfnAddPropSheetPage, LPARAM lParam, HINSTANCE * phinstInetCpl, IUnknown * punkSite)
{
    HRESULT hr = E_FAIL;

    if (NULL == *phinstInetCpl)
        *phinstInetCpl = LoadLibrary(TEXT("inetcpl.cpl"));

    // First add the pages from the Internet Control Panel.
    if (EVAL(*phinstInetCpl))
    {
        PFNADDINTERNETPROPERTYSHEETSEX pfnAddSheet = (PFNADDINTERNETPROPERTYSHEETSEX)GetProcAddress(*phinstInetCpl, STR_ADDINTERNETPROPSHEETSEX);
        if (EVAL(pfnAddSheet))
        {
            IEPROPPAGEINFO iepi = {0};

            iepi.cbSize = sizeof(iepi);
            iepi.dwFlags = (DWORD)-1;       // all pages

            hr = pfnAddSheet(pfnAddPropSheetPage, lParam, 0, 0, &iepi);
        }
        // Don't FreeLibrary here, otherwise PropertyPage will GP-fault!
    }

    ASSERT(SUCCEEDED(hr));

    if (((LPPROPSHEETHEADER)lParam)->nPages > 0)
        return hr;
    else
        return S_FALSE;

}


#if 0
/*****************************************************************************\

    Misc_SetDataDword

\*****************************************************************************/
HRESULT Misc_SetDataDword(IDataObject *pdto, FORMATETC *pfe, DWORD dw)
{
    HRESULT hres;
    HGLOBAL hglob;

    hres = Misc_CreateHglob(sizeof(dw), &dw, &hglob);
    if (SUCCEEDED(hres))
    {
        STGMEDIUM stg = { TYMED_HGLOBAL, hglob, 0 };
        hres = pdto->SetData(&fe, &stg, 1);

        if (!(EVAL(SUCCEEDED(hres))))
            GlobalFree(hglob);
    }
    else
        hres = E_OUTOFMEMORY;

    return hres;
}
#endif


CFtpPidlList * CreateRelativePidlList(CFtpFolder * pff, CFtpPidlList * pPidlListFull)
{
    int nSize = pPidlListFull->GetCount();
    CFtpPidlList * pPidlListNew = NULL;

    if (nSize > 0)
    {
        LPCITEMIDLIST pidlFirst = pff->GetPrivatePidlReference();
        int nCount = 0;

        while (!ILIsEmpty(pidlFirst))
        {
            pidlFirst = _ILNext(pidlFirst);
            nCount++;
        }

        if (nSize > 0)
        {
            for (int nIndex = 0; nIndex < nSize; nIndex++)
            {
                int nLeft = nCount;
                LPITEMIDLIST pidl = pPidlListFull->GetPidl(nIndex);

                while (nLeft--)
                    pidl = _ILNext(pidl);

                AssertMsg((pidl ? TRUE : FALSE), TEXT("CreateRelativePidlList() pPidlListFull->GetPidl() should never fail because we got the size and no mem allocation is needed."));
                if (0 == nIndex)
                {
                    CFtpPidlList_Create(1, (LPCITEMIDLIST *)&pidl, &pPidlListNew);
                    if (!pPidlListNew)
                        break;
                }
                else
                {
                    // We only want to add top level nodes.
                    // ftp://s/d1/d2/         <- Root of copy.
                    // ftp://s/d1/d2/d3a/     <- First Top Level Item
                    // ftp://s/d1/d2/d3a/f1   <- Skip non-top level items
                    // ftp://s/d1/d2/d3b/     <- Second Top Level Item
                    if (pidl && !ILIsEmpty(pidl) && ILIsEmpty(_ILNext(pidl)))
                        pPidlListNew->InsertSorted(pidl);
                }
            }
        }
    }

    return pPidlListNew;
}


#define SZ_VERB_DELETEA             "delete"
/*****************************************************************************\
    FUNCTION: Misc_DeleteHfpl

    DESCRIPTION:
        Delete the objects described by a pflHfpl.
\*****************************************************************************/
HRESULT Misc_DeleteHfpl(CFtpFolder * pff, HWND hwnd, CFtpPidlList * pflHfpl)
{
    IContextMenu * pcm;
    HRESULT hr = pff->GetUIObjectOfHfpl(hwnd, pflHfpl, IID_IContextMenu, (LPVOID *)&pcm, FALSE);

    if (EVAL(SUCCEEDED(hr)))
    {
        CMINVOKECOMMANDINFO ici = {
            sizeof(ici),            // cbSize
            CMIC_MASK_FLAG_NO_UI,    // fMask
            hwnd,                    // hwnd
            SZ_VERB_DELETEA,        // lpVerb
            0,                        // lpParameters
            0,                        // lpDirectory
            0,                        // nShow
            0,                        // dwHotKey
            0,                        // hIcon
        };
        hr = pcm->InvokeCommand(&ici);
        pcm->Release();
    }
    else
    {
        // Couldn't delete source; oh well.  Don't need UI.
        // BUGBUG -- Actually, maybe we ought to do UI after all.
    }

    return hr;
}

/*****************************************************************************\

    Misc_FindStatusBar

    Get the status bar from a browser window.

    _UNDOCUMENTED_: The following quirks are not documented.

    Note that we need to be very paranoid about the way GetControlWindow
    works.  Some people (Desktop) properly return error if the window
    does not exist.  Others (Explorer) return S_OK when the window
    does not exist, but they kindly set *lphwndOut = 0.  Still others
    (Find File) return S_OK but leave *lphwndOut unchanged!

    In order to work with all these bozos, we must manually set hwnd = 0
    before calling, and continue only if GetControlWindow returns success
    *and* the outgoing hwnd is nonzero.

    Furthermore, the documentation for GetControlWindow says that we
    have to check the window class before trusting the hwnd.

\*****************************************************************************/

#pragma BEGIN_CONST_DATA

TCHAR c_tszStatusBarClass[] = STATUSCLASSNAME;

#pragma END_CONST_DATA

HWND Misc_FindStatusBar(HWND hwndOwner)
{
    HWND hwnd = 0;    // Must preinit in case GetControlWindow fails

    if (EVAL(hwndOwner))
    {
        IShellBrowser * psb = FileCabinet_GetIShellBrowser(hwndOwner);

        if (EVAL(psb))
        {
            if (SUCCEEDED(psb->GetControlWindow(FCW_STATUS, &hwnd)) && hwnd) // This won't work when hosted in an IFRAME
            {
                //  Make sure it really is a status bar...
                TCHAR tszClass[ARRAYSIZE(c_tszStatusBarClass)+1];

                if (GetClassName(hwnd, tszClass, ARRAYSIZE(tszClass)) &&
                    !StrCmpI(tszClass, c_tszStatusBarClass))
                {
                    // We have a winner
                }
                else
                    hwnd = 0;        // False positive
            }
        }
    }

    return hwnd;
}

#ifdef DEBUG
void TraceMsgWithCurrentDir(DWORD dwTFOperation, LPCSTR pszMessage, HINTERNET hint)
{
    // For debugging...
    TCHAR szCurrentDir[MAX_PATH];
    DWORD cchDebugSize = ARRAYSIZE(szCurrentDir);

    DEBUG_CODE(DebugStartWatch());
    // PERF: Status FtpGetCurrentDirectory/FtpSetCurrentDirectory() takes
    //  180-280ms on ftp.microsoft.com on average.
    //  500-2000ms on ftp://ftp.tu-clausthal.de/ on average
    //  0-10ms on ftp://shapitst/ on average
    EVAL(FtpGetCurrentDirectory(hint, szCurrentDir, &cchDebugSize));
    DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "TraceMsgWithCurrentDir() FtpGetCurrentDirectory() returned %ls and took %lu milliseconds", szCurrentDir, DebugStopWatch()));
    TraceMsg(dwTFOperation, pszMessage, szCurrentDir);
}


void DebugStartWatch(void)
{
    LARGE_INTEGER liStopWatchStart;
    
    liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
    liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));

    ASSERT(!liStopWatchStart.QuadPart); // If you hit this, then the stopwatch is nested.
    QueryPerformanceFrequency(&g_liStopWatchFreq);
    QueryPerformanceCounter(&liStopWatchStart);

    TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) liStopWatchStart.HighPart);
    TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) liStopWatchStart.LowPart);
}

DWORD DebugStopWatch(void)
{
    LARGE_INTEGER liDiff;
    LARGE_INTEGER liStopWatchStart;
    
    QueryPerformanceCounter(&liDiff);
    liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
    liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
    liDiff.QuadPart -= liStopWatchStart.QuadPart;

    ASSERT(0 != g_liStopWatchFreq.QuadPart);    // I don't like to fault with div 0.
    DWORD dwTime = (DWORD)((liDiff.QuadPart * 1000) / g_liStopWatchFreq.QuadPart);
    
    TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) 0);
    TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) 0);

    return dwTime;
}
#endif // DEBUG


/*****************************************************************************\

    GetCfBuf

    Convert a clipboard format name to something stringable.

\*****************************************************************************/
void GetCfBufA(UINT cf, LPSTR pszOut, int cchOut)
{
    if (!GetClipboardFormatNameA(cf, pszOut, cchOut))
       wnsprintfA(pszOut, cchOut, "[%04x]", cf);
}

/*****************************************************************************\

    AllocHGlob

    Allocate a moveable HGLOBAL of the requested size, lock it, then call
    the callback.  On return, unlock it and get out.

    Returns the allocated HGLOBAL, or 0.

\*****************************************************************************/

HGLOBAL AllocHGlob(UINT cb, HGLOBWITHPROC pfn, LPVOID pvRef, LPCVOID pvPar

⌨️ 快捷键说明

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