Search code examples
c#winformscomoutlookclipboard

FileDescriptora Missing Characters


I am using the code found here to drag-drop .msg files directly from outlook. The FileDescriptorA class is implemented like this:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEDESCRIPTORA
{
    public uint dwFlags;
    public Guid clsid;
    public SIZEL sizel;
    public POINTL pointl;
    public uint dwFileAttributes;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
    public uint nFileSizeHigh;
    public uint nFileSizeLow;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string cFileName;
}

And the code to get the file names is:

MemoryStream fgdStream = 
  (MemoryStream)e.Data.GetData("FileGroupDescriptor");
byte[] fgdBytes = new byte[fgdStream.Length];
fgdStream.Read(fgdBytes, 0, fgdBytes.Length);
fgdStream.Close();

//copy the file group descriptor into unmanaged memory
IntPtr fgdaPtr = Marshal.AllocHGlobal(fgdBytes.Length);
Marshal.Copy(fgdBytes, 0, fgdaPtr, fgdBytes.Length);

int numFiles = Marshal.ReadInt32(fgdaPtr);

string[] fileNames = new string[numFiles];

//get the pointer to the first file descriptor
IntPtr fdPtr = (IntPtr)((int)fgdaPointer + Marshal.SizeOf(fgdaPointer));

//loop for the number of files acording to the file group descriptor
for(int fdIndex = 0;fdIndex < numfiles;fdIndex++)
{
    //marshal the pointer to the file descriptor as a FILEDESCRIPTORA struct
    object fdObj = Marshal.PtrToStructure(fdPtr, 
                          typeof(NativeMethods.FILEDESCRIPTORA));
    NativeMethods.FILEDESCRIPTORA fd = (NativeMethods.FILEDESCRIPTORA)fdObj;

    //get file name of file descriptor and put in array
    fileNames[fdIndex] = fd.cFileName;

    //move the file descriptor pointer to the next file descriptor
    fdPtr = (IntPtr)((int)fdPtr + Marshal.SizeOf(fd));
}

This all works great, except for that the file name coming back is always missing the first couple characters. Does anyone know what would cause that and/or how to fix it?


Solution

  • In the comments on the codeproject page another person mentions the same problem - in that case the offset of an array item was computed from the start of the structure, not taking into account the first 32/64 bits that contain the number of items in the array:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public sealed class FILEGROUPDESCRIPTORA
    {
        public uint cItems;
        public FILEDESCRIPTORA[] fgd;
    }