Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » [Outlook Drop] Read bytes from an IStorage
[Outlook Drop] Read bytes from an IStorage [message #520204] Thu, 11 March 2010 14:50 Go to next message
Thomas Kratz is currently offline Thomas KratzFriend
Messages: 165
Registered: July 2009
Senior Member
Hi all, I am making progress with my outlook drop transfer. The trick is to register FileContent and use the returned int as type for the transfers FORMATETC. it then returns an IStorage and I don't know how to read the bytes from it. It seems to be an outlook .msg file content (dont need to parse it, just want to store the file in jackrabbit) I found a c# example that goes like


switch(medium.tymed)
            {
                case TYMED.TYMED_ISTORAGE:
                    //to handle a IStorage it needs to be written into a second unmanaged
                    //memory mapped storage and then the data can be read from memory into
                    //a managed byte and returned as a MemoryStream

                    NativeMethods.IStorage iStorage = null;
                    NativeMethods.IStorage iStorage2 = null;
                    NativeMethods.ILockBytes iLockBytes = null;
                    System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat;
                    try
                    {
                        //marshal the returned pointer to a IStorage object
                        iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember);
                        Marshal.Release(medium.unionmember);

                        //create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store
                        iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
                        iStorage2 = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);

                        //copy the returned IStorage into the new IStorage
                        iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
                        iLockBytes.Flush();
                        iStorage2.Commit(0);

                        //get the STATSTG of the ILockBytes to determine how many bytes were written to it
                        iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG();
                        iLockBytes.Stat(out iLockBytesStat, 1);
                        int iLockBytesSize = (int)iLockBytesStat.cbSize;

                        //read the data from the ILockBytes (unmanaged byte array) into a managed byte array
                        byte[] iLockBytesContent = new byte[iLockBytesSize];
                        iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null);

                        //wrapped the managed byte array into a memory stream and return it
                        return new MemoryStream(iLockBytesContent);
                    }
                    finally
                    {
                        //release all unmanaged objects
                        Marshal.ReleaseComObject(iStorage2);
                        Marshal.ReleaseComObject(iLockBytes);
                        Marshal.ReleaseComObject(iStorage);
                    }



can anyone tell me what i need to do to gte the bytes from this IStorage

my code so far goes this way:

public OutLookTransfer()
	{
		type = registerType("FileContents");
	}

public Object nativeToJava(TransferData transferData)
	{

		IDataObject idata = new IDataObject(transferData.pIDataObject);
		idata.AddRef();
		FORMATETC formatetc = new FORMATETC();

		STGMEDIUM stgmedium = new STGMEDIUM();
		// stgmedium.tymed = COM.TYMED_HGLOBAL;

		formatetc.cfFormat = type;
		System.out.println("Format: " + formatetc.cfFormat);
		formatetc.lindex = 0;

		formatetc.ptd = 0;

		formatetc.tymed = 4 | 8 | 1;
		formatetc.dwAspect = COM.DVASPECT_CONTENT;

		transferData.result = getData(idata, formatetc, stgmedium);
		idata.Release();
		if (transferData.result != COM.S_OK)
		{
			// BigInteger bd = new BigInteger(Long.valueOf(transferData.result * -1).toString());
			System.out.println("Fehler" + transferData.result);
		}
		else
		{
			System.out.println("Ok");
		}

		if ((stgmedium.tymed & 8) == 8)
		{
			// IStorage
			IStorage storage = new IStorage(stgmedium.unionField);
			storage.AddRef();

   // what now ?



[Updated on: Thu, 11 March 2010 14:53]

Report message to a moderator

Re: [Outlook Drop] Read bytes from an IStorage [message #520890 is a reply to message #520204] Mon, 15 March 2010 16:29 Go to previous messageGo to next message
Grant Gayed is currently offline Grant GayedFriend
Messages: 2150
Registered: July 2009
Senior Member
Hi,

Unfortunately I'm getting a different result than you in this scenario, it's
giving me an IStream instead of an IStorage (maybe it's because I'm on
Windows 2000 and have an Outlook version from that era as well?). So I
don't have a way to write code and run it to see if it actually works. Here
are some thoughts though, with code snippets copied from various places in
swt that seem to be doing something similar:

To use the approach in your last reply you'll need to recompile swt's
libraries, or create a new library of your own, because swt's libraries do
not currently contain natives for CreateILockBytesOnHGlobal or
StgCreateDocfileOnILockBytes. I'm assuming this isn't ideal, so it may be
possible to use another approach that does not require adding any new
natives. To try this, go back to the last post in thread
http://www.eclipse.org/forums/index.php?t=msg&&th=14 7516&goto=464661 , get
the rest of its content that follows "storage.AddRef();", and see how many
times its while loop happens. If it's just once, then get its STATSTG's
pwcsName, and use it to invoke IStorage.OpenStream(...) like:

int length = OS.GlobalSize(pwcsName);
int /*long*/ ptr = OS.GlobalLock(pwcsName);
char[] buffer = new char[length];
COM.MoveMemory(buffer, ptr, length);
OS.GlobalUnlock(pwcsName);
String name = new String(buffer);
int /*long*/[] address = new int /*long*/[1];
yourIStorage.OpenStream(name, 0, COM.STGM_DIRECT | COM.STGM_READ |
COM.STGM_SHARE_EXCLUSIVE, 0, address); // not sure about the access bits,
just COM.STGM_READ may be enough

If OpenStream returns COM.S_OK then address[0] should contain a pointer to
an IStream, which can then be read with something like:

IStream tempContents = new IStream(address[0]);
tempContents.AddRef();
try {
FileOutputStream writer = new FileOutputStream(file);
int increment = 1024 * 4;
int /*long*/ pv = COM.CoTaskMemAlloc(increment);
int[] pcbWritten = new int[1];
while (tempContents.Read(pv, increment, pcbWritten) == COM.S_OK &&
pcbWritten[0] > 0) {
byte[] buffer = new byte[ pcbWritten[0]];
OS.MoveMemory(buffer, pv, pcbWritten[0]);
writer.write(buffer); // Note: if file does not exist, this will
create the file the first time it is called
}
COM.CoTaskMemFree(pv);
writer.close();
} catch (IOException err) {
}
tempContents.Release();


I'd be interested to know how close this gets to being helpful ;-).

Grant


"Thomas Kratz" <eiswind@googlemail.com> wrote in message
news:hnavvc$afh$1@build.eclipse.org...
> Hi all, I am making progress with my outlook drop transfer. The trick is
to register FileContent and use the returned int as type for the transfers
FORMATETC. it then returns an IStorage and I don't know how to read the
bytes from it. It seems to be an outlook .msg file content (dont need to
parse it, just want to store the file in jackrabbit) I found a c# example
that goes like
>
>
>
> switch(medium.tymed)
> {
> case TYMED.TYMED_ISTORAGE:
> //to handle a IStorage it needs to be written into a
second unmanaged
> //memory mapped storage and then the data can be read
from memory into
> //a managed byte and returned as a MemoryStream
>
> NativeMethods.IStorage iStorage = null;
> NativeMethods.IStorage iStorage2 = null;
> NativeMethods.ILockBytes iLockBytes = null;
> System.Runtime.InteropServices.ComTypes.STATSTG
iLockBytesStat;
> try
> {
> //marshal the returned pointer to a IStorage
object
> iStorage =
(NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium. unionmember);
> Marshal.Release(medium.unionmember);
>
> //create a ILockBytes (unmanaged byte array) and
then create a IStorage using the byte array as a backing store
> iLockBytes =
NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true);
> iStorage2 =
NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0);
>
> //copy the returned IStorage into the new IStorage
> iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2);
> iLockBytes.Flush();
> iStorage2.Commit(0);
>
> //get the STATSTG of the ILockBytes to determine
how many bytes were written to it
> iLockBytesStat = new
System.Runtime.InteropServices.ComTypes.STATSTG();
> iLockBytes.Stat(out iLockBytesStat, 1);
> int iLockBytesSize = (int)iLockBytesStat.cbSize;
>
> //read the data from the ILockBytes (unmanaged
byte array) into a managed byte array
> byte[] iLockBytesContent = new
byte[iLockBytesSize];
> iLockBytes.ReadAt(0, iLockBytesContent,
iLockBytesContent.Length, null);
>
> //wrapped the managed byte array into a memory
stream and return it
> return new MemoryStream(iLockBytesContent);
> }
> finally
> {
> //release all unmanaged objects
> Marshal.ReleaseComObject(iStorage2);
> Marshal.ReleaseComObject(iLockBytes);
> Marshal.ReleaseComObject(iStorage);
> }
>
>
>
> can anyone tell me what i need to do to gte the bytes from this IStorage
>
> my code so far goes this way:
>
>
> public OutLookTransfer()
> {
> type = registerType("FileContents");
> }
>
> public Object nativeToJava(TransferData transferData)
> {
>
> IDataObject idata = new IDataObject(transferData.pIDataObject);
> idata.AddRef();
> FORMATETC formatetc = new FORMATETC();
>
> STGMEDIUM stgmedium = new STGMEDIUM();
> // stgmedium.tymed = COM.TYMED_HGLOBAL;
>
> formatetc.cfFormat = type;
> System.out.println("Format: " + formatetc.cfFormat);
> formatetc.lindex = 0;
>
> formatetc.ptd = 0;
>
> formatetc.tymed = 4 | 8 | 1;
> formatetc.dwAspect = COM.DVASPECT_CONTENT;
>
> transferData.result = getData(idata, formatetc, stgmedium);
> idata.Release();
> if (transferData.result != COM.S_OK)
> {
> // BigInteger bd = new BigInteger(Long.valueOf(transferData.result
* -1).toString());
> System.out.println("Fehler" + transferData.result);
> }
> else
> {
> System.out.println("Ok");
> }
>
> if ((stgmedium.tymed & 8) == 8)
> {
> // IStorage
> IStorage storage = new IStorage(stgmedium.unionField);
> storage.AddRef();
>
> // what now ?
>
>
>
>
Re: [Outlook Drop] Read bytes from an IStorage [message #657165 is a reply to message #520204] Tue, 01 March 2011 19:07 Go to previous message
AlexK  is currently offline AlexK Friend
Messages: 3
Registered: May 2010
Junior Member
There are many like difficulties associated with such type of problems. But to my mind one of the best solutions is the special application. Which might cope with any problem for some short time. Next tool would be helpful here - .pst repair 2002.
Previous Topic:Text widget with CTRL+F search functionality
Next Topic:Widget is Disposed error in TableView
Goto Forum:
  


Current Time: Tue Jan 19 06:57:09 GMT 2021

Powered by FUDForum. Page generated in 0.01479 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top