Where do I need to call CoInitialize in the C++ REST SDK? - c++

I need to call some COM APIs from a simple REST server using the REST SDK. It's similar to the BlackJack sample code.
Whenever I try to create a COM object I get an exception that CoInitialize has not been called. But where exactly can I initialize the thread that processes the REST request? I couldn't find any documentation.
I tried the constructor (BlackJackDealer in the sample) but that does not work:
BlackJackDealer::BlackJackDealer(utility::string_t url) : m_listener(url)
{
CoInitialize(0);
...
}

Tasks in the C++ REST SDK execute on the Windows Threadpool by default. Instead of trying to join threadpool threads to an STA (which should be considered an anti-pattern), you can either:
Specify a custom scheduler (deriving from pplx::scheduler_interface) when creating tasks that need to call COM methods. See pplxinterface.h for the interface declaration and windows_scheduler::schedule() inside pplxwin.cpp for how the default scheduler is implemented on various Windows flavors.
Manually marshall any COM interactions to a thread that you own and control (and have called CoInitialize on). This probably means something like having a global vector of std::function objects that you protect with the usual mutex/condition_variable dance.
You may need to perform manual marshalling even if you go the custom scheduler route, but the custom scheduler will interoperate better with the existing task-based APIs.

Related

Why use CoInitialize(0); in C++

I have been writing a C++ program where I am creating a shortcut link for an exe file, and to do that I need to write the CoInitialize(0); at the starting. And without it the code does not work. Can someone help me to know why we use it?
I just want to know why we use this function.
CoInitialize(), and the extended and more recommended version CoInitializeEx(), are used to initialize the COM library for the current thread:
Initializes the COM library on the current thread
...
New applications should call CoInitializeEx instead of CoInitialize.
It has to be called for each thread that uses COM.
Note that CoInitialize() identifies the concurrency model as single-thread apartment (STA), whereas with CoInitializeEx() you have the freedom to specify the concurrency model.
More about COM threads and other related issues: Processes, Threads, and Apartments.
In case you are not familiar with COM (from the documentation):
COM is a platform-independent, distributed, object-oriented system for creating binary software components that can interact. COM is the foundation technology for Microsoft's OLE (compound documents) and ActiveX (Internet-enabled components) technologies.
If your program requires calling one of the initialization functions above, it means that either you directly, or any library you use, are using COM.
Note that each successful call to CoInitialize/Ex() must be matched with a call to CoUninitialize().
Edit:
As #IInspectable commented, using a COM object on a thread does not strictly require calling CoInitialize/Ex().
But, since COM objects have threading requirements as noted above, calling it ensures that the current thread uses the proper COM concurrency model.
See Why does CoCreateInstance work even though my thread never called CoInitialize? The curse of the implicit MTA.

Share asio::io_context with dll?

I have an application that imitates state of a vehicle and uses various plugins to transmit data. Each plugin is loaded dynamically and provides protocol-specific implementation for an interface to send the data. By specification each plugin may be operating concurrently and a sending method may be asynchronous.
I would like to be able to share asio::io_context or asio::thread_pool to utilize those resources allocated by the application (core). Each plugin would use asio::strand if needed. I really wouldn't want plugins to spawn new threads.
To provide compiler independence the API for a plugin is in C, hence I can't pass asio entities just like that.
Is it possible though to expose a context or a thread pool to a dynamically loaded dll which may be compiled with another toolchain?
Maybe via some kind of native handles?
Maybe I could wrap a custom executor?
I didn't find any constructors in the reference which would use native handles, etc.

Use COM STA or MTA Without Shared COM Objects?

This thread is great at explaining STA vs MTA for COM, however it doesn't address how to code for such or when to use one or the other, and only just discusses technicalities about COM apartments being used by thread-safe objects or not. I'd be willing to bet most users just want to know how to use the Win API through COM without any COM objects shared among multiple threads.
Should you use STA always if your COM objects aren't shared among threads, and your code makes use of multiple threads or a single thread each with its own COM object instances, none of the objects shared? Does it depend on the object you are using? If you don't always use STA for such when do you use MTA? Do you ever need a message pump in this case?
In my case I use the Task Scheduler API (ITaskService) and the Shell Links/Create Shortcut API (IShellLink) from the main GUI thread (using the Qt Framework), and the File Operation API (IFileOperation) and the Volume Shadow Copy Service API from a worker thread.
I call CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); from each thread before initializing and using the COM objects and CoUninitialize(); after. Is this proper usage of COM? Would the same apply using COM objects from the main GUI thread without a worker thread?
For making outbound COM calls to objects that you instantiated via CoCreateInstance, STA should be good enough, and is almost a must for your GUI thread (the one that has a GetMessage/DispatchMessage loop).
MTA starts to become relevant when hosting your own thread safe COM objects that are expected to be invoked from other processes.
The documentation for IFileOperation states this:
IFileOperation can only be applied in a single-threaded apartment
(STA) situation. It cannot be used for a multithreaded apartment (MTA)
situation. For MTA, you still must use SHFileOperation.
See all, this link: INFO: Calling Shell Functions and Interfaces from a Multithreaded Apartment
I suspect what the documentation is really trying to say is this:
The class implementing IFileOperation is not thread safe
It's ThreadingModel is declared "apartment" in the registry and will incur marhsalling overhead if accessed from an MTA thread.
On our application, have used ITaskScheduler on the main STA thread. And we use IFileOperation on a background STA thread that has its own message pump.
Some other links that I think are very useful:
https://support.microsoft.com/en-us/help/150777/info-descriptions-and-workings-of-ole-threading-models
https://devblogs.microsoft.com/oldnewthing/?p=22603

Accessing the C++ COM dll from Webservice

I am using a COM dll from a web service.
The COM dll is added as reference. And I am declaring the object as static in Global.asax.
I am creating the COM object in the Application_Start.
I have to call the COM dll interface function in each request.
I am getting exceptions here as memory corruption.I could see the logs that it happens when simultaneous requests come up.
Please let me know what is the best way to do that. How to make it thread safe.?
Try creating a new instance in each request and not use application scope for the object.
If you are accessing it at application scope(eg through Application_Start) you will need to make sure it is safe for multithreading. I don't know how C++ dlls handle threading but you might be able to manage multithreading at the asp.net level.
For example To manage a simple application level counter the code is something like:
Application.Lock();
Application["SomeGlobalCounter"] =
(int)Application["SomeGlobalCounter"] + 1;
Application.UnLock();
For more information you might want to see the MSDN page on Application State.
If the COM object is apartment threaded, COM provides the synchronization to enforce a single execution of a method per thread.
Generally, though, COM should be complaining of multiple threads trying to access an instance of an object using the same pointer shared across threads. Having a static variable holding a pointer to the object is probably a bad idea.
Once the COM object shared library is loaded somewhere (in-proc or out-of-proc) by creating an instance, creation of additional instances per thread should be fairly quick. That is, of course, dependent on what types of things that are being done during object construction.

Can an out-of-process COM object determine its parent process?

From an out-of-process COM object (LocalServer32) can I determine the client process that requested the creation of the object? - to be specific I need to get hold of the client processes command line.
This question arrises because (due to poor standardisation, implementation and support) the potential 3rd party clients of the object have a variety of idiosyncracies which the object needs to workaround.
To do this the object needs to be able to identify its current client.
Extending the interface of the COM object so that the client can identify itself is unfortunately not possible ... or to be more precise the interface can be extended but I won't be able to get the clients to call the extension.
Having looked into this further I suspect the answer is going to be "NO", but by all means tell me I'm wrong.
Using Process Explorer I can see that the parent process for my COM object is an instance of "svchost.exe", and not the client application.
Because COM server processes are shared by all clients of the same AppID, it's not possible to actually get the PID of the client application. As #Anders said, you can use CoImpersonateClient (or, better, call CoGetCallContext and interrogate the resulting IServerSecurity) to find the account and login session of the caller, but you cannot get the process itself.
If you are trying to work around bugs in legacy clients, I would recommend you create a new set of CLSIDs (or IIDs, if you can emulate all the bugs the legacy clients rely on with shims) for new (non-legacy) clients with VERY strict input validation, and implement new features only in these new CLSIDs. Legacy clients stick with their older CLSID, in which you can simply use the existing, legacy implementation (or a bug-for-bug compatible clone).
Maybe CoImpersonateClient()