Solved

CoCreateInstances failes when called twice

Posted on 2003-11-20
25
638 Views
Last Modified: 2013-12-03
I'm having all sorts of fun today jkr/dex.  Lend me your thoughts on this also please.

Ok, example based in reality, simplified to make this clear:

This is how the two CoCreateInstance calls work (i replaced DirectInput8Create with this to see if it made any difference so assume the failure with either call).

I run the normal program executable, which creates an instance of directinput8, this yields fine results with either call and I get my interface.  Then I run the service, which also does the same code to start directinput, and also yields good results and gets the interface ... and then they both are successful through the device creation/etc.

How this does not work:

Run the service first, and then the program.   OR Run the program, and then the program itself again.  I get the most general COM error you can get, so that's not much help.  The code is 99% the same.

The service does not seem to care what context you give it, INPROC_SERVER, ALL, etc, but the program only accepts INPROC_SERVER and gives you the wonderful class not registered error otherwise.

I'm all ears :)
0
Comment
Question by:_corey_
  • 14
  • 5
  • 5
  • +1
25 Comments
 
LVL 8

Author Comment

by:_corey_
ID: 9794492
Btw, I'm just scratching this together for boss for demo...Indeed, I would rather have this whole thing done a different way, but it should be possible I believe to get this working in any order.

Also, yes CoInitializeEx has been called.  I'm just not that familiar with the differences between service and normal program execution with COM.
0
 
LVL 23

Expert Comment

by:Roshan Davis
ID: 9795353
Please check the documentation "PRB: CoCreateInstance Fails in RPC Server" in MSDN
0
 
LVL 8

Author Comment

by:_corey_
ID: 9795433
That was a little difficult to find but an interesting read.  However, I don't believe it applies at all.

0
 
LVL 86

Expert Comment

by:jkr
ID: 9800031
Hm, but it does work when you use 'DirectInput8Create()' and call it twice?
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9800049
That is the question, isn't it?

Things to try:
1) Try running your program from the SYSTEM account.  See if it fails twice that way.
2)  Create a new empty program, just init's COM, gets the DI pointer, and then waits for the user to click a button.  Then, it releases the pointer and exits.  See if 2 of those program will run at the same time without errors.

If you do #2 and it works, then there is something in your app that is causing the issue.  Start stripping things out until you find what is causing it.  I would start with making sure that ALL COM interfaces are wrapped in smart pointers.  It is SO easy to make a mistake, and SO hard to find it once you have.  Smart Pointers save you 98% of the hassle.

Dex*
0
 
LVL 8

Author Comment

by:_corey_
ID: 9800058
Here's a more detailed list that I've found out:

1)  Run the program twice, with neither releasing the basic interface after it is created and the 2nd program fails at CoCreateInstance.

2)  Run the program twice with the first one releasing the basic interface immediately, the 2nd program will create a valid pointer.

3)  Create 2 basic interfaces with CoCreateInstance in the same process without releasing first and they both get valid pointers.

4)  Do #1 with DirectInput8Create with same results.
0
 
LVL 86

Expert Comment

by:jkr
ID: 9800087
I gues you simply are aquiring an exclusive resource that can only be owned by one process at a time...
0
 
LVL 8

Author Comment

by:_corey_
ID: 9800190
Ok, the basic app to initialize and not release will run correctly many times.

That is interesting because it would seem to rule out a smart pointer need although I use them extensively.

I don't call this code but once in the main project app, and I'm VERY positive no one else in the team is touching COM.

I have some directShow code all nicely written with smart pointers/etc, never touching directInput and not even initialized actually due to no camera being plugged in, as far as I can tell.
0
 
LVL 8

Author Comment

by:_corey_
ID: 9800197
I gues you simply are aquiring an exclusive resource that can only be owned by one process at a time...

Not from what I found out.

I can do that basic program over and over and not release.

Plus, I can release my main interface in the middle of using it in the main project app and start up another copy of it and get a valid pointer returned.
0
 
LVL 8

Author Comment

by:_corey_
ID: 9800240
Interesting results now actually:

I can release the main interface and have 2 programs run correctly, but I cannot release in the service and have the program run correctly.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9800307
Okay, so what I would do is start stripping out code of my program (just comment it out).  If you call that function during initialization, then strip it down to just the init routines, and see if your crippled program works properly when calling that routine.

If it does, then there is something about the code that you stripped out that is causing the problem.  Then you should just start adding things back in, one piece at a time, until you add something that breaks it.  Then we need to look at what you added...

Dex*
0
 
LVL 8

Author Comment

by:_corey_
ID: 9804245
I just realized something today.

When I'm running the service with the code in it (even with the interface released), no other DI "programs" will initialize correctly.  The gamecontrollers tools in Control Panel.  The samples for joystick reading in the DirectX samples.  They all fail.

So I decided to use my domain user account to run the service instead of SYSTEM.  This worked, but resulted in no desktop interaction even though I create the service with that permission.  However, with that running and finding the joystick in the service, the other programs could then initialize correctly.

Does that say anything?
0
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.

 
LVL 8

Author Comment

by:_corey_
ID: 9814444
I suppose I could spawn a new process that accesses the directInput com server with a different user, what do you think of that solution?
0
 
LVL 8

Author Comment

by:_corey_
ID: 9815226
I'm going to go a different route, although I was hoping to make this service work, I don't feel it's worth the effort to get around using the LocalSystem user for desktop interaction.

I wish I knew exactly why that happened with the directInput base interface.
0
 
LVL 19

Accepted Solution

by:
Dexstar earned 500 total points
ID: 9819351
_corey_ :

That's okay.  Typically, they recommend that you DO NOT make services that interact with the desktop, because there is a potential security hole.  If the user can get a window that belongs to your service, then they can send messages to that window, and possibly affect the service by crashing it, injecting code, or whatever.  If you have a service that needs to communicate with the user, you should have the user run an app that communicates with the service via IPC or something.

So just using a regular user account makes the issues all go away?

Dex*
0
 
LVL 8

Author Comment

by:_corey_
ID: 9819636
It does go away, but I don't get desktop interaction of course.

I agree with you on the above, but on a side-note this is a secluded system, like they'd be mass-produced and static so if it broke, it'd just be replaced.  I'm not woried too much about large security risks.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9819643
What desktop interaction did you need?  You might have to use 2 services...  :/
0
 
LVL 8

Author Comment

by:_corey_
ID: 9819654
Simply to send input commands to the system.  mouse movement, clicks.

That's the only interaction I need.  The problem is that LocalSystem account just totally kills the directInput class factory when it grabs one...it doesn't destroy earlier interfaces, just you cannot get any after it.
0
 
LVL 19

Expert Comment

by:Dexstar
ID: 9819761
You might try setting up the service to run as the local system, and interact with the desktop, but before you call the CoCreateInstance, try impersonating another user, any user... And then revert back to the original user (which should go back to the system account), and maybe it will work that way.  Just an idea.

Dex*
0
 
LVL 86

Expert Comment

by:jkr
ID: 9819892
>>It does go away, but I don't get desktop interaction of course.

You can do that with *any* service - all you have to do is granting access to the desktop. See e.g.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/interacting_with_the_user_in_a_service.asp ("Interacting with the User in a Service"):

DWORD dwGuiThreadId = 0;
 
int
UserMessageBox(
    RPC_BINDING_HANDLE h,
    LPSTR lpszWindowStation,
    LPSTR lpszDesktop,
    LPSTR lpszText,
    LPSTR lpszTitle,
    UINT fuStyle)
{
    DWORD dwThreadId;
    HWINSTA hwinstaSave;
    HDESK hdeskSave;
    HWINSTA hwinstaUser;
    HDESK hdeskUser;
    int result;
 
    // Ensure connection to service window station and desktop, and
    // save their handles.

    hwinstaSave = GetProcessWindowStation();
    dwThreadId = GetCurrentThreadId();
    hdeskSave = GetThreadDesktop(dwThreadId);
 
    // Impersonate the client and connect to the User's
    // window station and desktop.

    RpcImpersonateClient(h);
    hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
    if (hwinstaUser == NULL)
    {
        RpcRevertToSelf();
        return 0;
    }
    SetProcessWindowStation(hwinstaUser);
    hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
    RpcRevertToSelf();
    if (hdeskUser == NULL)
    {
        SetProcessWindowStation(hwinstaSave);
        CloseWindowStation(hwinstaUser);
        return 0;
    }
    SetThreadDesktop(hdeskUser);
 
    // Display message box.

    dwGuiThreadId = dwThreadId;
    result = MessageBox(NULL, lpszText, lpszTitle, fuStyle);
    dwGuiThreadId = 0;
 
    // Restore window station and desktop.

    SetThreadDesktop(hdeskSave);
    SetProcessWindowStation(hwinstaSave);
    CloseDesktop(hdeskUser);
    CloseWindowStation(hwinstaUser);
 
    return result;
}

The only problem is the 'impersonation', you do not have to use RPC, a named pipe would do it also - or any other way to let the service know about a primary token.
0
 
LVL 8

Author Comment

by:_corey_
ID: 9819938
Thanks for the detailed example jkr.

You wouldn't happen to know where I could find information on the affect of LocalSystem or any user on a ClassFactory or directX classes?  I'd like to know what happened even though I'm going to go around it.  First with a non-sevice, then a service as you pointed out if they want that.
0
 
LVL 8

Author Comment

by:_corey_
ID: 9819997
Post if you know jkr, but I'm giong to give you a fake Q for your points so it'll be an easy split.
0
 
LVL 86

Expert Comment

by:jkr
ID: 9820018
>>You wouldn't happen to know where I could find information on the affect
>>of LocalSystem or any user on a ClassFactory or directX classes?

My first guess would be: On MSDN *duck* :o)
0
 
LVL 8

Author Comment

by:_corey_
ID: 9820031
Yea, no clue where to find that on there.  Wish I could ask them the question.
0
 
LVL 86

Expert Comment

by:jkr
ID: 9820113
The problem is that DirectX uses a lot of 'services' that have nothing to do with Win32 services - so you simply get flooded with search results...
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

747 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

9 Experts available now in Live!

Get 1:1 Help Now