473,386 Members | 1,803 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

IStorage::CopyTo throws Invalid Pointer exception

I'm currently working on a project in C# (VS 2003 SP1, .Net 1.1) that
utilizes IStream/IStorage COM-Elements.
Up to now I have gotten everything to work to my satisfaction, but now
I have come across a problem I can't really explain:
When deleting an object from an IStorage, the space it used up will not
be freed, but rather marked as unused and overwritten the next time you
add an object to the storage.
This is obviously working as intended (according to the MSDN) and there
is no simple way to change this behavior.
Since my compound files can contain quite large amounts of data, this
seemed somewhat wasteful (especially given the fact that these files
will probably be sent through Email or uploaded to FTP sites), so I
intended to write a simple function that takes the contents of one
file, copies it to a temporary file, deletes the old and copies the old
contents back to the new file. According to the information I found
about this subject this should free the unused space.
Unfortunately all information I found on the topic was geared towards
C++, wrapping it in C# seems to make things a little more interesting
(as it does for most COM-Interfaces, in my experience).
I create a temporary IStorage using CreateDocFile pass it to the CopyTo
function, along with the parameters that closest resemble the ones I
saw in the C++ examples (0, Guid.Empty, (IntPtr)null), this results in
a COMException saying that an error occured due to an invalid pointer.
According to the MSDN this should only be caused when the pointer to
the IStorage is invalid, but the IStorage-object I pass is definately
functional (I tried adding substorages, streams etc.).
Here are some code snippets from my project that may be relevant:

The lines that actually cause the error:
---------------------------------------------------------------------------------------------------------------------------------------
string TempFile = System.IO.Path.GetTempFileName();
System.IO.File.Delete(TempFile);
APIImports.IStorage TempStorage =
APIImports.CreateStorage(TempFile,m_Read,m_Write);
Document.CopyTo(0,Guid.Empty,(IntPtr)null,TempStor age);
---------------------------------------------------------------------------------------------------------------------------------------

The CreateStorage-function:
---------------------------------------------------------------------------------------------------------------------------------------
IStorage RetVal = null;
uint STGM_Flags = 0;
int ErrCode = -1;
if (Read && !Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_READ;
else if (!Read && Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_WRITE;
else if (Read && Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_READWRITE;
else
return null;
STGM_Flags = STGM_Flags | STGM_SHARE_EXCLUSIVE;
ErrCode = StgCreateDocfile(Path,STGM_Flags,0,out RetVal);
if (ErrCode == 0)
return RetVal;
else
{
Marshal.ThrowExceptionForHR(ErrCode);
return null;
}
---------------------------------------------------------------------------------------------------------------------------------------

My definition for IStorage::CopyTo
---------------------------------------------------------------------------------------------------------------------------------------
void CopyTo(
uint ciidExclude,
Guid rgiidExclude,
IntPtr snbExclude,
IStorage pstgDest);
---------------------------------------------------------------------------------------------------------------------------------------

Any comments would be appreciated.

Sincerely,
Kevin Wienhold

Nov 6 '06 #1
6 2986
This error(STG_E_INVALIDPOINTER) usually occurs when the interface(IStorage)
or interface method(s) are not prototyped correctly in C#.
My definition for IStorage::CopyTo
---------------------------------------------------------------------------------------------------------------------------------------
void CopyTo(
uint ciidExclude,
Guid rgiidExclude,
IntPtr snbExclude,
IStorage pstgDest);
The docs state that snbExclude is an array of OLESTR which in c# would be
string[] snbExclude.

Since this parameter may be null, you may try IntPtr[] snbExclude and
passing IntPtr.Zero as the value of the first element of an array of IntPtr.
"KWienhold" <he******@trashmail.netwrote in message
news:11**********************@i42g2000cwa.googlegr oups.com...
I'm currently working on a project in C# (VS 2003 SP1, .Net 1.1) that
utilizes IStream/IStorage COM-Elements.
Up to now I have gotten everything to work to my satisfaction, but now
I have come across a problem I can't really explain:
When deleting an object from an IStorage, the space it used up will not
be freed, but rather marked as unused and overwritten the next time you
add an object to the storage.
This is obviously working as intended (according to the MSDN) and there
is no simple way to change this behavior.
Since my compound files can contain quite large amounts of data, this
seemed somewhat wasteful (especially given the fact that these files
will probably be sent through Email or uploaded to FTP sites), so I
intended to write a simple function that takes the contents of one
file, copies it to a temporary file, deletes the old and copies the old
contents back to the new file. According to the information I found
about this subject this should free the unused space.
Unfortunately all information I found on the topic was geared towards
C++, wrapping it in C# seems to make things a little more interesting
(as it does for most COM-Interfaces, in my experience).
I create a temporary IStorage using CreateDocFile pass it to the CopyTo
function, along with the parameters that closest resemble the ones I
saw in the C++ examples (0, Guid.Empty, (IntPtr)null), this results in
a COMException saying that an error occured due to an invalid pointer.
According to the MSDN this should only be caused when the pointer to
the IStorage is invalid, but the IStorage-object I pass is definately
functional (I tried adding substorages, streams etc.).
Here are some code snippets from my project that may be relevant:

The lines that actually cause the error:
---------------------------------------------------------------------------------------------------------------------------------------
string TempFile = System.IO.Path.GetTempFileName();
System.IO.File.Delete(TempFile);
APIImports.IStorage TempStorage =
APIImports.CreateStorage(TempFile,m_Read,m_Write);
Document.CopyTo(0,Guid.Empty,(IntPtr)null,TempStor age);
---------------------------------------------------------------------------------------------------------------------------------------

The CreateStorage-function:
---------------------------------------------------------------------------------------------------------------------------------------
IStorage RetVal = null;
uint STGM_Flags = 0;
int ErrCode = -1;
if (Read && !Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_READ;
else if (!Read && Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_WRITE;
else if (Read && Write)
STGM_Flags = STGM_Flags | STGM_ACCESS_READWRITE;
else
return null;
STGM_Flags = STGM_Flags | STGM_SHARE_EXCLUSIVE;
ErrCode = StgCreateDocfile(Path,STGM_Flags,0,out RetVal);
if (ErrCode == 0)
return RetVal;
else
{
Marshal.ThrowExceptionForHR(ErrCode);
return null;
}
---------------------------------------------------------------------------------------------------------------------------------------

My definition for IStorage::CopyTo
---------------------------------------------------------------------------------------------------------------------------------------
void CopyTo(
uint ciidExclude,
Guid rgiidExclude,
IntPtr snbExclude,
IStorage pstgDest);
---------------------------------------------------------------------------------------------------------------------------------------

Any comments would be appreciated.

Sincerely,
Kevin Wienhold

Nov 6 '06 #2
Thank you for your reply.
This error(STG_E_INVALIDPOINTER) usually occurs when the interface(IStorage)
or interface method(s) are not prototyped correctly in C#.
That's what I figured, but there don't seem to be too many IStorage
Interface definitions around for C#, most examples seem to use the one
from pInvoke.net (which is where I got mine from).
The docs state that snbExclude is an array of OLESTR which in c# would be
string[] snbExclude.

Since this parameter may be null, you may try IntPtr[] snbExclude and
passing IntPtr.Zero as the value of the first element of an array of IntPtr.
When passing an IntPtr-Array the call will fail, saying that the
parameter was not of the expected type.
I tried changing it to a string-array, its first element set to null,
but this will throw the same invalid pointer exception as before.
In addition I noticed that calling SetClass on my IStorage objects will
fail with that error as well.

Nov 7 '06 #3
Here is the layout that I use:

[ComImport,ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown )]
[Guid("0000000b-0000-0000-C000-000000000046")]
public interface IStorage
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out UCOMIStream ppstm);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] IntPtr reserved1,
[In] int grfMode,
[In] int reserved2,
[Out] out UCOMIStream ppstm);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out IStorage ppstg);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgPriority,
[In] uint grfMode,
[In] string[] snbExclude,
[In] uint reserved,
[Out] out IStorage ppstg);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CopyTo(
[In] uint ciidExclude,
[In] Guid rgiidExclude,
[In] string[] snbExclude,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint MoveElementTo(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName,
[In] int grfFlags);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Commit(
[In] int grfCommitFlags);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Revert();

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint enumElements(
[In] int reserved1,
[In] IntPtr reserved2,
[In] int reserved3,
[Out] out IenumFORMATETC ppenum);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint DestroyElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint RenameElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetElementTimes(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] ref FILETIME pctime,
[In] ref FILETIME patime,
[In] ref FILETIME pmtime);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetClass(
[In] ref Guid clsid);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetStateBits(
[In] uint grfStateBits,
[In] uint grfMask);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Stat(
[Out] out STATSTG pstatstg,
[In] uint grfStatFlag);
}

I have not tried to use CopyTo or SetClass. I know that if the vtable is
not layed out correctly, you will get com errors that don't make any sense
given the fact that parameters are passed correctly.

Have you tried to pass a valid string for a snb to exclude just to test if
the function succeeds? Perhaps the error has nothing to do with the layout
of the method but with the IStorage object itself that you are passing an
Interface pointer to CopyTo.
"KWienhold" <he******@trashmail.netwrote in message
news:11**********************@e3g2000cwe.googlegro ups.com...
Thank you for your reply.
>This error(STG_E_INVALIDPOINTER) usually occurs when the
interface(IStorage)
or interface method(s) are not prototyped correctly in C#.

That's what I figured, but there don't seem to be too many IStorage
Interface definitions around for C#, most examples seem to use the one
from pInvoke.net (which is where I got mine from).
>The docs state that snbExclude is an array of OLESTR which in c# would be
string[] snbExclude.

Since this parameter may be null, you may try IntPtr[] snbExclude and
passing IntPtr.Zero as the value of the first element of an array of
IntPtr.

When passing an IntPtr-Array the call will fail, saying that the
parameter was not of the expected type.
I tried changing it to a string-array, its first element set to null,
but this will throw the same invalid pointer exception as before.
In addition I noticed that calling SetClass on my IStorage objects will
fail with that error as well.

Nov 7 '06 #4
Thank you again for your reply, I really appreciate it.
After adding the [PreserveSig] directives to my definition both
functions now execute without error, unfortunately the compound file I
copy the data into is empty afterwards...
I tried changing the parameters around again (IntPtr, string, string[],
object etc.) and passed different values (valid and null ones) to no
avail.
Could you possibly try using CopyTo with your implementation? I'm
afraid something fundamental is wrong with my IStorage definition, but
I have no clue what it could be.

Sincerely,
Kevin Wienhold

Michael Phillips, Jr. schrieb:
Here is the layout that I use:

[ComImport,ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown )]
[Guid("0000000b-0000-0000-C000-000000000046")]
public interface IStorage
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out UCOMIStream ppstm);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStream(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] IntPtr reserved1,
[In] int grfMode,
[In] int reserved2,
[Out] out UCOMIStream ppstm);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CreateStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] int grfMode,
[In] int reserved1,
[In] int reserved2,
[Out] out IStorage ppstg);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint OpenStorage(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgPriority,
[In] uint grfMode,
[In] string[] snbExclude,
[In] uint reserved,
[Out] out IStorage ppstg);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint CopyTo(
[In] uint ciidExclude,
[In] Guid rgiidExclude,
[In] string[] snbExclude,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint MoveElementTo(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In, MarshalAs(UnmanagedType.Interface)] IStorage pstgDest,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName,
[In] int grfFlags);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Commit(
[In] int grfCommitFlags);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Revert();

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint enumElements(
[In] int reserved1,
[In] IntPtr reserved2,
[In] int reserved3,
[Out] out IenumFORMATETC ppenum);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint DestroyElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint RenameElement(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsOldName,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsNewName);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetElementTimes(
[In, MarshalAs(UnmanagedType.LPWStr)] string pwcsName,
[In] ref FILETIME pctime,
[In] ref FILETIME patime,
[In] ref FILETIME pmtime);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetClass(
[In] ref Guid clsid);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint SetStateBits(
[In] uint grfStateBits,
[In] uint grfMask);

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
uint Stat(
[Out] out STATSTG pstatstg,
[In] uint grfStatFlag);
}

I have not tried to use CopyTo or SetClass. I know that if the vtable is
not layed out correctly, you will get com errors that don't make any sense
given the fact that parameters are passed correctly.

Have you tried to pass a valid string for a snb to exclude just to test if
the function succeeds? Perhaps the error has nothing to do with the layout
of the method but with the IStorage object itself that you are passing an
Interface pointer to CopyTo.
"KWienhold" <he******@trashmail.netwrote in message
news:11**********************@e3g2000cwe.googlegro ups.com...
Thank you for your reply.
This error(STG_E_INVALIDPOINTER) usually occurs when the
interface(IStorage)
or interface method(s) are not prototyped correctly in C#.
That's what I figured, but there don't seem to be too many IStorage
Interface definitions around for C#, most examples seem to use the one
from pInvoke.net (which is where I got mine from).
The docs state that snbExclude is an array of OLESTR which in c# would be
string[] snbExclude.

Since this parameter may be null, you may try IntPtr[] snbExclude and
passing IntPtr.Zero as the value of the first element of an array of
IntPtr.
When passing an IntPtr-Array the call will fail, saying that the
parameter was not of the expected type.
I tried changing it to a string-array, its first element set to null,
but this will throw the same invalid pointer exception as before.
In addition I noticed that calling SetClass on my IStorage objects will
fail with that error as well.
Nov 8 '06 #5
It seems I finally got it to work, yay ;)
I replaced my IStorage definition with yours and changed the second
parameter from your CopyTo from Guid to Guid[].
If you pass null as the second parameter now everything gets copied to
the new file, as it should be. I guess Guid.Empty screwed up the
function as it was expecting an array of Interface IDs.
Again, thank you very much for your help, I don't think I would have
thought of PreserveSig to fix the error in the first place.

Sincerely,
Kevin Wienhold

Nov 8 '06 #6
I am happy everything worked out. I thank you for alerting me that
parameter 2 was not correct. I misread the typing for that parameter.
"KWienhold" <he******@trashmail.netwrote in message
news:11**********************@k70g2000cwa.googlegr oups.com...
It seems I finally got it to work, yay ;)
I replaced my IStorage definition with yours and changed the second
parameter from your CopyTo from Guid to Guid[].
If you pass null as the second parameter now everything gets copied to
the new file, as it should be. I guess Guid.Empty screwed up the
function as it was expecting an array of Interface IDs.
Again, thank you very much for your help, I don't think I would have
thought of PreserveSig to fix the error in the first place.

Sincerely,
Kevin Wienhold

Nov 8 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Darren Mann | last post by:
Hello, I've written a wrapper for IStorage and I know the majority of the code is working fine. The only issue is with EnumElements. When its called the function itself throws a COM Exception...
0
by: Egbert Nierop \(MVP for IIS\) | last post by:
Thanks for your time. In a --specific-- situation, I need a member variable to be unmanaged and I do not want to create a __gc __interface version because **thats** why I use managed Visual C++...
16
by: Dave | last post by:
I'm having a problem trying to set up code in VB to handle the case where an argument in an API definition is defined as a pointer to a pointer. An excerpt from the API's definition is: void...
10
by: Dave | last post by:
Has anyone out there managed to create a structured storage file using pure VB.Net? Specifically; with the API function StgCreateStorageEx? If so, could you post a working example here please. One...
2
by: eric.houghland | last post by:
Hello, I've read quite a bit about implementing this interface in .NET and believe I have a good start. I am able to use StgIsStorageFile, StgCreateStorage and StgOpenStorage. I am now...
2
by: Steven Nagy | last post by:
Hi all, I need to be able to take messages that have been saved from Outlook (*.msg) and read them into a C# application (think of it as workflow management). But these msg files are pretty...
7
by: Russell Mangel | last post by:
/* Hi, I am trying to hold a reference to un-managed pointer IStorage. The client/callers will make many accesses to IStorage, but only in-directly. For performance reasons IStorage needs to...
4
by: Ralf | last post by:
Hallo, I'm trying to call a COM function from C#. The function has a parameter from the type array of IStream* (IStream**). The COM component (out-proc-server (.exe)) has the following code: ...
4
by: bhumesh | last post by:
Hello, I am using the Marshalling of StgOpenStorage in my program. It is giving me the error Error as: The type or namespace name 'IStorage' could not be found (are you missing a using directive or...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.