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 + -
显示快捷键?