Are IShellWindows and IWebBrowser2 objects always out of process? - c++

I've been experimenting with instantiating CLSID_ShellWindows, and so far I've had luck only when using CLSCTX_LOCAL_SERVER. Even when I try creating it from within Explorer itself (after setting a hook and injecting a DLL), it works only when instantiated as an out-of-process object.
I was wondering if it's ever possible to obtain an in-process version of the shell windows and their related objects. Like for example, if you implement a browser helper object or Explorer toolband, and you obtain an IWebBrowser2 object/interface using the site pointer provided through SetSite, will that be an in-process object, or is that out of process as well?

Related

Use _COM_SMARTPTR CreateInstance without Registration within the same DLL

I'm currentyl trying to write a DLL which consumes a Typelib (.tlb) registered in the system. This Typelib requires that I implement two interfaces with my own classes, and register one of them within the Running Object Table, which I did in an ATL project using Visual Studio 2015.
The Application that consumes my DLL should have no knowledge of COM at all, everything should work there behind the scenes and hidden by the DLL I'm implementing.
Within my DLL, at some point I'm trying to get Instances of a clas MyClass which implements the above mentionend COM-Interfaces of the Typelib. The code looks like this:
IInterfaceClassPtr dataPtr;
hr = dataPtr.CreateInstance(CLSID_MyClass);
IInterfaceClassPtr is actually a Macro (all of this is generated by Visual Studio), which looks like this:
_COM_SMARTPTR_TYPEDEF(IExampleInterface, __uuidof(IExampleInterface));
IExampleInterface is defined in the Typelib I consume, and implemented by MyClass.
If I'm registering my own DLL using regsvr32, everything works fine. But I want to avoid that because it requires Admin privileges.
If my DLL is not registered, the above call fails with HRESULT "0x80040154, Class is not registered". I read the article Registration free activation of COM-Components (And a few others). But I can't tweak the consuming applications' manifest here - the class (MyClass) I'm trying to activate lives in the very same DLL as the mentioned "CreateInstance" call.
What do I need to do to be able to Create Instances of these Classes without using regsvr32 or some Manifest-Tweaking?
You can create concrete instances of your objects directly within your DLL (assuming the classes are implemented there).
CComObject<CMyClass>* pMyClassPtr;
CComObject<CMyClass>::CreateInstance(&pMyClassPtr);
pMyClassPtr->AddRef();
CComObject<T>::CreateInstance creates an instance of a COM object by directly calling new CComObject<T> so it bypasses the registry.
You can then use QueryInterface on the object to get your required interface.
IInterfaceClassPtr spIInterface;
pMyClassPtr->QueryInterface(&spIInterface);

C++ Unable to get Async DragDrop functioning correctly

We currently have a Silverlight UI (which we are unable to change from at this stage) for our system, which has very limited drag drop capabilities. We are currently running out of browser with elevated trust. So in order to handle Silverlight's shortcomings I have created a c++ com library in order to handle Drag Drop events. This works perfectly well for incoming events from other applications, however I'm struggling to get the Drag operations, with our app as the source, working correctly. Most of the files to be dragged from the app will be virtual, which I have managed to get working however regardless of everything I've tried I have been unable to get the operation to be asynchronous, and the app locks up during the process.
I initially implemented only the IAsyncOperation (need backward compatibility to xp), which had no apparent affect. My DataObject is queried for the interface, gets the ref. A Call to GetAsyncMode is made, which returns VARIANT_TRUE, and a call to StartOperation is made. However all operations are done on the same thread (ui thread) and no async seems to be in affect.
I Subsequently tried implementing ICallFactory to return an AsyncIDataObject. Here explorer seems to check for the ICallFactory interface, calls the CreateCall on the call object and queries it to make sure it has the correct interfaces. Using the symbol servers I am able to see that it this occurs in the AsyncStubInvoke call stack. From here a call to StdStubBuffer_QueryInterface is made which is searching for the ICallFactory interface. This check fails and I unfortunately cannot see what object is being checked for this interface. After this fails the call seems to fall back to SyncStubInvoke after an operation not supported error (following from the Interface not supported error). All of this too seems to have no effect on the end result and the call is still apparently synchronous with the source app locking up.
My DragDrop class which exposes the com calls is CComMultiThreadModel. I have tried using my DataObject as a basic class not inheriting from CComObjectRootEx and a wrapper IDataObject class which is defined in the IDL as well and does inherit from CComObjectRootEx as is also CComMultiThreadModel. I have also tried having this class inherit from IDispatch as well as IUnknown.
Any feedback would be greatly appreciated.

COm server accessing the application

I have written a simple dialog based MFC application using a thirdd party soft tree control. I am trying to write a automation client for the application. For this I wrote a singleton out-of-process COM Testing Agent for the dialog based application sample app. The Com server exposes a Run method to the automation client. This Run method access the gut of the mfc app and actually mimicks a click on the GUI. The problem i am facing is when the automation client tries to invoke Run method on the Com object it is able to invioke it but when the Run method crashes when it tries to access the control's methods such as getCaretInedx.
I have tried to cach the exception and log the message to a file but have not been able to do so.
My question is: Is there any limitation in the way a com object can access the application? Or am i missing anything to facilitate this.
Any help or pointer is greatly appreciated. Since this is my first in COM I have not been able to make much progress.
Thanks
Is your client's window actually being created? If not, the hwnd doesn't exist, which is probably why it crashes. Furthermore, your client may be hidden behind another window when it is started, and may exhibit different behavior than when the user called it through regular interaction.
In general, calling code that relies on or interacts with the UI from a COM server is fraught with peril, especially when that code is not written in the first place to behave like this. Most UI isn't that defensive about HWND's existing etc.

Reusing the web browser control

I have a pure Win32 application (no MFC, etc.) to which I want to add a web browser control in a window. I know the basics of COM and can create a COM object for the browser using
hr = CoCreateInstance(
CLSID_WebBrowser,
NULL,
CLSCTX_INPROC,
IID_IWebBrowser2,
(void**) &pWebBrowser);
However, apparently one needs to call SetClientSite, passing an IOleClientSite*. How do I obtain such an interface? This example implements its own browser class, which provides the interface by deriving from it and implementing it (here). I tried to go along that path, but in order to instantiate the browser class, I would have to register it (no?). This seems awfully complicated - I just want to use an existing COM object, not implement and register my own. What am I missing?
Assuming I do implement my own ClientSite class as part of my application, is it possible to not register it, and just instantiate it by calling new ClientSite (and then fetch the interface as using QueryInterface)? Will this work, or is it mandatory to call CoCreateInstance?
There is an example on CodeGuru and another on CodeProject which contains the simplest implementation for hosting a web browser control implemented in pure C. You do have to implement your own IOleClientSite, but it is one of the easier classes to implement. Yes, it is mandatory to call CoCreateInstance or OleCreate to create the instance of the web browser control.
http://www.codeguru.com/cpp/i-n/ieprogram/article.php/c4379/Display-a-Web-Page-in-a-Plain-C-Win32-Application.htm
http://www.codeproject.com/Articles/3365/Embed-an-HTML-control-in-your-own-window-using-pla
Try WTL (header only library from MS). Install its project templates. Create a new WTL project from template and select "web browser" control option (or whatever is the name). Now you can investigate generated sources or (my personal recommendation) move your stuff into this project
I'm not sure what exactly you're trying to do ...
... but I'd start by trying to use a simple ShellExecute(), if at all possible:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx
http://support.microsoft.com/kb/224816

COM & CoGetClassObject()

I have a little problem with CoGetClassObject().
I have an application which must use some DLLs of a specific version,
but they are also present in the system, in a more recent version.
So I start hooking the CoCreateInstance() and loadLibrary(), which I guess are good.
The problem is that the DLLs in the two versions are loaded.
So I think that CoGetClassObject() is the problem/solution because it provides a pointer to an interface of an object associated with a CLSID containing a DLL that the application must use in an older version.
But I don't know what this function "does", so how can I "override" this function ?
thanks.
PS : I'm new in the COM programming.
CoGetClassObject() simply does half the job that CoCreateInstance() does. It returns a class factory. CoCreateInstance() then call IClassFactory::CreateInstance() and releases the IClassFactory. You would only use it if you have a need to create many objects of a certain coclass and want to optimize that. It avoids the cost of creating and releasing the factory over and over again.
You are possibly overlooking a far simpler solution to this problem. You can simply copy the new version of the COM server DLL into the same directory as the client EXE. And create a zero byte file with the name "app.exe.local" where "app" is the name of the EXE. That's enough to force that copied DLL to be loaded instead of the one that the registry points to. The MSDN Library article about DLL redirection is here.
The very simple explanation is CoGetClassObject() opens HKCR\CLSID\{ClassId} and looks at InProcServer32 or LocalServer32 depending on what CLSCTX_* value is passed - that is the COM server path.
Once it find a COM server file path is loads (LoadLibraryEx() with LOAD_WITH_ALTERED_SEARCH_PATH flag in case of in-proc or CreateProcess() in case of out-proc) the COM server. Then it locates and calls DllGetClassObject() for in-proc servers or waits until a class factory is registered for out-proc servers.
This of course ignores stuff like DCOM etc. You can get a better idea of how it traverses the registry using Process Monitor utility.
If you want to load a specific COM DLL regardless of whether there is a newer version installed, and regardless of where the older DLL is located, then simply ignore CoCreateInstance() and CoGetClassObject() altogether. Load the older DLL yourself via LoadLibrary(), then call its exported DllGetClassObject() function directly to get the DLL's IClassFactory interface, then call IClassFactory::CreateInstance() as needed. This is all CoCreateInstance() and CoGetClassObject() do internally anyway, but this bypasses the Registry lookups they perform to determine the DLL path to load.