文件描述缺失字符

FileDescriptora Missing Characters

我正在使用找到的代码 here 直接从 outlook 中拖放 .msg 文件。 FileDescriptorA class 是这样实现的:

[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;
}

获取文件名的代码是:

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));
}

这一切都很好,除了返回的文件名总是缺少前几个字符。有谁知道什么会导致 and/or 如何修复它?

the codeproject page 的评论中,另一个人提到了同样的问题 - 在这种情况下,数组项的偏移量是从结构的开头计算的,没有考虑前 32/64 位包含数组中的项目数:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEGROUPDESCRIPTORA
{
    public uint cItems;
    public FILEDESCRIPTORA[] fgd;
}
IntPtr fileDescriptorPointer = (IntPtr)((long)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptorWPointer) - 4);

fileDescriptorPointer = (IntPtr)((long)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor) - 4);

(long) 64 位支持

- 4 用于获取前 2 个字符 (4 = sizeof(uint))

重复了逻辑(不是代码),所以必须修改两次。

实际上 运行 作为 32 位进程时必须区分代码,因为 -4 移动在这种情况下不起作用:

if (Environment.Is64BitProcess)
    {
        fileDescriptorPointer = (IntPtr)((long)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptorAPointer)) - 4;
    }
    else
    {
        fileDescriptorPointer = (IntPtr)((long)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptorAPointer)) ;
    }