COM Initialization and Use in Win32 C++ DLL - c++

I am writing a Win32 C++ DLL that uses the COM to query WMI. How can I programmatically determine if COM has already been initialized? Thanks.

Mark Ransom is right
the straightforward, clean and simple solution is to require COM initialization by the caller.
Ugly hack
You can try your first call - likely CoCreateInstance, and if it returns CO_E_NOTINITIALIZED, run CoInitialize yourself (and don't forget to uninit in that case)
However, it is still problematic to "inject" a CoInitialize into a caller thread from a DLL. So there's a
Clean Solution
Let the DLL create a worker thread (which means the DLL needs Init and Teardown calls), CoInitializeEx in this thread yourself, and move all the COM calls to that separate thread.

The easiest way is not to bother, just make it a requirement of anybody using your DLL that they initialize COM first. Otherwise you run the risk of messing up their own initialization if they perform it after yours.
On the other hand if your flags to CoInitializeEx match those of the application, you should be fine. From the CoInitializeEx documentation:
Multiple calls to CoInitializeEx by
the same thread are allowed as long as
they pass the same concurrency flag,
but subsequent valid calls return
S_FALSE.

It follows #peterchen clean solution as I coded it for a thread-safe COM logger component that I wanted to wrap:
IComLoggerPtr _logger;
_bstr_t _name;
HANDLE _thread;
HANDLE _completed;
Logger::Logger(_bstr_t name)
{
_name = name;
_completed = ::CreateEvent(NULL, false, false, NULL);
if (_completed == NULL)
::AtlThrowLastWin32();
// Launch the thread for COM interation
DWORD threadId;
_thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(this->threadRun),
(LPVOID)this, 0, &threadId);
// Wait object initialization
HRESULT hr = ::WaitForSingleObject(_completed, INFINITE);
if (FAILED(hr))
AtlThrow(hr);
}
Logger::~Logger()
{
::SetEvent(_completed);
CloseHandle(_thread);
CloseHandle(_completed);
}
DWORD WINAPI Logger::threadRun(LPVOID opaque)
{
Logger *obj = (Logger *)opaque;
// Init Free-Threaded COM subsystem
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr))
::AtlThrow(hr);
hr = obj->_logger.CreateInstance(__uuidof(ComLogger));
if (FAILED(hr))
::AtlThrow(hr);
obj->_logger->Init(obj->_name);
// Initialization completed
bool success = ::SetEvent(obj->_completed);
if (!success)
::AtlThrowLastWin32();
// Wait release event
hr = ::WaitForSingleObject(obj->_completed, INFINITE);
if (FAILED(hr))
AtlThrow(hr);
obj->_logger.Release();
// Release COM subsystem
::CoUninitialize();
}
HRESULT Logger::Log(_bstr_t description)
{
return _logger->Log(description);
}

CoInitializeEx\CoUninitialize should only be called by threads (not by Dll-calls).
BTW ,you should not Use CoInitializeEx\CoUninitialize in DllMain !

Related

Making an async COM call -- do I have to create my own P/S?

I have a custom interface defined in a type library and implemented in my code. I have not created my own proxy/stub. I have successfully marshaled the interface pointer from my main thread (STA) to a background thread (STA), in my case using IGlobalInterfaceTable.
From that background thread, I want to make an asynchronous call to the object on the UI thread. I have not implemented ICallFactory in my object. I see that the standard proxy does indeed implement ICallFactory (i.e, I can successfully QI on the background thread for ICallFactory). But the CreateCall for my custom interface fails with HRESULT 0x80040150 (Could not read key from registry).
Do I need to create my own proxy that explicitly implements ICallFactory in order to do this?
Here's my IDL:
[
object,
uuid(92303FE7-A79D-47DD-923F-62062105C00E),
async_uuid(2880C40C-9965-4544-AE39-DF08056E8CB6),
nonextensible,
pointer_default(unique),
oleautomation
]
interface IFoo: IUnknown
{
HRESULT Foo([in] long a, [in] long b);
}
[
uuid(D58B0A31-A2D5-4BFB-8702-3B710320493B)
]
coclass Foo
{
[default] interface IFoo;
};
And here's the background thread proc in my unit test:
static DWORD WINAPI threadproc(LPVOID lpParameter)
{
// get arguments
DWORD cookie = *(DWORD*)lpParameter;
// initialize COM
Assert::AreEqual(S_OK, CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
{
// get global interface table
IGlobalInterfaceTablePtr globalInterfaceTable;
Assert::AreEqual(S_OK, globalInterfaceTable.CreateInstance(CLSID_StdGlobalInterfaceTable));
// get object
MyLib::IFooPtr object;
Assert::AreEqual(S_OK, globalInterfaceTable->GetInterfaceFromGlobal(cookie, MyLib::IID_IFoo, (LPVOID*)&object));
// get async call factory
ICallFactoryPtr callFactory;
Assert::AreEqual(S_OK, object->QueryInterface(&callFactory));
//
// Everything is fine up until the CreateCall call below,
// which fails with HRESULT 0x80040150
//
// create async call object
IUnknownPtr callObject;
Assert::AreEqual(S_OK, callFactory->CreateCall(MyLib::IID_AsyncIFoo, NULL, IID_IUnknown, &callObject));
}
// uninitialize COM
CoUninitialize();
// success
return 0;
}
As far as I know, the universal marshaller does not work with Async COM. You need to build the (MIDL-generated) proxy (although, IIRC, you can merge the stubs if you're building a DLL).
You also need to register the proxy DLL (and build it with the -DREGISTER_PROXY_DLL define). Async COM needs more registry keys defined in order to make it work.

Can TerminateThread terminate a thread from another process?

In my Windows service application I may resort to calling TerminateThread API on some of the threads in my process. (Note that I do so only as a last resort measure when a thread fails to quit in a "normal fashion" using signaling mechanism and thread synchronization techniques.) What I've noticed in the event log submitted by a customer is that very rarely TerminateThread may throw the STATUS_INVALID_THREAD exception, which happens only when that API is called on a thread belonging to a threadpool.
Since I know for sure that none of my threads are started from a threadpool, the thread that my call to TerminateThread attempts to close must be coming from another process. This could happen only due to a race condition where my thread handle is closed first and then is passed again to the TerminateThread API while the OS reuses it for some other thread in another process.
So my question is, since my service is running with sufficiently high privileges (as localService) can TerminateThread API in this situation inadvertently terminate some thread belonging to another process? And if yes, how can I prevent this (apart from finding the race-condition, that I'm doing now)?
Let's let the docs speak for themselves:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85).aspx
Do not use TerminateThread():
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
[...]
You can terminate any thread, as long as you have a handle with sufficient privileges:
A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread.
Note that I do so only as a last resort measure when a thread fails to quit in a "normal fashion" using signaling mechanism and thread synchronization techniques.
That is a case where you cannot call TerminateThread. You can only call TerminateThread if you have precise control over the thread you are terminating and its full cooperation. If the thread fails to quit in the normal fashion, then you have lost control over the thread, the very opposite of the required conditions under which you can call TerminateThread.
If a process has lost control over one of its threads, the process cannot be saved. This is a fundamental property of threads -- they do not provide isolation of anything but flow control.
If you must do this you can do it like this.
All you need to start is the thread handle.
You call the first function with thread handle as input using the "undocumented" NtQueryInformationThread() function with the ThreadQuerySetWin32StartAddress argument, you get the StartAddress of the thread. More reading # NTInternals.
It calls NTQueryInformationThread by function address after getting the address via GetProcAddress. Then it calls it with the ThreadQuerySetWin32StartAddress argument, getting the StartAddress of the thread.
Then you call the second function which loops through all the threads via CreateToolHelp32Snapshot and compares against the supplied StartAddress. It calls TerminateThread once it finds it.
enum THREADINFOCLASS
{
ThreadQuerySetWin32StartAddress = 9,
};
typedef NTSTATUS(__stdcall * f_NtQueryInformationThread)(HANDLE, THREADINFOCLASS, void*, ULONG_PTR, ULONG_PTR*);
ULONG_PTR GetThreadStartAddress(HANDLE hThread)
{
auto NtQueryInformationThread = reinterpret_cast<f_NtQueryInformationThread>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationThread"));
if (!NtQueryInformationThread)
return 0;
ULONG_PTR ulStartAddress = 0;
NTSTATUS Ret = NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &ulStartAddress, sizeof(ULONG_PTR), nullptr);
if (NT_FAIL(Ret))
return 0;
return ulStartAddress;
}
bool TerminateThreadByStartaddress(ULONG_PTR StartAddress)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return false;
THREADENTRY32 TE32 = { 0 };
TE32.dwSize = sizeof(THREADENTRY32);
BOOL Ret = Thread32First(hSnap, &TE32);
while (Ret)
{
HANDLE hTempThread = OpenThread(THREAD_ALL_ACCESS, FALSE, TE32.th32ThreadID);
if (!hTempThread)
{
Ret = Thread32Next(hSnap, &TE32);
continue;
}
if (StartAddress == GetThreadStartAddress(hTempThread))
{
TerminateThread(hTempThread, 0);
CloseHandle(hTempThread);
CloseHandle(hSnap);
return true;
}
CloseHandle(hTempThread);
Ret = Thread32Next(hSnap, &TE32);
}
CloseHandle(hSnap);
return false;
}
Credits to my friend Broihon, I didn't write this code but have used it before.
Use undocumented NTSYSAPI NTSTATUS NTAPI NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus); from http://undocumented.ntinternals.net where ThreadHandle is result from OpenThread MS function and ExitStatus set to whatever you want.

Under what conditions is CCmdTarget::OnFinalRelease called?

The MSDN documentation for the CCmdTarget::OnFinalRelease method is pretty brief:
Called by the framework when the last OLE reference to or from the
object is released.
I have created a sub-class of CCmdTarget
class CMyEventHandler : public CCmdTarget { ... }
I'm trying to figure out under what conditions the OnFinalRelease method will be called. I have some code that looks something like this:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
Using this code, I observe that the OnFinalRelease method is never called. This means I have a memory leak. So I modified the wrap-up code as follows:
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(FALSE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, FALSE, myCookie);
delete myEventHandler;
myEventHandler = NULL;
This section of code is triggered off periodically throughout the day. What I notice now is that, while the destructor for the wrapped up instance of myEventHandler is called as expected, the OnFinalRelease function is getting called now! What's worse, it is being called not on the instance that has been wrapped up, but instead on a newly created instance of CMyEventHandler! Thinking that this might be due to a reference counting issue, I modified my wire-up and wrap-up code:
CMyEventHandler* myEventHandler = new CMyEventHandler();
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionAdvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
// Application continues...events arrive...eventually the event sink is shutdown
LPUNKNOWN pUnk = myEventHandler->GetIDispatch(TRUE);
AfxConnectionUnadvise(myEventSource, DIID_IMyEventInterface, pUnk, TRUE, myCookie);
pUnk->Release();
delete myEventHandler;
myEventHandler = NULL;
I let this run all day and now observe that OnFinalRelease is never called. The destructor for the wrapped up instance is called as I would expect, but I'm left feeling uneasy as I clearly don't understand the circumstances under which OnFinalRelease is called. Is OnFinalRelease called on some delay, or is there a way to force it to fire? What will trigger OnFinalRelease to be called?
If it matters, the event source is a .NET assembly exposing events via COM interop.
With COM you should always use the CoCreateInstance() AddRef() and Release() paradigm to manage lifetime of your objects, and let COM do the destruction of your objects based on reference counts. Avoid new and delete because using them breaks this paradigm and causes interesting side effects. You probably have a bug in the management of the reference counts.
The way to debug why the reference counts are not being managed correctly is to override CCmdTarget::InternalRelease() copy the source from oleunk.cpp and put some trace output or break points.
DWORD CMyEventHandler::InternalRelease()
{
ASSERT(GetInterfaceMap() != NULL);
if (m_dwRef == 0)
return 0;
LONG lResult = InterlockedDecrement(&m_dwRef);
if (lResult == 0)
{
AFX_MANAGE_STATE(m_pModuleState);
OnFinalRelease();
}
return lResult;
}
There are lots of times when passing IDispatch interfaces that code will bump reference counts and you have to decrement the reference count using Release(). Pay attention to where your code may be passing this interface because there is aconvention in COM that when Interfaces are passed using [in] or [out] where the caller or callee has to release the interface.
When the reference count issue is corrected you shoudl see the objects OnFinalRelease code being called and the object destoryed by hte MFC framework:
For CCmdTarget the destruction should happen as a result of the final
release in the parent class CWnd:
void CWnd::OnFinalRelease()
{
if (m_hWnd != NULL)
DestroyWindow(); // will call PostNcDestroy
else
PostNcDestroy();
}
FYI: Passing interfaces across threads without marshalling the interface pointers is another common reason to get errors in COM.
It doesn't appear that you ever call myEventHandler->Release(). Therefore, the last reference is never released, and OnFinalRelease is never called.

Loading CLR in C++, Start() problem

So I'm trying to load up the .NET 4 runtime and run my own C# DLL. The Start() method is throwing a HRESULT=0x1 error. If I comment out the start code, the C# DLL loads and executes, then the Stop() method throws a HRESULT=0x8000ffff error. I've looked for hours and all the code looks like what I have below (I left out all my debugging/error handling). Thank you very much for any tips in advance! =)
void DotNetLoad()
{
ICLRRuntimeHost *pClrHost = NULL;
ICLRMetaHost *lpMetaHost = NULL;
MessageBox(0, L"Creating CLR instance.", L"Bootstrap Message", 0);
HRESULT hr = CLRCreateInstance(
CLSID_CLRMetaHost,
IID_PPV_ARGS(&lpMetaHost));
ICLRRuntimeInfo *lpRuntimeInfo = NULL;
hr = lpMetaHost->GetRuntime(L"v4.0.30319",
IID_PPV_ARGS(&lpRuntimeInfo));
hr = lpRuntimeInfo->GetInterface(
CLSID_CLRRuntimeHost,
IID_ICLRRuntimeHost,
(LPVOID *)&pClrHost);
hr = pClrHost->Start();
DWORD dwRet = 0;
hr = pClrHost->ExecuteInDefaultAppDomain(
pwzTargetDll,
pwzNamespaceClass, pwzFunction, L"pwzArgument", &dwRet);
hr = pClrHost->Stop();
hr = pClrHost->Release();
}
I understand the bit about decoupling the init, .NET call, and deinit, but what do you mean by app startup and shutdown? Right now I have DotNetLoad being called from a DLL method that is injected into a remote process. Basically:
extern "C" __Declspec(dllexport) void Initialize()
{
DotNetLoad(params); //ex.
}
By combining runtime init with the assembly method call, followed by runtime deinit, you are executing this code on every call to DotNetLoad().
See the important block here. This leads me to believe that once you load the runtime into your process you don't want to do it again.
Split your initialization / deinitialization out of the method used to call the .NET assembly. Do the initialization only once (at app startup and prior to making the call), and do the deinitialization only once (at app shutdown). I tested this and it worked without error.

How to pass an interface pointer to a thread?

Note:
Using raw Win32 CreateTheard() API
No MFC
An interface is simply a pointer to a vtable
Question:
How to pass an interface pointer to a thread?
Illustration:
IS8Simulation *pis8 = NULL;
...
CoCreateInstance(
clsid,
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IS8Simulation),
(void **) &pis8);
...
hThread = CreateThread(
NULL,
0,
SecondaryThread,
//interface pointer pis8
0,
&dwGenericThreadID);
...
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
//using iValue accordingly
//E.g.: iValue->Open
Regards
As was stated below, passing a COM interface pointer between threads in not safe.
Assuming you know what you are doing:
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) pis8
0,
&dwGenericThreadID);
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
((IS8Simulation*) iValue)->Open();
}
Thread safe version:
void MainThread()
{
IStream* psis8;
HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8);
if (FAILED(res))
return;
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) psis8
0,
&dwGenericThreadID
);
}
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
IS8Simulation* pis8;
HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8);
if (FAILED(res))
return (DWORD) res;
pis8->Open();
}
If the interface in your question is a COM interface, the approach given by Quassnoi might not be sufficient. You have to pay attention to the threading-model of the COM object in use. If the secondary thread will join a separate COM apartment from the one that your COM object was created in, and if that object is not apartment-agile, you'll need to marshal that interface pointer so that the secondary thread gets a proxy, and not a direct pointer to the object.
A COM object is normally made apartment-agile by using a special implementation of IMarshal. The simplest approach is to aggregate the Free Threaded Marshaler.
Some useful links...
CoMarshalInterThreadInterfaceInStream
GlobalInterfaceTable (GIT)
CoCreateFreeThreadedMarshaler
Update: About the Free-threaded Marshaler...
It's clear from comments on this topic that some people would recommend that you never touch the FTM. While "Effective COM" is an excellent book, I think some of its recommendations are open to interpretation. Item 33 says "Beware the FTM"; it does not say "Never use the FTM". Very wisely it advises caution particularly when your apartment-agile object holds references to other objects, because they might not be apartment-agile. So really the advice is: think carefully when building apartment-agile objects, whether or not they use the FTM to achieve their agility. If you're sure you can build an apartment-agile object, I see no reason why you wouldn't use the FTM to achieve that.
You basically need to do the following:
CoMashalInterThreadInterfaceInStream ==> you get an IStream interface.
pass that IStream to the thread, e.g. as Quassnoi said.
in SecondaryThread, call CoGetInterfaceAndReleaseStream to get the interface (or a proxy to it, if necessary).
Do not release the IStream interface unless creating the thread fails, and don't exit the thread until yu have called CoGetInterfaceAndReleaseStream.
COM runtime will create the proxy for you automatically. The proxy ensures that e.g. an apartment-threaded COM component is called on the thread that created it. However, this also requires that:
The interface is IDispatch, or proxy/stub components are registered for the interface
the threadthat created the component has a message loop and processes messages