Solved

COM object - Invalid Pointer Error

Posted on 2003-11-05
18
1,143 Views
Last Modified: 2007-12-19
I am trying to create an instance of a mainframe emulator. I was previously successful, but managed to get something fouled up so that it stopped working. I downloaded code from the creators of the product, mimicked some of their code, and was ready to go. I continued to mess around with the code, until now both my code and the downloaded code do not work.

Here's a snipit of my code:

...

HRESULT hr;

hr = CoInitialize(NULL);
char SessionName[133];
strcpy(SessionName, "NAME"); // ("NAME" was working before. The details aren't important.

try
{
     hr = system.CreateInstance("Extra.System", NULL);
     sessions = system->Sessions;
     session = sessions->Open(SessionName);
     screen = session->Screen; // ERROR THROWN HERE
     ...
} catch {
     ...
}

That alone throws a _com_error of Invalid Pointer.

Again, I mention that this code was working about 3 hours ago, and just suddenly quit. Is this a problem with some sort of CoInitialize thing? After hr=system.Create, hr is "0." I was expecting it to be "1."

I have a feeling that the problem is not with the code, but with my system.

I appreciate any assistance.

0
Comment
Question by:ewmontgo
  • 10
  • 8
18 Comments
 
LVL 19

Expert Comment

by:Dexstar
ID: 9690177
ewmontgo:

> Again, I mention that this code was working about 3 hours ago, and just suddenly
> quit.

Are you saying that even the original, unmodified code has stopped working?  Otherwise, I would re-download the sample and see what got changed.  :)

> Is this a problem with some sort of CoInitialize thing? After
> hr=system.Create, hr is "0." I was expecting it to be "1."

No, 0 indicates success.

>      sessions = system->Sessions;
>      session = sessions->Open(SessionName);
>
> That alone throws a _com_error of Invalid Pointer.

What are the datatypes for those variables?

>      screen = session->Screen; // ERROR THROWN HERE

That line bothers me.  It seems like it should be session->Screen(); or session->get_Screen(); or something like that.

Hope that helps,
Dex*
0
 

Author Comment

by:ewmontgo
ID: 9693671
Yes, the original code I downloaded stopped working, exactly the same as my code stopped working.

I'm glad that a 0 indicates success.

The datatypes are specific to namespace Extra, but here are the declarations:
#import "C:\\Extra\\extra.tlb" named_guids
EXTRA::_SystemPtr system;
EXTRA::SessionsPtr sessions;
EXTRA::_SessionPtr session;
EXTRA::ScreenPtr screen;
char SessionName[100];
strcpy(SessionName, "MAINFRAME.EDP");

The screen = session->Screen line has been bothering me, too. It doesn't appear on intellisense, and I can't find it in the header file. But it worked (before it up and quit).

I've since re-downloaded the code and tried it again. It still fails. And I double-checked that the original code remained unchanged, and it had.

I think I may have located a potential source of the problem (knowing about HRESULT and 1 or 0): hr = CoInitialize(NULL) is coming up 0.
0
 

Author Comment

by:ewmontgo
ID: 9693678
I mean, hr = CoInitialize(NULL) is coming up 1.
0
 

Author Comment

by:ewmontgo
ID: 9693704
Okay, I've added if(FAILED(hr)) and if(SUCCEEDED(hr)) to both the CoInitialize and CreateInstance portions of the code. Both are succeeding.

The error is occurring at
session = sessions->Open(SessionName);
This is returning a NULL pointer. I don't know why.

Could this be a registry problem?
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9695489
Actually, the most significant bit of an HRESULT is used to determine success or failure.  So, 1 still means success, but it means S_FALSE.  That usually means CoInitialize has already been called, but it is okay to call it again.

You need to check the prototype of those functions.  Something about these 2 are not right:

     sessions = system->Sessions;
...
     screen = session->Screen; // ERROR THROWN HERE

The reason you couldn't find them in the header files is because of the #import directive.  When you use that, you need to look for the files .tli and .tlh that are created  (.tlh is the header).  Open up those files, and you'll see the function prototypes.  Maybe that will point you in the right direction.

If you can't figure it out, then post the prototypes here and I'll take a shot.

Dex*
0
 

Author Comment

by:ewmontgo
ID: 9695630
I've stepped through and into the code on those lines. It does indeed step into a .tli file, as advertised. I've also changed those two lines to the following:

sessions = system->GetSessions();
screen = session->GetScreen();

This did not lead to success. The problem is still that the line
session = sessions->Open(SessionName);
is returning a null pointer, which then causes the next line
screen = session->Screen; (or screen = session->GetScreen();)
to crash.

I've also stepped through the Open function, but I don't understand all of the functions that it's passing through (and it passes through a lot). They're inline functions (which I understand doesn't really matter). I'd be happy to post those, but I'm not sure if that would help?
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9695773
Try this:

Change this line:
     session = sessions->Open(SessionName);

To this:
     HRESULT hr = sessions->raw_Open( SessionName, &session );

(I don't have the prototype for that function, so that call may not be 100% ... But search the .tlh for that function to get the exact prototype)

Then you can check the HRESULT value to see if that function succeeds or fails, and if fails, then you can find out why.

Then change this:
     screen = session->GetScreen();

To This:
    hr = session->get_Screen( &screen );

or it may be:
    hr = session->raw_GetScreen( &screen );

(Depending on how the Interface was defined).

Try that and let me know what compiler errors or HRESULTs you get.

Dex*

     
0
 

Author Comment

by:ewmontgo
ID: 9695854
Here's the raw_Open function:
virtual HRESULT __stdcall raw_Open (
        VARIANT Name,
        IDispatch * * retval ) = 0;

[I don't know what a VARIANT is, but I tried to create one:
tagVARIANT v;
v.??? = SessName;]

And there is not a get_Screen, get_screen, Get_Screen, Get_screen, raw_GetScreen, etc function available.

0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9695911
Try this:

     HRESULT hr = sessions->raw_Open( CComVariant(SessionName), &screen );

What hr value do you get for that?
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:ewmontgo
ID: 9695993
(I changed it from &screen to &session).

I get a compiler error:
cannot convert parameter 2 from 'struct EXTRA::_Session ** ' to 'struct IDispatch ** '

If I cast as:
 (struct IDispatch **)&session
It compiles, and I get hr returned as 0, which passes the following if(FAILED(hr)), but session is still 0x00000000.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9696369
Yeah, I meant &session.  Okay, try this then:

struct EXTRA::_Session* pSession = NULL;
HRESULT hr = sessions->raw_Open( CComVariant(SessionName), &pSession );
if ( SUCCEEDED(hr) )
{
     session = EXTRA::_SessionPtr(pSession, false);
     // false will attach the Interface to the smart pointer, so there is no need to clean up
}

Try that.
Dex*
0
 

Author Comment

by:ewmontgo
ID: 9696406
I get the same compiler error:
cannot convert parameter 2 from 'struct EXTRA::_Session ** ' to 'struct IDispatch ** ',
and I can still cast it (the same way). If I cast it and run it, I end up with the same result. session->GetScreen(); returns NULL.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9696750
Well, I'm not sure if casting it that way is safe, but we can worry about that once we get the next step working.  The important thing is that the SessionPtr value is being set now.

We need to figure out what the "raw" function for "GetScreen" is.  Search the .tlh file for "Screen".  There has to be something in there.

Have you wrapped the whole thing is a try, catch block for _com_error& e ?  If one of the methods fails, it should throw such an exception (unless you're using the raw methods).  Does it ever get to the catch block?  If so, what is the value of the e.Error() ?
0
 

Author Comment

by:ewmontgo
ID: 9696872
I found what I think is the raw get screen function (I don't know how I missed it before):
virtual HRESULT __stdcall get_Screen (IDispatch * * retval ) = 0;

One thing, I'm .not. getting a value for sessionPtr. Here's the code for that (just to make sure I didn't make a typo):

struct EXTRA::_Session* pSession = NULL;
hr = sessions->raw_Open(CComVariant(SessionName), (struct IDispatch **)&pSession);
if(SUCCEEDED(hr))
{
     session= EXTRA::_SessionPtr(pSession, FALSE);
}

By debugging, I know that it runs the line session=EXTRA ..., which means hr is succeeding on the previous line. Why would it succeed if pSession is still NULL? If I leave out the casting, it won't compile.

When the get_Screen line fails:
hr = session->get_Screen((struct IDispatch **)&screen);
hr is -2147467261, but I think this line is failing because pSession is NULL. Something must be wrong with the raw_Open function, or one of its subsequent calls. I've searched both the tli and tlh files for raw_Open, but I didn't find anything new.

TLH has:
virtual HRESULT __stdcall raw_Open (
        VARIANT Name,
        IDispatch * * retval ) = 0;

TLI has:
inline IDispatchPtr Sessions::Open ( const _variant_t & Name ) {
    IDispatch * _result;
    HRESULT _hr = raw_Open(Name, &_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return IDispatchPtr(_result, false);
}

By the way, I really appreciate your assistance on this. Thank you.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9697050
ewmontgo:

> hr = session->get_Screen((struct IDispatch **)&screen);
> hr is -2147467261, but I think this line is failing because pSession is NULL.

Yes, that is exactly what is happening.  But why is it NULL?

Try this:
     IDispatchPtr spDispatch = sessions->Open(SessionName);
     if ( spDispatch == NULL )
     {
        // If it gets here, then something really bizarre is happening
        // because it didn't throw an exception, yet Open returned a NULL value
     }

If it gets inside of the block, then the issue is with your COM object.  For some reason, it is NOT returning a value, yet it is also not returning an error.  You'll have to read the documentation (if there is any) on the "Open" method to see how it is supposed to behave.  One would THINK that if it wasn't going to return a session, that it would return an error, but that is actually defined by the implementation of the COM object.

If you run the above code, and you keep getting (spDispatch == NULL), then try different values for your parameter to Open().  A VARIANT can be anything.  Here are some that I would try:

     spDispatch = sessions->Open(_bstr_t("MAINFRAME.EDP"));
     spDispatch = sessions->Open((long)0);
     spDispatch = sessions->Open((long)1);

Just to see if any of those give you a value for spDispatch.
Once you get a value of spDispatch, then it is just a matter of converting it to an EXTRA::_SessionPtr, but that should be trivial.


> By the way, I really appreciate your assistance on this. Thank you.

Enough to up the points when we get it working?  :P
(Just kidding...)

Dex*
0
 

Author Comment

by:ewmontgo
ID: 9697126
I guess it's an issue with the COM object, then. I tried all four of the spDispatch lines above. The fourth (->Open((long)1);) threw a _com_error with value -2147220992, which has text "Unknown Error" (real helpful). I'll have to check on the documentation for Open.

I've gotten this to work using JavaScript and a command line, and that still works (it uses the same principles as the C++ version). The problem is that I lose a lot of functionality using JavaScript instead of C++. It's just really puzzling, especially that the code I didn't touch suddenly quit, the JavaScript code still works, and there's no apparent reason.

This makes me think that something must be wrong in a Visual Studio related file? I know quite a bit about coding, but not much about COM objects. Would that be possible?
0
 
LVL 19

Accepted Solution

by:
Dexstar earned 130 total points
ID: 9697233
Okay, just as an aside, HRESULTs are unsigned, so -2147220992 becomes 0x80040200.  I looked up that error number I got "CO_E_FAILEDTOIMPERSONATE" (but no message text).  That doesn't seem to be very helpful though.  But its weird that you'd get that for one, but not for anything else.

Is this an in-process or out-of-process COM object?  Meaning, is it a DLL or does it run as a separate process?  Try re-installing the components.  They may have gotten messed up somehow.

Have you tried the obvious things like "Rebuild All" or rebooting the computer?  What about running your C++ program on another computer that has these components installed?

Dex*
0
 

Author Comment

by:ewmontgo
ID: 9700970
Okay, this is interesting -

I've had the original Extra client reinstalled on my computer. No problem, but my code still doesn't work. I ran the code (actually, the original one, in release format) on a companion's computer, and it broke his client to the point that he can't run it any more. This says to me that the code is changing something in the system (a dll or a registry entry or something) way early in the program. I think that the problem may go all the way back to this:

hr = CoInitialize(NULL);
hr = system.CreateInstance("EXTRA.System", NULL);

I tried throwing in if(FAILED(hr)), but hr doesn't fail in either case. If it's not possible that it's that line, it MUST be one of these:

sessions = system->Sessions; // try the raw function here?
session = sessions->Open(SessionName); // this is the line from above that's returning NULL
screen = session->Screen;

As aggravating as this problem is, it's also really quite interesting.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now