我可以将 Outlook 中的项目拖到我的 SWT 应用程序中吗?

发布于 2024-12-08 11:41:45 字数 4094 浏览 1 评论 0原文

背景

我们基于 Eclipse RCP 3.6 的应用程序允许人们拖动文件进行存储/处理。当从文件系统中拖动文件时,这种方法可以正常工作,但当人们直接从 Outlook 中拖动项目(消息或附件)时,这种方法就不行了。

这似乎是因为 Outlook 希望通过 FileGroupDescriptorWFileContents 向我们的应用程序提供文件,但 SWT 仅包含 FileTransfer 类型。 (在 FileTransfer 中,仅传递文件路径,并假设接收者可以找到并读取它们。FileGroupDescriptorW/FileContents 方法可以直接在应用程序到应用程序之间提供文件,而无需将临时文件写入磁盘。)

我们尝试生成一个可以接受 FileGroupDescriptorWByteArrayTransfer 子类,并且文件内容。根据网络上的一些示例,我们能够接收并解析 FileGroupDescriptorW ,它(顾名思义)描述了可传输的文件。 (参见下面的代码草图。)但是我们一直无法接受FileContents

这似乎是因为 Outlook 仅将 FileContents 数据提供为 TYMED_ISTREAMTYMED_ISTORAGE,但 SWT 只了解如何将数据交换为 TYMED_HGLOBAL。其中,TYMED_ISTORAGE 似乎更可取,因为尚不清楚 TYMED_ISTREAM 如何提供对多个文件内容的访问。

(考虑到我们需要处理两个类型,我们也对 SWT 只选择和转换单个 TransferData 类型感到担忧,但我们认为我们可以在 Java 中以某种方式解决这个问题:看起来所有TransferData 都可以在流程的其他点使用。)

问题

我们是否走在正确的轨道上?有人设法在 SWT 中接受 FileContents 吗?我们是否有可能在不离开 Java 的情况下处理 TYMED_ISTORAGE 数据(即使通过创建基于片段的补丁或 SWT 的派生版本),或者我们是否必须构建一些新的也有本机支持代码吗?

相关代码片段

提取文件名的草图代码:

    // THIS IS NOT PRODUCTION-QUALITY CODE - FOR ILLUSTRATION ONLY
    final Transfer transfer = new ByteArrayTransfer() {
        private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
        private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };

        @Override
        protected String[] getTypeNames() {
            return typeNames;
        }

        @Override
        protected int[] getTypeIds() {
            return typeIds;
        }

        @Override
        protected Object nativeToJava(TransferData transferData) {
            if (!isSupportedType(transferData))
                return null;

            final byte[] buffer = (byte[]) super.nativeToJava(transferData);
            if (buffer == null)
                return null;

            try {
                final DataInputStream in = new DataInputStream(new ByteArrayInputStream(buffer));

                long count = 0;
                for (int i = 0; i < 4; i++) {
                    count += in.readUnsignedByte() << i;
                }

                for (int i = 0; i < count; i++) {
                    final byte[] filenameBytes = new byte[260 * 2];
                    in.skipBytes(72); // probable architecture assumption(s) - may be wrong outside standard 32-bit Win XP
                    in.read(filenameBytes);
                    final String fileNameIncludingTrailingNulls = new String(filenameBytes, "UTF-16LE");
                    int stringLength = fileNameIncludingTrailingNulls.indexOf('\0');
                    if (stringLength == -1)
                        stringLength = 260;
                    final String fileName = fileNameIncludingTrailingNulls.substring(0, stringLength);
                    System.out.println("File " + i + ": " + fileName);
                }

                in.close();

                return buffer;
            }
            catch (final Exception e) {
                return null;
            }
        }
    };

在调试器中,我们看到 ByteArrayTransferisSupportedType() 最终返回 false 用于 FileContents,因为以下测试未通过(因为其 tymedTYMED_ISTREAM | TYMED_ISTORAGE):

    if (format.cfFormat == types[i] &&
        (format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT && 
        (format.tymed & COM.TYMED_HGLOBAL) == COM.TYMED_HGLOBAL  )
        return true;

这段摘录自 org.eclipse.swt.internal.ole.win32.COM 让我们对简单的解决方案不再抱有希望:

public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;

谢谢。

Background

Our Eclipse RCP 3.6-based application lets people drag files in for storage/processing. This works fine when the files are dragged from a filesystem, but not when people drag items (messages or attachments) directly from Outlook.

This appears to be because Outlook wants to feed our application the files via a FileGroupDescriptorW and FileContents, but SWT only includes a FileTransfer type. (In a FileTransfer, only the file paths are passed, with the assumption that the receiver can locate and read them. The FileGroupDescriptorW/FileContents approach can supply files directly application-to-application without writing temporary files out to disk.)

We have tried to produce a ByteArrayTransfer subclass that could accept FileGroupDescriptorW and FileContents. Based on some examples on the Web, we were able to receive and parse the FileGroupDescriptorW, which (as the name implies) describes the files available for transfer. (See code sketch below.) But we have been unable to accept the FileContents.

This seems to be because Outlook offers the FileContents data only as TYMED_ISTREAM or TYMED_ISTORAGE, but SWT only understands how to exchange data as TYMED_HGLOBAL. Of those, it appears that TYMED_ISTORAGE would be preferable, since it's not clear how TYMED_ISTREAM could provide access to multiple files' contents.

(We also have some concerns about SWT's desire to pick and convert only a single TransferData type, given that we need to process two, but we think we could probably hack around that in Java somehow: it seems that all the TransferDatas are available at other points of the process.)

Questions

Are we on the right track here? Has anyone managed to accept FileContents in SWT yet? Is there any chance that we could process the TYMED_ISTORAGE data without leaving Java (even if by creating a fragment-based patch to, or a derived version of, SWT), or would we have to build some new native support code too?

Relevant code snippets

Sketch code that extracts file names:

    // THIS IS NOT PRODUCTION-QUALITY CODE - FOR ILLUSTRATION ONLY
    final Transfer transfer = new ByteArrayTransfer() {
        private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
        private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };

        @Override
        protected String[] getTypeNames() {
            return typeNames;
        }

        @Override
        protected int[] getTypeIds() {
            return typeIds;
        }

        @Override
        protected Object nativeToJava(TransferData transferData) {
            if (!isSupportedType(transferData))
                return null;

            final byte[] buffer = (byte[]) super.nativeToJava(transferData);
            if (buffer == null)
                return null;

            try {
                final DataInputStream in = new DataInputStream(new ByteArrayInputStream(buffer));

                long count = 0;
                for (int i = 0; i < 4; i++) {
                    count += in.readUnsignedByte() << i;
                }

                for (int i = 0; i < count; i++) {
                    final byte[] filenameBytes = new byte[260 * 2];
                    in.skipBytes(72); // probable architecture assumption(s) - may be wrong outside standard 32-bit Win XP
                    in.read(filenameBytes);
                    final String fileNameIncludingTrailingNulls = new String(filenameBytes, "UTF-16LE");
                    int stringLength = fileNameIncludingTrailingNulls.indexOf('\0');
                    if (stringLength == -1)
                        stringLength = 260;
                    final String fileName = fileNameIncludingTrailingNulls.substring(0, stringLength);
                    System.out.println("File " + i + ": " + fileName);
                }

                in.close();

                return buffer;
            }
            catch (final Exception e) {
                return null;
            }
        }
    };

In the debugger, we see that ByteArrayTransfer's isSupportedType() ultimately returns false for the FileContents because the following test is not passed (since its tymed is TYMED_ISTREAM | TYMED_ISTORAGE):

    if (format.cfFormat == types[i] &&
        (format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT && 
        (format.tymed & COM.TYMED_HGLOBAL) == COM.TYMED_HGLOBAL  )
        return true;

This excerpt from org.eclipse.swt.internal.ole.win32.COM leaves us feeling less hope for an easy solution:

public static final int TYMED_HGLOBAL = 1;
//public static final int TYMED_ISTORAGE = 8;
//public static final int TYMED_ISTREAM = 4;

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初懵 2024-12-15 11:41:45

即使

//public static final int TYMED_ISTREAM = 4;

尝试下面的代码..它应该可以工作

package com.nagarro.jsag.poc.swtdrag;

imports ... 

public class MyTransfer extends ByteArrayTransfer {
private static int BYTES_COUNT = 592;
private static int SKIP_BYTES = 72;

private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };

@Override
protected String[] getTypeNames() {
    return typeNames;
}

@Override
protected int[] getTypeIds() {
    return typeIds;
}

@Override
protected Object nativeToJava(TransferData transferData) {
    String[] result = null;

    if (!isSupportedType(transferData) || transferData.pIDataObject == 0)
        return null;

    IDataObject data = new IDataObject(transferData.pIDataObject);
    data.AddRef();
    // Check for descriptor format type
    try {
        FORMATETC formatetcFD = transferData.formatetc;
        STGMEDIUM stgmediumFD = new STGMEDIUM();
        stgmediumFD.tymed = COM.TYMED_HGLOBAL;
        transferData.result = data.GetData(formatetcFD, stgmediumFD);

        if (transferData.result == COM.S_OK) {
            // Check for contents format type
            long hMem = stgmediumFD.unionField;
            long fileDiscriptorPtr = OS.GlobalLock(hMem);
            int[] fileCount = new int[1];
            try {
                OS.MoveMemory(fileCount, fileDiscriptorPtr, 4);
                fileDiscriptorPtr += 4;
                result = new String[fileCount[0]];
                for (int i = 0; i < fileCount[0]; i++) {
                    String fileName = handleFile(fileDiscriptorPtr, data);
                    System.out.println("FileName : = " + fileName);
                    result[i] = fileName;
                    fileDiscriptorPtr += BYTES_COUNT;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                OS.GlobalFree(hMem);
            }
        }
    } finally {
        data.Release();
    }
    return result;
}

private String handleFile(long fileDiscriptorPtr, IDataObject data) throws Exception {

    // GetFileName
    char[] fileNameChars = new char[OS.MAX_PATH];
    byte[] fileNameBytes = new byte[OS.MAX_PATH];
    COM.MoveMemory(fileNameBytes, fileDiscriptorPtr, BYTES_COUNT);
    // Skip some bytes.
    fileNameBytes = Arrays.copyOfRange(fileNameBytes, SKIP_BYTES, fileNameBytes.length);
    String fileNameIncludingTrailingNulls = new String(fileNameBytes, "UTF-16LE");
    fileNameChars = fileNameIncludingTrailingNulls.toCharArray();
    StringBuilder builder = new StringBuilder(OS.MAX_PATH);
    for (int i = 0; fileNameChars[i] != 0 && i < fileNameChars.length; i++) {
        builder.append(fileNameChars[i]);
    }
    String name = builder.toString();

    try {
        File file = saveFileContent(name, data);
        if (file != null) {
            System.out.println("File Saved @ " + file.getAbsolutePath());
            ;
        }
    } catch (IOException e) {
        System.out.println("Count not save file content");
        ;
    }

    return name;
}

private File saveFileContent(String fileName, IDataObject data) throws IOException {
    File file = null;
    FORMATETC formatetc = new FORMATETC();
    formatetc.cfFormat = typeIds[1];
    formatetc.dwAspect = COM.DVASPECT_CONTENT;
    formatetc.lindex = 0;
    formatetc.tymed = 4; // content.

    STGMEDIUM stgmedium = new STGMEDIUM();
    stgmedium.tymed = 4;

    if (data.GetData(formatetc, stgmedium) == COM.S_OK) {
        file = new File(fileName);
        IStream iStream = new IStream(stgmedium.unionField);
        iStream.AddRef();

        try (FileOutputStream outputStream = new FileOutputStream(file)) {

            int increment = 1024 * 4;
            long pv = COM.CoTaskMemAlloc(increment);
            int[] pcbWritten = new int[1];
            while (iStream.Read(pv, increment, pcbWritten) == COM.S_OK && pcbWritten[0] > 0) {
                byte[] buffer = new byte[pcbWritten[0]];
                OS.MoveMemory(buffer, pv, pcbWritten[0]);
                outputStream.write(buffer);
            }
            COM.CoTaskMemFree(pv);

        } finally {
            iStream.Release();
        }
        return file;
    } else {
        return null;
    }
}
}

even if

//public static final int TYMED_ISTREAM = 4;

Try below code.. it should work

package com.nagarro.jsag.poc.swtdrag;

imports ... 

public class MyTransfer extends ByteArrayTransfer {
private static int BYTES_COUNT = 592;
private static int SKIP_BYTES = 72;

private final String[] typeNames = new String[] { "FileGroupDescriptorW", "FileContents" };
private final int[] typeIds = new int[] { registerType(typeNames[0]), registerType(typeNames[1]) };

@Override
protected String[] getTypeNames() {
    return typeNames;
}

@Override
protected int[] getTypeIds() {
    return typeIds;
}

@Override
protected Object nativeToJava(TransferData transferData) {
    String[] result = null;

    if (!isSupportedType(transferData) || transferData.pIDataObject == 0)
        return null;

    IDataObject data = new IDataObject(transferData.pIDataObject);
    data.AddRef();
    // Check for descriptor format type
    try {
        FORMATETC formatetcFD = transferData.formatetc;
        STGMEDIUM stgmediumFD = new STGMEDIUM();
        stgmediumFD.tymed = COM.TYMED_HGLOBAL;
        transferData.result = data.GetData(formatetcFD, stgmediumFD);

        if (transferData.result == COM.S_OK) {
            // Check for contents format type
            long hMem = stgmediumFD.unionField;
            long fileDiscriptorPtr = OS.GlobalLock(hMem);
            int[] fileCount = new int[1];
            try {
                OS.MoveMemory(fileCount, fileDiscriptorPtr, 4);
                fileDiscriptorPtr += 4;
                result = new String[fileCount[0]];
                for (int i = 0; i < fileCount[0]; i++) {
                    String fileName = handleFile(fileDiscriptorPtr, data);
                    System.out.println("FileName : = " + fileName);
                    result[i] = fileName;
                    fileDiscriptorPtr += BYTES_COUNT;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                OS.GlobalFree(hMem);
            }
        }
    } finally {
        data.Release();
    }
    return result;
}

private String handleFile(long fileDiscriptorPtr, IDataObject data) throws Exception {

    // GetFileName
    char[] fileNameChars = new char[OS.MAX_PATH];
    byte[] fileNameBytes = new byte[OS.MAX_PATH];
    COM.MoveMemory(fileNameBytes, fileDiscriptorPtr, BYTES_COUNT);
    // Skip some bytes.
    fileNameBytes = Arrays.copyOfRange(fileNameBytes, SKIP_BYTES, fileNameBytes.length);
    String fileNameIncludingTrailingNulls = new String(fileNameBytes, "UTF-16LE");
    fileNameChars = fileNameIncludingTrailingNulls.toCharArray();
    StringBuilder builder = new StringBuilder(OS.MAX_PATH);
    for (int i = 0; fileNameChars[i] != 0 && i < fileNameChars.length; i++) {
        builder.append(fileNameChars[i]);
    }
    String name = builder.toString();

    try {
        File file = saveFileContent(name, data);
        if (file != null) {
            System.out.println("File Saved @ " + file.getAbsolutePath());
            ;
        }
    } catch (IOException e) {
        System.out.println("Count not save file content");
        ;
    }

    return name;
}

private File saveFileContent(String fileName, IDataObject data) throws IOException {
    File file = null;
    FORMATETC formatetc = new FORMATETC();
    formatetc.cfFormat = typeIds[1];
    formatetc.dwAspect = COM.DVASPECT_CONTENT;
    formatetc.lindex = 0;
    formatetc.tymed = 4; // content.

    STGMEDIUM stgmedium = new STGMEDIUM();
    stgmedium.tymed = 4;

    if (data.GetData(formatetc, stgmedium) == COM.S_OK) {
        file = new File(fileName);
        IStream iStream = new IStream(stgmedium.unionField);
        iStream.AddRef();

        try (FileOutputStream outputStream = new FileOutputStream(file)) {

            int increment = 1024 * 4;
            long pv = COM.CoTaskMemAlloc(increment);
            int[] pcbWritten = new int[1];
            while (iStream.Read(pv, increment, pcbWritten) == COM.S_OK && pcbWritten[0] > 0) {
                byte[] buffer = new byte[pcbWritten[0]];
                OS.MoveMemory(buffer, pv, pcbWritten[0]);
                outputStream.write(buffer);
            }
            COM.CoTaskMemFree(pv);

        } finally {
            iStream.Release();
        }
        return file;
    } else {
        return null;
    }
}
}
原来是傀儡 2024-12-15 11:41:45

您是否看过 https://bugs.eclipse.org/bugs/show_bug.cgi ?id=132514

此 bugzilla 条目附带了一个可能令人感兴趣的补丁(针对相当旧的 SWT 版本)。

Have you looked at https://bugs.eclipse.org/bugs/show_bug.cgi?id=132514 ?

Attached to this bugzilla entry is an patch (against an rather old version of SWT) that might be of interest.

迷途知返 2024-12-15 11:41:45

我遇到了同样的问题,并创建了一个小型库,为 JAVA SWT 提供拖放传输类。可以在这里找到:

https://github.com/HendrikHoetker/OutlookItemTransfer

目前它支持删除邮件从 Outlook 到 Java SWT 应用程序的项目将提供 OutlookItems 列表以及文件名和文件内容的字节数组。

一切都是纯 Java 且位于内存中(没有临时文件)。

在 SWT java 应用程序中的用法:

  if (OutlookItemTransfer.getInstance().isSupportedType(event.currentDataType)) {
      Object o = OutlookItemTransfer.getInstance().nativeToJava(event.currentDataType);
      if (o != null && o instanceof OutlookMessage[]) {
          OutlookMessage[] outlookMessages = (OutlookMessage[])o;
          for (OutlookMessage msg: outlookMessages) {
              //...
          }
      }
  }

OutlookItem 将提供两个元素:字符串形式的文件名和字节数组形式的文件内容。

从这里开始,人们可以将其写入文件或进一步处理字节数组。

针对你上面的问题:
- 您在文件描述符中找到的是 Outlook 项目的文件名和指向 IDataObject 的指针
- IDataObject 可以被解析并提供一个 IStorage 对象
- IStorageObject 将成为根容器,提供类似于文件系统的进一步子 IStorageObject 或 IStream(目录 = IStorage,文件 = IStream

您可以在以下代码行中找到这些元素:

  • 获取文件内容,请参阅 OutlookItemTransfer.java ,方法nativeToJava:

    FORMATETC 格式 = new FORMATETC();
    format.cfFormat = getTypeIds()[1];
    format.dwAspect = COM.DVASPECT_CONTENT;
    format.lindex = <文件索引>;
    格式.ptd = 0;
    格式.tymed = TYMED_ISTORAGE | TYMED_ISTREAM | COM.TYMED_HGLOBAL;
    
    STGMEDIUM 介质 = 新 STGMEDIUM();
    
    if (data.GetData(format,medium) == COM.S_OK) {
        //medium.tymed 现在将包含 TYMED_ISTORAGE
        // 在medium.unionfield中你会找到根IStorage
    }
    
  • 读取根IStorage,请参阅CompoundStorage,方法readOutlookStorage:

     // 打开 IStorage 对象
    IStorage 存储 = new IStorage(pIStorage);
    存储.AddRef();
    
    
    // 遍历 IStorage 对象的内容
    long[] pEnumStorage = new long[1];
    if (storage.EnumElements(0, 0, 0, pEnumStorage) == COM.S_OK) {
    
        // 获取存储迭代器
        IEnumSTATSTG enumStorage = new IEnumSTATSTG(pEnumStorage[0]);
        enumStorage.AddRef();
        enumStorage.Reset();
    
        // 准备 statstg 结构,它告诉迭代器找到的对象
        长 pSTATSTG = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, STATSTG.sizeof);
        获取的 int[] = 新 int[1];
    
        while (enumStorage.Next(1, pSTATSTG, fetched) == COM.S_OK && fetched[0] == 1) {
            // 获取找到的对象的描述
            STATSTG statstg = 新的 STATSTG();
            COM.MoveMemory(statstg, pSTATSTG, STATSTG.sizeof);
    
            // 获取找到的对象的名称
            字符串名称 = readPWCSName(statstg);
    
            // 取决于对象类型
            开关(statstg.type){
                case COM.STGTY_STREAM: { // 加载 IStream (=文件)
                    长[] pIStream = 新长[1];
    
                    // 获取指向IStream的指针
                    if (storage.OpenStream(名称, 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, pIStream) == COM.S_OK) {
                        // 加载IStream
                    }
                }
    
                case COM.STGTY_STORAGE: { // 加载 IStorage (=SubDirectory) - 需要递归来遍历子模具
    
                    }
    
                }
            }
        }
    
        // 关闭迭代器
        enumStorage.Release();
    }
    
    // 关闭 IStorage 对象
    存储.Release();
    

I had the same problem and created a small library providing a Drag'n Drop Transfer Class for JAVA SWT. It can be found here:

https://github.com/HendrikHoetker/OutlookItemTransfer

Currently it supports dropping Mail Items from Outlook to your Java SWT application and will provide a list of OutlookItems with the Filename and a byte array of the file contents.

All is pure Java and in-memory (no temp files).

Usage in your SWT java application:

  if (OutlookItemTransfer.getInstance().isSupportedType(event.currentDataType)) {
      Object o = OutlookItemTransfer.getInstance().nativeToJava(event.currentDataType);
      if (o != null && o instanceof OutlookMessage[]) {
          OutlookMessage[] outlookMessages = (OutlookMessage[])o;
          for (OutlookMessage msg: outlookMessages) {
              //...
          }
      }
  }

The OutlookItem will then provide two elements: filename as String and file contents as array of byte.

From here on, one could write it to a file or further process the byte array.

To your question above:
- What you find in the file descriptor is the filename of the outlook item and a pointer to an IDataObject
- the IDataObject can be parsed and will provide an IStorage object
- The IStorageObject will be then a root container providing further sub-IStorageObjects or IStreams similar to a filesystem (directory = IStorage, file = IStream

You find those elements in the following lines of code:

  • Get File Contents, see OutlookItemTransfer.java, method nativeToJava:

    FORMATETC format = new FORMATETC();
    format.cfFormat = getTypeIds()[1];
    format.dwAspect = COM.DVASPECT_CONTENT;
    format.lindex = <fileIndex>;
    format.ptd = 0;
    format.tymed = TYMED_ISTORAGE | TYMED_ISTREAM | COM.TYMED_HGLOBAL;
    
    STGMEDIUM medium = new STGMEDIUM();
    
    if (data.GetData(format, medium) == COM.S_OK) {
        // medium.tymed will now contain TYMED_ISTORAGE
        // in medium.unionfield you will find the root IStorage
    }
    
  • Read the root IStorage, see CompoundStorage, method readOutlookStorage:

        // open IStorage object
    IStorage storage = new IStorage(pIStorage);
    storage.AddRef();
    
    
    // walk through the content of the IStorage object
    long[] pEnumStorage = new long[1];
    if (storage.EnumElements(0, 0, 0, pEnumStorage) == COM.S_OK) {
    
        // get storage iterator
        IEnumSTATSTG enumStorage = new IEnumSTATSTG(pEnumStorage[0]);
        enumStorage.AddRef();
        enumStorage.Reset();
    
        // prepare statstg structure which tells about the object found by the iterator
        long pSTATSTG = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, STATSTG.sizeof);
        int[] fetched = new int[1];
    
        while (enumStorage.Next(1, pSTATSTG, fetched) == COM.S_OK && fetched[0] == 1) {
            // get the description of the the object found
            STATSTG statstg = new STATSTG();
            COM.MoveMemory(statstg, pSTATSTG, STATSTG.sizeof);
    
            // get the name of the object found
            String name = readPWCSName(statstg);
    
            // depending on type of object
            switch (statstg.type) {
                case COM.STGTY_STREAM: {    // load an IStream (=File)
                    long[] pIStream = new long[1];
    
                    // get the pointer to the IStream
                    if (storage.OpenStream(name, 0, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, pIStream) == COM.S_OK) {
                        // load the IStream
                    }
                }
    
                case COM.STGTY_STORAGE: {   // load an IStorage (=SubDirectory) - requires recursion to traverse the sub dies
    
                    }
    
                }
            }
        }
    
        // close the iterator
        enumStorage.Release();
    }
    
    // close the IStorage object
    storage.Release();
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文