Copy file from TrueCrypt volume to clipboard?

前端 未结 1 1006
难免孤独
难免孤独 2021-01-03 00:21

I use this code to copy files to Clipboard:

IDataObject data = new DataObject();
data.SetData(DataFormats.FileDrop, new string[] {@\"X:\\test.doc\"});
Memory         


        
1条回答
  •  隐瞒了意图╮
    2021-01-03 01:00

    Unfortunately, I do not think you can get away without a proper Shell ID list, on my Windows 7 your code doesn't even work with regular file system. The proper code would first and foremost provide a CIDL:

        var data = new DataObject();
        var files = new StringCollection() { @"T:\Test.doc" };
        data.SetFileDropList(files);
        data.SetData("Preferred DropEffect", true, new MemoryStream(new byte[] { 5, 0, 0, 0 }));
        data.SetData("Shell IDList Array", true, CreateShellIDList(files));
        Clipboard.SetDataObject(data, true);
    

    Where CreateShellIDList creates a binary representation of CIDA (CFSTR_SHELLIDLIST) structure needed. The implementation is below:

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr ILCreateFromPath(string path);
    [DllImport("shell32.dll", CharSet = CharSet.None)]
    public static extern void ILFree(IntPtr pidl);
    [DllImport("shell32.dll", CharSet = CharSet.None)]
    public static extern int ILGetSize(IntPtr pidl);
    
    private static MemoryStream CreateShellIDList(StringCollection filenames)
    {
        // first convert all files into pidls list
        int pos = 0;
        byte[][] pidls = new byte[filenames.Count][];
        foreach (var filename in filenames)
        {
            // Get pidl based on name
            IntPtr pidl = ILCreateFromPath(filename);
            int pidlSize = ILGetSize(pidl);
            // Copy over to our managed array
            pidls[pos] = new byte[pidlSize];
            Marshal.Copy(pidl, pidls[pos++], 0, pidlSize);
            ILFree(pidl);
        }
    
        // Determine where in CIDA we will start pumping PIDLs
        int pidlOffset = 4 * (filenames.Count + 2);
        // Start the CIDA stream stream
        var memStream = new MemoryStream();
        var sw = new BinaryWriter(memStream);
        // Initialize CIDA witha count of files
        sw.Write(filenames.Count);
        // Calcualte and write relative offsets of every pidl starting with root
        sw.Write(pidlOffset);
        pidlOffset += 4; // root is 4 bytes
        foreach(var pidl in pidls)
        {
            sw.Write(pidlOffset);
            pidlOffset += pidl.Length;
        }
    
        // Write the root pidl (0) followed by all pidls
        sw.Write(0);
        foreach(var pidl in pidls) sw.Write(pidl);
        // stream now contains the CIDA
        return memStream;
    }
    

    I can't take all the credit here, I found this CIDA code some time ago and just ported it to c#. Can't really remember the original source but it works well so far (I just tested it on TrueCrypt as well)

    0 讨论(0)
提交回复
热议问题