util.cpp

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

CPP
1,997
字号
        This function is exists to be called back during
    long FTP operations so we can update the progress
    dialog during FtpPutFile or FtpGetFile.

    A pointer to our PROGRESSINFO struct is passed in
    dwContext.
\****************************************************/
void FtpProgressInternetStatusCB(IN HINTERNET hInternet, IN DWORD_PTR pdwContext, IN DWORD dwInternetStatus, IN LPVOID lpwStatusInfo, IN DWORD dwStatusInfoLen)
{
    LPPROGRESSINFO pProgInfo = (LPPROGRESSINFO) pdwContext;
    if (EVAL(pProgInfo))
    {
        switch (dwInternetStatus)
        {
        case INTERNET_STATUS_RESPONSE_RECEIVED:
        case INTERNET_STATUS_REQUEST_SENT:
            if (EVAL(lpwStatusInfo && (sizeof(DWORD) == dwStatusInfoLen)
                && pProgInfo))
            {
                if (pProgInfo->hint && pProgInfo->ppd->HasUserCancelled())
                {
                    EVAL(InternetCloseHandle(pProgInfo->hint));
                    pProgInfo->hint = NULL;
                }

                pProgInfo->dwCompletedInCurFile += *(LPDWORD)lpwStatusInfo;

                // Has a big enough chunck of the file completed that we need
                // to update the progress?  We only want to update the progress
                // every SIZE_PROGRESS_AFTERBYTES (50k) chunck.
                if (pProgInfo->dwLastDisplayed < (pProgInfo->dwCompletedInCurFile / SIZE_PROGRESS_AFTERBYTES))
                {
                    ULARGE_INTEGER uliBytesCompleted;

                    pProgInfo->dwLastDisplayed = (pProgInfo->dwCompletedInCurFile / SIZE_PROGRESS_AFTERBYTES);

                    uliBytesCompleted.HighPart = 0;
                    uliBytesCompleted.LowPart = pProgInfo->dwCompletedInCurFile;
                    uliBytesCompleted.QuadPart += pProgInfo->uliBytesCompleted.QuadPart;

                    if (pProgInfo->ppd)
                        EVAL(SUCCEEDED(pProgInfo->ppd->SetProgress64(uliBytesCompleted.QuadPart, pProgInfo->uliBytesTotal.QuadPart)));
                }
            }
            break;
        }
    }
}


/*****************************************************************************\
    Misc_CreateHglob

    Allocate an hglobal of the indicated size, initialized from the
    specified buffer.
\*****************************************************************************/
HRESULT Misc_CreateHglob(SIZE_T cb, LPVOID pv, HGLOBAL *phglob)
{
    HRESULT hres = E_OUTOFMEMORY;

    *phglob = 0;            // Rules are rules
    if (cb)
    {
        *phglob = (HGLOBAL) LocalAlloc(LPTR, cb);
        if (phglob)
        {
            hres = S_OK;
            CopyMemory(*phglob, pv, cb);
        }
    }
    else
        hres = E_INVALIDARG;    // Can't clone a discardable block

    return hres;
}


/*****************************************************************************\
    _HIDA_Create_Tally

    Worker function for HIDA_Create which tallies up the total size.
\*****************************************************************************/
int _HIDA_Create_Tally(LPVOID pvPidl, LPVOID pv)
{
    LPCITEMIDLIST pidl = (LPCITEMIDLIST) pvPidl;
    UINT *pcb = (UINT *) pv;
    int nContinue = (pv ? TRUE : FALSE);

    *pcb += ILGetSize(pidl);
    return nContinue;
}


/*****************************************************************************\
    _HIDA_Create_AddIdl

    Worker function for HIDA_Create which appends another ID List
    to the growing HIDA.
\*****************************************************************************/
int _HIDA_Create_AddIdl(LPVOID pvPidl, LPVOID pv)
{
    LPCITEMIDLIST pidl = (LPCITEMIDLIST) pvPidl;
    LPHIDACREATEINFO phci = (LPHIDACREATEINFO) pv;
    UINT cb = ILGetSize(pidl);

    pidaPhci(phci)->aoffset[phci->ipidl++] = phci->ib;
    CopyMemory(pvByteIndexCb(pidaPhci(phci), phci->ib), pidl, cb);
    phci->ib += cb;

    return phci ? TRUE : FALSE;
}


/*****************************************************************************\
    _Misc_HIDA_Init

    Once we've allocated the memory for a HIDA, fill it with stuff.
\*****************************************************************************/
BOOL _Misc_HIDA_Init(LPVOID hida, LPVOID pv, LPCVOID pvParam2, BOOL fUnicode)
{
    LPHIDACREATEINFO phci = (LPHIDACREATEINFO) pv;

    phci->hida = hida;
    pidaPhci(phci)->cidl = phci->cpidl;
    phci->ipidl = 0;

    phci->pflHfpl->TraceDump(_ILNext(phci->pidlFolder), TEXT("_Misc_HIDA_Init() TraceDump Before"));

    _HIDA_Create_AddIdl((LPVOID) phci->pidlFolder, (LPVOID) phci);
    phci->pflHfpl->Enum(_HIDA_Create_AddIdl, (LPVOID) phci);

    phci->pflHfpl->TraceDump(_ILNext(phci->pidlFolder), TEXT("_Misc_HIDA_Init() TraceDump After"));

    return 1;
}


/*****************************************************************************\
    HIDA_Create

    Swiped from idlist.c in the shell because they didn't    ;Internal
    export it.                        ;Internal
\*****************************************************************************/
HIDA Misc_HIDA_Create(LPCITEMIDLIST pidlFolder, CFtpPidlList * pflHfpl)
{
    HIDACREATEINFO hci;
    LPHIDACREATEINFO phci = &hci;
    HIDA hida;

    pflHfpl->TraceDump(_ILNext(pidlFolder), TEXT("Misc_HIDA_Create() TraceDump Before"));
    phci->pidlFolder = pidlFolder;
    phci->pflHfpl = pflHfpl;
    phci->cpidl = pflHfpl->GetCount();
    phci->ib = sizeof(CIDA) + sizeof(UINT) * phci->cpidl;
    phci->cb = phci->ib + ILGetSize(pidlFolder);

    pflHfpl->Enum(_HIDA_Create_Tally, (LPVOID) &phci->cb);

    hida = AllocHGlob(phci->cb, _Misc_HIDA_Init, phci, NULL, FALSE);
    pflHfpl->TraceDump(_ILNext(pidlFolder), TEXT("Misc_HIDA_Create() TraceDump Before"));

    return hida;
}


typedef struct tagURL_FILEGROUP
{
    LPFILEGROUPDESCRIPTORA   pfgdA;
    LPFILEGROUPDESCRIPTORW   pfgdW;
    LPCITEMIDLIST            pidlParent;
} URL_FILEGROUP;

/*****************************************************************************\
    Misc_HFGD_Create

    Build a file group descriptor based on an pflHfpl.

    CFtpObj::_DelayRender_FGD() did the recursive walk to expand the list 
    of pidls, so we don't have to.
\*****************************************************************************/
#define cbFgdCfdW(cfd) FIELD_OFFSET(FILEGROUPDESCRIPTORW, fgd[cfd])
#define cbFgdCfdA(cfd) FIELD_OFFSET(FILEGROUPDESCRIPTORA, fgd[cfd])

int _Misc_HFGD_Create(LPVOID pvPidl, LPVOID pv)
{
    BOOL fSucceeded = TRUE;
    URL_FILEGROUP * pUrlFileGroup = (URL_FILEGROUP *) pv;
    LPCITEMIDLIST pidlFull = (LPCITEMIDLIST) pvPidl;
    LPCITEMIDLIST pidl;

    LPFILEGROUPDESCRIPTORA pfgdA = pUrlFileGroup->pfgdA;
    LPFILEGROUPDESCRIPTORW pfgdW = pUrlFileGroup->pfgdW;
    LPFILEDESCRIPTORA pfdA = (pfgdA ? &pfgdA->fgd[pfgdA->cItems++] : NULL);
    LPFILEDESCRIPTORW pfdW = (pfgdW ? &pfgdW->fgd[pfgdW->cItems++] : NULL);

    pidl = ILGetLastID(pidlFull);
    if (pfdA)
    {
#if !DEBUG_LEGACY_PROGRESS
        pfdA->dwFlags = (FD_ATTRIBUTES | FD_FILESIZE | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_PROGRESSUI);
#else // !DEBUG_LEGACY_PROGRESS
        pfdA->dwFlags = (FD_ATTRIBUTES | FD_FILESIZE | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME);
#endif // !DEBUG_LEGACY_PROGRESS
        pfdA->dwFileAttributes = FtpItemID_GetAttributes(pidl);
        pfdA->nFileSizeLow = FtpItemID_GetFileSizeLo(pidl);
        pfdA->nFileSizeHigh = FtpItemID_GetFileSizeHi(pidl);

        // This sucks but all WIN32_FIND_DATA want to be stored in TimeZone independent
        // ways, except for WININET's FTP.  Also note that we only store Modified
        // time and use if for everything because of another UNIX/Wininet issue.
        // See priv.h on more FTP Time/Date issues.
        pfdA->ftCreationTime = FtpPidl_GetFileTime(ILFindLastID(pidl));
        pfdA->ftLastWriteTime = pfdA->ftCreationTime;
        pfdA->ftLastAccessTime = pfdA->ftCreationTime;
    }
    else
    {
#if !DEBUG_LEGACY_PROGRESS
        pfdW->dwFlags = (FD_ATTRIBUTES | FD_FILESIZE | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_PROGRESSUI);
#else // !DEBUG_LEGACY_PROGRESS
        pfdW->dwFlags = (FD_ATTRIBUTES | FD_FILESIZE | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME);
#endif // !DEBUG_LEGACY_PROGRESS
        pfdW->dwFileAttributes = FtpItemID_GetAttributes(pidl);
        pfdW->nFileSizeLow = FtpItemID_GetFileSizeLo(pidl);
        pfdW->nFileSizeHigh = FtpItemID_GetFileSizeHi(pidl);

        // This sucks but all WIN32_FIND_DATA want to be stored in TimeZone independent
        // ways, except for WININET's FTP.  Also note that we only store Modified
        // time and use if for everything because of another UNIX/Wininet issue.
        // See priv.h on more FTP Time/Date issues.
        pfdW->ftCreationTime = FtpPidl_GetFileTime(ILFindLastID(pidl));
        pfdW->ftLastWriteTime = pfdW->ftCreationTime;
        pfdW->ftLastAccessTime = pfdW->ftCreationTime;
    }

    LPCITEMIDLIST pidlDiff = FtpItemID_FindDifference(pUrlFileGroup->pidlParent, pidlFull);

    if (pfdA)
    {
        GetWirePathFromPidl(pidlDiff, pfdA->cFileName, ARRAYSIZE(pfdA->cFileName), FALSE);
        UrlPathRemoveSlashA(pfdA->cFileName);
        UrlPathRemoveFrontSlashA(pfdA->cFileName);
        UrlPathToFilePathA(pfdA->cFileName);
    }
    else
    {
        GetDisplayPathFromPidl(pidlDiff, pfdW->cFileName, ARRAYSIZE(pfdW->cFileName), FALSE);
        UrlPathRemoveSlashW(pfdW->cFileName);
        UrlPathRemoveFrontSlashW(pfdW->cFileName);
        UrlPathToFilePathW(pfdW->cFileName);
    }

    TraceMsg(TF_FTPURL_UTILS, "_Misc_HFGD_Create() pfd(A/W)->dwFileAttributes=%#08lX", (pfdW ? pfdW->dwFileAttributes : pfdA->dwFileAttributes));

    return fSucceeded;
}


BOOL _Misc_HFGD_Init(LPVOID pv, LPVOID pvHFPL, LPCVOID pvParam2, BOOL fUnicode)
{
    CFtpPidlList * pflHfpl = (CFtpPidlList *) pvHFPL;
    URL_FILEGROUP urlFG = {0};

    urlFG.pidlParent = (LPCITEMIDLIST) pvParam2;
    if (fUnicode)
        urlFG.pfgdW = (LPFILEGROUPDESCRIPTORW) pv;
    else
        urlFG.pfgdA = (LPFILEGROUPDESCRIPTORA) pv;

    TraceMsg(TF_PIDLLIST_DUMP, "_Misc_HFGD_Init() TraceDump Before");
    pflHfpl->TraceDump(NULL, TEXT("_Misc_HFGD_Init() TraceDump before"));

    pflHfpl->Enum(_Misc_HFGD_Create, (LPVOID) &urlFG);

    pflHfpl->TraceDump(NULL, TEXT("_Misc_HFGD_Init() TraceDump after"));

    return 1;
}


HGLOBAL Misc_HFGD_Create(CFtpPidlList * pflHfpl, LPCITEMIDLIST pidlItem, BOOL fUnicode)
{
    DWORD dwCount = pflHfpl->GetCount();
    DWORD cbAllocSize = (fUnicode ? cbFgdCfdW(dwCount) : cbFgdCfdA(dwCount));

    return AllocHGlob(cbAllocSize, _Misc_HFGD_Init, pflHfpl, (LPCVOID) pidlItem, fUnicode);
}


// Returns the submenu of the given menu and ID.  Returns NULL if there
// is no submenu
int _MergePopupMenus(HMENU hmDest, HMENU hmSource, int idCmdFirst, int idCmdLast)
{
    int i, idFinal = idCmdFirst;

    for (i = GetMenuItemCount(hmSource) - 1; i >= 0; --i)
    {
        MENUITEMINFO mii;

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

        if (EVAL(GetMenuItemInfo(hmSource, i, TRUE, &mii)))
        {
            HMENU hmDestSub = GetMenuFromID(hmDest, mii.wID);
            if (hmDestSub)
            {
                int idTemp = Shell_MergeMenus(hmDestSub, mii.hSubMenu, (UINT)0, idCmdFirst, idCmdLast, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);

                if (idFinal < idTemp)
                    idFinal = idTemp;
            }
        }
    }

    return idFinal;
}


/*****************************************************************************\
    FUNCTION: AddToPopupMenu

    DESCRIPTION:
      Swiped from utils.c in RNAUI, in turn swiped from the    ;Internal
      shell.                            ;Internal
                                  ;Internal
      Takes a destination menu and a (menu id, submenu index) pair,
      and inserts the items from the (menu id, submenu index) at location
      imi in the destination menu, with a separator, returning the number
      of items added.  (imi = index to menu item)
  
      Returns the first the number of items added.
  
      hmenuDst        - destination menu
      idMenuToAdd        - menu resource identifier
      idSubMenuIndex    - submenu from menu resource to act as template
      indexMenu        - location at which menu items should be inserted
      idCmdFirst        - first available menu identifier
      idCmdLast       - first unavailable menu identifier
      uFlags            - flags for Shell_MergeMenus
\*****************************************************************************/
#define FLAGS_MENUMERGE                 (MM_SUBMENUSHAVEIDS | MM_DONTREMOVESEPS)

UINT AddToPopupMenu(HMENU hmenuDst, UINT idMenuToAdd, UINT idSubMenuIndex, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
    UINT nLastItem = 0;

    HMENU hmenuSrc = LoadMenu(g_hinst, MAKEINTRESOURCE(idMenuToAdd));
    if (hmenuSrc)
    {
        nLastItem = Shell_MergeMenus(hmenuDst, GetSubMenu(hmenuSrc, idSubMenuIndex), indexMenu, idCmdFirst, idCmdLast, (uFlags | FLAGS_MENUMERGE));
        DestroyMenu(hmenuSrc);
    }

    return nLastItem;
}


UINT MergeInToPopupMenu(HMENU hmenuDst, UINT idMenuToMerge, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
    UINT nLastItem = 0;

    HMENU hmenuSrc = LoadMenu(g_hinst, MAKEINTRESOURCE(idMenuToMerge));
    if (hmenuSrc)
    {
        nLastItem = _MergePopupMenus(hmenuDst, hmenuSrc, idCmdFirst, idCmdLast);
        DestroyMenu(hmenuSrc);
    }

    return nLastItem;
}


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

    GetMenuFromID

    Swiped from defviewx.c in the shell.            ;Internal
                                ;Internal
    Given an actual menu and a menu identifier which corresponds
    to a submenu, return the submenu handle.

    hmenu - source menu
    idm   - menu identifier

\*****************************************************************************/
HMENU GetMenuFromID(HMENU hmenu, UINT idm)
{
    HMENU hmenuRet = NULL;
    if (!hmenu)
        return NULL;

    MENUITEMINFO mii;
    mii.cbSize = sizeof(mii);
    mii.fMask = MIIM_SUBMENU;
    mii.cch = 0;             // just in case
    mii.hSubMenu = 0;        // in case GetMenuItemInfo fails

    if (GetMenuItemInfo(hmenu, idm, 0, &mii))

⌨️ 快捷键说明

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