1 #include "wxActiveX.h"
2 #include <wx/strconv.h>
3 #include <wx/event.h>
4 #include <oleidl.h>
5 #include <winerror.h>
6 #include <idispids.h>
7 #include <exdispid.h>
8 #include <olectl.h>
9 #include <Mshtml.h>
10 #include <sstream>
11 using namespace std;
12 
13 // Depending on compilation mode, the wx headers may have undef'd
14 // this, but in this case we need it so the virtual method in
15 // FrameSite will match what is in oleidl.h.
16 #ifndef GetObject
17     #ifdef _UNICODE
18         #define GetObject GetObjectW
19     #else
20         #define GetObject GetObjectA
21     #endif
22 #endif
23 
24 
25 //////////////////////////////////////////////////////////////////////
26 BEGIN_EVENT_TABLE(wxActiveX, wxWindow)
27     EVT_SIZE(wxActiveX::OnSize)
28     EVT_PAINT(wxActiveX::OnPaint)
29     EVT_MOUSE_EVENTS(wxActiveX::OnMouse)
30     EVT_SET_FOCUS(wxActiveX::OnSetFocus)
31     EVT_KILL_FOCUS(wxActiveX::OnKillFocus)
32 
33 END_EVENT_TABLE()
34 
35 class wxActiveX;
36 
37 class FrameSite :
38     public IOleClientSite,
39     public IOleInPlaceSiteEx,
40     public IOleInPlaceFrame,
41     public IOleItemContainer,
42     public IDispatch,
43     public IOleCommandTarget,
44     public IOleDocumentSite,
45     public IAdviseSink,
46     public IOleControlSite
47 {
48 private:
49     DECLARE_OLE_UNKNOWN(FrameSite);
50 
51 public:
52 	FrameSite(wxActiveX * win);
53 	virtual ~FrameSite();
54 
55 	//IOleWindow
56 	STDMETHODIMP GetWindow(HWND*);
57 	STDMETHODIMP ContextSensitiveHelp(BOOL);
58 
59     //IOleInPlaceUIWindow
60 	STDMETHODIMP GetBorder(LPRECT);
61 	STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS);
62 	STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS);
63 	STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject*, LPCOLESTR);
64 
65     //IOleInPlaceFrame
66 	STDMETHODIMP InsertMenus(HMENU, LPOLEMENUGROUPWIDTHS);
67 	STDMETHODIMP SetMenu(HMENU, HOLEMENU, HWND);
68 	STDMETHODIMP RemoveMenus(HMENU);
69 	STDMETHODIMP SetStatusText(LPCOLESTR);
70 	STDMETHODIMP EnableModeless(BOOL);
71 	STDMETHODIMP TranslateAccelerator(LPMSG, WORD);
72 
73 	//IOleInPlaceSite
74 	STDMETHODIMP CanInPlaceActivate();
75 	STDMETHODIMP OnInPlaceActivate();
76 	STDMETHODIMP OnUIActivate();
77 	STDMETHODIMP GetWindowContext(IOleInPlaceFrame**, IOleInPlaceUIWindow**,
78 		LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO);
79 	STDMETHODIMP Scroll(SIZE);
80 	STDMETHODIMP OnUIDeactivate(BOOL);
81 	STDMETHODIMP OnInPlaceDeactivate();
82 	STDMETHODIMP DiscardUndoState();
83 	STDMETHODIMP DeactivateAndUndo();
84 	STDMETHODIMP OnPosRectChange(LPCRECT);
85 
86     //IOleInPlaceSiteEx
87 	STDMETHODIMP OnInPlaceActivateEx(BOOL*, DWORD);
88 	STDMETHODIMP OnInPlaceDeactivateEx(BOOL);
89 	STDMETHODIMP RequestUIActivate();
90 
91 	//IOleClientSite
92 	STDMETHODIMP SaveObject();
93 	STDMETHODIMP GetMoniker(DWORD, DWORD, IMoniker**);
94 	STDMETHODIMP GetContainer(LPOLECONTAINER FAR*);
95 	STDMETHODIMP ShowObject();
96 	STDMETHODIMP OnShowWindow(BOOL);
97 	STDMETHODIMP RequestNewObjectLayout();
98 
99 	//IOleControlSite
100 	STDMETHODIMP OnControlInfoChanged();
101 	STDMETHODIMP LockInPlaceActive(BOOL);
102 	STDMETHODIMP GetExtendedControl(IDispatch**);
103 	STDMETHODIMP TransformCoords(POINTL*, POINTF*, DWORD);
104 	STDMETHODIMP TranslateAccelerator(LPMSG, DWORD);
105 	STDMETHODIMP OnFocus(BOOL);
106 	STDMETHODIMP ShowPropertyFrame();
107 
108 	//IOleCommandTarget
109 	STDMETHODIMP QueryStatus(const GUID*, ULONG, OLECMD[], OLECMDTEXT*);
110 	STDMETHODIMP Exec(const GUID*, DWORD, DWORD, VARIANTARG*, VARIANTARG*);
111 
112 	//IParseDisplayName
113 	STDMETHODIMP ParseDisplayName(IBindCtx*, LPOLESTR, ULONG*, IMoniker**);
114 
115     //IOleContainer
116 	STDMETHODIMP EnumObjects(DWORD, IEnumUnknown**);
117 	STDMETHODIMP LockContainer(BOOL);
118 
119 	//IOleItemContainer
120 	STDMETHODIMP GetObject(LPOLESTR, DWORD, IBindCtx*, REFIID, void**);
121 	STDMETHODIMP GetObjectStorage(LPOLESTR, IBindCtx*, REFIID, void**);
122 	STDMETHODIMP IsRunning(LPOLESTR);
123 
124 	//IDispatch
125 	STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*);
126 	STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**);
127 	STDMETHODIMP GetTypeInfoCount(unsigned int*);
128 	STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
129 
130 	//IAdviseSink
131 	void STDMETHODCALLTYPE OnDataChange(FORMATETC*, STGMEDIUM*);
132 	void STDMETHODCALLTYPE OnViewChange(DWORD, LONG);
133 	void STDMETHODCALLTYPE OnRename(IMoniker*);
134 	void STDMETHODCALLTYPE OnSave();
135 	void STDMETHODCALLTYPE OnClose();
136 
137     // IOleDocumentSite
138 	HRESULT STDMETHODCALLTYPE ActivateMe(IOleDocumentView __RPC_FAR *pViewToActivate);
139 
140 protected:
141 
142 	wxActiveX * m_window;
143 
144 	HDC m_hDCBuffer;
145 	HWND m_hWndParent;
146 
147 	bool m_bSupportsWindowlessActivation;
148 	bool m_bInPlaceLocked;
149 	bool m_bInPlaceActive;
150 	bool m_bUIActive;
151 	bool m_bWindowless;
152 
153 
154 
155 	LCID m_nAmbientLocale;
156 	COLORREF m_clrAmbientForeColor;
157 	COLORREF m_clrAmbientBackColor;
158 	bool m_bAmbientShowHatching;
159 	bool m_bAmbientShowGrabHandles;
160 	bool m_bAmbientAppearance;
161 };
162 
163 DEFINE_OLE_TABLE(FrameSite)
164     OLE_INTERFACE(IID_IUnknown, IOleClientSite)
165 
166     OLE_IINTERFACE(IOleClientSite)
167 
168     OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
169     OLE_IINTERFACE(IOleInPlaceSite)
170     OLE_IINTERFACE(IOleInPlaceSiteEx)
171 
172     //OLE_IINTERFACE(IOleWindow)
173     OLE_IINTERFACE(IOleInPlaceUIWindow)
174     OLE_IINTERFACE(IOleInPlaceFrame)
175 
176     OLE_IINTERFACE(IParseDisplayName)
177     OLE_IINTERFACE(IOleContainer)
178     OLE_IINTERFACE(IOleItemContainer)
179 
180     OLE_IINTERFACE(IDispatch)
181 
182     OLE_IINTERFACE(IOleCommandTarget)
183 
184     OLE_IINTERFACE(IOleDocumentSite)
185 
186     OLE_IINTERFACE(IAdviseSink)
187 
188     OLE_IINTERFACE(IOleControlSite)
189 END_OLE_TABLE;
190 
191 
wxActiveX(wxWindow * parent,REFCLSID clsid,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)192 wxActiveX::wxActiveX(wxWindow * parent, REFCLSID clsid, wxWindowID id,
193         const wxPoint& pos,
194         const wxSize& size,
195         long style,
196         const wxString& name) :
197 wxWindow(parent, id, pos, size, style, name)
198 {
199     m_bAmbientUserMode = true;
200     m_docAdviseCookie = 0;
201     CreateActiveX(clsid);
202 }
203 
wxActiveX(wxWindow * parent,wxString progId,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)204 wxActiveX::wxActiveX(wxWindow * parent, wxString progId, wxWindowID id,
205         const wxPoint& pos,
206         const wxSize& size,
207         long style,
208         const wxString& name) :
209     wxWindow(parent, id, pos, size, style, name)
210 {
211     m_bAmbientUserMode = true;
212     m_docAdviseCookie = 0;
213     CreateActiveX((LPOLESTR) (const wchar_t *) progId.wc_str(wxConvUTF8));
214 }
215 
~wxActiveX()216 wxActiveX::~wxActiveX()
217 {
218 	// disconnect connection points
219 	wxOleConnectionArray::iterator it = m_connections.begin();
220 	while (it != m_connections.end())
221 	{
222 		wxOleConnectionPoint& cp = it->first;
223 		cp->Unadvise(it->second);
224 
225 		it++;
226 	};
227 	m_connections.clear();
228 
229     if (m_oleInPlaceObject.Ok())
230 	{
231 		m_oleInPlaceObject->InPlaceDeactivate();
232 		m_oleInPlaceObject->UIDeactivate();
233 	}
234 
235 
236 	if (m_oleObject.Ok())
237 	{
238 	    if (m_docAdviseCookie != 0)
239     		m_oleObject->Unadvise(m_docAdviseCookie);
240 
241 	    m_oleObject->DoVerb(OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
242         m_oleObject->Close(OLECLOSE_NOSAVE);
243 		m_oleObject->SetClientSite(NULL);
244 	}
245 }
246 
CreateActiveX(REFCLSID clsid)247 void wxActiveX::CreateActiveX(REFCLSID clsid)
248 {
249 	//SetTransparent();
250 
251 	HRESULT hret;
252 
253     ////////////////////////////////////////////////////////
254 	// FrameSite
255     FrameSite *frame = new FrameSite(this);
256     // oleClientSite
257     hret = m_clientSite.QueryInterface(IID_IOleClientSite, (IDispatch *) frame);
258     wxASSERT(SUCCEEDED(hret));
259     // adviseSink
260     wxAutoOleInterface<IAdviseSink> adviseSink(IID_IAdviseSink, (IDispatch *) frame);
261     wxASSERT(adviseSink.Ok());
262 
263 
264 	// // Create Object, get IUnknown interface
265     m_ActiveX.CreateInstance(clsid, IID_IUnknown);
266 	wxASSERT(m_ActiveX.Ok());
267 
268 	// Type Info
269 	GetTypeInfo();
270 
271 	// Get IOleObject interface
272 	hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
273 	wxASSERT(SUCCEEDED(hret));
274 
275     // get IViewObject Interface
276     hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
277 	wxASSERT(SUCCEEDED(hret));
278 
279     // document advise
280     m_docAdviseCookie = 0;
281     hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
282     WXOLE_WARN(hret, "m_oleObject->Advise(adviseSink, &m_docAdviseCookie),\"Advise\")");
283     m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
284 	OleSetContainedObject(m_oleObject, TRUE);
285     OleRun(m_oleObject);
286 
287 
288     // Get IOleInPlaceObject interface
289 	hret = m_oleInPlaceObject.QueryInterface(IID_IOleInPlaceObject, m_ActiveX);
290 	wxASSERT(SUCCEEDED(hret));
291 
292     // status
293 	DWORD dwMiscStatus;
294 	m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
295     wxASSERT(SUCCEEDED(hret));
296 
297     // set client site first ?
298     if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
299 		m_oleObject->SetClientSite(m_clientSite);
300 
301 
302     // stream init
303     wxAutoOleInterface<IPersistStreamInit>
304 		pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
305 
306     if (pPersistStreamInit.Ok())
307     {
308         hret = pPersistStreamInit->InitNew();
309         WXOLE_WARN(hret, "CreateActiveX::pPersistStreamInit->InitNew()");
310     };
311 
312     if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
313 		m_oleObject->SetClientSite(m_clientSite);
314 
315 
316 	int w, h;
317 	GetClientSize(&w, &h);
318 	RECT posRect;
319 	posRect.left = 0;
320 	posRect.top = 0;
321 	posRect.right = w;
322 	posRect.bottom = h;
323 
324     m_oleObjectHWND = 0;
325 
326     if (m_oleInPlaceObject.Ok())
327     {
328     	hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
329 	    WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)");
330         if (SUCCEEDED(hret))
331 	        ::SetActiveWindow(m_oleObjectHWND);
332     };
333 
334 
335     if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
336     {
337 		if (w > 0 && h > 0 && m_oleInPlaceObject.Ok())
338 			m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
339 
340 		hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_clientSite, 0, (HWND)GetHWND(), &posRect);
341         hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, (HWND)GetHWND(), &posRect);
342     };
343 
344 	if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
345 	{
346 		hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
347 		WXOLE_WARN(hret, "m_oleInPlaceObject->GetWindow(&m_oleObjectHWND)");
348 	};
349 
350 	if (m_oleObjectHWND)
351 	{
352 		::SetActiveWindow(m_oleObjectHWND);
353 		::ShowWindow(m_oleObjectHWND, SW_SHOW);
354 
355 		// Update by GBR to resize older controls
356         wxSizeEvent szEvent;
357         szEvent.m_size = wxSize(w, h) ;
358 		AddPendingEvent(szEvent);
359 	};
360 }
361 
CreateActiveX(LPOLESTR progId)362 void wxActiveX::CreateActiveX(LPOLESTR progId)
363 {
364     CLSID clsid;
365     if (CLSIDFromProgID(progId, &clsid) != S_OK)
366     	return;
367 
368     CreateActiveX(clsid);
369 };
370 
371 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
372 // Case Insensitive Map of Event names to eventTypes
373 // created dynamically at run time in:
374 //      EVT_ACTIVEX(eventName, id, fn)
375 // we map the pointer to them so that:
376 //      const wxEventType& RegisterActiveXEvent(wxString eventName);
377 // can return a const reference, which is neccessary for event tables
378 // probably should use a wxWindows hash table here, but I'm lazy ...
379 struct less_wxStringI
380 {
operator ()less_wxStringI381     bool operator()(const wxString& x, const wxString& y) const
382     {
383         return x.CmpNoCase(y) < 0;
384     };
385 };
386 
387 typedef map<wxString, wxEventType *, less_wxStringI> ActiveXNamedEventMap;
388 static ActiveXNamedEventMap sg_NamedEventMap;
389 
RegisterActiveXEvent(const wxChar * eventName)390 const wxEventType& RegisterActiveXEvent(const wxChar *eventName)
391 {
392     wxString ev = eventName;
393     ActiveXNamedEventMap::iterator it = sg_NamedEventMap.find(ev);
394     if (it == sg_NamedEventMap.end())
395     {
396         wxEventType  *et = new wxEventType(wxNewEventType());
397         sg_NamedEventMap[ev] = et;
398 
399         return *et;
400     };
401 
402     return *(it->second);
403 };
404 
405 
406 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
407 // Map of Event DISPID's to eventTypes
408 // created dynamically at run time in:
409 //      EVT_ACTIVEX(eventName, id, fn)
410 // we map the pointer to them so that:
411 //      const wxEventType& RegisterActiveXEvent(wxString eventName);
412 // can return a const reference, which is neccessary for event tables
413 
414 typedef map<DISPID, wxEventType *> ActiveXDISPIDEventMap;
415 static ActiveXDISPIDEventMap sg_dispIdEventMap;
416 
RegisterActiveXEvent(DISPID event)417 const wxEventType& RegisterActiveXEvent(DISPID event)
418 {
419     ActiveXDISPIDEventMap::iterator it = sg_dispIdEventMap.find(event);
420     if (it == sg_dispIdEventMap.end())
421     {
422         wxEventType  *et = new wxEventType(wxNewEventType());
423         sg_dispIdEventMap[event] = et;
424 
425         return *et;
426     };
427 
428     return *(it->second);
429 };
430 
431 // one off class for automatic freeing of activeX eventtypes
432 class ActiveXEventMapFlusher
433 {
434 public:
~ActiveXEventMapFlusher()435     ~ActiveXEventMapFlusher()
436     {
437         // Named events
438         ActiveXNamedEventMap::iterator it = sg_NamedEventMap.end();
439         while (it != sg_NamedEventMap.end())
440         {
441             delete it->second;
442             it++;
443         };
444 
445         // DISPID events
446         ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.end();
447         while (dit != sg_dispIdEventMap.end())
448         {
449             delete dit->second;
450             dit++;
451         };
452     };
453 };
454 
455 static ActiveXEventMapFlusher s_dummyActiveXEventMapFlusher;
456 
457 
458 //////////////////////////////////////////////////////
MSWVariantToVariant(VARIANTARG & va,wxVariant & vx)459 bool MSWVariantToVariant(VARIANTARG& va, wxVariant& vx)
460 {
461     switch(va.vt)
462     {
463 	case VT_VARIANT | VT_BYREF:
464 		return MSWVariantToVariant(*va.pvarVal, vx);
465 
466     case VT_I2:
467     case VT_I4:
468         vx = (long) va.iVal;
469         return true;
470 
471     case VT_I2 | VT_BYREF:
472     case VT_I4 | VT_BYREF:
473         vx = (long) *va.piVal;
474         return true;
475 
476     case VT_BSTR:
477         vx = wxString(va.bstrVal);
478         return true;
479 
480     case VT_BSTR | VT_BYREF:
481         vx = wxString(*va.pbstrVal);
482         return true;
483 
484 	case VT_BOOL:
485 		vx = (va.boolVal != FALSE);
486 		return true;
487 
488 	case VT_BOOL | VT_BYREF:
489 		vx = (*va.pboolVal != FALSE);
490 		return true;
491 
492     default:
493         vx.MakeNull();
494         return false;
495     };
496 };
497 
VariantToMSWVariant(wxVariant & vx,VARIANTARG & va)498 bool VariantToMSWVariant(wxVariant& vx, VARIANTARG& va)
499 {
500     switch(va.vt)
501     {
502 	case VT_VARIANT | VT_BYREF:
503 		return VariantToMSWVariant(vx, va);
504 
505     case VT_I2:
506     case VT_I4:
507         va.iVal = (long) vx;
508         return true;
509 
510     case VT_I2 | VT_BYREF:
511     case VT_I4 | VT_BYREF:
512          *va.piVal = (long) vx;
513         return true;
514 
515 	case VT_BOOL:
516 		va.boolVal = ((bool) vx) ? TRUE : FALSE;
517 		return true;
518 
519 	case VT_BOOL | VT_BYREF:
520 		*va.pboolVal = ((bool) vx) ? TRUE : FALSE;
521 		return true;
522 
523     default:
524         return false;
525     };
526 };
527 
528 class wxActiveXEvents : public IDispatch
529 {
530 private:
531     DECLARE_OLE_UNKNOWN(wxActiveXEvents);
532 
533 
534     wxActiveX *m_activeX;
535 
536 public:
wxActiveXEvents(wxActiveX * ax)537     wxActiveXEvents(wxActiveX *ax) : m_activeX(ax) {}
~wxActiveXEvents()538 	virtual ~wxActiveXEvents()
539     {
540     }
541 
542 	//IDispatch
GetIDsOfNames(REFIID r,OLECHAR ** o,unsigned int i,LCID l,DISPID * d)543 	STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
544 	{
545         return E_NOTIMPL;
546     };
547 
GetTypeInfo(unsigned int i,LCID l,ITypeInfo ** t)548 	STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
549 	{
550         return E_NOTIMPL;
551     };
552 
GetTypeInfoCount(unsigned int * i)553 	STDMETHODIMP GetTypeInfoCount(unsigned int* i)
554 	{
555         return E_NOTIMPL;
556     };
557 
558 
DispatchEvent(int eventIdx,const wxEventType & eventType,DISPPARAMS * pDispParams)559     void DispatchEvent(int eventIdx, const wxEventType& eventType, DISPPARAMS * pDispParams)
560     {
561         wxASSERT(eventIdx >= 0 && eventIdx < int(m_activeX->m_events.size()));
562         wxActiveX::FuncX &func = m_activeX->m_events[eventIdx];
563 
564 		wxActiveXEvent  event;
565     	event.SetId(m_activeX->GetId());
566 	    event.SetEventType(eventType);
567         event.m_params.NullList();
568         event.m_params.SetName(func.name);
569 
570         // arguments
571         if (pDispParams)
572         {
573 			// cdecl call
574             // sometimes the pDispParams does not match the param info for a activex control
575             int nArg = min(func.params.size(), pDispParams->cArgs);
576             for (int i = nArg - 1; i >= 0; i--)
577             {
578                 VARIANTARG& va = pDispParams->rgvarg[i];
579 				wxActiveX::ParamX &px = func.params[nArg - i - 1];
580                 wxVariant vx;
581 
582                 vx.SetName(px.name);
583                 MSWVariantToVariant(va, vx);
584                 event.m_params.Append(vx);
585             };
586         };
587 
588 		if (func.hasOut)
589 		{
590             int nArg = min(func.params.size(), pDispParams->cArgs);
591     		m_activeX->GetParent()->ProcessEvent(event);
592             for (int i = 0; i < nArg; i++)
593             {
594                 VARIANTARG& va = pDispParams->rgvarg[i];
595 				wxActiveX::ParamX &px = func.params[nArg - i - 1];
596 
597 				if (px.IsOut())
598 				{
599 					wxVariant& vx = event.m_params[nArg - i - 1];
600 
601 					VariantToMSWVariant(vx, va);
602 				};
603 			};
604 		}
605 		else
606     		m_activeX->GetParent()->AddPendingEvent(event);
607 
608     };
609 
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,unsigned int * puArgErr)610 	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
611 						  WORD wFlags, DISPPARAMS * pDispParams,
612 						  VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
613 						  unsigned int * puArgErr)
614 	{
615 	    if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
616             return E_NOTIMPL;
617 
618         wxASSERT(m_activeX);
619 
620         // map dispid to m_eventsIdx
621         wxActiveX::MemberIdList::iterator mid = m_activeX->m_eventsIdx.find((MEMBERID) dispIdMember);
622         if (mid == m_activeX->m_eventsIdx.end())
623             return S_OK;
624 
625         int funcIdx = mid->second;
626         wxActiveX::FuncX &func = m_activeX->m_events[funcIdx];
627 
628 
629         // try to find dispid event
630         ActiveXDISPIDEventMap::iterator dit = sg_dispIdEventMap.find(dispIdMember);
631         if (dit != sg_dispIdEventMap.end())
632         {
633             // Dispatch Event
634             DispatchEvent(funcIdx, *(dit->second), pDispParams);
635         	return S_OK;
636         };
637 
638         // try named event
639         ActiveXNamedEventMap::iterator nit = sg_NamedEventMap.find(func.name);
640         if (nit == sg_NamedEventMap.end())
641             return S_OK;
642 
643         // Dispatch Event
644         DispatchEvent(funcIdx, *(nit->second), pDispParams);
645     	return S_OK;
646     }
647 };
648 
649 
650 DEFINE_OLE_TABLE(wxActiveXEvents)
651 	OLE_IINTERFACE(IUnknown)
652 	OLE_INTERFACE(IID_IDispatch, IDispatch)
653 END_OLE_TABLE;
654 
EventName()655 wxString wxActiveXEvent::EventName()
656 {
657     return m_params.GetName();
658 };
659 
ParamCount() const660 int wxActiveXEvent::ParamCount() const
661 {
662     return m_params.GetCount();
663 };
664 
ParamType(int idx)665 wxString wxActiveXEvent::ParamType(int idx)
666 {
667     wxASSERT(idx >= 0 && idx < m_params.GetCount());
668 
669     return m_params[idx].GetType();
670 };
671 
ParamName(int idx)672 wxString wxActiveXEvent::ParamName(int idx)
673 {
674     wxASSERT(idx >= 0 && idx < m_params.GetCount());
675 
676     return m_params[idx].GetName();
677 };
678 
679 static wxVariant nullVar;
680 
operator [](int idx)681 wxVariant& wxActiveXEvent::operator[] (int idx)
682 {
683     wxASSERT(idx >= 0 && idx < ParamCount());
684 
685     return m_params[idx];
686 };
687 
operator [](wxString name)688 wxVariant& wxActiveXEvent::operator[] (wxString name)
689 {
690     for (int i = 0; i < m_params.GetCount(); i++)
691     {
692         if (name.CmpNoCase(m_params[i].GetName()) == 0)
693             return m_params[i];
694     };
695 
696     wxString err = _T("wxActiveXEvent::operator[] invalid name <") + name + _T(">");
697     err += _T("\r\nValid Names = :\r\n");
698     for (int i = 0; i < m_params.GetCount(); i++)
699     {
700         err += m_params[i].GetName();
701         err += _T("\r\n");
702     };
703 
704     wxASSERT_MSG(false, err);
705 
706     return nullVar;
707 };
708 
GetTypeInfo()709 void wxActiveX::GetTypeInfo()
710 {
711 	/*
712 	We are currently only interested in the IDispatch interface
713 	to the control. For dual interfaces (TypeKind = TKIND_INTERFACE)
714 	we should drill down through the inheritance
715 	(using TYPEATTR->cImplTypes) and GetRefTypeOfImplType(n)
716 	and retrieve all the func names etc that way, then generate a C++
717 	header	file for it.
718 
719 	But we don't do this and probably never will, so if we have a DUAL
720 	interface then we query for the IDispatch
721 	via GetRefTypeOfImplType(-1).
722 	*/
723 
724 	HRESULT hret = 0;
725 
726 	// get type info via class info
727 	wxAutoOleInterface<IProvideClassInfo> classInfo(IID_IProvideClassInfo, m_ActiveX);
728 	if (! classInfo.Ok())
729 		return;
730 
731 	// type info
732 	wxAutoOleInterface<ITypeInfo> typeInfo;
733 	hret = classInfo->GetClassInfo(typeInfo.GetRef());
734 	if (! typeInfo.Ok())
735 		return;
736 
737 	// TYPEATTR
738 	TYPEATTR *ta = NULL;
739 	hret = typeInfo->GetTypeAttr(&ta);
740 	if (! ta)
741 		return;
742 
743     // this should be a TKIND_COCLASS
744     wxASSERT(ta->typekind == TKIND_COCLASS);
745 
746     // iterate contained interfaces
747 	for (int i = 0; i < ta->cImplTypes; i++)
748 	{
749 		HREFTYPE rt = 0;
750 
751 		// get dispatch type info handle
752 		hret = typeInfo->GetRefTypeOfImplType(i, &rt);
753 		if (! SUCCEEDED(hret))
754 			continue;
755 
756 		// get dispatch type info interface
757 		wxAutoOleInterface<ITypeInfo>  ti;
758 		hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
759 		if (! ti.Ok())
760 			continue;
761 
762         // check if default event sink
763         bool defEventSink = false;
764         int impTypeFlags = 0;
765         typeInfo->GetImplTypeFlags(i, &impTypeFlags);
766 
767         if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
768         {
769             if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
770             {
771                 WXOLE_TRACEOUT("Default Event Sink");
772                 defEventSink = true;
773             }
774             else
775             {
776                 WXOLE_TRACEOUT("Default Interface");
777             }
778         };
779 
780 
781 		// process
782 		GetTypeInfo(ti, defEventSink);
783 	};
784 
785 
786     // free
787     typeInfo->ReleaseTypeAttr(ta);
788 };
789 
GetTypeInfo(ITypeInfo * ti,bool defEventSink)790 void wxActiveX::GetTypeInfo(ITypeInfo *ti, bool defEventSink)
791 {
792 	ti->AddRef();
793 	wxAutoOleInterface<ITypeInfo> typeInfo(ti);
794 
795 	// TYPEATTR
796 	TYPEATTR *ta = NULL;
797 	HRESULT hret = typeInfo->GetTypeAttr(&ta);
798 	if (! ta)
799 		return;
800 
801 	if (ta->typekind == TKIND_DISPATCH)
802 	{
803         WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
804 
805         if (defEventSink)
806         {
807             wxActiveXEvents *disp = new wxActiveXEvents(this);
808             ConnectAdvise(ta->guid, disp);
809         };
810 
811 
812 		// Get Function Names
813 		for (int i = 0; i < ta->cFuncs; i++)
814 		{
815 			FUNCDESC FAR *fd = NULL;
816 
817 			hret = typeInfo->GetFuncDesc(i, &fd);
818 			if (! fd)
819 				continue;
820 
821 			BSTR anames[1] = {NULL};
822 			unsigned int n = 0;
823 
824 			hret = typeInfo->GetNames(fd->memid, anames, 1, &n);
825 
826 			if (anames[0])
827 			{
828 				wxString name = anames[0];
829 
830 				WXOLE_TRACEOUT("Name " << i << " = " << name.c_str());
831 				SysFreeString(anames[0]);
832 
833                 if (defEventSink)
834                 {
835                     FuncX func;
836                     func.name = name;
837                     func.memid = fd->memid;
838 					func.hasOut = false;
839 
840                     // get Param Names
841                     unsigned int maxPNames = fd->cParams + 1;
842                     unsigned int nPNames = 0;
843                     BSTR *pnames = new BSTR[maxPNames];
844 
845                     hret = typeInfo->GetNames(fd->memid, pnames, maxPNames, &nPNames);
846                     wxASSERT(int(nPNames) >= fd->cParams + 1);
847 
848                     SysFreeString(pnames[0]);
849 					// params
850 					for (int p = 0; p < fd->cParams; p++)
851 					{
852 						ParamX param;
853 
854 						param.flags = fd->lprgelemdescParam[p].idldesc.wIDLFlags;
855 						param.vt = fd->lprgelemdescParam[p].tdesc.vt;
856                         param.isPtr = (param.vt == VT_PTR);
857                         param.isSafeArray = (param.vt == VT_SAFEARRAY);
858                         if (param.isPtr || param.isSafeArray)
859                             param.vt = fd->lprgelemdescParam[p].tdesc.lptdesc->vt;
860 
861                         param.name = pnames[p + 1];
862                         SysFreeString(pnames[p + 1]);
863 
864 						func.hasOut |= (param.IsOut() || param.isPtr);
865 						func.params.push_back(param);
866 					};
867                     delete [] pnames;
868 
869                     m_events.push_back(func);
870                     m_eventsIdx[fd->memid] = m_events.size() - 1;
871                 };
872 			};
873 
874 			typeInfo->ReleaseFuncDesc(fd);
875 		};
876 	}
877 
878 	typeInfo->ReleaseTypeAttr(ta);
879 };
880 
881 ///////////////////////////////////////////////
882 // Type Info exposure
GetEvent(int idx) const883 const wxActiveX::FuncX& wxActiveX::GetEvent(int idx) const
884 {
885     wxASSERT(idx >= 0 && idx < GetEventCount());
886 
887     return m_events[idx];
888 };
889 
890 ///////////////////////////////////////////////
891 
ConnectAdvise(REFIID riid,IUnknown * events)892 HRESULT wxActiveX::ConnectAdvise(REFIID riid, IUnknown *events)
893 {
894 	wxOleConnectionPoint	cp;
895 	DWORD					adviseCookie = 0;
896 
897 	wxAutoOleInterface<IConnectionPointContainer> cpContainer(IID_IConnectionPointContainer, m_ActiveX);
898 	if (! cpContainer.Ok())
899 		return E_FAIL;
900 
901 	HRESULT hret = cpContainer->FindConnectionPoint(riid, cp.GetRef());
902 	if (! SUCCEEDED(hret))
903 		return hret;
904 
905 	hret = cp->Advise(events, &adviseCookie);
906 
907 	if (SUCCEEDED(hret))
908 		m_connections.push_back(wxOleConnection(cp, adviseCookie));
909 
910 	return hret;
911 };
912 
AmbientPropertyChanged(DISPID dispid)913 HRESULT wxActiveX::AmbientPropertyChanged(DISPID dispid)
914 {
915     wxAutoOleInterface<IOleControl> oleControl(IID_IOleControl, m_oleObject);
916 
917     if (oleControl.Ok())
918         return oleControl->OnAmbientPropertyChange(dispid);
919     else
920         return S_FALSE;
921 };
922 
923 #define HIMETRIC_PER_INCH   2540
924 #define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
925 
PixelsToHimetric(SIZEL & sz)926 static void PixelsToHimetric(SIZEL &sz)
927 {
928 	static int logX = 0;
929 	static int logY = 0;
930 
931 	if (logY == 0)
932 	{
933 		// initaliase
934 		HDC dc = GetDC(NULL);
935 		logX = GetDeviceCaps(dc, LOGPIXELSX);
936 		logY = GetDeviceCaps(dc, LOGPIXELSY);
937 		ReleaseDC(NULL, dc);
938 	};
939 
940 #define HIMETRIC_INCH   2540
941 #define CONVERT(x, logpixels)   MulDiv(HIMETRIC_INCH, (x), (logpixels))
942 
943 	sz.cx = CONVERT(sz.cx, logX);
944 	sz.cy = CONVERT(sz.cy, logY);
945 
946 #undef CONVERT
947 #undef HIMETRIC_INCH
948 }
949 
950 
OnSize(wxSizeEvent & event)951 void wxActiveX::OnSize(wxSizeEvent& event)
952 {
953 	int w, h;
954 	GetClientSize(&w, &h);
955 
956 	RECT posRect;
957 	posRect.left = 0;
958 	posRect.top = 0;
959 	posRect.right = w;
960 	posRect.bottom = h;
961 
962 	if (w <= 0 && h <= 0)
963 		return;
964 
965 	// extents are in HIMETRIC units
966     if (m_oleObject.Ok())
967     {
968         SIZEL sz = {w, h};
969 	    PixelsToHimetric(sz);
970 
971         SIZEL sz2;
972 
973         m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
974         if (sz2.cx !=  sz.cx || sz.cy != sz2.cy)
975             m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
976     };
977 
978     if (m_oleInPlaceObject.Ok())
979 		m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
980 }
981 
OnPaint(wxPaintEvent & event)982 void wxActiveX::OnPaint(wxPaintEvent& event)
983 {
984 	//wxLogTrace(wxT("repainting activex win"));
985 	wxPaintDC dc(this);
986 	//dc.BeginDrawing();
987 	int w, h;
988 	GetSize(&w, &h);
989 	RECT posRect;
990 	posRect.left = 0;
991 	posRect.top = 0;
992 	posRect.right = w;
993 	posRect.bottom = h;
994 
995 	// Draw only when control is windowless or deactivated
996 	if (m_viewObject)
997 	{
998 		::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
999 		{
1000 			RECTL *prcBounds = (RECTL *) &posRect;
1001 			m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1002 				(HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
1003 		}
1004 	}
1005 	else
1006 	{
1007 		dc.SetBrush(*wxRED_BRUSH);
1008 		dc.DrawRectangle(0, 0, w, h);
1009 		dc.SetBrush(wxNullBrush);
1010 	}
1011 	//dc.EndDrawing();
1012 }
1013 
OnMouse(wxMouseEvent & event)1014 void wxActiveX::OnMouse(wxMouseEvent& event)
1015 {
1016 	if (m_oleObjectHWND == NULL)
1017     {
1018         //wxLogTrace(wxT("no oleInPlaceObject"));
1019         event.Skip();
1020         return;
1021     }
1022 
1023 	//wxLogTrace(wxT("mouse event"));
1024 	UINT msg = 0;
1025 	WPARAM wParam = 0;
1026 	LPARAM lParam = 0;
1027 	LRESULT lResult = 0;
1028 
1029 	if (event.m_metaDown)
1030         wParam |= MK_CONTROL;
1031 	if (event.m_shiftDown)
1032         wParam |= MK_SHIFT;
1033 	if (event.m_leftDown)
1034         wParam |= MK_LBUTTON;
1035 	if (event.m_middleDown)
1036         wParam |= MK_MBUTTON;
1037 	if (event.m_rightDown)
1038         wParam |= MK_RBUTTON;
1039 	lParam = event.m_x << 16;
1040 	lParam |= event.m_y;
1041 
1042 	if (event.LeftDown())
1043         msg = WM_LBUTTONDOWN;
1044 	else if (event.LeftDClick())
1045         msg = WM_LBUTTONDBLCLK;
1046 	else if (event.LeftUp())
1047         msg = WM_LBUTTONUP;
1048 	else if (event.MiddleDown())
1049         msg = WM_MBUTTONDOWN;
1050 	else if (event.MiddleDClick())
1051         msg = WM_MBUTTONDBLCLK;
1052 	else if (event.MiddleUp())
1053         msg = WM_MBUTTONUP;
1054 	else if (event.RightDown())
1055         msg = WM_RBUTTONDOWN;
1056 	else if (event.RightDClick())
1057         msg = WM_RBUTTONDBLCLK;
1058 	else if (event.RightUp())
1059         msg = WM_RBUTTONUP;
1060 	else if (event.Moving() || event.Dragging())
1061         msg = WM_MOUSEMOVE;
1062 
1063 	wxString log;
1064 	if (msg == 0)
1065     {
1066         //wxLogTrace(wxT("no message"));
1067         event.Skip(); return;
1068     };
1069 
1070 	if (!::SendMessage(m_oleObjectHWND, msg, wParam, lParam))
1071     {
1072         //wxLogTrace(wxT("msg not delivered"));
1073         event.Skip();
1074         return;
1075     };
1076 
1077 	//wxLogTrace(wxT("msg sent"));
1078 }
1079 
MSWWindowProc(WXUINT nMsg,WXWPARAM wParam,WXLPARAM lParam)1080 long wxActiveX::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
1081 {
1082 	if (m_oleObjectHWND == NULL)
1083         return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
1084 
1085     switch(nMsg)
1086     {
1087     case WM_SYSKEYDOWN:
1088     case WM_SYSKEYUP:
1089     case WM_CHAR:
1090     case WM_DEADCHAR:
1091     case WM_KEYDOWN:
1092     case WM_KEYUP:
1093     case WM_SYSCHAR:
1094     case WM_SYSDEADCHAR:
1095         PostMessage(m_oleObjectHWND, nMsg, wParam, lParam);
1096 
1097     default:
1098         return wxWindow::MSWWindowProc(nMsg, wParam, lParam);
1099     };
1100 };
1101 
OnSetFocus(wxFocusEvent & event)1102 void wxActiveX::OnSetFocus(wxFocusEvent& event)
1103 {
1104 	if (m_oleInPlaceActiveObject.Ok())
1105         m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1106 }
1107 
OnKillFocus(wxFocusEvent & event)1108 void wxActiveX::OnKillFocus(wxFocusEvent& event)
1109 {
1110 	if (m_oleInPlaceActiveObject.Ok())
1111         m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1112 }
1113 
1114 
FrameSite(wxActiveX * win)1115 FrameSite::FrameSite(wxActiveX * win)
1116 {
1117 	m_window = win;
1118 	m_bSupportsWindowlessActivation = true;
1119 	m_bInPlaceLocked = false;
1120 	m_bUIActive = false;
1121 	m_bInPlaceActive = false;
1122 	m_bWindowless = false;
1123 
1124 	m_nAmbientLocale = 0;
1125 	m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
1126 	m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
1127 	m_bAmbientShowHatching = true;
1128 	m_bAmbientShowGrabHandles = true;
1129 	m_bAmbientAppearance = true;
1130 
1131 	m_hDCBuffer = NULL;
1132 	m_hWndParent = (HWND)m_window->GetHWND();
1133 }
1134 
~FrameSite()1135 FrameSite::~FrameSite()
1136 {
1137 }
1138 
1139 
1140 //IDispatch
1141 
GetIDsOfNames(REFIID riid,OLECHAR ** rgszNames,unsigned int cNames,LCID lcid,DISPID * rgDispId)1142 HRESULT FrameSite::GetIDsOfNames(REFIID riid, OLECHAR ** rgszNames, unsigned int cNames,
1143 								 LCID lcid, DISPID * rgDispId)
1144 {
1145 	WXOLE_TRACE("IDispatch::GetIDsOfNames");
1146 	return E_NOTIMPL;
1147 }
1148 
GetTypeInfo(unsigned int iTInfo,LCID lcid,ITypeInfo ** ppTInfo)1149 HRESULT FrameSite::GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo ** ppTInfo)
1150 {
1151 	WXOLE_TRACE("IDispatch::GetTypeInfo");
1152 	return E_NOTIMPL;
1153 }
1154 
GetTypeInfoCount(unsigned int * pcTInfo)1155 HRESULT FrameSite::GetTypeInfoCount(unsigned int * pcTInfo)
1156 {
1157 	WXOLE_TRACE("IDispatch::GetTypeInfoCount");
1158 	return E_NOTIMPL;
1159 }
1160 
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,unsigned int * puArgErr)1161 HRESULT FrameSite::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
1162 						  WORD wFlags, DISPPARAMS * pDispParams,
1163 						  VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
1164 						  unsigned int * puArgErr)
1165 {
1166 	WXOLE_TRACE("IDispatch::Invoke");
1167 
1168 	if (!(wFlags & DISPATCH_PROPERTYGET))
1169         return S_OK;
1170 
1171     HRESULT hr;
1172 
1173 	if (pVarResult == NULL)
1174 		return E_INVALIDARG;
1175 
1176     //The most common case is boolean, use as an initial type
1177     V_VT(pVarResult) = VT_BOOL;
1178 
1179 	switch (dispIdMember)
1180 	{
1181         case DISPID_AMBIENT_MESSAGEREFLECT:
1182             WXOLE_TRACE("Invoke::DISPID_AMBIENT_MESSAGEREFLECT");
1183             V_BOOL(pVarResult)= FALSE;
1184             return S_OK;
1185 
1186         case DISPID_AMBIENT_DISPLAYASDEFAULT:
1187             WXOLE_TRACE("Invoke::DISPID_AMBIENT_DISPLAYASDEFAULT");
1188             V_BOOL(pVarResult)= TRUE;
1189             return S_OK;
1190 
1191         case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
1192             WXOLE_TRACE("Invoke::DISPID_AMBIENT_OFFLINEIFNOTCONNECTED");
1193             V_BOOL(pVarResult) = TRUE;
1194             return S_OK;
1195 
1196 
1197         case DISPID_AMBIENT_SILENT:
1198             WXOLE_TRACE("Invoke::DISPID_AMBIENT_SILENT");
1199             V_BOOL(pVarResult)= TRUE;
1200             return S_OK;
1201 
1202 		case DISPID_AMBIENT_APPEARANCE:
1203 			pVarResult->vt = VT_BOOL;
1204 			pVarResult->boolVal = m_bAmbientAppearance;
1205 			break;
1206 
1207 		case DISPID_AMBIENT_FORECOLOR:
1208 			pVarResult->vt = VT_I4;
1209 			pVarResult->lVal = (long) m_clrAmbientForeColor;
1210 			break;
1211 
1212 		case DISPID_AMBIENT_BACKCOLOR:
1213 			pVarResult->vt = VT_I4;
1214 			pVarResult->lVal = (long) m_clrAmbientBackColor;
1215 			break;
1216 
1217 		case DISPID_AMBIENT_LOCALEID:
1218 			pVarResult->vt = VT_I4;
1219 			pVarResult->lVal = (long) m_nAmbientLocale;
1220 			break;
1221 
1222 		case DISPID_AMBIENT_USERMODE:
1223 			pVarResult->vt = VT_BOOL;
1224 			pVarResult->boolVal = m_window->m_bAmbientUserMode;
1225 			break;
1226 
1227 		case DISPID_AMBIENT_SHOWGRABHANDLES:
1228 			pVarResult->vt = VT_BOOL;
1229 			pVarResult->boolVal = m_bAmbientShowGrabHandles;
1230 			break;
1231 
1232 		case DISPID_AMBIENT_SHOWHATCHING:
1233 			pVarResult->vt = VT_BOOL;
1234 			pVarResult->boolVal = m_bAmbientShowHatching;
1235 			break;
1236 
1237 		default:
1238 			return DISP_E_MEMBERNOTFOUND;
1239 	}
1240 
1241     return S_OK;
1242 }
1243 
1244 //IOleWindow
1245 
GetWindow(HWND * phwnd)1246 HRESULT FrameSite::GetWindow(HWND * phwnd)
1247 {
1248 	WXOLE_TRACE("IOleWindow::GetWindow");
1249 	if (phwnd == NULL)
1250         return E_INVALIDARG;
1251 	(*phwnd) = m_hWndParent;
1252 	return S_OK;
1253 }
1254 
ContextSensitiveHelp(BOOL fEnterMode)1255 HRESULT FrameSite::ContextSensitiveHelp(BOOL fEnterMode)
1256 {
1257 	WXOLE_TRACE("IOleWindow::ContextSensitiveHelp");
1258 	return S_OK;
1259 }
1260 
1261 //IOleInPlaceUIWindow
1262 
GetBorder(LPRECT lprectBorder)1263 HRESULT FrameSite::GetBorder(LPRECT lprectBorder)
1264 {
1265 	WXOLE_TRACE("IOleInPlaceUIWindow::GetBorder");
1266 	if (lprectBorder == NULL)
1267         return E_INVALIDARG;
1268 	return INPLACE_E_NOTOOLSPACE;
1269 }
1270 
RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)1271 HRESULT FrameSite::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
1272 {
1273 	WXOLE_TRACE("IOleInPlaceUIWindow::RequestBorderSpace");
1274 	if (pborderwidths == NULL)
1275         return E_INVALIDARG;
1276 	return INPLACE_E_NOTOOLSPACE;
1277 }
1278 
SetBorderSpace(LPCBORDERWIDTHS pborderwidths)1279 HRESULT FrameSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
1280 {
1281 	WXOLE_TRACE("IOleInPlaceUIWindow::SetBorderSpace");
1282 	return S_OK;
1283 }
1284 
SetActiveObject(IOleInPlaceActiveObject * pActiveObject,LPCOLESTR pszObjName)1285 HRESULT FrameSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1286 {
1287 	WXOLE_TRACE("IOleInPlaceUIWindow::SetActiveObject");
1288 
1289     if (pActiveObject)
1290         pActiveObject->AddRef();
1291 
1292     m_window->m_oleInPlaceActiveObject = pActiveObject;
1293 	return S_OK;
1294 }
1295 
1296 //IOleInPlaceFrame
1297 
InsertMenus(HMENU hmenuShared,LPOLEMENUGROUPWIDTHS lpMenuWidths)1298 HRESULT FrameSite::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
1299 {
1300 	WXOLE_TRACE("IOleInPlaceFrame::InsertMenus");
1301 	return S_OK;
1302 }
1303 
SetMenu(HMENU hmenuShared,HOLEMENU holemenu,HWND hwndActiveObject)1304 HRESULT FrameSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
1305 {
1306 	WXOLE_TRACE("IOleInPlaceFrame::SetMenu");
1307 	return S_OK;
1308 }
1309 
RemoveMenus(HMENU hmenuShared)1310 HRESULT FrameSite::RemoveMenus(HMENU hmenuShared)
1311 {
1312 	WXOLE_TRACE("IOleInPlaceFrame::RemoveMenus");
1313 	return S_OK;
1314 }
1315 
SetStatusText(LPCOLESTR pszStatusText)1316 HRESULT FrameSite::SetStatusText(LPCOLESTR pszStatusText)
1317 {
1318 	WXOLE_TRACE("IOleInPlaceFrame::SetStatusText");
1319 	//((wxFrame*)wxGetApp().GetTopWindow())->GetStatusBar()->SetStatusText(pszStatusText);
1320 	return S_OK;
1321 }
1322 
EnableModeless(BOOL fEnable)1323 HRESULT FrameSite::EnableModeless(BOOL fEnable)
1324 {
1325 	WXOLE_TRACE("IOleInPlaceFrame::EnableModeless");
1326 	return S_OK;
1327 }
1328 
TranslateAccelerator(LPMSG lpmsg,WORD wID)1329 HRESULT FrameSite::TranslateAccelerator(LPMSG lpmsg, WORD wID)
1330 {
1331 	WXOLE_TRACE("IOleInPlaceFrame::TranslateAccelerator");
1332 	// TODO: send an event with this id
1333     if (m_window->m_oleInPlaceActiveObject.Ok())
1334     	m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
1335 
1336 	return S_FALSE;
1337 }
1338 
1339 //IOleInPlaceSite
1340 
CanInPlaceActivate()1341 HRESULT FrameSite::CanInPlaceActivate()
1342 {
1343 	WXOLE_TRACE("IOleInPlaceSite::CanInPlaceActivate");
1344 	return S_OK;
1345 }
1346 
OnInPlaceActivate()1347 HRESULT FrameSite::OnInPlaceActivate()
1348 {
1349 	WXOLE_TRACE("IOleInPlaceSite::OnInPlaceActivate");
1350 	m_bInPlaceActive = true;
1351 	return S_OK;
1352 }
1353 
OnUIActivate()1354 HRESULT FrameSite::OnUIActivate()
1355 {
1356 	WXOLE_TRACE("IOleInPlaceSite::OnUIActivate");
1357 	m_bUIActive = true;
1358 	return S_OK;
1359 }
1360 
GetWindowContext(IOleInPlaceFrame ** ppFrame,IOleInPlaceUIWindow ** ppDoc,LPRECT lprcPosRect,LPRECT lprcClipRect,LPOLEINPLACEFRAMEINFO lpFrameInfo)1361 HRESULT FrameSite::GetWindowContext(IOleInPlaceFrame **ppFrame,
1362 									IOleInPlaceUIWindow **ppDoc,
1363 									LPRECT lprcPosRect,
1364 									LPRECT lprcClipRect,
1365 									LPOLEINPLACEFRAMEINFO lpFrameInfo)
1366 {
1367 	WXOLE_TRACE("IOleInPlaceSite::GetWindowContext");
1368 	if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
1369 		lprcClipRect == NULL || lpFrameInfo == NULL)
1370 	{
1371 		if (ppFrame != NULL)
1372             (*ppFrame) = NULL;
1373 		if (ppDoc != NULL)
1374             (*ppDoc) = NULL;
1375 		return E_INVALIDARG;
1376 	}
1377 
1378     HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
1379     if (! SUCCEEDED(hr))
1380     {
1381         WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceFrame Error !");
1382         return E_UNEXPECTED;
1383     };
1384 
1385     hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
1386     if (! SUCCEEDED(hr))
1387     {
1388         WXOLE_TRACE("IOleInPlaceSite::IOleInPlaceUIWindow Error !");
1389         (*ppFrame)->Release();
1390         *ppFrame = NULL;
1391         return E_UNEXPECTED;
1392     };
1393 
1394 	int w, h;
1395 	m_window->GetClientSize(&w, &h);
1396     if (lprcPosRect)
1397     {
1398 	    lprcPosRect->left = lprcPosRect->top = 0;
1399 	    lprcPosRect->right = w;
1400 	    lprcPosRect->bottom = h;
1401     };
1402     if (lprcClipRect)
1403     {
1404 	    lprcClipRect->left = lprcClipRect->top = 0;
1405 	    lprcClipRect->right = w;
1406 	    lprcClipRect->bottom = h;
1407     };
1408 
1409     memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
1410     lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
1411 	lpFrameInfo->hwndFrame = m_hWndParent;
1412 
1413 	return S_OK;
1414 }
1415 
Scroll(SIZE scrollExtent)1416 HRESULT FrameSite::Scroll(SIZE scrollExtent)
1417 {
1418 	WXOLE_TRACE("IOleInPlaceSite::Scroll");
1419 	return S_OK;
1420 }
1421 
OnUIDeactivate(BOOL fUndoable)1422 HRESULT FrameSite::OnUIDeactivate(BOOL fUndoable)
1423 {
1424 	WXOLE_TRACE("IOleInPlaceSite::OnUIDeactivate");
1425 	m_bUIActive = false;
1426 	return S_OK;
1427 }
1428 
OnInPlaceDeactivate()1429 HRESULT FrameSite::OnInPlaceDeactivate()
1430 {
1431 	WXOLE_TRACE("IOleInPlaceSite::OnInPlaceDeactivate");
1432 	m_bInPlaceActive = false;
1433 	return S_OK;
1434 }
1435 
DiscardUndoState()1436 HRESULT FrameSite::DiscardUndoState()
1437 {
1438 	WXOLE_TRACE("IOleInPlaceSite::DiscardUndoState");
1439 	return S_OK;
1440 }
1441 
DeactivateAndUndo()1442 HRESULT FrameSite::DeactivateAndUndo()
1443 {
1444 	WXOLE_TRACE("IOleInPlaceSite::DeactivateAndUndo");
1445 	return S_OK;
1446 }
1447 
OnPosRectChange(LPCRECT lprcPosRect)1448 HRESULT FrameSite::OnPosRectChange(LPCRECT lprcPosRect)
1449 {
1450 	WXOLE_TRACE("IOleInPlaceSite::OnPosRectChange");
1451     if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
1452         m_window->m_oleInPlaceObject->SetObjectRects(lprcPosRect, lprcPosRect);
1453 
1454 	return S_OK;
1455 }
1456 
1457 //IOleInPlaceSiteEx
1458 
OnInPlaceActivateEx(BOOL * pfNoRedraw,DWORD dwFlags)1459 HRESULT FrameSite::OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD dwFlags)
1460 {
1461 	WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceActivateEx");
1462 	OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
1463     if (pfNoRedraw)
1464         (*pfNoRedraw) = FALSE;
1465 	return S_OK;
1466 }
1467 
OnInPlaceDeactivateEx(BOOL fNoRedraw)1468 HRESULT FrameSite::OnInPlaceDeactivateEx(BOOL fNoRedraw)
1469 {
1470 	WXOLE_TRACE("IOleInPlaceSiteEx::OnInPlaceDeactivateEx");
1471     OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
1472 	return S_OK;
1473 }
1474 
RequestUIActivate()1475 HRESULT FrameSite::RequestUIActivate()
1476 {
1477 	WXOLE_TRACE("IOleInPlaceSiteEx::RequestUIActivate");
1478 	return S_OK;
1479 }
1480 
1481 
1482 //IOleClientSite
1483 
SaveObject()1484 HRESULT FrameSite::SaveObject()
1485 {
1486 	WXOLE_TRACE("IOleClientSite::SaveObject");
1487 	return S_OK;
1488 }
1489 
GetMoniker(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker ** ppmk)1490 HRESULT FrameSite::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,
1491 							  IMoniker ** ppmk)
1492 {
1493 	WXOLE_TRACE("IOleClientSite::GetMoniker");
1494 	return E_NOTIMPL;
1495 }
1496 
GetContainer(LPOLECONTAINER * ppContainer)1497 HRESULT FrameSite::GetContainer(LPOLECONTAINER * ppContainer)
1498 {
1499 	WXOLE_TRACE("IOleClientSite::GetContainer");
1500 	if (ppContainer == NULL)
1501         return E_INVALIDARG;
1502 
1503     HRESULT hr = QueryInterface(IID_IOleContainer, (void**)(ppContainer));
1504     wxASSERT(SUCCEEDED(hr));
1505 
1506 	return hr;
1507 }
1508 
ShowObject()1509 HRESULT FrameSite::ShowObject()
1510 {
1511 	WXOLE_TRACE("IOleClientSite::ShowObject");
1512 	if (m_window->m_oleObjectHWND)
1513 		::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
1514 	return S_OK;
1515 }
1516 
OnShowWindow(BOOL fShow)1517 HRESULT FrameSite::OnShowWindow(BOOL fShow)
1518 {
1519 	WXOLE_TRACE("IOleClientSite::OnShowWindow");
1520 	return S_OK;
1521 }
1522 
RequestNewObjectLayout()1523 HRESULT FrameSite::RequestNewObjectLayout()
1524 {
1525 	WXOLE_TRACE("IOleClientSite::RequestNewObjectLayout");
1526 	return E_NOTIMPL;
1527 }
1528 
1529 // IParseDisplayName
1530 
ParseDisplayName(IBindCtx * pbc,LPOLESTR pszDisplayName,ULONG * pchEaten,IMoniker ** ppmkOut)1531 HRESULT FrameSite::ParseDisplayName(IBindCtx *pbc, LPOLESTR pszDisplayName,
1532 									ULONG *pchEaten, IMoniker **ppmkOut)
1533 {
1534 	WXOLE_TRACE("IParseDisplayName::ParseDisplayName");
1535 	return E_NOTIMPL;
1536 }
1537 
1538 //IOleContainer
1539 
EnumObjects(DWORD grfFlags,IEnumUnknown ** ppenum)1540 HRESULT FrameSite::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum)
1541 {
1542 	WXOLE_TRACE("IOleContainer::EnumObjects");
1543 	return E_NOTIMPL;
1544 }
1545 
LockContainer(BOOL fLock)1546 HRESULT FrameSite::LockContainer(BOOL fLock)
1547 {
1548 	WXOLE_TRACE("IOleContainer::LockContainer");
1549 	// TODO
1550 	return S_OK;
1551 }
1552 
1553 //IOleItemContainer
1554 
GetObject(LPOLESTR pszItem,DWORD dwSpeedNeeded,IBindCtx * pbc,REFIID riid,void ** ppvObject)1555 HRESULT FrameSite::GetObject(LPOLESTR pszItem, DWORD dwSpeedNeeded,
1556 							 IBindCtx * pbc, REFIID riid, void ** ppvObject)
1557 {
1558 	WXOLE_TRACE("IOleItemContainer::GetObject");
1559 	if (pszItem == NULL)
1560         return E_INVALIDARG;
1561 	if (ppvObject == NULL)
1562         return E_INVALIDARG;
1563 
1564 	*ppvObject = NULL;
1565 	return MK_E_NOOBJECT;
1566 }
1567 
GetObjectStorage(LPOLESTR pszItem,IBindCtx * pbc,REFIID riid,void ** ppvStorage)1568 HRESULT FrameSite::GetObjectStorage(LPOLESTR pszItem, IBindCtx * pbc,
1569 									REFIID riid, void ** ppvStorage)
1570 {
1571 	WXOLE_TRACE("IOleItemContainer::GetObjectStorage");
1572 	if (pszItem == NULL)
1573         return E_INVALIDARG;
1574 	if (ppvStorage == NULL)
1575         return E_INVALIDARG;
1576 
1577 	*ppvStorage = NULL;
1578 	return MK_E_NOOBJECT;
1579 }
1580 
IsRunning(LPOLESTR pszItem)1581 HRESULT FrameSite::IsRunning(LPOLESTR pszItem)
1582 {
1583 	WXOLE_TRACE("IOleItemContainer::IsRunning");
1584 	if (pszItem == NULL)
1585         return E_INVALIDARG;
1586 
1587 	return MK_E_NOOBJECT;
1588 }
1589 
1590 
1591 
1592 //IOleControlSite
1593 
OnControlInfoChanged()1594 HRESULT FrameSite::OnControlInfoChanged()
1595 {
1596 	WXOLE_TRACE("IOleControlSite::OnControlInfoChanged");
1597 	return S_OK;
1598 }
1599 
LockInPlaceActive(BOOL fLock)1600 HRESULT FrameSite::LockInPlaceActive(BOOL fLock)
1601 {
1602 	WXOLE_TRACE("IOleControlSite::LockInPlaceActive");
1603 	m_bInPlaceLocked = (fLock) ? true : false;
1604 	return S_OK;
1605 }
1606 
GetExtendedControl(IDispatch ** ppDisp)1607 HRESULT FrameSite::GetExtendedControl(IDispatch ** ppDisp)
1608 {
1609 	WXOLE_TRACE("IOleControlSite::GetExtendedControl");
1610 	return E_NOTIMPL;
1611 }
1612 
TransformCoords(POINTL * pPtlHimetric,POINTF * pPtfContainer,DWORD dwFlags)1613 HRESULT FrameSite::TransformCoords(POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD dwFlags)
1614 {
1615 	WXOLE_TRACE("IOleControlSite::TransformCoords");
1616 	HRESULT hr = S_OK;
1617 
1618 	if (pPtlHimetric == NULL)
1619 		return E_INVALIDARG;
1620 
1621 	if (pPtfContainer == NULL)
1622 		return E_INVALIDARG;
1623 
1624 	return E_NOTIMPL;
1625 
1626 }
1627 
TranslateAccelerator(LPMSG pMsg,DWORD grfModifiers)1628 HRESULT FrameSite::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
1629 {
1630 	WXOLE_TRACE("IOleControlSite::TranslateAccelerator");
1631 	// TODO: send an event with this id
1632 	return E_NOTIMPL;
1633 }
1634 
OnFocus(BOOL fGotFocus)1635 HRESULT FrameSite::OnFocus(BOOL fGotFocus)
1636 {
1637 	WXOLE_TRACE("IOleControlSite::OnFocus");
1638 	return S_OK;
1639 }
1640 
ShowPropertyFrame()1641 HRESULT FrameSite::ShowPropertyFrame()
1642 {
1643 	WXOLE_TRACE("IOleControlSite::ShowPropertyFrame");
1644 	return E_NOTIMPL;
1645 }
1646 
1647 //IOleCommandTarget
1648 
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD * prgCmds,OLECMDTEXT * pCmdTet)1649 HRESULT FrameSite::QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds,
1650 							   OLECMD * prgCmds, OLECMDTEXT * pCmdTet)
1651 {
1652 	WXOLE_TRACE("IOleCommandTarget::QueryStatus");
1653 	if (prgCmds == NULL) return E_INVALIDARG;
1654 	bool bCmdGroupFound = false;
1655 
1656 	for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
1657 	{
1658 		// unsupported by default
1659 		prgCmds[nCmd].cmdf = 0;
1660 
1661 		// TODO
1662 	}
1663 
1664 	if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
1665 	return S_OK;
1666 }
1667 
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdExecOpt,VARIANTARG * pVaIn,VARIANTARG * pVaOut)1668 HRESULT FrameSite::Exec(const GUID * pguidCmdGroup, DWORD nCmdID,
1669 						DWORD nCmdExecOpt, VARIANTARG * pVaIn,
1670 						VARIANTARG * pVaOut)
1671 {
1672 	WXOLE_TRACE("IOleCommandTarget::Exec");
1673 	bool bCmdGroupFound = false;
1674 
1675 	if (!bCmdGroupFound) { OLECMDERR_E_UNKNOWNGROUP; }
1676 	return OLECMDERR_E_NOTSUPPORTED;
1677 }
1678 
1679 //IAdviseSink
1680 
OnDataChange(FORMATETC * pFormatEtc,STGMEDIUM * pgStgMed)1681 void STDMETHODCALLTYPE FrameSite::OnDataChange(FORMATETC * pFormatEtc, STGMEDIUM * pgStgMed)
1682 {
1683 	WXOLE_TRACE("IAdviseSink::OnDataChange");
1684 }
1685 
OnViewChange(DWORD dwAspect,LONG lIndex)1686 void STDMETHODCALLTYPE FrameSite::OnViewChange(DWORD dwAspect, LONG lIndex)
1687 {
1688 	WXOLE_TRACE("IAdviseSink::OnViewChange");
1689 	// redraw the control
1690 }
1691 
OnRename(IMoniker * pmk)1692 void STDMETHODCALLTYPE FrameSite::OnRename(IMoniker * pmk)
1693 {
1694 	WXOLE_TRACE("IAdviseSink::OnRename");
1695 }
1696 
OnSave()1697 void STDMETHODCALLTYPE FrameSite::OnSave()
1698 {
1699 	WXOLE_TRACE("IAdviseSink::OnSave");
1700 }
1701 
OnClose()1702 void STDMETHODCALLTYPE FrameSite::OnClose()
1703 {
1704 	WXOLE_TRACE("IAdviseSink::OnClose");
1705 }
1706 
1707 /////////////////////////////////////////////
1708 // IOleDocumentSite
ActivateMe(IOleDocumentView __RPC_FAR * pViewToActivate)1709 HRESULT STDMETHODCALLTYPE FrameSite::ActivateMe(
1710         /* [in] */ IOleDocumentView __RPC_FAR *pViewToActivate)
1711 {
1712     wxAutoOleInterface<IOleInPlaceSite> inPlaceSite(IID_IOleInPlaceSite, (IDispatch *) this);
1713     if (!inPlaceSite.Ok())
1714     	return E_FAIL;
1715 
1716     if (pViewToActivate)
1717     {
1718     	m_window->m_docView = pViewToActivate;
1719         m_window->m_docView->SetInPlaceSite(inPlaceSite);
1720     }
1721     else
1722     {
1723     	wxAutoOleInterface<IOleDocument> oleDoc(IID_IOleDocument, m_window->m_oleObject);
1724         if (! oleDoc.Ok())
1725         	return E_FAIL;
1726 
1727         HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL, 0, m_window->m_docView.GetRef());
1728         if (hr != S_OK)
1729         	return E_FAIL;
1730 
1731 		m_window->m_docView->SetInPlaceSite(inPlaceSite);
1732     };
1733 
1734     m_window->m_docView->UIActivate(TRUE);
1735 
1736     return S_OK;
1737 };
1738 
1739 
1740 
1741 static IMalloc *iMalloc = NULL;
1742 
GetIMalloc()1743 IMalloc *wxOleInit::GetIMalloc()
1744 {
1745 	assert(iMalloc);
1746 	return iMalloc;
1747 };
1748 
wxOleInit()1749 wxOleInit::wxOleInit()
1750 {
1751     if (OleInitialize(NULL) == S_OK && iMalloc == NULL)
1752 	    CoGetMalloc(1, &iMalloc);
1753     else if (iMalloc)
1754     	iMalloc->AddRef();
1755 };
1756 
~wxOleInit()1757 wxOleInit::~wxOleInit()
1758 {
1759 	if (iMalloc)
1760     {
1761     	if (iMalloc->Release() == 0)
1762         	iMalloc = NULL;
1763     };
1764 
1765     OleUninitialize();
1766 }
1767 
OLEHResultToString(HRESULT hr)1768 wxString OLEHResultToString(HRESULT hr)
1769 {
1770     switch (hr)
1771     {
1772     case S_OK:
1773     	return _T("");
1774 
1775     case OLECMDERR_E_UNKNOWNGROUP:
1776 		return _T("The pguidCmdGroup parameter is not NULL but does not specify a recognized command group.");
1777 
1778     case OLECMDERR_E_NOTSUPPORTED:
1779 		return _T("The nCmdID parameter is not a valid command in the group identified by pguidCmdGroup.");
1780 
1781     case OLECMDERR_E_DISABLED:
1782 		return _T("The command identified by nCmdID is currently disabled and cannot be executed.");
1783 
1784     case OLECMDERR_E_NOHELP:
1785 		return _T("The caller has asked for help on the command identified by nCmdID, but no help is available.");
1786 
1787     case OLECMDERR_E_CANCELED:
1788 		return _T("The user canceled the execution of the command.");
1789 
1790     case E_INVALIDARG:
1791         return _T("E_INVALIDARG");
1792 
1793     case E_OUTOFMEMORY:
1794         return _T("E_OUTOFMEMORY");
1795 
1796     case E_NOINTERFACE:
1797         return _T("E_NOINTERFACE");
1798 
1799     case E_UNEXPECTED:
1800         return _T("E_UNEXPECTED");
1801 
1802     case STG_E_INVALIDFLAG:
1803         return _T("STG_E_INVALIDFLAG");
1804 
1805     case E_FAIL:
1806         return _T("E_FAIL");
1807 
1808     case E_NOTIMPL:
1809         return _T("E_NOTIMPL");
1810 
1811     default:
1812         {
1813             wxString s;
1814             s.Printf(_T("Unknown - 0x%X"), hr);
1815             return s;
1816         }
1817     };
1818 };
1819 
1820 // borrowed from src/msw/ole/oleutils.cpp
GetIIDName(REFIID riid)1821 wxString GetIIDName(REFIID riid)
1822 {
1823   // an association between symbolic name and numeric value of an IID
1824   struct KNOWN_IID
1825   {
1826     const IID  *pIid;
1827     const wxChar *szName;
1828   };
1829 
1830   // construct the table containing all known interfaces
1831   #define ADD_KNOWN_IID(name) { &IID_I##name, _T(#name) }
1832   #define ADD_KNOWN_GUID(name) { &name, _T(#name) }
1833 
1834   static const KNOWN_IID aKnownIids[] =
1835   {
1836     ADD_KNOWN_IID(AdviseSink),
1837     ADD_KNOWN_IID(AdviseSink2),
1838     ADD_KNOWN_IID(BindCtx),
1839     ADD_KNOWN_IID(ClassFactory),
1840 #if ( !defined( __VISUALC__) || (__VISUALC__!=1010) ) && !defined(__MWERKS__)
1841     ADD_KNOWN_IID(ContinueCallback),
1842     ADD_KNOWN_IID(EnumOleDocumentViews),
1843     ADD_KNOWN_IID(OleCommandTarget),
1844     ADD_KNOWN_IID(OleDocument),
1845     ADD_KNOWN_IID(OleDocumentSite),
1846     ADD_KNOWN_IID(OleDocumentView),
1847     ADD_KNOWN_IID(Print),
1848 #endif
1849     ADD_KNOWN_IID(DataAdviseHolder),
1850     ADD_KNOWN_IID(DataObject),
1851     ADD_KNOWN_IID(Debug),
1852     ADD_KNOWN_IID(DebugStream),
1853     ADD_KNOWN_IID(DfReserved1),
1854     ADD_KNOWN_IID(DfReserved2),
1855     ADD_KNOWN_IID(DfReserved3),
1856     ADD_KNOWN_IID(Dispatch),
1857     ADD_KNOWN_IID(DropSource),
1858     ADD_KNOWN_IID(DropTarget),
1859     ADD_KNOWN_IID(EnumCallback),
1860     ADD_KNOWN_IID(EnumFORMATETC),
1861     ADD_KNOWN_IID(EnumGeneric),
1862     ADD_KNOWN_IID(EnumHolder),
1863     ADD_KNOWN_IID(EnumMoniker),
1864     ADD_KNOWN_IID(EnumOLEVERB),
1865     ADD_KNOWN_IID(EnumSTATDATA),
1866     ADD_KNOWN_IID(EnumSTATSTG),
1867     ADD_KNOWN_IID(EnumString),
1868     ADD_KNOWN_IID(EnumUnknown),
1869     ADD_KNOWN_IID(EnumVARIANT),
1870     ADD_KNOWN_IID(ExternalConnection),
1871     ADD_KNOWN_IID(InternalMoniker),
1872     ADD_KNOWN_IID(LockBytes),
1873     ADD_KNOWN_IID(Malloc),
1874     ADD_KNOWN_IID(Marshal),
1875     ADD_KNOWN_IID(MessageFilter),
1876     ADD_KNOWN_IID(Moniker),
1877     ADD_KNOWN_IID(OleAdviseHolder),
1878     ADD_KNOWN_IID(OleCache),
1879     ADD_KNOWN_IID(OleCache2),
1880     ADD_KNOWN_IID(OleCacheControl),
1881     ADD_KNOWN_IID(OleClientSite),
1882     ADD_KNOWN_IID(OleContainer),
1883     ADD_KNOWN_IID(OleInPlaceActiveObject),
1884     ADD_KNOWN_IID(OleInPlaceFrame),
1885     ADD_KNOWN_IID(OleInPlaceObject),
1886     ADD_KNOWN_IID(OleInPlaceSite),
1887     ADD_KNOWN_IID(OleInPlaceUIWindow),
1888     ADD_KNOWN_IID(OleItemContainer),
1889     ADD_KNOWN_IID(OleLink),
1890     ADD_KNOWN_IID(OleManager),
1891     ADD_KNOWN_IID(OleObject),
1892     ADD_KNOWN_IID(OlePresObj),
1893     ADD_KNOWN_IID(OleWindow),
1894     ADD_KNOWN_IID(PSFactory),
1895     ADD_KNOWN_IID(ParseDisplayName),
1896     ADD_KNOWN_IID(Persist),
1897     ADD_KNOWN_IID(PersistFile),
1898     ADD_KNOWN_IID(PersistStorage),
1899     ADD_KNOWN_IID(PersistStream),
1900     ADD_KNOWN_IID(ProxyManager),
1901     ADD_KNOWN_IID(RootStorage),
1902     ADD_KNOWN_IID(RpcChannel),
1903     ADD_KNOWN_IID(RpcProxy),
1904     ADD_KNOWN_IID(RpcStub),
1905     ADD_KNOWN_IID(RunnableObject),
1906     ADD_KNOWN_IID(RunningObjectTable),
1907     ADD_KNOWN_IID(StdMarshalInfo),
1908     ADD_KNOWN_IID(Storage),
1909     ADD_KNOWN_IID(Stream),
1910     ADD_KNOWN_IID(StubManager),
1911     ADD_KNOWN_IID(Unknown),
1912     ADD_KNOWN_IID(ViewObject),
1913     ADD_KNOWN_IID(ViewObject2),
1914     ADD_KNOWN_GUID(IID_IDispatch),
1915     ADD_KNOWN_GUID(IID_IWebBrowser),
1916     ADD_KNOWN_GUID(IID_IWebBrowserApp),
1917     ADD_KNOWN_GUID(IID_IWebBrowser2),
1918     ADD_KNOWN_GUID(IID_IWebBrowser),
1919     ADD_KNOWN_GUID(DIID_DWebBrowserEvents2),
1920     ADD_KNOWN_GUID(DIID_DWebBrowserEvents),
1921   };
1922 
1923   // don't clobber preprocessor name space
1924   #undef ADD_KNOWN_IID
1925   #undef ADD_KNOWN_GUID
1926 
1927   // try to find the interface in the table
1928   for ( size_t ui = 0; ui < WXSIZEOF(aKnownIids); ui++ )
1929   {
1930     if ( riid == *aKnownIids[ui].pIid )
1931     {
1932       return aKnownIids[ui].szName;
1933     }
1934   }
1935 
1936   // unknown IID, just transform to string
1937   LPOLESTR str = NULL;
1938   StringFromIID(riid, &str);
1939   if (str)
1940   {
1941       wxString s = str;
1942       CoTaskMemFree(str);
1943       return s;
1944   }
1945   else
1946       return _T("StringFromIID() error");
1947 }
1948