-1

I used EasyHook to hook into the SetClipboardData() function.

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

I can either pass the data to the original function or return NULL.

The goal is to prevent the user from copying specific files.

This DLL will be injected into Explorer.exe and will be called whenever a user tries to copy a file.

How to obtain the filename being copied?

Is there any other way to achieve this?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Nocturnal
  • 33
  • 5
  • 1
    `GetFinalPathFromHandle` require file handle. hMem - not a file handle – RbMm Sep 04 '19 at 15:09
  • Yes i know. I tried that with NtOpenFile function which has a file handle.I forgot to remove GetFinalPathFromHandle from question. – Nocturnal Sep 04 '19 at 15:14
  • you need call `GetClipboardFormatName` - may be you get `CFSTR_FILENAMEW` or `CFSTR_SHELLIDLIST` – RbMm Sep 04 '19 at 15:14
  • *I tried that with NtOpenFile function* - but you need have file name for this first – RbMm Sep 04 '19 at 15:15
  • @RbMm i used GetFinalPathFromHandle when i hooked into the NtOpenFile function from ntdll. GetClipboardFormatName outputs multiple values such as DataObject, ShellIdListArray, DataObjectAttributes, FileName, FileNameW. – Nocturnal Sep 04 '19 at 15:24
  • @RbMm is there anyway to get filename or path from the handle? – Nocturnal Sep 04 '19 at 15:26
  • of course exist. but i not understand your question - are this about clipboard data, are this about get file name by handle.. – RbMm Sep 04 '19 at 15:27
  • if you have `FileNameW` (same as `CFSTR_FILENAMEW`) - what else you want ? – RbMm Sep 04 '19 at 15:27
  • @RbMm i want to get the filename before it goes to clipboard so i can prevent or allow it based on the file name. – Nocturnal Sep 04 '19 at 15:29
  • so ask another question - i have file handle - how get file path by it. or something else. how here clipboard related ? – RbMm Sep 04 '19 at 15:31
  • You realize the user can just copy the file in other ways? – Anders Sep 04 '19 at 16:02
  • @Anders yes the scope of the hook is to only prevent copy action using ctrl+c or copy from right click menu. – Nocturnal Sep 04 '19 at 16:04

1 Answers1

0

Files can be copied/pasted using a number of different clipboard formats, and multiple formats can reside on the clipboard at the same time.

  • CF_HDROP
  • CFSTR_FILECONTENTS
  • CFSTR_FILEDESCRIPTOR
  • CFSTR_FILENAME
  • CFSTR_FILENAMEMAP
  • CFSTR_MOUNTEDVOLUME
  • CFSTR_SHELLIDLIST
  • CFSTR_SHELLIDLISTOFFSET

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

So, you would need something like this:

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);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770