Error instantiating COM object - c++

currently I'm struggling trying to use a COM dll on a simple system that I've made. Everything compiles successfully, but in runtime the CoCreateInstace is returning S_OK, but somehow my object pointer is returning NULL.
This interface pointer is created on my class header. The weirdest thing is that instantiating this same pointer type on the method stack results in a correct object, but subsequent calls to __hook turn on an access violation when trying to create a BASE com class.
Some other aspects that might be useful:
Tried to run the program with CoInitalizeEx started as COINIT_MULTITHREADED and COINIT_APARTMENTTHREADED
The project is a dll which uses the COM dll in it
I've tried the same method without starting a new thread and the error persists
I've made a test program ( no threads, executable ) and the object is created normally, and hooked correctly. So my guess it is something related to it being a DLL itself or threaded related.
PS: As bonus question, why google doesn't return anything favorable related to COM? :)

It sounds like a bug in the COM object's implementation of IUnknown::QueryInterface - not setting the output pointer but returning S_OK.
CoCreateInstance for an in-proc server is basically:
Load the DLL into memory
Call DllGetClassObject to get the class factory
Call IClassFactory::CreateInstance from the class factory which allocates a new object
Call IUnknown::QueryInterface on the new object to get the desired interface.
Returning NULL but S_OK at any step should result in a crash, except for the QI call at the end.

Found the problem: The module attribute was defined on a static library, and that made the COM object go crazy; Moving it to the DLL source resolved the problem.

Related

Is there a way to explicitly detatch an implicitly linked DLL?

This is not for production code, this is for a unit test.
We have a legacy DLL which frees resources on a DLL_PROCESS_DETACH event. We had a crash scenario in the static destruction phase of an executable because the destructor of a static variable was trying to access resources unmapped by the DLL (dangling reference).
I'd like to reproduce this crash scenario in a unit test so I can prove I've fixed it.
You may be able to get a handle to the module with GetModuleHandle(LPCTSTR lpModuleName), and pass that to FreeLibrary().
The documentation for GetModuleHandle() states:
The GetModuleHandle function returns a handle to a mapped module without incrementing its reference count. However, if this handle is passed to the FreeLibrary function, the reference count of the mapped module will be decremented. Therefore, do not pass a handle returned by GetModuleHandle to the FreeLibrary function. Doing so can cause a DLL module to be unmapped prematurely.
Despite the warning not to do so, that sounds like it is exactly what you are looking to do. This should be fairly easy to test in your scenario, to verify that it does what you want.

What happens to Dispatch Pointer after crash

Assume that I have two processes, A and B. Process A instantiates an IDispatch object in process B (Process A loads the proxy stub, marshalling is done through it). During this, process B crashes and the IDispatch object goes down with it. Process A still has a pointer to something, but when it tries to call a function on that IDispatch object, the marshaller returns an error code. What is that error code? E_POINTER? E_FAIL?
You'll normally get RPC_E_SERVERFAULT. This is unpleasant behavior, the server is usually toast after this. A fix is available in Vista and up with IGlobalOptions. Check this blog post for details.

CComModule::Unlock();

I've been trying to determine what this function does, however I cannot seem to find it anywhere under the MSDN documentation of the CComModule class.
Could anyone tell me what it is used for?
This function is for DllCanUnloadNow() to work properly.
You know that when you call CoCreateInstance() for an in-proc server COM automagically calls LoadLibraryEx() to load the COM server DLL if necessary. But how long is the DLL kept loaded? In fact COM calls DllCanUnloadNow() for every loaded COM server DLL periodically. If it returns S_OK COM is allowed to call FreeLibrary().
When is it safe to unload the DLL? Obviously you can't unload it until all the objects implemented by the DLL are destroyed. So here comes "lock count" - an global integer variable counting the number of live objects implemented by the DLL.
When a new COM object is created - CComModule::Lock() is called from its constructor (usually CComObject constructor) and increments the variable, when an object is destroyed - CComModule::Unlock() is called from its destructor and decrements the variable. When CComModule::GetLockCount() returns zero it means that there no live objects and it's safe to unload the DLL.
So the lock count is very similar to the reference count implemented by IUnknown. The reference count is per object, the lock count is per COM in-proc server.

C++ setTimout function?

What's the cheapest way for a JavaScript like setTimeout-function in C++?
I would need this:
5000 miliseconds from now, start function xy (no parameters, no return value).
The reason for this is I need to initialize COM for text to speech, but when I do it on dll attach, it crashes.
It works fine however if I do not call CoInitialize from dllmain.
I just need to call CoInitialize and CoCreateInstance, and then use the instance in other functions. I can catch the uninitialized instance by checking for NULL, but I need to initialize COM - without crashing.
Calling CoInitialize() from DllMain() is a bad thing to do; there are LOTS of restrictions on what you can do from DllMain(); see here: http://blogs.msdn.com/larryosterman/archive/2004/04/23/118979.aspx
Even if it DID work reliably then initialising COM from within DllMain() isn't an especially nice thing to do as COM is initialised per thread and you don't know what the application itself wants to do with regards to COM apartments for the thread that you want to initialise COM for... This means that you might initialise COM in one way and then the application might need to initialise it in another way and might fail because of what your DLL had done...
You COULD spin up a thread in DllMain() as long as you are careful (see here http://blogs.msdn.com/oldnewthing/archive/2007/09/04/4731478.aspx) and then initialise COM on that thread and do all your COM related work on that thread. You would need to marshal whatever data you need to use COM with from whatever thread you're called on to your own COM thread and make the COM call from there...
And then there's the question of whether the instance of the COM object that you create (could you reliably do what you want to do) would be usable from the thread that was calling into your DLL to make the call... You do understand how you'd have to marshal the interface pointer if required, etc?
Alternatively you should expose YOUR functionality via COM and then have the application load your DLL as a COM DLL and everything will work just fine. You can specify the apartment type that you need and the app is responsible for setting things up for you correctly.
So, in summary, you don't need the answer to your question.
When it is OK to stop the execution for 5 seconds entirely, you can use the Winapi Sleep function. Beware that the documentation of Sleep minds some possible problems with CoInitialize and Messages.

CoCreateInstance returning E_NOINTERFACE even though interface is found

I have a COM class CMyCOMServer implementing IMyInterface in one application, both with correct GUIDs. CMyCOMServer::QueryInterface will return S_OK (and cast itself to the right type) if IUnknown or IMyInterface is requested, otherwise it returns E_NOINTERFACE.
In another app on the same PC, I call:
HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER,
__uuidof(IMyInterface ),(void **)&pInterface);
It returns E_NOINTERFACE. So I assumed I was doing something wrong and added a breakpoint on CMyCOMServer::QueryInterface. I found that when CoCreateInstance is called, QueryInterface is triggered several times for different interfaces:
First, IUnknown is requested - no problem
Then, several interfaces like IMarshall etc are requested... these are not supported so E_NOINTERFACE is returned
Finally, IMyInterface is requested. I verify QueryInterface returns S_OK and sets (IMyInterface *)this as the interface pointer, as expected
So my confusion is why the calling CoCreateInstance is leaving me a NULL pointer and return code of E_NOINTERFACE, when the COM server app is clearly returning the interface I ask for?
EDIT: my client app calls CoInitialize(NULL) at startup, this makes no difference.
If your COM server is running in a different process, or a different apartment in the same process, COM needs to know how to package and transmit parameters when you make calls to your interface. This process is called "marshaling".
If you define a custom interface, you need to implement marshaling for it using one of the following approaches.
Standard marshaling: have the MIDL compiler to generate a proxy
and stub which you must register on the system. This is probably the best option since you have already defined your interface.
OLE Automation marshaling: you define an automation compatible
custom interface and use the
marshaller which is already part of
the COM framework
Custom marshaling: you implement the methods of IMarshal
When you are debugging your COM server, although you see that you are returning your custom interface in the call to QueryInterface, it does not make it across the process boundary because COM cannot figure out how to marshal that interface, hence the client sees E_NOINTERFACE.
UPDATE (based on your comment)
If this is an existing COM server app then you probably already have a proxy/stub. You need to register this on both the client and server. Could it be that you were testing this on a new machine(s) and you simply forgot to register this? To register you simply do regsvr32 on the proxy/stub dll.
This happens because COM subsystem tries to marshal your custom interface (IMyInterface) and simply has no idea how to do that. That happens either because the server is out-proc or because the server is in-proc and the thread of the consumer application that calls CoCreateInstance() has called CoInitialize()/ CoInitializeEx() incorrectly so that "multithreaded apartment" is requested as mentioned in the article user Thomas refers to in the other answer.
If you only need an in-proc server you could suppress marshalling by ensuring that the thread calling CoCreateInstance() either calls CoInitialize() or CoInitializeEx() with COINIT_APARTMENTTHREADED to enforce "single-threaded apartment".
If you need an out-proc server you can't get around marshalling. In the latter case you could do one of the following:
implement IMarshal - least preferable
add proxy/stubs and register them for your custom interface
(not sure if it will work for out-proc, but it's the simplest) if your interface can be marshalled with automation marshaller simply include a typlib into the resources of your COM server and register that typelib in the registry.
Could this be the threading model problem that Raymond Chen wrote about?
Edit in reply to the comment:
If your threading model is incompatible with the threading model of the object you're creating, then COM marshalling kicks in. And if the marshalling stuff isn't there, the error that comes out is E_NOINTERFACE, because the marshalling interface is missing.
It's more about threading models than about marshalling, really.
The previous comments about E_NOINTERFACE returned because marshalling interface is missing was very helpful,
however,
for us the answer/fix was to force the main application (the one calling CoCreateInstance) to be STA (single threaded apartment), and this was done by setting an advanced linker option, i.e.:
"CLR Thread Attribute" is set to "STA threading attribute"
or on the link command line you do:
"/CLRTHREADATTRIBUTE:STA"
This prevents a mix of MTA and STA, which causes a call across threads.
Hope someone else finds this helpful.