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