Getting the pointer of a Class-Caller!

Project:

Client declares an object-variable of a class defined inside a In-Process-Server (Active-X-dll).

If the project wouldn't be splitted into Client and Server i could get my Pointer without problem, because my object-variable is public for Project.

Right now i'm solving this with an byref-argument during a calling of a class-method for the first time (example: Set MyClass=AnotherObject.DoSomething(argWhatShouldYouDo, MyClass))

Now: As we should all know, all COM-Objects/Classes (and VB is COM!!) are derived fro IUnknown, which implements three invisible methods: AddRef, Release, QueryInterface.

IF i understand the msdn correctly, QueryInterface should give me an Array of pointers, which would actually be all variables i declared "as CMyClass".

Now, any ideas to get this Information from QueryInterface (Position 1 in the vtable of each COM-Object/Class) without doing some Hardcore hacks (Actually, there is a hack from Bruce McKinney i'm using to implement the "For each Next"-Feature in a Collection-Class of my on design, without using an internal Collection object (I'm using an array of variants))?

If there are no ideas, could at least somebody tell me, how an API-Like Declaration of IUnknown::QueryInterface would look like?

"Declare QueryInterface Lib blabla.dll (Arguments ByVal/ByRef.....)"

I'm especially interested, how the Arguments would look like. Right now i found out (ByVal Arg1 as GUID, Byval pointers() as variant)

In the C++-Headers:
REFIID Arg1
INT **pointers

Any Help is appreciated!

Zvoni
------------------------------------------
Only stupidity of mankind and the universe
are infinite, but i'm not sure concerning
the universe. A. Einstein

Comments

  • : Project:
    :
    : Client declares an object-variable of a class defined inside a In-Process-Server (Active-X-dll).

    I can't help but think you're going way overboard here. Or perhaps I don't understand the assignment. This requirement seems to only be saying you need two projects, one that references the other and which instantiates a class from it. Like this:

    Dim objMyObject As New MyDLL.clsMyClass

    Or am I missing something? Why on earth are you trying to hack into QueryInterface?


    [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]

    [code]
    $ select * from users where clue > 0
    no rows returned
    [/code]

  • : : Project:
    : :
    : : Client declares an object-variable of a class defined inside a In-Process-Server (Active-X-dll).
    :
    : I can't help but think you're going way overboard here. Or perhaps I don't understand the assignment. This requirement seems to only be saying you need two projects, one that references the other and which instantiates a class from it. Like this:
    :
    : Dim objMyObject As New MyDLL.clsMyClass
    :
    : Or am I missing something? Why on earth are you trying to hack into QueryInterface?
    :
    :
    : [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]
    :
    : [code]
    : $ select * from users where clue > 0
    : no rows returned
    : [/code]
    :
    :

    It's like this: You're living in a Flat in a Building (The Process). Your Neighbor living a flat above you, but in the same building, uses the method "Phone" to call you. What i want is to see the Phone-Number of the one calling me, on my phone-display, instead of not seeing, who is calling me, and the Caller "telling" me on the phone, why he is calling, including telling me his phonenumber on the phone.

    Got it now?

    The ActiveX-Dll is basically a mother-object (MultiUse) owning a Collection-Class (PublicNotCreatable), which in turn owns my Class-Objects (MultiUse again).

    Now to iterate through my Collection there are two ways: Using the Collection-Class to "movenext"
    [code]
    [green]'But since my Collection-Class is "PublicNotCreatable" i can't create it directly, so the client had to use the "inheritance"-syntax:

    Client-Code!
    [/green]
    MyMother.ColClasses.MoveNext
    [/code]

    or to use the Class-Object to "movenext" on its own!
    [code]
    [green]
    'Client-Code!
    [/green]
    MyClass.MoveNext
    [/code]
    The Result of this method is given back to my variable in the Client.


    [code]
    [green]'Client (All Classes from the dll)[/green]
    Dim MyMother as CMyMother
    Dim MyClass as CMyClass [green]'represents one item from the Collection-Class[/green]
    Set MyClass=New CMyClass

    [green]'Using now:[/green]
    Set MyClass=MyMother.OpenDoor("Collect Inhabitants",MyClass)
    [green]'OpenDoor is a "Public Function (Arg1 as String, ByRef CallingClass as CMyClass) As CMyClass" in the dll[/green]

    MyClass.MoveFirst
    MyClass.Kill
    MyClass.MoveNext
    MyClass.Kill
    .
    .
    .
    [green]'Goal[/green]
    Set MyClass=MyMother.OpenDoor("Collect Inhabitants")
    [green]'OpenDoor is a "Public Function (Arg1 as String) As CMyClass"[/green]
    MyClass.MoveFirst
    MyClass.Kill
    MyClass.MoveNext
    MyClass.Kill
    [/code]


    ActiveX-Dll:
    To get the "Self-Moving"-Feature i use the API-Function "CopyMemory" with VarPtr(CallingClass) and ObjPtr(CMyClasses.Item(Index)) in the dll
    [code]
    CopyMemory ByVal VarPtr(CallingClass), ObjPtr(CMyClasses.Item(Index)),4
    [/code]

    Now coming back to QueryInterface: If i understood the MSDN correctly, the second Argument of QueryInterface gives me an Array of Pointers of all Variables pointing to my Object! AND THAT'S EXACLTY WHAT I NEED - THE BLASTED POINTER! So i don't have to use this "Public Function (Arg1 as String, [b]ByRef CallingClass as CMyClass[/b]) As CMyClass"-Garbage.

    And MyClass has(!!) the QueryInterface-Function (Since MyClass is COM, all objects implement IUnknown), but it is hidden (vTable-Entry 1, AddRef is 2, Release is 3).

    That's my Problem i'm trying to solve!
    ------------------------------------------
    Only stupidity of mankind and the universe
    are infinite, but i'm not sure concerning
    the universe. A. Einstein

  • [b][red]This message was edited by infidel at 2006-3-23 9:1:42[/red][/b][hr]
    : It's like this: You're living in a Flat in a Building (The Process). Your Neighbor living a flat above you, but in the same building, uses the method "Phone" to call you. What i want is to see the Phone-Number of the one calling me, on my phone-display, instead of not seeing, who is calling me, and the Caller "telling" me on the phone, why he is calling, including telling me his phonenumber on the phone.
    :
    : Got it now?

    I guess so. I don't understand why, though. But whatever.

    : Now coming back to QueryInterface: If i understood the MSDN correctly, the second Argument of QueryInterface gives me an Array of Pointers of all Variables pointing to my Object! AND THAT'S EXACLTY WHAT I NEED - THE BLASTED POINTER! So i don't have to use this "Public Function (Arg1 as String, [b]ByRef CallingClass as CMyClass[/b]) As CMyClass"-Garbage.

    Well I suppose "Garbage" is all relative. It's simple, it works, it's not hideous, and it doesn't involve struggling with the bizarro world of IUnknown. Plus, what if you had multiple instances of your class? Or multiple references to a single object of that class? What good would an array of reference holders do?

    : And MyClass has(!!) the QueryInterface-Function (Since MyClass is COM, all objects implement IUnknown), but it is hidden (vTable-Entry 1, AddRef is 2, Release is 3).

    Here's what I found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/html/54d5ff80-18db-43f2-b636-f93ac053146d.asp

    [code]
    HRESULT QueryInterface(

    REFIID iid,

    void ** ppvObject

    );

    Parameters:

    iid [in] Identifier of the interface being requested.

    ppvObject [out] Address of pointer variable that receives the interface
    pointer requested in riid. Upon successful return, *ppvObject contains
    the requested interface pointer to the object. If the object does not
    support the interface specified in iid, *ppvObject is set to NULL.
    [/code]

    That doesn't sound like what you said.

    Oh, and btw, it's possible to spoof the caller-id system ;-)


    [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]

    [code]
    $ select * from users where clue > 0
    no rows returned
    [/code]







  • :
    : I guess so. I don't understand why, though. But whatever.
    :
    Because i have to replace a dll, which was called in the "Not Garbage"-Way. Care to change the complete Client-Code too?

    : : Now coming back to QueryInterface: If i understood the MSDN correctly, the second Argument of QueryInterface gives me an Array of Pointers of all Variables pointing to my Object! AND THAT'S EXACLTY WHAT I NEED - THE BLASTED POINTER! So i don't have to use this "Public Function (Arg1 as String, [b]ByRef CallingClass as CMyClass[/b]) As CMyClass"-Garbage.
    :
    : Well I suppose "Garbage" is all relative. It's simple, it works, it's not hideous, and it doesn't involve struggling with the bizarro world of IUnknown. Plus, what if you had multiple instances of your class? Or multiple references to a single object of that class? What good would an array of reference holders do?
    :

    It wouldn't matter since the "reading" of the pointer would be implemented in the Class_Initialize-Event of my class, so i would always get the "newest" pointer from the array (should be the last one inside the array).

    : : And MyClass has(!!) the QueryInterface-Function (Since MyClass is COM, all objects implement IUnknown), but it is hidden (vTable-Entry 1, AddRef is 2, Release is 3).
    :
    : Here's what I found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/html/54d5ff80-18db-43f2-b636-f93ac053146d.asp
    :
    : [code]
    : HRESULT QueryInterface(
    :
    : REFIID iid,
    :
    : void ** ppvObject
    :
    : );
    :
    : Parameters:
    :
    : iid [in] Identifier of the interface being requested.
    :
    : ppvObject [out] Address of pointer variable that receives the interface
    : pointer requested in riid. Upon successful return, *ppvObject contains
    : the requested interface pointer to the object. If the object does not
    : support the interface specified in iid, *ppvObject is set to NULL.
    : [/code]
    :

    i found that one too, and *ppvobject is the Pointer to the Array of Pointers, which i need. But even if i could hack into QueryInterface i found a new problem: REFIID in C++ is a UserType in VB (As UUID).

    Now, does [blue]Public Function Blubb ([b]ByVal Arg1 as UUID[/b], ByVal Pointers as long) as Something[/blue] ring any bells? UserTypes cannot be ByVal....grml....



    : That doesn't sound like what you said.
    :
    : Oh, and btw, it's possible to spoof the caller-id system ;-)
    :
    :
    Erm..... huh? (<-- intelligent question!) ;-)
    ------------------------------------------
    Only stupidity of mankind and the universe
    are infinite, but i'm not sure concerning
    the universe. A. Einstein

  • : It wouldn't matter since the "reading" of the pointer would be implemented in the Class_Initialize-Event of my class, so i would always get the "newest" pointer from the array (should be the last one inside the array).

    How do you know that it would be the last one?

    : : [code]
    : : HRESULT QueryInterface(
    : :
    : : REFIID iid,
    : :
    : : void ** ppvObject
    : :
    : : );
    : :
    : : Parameters:
    : :
    : : iid [in] Identifier of the interface being requested.
    : :
    : : ppvObject [out] Address of pointer variable that receives the interface
    : : pointer requested in riid. Upon successful return, *ppvObject contains
    : : the requested interface pointer to the object. If the object does not
    : : support the interface specified in iid, *ppvObject is set to NULL.
    : : [/code]
    : :
    :
    : i found that one too, and *ppvobject is the Pointer to the Array of Pointers, which i need.

    But it isn't. Read it again. *ppvObject is a pointer to the interface that you requested, unless you requested an unsupported interface, in which case it is NULL. So let's say you request the IUnknown interface for a given object. You get back a pointer to the IUnknown interface of that instance, not an array of reference holders. At least that's how I read it.

    : : Oh, and btw, it's possible to spoof the caller-id system ;-)
    : :
    : :
    : Erm..... huh? (<-- intelligent question!) ;-)

    You gave the example of someone calling you and you seeing who is calling from the phone company rather than the caller telling you. Turns out you can spoof the caller-id system, meaning it's possible to have someone's telephone display a name and number other than the one you're calling from.


    [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]

    [code]
    $ select * from users where clue > 0
    no rows returned
    [/code]

  • : : It wouldn't matter since the "reading" of the pointer would be implemented in the Class_Initialize-Event of my class, so i would always get the "newest" pointer from the array (should be the last one inside the array).
    :
    : How do you know that it would be the last one?

    I don't. Therefore i wrote SHOULD be the last.....

    :
    : : : [code]
    : : : HRESULT QueryInterface(
    : : :
    : : : REFIID iid,
    : : :
    : : : void ** ppvObject
    : : :
    : : : );
    : : :
    : : : Parameters:
    : : :
    : : : iid [in] Identifier of the interface being requested.
    : : :
    : : : ppvObject [out] Address of pointer variable that receives the interface
    : : : pointer requested in riid. Upon successful return, *ppvObject contains
    : : : the requested interface pointer to the object. If the object does not
    : : : support the interface specified in iid, *ppvObject is set to NULL.
    : : : [/code]
    : : :
    : :
    : : i found that one too, and *ppvobject is the Pointer to the Array of Pointers, which i need.
    :
    : But it isn't. Read it again. *ppvObject is a pointer to the interface that you requested, unless you requested an unsupported interface, in which case it is NULL. So let's say you request the IUnknown interface for a given object. You get back a pointer to the IUnknown interface of that instance, not an array of reference holders. At least that's how I read it.

    hmm.... you're right. I was reading the msdn yesterday still looking for my function. Blast......

    :
    : : : Oh, and btw, it's possible to spoof the caller-id system ;-)
    : : :
    : : :
    : : Erm..... huh? (<-- intelligent question!) ;-)
    :
    : You gave the example of someone calling you and you seeing who is calling from the phone company rather than the caller telling you. Turns out you can spoof the caller-id system, meaning it's possible to have someone's telephone display a name and number other than the one you're calling from.

    Ah, yes. God bless me, that i don't give out my phone number like other people their business cards......

    Zvoni
    :
    :
    : [size=5][italic][blue][RED]i[/RED]nfidel[/blue][/italic][/size]
    :
    : [code]
    : $ select * from users where clue > 0
    : no rows returned
    : [/code]
    :
    :

    ------------------------------------------
    Only stupidity of mankind and the universe
    are infinite, but i'm not sure concerning
    the universe. A. Einstein

  • I found out what the Problem was!

    I'm coding an activeX-DLL, and there is no "SingleUse"-Instancing for Classes as in an activeX-EXE.

    I solved it with an internal array for the values of my Objects, instead of an array of the complete Objects, since i only need the values, but i need the methods and events only once.

    For those who haven't understood one word now: I'm simulating a "SingleUse"-Instancing of a "MultiUse"-Class in an ActiveX-DLL.

    Problem solved, no need for VarPtr, ObjPtr and CopyMemory.

    Zvoni

    P.S.: And yes, "For Each" still works..... *evilgrin*
    ------------------------------------------
    Only stupidity of mankind and the universe
    are infinite, but i'm not sure concerning
    the universe. A. Einstein

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories