COm server accessing the application - mfc

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.

Related

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.

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

How do I release an InMemoryWorkspaceFactory in the ESRI Map Control?

I am embedding the ESRI Map Control into a custom ActiveX control written in MFC/C++. The custom ActiveX control serves as a Map Control wrapper so I can embed it into a specific environment that is runtime only and non-relational. Thanks to this site, I am able to load feature points into an in-memory workspace. However, the hosting environment now gets stuck in memory when closed, and it only does this when I am using the InMemoryWorkspaceFactory. My conclusion, therefore, is that the factory has locked a file or resource and, by not releasing it, is causing the host environment to never close.
Is there a way I can manually delete all features and feature classes during my ActiveX control's WM_DESTROY message and release the workspace completely? There doesn't seem to be a counterpart to the IWorkspaceFactory's Create method. My code is releasing all interfaces to the workspace factory, but apparently there are still references internally in ArcObjects.
I discovered the answer to my question. It wasn't the in-memory workspace that needed to be closed, it was ArcObjects in general. The solution is to make sure to call the Shutdown method of the IAoInitialize interface during the WM_DESTROY message.

C++ hook process and show status

Ok so I am learning C++ slowly. I am familiar with all the console syntax and everything, but now I'm moving on to windows programming. Now what im trying to do, is create a DLL that I inject into a process, so it's hooked in. All I want the C++ application to do, is have text in it, that says "Hooked" if it's successfully injected, and an error if something wrong happened. Or even if I can do it without a DLL, Just open an executable, and when the certain process I'm trying to hook is opened, the status is changed to "Hooked". Also I have a safaribooksonline.com account so if there is any good reads you would recommend, just write it down. thanks
I think you might be looking at this backwards. In C/C++ an application 'pulls' a DLL in rather than having a DLL 'injected' into an application. Typically for plugins/hooks, there is some mechanism to inform an application of a DLL's availability (often just its presence in a specific directory) and a configuration file or some other logic is used to instruct the application to explicitly load the library, extract a function or two, and call them.
For Windows programming, I'd suggest doing a search for examples of the LoadLibrary() API call. You'll likely find a tutorial or two on how to do it.
If by "hooked" you mean, "have my DLL run in that processes' address space", you want CreateRemoteThread(). This is fairly advanced and difficult to debug, because your bugs make the other program crash. It's how a lot of malware works, by the way.
If you mean "have my DLL get notified of activity in the other process", you want SetWindowsHookEx().
Sounds like you want to inject as soon as the application starts? You can do that with Microsoft's Detours DetourCreateProcessWithDll(). Example here.

MSHTML IWebBrowser2 - Sinking page events causes missed keystrokes?

I've got a bit of a problem with my application using MSHTML. I have everything working except for the odd keystroke missing behavior when typing fast as mentioned in the subject line. I think it may have to do with the method I use to sink the events?
The details: my application is a separate program written in C++ and MFC in Visual Studio 2005. The program attaches to a currently running (independent) instance of Internet Explorer and gets the pointer to the IWebBrowser2 interface and passes it to an object of type CCmdTarget:
class CHandler : public CCmdTarget
{
IWebBrowser2* m_pWebBrowser2;
DWORD m_dwBrowserCookie;
…
DECLARE_DISPATCH_MAP()
};
This class keeps track of what's happening in the browser. I sink the browser events with the following command:
LPUNKNOWN pUnkSink = GetIDispatch(FALSE);
retval = AfxConnectionAdvise((LPUNKNOWN)m_pWebBrowser2, DIID_DWebBrowserEvents2, pUnkSink, FALSE, &m_dwBrowserCookie);
If I comment out the AfxConnectionAdvise, then no keystrokes are missed but no more events. If I leave it in I sink the events but miss the occasional keystroke if typing fast.
I know there are a number of ways of connecting to the events (AtlAdvise, connection points), but this was the only one I could get working.
Any suggestions would be great!
If you're just looking for keystrokes, can't you subclass the control?
Underneath the covers all the various connection methods (AtlAdvise, AfxConnectionAdvise, etc) all use IConnectionPointContainer and IConnectionPoint — they're just saving you typing boilerplate COM goo.
I suspect this has to do with how you're connecting to the running instance of IE. How are you getting the IWebBrowser2 pointer? Are you being loaded into the IE process or are you a separate process? If you're running on a different thread than the IWebBrowser2's original thread (the IE Tab UI thread), are you doing proper COM marshalling?