util.cpp

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

CPP
1,997
字号
/*****************************************************************************\
    FILE: util.cpp
    
    DESCRIPTION:
        Shared stuff that operates on all classes.
\*****************************************************************************/

#include "priv.h"
#include "util.h"
#include "ftpurl.h"
#include "view.h"
#include "statusbr.h"
#include <commctrl.h>
#include <shdocvw.h>

HINSTANCE g_hinst;              /* My instance handle */
CHAR g_szShell32[MAX_PATH];     /* Full path to shell32.dll (must be ANSI) */

DWORD GetOSVer(void);

#ifdef DEBUG
DWORD g_TLSliStopWatchStartHi = 0;
DWORD g_TLSliStopWatchStartLo = 0;
LARGE_INTEGER g_liStopWatchFreq = {0};
#endif // DEBUG

// Shell32.dll v3 (original Win95/WinNT) has so many bugs when it receives
// an IDataObject with FILEGROUPDESCRIPTOR that it doesn't make sense to allow
// users to drag from FTP with FILEGROUPDESCRIPTOR on these early shell machines.
// This #define turns this on off.
//#define BROWSERONLY_DRAGGING        1

const VARIANT c_vaEmpty = {0};
#define PVAREMPTY ((VARIANT*)&c_vaEmpty)

//////////////////////////// IE 5 vs IE 4 /////////////////////////////////
// These are functions that IE5 exposes (normally in shlwapi), but
// if we want to be compatible with IE4, we need to have our own copy.s
// If we turn on USE_IE5_UTILS, we won't work with IE4's DLLs (like shlwapi).
//
#ifndef USE_IE5_UTILS
void UnicWrapper_IUnknown_Set(IUnknown ** ppunk, IUnknown * punk)
{
    ENTERCRITICAL;

    if (*ppunk)
        (*ppunk)->Release();

    *ppunk = punk;
    if (punk)
        punk->AddRef();

    LEAVECRITICAL;
}

void UnicWrapper_IUnknown_AtomicRelease(void ** ppunk)
{
    if (ppunk && *ppunk) {
        IUnknown* punk = *(IUnknown**)ppunk;
        *ppunk = NULL;
        punk->Release();
    }
}


DWORD UnicWrapper_SHWaitForSendMessageThread(HANDLE hThread, DWORD dwTimeout)
{
    MSG msg;
    DWORD dwRet;
    DWORD dwEnd = GetTickCount() + dwTimeout;

    // We will attempt to wait up to dwTimeout for the thread to
    // terminate
    do
    {
        dwRet = MsgWaitForMultipleObjects(1, &hThread, FALSE,
                dwTimeout, QS_SENDMESSAGE);
        if (dwRet == WAIT_OBJECT_0 ||
            dwRet == WAIT_FAILED)
        {
            // The thread must have exited, so we are happy
            break;
        }

        if (dwRet == WAIT_TIMEOUT)
        {
            // The thread is taking too long to finish, so just
            // return and let the caller kill it
            break;
        }

        // There must be a pending SendMessage from either the
        // thread we are killing or some other thread/process besides
        // this one.  Do a PeekMessage to process the pending
        // SendMessage and try waiting again
        PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

        if (dwTimeout != INFINITE)
            dwTimeout = dwEnd - GetTickCount();
    }
    while((dwTimeout == INFINITE) || ((long)dwTimeout > 0));

    return(dwRet);
}


/****************************************************\
    FUNCTION: UnicWrapper_AutoCompleteFileSysInEditbox

    DESCRIPTION:
        This function will have AutoComplete take over
    an editbox to help autocomplete DOS paths.
\****************************************************/
HRESULT UnicWrapper_AutoCompleteFileSysInEditbox(HWND hwndEdit)
{
    HRESULT hr;
    IUnknown * punkACLISF;

    hr = CoCreateInstance(CLSID_ACListISF, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&punkACLISF);
    if (EVAL(SUCCEEDED(hr)))
    {
        IAutoComplete * pac;

        // Create the AutoComplete Object
        hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, IID_IAutoComplete, (void **)&pac);
        if (EVAL(SUCCEEDED(hr)))
        {
            hr = pac->Init(hwndEdit, punkACLISF, NULL, NULL);
            pac->Release();
        }

        punkACLISF->Release();
    }

    return hr;
}


#endif // USE_IE5_UTILS
//////////////////////////// IE 5 vs IE 4 /////////////////////////////////


void IUnknown_Set(IMalloc ** ppm, IMalloc * pm)
{
    ENTERCRITICAL;

    if (*ppm)
        (*ppm)->Release();
    
    *ppm = pm;

    if (pm)
        pm->AddRef();

    LEAVECRITICAL;
}

// TODO: This is a remnent of using C++ in stead of real COM
void IUnknown_Set(CFtpFolder ** ppff, CFtpFolder * pff)
{
    ENTERCRITICAL;

    if (*ppff)
        (*ppff)->Release();
    
    *ppff = pff;

    if (pff)
        pff->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpDir ** ppfd, CFtpDir * pfd)
{
    ENTERCRITICAL;

    if (*ppfd)
        (*ppfd)->Release();
    
    *ppfd = pfd;

    if (pfd)
        pfd->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpSite ** ppfs, CFtpSite * pfs)
{
    ENTERCRITICAL;

    if (*ppfs)
        (*ppfs)->Release();
    
    *ppfs = pfs;

    if (pfs)
        pfs->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpList ** ppfl, CFtpList * pfl)
{
    ENTERCRITICAL;

    if (*ppfl)
        (*ppfl)->Release();
    
    *ppfl = pfl;

    if (pfl)
        pfl->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpPidlList ** ppflpidl, CFtpPidlList * pflpidl)
{
    ENTERCRITICAL;

    if (*ppflpidl)
        (*ppflpidl)->Release();
    
    *ppflpidl = pflpidl;

    if (pflpidl)
        pflpidl->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpEfe ** ppfefe, CFtpEfe * pfefe)
{
    ENTERCRITICAL;

    if (*ppfefe)
        (*ppfefe)->Release();
    
    *ppfefe = pfefe;

    if (pfefe)
        pfefe->AddRef();

    LEAVECRITICAL;
}

void IUnknown_Set(CFtpGlob ** ppfg, CFtpGlob * pfg)
{
    ENTERCRITICAL;

    if (*ppfg)
        (*ppfg)->Release();
    
    *ppfg = pfg;

    if (pfg)
        pfg->AddRef();

    LEAVECRITICAL;
}


void IUnknown_Set(CFtpMenu ** ppfcm, CFtpMenu * pfcm)
{
    ENTERCRITICAL;

    if (*ppfcm)
        (*ppfcm)->Release();
    
    *ppfcm = pfcm;

    if (pfcm)
        pfcm->AddRef();

    LEAVECRITICAL;
}


void IUnknown_Set(CFtpStm ** ppfstm, CFtpStm * pfstm)
{
    ENTERCRITICAL;

    if (*ppfstm)
        (*ppfstm)->Release();
    
    *ppfstm = pfstm;

    if (pfstm)
        pfstm->AddRef();

    LEAVECRITICAL;
}


#undef ILCombine
// Fix Shell32 bug
LPITEMIDLIST ILCombineWrapper(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
    if (!pidl1)
        return ILClone(pidl2);

    if (!pidl2)
        return ILClone(pidl1);

    return ILCombine(pidl1, pidl2);
}


#undef ILClone
// Fix Shell32 bug
LPITEMIDLIST ILCloneWrapper(LPCITEMIDLIST pidl)
{
    if (!pidl)
        return NULL;

    return ILClone(pidl);
}


#undef ILFree
// Fix Shell32 bug
void ILFreeWrapper(LPITEMIDLIST pidl)
{
    if (pidl)
        ILFree(pidl);
}


// BUGBUG: Don't ship with this on.
//#define DEBUG_LEGACY

BOOL IsLegacyChangeNotifyNeeded(LONG wEventId)
{
#ifdef DEBUG_LEGACY
    return TRUE;
#endif // DEBUG_LEGACY

    // The only version that doesn't support IDelegateFolder pidls is
    // shell32 v3 (w/o IE4 Shell Intergrated)
    BOOL fResult = (SHELL_VERSION_W95NT4 == GetShellVersion());
    
    return fResult;
}



/*****************************************************************************\
    FUNCTION: LegacyChangeNotify

    DESCRIPTION:
        Browser only can't read IDelegateFolder pidls (our Pidls), so we need
    to use this function instead of SHChangeNotify that will use hacks to
    get DefView's ListView to update by using 
    SHShellFolderView_Message(HWND hwnd, UINT uMsg, LPARAM lParam).

    These are the messages to use.
    SFVM_ADDOBJECT (SHCNE_CREATE & SHCNE_MKDIR),
    SFVM_UPDATEOBJECT (SHCNE_RENAMEFOLDER, SHCNE_RENAMEITEM, SHCNE_ATTRIBUTES), or SFVM_REFRESHOBJECT(),
    SFVM_REMOVEOBJECT (SHCNE_RMDIR & SHCNE_DELETE).
\*****************************************************************************/
HRESULT LegacyChangeNotify(HWND hwnd, LONG wEventId, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
    if (EVAL(hwnd))       // We can't talk to the window w/o this.
    {
        switch(wEventId)
        {
        case SHCNE_CREATE:
        case SHCNE_MKDIR:
        {
            // BUGBUG: If the item alread exists, it will create a new duplicate name.
            //         We need to skip this if it exists.
            LPCITEMIDLIST pidlRelative = ILGetLastID(pidl1);
            // For some lame reason, SFVM_ADDOBJECT frees the pidl we give them.
            EVAL(SHShellFolderView_Message(hwnd, SFVM_ADDOBJECT, (LPARAM) ILClone(pidlRelative)));
            break;
        }
        case SHCNE_RMDIR:
        case SHCNE_DELETE:
        {
            LPCITEMIDLIST pidlRelative = ILGetLastID(pidl1);
            EVAL(SHShellFolderView_Message(hwnd, SFVM_REMOVEOBJECT, (LPARAM) pidlRelative));
            break;
        }
        case SHCNE_RENAMEFOLDER:
        case SHCNE_RENAMEITEM:
        case SHCNE_ATTRIBUTES:
        {
            LPCITEMIDLIST pidlArray[2];
            
            pidlArray[0] = ILGetLastID(pidl1);
            pidlArray[1] = ILClone(ILGetLastID(pidl2));
            EVAL(SHShellFolderView_Message(hwnd, SFVM_UPDATEOBJECT, (LPARAM) pidlArray));
            break;
        }
        }
    }

    return S_OK;

⌨️ 快捷键说明

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