Pointer to a Pointer in VB

  • Thread starter Thread starter Dave
  • Start date Start date
D

Dave

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 ** Object //Pointer to an interface pointer


Object
[out] Pointer to an interface pointer variable that receives a pointer for
an interface.


Has anyone solved this for the VB language?

Dave
 
Dave,
Have you tried asking this "down the hall" in the
microsoft.public.dotnet.framework.interop newsgroup?

Unfortunately I suspect most regulars in this newsgroup do not do enough
interop to offer much assistance.

If you don't have it Adam Nathan's book ".NET and COM - The Complete
Interoperability Guide" from SAMS Press, provides you will every thing you
ever wanted to know about Interop and then some.

Hope this helps
Jay
 
Jay

Yes. I crossposted it in the Interop group as well as here. No luck there as
yet.

I'm not sure if using API's is in the Interop domain as its not COM related.

Thanks for your interest anyway.

Dave
 
have you tried to use IntPtr yet?

| 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 ** Object //Pointer to an interface pointer
|
|
| Object
| [out] Pointer to an interface pointer variable that receives a pointer for
| an interface.
|
|
| Has anyone solved this for the VB language?
|
| Dave
|
|
 
Dave,
I'm not sure if using API's is in the Interop domain as its not COM
related.
This reminds me of the story of three blind men describing what an Elephant
is. ;-)

Is COM a subset of Interop or is Interop a subset of COM?

I consider APIs & COM to be two aspects of Interop. As both are
interoperating between managed code and unmanaged code.

Making API's well within the domain of Interop.

Just a thought
Jay
 
I've looked at IntPtr but I don't make a connection between it and my
problem.

I can make VariableX point to an object. The problem is how do I then define
VariableY which points to VariableX? If I do a VariableY = Variable X I get
both variables pointing to the same object.

Or am I missing something here?

Dave
 
I understand Interop as providing a Net application with the ability to
interface with a component buried in a Control or an In-process or
out-of-process server (ocx, dll, exe). That is a COM based component.

The problem I'm having is within the API domain. Which is an interface
buried within an old MS-DOS style dynamic link library.

By the way the API function I'm having difficulty with is the
StgCreateStorageEx which lives in the Ole32.dll.

Dave
 
What does the pointer that the pointer points to, point to? A structure?

--
HTH,
-- Tom Spink, Über Geek

Please respond to the newsgroup,
so all can benefit

" System.Reflection Master "

==== Converting to 2002 ====
Remove inline declarations
 
Hi Tom

The API function I'm trying to use is StgCreateStorageEx which is in the
Ole32.dll.

MSDN defines athe argument as...

ppObjectOpen
[out] Pointer to an interface pointer variable that receives a pointer for
an interface on the new storage object; contains NULL if operation failed.

I can easily make this API function work in VB6 without any voodoo. The
function returns a STG_E_INVALIDPOINTER error (&H30030009) in VB7.
But even if it did work I can't figure out how I'd access the returned
IStorage interface.

I've found a couple of people having the same problem in VB with this set of
API functions (those defining double indirection). They didn't get the
answer either it seems.

Dave
 
i know exactly what you want to do. i'd like to know what you find out but i
doubt i'm going to get an answer for you.

i was elated by how much more c/c++ vb.net has become...they just missed my
beloved ol' friends:

expr ? true : false ' not the same as iif()
&variable
*variable

deeper variable interaction solves the problem pretty easily.

y = &variable = same as y = x in vb, as you explain
y = *variable = solution!

let us know what you find out.

steve


| I've looked at IntPtr but I don't make a connection between it and my
| problem.
|
| I can make VariableX point to an object. The problem is how do I then
define
| VariableY which points to VariableX? If I do a VariableY = Variable X I
get
| both variables pointing to the same object.
|
| Or am I missing something here?
|
| Dave
|
|
| | > have you tried to use IntPtr yet?
| >
|
|
 
Dave,
Read Adam Nathan's book, he explains what you need to do to get the "pointer
to interface pointer variable" magic to work. Plus he gives you the
definition for StgCreateStorageEx!

Note this is COM, as you have a pointer to an interface pointer, the
interface pointer is a COM interface!

Basically ppObjectOpen is ByRef Object, with a
MarshalAs(UnmanagedType.IUnknown) Attribute.

Something to the effect, you will need to double check syntax:

Declare Sub StgCreateStorageEx(... <MarshalAs(UnmanagedType.IUnknown)>
ByRef ppObjectOpen As Object)

However to actually use the interface returned in ppObjectOpen, you will
need to define the IStorage interface.

Once you have the IStorage interface defined, you define a variable of type
IStorage and use it.

After you get StgCreateStorageEx, defining the IStorage interface is the
tricky part.

Hope this helps
Jay

Dave said:
Hi Tom

The API function I'm trying to use is StgCreateStorageEx which is in the
Ole32.dll.

MSDN defines athe argument as...

ppObjectOpen
[out] Pointer to an interface pointer variable that receives a pointer for
an interface on the new storage object; contains NULL if operation failed.

I can easily make this API function work in VB6 without any voodoo. The
function returns a STG_E_INVALIDPOINTER error (&H30030009) in VB7.
But even if it did work I can't figure out how I'd access the returned
IStorage interface.

I've found a couple of people having the same problem in VB with this set of
API functions (those defining double indirection). They didn't get the
answer either it seems.

Dave


Tom Spink said:
What does the pointer that the pointer points to, point to? A structure?

--
HTH,
-- Tom Spink, Über Geek

Please respond to the newsgroup,
so all can benefit

" System.Reflection Master "

==== Converting to 2002 ====
Remove inline declarations
 
Hi again Jay.

Ok Here are some snippets from my code.

First the definition of the interface IStorage:
________________________________________________________________

<Guid("0000000B-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComConversionLoss()> _
Public Interface IStorage
Function Commit(ByVal grfCommitFlags As STGC) As Integer
Function CopyTo(ByVal ciidExclude As Integer, ByVal rgiidExclude As
LPGUID, ByVal snbExclude As IntPtr, ByVal pstgDest As IStorage) As Integer
Function CreateStorage(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As
String, ByVal grfMode As STGM, ByVal reserved1 As Integer, ByVal reserved2
As Integer, ByRef ppstg As IStorage) As Integer
Function CreateStream(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As
String, ByVal grfMode As STGM, ByVal reserved1 As Integer, ByVal reserved2
As Integer, ByRef ppstm As IStream) As Integer
Function DestroyElement(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName
As String) As Integer
Function EnumElements(ByVal reserved1 As Integer, ByVal reserved2 As
IntPtr, ByVal reserved3 As Integer, ByRef ppenum As IEnumSTATSTG) As Integer
Function MoveElementTo(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As
String, ByVal pstgDest As IStorage, <MarshalAs(UnmanagedType.LPWStr)> ByVal
pwcsNewName As String, ByVal grfFlags As STGMOVE) As Integer
Function OpenStorage(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As
String, ByVal pstgPriority As IntPtr, ByVal grfMode As STGM, ByVal
snbExclude As IntPtr, ByVal reserved As Integer, ByRef ppstg As IStorage) As
Integer
Function OpenStream(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As
String, ByVal reserved1 As IntPtr, ByVal grfMode As STGM, ByVal reserved2 As
Integer, ByRef ppstm As IStream) As Integer
Function RenameElement(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsOldName
As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsNewName As String) As
Integer
Function Revert() As Integer
Function SetClass(ByVal clsid As LPGUID) As Integer
Function SetElementTimes(<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName
As String, ByVal pctime As FILETIME, ByVal patime As FILETIME, ByVal pmtime
As FILETIME) As Integer
Function SetStateBits(ByVal grfStateBits As Integer, ByVal grfMask As
Integer) As Integer
Function Stat(ByRef pstatstg As STATSTG, ByVal grfStatFlag As STATFLAG) As
Integer
End Interface
_______________________________________________________________________


Next, the declaration of the StgCreateStorageEx
________________________________________________________________________

Declare Function StgCreateStorageEx Lib "ole32.dll" ( _
<MarshalAs(UnmanagedType.LPWStr)> ByRef pwcsName As String, _
ByVal grfMode As Int32, _
ByVal stgfmt As Int32, _
ByVal grfAttrs As Int32, _
<MarshalAs(UnmanagedType.Struct)> ByRef pStgOptions As STGOPTIONS, _
ByVal reserved As Int32, _
ByVal riid As Guid, _
ByRef ppObjectOpen As Object) As Integer
_______________________________________________________________________

Finaly, the call itself
_______________________________________________________________________

Dim objIStorage As IStorage()
Dim R As Integer


R = StgCreateStorageEx(PATH, _
STGM.STGM_READWRITE Or STGM.STGM_SHARE_EXCLUSIVE, _
STGFMT.STGFMT_ANY, _
0, _
StgOptions, _
0, _
IID_Storage, _
objIStorage)
________________________________________________________________________

The call goes through but the function returns a STG_E_INVALIDPOINTER error
value.

FYI: As I mentioned, I crossposted this in the Interop bucket. So far I've
gotten ziltch from that group. But then again they don't get out of bed
until 4:00 PM. Just kidding.

Thanks again for your interest.

Dave
 
For the record I redefined the StgCreateStorage to read as suggested (see
last line).

Same result.


Declare Function StgCreateStorageEx Lib "ole32.dll" ( _
<MarshalAs(UnmanagedType.LPWStr)> ByRef pwcsName As String, _
ByVal grfMode As Int32, _
ByVal stgfmt As Int32, _
ByVal grfAttrs As Int32, _
<MarshalAs(UnmanagedType.Struct)> ByRef pStgOptions As STGOPTIONS, _
ByVal reserved As Int32, _
ByVal riid As Guid, _
<MarshalAs(UnmanagedType.IUnknown)> ByRef ppObjectOpen As Object) As
Integer
 
Dave,
FYI: As I mentioned, I crossposted this in the Interop bucket. So far I've
gotten ziltch from that group. But then again they don't get out of bed
until 4:00 PM. Just kidding.
Remember it is the weekend for the bulk of the world, you will probably get
more help on Monday when most developers are on.

When defining a preexisting interface, it is best to include the ComImport
attribute otherwise the framework may replace the existing interface handler
with its interface handler. (Nathan's book explains it better).

If your are manually defining the IStorage interface, I'm not sure why you
would include the ComConversionLoss attribute.

Its best to include the PreserveSig attribute on the interfaces functions.

How do you have STGOPTIONS defined.

Your StdCreateStorageEx declaration has a number of issues. You are sending
ByRef when you should not, and sending ByVal when you should not. Which
concerns me that you may have issues with the interface itself. For example
IStream is already defined by System.Runtime.InteropServices.UCOMIStream,
which you should reference instead of defining it yourself...

untested:
Declare Auto Function StgCreateStorageEx Lib "ole32.dll" ( _
<MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As String, _
ByVal grfMode As Int32, _
ByVal stgfmt As Int32, _
ByVal grfAttrs As Int32, _
<MarshalAs(UnmanagedType.Struct)> ByRef pStgOptions As STGOPTIONS, _
ByVal reserved As IntPtr, _
ByRef riid As Guid, _
<MarshalAs(UnmanagedType.IUnknown)> ByRef ppObjectOpen As Object) As
Integer

Hope this helps
Jay
 
Jay

I tried your version of the function definition. No change I'm afraid.

You suggest that I should be referencing
System.Runtime.InteropServices.UCOMIStream. That would be fine except the
UCOM portion does not exist in my Net Framework (V1.0). That is one of the
reasons I'm defining the IStorage interface myself. From various discussions
I've spotted on the web it seems that I'm not the only person that doesn't
have UCOM.

I'm coming to the conclusion that VB.Net is not the vehicle for quick
development that it was in VB6. It seems to me that its just an exercise in
frustration and an imprediment to getting things done. I would migrate my
working VB6 dll to VB.Net but it depends on a number of old unsupported VB6
function (ie: VarPtr) and won't migrate. Perhaps I'll just reference my old,
working VB6 dll, from Net.

Thanks for your efforts once again.

Dave
 
Dave,
I tried your version of the function definition. No change I'm afraid.
Well there are obviously other problems with it that I did not identify. I
am not even close the level of the experts in the interop newsgroup.
You suggest that I should be referencing
System.Runtime.InteropServices.UCOMIStream. That would be fine except the
UCOM portion does not exist in my Net Framework (V1.0).
What gives you that idea?????

It is in mscorlib V1.0.3705, so it better be part of your copy of .NET
Framework V1.0!

I'm coming to the conclusion that VB.Net is not the vehicle for quick
development that it was in VB6. It seems to me that its just an exercise in
frustration and an imprediment to getting things done. I would migrate my
working VB6 dll to VB.Net but it depends on a number of old unsupported VB6
function (ie: VarPtr) and won't migrate. Perhaps I'll just reference my old,
working VB6 dll, from Net.
The way I see it, VB.NET is for quick .NET development, .NET is all about
OOP development. If you want or need to use a lot of legacy COM interfaces
or Win32 calls, then you may want to stay with VB6 as VB6 is for quick COM
development.

Hope this helps
Jay
 
Back
Top