How to use IGlobalInterfaceTable to pass an interface pointer? - c++

Without:
MFC
ATL
Question:
What are the steps involved, to use IGlobalInterfaceTable, when passing a particular interface pointer to several threads using CreateThread?

I think this page covers it rather well.
Call RegisterInterfaceInGlobal to put your COM interface in the GIT, pass its cookie to your other threads, which can then call GetInterfaceFromGlobal using that cookie to get the original interface.
Note that each thread has to call CoCreateInstance(CLSID_StdGlobalInterfaceTable... but don't worry, they all get an interface pointer to the same instance of the GIT.

Related

Passing 'this' pointer to MouseProc of SetWindowsHookEx

Generally, whenever we want to wrap a Window/Thread in a C++ object, we do so by passing the this pointer via SetWindowLong/GetWindowLong or SetProp/GetProp for a Window, and as lpParameter for CreateThread/etc.
My question is specific to Hooks. What is the elegant approach to pass the 'this' pointer to SetWindowsHookEx's callback procedures, or in other words How to wrap a hook's callback procedure ?
Since SetWindowsHookEx does not accept any UserData argument, I don't see much options apart from using un-encapsulated i.e. global/static/TLS data.
You are expected to have just one instance of a given hook, so global data is not an issue.
If you are developing a library allowing multiple hook instances that can be dynamically added or removed, do not add multiple hooks at the OS level. Instead, add a library-level hook procedure that walks the list of hook instances. Since you maintain this list, you can track whatever "user data" alongside each entry you want.
The 'most elegant approach' is to use a thunk. It's a small piece of code generated at runtime that holds your this pointer. This is the approach that ATL uses even for regular windows.
See
What is a thunk?
How to generate the code for thunks
C++ WinAPI Wrapper Object using thunks (x32 and x64)

Check pointer handle is valid

I want to implement a Microsoft CryptographicServiceProvider library and currently I thinking about the best way how to deal with context handle which I create.
My question is specific to this case but the design approach can be used in other situations.
I come from a managed code background and I am not 100% shure about multithread pointer handling in C/C++.
In general there are two functions which are responsible for handle creation and destruction (CryptAcquireContext, CryptReleaseContext), and all subsequent CSP functions uses the handle which is return by the creator function.
I didn't found any concrete information or specification from Microsoft which gives a design approach or rules how to do it. But I did research with other CSP providers created by Microsoft to find out the design rules, which are:
The functions must be thread safe
The context handle will not be shared between threads
If a context handle is not valid return with an error
Other MS CSP Provider will return a valid pointer as handle, or NULL if not.
I don't think that the calling application will pass complete garbage but it could happen that it passes a handle which has been already released and my library should return with an error.
This brought me to three ideas how to implement that:
Just allocate memory of my context struct with malloc or new and return the raw pointer as handle.
I can expect that the applications which call my library will pass a valid handle. But if not my library will run into an undefined behaviour. So I need a better solution.
Add the pointer which I create to a list (std::list, std::map). So I can iterate the list to check if the pointer exists. The access to the list is guarded with a mutex.
This should be safe and a regular API usage shouldn't be a performance issue. But in a Terminal Server scenario it could be. In this case the Windows process lsass.exe creates for every user who wants to login a CSP context in a separate thread and makes around 10 API calls per context.
The design goal is that my library should be able to handle 300 clients parallel. I don't know how many threads a created by Windows in this case.
So if possible I would prefer a lockless implementation.
I allocate a basic struct which holds a check value and the pointer of the actual data. Use the pointer of this struct as context handle.
typedef struct CSPHandle
{
int Type; // (eg. magic number CSPContext=0xA1B2C3D4)
CSPContextPtr pCSPContext;
};
So I could read the first byte of the passed pointer and check if the data equals my defined type. And I have the full control about actual data pointer, which is set to NULL if the context is released. Is this a good or bad idea?
What are your thoughts about this case? Should I go with one of these approaches or is there a other solution?
Thanks
I found a solution and will answer my question.
I overlooked a little but important detail
In CSP there are not direct API calls to the dll (load library, get function pointer, call function) because the function calls are forwarded by the Microsoft CSP which loads the CSP library by name.
So the Microsoft CSP needs to know and to check the passed context to get a correct mapping to the specific library.
Example:
1. client->cryptacquirecontext(in cspname, out ctx)
2. MS CSP->loads libray from the cspname
3. MS CSP->calls the function pointer of the loaded library
4. CSP LIB->cryptacquirecontext creates new context
5. MS CSP->receives the returned csp handle and saves it to the dll mapping
6. MS CSP->returns the result to the calling application
7. client->cryptsetprovparam(ctx) // which was created before
8. MS CSP->checks if the context exists and which library is responsible
9. MS CSP->if the given context can not be mapped to a csp dll an error will be returned, because the MS CSP doesn’t know which function pointer should be called.
So in this case it should be sufficient just to allocate memory. If the client application passes invalid context handle it will never hit the csp library.
I think that the MS CSP uses a list with mutex guard to store the context mappings. Because the context can be anything from a random number to a valid pointer.

From a COM Service EXE gets started

I'm trying to program my first COM Service EXE. And I'm can't to find some informations in the Net.
A Service EXE starts executing from its Run() method, do I need to implement my main functions in it to get my service works or do I need to implement a specific function that is related to it?
Thank you so much !!
You have not stated that you are using C++ and ATL, but it can be guessed from the tags given to the question.
If your COM objects do not need any global initialization, you do not have to modify the provided Run() function or anything similar. It works like this: If the service is not running, and some program requires a COM object from your service be created, the COM/DCOM infrastructure first starts the service. Alternatively, you can pre-start the service using any standard means (e.g. manually, or set its startup type to Automatic). Once the service is running, the COM objects are created within the service.
So, without a need for extra global initialization, you simply implement your COM objects as in any local server or in-process server. If they need any instance initialization, you will put it into the constructor of the COM object, or to its FinalConstruct method (this method gets called after the constructor, so you have take advantage of the fact that the object already exists, AND you can also fail it if needed, as FinalConstruct returns an HRESULT).
If you need a global (service-wide) initialization code, then you can put it into several places, each at different stage of the service construction. One of such places would be the Run() method, yes.

C++ multi threading data structure for communication between two threads

I have a thread that calls various APIs of a COM interface. Now I want to invoke these functions from another thread. Can you please advise how I can achieve this?
How can I implement the communication between these two threads? If I define a Message queue sort of data structure which is common for these two threads then how do I define a common data structure as the parameters are different for each COM API.
Thanks in advance
The typical way is to use callbacks. You pass your data round via pointer. You can either use polymorphism to override the method that the base class calls when you pop it off the queue. Base calls function x, you override function x in derivative classes to achieve what you want.
Another way is to use plain old callbacks. You pass the address of your function onto a queue along with any data you need, wrapped up cleanly in a struct. All of the callbacks must have the same signature, so you'll probably need to cast your data to void.
You don't define one common data structure. There is a different data structure for each different function signature. Only common thing between those structures is identifier of the function. In your thread you'll have giant switch (or std::map) that would translate function identifier to function itself. After that you know how to interpret the rest of the structure. The structures should have POD semantic.
If each thread is running as a single-threaded apartment then you can make calls on the required APIs from a remote thread by marshalling its interface pointer as an IStream from the object's owning thread to the other thread via CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream. Once the remote thread has an interface pointer, you can make calls on it directly.
You might also be able to do this more simply using the Global Interface Table, depending on your app's threading model. This would be the easiest way.

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.