CoCreateInstances failes when called twice

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 :)
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

_corey_Author Commented:
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.
Roshan DavisCommented:
Please check the documentation "PRB: CoCreateInstance Fails in RPC Server" in MSDN
_corey_Author Commented:
That was a little difficult to find but an interesting read.  However, I don't believe it applies at all.

Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

Hm, but it does work when you use 'DirectInput8Create()' and call it twice?
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.

_corey_Author Commented:
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.
I gues you simply are aquiring an exclusive resource that can only be owned by one process at a time...
_corey_Author Commented:
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.
_corey_Author Commented:
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.
_corey_Author Commented:
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.
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...

_corey_Author Commented:
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?
_corey_Author Commented:
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?
_corey_Author Commented:
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.
_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?


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
_corey_Author Commented:
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.
What desktop interaction did you need?  You might have to use 2 services...  :/
_corey_Author Commented:
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 doesn't destroy earlier interfaces, just you cannot get any after it.
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.

>>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. ("Interacting with the User in a Service"):

DWORD dwGuiThreadId = 0;
    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.

    hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
    if (hwinstaUser == NULL)
        return 0;
    hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
    if (hdeskUser == NULL)
        return 0;
    // Display message box.

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

    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.
_corey_Author Commented:
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.
_corey_Author Commented:
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.
>>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)
_corey_Author Commented:
Yea, no clue where to find that on there.  Wish I could ask them the question.
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...
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.