从 SetClipboardData 挂钩获取文件名

Obtain file name from SetClipboardData hook

我使用 EasyHook 挂接到 SetClipboardData() 函数。

HANDLE mySetClipBoardData (UINT uFormat, HANDLE hMem){
    return SetClipboardData(uFormat, hMem);
    //return NULL;
}

我可以将数据传递给原始函数或 return NULL。

目标是防止用户复制特定文件。

此 DLL 将被注入 Explorer.exe 并在用户尝试复制文件时调用。

如何获取被复制的文件名?

还有其他方法可以实现吗?

文件可以copied/pasted使用多种不同的剪贴板格式,并且多种格式可以同时驻留在剪贴板上。

  • CF_HDROP
  • CFSTR_FILECONTENTS
  • CFSTR_FILEDESCRIPTOR
  • CFSTR_FILENAME
  • CFSTR_FILENAME地图
  • CFSTR_MOUNTEDVOLUME
  • CFSTR_SHELLIDLIST
  • CFSTR_SHELLIDLIST偏移量

参考Shell Clipboard Formats for specific details about each format. In particular, see Formats for Transferring File System Objects.

所以,你需要这样的东西:

const UINT ui_CFSTR_SHELLIDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
const UINT ui_CFSTR_FILENAMEA = RegisterClipboardFormat(CFSTR_FILENAMEA);
const UINT ui_CFSTR_FILENAMEW = RegisterClipboardFormat(CFSTR_FILENAMEW);
...

HANDLE WINAPI mySetClipBoardData (UINT uFormat, HANDLE hMem)
{
    if (!hMem) // DELAYED RENDERING! The real data will come later...
        return SetClipboardData(uFormat, hMem);

    if (uFormat == CF_HDROP)
    {
        LPDROPFILES pDF = (LPDROPFILES) GlobalLock(hMem);
        if (pDF->fWide)
        {
            LPWSTR pFiles = (LPWSTR) (((LPBYTE)pDF) + pDF->pFiles);
            while (*pFiles)
            {
                LPWSTR pFile = pFiles;
                if (pFile refers to the desired file)
                {
                    GlobalUnlock(hMem);
                    SetLastError(...);
                    return NULL;

                    // alternatively, build up a new string to place on the clipboard that omits this file...
                }
                pFiles += (lstrlenW(pFile) + 1);
            }
        }
        else
        {
            LPSTR pFiles = (LPSTR) (((LPBYTE)pDF) + pDF->pFiles);
            while (*pFiles)
            {
                LPSTR pFile = pFiles;
                if (pFile refers to the desired file)
                {
                    GlobalUnlock(hMem);
                    SetLastError(...);
                    return NULL;

                    // alternatively, build up a new string to place on the clipboard that omits this file...
                }
                pFiles += (lstrlenA(pFile) + 1);
            }
        }

        GlobalUnlock(hMem);

        /* alternatively:

        TCHAR szFile[MAX_PATH];
        UINT count = DragQueryFile((HDROP)hMem, (UINT)-1, NULL, 0);
        for (UINT i = 0; i < count; ++i)
        {
            DragQueryFile((HDROP)hMem, i, szFile, MAX_PATH);
            if (szFile refers to the desired file)
            {
                SetLastError(...);
                return NULL;

                // alternatively, build up a new string to place on the clipboard that omits this file...
            }
        }
        */
    }
    else if (uFormat == ui_CFSTR_SHELLIDLIST)
    {
        #define HIDA_GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
        #define HIDA_GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])

        LPIDA pIDA = (LPIDA) GlobalLock(hMem);
        LPCITEMIDLIST pidlParent = HIDA_GetPIDLFolder(pIDA);

        for (UINT i = 0; i < pIDA->cidl; ++i)
        {
            LPCITEMIDLIST pidlFile = HIDA_GetPIDLItem(pIDA, i);

            if (pidlParent+pidlFile refers to the desired file)
            {
                GlobalUnlock(hMem);
                SetLastError(...);
                return NULL;

                // alternatively, build up a new array to place on the clipboard that omits this file...
            }
        }

        GlobalUnlock(hMem);
    }
    else if (uFormat == ui_CFSTR_FILENAMEA)
    {
        LPSTR pFile = (LPSTR) GlobalLock(hMem);
        if (pFile refers to the desired file)
        {
            GlobalUnlock(hMem);
            SetLastError(...);
            return NULL;
        }
        GlobalUnlock(hMem);
    }
    else if (uFormat == ui_CFSTR_FILENAMEW)
    {
        LPWSTR pFile = (LPWSTR) GlobalLock(hMem);
        if (pFile refers to the desired file)
        {
            GlobalUnlock(hMem);
            SetLastError(...);
            return NULL;
        }
        GlobalUnlock(hMem);
    }
    else
    {
        // handle other shell formats as needed...
    }

    return SetClipboardData(uFormat, hMem);
}