src/activeqt/control/qaxserverbase.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the ActiveQt framework of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:BSD$
       
    10 ** You may use this file under the terms of the BSD license as follows:
       
    11 **
       
    12 ** "Redistribution and use in source and binary forms, with or without
       
    13 ** modification, are permitted provided that the following conditions are
       
    14 ** met:
       
    15 **   * Redistributions of source code must retain the above copyright
       
    16 **     notice, this list of conditions and the following disclaimer.
       
    17 **   * Redistributions in binary form must reproduce the above copyright
       
    18 **     notice, this list of conditions and the following disclaimer in
       
    19 **     the documentation and/or other materials provided with the
       
    20 **     distribution.
       
    21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
       
    22 **     the names of its contributors may be used to endorse or promote
       
    23 **     products derived from this software without specific prior written
       
    24 **     permission.
       
    25 **
       
    26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
       
    37 ** $QT_END_LICENSE$
       
    38 **
       
    39 ****************************************************************************/
       
    40 
       
    41 #define QT_NO_CAST_TO_ASCII
       
    42 
       
    43 #ifndef QT_NO_WIN_ACTIVEQT
       
    44 
       
    45 #include <qabstracteventdispatcher.h>
       
    46 #include <qapplication.h>
       
    47 #include <qbuffer.h>
       
    48 #include <qdatastream.h>
       
    49 #include <qdebug.h>
       
    50 #include <qevent.h>
       
    51 #include <qeventloop.h>
       
    52 #include <qfile.h>
       
    53 #include <qpointer.h>
       
    54 #include <qhash.h>
       
    55 #include <qmap.h>
       
    56 #include <qmenubar.h>
       
    57 #include <qmenu.h>
       
    58 #include <qmetaobject.h>
       
    59 #include <qpixmap.h>
       
    60 #include <qstatusbar.h>
       
    61 #include <qwhatsthis.h>
       
    62 #include <ocidl.h>
       
    63 #include <olectl.h>
       
    64 #include <private/qcoreapplication_p.h>
       
    65 
       
    66 #include "qaxfactory.h"
       
    67 #include "qaxbindable.h"
       
    68 #include "qaxaggregated.h"
       
    69 
       
    70 #include "../shared/qaxtypes.h"
       
    71 
       
    72 #if defined Q_CC_GNU
       
    73 #   include <w32api.h>
       
    74 #endif
       
    75 
       
    76 #ifndef Q_OS_WIN64
       
    77 #define ULONG_PTR DWORD
       
    78 #endif
       
    79 
       
    80 QT_BEGIN_NAMESPACE
       
    81 
       
    82 extern HHOOK qax_hhook;
       
    83 
       
    84 // in qaxserver.cpp
       
    85 extern ITypeLib *qAxTypeLibrary;
       
    86 extern QAxFactory *qAxFactory();
       
    87 extern unsigned long qAxLock();
       
    88 extern unsigned long qAxUnlock();
       
    89 extern HANDLE qAxInstance;
       
    90 extern bool qAxOutProcServer;
       
    91 
       
    92 static int invokeCount = 0;
       
    93 
       
    94 #ifdef QT_DEBUG
       
    95 unsigned long qaxserverbase_instance_count = 0;
       
    96 #endif
       
    97 
       
    98 // in qaxserverdll.cpp
       
    99 extern bool qax_ownQApp;
       
   100 
       
   101 struct QAxExceptInfo
       
   102 {
       
   103     QAxExceptInfo(int c, const QString &s, const QString &d, const QString &x)
       
   104 	: code(c), src(s), desc(d), context(x)
       
   105     {
       
   106     }
       
   107     int code;
       
   108     QString src;
       
   109     QString desc;
       
   110     QString context;
       
   111 };
       
   112 
       
   113 
       
   114 bool qt_sendSpontaneousEvent(QObject*, QEvent*);
       
   115 
       
   116 /*
       
   117     \class QAxServerBase
       
   118     \brief The QAxServerBase class is an ActiveX control hosting a QWidget.
       
   119 
       
   120     \internal
       
   121 */
       
   122 class QAxServerBase :
       
   123     public QObject,
       
   124     public IAxServerBase,
       
   125     public IDispatch,
       
   126     public IOleObject,
       
   127     public IOleControl,
       
   128 #if defined Q_CC_GNU
       
   129 #   if (__W32API_MAJOR_VERSION < 2 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION < 5))
       
   130     public IViewObject, // this should not be needed as IViewObject2 is meant to inherit from this,
       
   131                         // untill the mingw headers are fixed this will need to stay.
       
   132 #   endif
       
   133 #endif
       
   134     public IViewObject2,
       
   135     public IOleInPlaceObject,
       
   136     public IOleInPlaceActiveObject,
       
   137     public IProvideClassInfo2,
       
   138     public IConnectionPointContainer,
       
   139     public IPersistStream,
       
   140     public IPersistStreamInit,
       
   141     public IPersistStorage,
       
   142     public IPersistPropertyBag,
       
   143     public IPersistFile,
       
   144     public IDataObject
       
   145 {
       
   146 public:
       
   147     typedef QMap<QUuid,IConnectionPoint*> ConnectionPoints;
       
   148     typedef QMap<QUuid,IConnectionPoint*>::Iterator ConnectionPointsIterator;
       
   149 
       
   150     QAxServerBase(const QString &classname, IUnknown *outerUnknown);
       
   151     QAxServerBase(QObject *o);
       
   152 
       
   153     void init();
       
   154 
       
   155     ~QAxServerBase();
       
   156 
       
   157 // Window creation
       
   158     HWND create(HWND hWndParent, RECT& rcPos);
       
   159     HMENU createPopup(QMenu *popup, HMENU oldMenu = 0);
       
   160     void createMenu(QMenuBar *menuBar);
       
   161     void removeMenu();
       
   162 
       
   163     static LRESULT CALLBACK ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
       
   164 
       
   165 // Object registration with OLE
       
   166     void registerActiveObject(IUnknown *object);
       
   167     void revokeActiveObject();
       
   168 
       
   169 // IUnknown
       
   170     unsigned long WINAPI AddRef()
       
   171     {
       
   172 	if (m_outerUnknown)
       
   173 	    return m_outerUnknown->AddRef();
       
   174 
       
   175 	EnterCriticalSection(&refCountSection);
       
   176 	unsigned long r = ++ref;
       
   177 	LeaveCriticalSection(&refCountSection);
       
   178 
       
   179 	return r;
       
   180     }
       
   181     unsigned long WINAPI Release()
       
   182     {
       
   183     	if (m_outerUnknown)
       
   184 	    return m_outerUnknown->Release();
       
   185 
       
   186 	EnterCriticalSection(&refCountSection);
       
   187 	unsigned long r = --ref;
       
   188 	LeaveCriticalSection(&refCountSection);
       
   189 
       
   190 	if (!r) {
       
   191 	    delete this;
       
   192 	    return 0;
       
   193 	}
       
   194 	return r;
       
   195     }
       
   196     HRESULT WINAPI QueryInterface(REFIID iid, void **iface);
       
   197     HRESULT InternalQueryInterface(REFIID iid, void **iface);
       
   198 
       
   199 // IAxServerBase
       
   200     IUnknown *clientSite() const
       
   201     {
       
   202 	return m_spClientSite;
       
   203     }
       
   204 
       
   205     void emitPropertyChanged(const char*);
       
   206     bool emitRequestPropertyChange(const char*);
       
   207     QObject *qObject() const
       
   208     {
       
   209 	return theObject;
       
   210     }
       
   211     void ensureMetaData();
       
   212     bool isPropertyExposed(int index);
       
   213 
       
   214     void reportError(int code, const QString &src, const QString &desc, const QString &context)
       
   215     {
       
   216         if (exception)
       
   217             delete exception;
       
   218         exception = new QAxExceptInfo(code, src, desc, context);
       
   219     }
       
   220 
       
   221 // IDispatch
       
   222     STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
       
   223     STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
       
   224     STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid);
       
   225     STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
       
   226 		LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
       
   227 		EXCEPINFO* pexcepinfo, UINT* puArgErr);
       
   228 
       
   229 // IProvideClassInfo
       
   230     STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo);
       
   231 
       
   232 // IProvideClassInfo2
       
   233     STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID);
       
   234 
       
   235 // IOleObject
       
   236     STDMETHOD(Advise)(IAdviseSink* pAdvSink, DWORD* pdwConnection);
       
   237     STDMETHOD(Close)(DWORD dwSaveOption);
       
   238     STDMETHOD(DoVerb)(LONG iVerb, LPMSG lpmsg, IOleClientSite* pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect);
       
   239     STDMETHOD(EnumAdvise)(IEnumSTATDATA** ppenumAdvise);
       
   240     STDMETHOD(EnumVerbs)(IEnumOLEVERB** ppEnumOleVerb);
       
   241     STDMETHOD(GetClientSite)(IOleClientSite** ppClientSite);
       
   242     STDMETHOD(GetClipboardData)(DWORD dwReserved, IDataObject** ppDataObject);
       
   243     STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL* psizel);
       
   244     STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus);
       
   245     STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk);
       
   246     STDMETHOD(GetUserClassID)(CLSID* pClsid);
       
   247     STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType);
       
   248     STDMETHOD(InitFromData)(IDataObject* pDataObject, BOOL fCreation, DWORD dwReserved);
       
   249     STDMETHOD(IsUpToDate)();
       
   250     STDMETHOD(SetClientSite)(IOleClientSite* pClientSite);
       
   251     STDMETHOD(SetColorScheme)(LOGPALETTE* pLogPal);
       
   252     STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel);
       
   253     STDMETHOD(SetHostNames)(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
       
   254     STDMETHOD(SetMoniker)(DWORD dwWhichMoniker, IMoniker* ppmk);
       
   255     STDMETHOD(Unadvise)(DWORD dwConnection);
       
   256     STDMETHOD(Update)();
       
   257 
       
   258 // IViewObject
       
   259     STDMETHOD(Draw)(DWORD dwAspect, LONG lIndex, void *pvAspect, DVTARGETDEVICE *ptd,
       
   260 		    HDC hicTargetDevice, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
       
   261 		    BOOL(__stdcall*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue);
       
   262     STDMETHOD(GetColorSet)(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
       
   263 		    HDC hicTargetDev, LOGPALETTE **ppColorSet);
       
   264     STDMETHOD(Freeze)(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze);
       
   265     STDMETHOD(Unfreeze)(DWORD dwFreeze);
       
   266     STDMETHOD(SetAdvise)(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink);
       
   267     STDMETHOD(GetAdvise)(DWORD *aspects, DWORD *advf, IAdviseSink **pAdvSink);
       
   268 
       
   269 // IViewObject2
       
   270     STDMETHOD(GetExtent)(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel);
       
   271 
       
   272 // IOleControl
       
   273     STDMETHOD(FreezeEvents)(BOOL);
       
   274     STDMETHOD(GetControlInfo)(LPCONTROLINFO);
       
   275     STDMETHOD(OnAmbientPropertyChange)(DISPID);
       
   276     STDMETHOD(OnMnemonic)(LPMSG);
       
   277 
       
   278 // IOleWindow
       
   279     STDMETHOD(GetWindow)(HWND *pHwnd);
       
   280     STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
       
   281 
       
   282 // IOleInPlaceObject
       
   283     STDMETHOD(InPlaceDeactivate)();
       
   284     STDMETHOD(UIDeactivate)();
       
   285     STDMETHOD(SetObjectRects)(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
       
   286     STDMETHOD(ReactivateAndUndo)();
       
   287 
       
   288 // IOleInPlaceActiveObject
       
   289     STDMETHOD(TranslateAcceleratorW)(MSG *pMsg);
       
   290     STDMETHOD(TranslateAcceleratorA)(MSG *pMsg);
       
   291     STDMETHOD(OnFrameWindowActivate)(BOOL);
       
   292     STDMETHOD(OnDocWindowActivate)(BOOL fActivate);
       
   293     STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow);
       
   294     STDMETHOD(EnableModeless)(BOOL);
       
   295 
       
   296 // IConnectionPointContainer
       
   297     STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints**);
       
   298     STDMETHOD(FindConnectionPoint)(REFIID, IConnectionPoint**);
       
   299 
       
   300 // IPersist
       
   301     STDMETHOD(GetClassID)(GUID*clsid)
       
   302     {
       
   303 	*clsid = qAxFactory()->classID(class_name);
       
   304 	return S_OK;
       
   305     }
       
   306 
       
   307 // IPersistStreamInit
       
   308     STDMETHOD(InitNew)(VOID);
       
   309     STDMETHOD(IsDirty)();
       
   310     STDMETHOD(Load)(IStream *pStm);
       
   311     STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
       
   312     STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
       
   313 
       
   314 // IPersistPropertyBag
       
   315     STDMETHOD(Load)(IPropertyBag *, IErrorLog *);
       
   316     STDMETHOD(Save)(IPropertyBag *, BOOL, BOOL);
       
   317 
       
   318 // IPersistStorage
       
   319     STDMETHOD(InitNew)(IStorage *pStg);
       
   320     STDMETHOD(Load)(IStorage *pStg);
       
   321     STDMETHOD(Save)(IStorage *pStg, BOOL fSameAsLoad);
       
   322     STDMETHOD(SaveCompleted)(IStorage *pStgNew);
       
   323     STDMETHOD(HandsOffStorage)();
       
   324 
       
   325 // IPersistFile
       
   326     STDMETHOD(SaveCompleted)(LPCOLESTR fileName);
       
   327     STDMETHOD(GetCurFile)(LPOLESTR *currentFile);
       
   328     STDMETHOD(Load)(LPCOLESTR fileName, DWORD mode);
       
   329     STDMETHOD(Save)(LPCOLESTR fileName, BOOL fRemember);
       
   330 
       
   331 // IDataObject
       
   332     STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
       
   333     STDMETHOD(GetDataHere)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */);
       
   334     STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */);
       
   335     STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */);
       
   336     STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */);
       
   337     STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */);
       
   338     STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
       
   339     STDMETHOD(DUnadvise)(DWORD dwConnection);
       
   340     STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise);
       
   341 
       
   342 // QObject
       
   343     int qt_metacall(QMetaObject::Call, int index, void **argv);
       
   344 
       
   345     bool eventFilter(QObject *o, QEvent *e);
       
   346 private:
       
   347     void update();
       
   348     void resize(const QSize &newSize);
       
   349     void updateGeometry();
       
   350     void updateMask();
       
   351     bool internalCreate();
       
   352     void internalBind();
       
   353     void internalConnect();
       
   354     HRESULT internalActivate();
       
   355 
       
   356     friend class QAxBindable;
       
   357     friend class QAxPropertyPage;
       
   358 
       
   359     QAxAggregated *aggregatedObject;
       
   360     ConnectionPoints points;
       
   361 
       
   362     union {
       
   363 	QWidget *widget;
       
   364 	QObject *object;
       
   365     } qt;
       
   366     QPointer<QObject> theObject;
       
   367     unsigned isWidget		:1;
       
   368     unsigned ownObject		:1;
       
   369     unsigned initNewCalled	:1;
       
   370     unsigned dirtyflag		:1;
       
   371     unsigned hasStockEvents	:1;
       
   372     unsigned stayTopLevel	:1;
       
   373     unsigned isInPlaceActive	:1;
       
   374     unsigned isUIActive		:1;
       
   375     unsigned wasUIActive	:1;
       
   376     unsigned inDesignMode	:1;
       
   377     unsigned canTakeFocus	:1;
       
   378     short freezeEvents;
       
   379 
       
   380     HWND m_hWnd;
       
   381 
       
   382     HMENU hmenuShared;
       
   383     HOLEMENU holemenu;
       
   384     HWND hwndMenuOwner;
       
   385     QMap<HMENU, QMenu*> menuMap;
       
   386     QMap<UINT, QAction*> actionMap;
       
   387     QPointer<QMenuBar> menuBar;
       
   388     QPointer<QStatusBar> statusBar;
       
   389     QPointer<QMenu> currentPopup;
       
   390     QAxExceptInfo *exception;
       
   391 
       
   392     CRITICAL_SECTION refCountSection;
       
   393     CRITICAL_SECTION createWindowSection;
       
   394 
       
   395     unsigned long ref;
       
   396     unsigned long ole_ref;
       
   397 
       
   398     QString class_name;
       
   399     QString currentFileName;
       
   400 
       
   401     QHash<long, int> indexCache;
       
   402     QHash<int,DISPID> signalCache;
       
   403 
       
   404     IUnknown *m_outerUnknown;
       
   405     IAdviseSink *m_spAdviseSink;
       
   406     QList<STATDATA> adviseSinks;
       
   407     IOleClientSite *m_spClientSite;
       
   408     IOleInPlaceSiteWindowless *m_spInPlaceSite;
       
   409     IOleInPlaceFrame *m_spInPlaceFrame;
       
   410     ITypeInfo *m_spTypeInfo;
       
   411     IStorage *m_spStorage;
       
   412     QSize m_currentExtent;
       
   413 };
       
   414 
       
   415 class QAxServerAggregate : public IUnknown
       
   416 {
       
   417 public:
       
   418     QAxServerAggregate(const QString &className, IUnknown *outerUnknown)
       
   419 	: m_outerUnknown(outerUnknown), ref(0)
       
   420     {
       
   421 	object = new QAxServerBase(className, outerUnknown);
       
   422 	object->registerActiveObject(this);
       
   423 
       
   424 	InitializeCriticalSection(&refCountSection);
       
   425 	InitializeCriticalSection(&createWindowSection);
       
   426     }
       
   427     ~QAxServerAggregate()
       
   428     {
       
   429 	DeleteCriticalSection(&refCountSection);
       
   430 	DeleteCriticalSection(&createWindowSection);
       
   431 
       
   432 	delete object;
       
   433     }
       
   434 
       
   435 // IUnknown
       
   436     unsigned long WINAPI AddRef()
       
   437     {
       
   438 	EnterCriticalSection(&refCountSection);
       
   439 	unsigned long r = ++ref;
       
   440 	LeaveCriticalSection(&refCountSection);
       
   441 
       
   442 	return r;
       
   443     }
       
   444     unsigned long WINAPI Release()
       
   445     {
       
   446 	EnterCriticalSection(&refCountSection);
       
   447 	unsigned long r = --ref;
       
   448 	LeaveCriticalSection(&refCountSection);
       
   449 
       
   450 	if (!r) {
       
   451 	    delete this;
       
   452 	    return 0;
       
   453 	}
       
   454 	return r;
       
   455     }
       
   456     HRESULT WINAPI QueryInterface(REFIID iid, void **iface)
       
   457     {
       
   458 	*iface = 0;
       
   459 
       
   460 	HRESULT res = E_NOINTERFACE;
       
   461 	if (iid == IID_IUnknown) {
       
   462 	    *iface = (IUnknown*)this;
       
   463 	    AddRef();
       
   464 	    return S_OK;
       
   465 	}
       
   466 	return object->InternalQueryInterface(iid, iface);
       
   467     }
       
   468 
       
   469 private:
       
   470     QAxServerBase *object;
       
   471     IUnknown *m_outerUnknown;
       
   472     unsigned long ref;
       
   473 
       
   474     CRITICAL_SECTION refCountSection;
       
   475     CRITICAL_SECTION createWindowSection;
       
   476 };
       
   477 
       
   478 bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper)
       
   479 {
       
   480     *wrapper = 0;
       
   481     QAxServerBase *obj = new QAxServerBase(object);
       
   482     obj->QueryInterface(IID_IDispatch, (void**)wrapper);
       
   483     if (*wrapper)
       
   484 	return true;
       
   485 
       
   486     delete obj;
       
   487     return false;
       
   488 }
       
   489 
       
   490 
       
   491 /*
       
   492     Helper class to enumerate all supported event interfaces.
       
   493 */
       
   494 class QAxSignalVec : public IEnumConnectionPoints
       
   495 {
       
   496 public:
       
   497     QAxSignalVec(const QAxServerBase::ConnectionPoints &points)
       
   498 	: cpoints(points), ref(0)
       
   499     {
       
   500 	InitializeCriticalSection(&refCountSection);
       
   501 	for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
       
   502 	    (*i)->AddRef();
       
   503     }
       
   504     QAxSignalVec(const QAxSignalVec &old)
       
   505     {
       
   506 	InitializeCriticalSection(&refCountSection);
       
   507 	ref = 0;
       
   508 	cpoints = old.cpoints;
       
   509 	for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
       
   510 	    (*i)->AddRef();
       
   511 	it = old.it;
       
   512     }
       
   513     ~QAxSignalVec()
       
   514     {
       
   515 	for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i)
       
   516 	    (*i)->Release();
       
   517 
       
   518 	DeleteCriticalSection(&refCountSection);
       
   519     }
       
   520 
       
   521     unsigned long __stdcall AddRef()
       
   522     {
       
   523 	EnterCriticalSection(&refCountSection);
       
   524 	unsigned long r = ++ref;
       
   525 	LeaveCriticalSection(&refCountSection);
       
   526 	return ++r;
       
   527     }
       
   528     unsigned long __stdcall Release()
       
   529     {
       
   530 	EnterCriticalSection(&refCountSection);
       
   531 	unsigned long r = --ref;
       
   532 	LeaveCriticalSection(&refCountSection);
       
   533 
       
   534 	if (!r) {
       
   535 	    delete this;
       
   536 	    return 0;
       
   537 	}
       
   538 	return r;
       
   539     }
       
   540     STDMETHOD(QueryInterface)(REFIID iid, void **iface)
       
   541     {
       
   542 	*iface = 0;
       
   543 	if (iid == IID_IUnknown)
       
   544 	    *iface = this;
       
   545 	else if (iid == IID_IEnumConnectionPoints)
       
   546 	    *iface = this;
       
   547 	else
       
   548 	    return E_NOINTERFACE;
       
   549 
       
   550 	AddRef();
       
   551 	return S_OK;
       
   552     }
       
   553     STDMETHOD(Next)(ULONG cConnections, IConnectionPoint **cpoint, ULONG *pcFetched)
       
   554     {
       
   555 	unsigned long i;
       
   556 	for (i = 0; i < cConnections; i++) {
       
   557 	    if (it == cpoints.end())
       
   558 		break;
       
   559 	    IConnectionPoint *cp = *it;
       
   560 	    cp->AddRef();
       
   561 	    cpoint[i] = cp;
       
   562 	    ++it;
       
   563 	}
       
   564 	*pcFetched = i;
       
   565 	return i == cConnections ? S_OK : S_FALSE;
       
   566     }
       
   567     STDMETHOD(Skip)(ULONG cConnections)
       
   568     {
       
   569 	while (cConnections) {
       
   570 	    ++it;
       
   571 	    --cConnections;
       
   572 	    if (it == cpoints.end())
       
   573 		return S_FALSE;
       
   574 	}
       
   575 	return S_OK;
       
   576     }
       
   577     STDMETHOD(Reset)()
       
   578     {
       
   579 	it = cpoints.begin();
       
   580 
       
   581 	return S_OK;
       
   582     }
       
   583     STDMETHOD(Clone)(IEnumConnectionPoints **ppEnum)
       
   584     {
       
   585 	*ppEnum = new QAxSignalVec(*this);
       
   586 	(*ppEnum)->AddRef();
       
   587 
       
   588 	return S_OK;
       
   589     }
       
   590 
       
   591     QAxServerBase::ConnectionPoints cpoints;
       
   592     QAxServerBase::ConnectionPointsIterator it;
       
   593 
       
   594 private:
       
   595     CRITICAL_SECTION refCountSection;
       
   596 
       
   597     unsigned long ref;
       
   598 };
       
   599 
       
   600 /*
       
   601     Helper class to store and enumerate all connected event listeners.
       
   602 */
       
   603 class QAxConnection : public IConnectionPoint,
       
   604 		      public IEnumConnections
       
   605 {
       
   606 public:
       
   607     typedef QList<CONNECTDATA> Connections;
       
   608     typedef QList<CONNECTDATA>::Iterator Iterator;
       
   609 
       
   610     QAxConnection(QAxServerBase *parent, const QUuid &uuid)
       
   611 	: that(parent), iid(uuid), ref(1)
       
   612     {
       
   613 	InitializeCriticalSection(&refCountSection);
       
   614     }
       
   615     QAxConnection(const QAxConnection &old)
       
   616     {
       
   617 	InitializeCriticalSection(&refCountSection);
       
   618 	ref = 0;
       
   619 	connections = old.connections;
       
   620 	it = old.it;
       
   621 	that = old.that;
       
   622 	iid = old.iid;
       
   623 	QList<CONNECTDATA>::Iterator it = connections.begin();
       
   624 	while (it != connections.end()) {
       
   625 	    CONNECTDATA connection = *it;
       
   626 	    ++it;
       
   627 	    connection.pUnk->AddRef();
       
   628 	}
       
   629     }
       
   630     ~QAxConnection()
       
   631     {
       
   632 	DeleteCriticalSection(&refCountSection);
       
   633     }
       
   634 
       
   635     unsigned long __stdcall AddRef()
       
   636     {
       
   637 	EnterCriticalSection(&refCountSection);
       
   638 	unsigned long r = ++ref;
       
   639 	LeaveCriticalSection(&refCountSection);
       
   640 	return r;
       
   641     }
       
   642     unsigned long __stdcall Release()
       
   643     {
       
   644 	EnterCriticalSection(&refCountSection);
       
   645 	unsigned long r = --ref;
       
   646 	LeaveCriticalSection(&refCountSection);
       
   647 
       
   648 	if (!r) {
       
   649 	    delete this;
       
   650 	    return 0;
       
   651 	}
       
   652 	return r;
       
   653     }
       
   654     STDMETHOD(QueryInterface)(REFIID iid, void **iface)
       
   655     {
       
   656 	*iface = 0;
       
   657 	if (iid == IID_IUnknown)
       
   658 	    *iface = (IConnectionPoint*)this;
       
   659 	else if (iid == IID_IConnectionPoint)
       
   660 	    *iface = this;
       
   661 	else if (iid == IID_IEnumConnections)
       
   662 	    *iface = this;
       
   663 	else
       
   664 	    return E_NOINTERFACE;
       
   665 
       
   666 	AddRef();
       
   667 	return S_OK;
       
   668     }
       
   669     STDMETHOD(GetConnectionInterface)(IID *pIID)
       
   670     {
       
   671 	*pIID = iid;
       
   672 	return S_OK;
       
   673     }
       
   674     STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC)
       
   675     {
       
   676 	return that->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC);
       
   677     }
       
   678     STDMETHOD(Advise)(IUnknown*pUnk, DWORD *pdwCookie)
       
   679     {
       
   680 	{
       
   681 	    IDispatch *checkImpl = 0;
       
   682 	    pUnk->QueryInterface(iid, (void**)&checkImpl);
       
   683 	    if (!checkImpl)
       
   684 		return CONNECT_E_CANNOTCONNECT;
       
   685 	    checkImpl->Release();
       
   686 	}
       
   687 
       
   688 	CONNECTDATA cd;
       
   689 	cd.dwCookie = connections.count()+1;
       
   690 	cd.pUnk = pUnk;
       
   691 	cd.pUnk->AddRef();
       
   692 	connections.append(cd);
       
   693 
       
   694 	*pdwCookie = cd.dwCookie;
       
   695 	return S_OK;
       
   696     }
       
   697     STDMETHOD(Unadvise)(DWORD dwCookie)
       
   698     {
       
   699 	QList<CONNECTDATA>::Iterator it = connections.begin();
       
   700 	while (it != connections.end()) {
       
   701 	    CONNECTDATA cd = *it;
       
   702 	    if (cd.dwCookie == dwCookie) {
       
   703 		cd.pUnk->Release();
       
   704 		connections.erase(it);
       
   705 		return S_OK;
       
   706 	    }
       
   707 	    ++it;
       
   708 	}
       
   709 	return CONNECT_E_NOCONNECTION;
       
   710     }
       
   711     STDMETHOD(EnumConnections)(IEnumConnections **ppEnum)
       
   712     {
       
   713 	*ppEnum = this;
       
   714 	AddRef();
       
   715 
       
   716 	return S_OK;
       
   717     }
       
   718     STDMETHOD(Next)(ULONG cConnections, CONNECTDATA *cd, ULONG *pcFetched)
       
   719     {
       
   720 	unsigned long i;
       
   721 	for (i = 0; i < cConnections; i++) {
       
   722 	    if (it == connections.end())
       
   723 		break;
       
   724 	    cd[i] = *it;
       
   725 	    cd[i].pUnk->AddRef();
       
   726 	    ++it;
       
   727 	}
       
   728 	if (pcFetched)
       
   729 	    *pcFetched = i;
       
   730 	return i == cConnections ? S_OK : S_FALSE;
       
   731     }
       
   732     STDMETHOD(Skip)(ULONG cConnections)
       
   733     {
       
   734 	while (cConnections) {
       
   735 	    ++it;
       
   736 	    --cConnections;
       
   737 	    if (it == connections.end())
       
   738 		return S_FALSE;
       
   739 	}
       
   740 	return S_OK;
       
   741     }
       
   742     STDMETHOD(Reset)()
       
   743     {
       
   744 	it = connections.begin();
       
   745 
       
   746 	return S_OK;
       
   747     }
       
   748     STDMETHOD(Clone)(IEnumConnections **ppEnum)
       
   749     {
       
   750 	*ppEnum = new QAxConnection(*this);
       
   751 	(*ppEnum)->AddRef();
       
   752 
       
   753 	return S_OK;
       
   754     }
       
   755 
       
   756 private:
       
   757     QAxServerBase *that;
       
   758     QUuid iid;
       
   759     Connections connections;
       
   760     Iterator it;
       
   761 
       
   762     CRITICAL_SECTION refCountSection;
       
   763     unsigned long ref;
       
   764 };
       
   765 
       
   766 // callback for DLL server to hook into non-Qt eventloop
       
   767 LRESULT CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam)
       
   768 {
       
   769     if (qApp && !invokeCount)
       
   770         qApp->sendPostedEvents();
       
   771 
       
   772     return CallNextHookEx(qax_hhook, nCode, wParam, lParam);
       
   773 }
       
   774 
       
   775 // filter for executable case to hook into Qt eventloop
       
   776 // for DLLs the client calls TranslateAccelerator
       
   777 bool qax_winEventFilter(void *message)
       
   778 {
       
   779     MSG *pMsg = (MSG*)message;
       
   780     if (pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST)
       
   781 	return false;
       
   782 
       
   783     bool ret = false;
       
   784     QWidget *aqt = QWidget::find(pMsg->hwnd);
       
   785     if (!aqt)
       
   786 	return ret;
       
   787 
       
   788     HWND baseHwnd = ::GetParent(aqt->winId());
       
   789     QAxServerBase *axbase = 0;
       
   790     while (!axbase && baseHwnd) {
       
   791 #ifdef GWLP_USERDATA
       
   792         axbase = (QAxServerBase*)GetWindowLongPtr(baseHwnd, GWLP_USERDATA);
       
   793 #else
       
   794         axbase = (QAxServerBase*)GetWindowLong(baseHwnd, GWL_USERDATA);
       
   795 #endif
       
   796 
       
   797 	baseHwnd = ::GetParent(baseHwnd);
       
   798     }
       
   799     if (!axbase)
       
   800 	return ret;
       
   801 
       
   802     HRESULT hres = axbase->TranslateAcceleratorW(pMsg);
       
   803     return hres == S_OK;
       
   804 }
       
   805 
       
   806 extern void qWinMsgHandler(QtMsgType t, const char* str);
       
   807 
       
   808 // COM Factory class, mapping COM requests to ActiveQt requests.
       
   809 // One instance of this class for each ActiveX the server can provide.
       
   810 class QClassFactory : public IClassFactory2
       
   811 {
       
   812 public:
       
   813     QClassFactory(CLSID clsid)
       
   814 	: ref(0), licensed(false)
       
   815     {
       
   816 	InitializeCriticalSection(&refCountSection);
       
   817 
       
   818 	// COM only knows the CLSID, but QAxFactory is class name based...
       
   819 	QStringList keys = qAxFactory()->featureList();
       
   820 	for (QStringList::Iterator  key = keys.begin(); key != keys.end(); ++key) {
       
   821 	    if (qAxFactory()->classID(*key) == clsid) {
       
   822 		className = *key;
       
   823 		break;
       
   824 	    }
       
   825 	}
       
   826 
       
   827 	const QMetaObject *mo = qAxFactory()->metaObject(className);
       
   828 	if (mo) {
       
   829 	    classKey = QLatin1String(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value());
       
   830 	    licensed = !classKey.isEmpty();
       
   831 	}
       
   832     }
       
   833 
       
   834     ~QClassFactory()
       
   835     {
       
   836 	DeleteCriticalSection(&refCountSection);
       
   837     }
       
   838 
       
   839     // IUnknown
       
   840     unsigned long WINAPI AddRef()
       
   841     {
       
   842 	EnterCriticalSection(&refCountSection);
       
   843 	unsigned long r = ++ref;
       
   844 	LeaveCriticalSection(&refCountSection);
       
   845 	return ++r;
       
   846     }
       
   847     unsigned long WINAPI Release()
       
   848     {
       
   849 	EnterCriticalSection(&refCountSection);
       
   850 	unsigned long r = --ref;
       
   851 	LeaveCriticalSection(&refCountSection);
       
   852 
       
   853 	if (!r) {
       
   854 	    delete this;
       
   855 	    return 0;
       
   856 	}
       
   857 	return r;
       
   858     }
       
   859     HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface)
       
   860     {
       
   861 	*iface = 0;
       
   862 	if (iid == IID_IUnknown)
       
   863 	    *iface = (IUnknown*)this;
       
   864 	else if (iid == IID_IClassFactory)
       
   865 	    *iface = (IClassFactory*)this;
       
   866 	else if (iid == IID_IClassFactory2 && licensed)
       
   867 	    *iface = (IClassFactory2*)this;
       
   868 	else
       
   869 	    return E_NOINTERFACE;
       
   870 
       
   871 	AddRef();
       
   872 	return S_OK;
       
   873     }
       
   874 
       
   875     HRESULT WINAPI CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject)
       
   876     {
       
   877 	if (pUnkOuter) {
       
   878 	    if (iid != IID_IUnknown)
       
   879 		return CLASS_E_NOAGGREGATION;
       
   880 	    const QMetaObject *mo = qAxFactory()->metaObject(className);
       
   881 	    if (mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no"))
       
   882 		return CLASS_E_NOAGGREGATION;
       
   883 	}
       
   884 
       
   885     	// Make sure a QApplication instance is present (inprocess case)
       
   886         if (!qApp) {
       
   887             qInstallMsgHandler(qWinMsgHandler);
       
   888             qax_ownQApp = true;
       
   889             int argc = 0;
       
   890             QApplication *app = new QApplication(argc, 0);
       
   891         }
       
   892         qApp->setQuitOnLastWindowClosed(false);
       
   893 
       
   894         if (qAxOutProcServer)
       
   895             QAbstractEventDispatcher::instance()->setEventFilter(qax_winEventFilter);
       
   896         else
       
   897             QApplication::instance()->d_func()->in_exec = true;
       
   898 
       
   899         // hook into eventloop; this allows a server to create his own QApplication object
       
   900         if (!qax_hhook && qax_ownQApp) {
       
   901             qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId());
       
   902         }
       
   903 
       
   904 	HRESULT res;
       
   905 	// Create the ActiveX wrapper - aggregate if requested
       
   906 	if (pUnkOuter) {
       
   907 	    QAxServerAggregate *aggregate = new QAxServerAggregate(className, pUnkOuter);
       
   908 	    res = aggregate->QueryInterface(iid, ppObject);
       
   909 	    if (FAILED(res))
       
   910 		delete aggregate;
       
   911 	} else {
       
   912 	    QAxServerBase *activeqt = new QAxServerBase(className, pUnkOuter);
       
   913 	    res = activeqt->QueryInterface(iid, ppObject);
       
   914 	    if (FAILED(res))
       
   915 		delete activeqt;
       
   916 	    else
       
   917 		activeqt->registerActiveObject((IUnknown*)(IDispatch*)activeqt);
       
   918 	}
       
   919 	return res;
       
   920     }
       
   921 
       
   922     // IClassFactory
       
   923     HRESULT WINAPI CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject)
       
   924     {
       
   925 	// class is licensed
       
   926 	if (licensed && !qAxFactory()->validateLicenseKey(className, QString()))
       
   927 	    return CLASS_E_NOTLICENSED;
       
   928 
       
   929 	return CreateInstanceHelper(pUnkOuter, iid, ppObject);
       
   930     }
       
   931     HRESULT WINAPI LockServer(BOOL fLock)
       
   932     {
       
   933 	if (fLock)
       
   934 	    qAxLock();
       
   935 	else
       
   936 	    qAxUnlock();
       
   937 
       
   938 	return S_OK;
       
   939     }
       
   940 
       
   941     // IClassFactory2
       
   942     HRESULT WINAPI RequestLicKey(DWORD, BSTR *pKey)
       
   943     {
       
   944 	if (!pKey)
       
   945 	    return E_POINTER;
       
   946 	*pKey = 0;
       
   947 
       
   948 	// This of course works only on fully licensed machines
       
   949 	if (!qAxFactory()->validateLicenseKey(className, QString()))
       
   950 	    return CLASS_E_NOTLICENSED;
       
   951 
       
   952 	*pKey = QStringToBSTR(classKey);
       
   953 	return S_OK;
       
   954     }
       
   955 
       
   956     HRESULT WINAPI GetLicInfo(LICINFO *pLicInfo)
       
   957     {
       
   958 	if (!pLicInfo)
       
   959 	    return E_POINTER;
       
   960 	pLicInfo->cbLicInfo = sizeof(LICINFO);
       
   961 
       
   962 	// class specific license key?
       
   963 	const QMetaObject *mo = qAxFactory()->metaObject(className);
       
   964 	const char *key = mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value();
       
   965 	pLicInfo->fRuntimeKeyAvail = key && key[0];
       
   966 
       
   967 	// machine fully licensed?
       
   968 	pLicInfo->fLicVerified = qAxFactory()->validateLicenseKey(className, QString());
       
   969 
       
   970 	return S_OK;
       
   971     }
       
   972 
       
   973     HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID iid, BSTR bKey, PVOID *ppObject)
       
   974     {
       
   975         QString licenseKey = QString::fromWCharArray(bKey);
       
   976 	if (!qAxFactory()->validateLicenseKey(className, licenseKey))
       
   977 	    return CLASS_E_NOTLICENSED;
       
   978 	return CreateInstanceHelper(pUnkOuter, iid, ppObject);
       
   979     }
       
   980 
       
   981     QString className;
       
   982 
       
   983 protected:
       
   984     CRITICAL_SECTION refCountSection;
       
   985     unsigned long ref;
       
   986     bool licensed;
       
   987     QString classKey;
       
   988 };
       
   989 
       
   990 // Create a QClassFactory object for class \a iid
       
   991 HRESULT GetClassObject(REFIID clsid, REFIID iid, void **ppUnk)
       
   992 {
       
   993     QClassFactory *factory = new QClassFactory(clsid);
       
   994     if (!factory)
       
   995 	return E_OUTOFMEMORY;
       
   996     if (factory->className.isEmpty()) {
       
   997 	delete factory;
       
   998 	return E_NOINTERFACE;
       
   999     }
       
  1000     HRESULT res = factory->QueryInterface(iid, ppUnk);
       
  1001     if (res != S_OK)
       
  1002 	delete factory;
       
  1003     return res;
       
  1004 }
       
  1005 
       
  1006 
       
  1007 /*!
       
  1008     Constructs a QAxServerBase object wrapping the QWidget \a
       
  1009     classname into an ActiveX control.
       
  1010 
       
  1011     The constructor is called by the QClassFactory object provided by
       
  1012     the COM server for the respective CLSID.
       
  1013 */
       
  1014 QAxServerBase::QAxServerBase(const QString &classname, IUnknown *outerUnknown)
       
  1015 : aggregatedObject(0), ref(0), ole_ref(0), class_name(classname),
       
  1016   m_hWnd(0), hmenuShared(0), hwndMenuOwner(0),
       
  1017   m_outerUnknown(outerUnknown)
       
  1018 {
       
  1019     init();
       
  1020 
       
  1021     internalCreate();
       
  1022 }
       
  1023 
       
  1024 /*!
       
  1025     Constructs a QAxServerBase object wrapping \a o.
       
  1026 */
       
  1027 QAxServerBase::QAxServerBase(QObject *o)
       
  1028 : aggregatedObject(0), ref(0), ole_ref(0),
       
  1029   m_hWnd(0), hmenuShared(0), hwndMenuOwner(0),
       
  1030   m_outerUnknown(0)
       
  1031 {
       
  1032     init();
       
  1033 
       
  1034     qt.object = o;
       
  1035     if (o) {
       
  1036 	theObject = o;
       
  1037 	isWidget = false;
       
  1038 	class_name = QLatin1String(o->metaObject()->className());
       
  1039     }
       
  1040     internalBind();
       
  1041     internalConnect();
       
  1042 }
       
  1043 
       
  1044 /*!
       
  1045     Initializes data members.
       
  1046 */
       
  1047 void QAxServerBase::init()
       
  1048 {
       
  1049     qt.object = 0;
       
  1050     isWidget		= false;
       
  1051     ownObject		= false;
       
  1052     initNewCalled	= false;
       
  1053     dirtyflag		= false;
       
  1054     hasStockEvents	= false;
       
  1055     stayTopLevel	= false;
       
  1056     isInPlaceActive	= false;
       
  1057     isUIActive		= false;
       
  1058     wasUIActive		= false;
       
  1059     inDesignMode	= false;
       
  1060     canTakeFocus	= false;
       
  1061     freezeEvents = 0;
       
  1062     exception = 0;
       
  1063 
       
  1064     m_spAdviseSink = 0;
       
  1065     m_spClientSite = 0;
       
  1066     m_spInPlaceSite = 0;
       
  1067     m_spInPlaceFrame = 0;
       
  1068     m_spTypeInfo = 0;
       
  1069     m_spStorage = 0;
       
  1070 
       
  1071     InitializeCriticalSection(&refCountSection);
       
  1072     InitializeCriticalSection(&createWindowSection);
       
  1073 
       
  1074 #ifdef QT_DEBUG
       
  1075     EnterCriticalSection(&refCountSection);
       
  1076     ++qaxserverbase_instance_count;
       
  1077     LeaveCriticalSection(&refCountSection);
       
  1078 #endif
       
  1079 
       
  1080     qAxLock();
       
  1081 
       
  1082     points[IID_IPropertyNotifySink] = new QAxConnection(this, IID_IPropertyNotifySink);
       
  1083 }
       
  1084 
       
  1085 /*!
       
  1086     Destroys the QAxServerBase object, releasing all allocated
       
  1087     resources and interfaces.
       
  1088 */
       
  1089 QAxServerBase::~QAxServerBase()
       
  1090 {
       
  1091 #ifdef QT_DEBUG
       
  1092     EnterCriticalSection(&refCountSection);
       
  1093     --qaxserverbase_instance_count;
       
  1094     LeaveCriticalSection(&refCountSection);
       
  1095 #endif
       
  1096 
       
  1097     revokeActiveObject();
       
  1098 
       
  1099     for (QAxServerBase::ConnectionPointsIterator it = points.begin(); it != points.end(); ++it) {
       
  1100 	if (it.value())
       
  1101 	    (*it)->Release();
       
  1102     }
       
  1103     delete aggregatedObject;
       
  1104     aggregatedObject = 0;
       
  1105     if (theObject) {
       
  1106 	qt.object->disconnect(this);
       
  1107 	QObject *aqt = qt.object;
       
  1108 	qt.object = 0;
       
  1109 	if (ownObject)
       
  1110 	    delete aqt;
       
  1111     }
       
  1112 
       
  1113     if (m_spAdviseSink) m_spAdviseSink->Release();
       
  1114     m_spAdviseSink = 0;
       
  1115     for (int i = 0; i < adviseSinks.count(); ++i) {
       
  1116         adviseSinks.at(i).pAdvSink->Release();
       
  1117     }
       
  1118     if (m_spClientSite) m_spClientSite->Release();
       
  1119     m_spClientSite = 0;
       
  1120     if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
       
  1121     m_spInPlaceFrame = 0;
       
  1122     if (m_spInPlaceSite) m_spInPlaceSite->Release();
       
  1123     m_spInPlaceSite = 0;
       
  1124     if (m_spTypeInfo) m_spTypeInfo->Release();
       
  1125     m_spTypeInfo = 0;
       
  1126     if (m_spStorage) m_spStorage->Release();
       
  1127     m_spStorage = 0;
       
  1128 
       
  1129     DeleteCriticalSection(&refCountSection);
       
  1130     DeleteCriticalSection(&createWindowSection);
       
  1131 
       
  1132     qAxUnlock();
       
  1133 }
       
  1134 
       
  1135 /*
       
  1136     Registering with OLE
       
  1137 */
       
  1138 void QAxServerBase::registerActiveObject(IUnknown *object)
       
  1139 {
       
  1140     if (ole_ref || !qt.object || !qAxOutProcServer)
       
  1141 	return;
       
  1142 
       
  1143     const QMetaObject *mo = qt.object->metaObject();
       
  1144     if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes"))
       
  1145 	RegisterActiveObject(object, qAxFactory()->classID(class_name), ACTIVEOBJECT_WEAK, &ole_ref);
       
  1146 }
       
  1147 
       
  1148 void QAxServerBase::revokeActiveObject()
       
  1149 {
       
  1150     if (!ole_ref)
       
  1151 	return;
       
  1152 
       
  1153     RevokeActiveObject(ole_ref, 0);
       
  1154     ole_ref = 0;
       
  1155 }
       
  1156 
       
  1157 /*
       
  1158     QueryInterface implementation.
       
  1159 */
       
  1160 HRESULT WINAPI QAxServerBase::QueryInterface(REFIID iid, void **iface)
       
  1161 {
       
  1162     if (m_outerUnknown)
       
  1163 	return m_outerUnknown->QueryInterface(iid, iface);
       
  1164 
       
  1165     return InternalQueryInterface(iid, iface);
       
  1166 }
       
  1167 
       
  1168 HRESULT QAxServerBase::InternalQueryInterface(REFIID iid, void **iface)
       
  1169 {
       
  1170     *iface = 0;
       
  1171 
       
  1172     if (iid == IID_IUnknown) {
       
  1173 	*iface = (IUnknown*)(IDispatch*)this;
       
  1174     } else {
       
  1175 	HRESULT res = S_OK;
       
  1176 	if (aggregatedObject)
       
  1177 	    res = aggregatedObject->queryInterface(iid, iface);
       
  1178 	if (*iface)
       
  1179 	    return res;
       
  1180     }
       
  1181 
       
  1182     if (!(*iface)) {
       
  1183 	if (iid == qAxFactory()->interfaceID(class_name))
       
  1184 	    *iface = (IDispatch*)this;
       
  1185 	if (iid == IID_IDispatch)
       
  1186 	    *iface = (IDispatch*)this;
       
  1187 	else if (iid == IID_IAxServerBase)
       
  1188 	    *iface = (IAxServerBase*)this;
       
  1189 	else if (iid == IID_IOleObject)
       
  1190 	    *iface = (IOleObject*)this;
       
  1191 	else if (iid == IID_IConnectionPointContainer)
       
  1192 	    *iface = (IConnectionPointContainer*)this;
       
  1193 	else if (iid == IID_IProvideClassInfo)
       
  1194 	    *iface = (IProvideClassInfo*)this;
       
  1195 	else if (iid == IID_IProvideClassInfo2)
       
  1196 	    *iface = (IProvideClassInfo2*)this;
       
  1197 	else if (iid == IID_IPersist)
       
  1198 	    *iface = (IPersist*)(IPersistStream*)this;
       
  1199 	else if (iid == IID_IPersistStream)
       
  1200 	    *iface = (IPersistStream*)this;
       
  1201 	else if (iid == IID_IPersistStreamInit)
       
  1202 	    *iface = (IPersistStreamInit*)this;
       
  1203 	else if (iid == IID_IPersistStorage)
       
  1204 	    *iface = (IPersistStorage*)this;
       
  1205 	else if (iid == IID_IPersistPropertyBag)
       
  1206 	    *iface = (IPersistPropertyBag*)this;
       
  1207         else if (iid == IID_IPersistFile &&
       
  1208             qAxFactory()->metaObject(class_name)->indexOfClassInfo("MIME") != -1)
       
  1209             *iface = (IPersistFile*)this;
       
  1210 	else if (iid == IID_IViewObject)
       
  1211 	    *iface = (IViewObject*)this;
       
  1212 	else if (iid == IID_IViewObject2)
       
  1213 	    *iface = (IViewObject2*)this;
       
  1214 	else if (isWidget) {
       
  1215 	    if (iid == IID_IOleControl)
       
  1216 		*iface = (IOleControl*)this;
       
  1217 	    else if (iid == IID_IOleWindow)
       
  1218 		*iface = (IOleWindow*)(IOleInPlaceObject*)this;
       
  1219 	    else if (iid == IID_IOleInPlaceObject)
       
  1220 		*iface = (IOleInPlaceObject*)this;
       
  1221 	    else if (iid == IID_IOleInPlaceActiveObject)
       
  1222 		*iface = (IOleInPlaceActiveObject*)this;
       
  1223 	    else if (iid == IID_IDataObject)
       
  1224 		*iface = (IDataObject*)this;
       
  1225 	}
       
  1226     }
       
  1227     if (!*iface)
       
  1228 	return E_NOINTERFACE;
       
  1229 
       
  1230     AddRef();
       
  1231     return S_OK;
       
  1232 }
       
  1233 
       
  1234 /*!
       
  1235     Detects and initilaizes implementation of QAxBindable in objects.
       
  1236 */
       
  1237 void QAxServerBase::internalBind()
       
  1238 {
       
  1239     QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
       
  1240     if (axb) {
       
  1241 	// no addref; this is aggregated
       
  1242 	axb->activex = this;
       
  1243 	if (!aggregatedObject)
       
  1244 	    aggregatedObject = axb->createAggregate();
       
  1245 	if (aggregatedObject) {
       
  1246 	    aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this;
       
  1247 	    aggregatedObject->the_object = qt.object;
       
  1248 	}
       
  1249     }
       
  1250 }
       
  1251 
       
  1252 /*!
       
  1253     Connects object signals to event dispatcher.
       
  1254 */
       
  1255 void QAxServerBase::internalConnect()
       
  1256 {
       
  1257     QUuid eventsID = qAxFactory()->eventsID(class_name);
       
  1258     if (!eventsID.isNull()) {
       
  1259 	if (!points[eventsID])
       
  1260 	    points[eventsID] = new QAxConnection(this, eventsID);
       
  1261 
       
  1262 	// connect the generic slot to all signals of qt.object
       
  1263 	const QMetaObject *mo = qt.object->metaObject();
       
  1264         for (int isignal = mo->methodCount()-1; isignal >= 0; --isignal) {
       
  1265             if (mo->method(isignal).methodType() == QMetaMethod::Signal)
       
  1266 	        QMetaObject::connect(qt.object, isignal, this, isignal);
       
  1267         }
       
  1268     }
       
  1269 }
       
  1270 
       
  1271 /*!
       
  1272     Creates the QWidget for the classname passed to the c'tor.
       
  1273 
       
  1274     All signals of the widget class are connected to the internal event mapper.
       
  1275     If the widget implements QAxBindable, stock events are also connected.
       
  1276 */
       
  1277 bool QAxServerBase::internalCreate()
       
  1278 {
       
  1279     if (qt.object)
       
  1280 	return true;
       
  1281 
       
  1282     qt.object = qAxFactory()->createObject(class_name);
       
  1283     Q_ASSERT(qt.object);
       
  1284     if (!qt.object)
       
  1285 	return false;
       
  1286 
       
  1287     theObject = qt.object;
       
  1288     ownObject = true;
       
  1289     isWidget = qt.object->isWidgetType();
       
  1290     hasStockEvents = qAxFactory()->hasStockEvents(class_name);
       
  1291     stayTopLevel = qAxFactory()->stayTopLevel(class_name);
       
  1292 
       
  1293     internalBind();
       
  1294     if (isWidget) {
       
  1295         if (!stayTopLevel) {
       
  1296             QEvent e(QEvent::EmbeddingControl);
       
  1297             QApplication::sendEvent(qt.widget, &e);
       
  1298             ::SetWindowLong(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
       
  1299         }
       
  1300         qt.widget->setAttribute(Qt::WA_QuitOnClose, false);
       
  1301         qt.widget->move(0, 0);
       
  1302 
       
  1303         // initialize to sizeHint, but don't set resized flag so that container has a chance to override
       
  1304         bool wasResized = qt.widget->testAttribute(Qt::WA_Resized);
       
  1305         updateGeometry();
       
  1306         if (!wasResized && qt.widget->testAttribute(Qt::WA_Resized)
       
  1307             && qt.widget->sizePolicy() != QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)) {
       
  1308             qt.widget->setAttribute(Qt::WA_Resized, false);
       
  1309         }
       
  1310     }
       
  1311 
       
  1312     internalConnect();
       
  1313     // install an event filter for stock events
       
  1314     if (isWidget) {
       
  1315         qt.object->installEventFilter(this);
       
  1316         const QList<QWidget*> children = qFindChildren<QWidget*>(qt.object);
       
  1317         QList<QWidget*>::ConstIterator it = children.constBegin();
       
  1318         while (it != children.constEnd()) {
       
  1319             (*it)->installEventFilter(this);
       
  1320             ++it;
       
  1321         }
       
  1322     }
       
  1323     return true;
       
  1324 }
       
  1325 
       
  1326 /*
       
  1327 class HackMenuData : public QMenuData
       
  1328 {
       
  1329     friend class QAxServerBase;
       
  1330 };
       
  1331 */
       
  1332 
       
  1333 class HackWidget : public QWidget
       
  1334 {
       
  1335     friend class QAxServerBase;
       
  1336 };
       
  1337 /*
       
  1338     Message handler. \a hWnd is always the ActiveX widget hosting the Qt widget.
       
  1339     \a uMsg is handled as follows
       
  1340     \list
       
  1341     \i WM_CREATE The ActiveX control is created
       
  1342     \i WM_DESTROY The QWidget is destroyed
       
  1343     \i WM_SHOWWINDOW The QWidget is parented into the ActiveX window
       
  1344     \i WM_PAINT The QWidget is updated
       
  1345     \i WM_SIZE The QWidget is resized to the new size
       
  1346     \i WM_SETFOCUS and
       
  1347     \i WM_KILLFOCUS The client site is notified about the focus transfer
       
  1348     \i WM_MOUSEACTIVATE The ActiveX is activated
       
  1349     \endlist
       
  1350 
       
  1351     The semantics of \a wParam and \a lParam depend on the value of \a uMsg.
       
  1352 */
       
  1353 LRESULT CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
       
  1354 {
       
  1355     if (uMsg == WM_CREATE) {
       
  1356         CREATESTRUCT *cs = (CREATESTRUCT*)lParam;
       
  1357         QAxServerBase *that = (QAxServerBase*)cs->lpCreateParams;
       
  1358 
       
  1359 #ifdef GWLP_USERDATA
       
  1360         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)that);
       
  1361 #else
       
  1362         SetWindowLong(hWnd, GWL_USERDATA, (LONG)that);
       
  1363 #endif
       
  1364 
       
  1365         that->m_hWnd = hWnd;
       
  1366 
       
  1367         return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
       
  1368     }
       
  1369 
       
  1370     QAxServerBase *that = 0;
       
  1371 
       
  1372 #ifdef GWLP_USERDATA
       
  1373     that = (QAxServerBase*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
       
  1374 #else
       
  1375     that = (QAxServerBase*)GetWindowLong(hWnd, GWL_USERDATA);
       
  1376 #endif
       
  1377 
       
  1378     if (that) {
       
  1379         int width = that->qt.widget ? that->qt.widget->width() : 0;
       
  1380         int height = that->qt.widget ? that->qt.widget->height() : 0;
       
  1381         RECT rcPos = {0, 0, width + 1, height + 1};
       
  1382 
       
  1383         switch (uMsg) {
       
  1384         case WM_NCDESTROY:
       
  1385 	    that->m_hWnd = 0;
       
  1386 	    break;
       
  1387 
       
  1388         case WM_QUERYENDSESSION:
       
  1389         case WM_DESTROY:
       
  1390             // save the window handle
       
  1391             if (that->qt.widget) {
       
  1392                 that->qt.widget->hide();
       
  1393                 ::SetParent(that->qt.widget->winId(), 0);
       
  1394             }
       
  1395 	    break;
       
  1396 
       
  1397         case WM_SHOWWINDOW:
       
  1398 	    if(wParam) {
       
  1399 	        that->internalCreate();
       
  1400 	        if (!that->stayTopLevel) {
       
  1401 		    ::SetParent(that->qt.widget->winId(), that->m_hWnd);
       
  1402 		    that->qt.widget->raise();
       
  1403 		    that->qt.widget->move(0, 0);
       
  1404 	        }
       
  1405 	        that->qt.widget->show();
       
  1406 	    } else if (that->qt.widget) {
       
  1407 	        that->qt.widget->hide();
       
  1408 	    }
       
  1409 	    break;
       
  1410 
       
  1411         case WM_ERASEBKGND:
       
  1412 	    that->updateMask();
       
  1413 	    break;
       
  1414 
       
  1415         case WM_SIZE:
       
  1416             that->resize(QSize(LOWORD(lParam), HIWORD(lParam)));
       
  1417 	    break;
       
  1418 
       
  1419         case WM_SETFOCUS:
       
  1420 	    if (that->isInPlaceActive && that->m_spClientSite && !that->inDesignMode && that->canTakeFocus) {
       
  1421 	        that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos);
       
  1422 	        if (that->isUIActive) {
       
  1423 		    IOleControlSite *spSite = 0;
       
  1424 		    that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite);
       
  1425 		    if (spSite) {
       
  1426 		        spSite->OnFocus(true);
       
  1427 		        spSite->Release();
       
  1428 		    }
       
  1429                     QWidget *candidate = that->qt.widget;
       
  1430                     while (!(candidate->focusPolicy() & Qt::TabFocus)) {
       
  1431                         candidate = candidate->nextInFocusChain();
       
  1432                         if (candidate == that->qt.widget) {
       
  1433                             candidate = 0;
       
  1434                             break;
       
  1435                         }
       
  1436                     }
       
  1437                     if (candidate) {
       
  1438                         candidate->setFocus();
       
  1439                         HackWidget *widget = (HackWidget*)that->qt.widget;
       
  1440                         if (::GetKeyState(VK_SHIFT) < 0)
       
  1441                             widget->focusNextPrevChild(false);
       
  1442                     }
       
  1443 	        }
       
  1444 	    }
       
  1445 	    break;
       
  1446 
       
  1447         case WM_KILLFOCUS:
       
  1448 	    if (that->isInPlaceActive && that->isUIActive && that->m_spClientSite) {
       
  1449 	        IOleControlSite *spSite = 0;
       
  1450 	        that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite);
       
  1451 	        if (spSite) {
       
  1452 		    if (!::IsChild(that->m_hWnd, ::GetFocus()))
       
  1453 		        spSite->OnFocus(false);
       
  1454 		    spSite->Release();
       
  1455 	        }
       
  1456 	    }
       
  1457 	    break;
       
  1458 
       
  1459         case WM_MOUSEACTIVATE:
       
  1460 	    that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos);
       
  1461 	    break;
       
  1462 
       
  1463         case WM_INITMENUPOPUP:
       
  1464 	    if (that->qt.widget) {
       
  1465 	        that->currentPopup = that->menuMap[(HMENU)wParam];
       
  1466 	        if (!that->currentPopup)
       
  1467 		    break;
       
  1468 	        const QMetaObject *mo = that->currentPopup->metaObject();
       
  1469 	        int index = mo->indexOfSignal("aboutToShow()");
       
  1470 	        if (index < 0)
       
  1471 		    break;
       
  1472 
       
  1473 	        that->currentPopup->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0);
       
  1474 	        that->createPopup(that->currentPopup, (HMENU)wParam);
       
  1475 	        return 0;
       
  1476 	    }
       
  1477 	    break;
       
  1478 
       
  1479         case WM_MENUSELECT:
       
  1480         case WM_COMMAND:
       
  1481 	    if (that->qt.widget) {
       
  1482 	        QMenuBar *menuBar = that->menuBar;
       
  1483 	        if (!menuBar)
       
  1484 		    break;
       
  1485 
       
  1486                 QObject *menuObject = 0;
       
  1487 	        bool menuClosed = false;
       
  1488 
       
  1489                 if (uMsg == WM_COMMAND) {
       
  1490 		    menuObject = that->actionMap.value(wParam);
       
  1491                 } else if (!lParam) {
       
  1492 		    menuClosed = true;
       
  1493                     menuObject = that->currentPopup;
       
  1494                 } else {
       
  1495                     menuObject = that->actionMap.value(LOWORD(wParam));
       
  1496                 }
       
  1497 
       
  1498 	        if (menuObject) {
       
  1499 		    const QMetaObject *mo = menuObject->metaObject();
       
  1500 		    int index = -1;
       
  1501 
       
  1502 		    if (uMsg == WM_COMMAND)
       
  1503 		        index = mo->indexOfSignal("activated()");
       
  1504 		    else if (menuClosed)
       
  1505 		        index = mo->indexOfSignal("aboutToHide()");
       
  1506 		    else
       
  1507 		        index = mo->indexOfSignal("hovered()");
       
  1508 
       
  1509 		    if (index < 0)
       
  1510 		        break;
       
  1511 
       
  1512 		    menuObject->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0);
       
  1513                     if (menuClosed || uMsg == WM_COMMAND)
       
  1514                         that->currentPopup = 0;
       
  1515 		    return 0;
       
  1516 	        }
       
  1517 	    }
       
  1518 	    break;
       
  1519 
       
  1520         default:
       
  1521 	    break;
       
  1522         }
       
  1523     }
       
  1524 
       
  1525     return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
       
  1526 }
       
  1527 
       
  1528 /*!
       
  1529     Creates the window hosting the QWidget.
       
  1530 */
       
  1531 HWND QAxServerBase::create(HWND hWndParent, RECT& rcPos)
       
  1532 {
       
  1533     Q_ASSERT(isWidget && qt.widget);
       
  1534 
       
  1535     static ATOM atom = 0;
       
  1536     HINSTANCE hInst = (HINSTANCE)qAxInstance;
       
  1537     EnterCriticalSection(&createWindowSection);
       
  1538     QString cn(QLatin1String("QAxControl"));
       
  1539     cn += QString::number((int)ActiveXProc);
       
  1540     if (!atom) {
       
  1541         WNDCLASS wcTemp;
       
  1542         wcTemp.style = CS_DBLCLKS;
       
  1543         wcTemp.cbClsExtra = 0;
       
  1544         wcTemp.cbWndExtra = 0;
       
  1545         wcTemp.hbrBackground = 0;
       
  1546         wcTemp.hCursor = 0;
       
  1547         wcTemp.hIcon = 0;
       
  1548         wcTemp.hInstance = hInst;
       
  1549         wcTemp.lpszClassName = (wchar_t*)cn.utf16();
       
  1550         wcTemp.lpszMenuName = 0;
       
  1551         wcTemp.lpfnWndProc = ActiveXProc;
       
  1552 
       
  1553         atom = RegisterClass(&wcTemp);
       
  1554     }
       
  1555     LeaveCriticalSection(&createWindowSection);
       
  1556     if (!atom  && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
       
  1557 	return 0;
       
  1558 
       
  1559     Q_ASSERT(!m_hWnd);
       
  1560     HWND hWnd = ::CreateWindow((wchar_t*)cn.utf16(), 0,
       
  1561                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
       
  1562                                rcPos.left, rcPos.top, rcPos.right - rcPos.left,
       
  1563                                rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this);
       
  1564 
       
  1565     Q_ASSERT(m_hWnd == hWnd);
       
  1566 
       
  1567     updateMask();
       
  1568     EnableWindow(m_hWnd, qt.widget->isEnabled());
       
  1569 
       
  1570     return hWnd;
       
  1571 }
       
  1572 
       
  1573 /*
       
  1574     Recoursively creates Win32 submenus.
       
  1575 */
       
  1576 HMENU QAxServerBase::createPopup(QMenu *popup, HMENU oldMenu)
       
  1577 {
       
  1578     HMENU popupMenu = oldMenu ? oldMenu : CreatePopupMenu();
       
  1579     menuMap.insert(popupMenu, popup);
       
  1580 
       
  1581     if (oldMenu) while (GetMenuItemCount(oldMenu)) {
       
  1582 	DeleteMenu(oldMenu, 0, MF_BYPOSITION);
       
  1583     }
       
  1584 
       
  1585     const QList<QAction*> actions = popup->actions();
       
  1586     for (int i = 0; i < actions.count(); ++i) {
       
  1587         QAction *action = actions.at(i);
       
  1588 
       
  1589         uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED;
       
  1590         if (action->isSeparator())
       
  1591             flags |= MF_SEPARATOR;
       
  1592         else if (action->menu())
       
  1593             flags |= MF_POPUP;
       
  1594         else
       
  1595             flags |= MF_STRING;
       
  1596         if (action->isChecked())
       
  1597             flags |= MF_CHECKED;
       
  1598 
       
  1599 	ushort itemId;
       
  1600         if (flags & MF_POPUP) {
       
  1601             itemId = static_cast<ushort>(
       
  1602                 reinterpret_cast<ulong>(createPopup(action->menu()))
       
  1603             );
       
  1604         } else {
       
  1605             itemId = static_cast<ushort>(reinterpret_cast<ulong>(action));
       
  1606             actionMap.remove(itemId);
       
  1607             actionMap.insert(itemId, action);
       
  1608         }
       
  1609         AppendMenu(popupMenu, flags, itemId, (const wchar_t *)action->text().utf16());
       
  1610     }
       
  1611     if (oldMenu)
       
  1612         DrawMenuBar(hwndMenuOwner);
       
  1613     return popupMenu;
       
  1614 }
       
  1615 
       
  1616 /*!
       
  1617     Creates a Win32 menubar.
       
  1618 */
       
  1619 void QAxServerBase::createMenu(QMenuBar *menuBar)
       
  1620 {
       
  1621     hmenuShared = ::CreateMenu();
       
  1622 
       
  1623     int edit = 0;
       
  1624     int object = 0;
       
  1625     int help = 0;
       
  1626 
       
  1627     const QList<QAction*> actions = menuBar->actions();
       
  1628     for (int i = 0; i < actions.count(); ++i) {
       
  1629         QAction *action = actions.at(i);
       
  1630 
       
  1631         uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED;
       
  1632 	if (action->isSeparator())
       
  1633 	    flags |= MF_SEPARATOR;
       
  1634 	else if (action->menu())
       
  1635 	    flags |= MF_POPUP;
       
  1636 	else
       
  1637 	    flags |= MF_STRING;
       
  1638 
       
  1639 	if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Edit"))
       
  1640 	    edit++;
       
  1641 	else if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Help"))
       
  1642 	    help++;
       
  1643 	else
       
  1644 	    object++;
       
  1645 
       
  1646 	ushort itemId;
       
  1647         if (flags & MF_POPUP) {
       
  1648             itemId = static_cast<ushort>(
       
  1649                 reinterpret_cast<ulong>(createPopup(action->menu()))
       
  1650             );
       
  1651         } else {
       
  1652             itemId = static_cast<ushort>(reinterpret_cast<ulong>(action));
       
  1653             actionMap.insert(itemId, action);
       
  1654         }
       
  1655         AppendMenu(hmenuShared, flags, itemId, (const wchar_t *)action->text().utf16());
       
  1656     }
       
  1657 
       
  1658     OLEMENUGROUPWIDTHS menuWidths = {0,edit,0,object,0,help};
       
  1659     HRESULT hres = m_spInPlaceFrame->InsertMenus(hmenuShared, &menuWidths);
       
  1660     if (FAILED(hres)) {
       
  1661 	::DestroyMenu(hmenuShared);
       
  1662 	hmenuShared = 0;
       
  1663 	return;
       
  1664     }
       
  1665 
       
  1666     m_spInPlaceFrame->GetWindow(&hwndMenuOwner);
       
  1667 
       
  1668     holemenu = OleCreateMenuDescriptor(hmenuShared, &menuWidths);
       
  1669     hres = m_spInPlaceFrame->SetMenu(hmenuShared, holemenu, m_hWnd);
       
  1670     if (FAILED(hres)) {
       
  1671 	::DestroyMenu(hmenuShared);
       
  1672 	hmenuShared = 0;
       
  1673 	OleDestroyMenuDescriptor(holemenu);
       
  1674     }
       
  1675 }
       
  1676 
       
  1677 /*!
       
  1678     Remove the Win32 menubar.
       
  1679 */
       
  1680 void QAxServerBase::removeMenu()
       
  1681 {
       
  1682     if (hmenuShared)
       
  1683 	m_spInPlaceFrame->RemoveMenus(hmenuShared);
       
  1684     holemenu = 0;
       
  1685     m_spInPlaceFrame->SetMenu(0, 0, m_hWnd);
       
  1686     if (hmenuShared) {
       
  1687 	DestroyMenu(hmenuShared);
       
  1688 	hmenuShared = 0;
       
  1689 	menuMap.clear();
       
  1690     }
       
  1691     hwndMenuOwner = 0;
       
  1692 }
       
  1693 
       
  1694 extern bool ignoreSlots(const char *test);
       
  1695 extern bool ignoreProps(const char *test);
       
  1696 
       
  1697 /*!
       
  1698     Makes sure the type info is loaded
       
  1699 */
       
  1700 void QAxServerBase::ensureMetaData()
       
  1701 {
       
  1702     if (!m_spTypeInfo) {
       
  1703 	qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->interfaceID(class_name), &m_spTypeInfo);
       
  1704 	m_spTypeInfo->AddRef();
       
  1705     }
       
  1706 }
       
  1707 
       
  1708 /*!
       
  1709     \internal
       
  1710     Returns true if the property \a index is exposed to COM and should
       
  1711     be saved/loaded.
       
  1712 */
       
  1713 bool QAxServerBase::isPropertyExposed(int index)
       
  1714 {
       
  1715     if (!theObject)
       
  1716 	return false;
       
  1717 
       
  1718     bool result = false;
       
  1719     const QMetaObject *mo = theObject->metaObject();
       
  1720 
       
  1721     int qtProps = 0;
       
  1722     if (theObject->isWidgetType())
       
  1723 	qtProps = QWidget::staticMetaObject.propertyCount();
       
  1724     QMetaProperty property = mo->property(index);
       
  1725     if (index <= qtProps && ignoreProps(property.name()))
       
  1726 	return result;
       
  1727 
       
  1728     BSTR bstrNames = QStringToBSTR(QLatin1String(property.name()));
       
  1729     DISPID dispId;
       
  1730     GetIDsOfNames(IID_NULL, (BSTR*)&bstrNames, 1, LOCALE_USER_DEFAULT, &dispId);
       
  1731     result = dispId != DISPID_UNKNOWN;
       
  1732     SysFreeString(bstrNames);
       
  1733 
       
  1734     return result;
       
  1735 }
       
  1736 
       
  1737 
       
  1738 /*!
       
  1739     \internal
       
  1740     Updates the view, or asks the client site to do so.
       
  1741 */
       
  1742 void QAxServerBase::update()
       
  1743 {
       
  1744     if (isInPlaceActive) {
       
  1745 	if (m_hWnd)
       
  1746 	    ::InvalidateRect(m_hWnd, 0, true);
       
  1747 	else if (m_spInPlaceSite)
       
  1748 	    m_spInPlaceSite->InvalidateRect(NULL, true);
       
  1749     } else if (m_spAdviseSink) {
       
  1750         m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
       
  1751         for (int i = 0; i < adviseSinks.count(); ++i) {
       
  1752 	    adviseSinks.at(i).pAdvSink->OnViewChange(DVASPECT_CONTENT, -1);
       
  1753         }
       
  1754     }
       
  1755 }
       
  1756 
       
  1757 /*!
       
  1758     Resizes the control, faking a QResizeEvent if required
       
  1759 */
       
  1760 void QAxServerBase::resize(const QSize &size)
       
  1761 {
       
  1762     if (!isWidget || !qt.widget || !size.isValid() || size == QSize(0, 0))
       
  1763         return;
       
  1764 
       
  1765     QSize oldSize = qt.widget->size();
       
  1766     qt.widget->resize(size);
       
  1767     QSize newSize = qt.widget->size();
       
  1768     // make sure we get a resize event even if not embedded as a control
       
  1769     if (!m_hWnd && !qt.widget->isVisible() && newSize != oldSize) {
       
  1770         QResizeEvent resizeEvent(newSize, oldSize);
       
  1771 #ifndef QT_DLL // import from static library
       
  1772         extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
       
  1773 #endif
       
  1774         qt_sendSpontaneousEvent(qt.widget, &resizeEvent);
       
  1775     }
       
  1776     m_currentExtent = qt.widget->size();
       
  1777 }
       
  1778 
       
  1779 /*!
       
  1780     \internal
       
  1781 
       
  1782     Updates the internal size values.
       
  1783 */
       
  1784 void QAxServerBase::updateGeometry()
       
  1785 {
       
  1786     if (!isWidget || !qt.widget)
       
  1787 	return;
       
  1788 
       
  1789     const QSize sizeHint = qt.widget->sizeHint();
       
  1790     const QSize size = qt.widget->size();
       
  1791     if (sizeHint.isValid()) { // if provided, adjust to sizeHint
       
  1792         QSize newSize = size;
       
  1793         if (!qt.widget->testAttribute(Qt::WA_Resized)) {
       
  1794             newSize = sizeHint;
       
  1795         } else { // according to sizePolicy rules if already resized
       
  1796             QSizePolicy sizePolicy = qt.widget->sizePolicy();
       
  1797             if (sizeHint.width() > size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::ShrinkFlag))
       
  1798 	        newSize.setWidth(sizeHint.width());
       
  1799             if (sizeHint.width() < size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::GrowFlag))
       
  1800                 newSize.setWidth(sizeHint.width());
       
  1801             if (sizeHint.height() > size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::ShrinkFlag))
       
  1802 	        newSize.setHeight(sizeHint.height());
       
  1803             if (sizeHint.height() < size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::GrowFlag))
       
  1804                 newSize.setHeight(sizeHint.height());
       
  1805         }
       
  1806         resize(newSize);
       
  1807 
       
  1808     // set an initial size suitable for embedded controls
       
  1809     } else if (!qt.widget->testAttribute(Qt::WA_Resized)) {
       
  1810         resize(QSize(100, 100));
       
  1811         qt.widget->setAttribute(Qt::WA_Resized, false);
       
  1812     }
       
  1813 }
       
  1814 
       
  1815 /*!
       
  1816     \internal
       
  1817 
       
  1818     Updates the mask of the widget parent.
       
  1819 */
       
  1820 void QAxServerBase::updateMask()
       
  1821 {
       
  1822     if (!isWidget || !qt.widget || qt.widget->mask().isEmpty())
       
  1823 	return;
       
  1824 
       
  1825     QRegion rgn = qt.widget->mask();
       
  1826     HRGN hrgn = rgn.handle();
       
  1827 
       
  1828     // Since SetWindowRegion takes ownership
       
  1829     HRGN wr = CreateRectRgn(0,0,0,0);
       
  1830     CombineRgn(wr, hrgn, 0, RGN_COPY);
       
  1831     SetWindowRgn(m_hWnd, wr, true);
       
  1832 }
       
  1833 
       
  1834 static bool checkHRESULT(HRESULT hres)
       
  1835 {
       
  1836     const char *name = 0;
       
  1837     switch(hres) {
       
  1838     case S_OK:
       
  1839 	return true;
       
  1840     case DISP_E_BADPARAMCOUNT:
       
  1841 #if defined(QT_CHECK_STATE)
       
  1842 	qWarning("QAxBase: Error calling IDispatch member %s: Bad parameter count", name);
       
  1843 #endif
       
  1844 	return false;
       
  1845     case DISP_E_BADVARTYPE:
       
  1846 #if defined(QT_CHECK_STATE)
       
  1847 	qWarning("QAxBase: Error calling IDispatch member %s: Bad variant type", name);
       
  1848 #endif
       
  1849 	return false;
       
  1850     case DISP_E_EXCEPTION:
       
  1851 #if defined(QT_CHECK_STATE)
       
  1852 	    qWarning("QAxBase: Error calling IDispatch member %s: Exception thrown by server", name);
       
  1853 #endif
       
  1854 	return false;
       
  1855     case DISP_E_MEMBERNOTFOUND:
       
  1856 #if defined(QT_CHECK_STATE)
       
  1857 	qWarning("QAxBase: Error calling IDispatch member %s: Member not found", name);
       
  1858 #endif
       
  1859 	return false;
       
  1860     case DISP_E_NONAMEDARGS:
       
  1861 #if defined(QT_CHECK_STATE)
       
  1862 	qWarning("QAxBase: Error calling IDispatch member %s: No named arguments", name);
       
  1863 #endif
       
  1864 	return false;
       
  1865     case DISP_E_OVERFLOW:
       
  1866 #if defined(QT_CHECK_STATE)
       
  1867 	qWarning("QAxBase: Error calling IDispatch member %s: Overflow", name);
       
  1868 #endif
       
  1869 	return false;
       
  1870     case DISP_E_PARAMNOTFOUND:
       
  1871 #if defined(QT_CHECK_STATE)
       
  1872 	qWarning("QAxBase: Error calling IDispatch member %s: Parameter not found", name);
       
  1873 #endif
       
  1874 	return false;
       
  1875     case DISP_E_TYPEMISMATCH:
       
  1876 #if defined(QT_CHECK_STATE)
       
  1877 	qWarning("QAxBase: Error calling IDispatch member %s: Type mismatch", name);
       
  1878 #endif
       
  1879 	return false;
       
  1880     case DISP_E_UNKNOWNINTERFACE:
       
  1881 #if defined(QT_CHECK_STATE)
       
  1882 	qWarning("QAxBase: Error calling IDispatch member %s: Unknown interface", name);
       
  1883 #endif
       
  1884 	return false;
       
  1885     case DISP_E_UNKNOWNLCID:
       
  1886 #if defined(QT_CHECK_STATE)
       
  1887 	qWarning("QAxBase: Error calling IDispatch member %s: Unknown locale ID", name);
       
  1888 #endif
       
  1889 	return false;
       
  1890     case DISP_E_PARAMNOTOPTIONAL:
       
  1891 #if defined(QT_CHECK_STATE)
       
  1892 	qWarning("QAxBase: Error calling IDispatch member %s: Non-optional parameter missing", name);
       
  1893 #endif
       
  1894 	return false;
       
  1895     default:
       
  1896 #if defined(QT_CHECK_STATE)
       
  1897 	qWarning("QAxBase: Error calling IDispatch member %s: Unknown error", name);
       
  1898 #endif
       
  1899 	return false;
       
  1900     }
       
  1901 }
       
  1902 
       
  1903 static inline QByteArray paramType(const QByteArray &ptype, bool *out)
       
  1904 {
       
  1905     *out = ptype.endsWith('&') || ptype.endsWith("**");
       
  1906     if (*out) {
       
  1907         QByteArray res(ptype);
       
  1908 	res.truncate(res.length() - 1);
       
  1909         return res;
       
  1910     }
       
  1911 
       
  1912     return ptype;
       
  1913 }
       
  1914 
       
  1915 /*!
       
  1916     Catches all signals emitted by the Qt widget and fires the respective COM event.
       
  1917 
       
  1918     \a isignal is the Qt Meta Object index of the received signal, and \a _o the
       
  1919     signal parameters.
       
  1920 */
       
  1921 int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv)
       
  1922 {
       
  1923     Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
       
  1924 
       
  1925     if (index == -1) {
       
  1926         if (sender() && m_spInPlaceFrame) {
       
  1927             if (qobject_cast<QStatusBar*>(sender()) != statusBar)
       
  1928                 return true;
       
  1929 
       
  1930             if (statusBar->isHidden()) {
       
  1931                 QString message = *(QString*)argv[1];
       
  1932                 m_spInPlaceFrame->SetStatusText(QStringToBSTR(message));
       
  1933             }
       
  1934         }
       
  1935         return true;
       
  1936     }
       
  1937 
       
  1938     if (freezeEvents || inDesignMode)
       
  1939         return true;
       
  1940 
       
  1941     ensureMetaData();
       
  1942 
       
  1943     // get the signal information.
       
  1944     const QMetaObject *mo = qt.object->metaObject();
       
  1945     QMetaMethod signal;
       
  1946     DISPID eventId = index;
       
  1947     int pcount = 0;
       
  1948     QByteArray type;
       
  1949     QList<QByteArray> ptypes;
       
  1950 
       
  1951     switch(index) {
       
  1952     case DISPID_KEYDOWN:
       
  1953     case DISPID_KEYUP:
       
  1954         pcount = 2;
       
  1955         ptypes << "int&" << "int";
       
  1956         break;
       
  1957     case DISPID_KEYPRESS:
       
  1958         pcount = 1;
       
  1959         ptypes << "int&";
       
  1960         break;
       
  1961     case DISPID_MOUSEDOWN:
       
  1962     case DISPID_MOUSEMOVE:
       
  1963     case DISPID_MOUSEUP:
       
  1964         pcount = 4;
       
  1965         ptypes << "int" << "int" << "int" << "int";
       
  1966         break;
       
  1967     case DISPID_CLICK:
       
  1968         pcount = 0;
       
  1969         break;
       
  1970     case DISPID_DBLCLICK:
       
  1971         pcount = 0;
       
  1972         break;
       
  1973     default:
       
  1974         {
       
  1975             signal = mo->method(index);
       
  1976             Q_ASSERT(signal.methodType() == QMetaMethod::Signal);
       
  1977             type = signal.typeName();
       
  1978             QByteArray signature(signal.signature());
       
  1979             QByteArray name(signature);
       
  1980             name.truncate(name.indexOf('('));
       
  1981 
       
  1982             eventId = signalCache.value(index, -1);
       
  1983             if (eventId == -1) {
       
  1984                 ITypeInfo *eventInfo = 0;
       
  1985                 qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->eventsID(class_name), &eventInfo);
       
  1986                 if (eventInfo) {
       
  1987                     QString uni_name = QLatin1String(name);
       
  1988                     const OLECHAR *olename = reinterpret_cast<const OLECHAR *>(uni_name.utf16());
       
  1989                     eventInfo->GetIDsOfNames((OLECHAR**)&olename, 1, &eventId);
       
  1990                     eventInfo->Release();
       
  1991                 }
       
  1992             }
       
  1993 
       
  1994             signature = signature.mid(name.length() + 1);
       
  1995             signature.truncate(signature.length() - 1);
       
  1996 
       
  1997             if (!signature.isEmpty())
       
  1998                 ptypes = signature.split(',');
       
  1999 
       
  2000             pcount = ptypes.count();
       
  2001         }
       
  2002         break;
       
  2003     }
       
  2004     if (pcount && !argv) {
       
  2005         qWarning("QAxServerBase::qt_metacall: Missing %d arguments", pcount);
       
  2006         return false;
       
  2007     }
       
  2008     if (eventId == -1)
       
  2009         return false;
       
  2010 
       
  2011     // For all connected event sinks...
       
  2012     IConnectionPoint *cpoint = 0;
       
  2013     GUID IID_QAxEvents = qAxFactory()->eventsID(class_name);
       
  2014     FindConnectionPoint(IID_QAxEvents, &cpoint);
       
  2015     if (cpoint) {
       
  2016         IEnumConnections *clist = 0;
       
  2017         cpoint->EnumConnections(&clist);
       
  2018         if (clist) {
       
  2019             clist->Reset();
       
  2020             ULONG cc = 1;
       
  2021             CONNECTDATA c[1];
       
  2022             clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2023             if (cc) {
       
  2024                 // setup parameters
       
  2025                 unsigned int argErr = 0;
       
  2026                 DISPPARAMS dispParams;
       
  2027                 dispParams.cArgs = pcount;
       
  2028                 dispParams.cNamedArgs = 0;
       
  2029                 dispParams.rgdispidNamedArgs = 0;
       
  2030                 dispParams.rgvarg = 0;
       
  2031 
       
  2032                 if (pcount) // Use malloc/free for eval package compatibility
       
  2033                     dispParams.rgvarg = (VARIANTARG*)malloc(pcount * sizeof(VARIANTARG));
       
  2034                 int p = 0;
       
  2035                 for (p = 0; p < pcount; ++p) {
       
  2036                     VARIANT *arg = dispParams.rgvarg + (pcount - p - 1);
       
  2037                     VariantInit(arg);
       
  2038 
       
  2039                     bool out;
       
  2040                     QByteArray ptype = paramType(ptypes.at(p), &out);
       
  2041                     QVariant variant;
       
  2042                     if (mo->indexOfEnumerator(ptype) != -1) {
       
  2043                         // convert enum values to int
       
  2044                         variant = QVariant(*reinterpret_cast<int *>(argv[p+1]));
       
  2045                     } else {
       
  2046                         QVariant::Type vt = QVariant::nameToType(ptype);
       
  2047                         if (vt == QVariant::UserType) {
       
  2048                             if (ptype.endsWith('*')) {
       
  2049                                 variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]);
       
  2050                                 // qVariantSetValue(variant, *(void**)(argv[p + 1]), ptype);
       
  2051                             } else {
       
  2052                                 variant = QVariant(QMetaType::type(ptype), argv[p+1]);
       
  2053                                 // qVariantSetValue(variant, argv[p + 1], ptype);
       
  2054                             }
       
  2055                         } else {
       
  2056                             variant = QVariant(vt, argv[p + 1]);
       
  2057                         }
       
  2058                     }
       
  2059 
       
  2060                     QVariantToVARIANT(variant, *arg, type, out);
       
  2061                 }
       
  2062 
       
  2063                 VARIANT retval;
       
  2064                 VariantInit(&retval);
       
  2065                 VARIANT *pretval = 0;
       
  2066                 if (!type.isEmpty())
       
  2067                     pretval = &retval;
       
  2068 
       
  2069                 // call listeners (through IDispatch)
       
  2070                 while (cc) {
       
  2071                     if (c->pUnk) {
       
  2072                         IDispatch *disp = 0;
       
  2073                         c->pUnk->QueryInterface(IID_QAxEvents, (void**)&disp);
       
  2074                         if (disp) {
       
  2075                             disp->Invoke(eventId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, pretval, 0, &argErr);
       
  2076 
       
  2077                             // update out-parameters and return value
       
  2078                             if (index > 0) {
       
  2079                                 for (p = 0; p < pcount; ++p) {
       
  2080                                     bool out;
       
  2081                                     QByteArray ptype = paramType(ptypes.at(p), &out);
       
  2082                                     if (out)
       
  2083                                         QVariantToVoidStar(VARIANTToQVariant(dispParams.rgvarg[pcount - p - 1], ptype), argv[p+1], ptype);
       
  2084                                 }
       
  2085                                 if (pretval)
       
  2086                                     QVariantToVoidStar(VARIANTToQVariant(retval, type), argv[0], type);
       
  2087                             }
       
  2088                             disp->Release();
       
  2089                         }
       
  2090                         c->pUnk->Release(); // AddRef'ed by clist->Next implementation
       
  2091                     }
       
  2092                     clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2093                 }
       
  2094 
       
  2095                 // clean up
       
  2096                 for (p = 0; p < pcount; ++p)
       
  2097                     clearVARIANT(dispParams.rgvarg+p);
       
  2098                 free(dispParams.rgvarg);
       
  2099             }
       
  2100             clist->Release();
       
  2101         }
       
  2102         cpoint->Release();
       
  2103     }
       
  2104 
       
  2105     return true;
       
  2106 }
       
  2107 
       
  2108 /*!
       
  2109     Call IPropertyNotifySink of connected clients.
       
  2110     \a dispId specifies the ID of the property that changed.
       
  2111 */
       
  2112 bool QAxServerBase::emitRequestPropertyChange(const char *property)
       
  2113 {
       
  2114     long dispId = -1;
       
  2115 
       
  2116     IConnectionPoint *cpoint = 0;
       
  2117     FindConnectionPoint(IID_IPropertyNotifySink, &cpoint);
       
  2118     if (cpoint) {
       
  2119 	IEnumConnections *clist = 0;
       
  2120 	cpoint->EnumConnections(&clist);
       
  2121 	if (clist) {
       
  2122 	    clist->Reset();
       
  2123 	    ULONG cc = 1;
       
  2124 	    CONNECTDATA c[1];
       
  2125 	    clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2126 	    if (cc) {
       
  2127 		if (dispId == -1) {
       
  2128 		    BSTR bstr = QStringToBSTR(QLatin1String(property));
       
  2129 		    GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId);
       
  2130 		    SysFreeString(bstr);
       
  2131 		}
       
  2132 		if (dispId != -1) while (cc) {
       
  2133 		    if (c->pUnk) {
       
  2134 			IPropertyNotifySink *sink = 0;
       
  2135 			c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink);
       
  2136 			bool disallows = sink && sink->OnRequestEdit(dispId) == S_FALSE;
       
  2137 			sink->Release();
       
  2138 			c->pUnk->Release();
       
  2139 			if (disallows) { // a client disallows the property to change
       
  2140 			    clist->Release();
       
  2141 			    cpoint->Release();
       
  2142 			    return false;
       
  2143 			}
       
  2144 		    }
       
  2145 		    clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2146 		}
       
  2147 	    }
       
  2148 	    clist->Release();
       
  2149 	}
       
  2150 	cpoint->Release();
       
  2151     }
       
  2152     dirtyflag = true;
       
  2153     return true;
       
  2154 }
       
  2155 
       
  2156 /*!
       
  2157     Call IPropertyNotifySink of connected clients.
       
  2158     \a dispId specifies the ID of the property that changed.
       
  2159 */
       
  2160 void QAxServerBase::emitPropertyChanged(const char *property)
       
  2161 {
       
  2162     long dispId = -1;
       
  2163 
       
  2164     IConnectionPoint *cpoint = 0;
       
  2165     FindConnectionPoint(IID_IPropertyNotifySink, &cpoint);
       
  2166     if (cpoint) {
       
  2167 	IEnumConnections *clist = 0;
       
  2168 	cpoint->EnumConnections(&clist);
       
  2169 	if (clist) {
       
  2170 	    clist->Reset();
       
  2171 	    ULONG cc = 1;
       
  2172 	    CONNECTDATA c[1];
       
  2173 	    clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2174 	    if (cc) {
       
  2175 		if (dispId == -1) {
       
  2176 		    BSTR bstr = QStringToBSTR(QLatin1String(property));
       
  2177 		    GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId);
       
  2178 		    SysFreeString(bstr);
       
  2179 		}
       
  2180 		if (dispId != -1) while (cc) {
       
  2181 		    if (c->pUnk) {
       
  2182 			IPropertyNotifySink *sink = 0;
       
  2183 			c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink);
       
  2184 			if (sink) {
       
  2185 			    sink->OnChanged(dispId);
       
  2186 			    sink->Release();
       
  2187 			}
       
  2188 			c->pUnk->Release();
       
  2189 		    }
       
  2190 		    clist->Next(cc, (CONNECTDATA*)&c, &cc);
       
  2191 		}
       
  2192 	    }
       
  2193 	    clist->Release();
       
  2194 	}
       
  2195 	cpoint->Release();
       
  2196     }
       
  2197     dirtyflag = true;
       
  2198 }
       
  2199 
       
  2200 //**** IProvideClassInfo
       
  2201 /*
       
  2202     Provide the ITypeInfo implementation for the COM class.
       
  2203 */
       
  2204 HRESULT WINAPI QAxServerBase::GetClassInfo(ITypeInfo** pptinfo)
       
  2205 {
       
  2206     if (!pptinfo)
       
  2207 	return E_POINTER;
       
  2208 
       
  2209     *pptinfo = 0;
       
  2210     if (!qAxTypeLibrary)
       
  2211 	return DISP_E_BADINDEX;
       
  2212 
       
  2213     return qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->classID(class_name), pptinfo);
       
  2214 }
       
  2215 
       
  2216 //**** IProvideClassInfo2
       
  2217 /*
       
  2218     Provide the ID of the event interface.
       
  2219 */
       
  2220 HRESULT WINAPI QAxServerBase::GetGUID(DWORD dwGuidKind, GUID* pGUID)
       
  2221 {
       
  2222     if (!pGUID)
       
  2223 	return E_POINTER;
       
  2224 
       
  2225     if (dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID) {
       
  2226 	*pGUID = qAxFactory()->eventsID(class_name);
       
  2227 	return S_OK;
       
  2228     }
       
  2229     *pGUID = GUID_NULL;
       
  2230     return E_FAIL;
       
  2231 }
       
  2232 
       
  2233 //**** IDispatch
       
  2234 /*
       
  2235     Returns the number of class infos for this IDispatch.
       
  2236 */
       
  2237 HRESULT WINAPI QAxServerBase::GetTypeInfoCount(UINT* pctinfo)
       
  2238 {
       
  2239     if (!pctinfo)
       
  2240 	return E_POINTER;
       
  2241 
       
  2242     *pctinfo = qAxTypeLibrary ? 1 : 0;
       
  2243     return S_OK;
       
  2244 }
       
  2245 
       
  2246 /*
       
  2247     Provides the ITypeInfo for this IDispatch implementation.
       
  2248 */
       
  2249 HRESULT WINAPI QAxServerBase::GetTypeInfo(UINT itinfo, LCID /*lcid*/, ITypeInfo** pptinfo)
       
  2250 {
       
  2251     if (!pptinfo)
       
  2252 	return E_POINTER;
       
  2253 
       
  2254     if (!qAxTypeLibrary)
       
  2255 	return DISP_E_BADINDEX;
       
  2256 
       
  2257     ensureMetaData();
       
  2258 
       
  2259     *pptinfo = m_spTypeInfo;
       
  2260     (*pptinfo)->AddRef();
       
  2261 
       
  2262     return S_OK;
       
  2263 }
       
  2264 
       
  2265 /*
       
  2266     Provides the names of the methods implemented in this IDispatch implementation.
       
  2267 */
       
  2268 HRESULT WINAPI QAxServerBase::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
       
  2269 				     LCID /*lcid*/, DISPID* rgdispid)
       
  2270 {
       
  2271     if (!rgszNames || !rgdispid)
       
  2272 	return E_POINTER;
       
  2273 
       
  2274     if (!qAxTypeLibrary)
       
  2275 	return DISP_E_UNKNOWNNAME;
       
  2276 
       
  2277     ensureMetaData();
       
  2278     if (!m_spTypeInfo)
       
  2279 	return DISP_E_UNKNOWNNAME;
       
  2280 
       
  2281     return m_spTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
       
  2282 }
       
  2283 
       
  2284 /*
       
  2285     Map the COM call to the Qt slot/property for \a dispidMember.
       
  2286 */
       
  2287 HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
       
  2288 		  LCID /*lcid*/, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult,
       
  2289 		  EXCEPINFO* pexcepinfo, UINT* puArgErr)
       
  2290 {
       
  2291     if (riid != IID_NULL)
       
  2292 	return DISP_E_UNKNOWNINTERFACE;
       
  2293     if (!theObject)
       
  2294 	return E_UNEXPECTED;
       
  2295 
       
  2296     HRESULT res = DISP_E_MEMBERNOTFOUND;
       
  2297 
       
  2298     bool uniqueIndex = wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_METHOD;
       
  2299 
       
  2300     int index = uniqueIndex ? indexCache.value(dispidMember, -1) : -1;
       
  2301     QByteArray name;
       
  2302     if (index == -1) {
       
  2303 	ensureMetaData();
       
  2304 
       
  2305         // This property or method is invoked when an ActiveX client specifies
       
  2306         // the object name without a property or method. We only support property.
       
  2307         if (dispidMember == DISPID_VALUE && (wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT)) {
       
  2308             const QMetaObject *mo = qt.object->metaObject();
       
  2309             index = mo->indexOfClassInfo("DefaultProperty");
       
  2310             if (index != -1) {
       
  2311                 name  = mo->classInfo(index).value();
       
  2312                 index = mo->indexOfProperty(name);
       
  2313             }
       
  2314         } else {
       
  2315 	    BSTR bname;
       
  2316 	    UINT cname = 0;
       
  2317 	    if (m_spTypeInfo)
       
  2318 	        m_spTypeInfo->GetNames(dispidMember, &bname, 1, &cname);
       
  2319 	    if (!cname)
       
  2320 	        return res;
       
  2321 
       
  2322             name = QString::fromWCharArray(bname).toLatin1();
       
  2323 	    SysFreeString(bname);
       
  2324         }
       
  2325     }
       
  2326 
       
  2327     const QMetaObject *mo = qt.object->metaObject();
       
  2328     QSize oldSizeHint;
       
  2329     if (isWidget)
       
  2330 	oldSizeHint = qt.widget->sizeHint();
       
  2331 
       
  2332     switch (wFlags) {
       
  2333     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
       
  2334     case DISPATCH_PROPERTYGET:
       
  2335 	{
       
  2336 	    if (index == -1) {
       
  2337 		index = mo->indexOfProperty(name);
       
  2338 		if (index == -1 && wFlags == DISPATCH_PROPERTYGET)
       
  2339 		    return res;
       
  2340 	    }
       
  2341 
       
  2342 	    QMetaProperty property;
       
  2343             if (index < mo->propertyCount())
       
  2344                 property = mo->property(index);
       
  2345 
       
  2346 	    if (property.isReadable()) {
       
  2347 		if (!pvarResult)
       
  2348 		    return DISP_E_PARAMNOTOPTIONAL;
       
  2349 		if (pDispParams->cArgs ||
       
  2350 		     pDispParams->cNamedArgs)
       
  2351 		    return DISP_E_BADPARAMCOUNT;
       
  2352 
       
  2353 		QVariant var = qt.object->property(property.name());
       
  2354 		if (!var.isValid())
       
  2355 		    res =  DISP_E_MEMBERNOTFOUND;
       
  2356 		else if (!QVariantToVARIANT(var, *pvarResult))
       
  2357 		    res = DISP_E_TYPEMISMATCH;
       
  2358 		else
       
  2359 		    res = S_OK;
       
  2360 		break;
       
  2361 	    } else if (wFlags == DISPATCH_PROPERTYGET) {
       
  2362 		break;
       
  2363 	    }
       
  2364 	}
       
  2365 	// FALLTHROUGH if wFlags == DISPATCH_PROPERTYGET|DISPATCH_METHOD AND not a property.
       
  2366     case DISPATCH_METHOD:
       
  2367 	{
       
  2368             int nameLength = 0;
       
  2369 	    if (index == -1) {
       
  2370 	        nameLength = name.length();
       
  2371 	        name += '(';
       
  2372 		// no parameter - shortcut
       
  2373 		if (!pDispParams->cArgs)
       
  2374 		    index = mo->indexOfSlot((name + ')'));
       
  2375 		// search
       
  2376 		if (index == -1) {
       
  2377 		    for (int i = 0; i < mo->methodCount(); ++i) {
       
  2378                         const QMetaMethod slot(mo->method(i));
       
  2379                         if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) {
       
  2380 			    index = i;
       
  2381 			    break;
       
  2382 			}
       
  2383 		    }
       
  2384                     // resolve overloads
       
  2385                     if (index == -1) {
       
  2386                         QRegExp regexp(QLatin1String("_([0-9])\\("));
       
  2387                         if (regexp.lastIndexIn(QString::fromLatin1(name.constData())) != -1) {
       
  2388                             name = name.left(name.length() - regexp.cap(0).length()) + '(';
       
  2389                             int overload = regexp.cap(1).toInt() + 1;
       
  2390 
       
  2391                             for (int s = 0; s < qt.object->metaObject()->methodCount(); ++s) {
       
  2392                                 QMetaMethod slot = qt.object->metaObject()->method(s);
       
  2393                                 if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) {
       
  2394                                     if (!--overload) {
       
  2395                                         index = s;
       
  2396                                         break;
       
  2397                                     }
       
  2398                                 }
       
  2399                             }
       
  2400                         }
       
  2401                     }
       
  2402 		    if (index == -1)
       
  2403 			return res;
       
  2404 		}
       
  2405 	    }
       
  2406 
       
  2407             int lookupIndex = index;
       
  2408 
       
  2409 	    // get slot info
       
  2410 	    QMetaMethod slot(mo->method(index));
       
  2411             Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
       
  2412 	    QByteArray type = slot.typeName();
       
  2413 	    name = slot.signature();
       
  2414             nameLength = name.indexOf('(');
       
  2415 	    QByteArray prototype = name.mid(nameLength + 1);
       
  2416 	    prototype.truncate(prototype.length() - 1);
       
  2417 	    QList<QByteArray> ptypes;
       
  2418 	    if (!prototype.isEmpty())
       
  2419 		ptypes = prototype.split(',');
       
  2420 	    int pcount = ptypes.count();
       
  2421 
       
  2422 	    // verify parameter count
       
  2423             if (pcount > pDispParams->cArgs) {
       
  2424                 // count cloned slots immediately following the real thing
       
  2425                 int defArgs = 0;
       
  2426                 while (index < mo->methodCount()) {
       
  2427                     ++index;
       
  2428                     slot = mo->method(index);
       
  2429                     if (!(slot.attributes() & QMetaMethod::Cloned))
       
  2430                         break;
       
  2431                     --pcount;
       
  2432                     // found a matching overload. ptypes still valid
       
  2433                     if (pcount <= pDispParams->cArgs)
       
  2434                         break;
       
  2435                 }
       
  2436                 // still wrong :(
       
  2437                 if (pcount > pDispParams->cArgs)
       
  2438 		    return DISP_E_PARAMNOTOPTIONAL;
       
  2439             } else if (pcount < pDispParams->cArgs) {
       
  2440 		return DISP_E_BADPARAMCOUNT;
       
  2441             }
       
  2442 
       
  2443 	    // setup parameters (pcount + return)
       
  2444 	    bool ok = true;
       
  2445             void *static_argv[QAX_NUM_PARAMS + 1];
       
  2446             QVariant static_varp[QAX_NUM_PARAMS + 1];
       
  2447             void *static_argv_pointer[QAX_NUM_PARAMS + 1];
       
  2448 
       
  2449             int totalParam = pcount;
       
  2450             if (!type.isEmpty())
       
  2451                 ++totalParam;
       
  2452 
       
  2453 	    void **argv = 0; // the actual array passed into qt_metacall
       
  2454             void **argv_pointer = 0; // in case we need an additional level of indirection
       
  2455 	    QVariant *varp = 0; // QVariants to hold the temporary Qt data object for us
       
  2456 
       
  2457             if (totalParam) {
       
  2458                 if (totalParam <= QAX_NUM_PARAMS) {
       
  2459                     argv = static_argv;
       
  2460                     argv_pointer = static_argv_pointer;
       
  2461                     varp = static_varp;
       
  2462                 } else {
       
  2463                     argv = new void*[pcount + 1];
       
  2464                     argv_pointer = new void*[pcount + 1];
       
  2465                     varp = new QVariant[pcount + 1];
       
  2466                 }
       
  2467 
       
  2468                 argv_pointer[0] = 0;
       
  2469             }
       
  2470 
       
  2471 	    for (int p = 0; p < pcount; ++p) {
       
  2472 		// map the VARIANT to the void*
       
  2473 		bool out;
       
  2474 		QByteArray ptype = paramType(ptypes.at(p), &out);
       
  2475 		varp[p + 1] = VARIANTToQVariant(pDispParams->rgvarg[pcount - p - 1], ptype);
       
  2476                 argv_pointer[p + 1] = 0;
       
  2477 		if (varp[p + 1].isValid()) {
       
  2478                     if (varp[p + 1].type() == QVariant::UserType) {
       
  2479                         argv[p + 1] = varp[p + 1].data();
       
  2480                     } else if (ptype == "QVariant") {
       
  2481                         argv[p + 1] = varp + p + 1;
       
  2482                     } else {
       
  2483                         argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
       
  2484                         if (ptype.endsWith('*')) {
       
  2485                             argv_pointer[p + 1] = argv[p + 1];
       
  2486                             argv[p + 1] = argv_pointer + p + 1;
       
  2487                         }
       
  2488                     }
       
  2489                 } else if (ptype == "QVariant") {
       
  2490                     argv[p + 1] = varp + p + 1;
       
  2491 		} else {
       
  2492 		    if (puArgErr)
       
  2493 			*puArgErr = pcount-p-1;
       
  2494 		    ok = false;
       
  2495 		}
       
  2496 	    }
       
  2497 
       
  2498             // return value
       
  2499 	    if (!type.isEmpty()) {
       
  2500                 QVariant::Type vt = QVariant::nameToType(type);
       
  2501                 if (vt == QVariant::UserType)
       
  2502                     vt = QVariant::Invalid;
       
  2503                 varp[0] = QVariant(vt);
       
  2504                 if (varp[0].type() == QVariant::Invalid && mo->indexOfEnumerator(slot.typeName()) != -1)
       
  2505                     varp[0] = QVariant(QVariant::Int);
       
  2506 
       
  2507                 if (varp[0].type() == QVariant::Invalid) {
       
  2508                     if (type == "QVariant")
       
  2509                         argv[0] = varp;
       
  2510                     else
       
  2511                         argv[0] = 0;
       
  2512                 } else {
       
  2513                     argv[0] = const_cast<void*>(varp[0].constData());
       
  2514                 }
       
  2515                 if (type.endsWith('*')) {
       
  2516                     argv_pointer[0] = argv[0];
       
  2517                     argv[0] = argv_pointer;
       
  2518                 }
       
  2519 	    }
       
  2520 
       
  2521 	    // call the slot if everthing went fine.
       
  2522 	    if (ok) {
       
  2523             ++invokeCount;
       
  2524             qt.object->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv);
       
  2525             if (--invokeCount < 0)
       
  2526                 invokeCount = 0;
       
  2527 
       
  2528 		// update reference parameters and return value
       
  2529 		for (int p = 0; p < pcount; ++p) {
       
  2530 		    bool out;
       
  2531 		    QByteArray ptype = paramType(ptypes.at(p), &out);
       
  2532 		    if (out) {
       
  2533 			if (!QVariantToVARIANT(varp[p + 1], pDispParams->rgvarg[pcount - p - 1], ptype, out))
       
  2534 			    ok = false;
       
  2535 		    }
       
  2536 		}
       
  2537                 if (!type.isEmpty() && pvarResult) {
       
  2538                     if (!varp[0].isValid() && type != "QVariant")
       
  2539                         varp[0] = QVariant(QMetaType::type(type), argv_pointer);
       
  2540 //                        qVariantSetValue(varp[0], argv_pointer[0], type);
       
  2541 		    ok = QVariantToVARIANT(varp[0], *pvarResult, type);
       
  2542                 }
       
  2543 	    }
       
  2544             if (argv && argv != static_argv) {
       
  2545                 delete []argv;
       
  2546                 delete []argv_pointer;
       
  2547                 delete []varp;
       
  2548             }
       
  2549 
       
  2550 	    res = ok ? S_OK : DISP_E_TYPEMISMATCH;
       
  2551 
       
  2552             // reset in case index changed for default-arg handling
       
  2553             index = lookupIndex;
       
  2554 	}
       
  2555 	break;
       
  2556     case DISPATCH_PROPERTYPUT:
       
  2557     case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF:
       
  2558 	{
       
  2559             if (index == -1) {
       
  2560                 index = mo->indexOfProperty(name);
       
  2561                 if (index == -1)
       
  2562                     return res;
       
  2563             }
       
  2564 
       
  2565             QMetaProperty property;
       
  2566             if (index < mo->propertyCount())
       
  2567                 property = mo->property(index);
       
  2568             if (!property.isWritable())
       
  2569                 return DISP_E_MEMBERNOTFOUND;
       
  2570             if (!pDispParams->cArgs)
       
  2571                 return DISP_E_PARAMNOTOPTIONAL;
       
  2572             if (pDispParams->cArgs != 1 ||
       
  2573                 pDispParams->cNamedArgs != 1 ||
       
  2574                 *pDispParams->rgdispidNamedArgs != DISPID_PROPERTYPUT)
       
  2575                 return DISP_E_BADPARAMCOUNT;
       
  2576 
       
  2577             QVariant var = VARIANTToQVariant(*pDispParams->rgvarg, property.typeName(), property.type());
       
  2578             if (!var.isValid()) {
       
  2579                 if (puArgErr)
       
  2580                     *puArgErr = 0;
       
  2581                 return DISP_E_BADVARTYPE;
       
  2582             }
       
  2583             if (!qt.object->setProperty(property.name(), var)) {
       
  2584                 if (puArgErr)
       
  2585                     *puArgErr = 0;
       
  2586                 return DISP_E_TYPEMISMATCH;
       
  2587             }
       
  2588 
       
  2589             res = S_OK;
       
  2590 	}
       
  2591 	break;
       
  2592 
       
  2593     default:
       
  2594 	break;
       
  2595     }
       
  2596 
       
  2597     // maybe calling a setter? Notify client about changes
       
  2598     switch(wFlags) {
       
  2599     case DISPATCH_METHOD:
       
  2600     case DISPATCH_PROPERTYPUT:
       
  2601     case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF:
       
  2602         if (m_spAdviseSink || adviseSinks.count()) {
       
  2603             FORMATETC fmt;
       
  2604             fmt.cfFormat = 0;
       
  2605             fmt.ptd = 0;
       
  2606             fmt.dwAspect = DVASPECT_CONTENT;
       
  2607             fmt.lindex = -1;
       
  2608             fmt.tymed = TYMED_NULL;
       
  2609 
       
  2610             STGMEDIUM stg;
       
  2611             stg.tymed = TYMED_NULL;
       
  2612             stg.pUnkForRelease = 0;
       
  2613             stg.hBitmap = 0; // initializes the whole union
       
  2614 
       
  2615             if (m_spAdviseSink) {
       
  2616                 m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1);
       
  2617                 m_spAdviseSink->OnDataChange(&fmt, &stg);
       
  2618             }
       
  2619             for (int i = 0; i < adviseSinks.count(); ++i) {
       
  2620                 adviseSinks.at(i).pAdvSink->OnDataChange(&fmt, &stg);
       
  2621             }
       
  2622         }
       
  2623 
       
  2624         dirtyflag = true;
       
  2625         break;
       
  2626     default:
       
  2627         break;
       
  2628     }
       
  2629 
       
  2630     if (index != -1 && uniqueIndex)
       
  2631 	indexCache.insert(dispidMember, index);
       
  2632 
       
  2633     if (exception) {
       
  2634 	if (pexcepinfo) {
       
  2635 	    memset(pexcepinfo, 0, sizeof(EXCEPINFO));
       
  2636 
       
  2637 	    pexcepinfo->wCode = exception->code;
       
  2638 	    if (!exception->src.isNull())
       
  2639 		pexcepinfo->bstrSource = QStringToBSTR(exception->src);
       
  2640 	    if (!exception->desc.isNull())
       
  2641 		pexcepinfo->bstrDescription = QStringToBSTR(exception->desc);
       
  2642 	    if (!exception->context.isNull()) {
       
  2643 		QString context = exception->context;
       
  2644 		int contextID = 0;
       
  2645 		int br = context.indexOf(QLatin1Char('['));
       
  2646 		if (br != -1) {
       
  2647 		    context = context.mid(br+1);
       
  2648 		    context = context.left(context.length() - 1);
       
  2649 		    contextID = context.toInt();
       
  2650 
       
  2651 		    context = exception->context;
       
  2652 		    context = context.left(br-1);
       
  2653 		}
       
  2654 		pexcepinfo->bstrHelpFile = QStringToBSTR(context);
       
  2655 		pexcepinfo->dwHelpContext = contextID;
       
  2656 	    }
       
  2657 	}
       
  2658 	delete exception;
       
  2659 	exception = 0;
       
  2660 	return DISP_E_EXCEPTION;
       
  2661     } else if (isWidget) {
       
  2662 	QSize sizeHint = qt.widget->sizeHint();
       
  2663 	if (oldSizeHint != sizeHint) {
       
  2664 	    updateGeometry();
       
  2665 	    if (m_spInPlaceSite) {
       
  2666                 RECT rect = {0, 0, sizeHint.width(), sizeHint.height()};
       
  2667 		m_spInPlaceSite->OnPosRectChange(&rect);
       
  2668 	    }
       
  2669 	}
       
  2670 	updateMask();
       
  2671     }
       
  2672 
       
  2673     return res;
       
  2674 }
       
  2675 
       
  2676 //**** IConnectionPointContainer
       
  2677 /*
       
  2678     Provide the IEnumConnectionPoints implemented in the QAxSignalVec class.
       
  2679 */
       
  2680 HRESULT WINAPI QAxServerBase::EnumConnectionPoints(IEnumConnectionPoints **epoints)
       
  2681 {
       
  2682     if (!epoints)
       
  2683 	return E_POINTER;
       
  2684     *epoints = new QAxSignalVec(points);
       
  2685     (*epoints)->AddRef();
       
  2686     return S_OK;
       
  2687 }
       
  2688 
       
  2689 /*
       
  2690     Provide the IConnectionPoint implemented in the QAxConnection for \a iid.
       
  2691 */
       
  2692 HRESULT WINAPI QAxServerBase::FindConnectionPoint(REFIID iid, IConnectionPoint **cpoint)
       
  2693 {
       
  2694     if (!cpoint)
       
  2695 	return E_POINTER;
       
  2696 
       
  2697     IConnectionPoint *cp = points[iid];
       
  2698     *cpoint = cp;
       
  2699     if (cp) {
       
  2700 	cp->AddRef();
       
  2701 	return S_OK;
       
  2702     }
       
  2703     return CONNECT_E_NOCONNECTION;
       
  2704 }
       
  2705 
       
  2706 //**** IPersistStream
       
  2707 /*
       
  2708     \reimp
       
  2709 
       
  2710     See documentation of IPersistStorage::IsDirty.
       
  2711 */
       
  2712 HRESULT WINAPI QAxServerBase::IsDirty()
       
  2713 {
       
  2714     return dirtyflag ? S_OK : S_FALSE;
       
  2715 }
       
  2716 
       
  2717 HRESULT WINAPI QAxServerBase::Load(IStream *pStm)
       
  2718 {
       
  2719     STATSTG stat;
       
  2720     HRESULT hres = pStm->Stat(&stat, STATFLAG_DEFAULT);
       
  2721     bool openAsText = false;
       
  2722     QByteArray qtarray;
       
  2723     if (hres == S_OK) {
       
  2724         QString streamName = QString::fromWCharArray(stat.pwcsName);
       
  2725         CoTaskMemFree(stat.pwcsName);
       
  2726         openAsText = streamName == QLatin1String("SomeStreamName");
       
  2727 	if (stat.cbSize.HighPart) // more than 4GB - too large!
       
  2728 	    return S_FALSE;
       
  2729 
       
  2730 	qtarray.resize(stat.cbSize.LowPart);
       
  2731         ULONG read;
       
  2732 	pStm->Read(qtarray.data(), stat.cbSize.LowPart, &read);
       
  2733     }
       
  2734     const QMetaObject *mo = qt.object->metaObject();
       
  2735 
       
  2736     QBuffer qtbuffer(&qtarray);
       
  2737     QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value();
       
  2738     if (!mimeType.isEmpty()) {
       
  2739         mimeType = mimeType.left(mimeType.indexOf(':')); // first type
       
  2740         QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
       
  2741         if (axb && axb->readData(&qtbuffer, QString::fromLatin1(mimeType)))
       
  2742             return S_OK;
       
  2743     }
       
  2744 
       
  2745     qtbuffer.close(); // resets
       
  2746     qtbuffer.open(openAsText ? (QIODevice::ReadOnly | QIODevice::Text) : QIODevice::ReadOnly);
       
  2747 
       
  2748     QDataStream qtstream(&qtbuffer);
       
  2749     int version;
       
  2750     qtstream >> version;
       
  2751     qtstream.setVersion(version);
       
  2752     int more = 0;
       
  2753     qtstream >> more;
       
  2754 
       
  2755     while (!qtbuffer.atEnd() && more) {
       
  2756 	QString propname;
       
  2757 	QVariant value;
       
  2758 	qtstream >> propname;
       
  2759 	if (propname.isEmpty())
       
  2760 	    break;
       
  2761 	qtstream >> value;
       
  2762 	qtstream >> more;
       
  2763 
       
  2764 	int idx = mo->indexOfProperty(propname.toLatin1());
       
  2765 	QMetaProperty property = mo->property(idx);
       
  2766 	if (property.isWritable())
       
  2767 	    qt.object->setProperty(propname.toLatin1(), value);
       
  2768     }
       
  2769     return S_OK;
       
  2770 }
       
  2771 
       
  2772 HRESULT WINAPI QAxServerBase::Save(IStream *pStm, BOOL clearDirty)
       
  2773 {
       
  2774     const QMetaObject *mo = qt.object->metaObject();
       
  2775 
       
  2776     QBuffer qtbuffer;
       
  2777     bool saved = false;
       
  2778     QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value();
       
  2779     if (!mimeType.isEmpty()) {
       
  2780         QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
       
  2781         saved = axb && axb->writeData(&qtbuffer);
       
  2782         qtbuffer.close();
       
  2783     }
       
  2784 
       
  2785     if (!saved) {
       
  2786         qtbuffer.open(QIODevice::WriteOnly);
       
  2787         QDataStream qtstream(&qtbuffer);
       
  2788         qtstream << qtstream.version();
       
  2789 
       
  2790         for (int prop = 0; prop < mo->propertyCount(); ++prop) {
       
  2791 	    if (!isPropertyExposed(prop))
       
  2792 	        continue;
       
  2793 	    QMetaProperty metaprop = mo->property(prop);
       
  2794             if (QByteArray(metaprop.typeName()).endsWith('*'))
       
  2795                 continue;
       
  2796 	    QString property = QLatin1String(metaprop.name());
       
  2797 	    QVariant qvar = qt.object->property(metaprop.name());
       
  2798 	    if (qvar.isValid()) {
       
  2799 	        qtstream << int(1);
       
  2800 	        qtstream << property;
       
  2801 	        qtstream << qvar;
       
  2802 	    }
       
  2803         }
       
  2804 
       
  2805         qtstream << int(0);
       
  2806         qtbuffer.close();
       
  2807     }
       
  2808 
       
  2809     QByteArray qtarray = qtbuffer.buffer();
       
  2810     ULONG written = 0;
       
  2811     const char *data = qtarray.constData();
       
  2812     ULARGE_INTEGER newsize;
       
  2813     newsize.HighPart = 0;
       
  2814     newsize.LowPart = qtarray.size();
       
  2815     pStm->SetSize(newsize);
       
  2816     pStm->Write(data, qtarray.size(), &written);
       
  2817     pStm->Commit(STGC_ONLYIFCURRENT);
       
  2818 
       
  2819     if (clearDirty)
       
  2820         dirtyflag = false;
       
  2821     return S_OK;
       
  2822 }
       
  2823 
       
  2824 HRESULT WINAPI QAxServerBase::GetSizeMax(ULARGE_INTEGER *pcbSize)
       
  2825 {
       
  2826     const QMetaObject *mo = qt.object->metaObject();
       
  2827 
       
  2828     int np = mo->propertyCount();
       
  2829     pcbSize->HighPart = 0;
       
  2830     pcbSize->LowPart = np * 50;
       
  2831 
       
  2832     return S_OK;
       
  2833 }
       
  2834 
       
  2835 //**** IPersistStorage
       
  2836 
       
  2837 HRESULT WINAPI QAxServerBase::InitNew(IStorage *pStg)
       
  2838 {
       
  2839     if (initNewCalled)
       
  2840 	return CO_E_ALREADYINITIALIZED;
       
  2841 
       
  2842     dirtyflag = false;
       
  2843     initNewCalled = true;
       
  2844 
       
  2845     m_spStorage = pStg;
       
  2846     if (m_spStorage)
       
  2847 	m_spStorage->AddRef();
       
  2848     return S_OK;
       
  2849 }
       
  2850 
       
  2851 HRESULT WINAPI QAxServerBase::Load(IStorage *pStg)
       
  2852 {
       
  2853     if (InitNew(pStg) != S_OK)
       
  2854 	return CO_E_ALREADYINITIALIZED;
       
  2855 
       
  2856     IStream *spStream = 0;
       
  2857     QString streamName = QLatin1String(qt.object->metaObject()->className());
       
  2858     streamName.replace(QLatin1Char(':'), QLatin1Char('.'));
       
  2859     /* Also invalid, but not relevant
       
  2860     streamName.replace(QLatin1Char('/'), QLatin1Char('_'));
       
  2861     streamName.replace(QLatin1Char('\\'), QLatin1Char('_'));
       
  2862     */
       
  2863     streamName += QLatin1String("_Stream4.2");
       
  2864 
       
  2865     pStg->OpenStream((const wchar_t *)streamName.utf16(), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream);
       
  2866     if (!spStream) // support for streams saved with 4.1 and earlier
       
  2867         pStg->OpenStream(L"SomeStreamName", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream);
       
  2868     if (!spStream)
       
  2869 	return E_FAIL;
       
  2870 
       
  2871     Load(spStream);
       
  2872     spStream->Release();
       
  2873 
       
  2874     return S_OK;
       
  2875 }
       
  2876 
       
  2877 HRESULT WINAPI QAxServerBase::Save(IStorage *pStg, BOOL fSameAsLoad)
       
  2878 {
       
  2879     IStream *spStream = 0;
       
  2880     QString streamName = QLatin1String(qt.object->metaObject()->className());
       
  2881     streamName.replace(QLatin1Char(':'), QLatin1Char('.'));
       
  2882     /* Also invalid, but not relevant
       
  2883     streamName.replace(QLatin1Char('/'), QLatin1Char('_'));
       
  2884     streamName.replace(QLatin1Char('\\'), QLatin1Char('_'));
       
  2885     */
       
  2886     streamName += QLatin1String("_Stream4.2");
       
  2887 
       
  2888     pStg->CreateStream((const wchar_t *)streamName.utf16(), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStream);
       
  2889     if (!spStream)
       
  2890 	return E_FAIL;
       
  2891 
       
  2892     Save(spStream, true);
       
  2893 
       
  2894     spStream->Release();
       
  2895     return S_OK;
       
  2896 }
       
  2897 
       
  2898 HRESULT WINAPI QAxServerBase::SaveCompleted(IStorage *pStgNew)
       
  2899 {
       
  2900     if (pStgNew) {
       
  2901 	if (m_spStorage)
       
  2902 	    m_spStorage->Release();
       
  2903 	m_spStorage = pStgNew;
       
  2904 	m_spStorage->AddRef();
       
  2905     }
       
  2906     return S_OK;
       
  2907 }
       
  2908 
       
  2909 HRESULT WINAPI QAxServerBase::HandsOffStorage()
       
  2910 {
       
  2911     if (m_spStorage) m_spStorage->Release();
       
  2912     m_spStorage = 0;
       
  2913 
       
  2914     return S_OK;
       
  2915 }
       
  2916 
       
  2917 //**** IPersistPropertyBag
       
  2918 /*
       
  2919     Initialize the properties of the Qt widget.
       
  2920 */
       
  2921 HRESULT WINAPI QAxServerBase::InitNew()
       
  2922 {
       
  2923     if (initNewCalled)
       
  2924 	return CO_E_ALREADYINITIALIZED;
       
  2925 
       
  2926     dirtyflag = false;
       
  2927     initNewCalled = true;
       
  2928     return S_OK;
       
  2929 }
       
  2930 
       
  2931 /*
       
  2932     Set the properties of the Qt widget to the values provided in the \a bag.
       
  2933 */
       
  2934 HRESULT WINAPI QAxServerBase::Load(IPropertyBag *bag, IErrorLog * /*log*/)
       
  2935 {
       
  2936     if (!bag)
       
  2937 	return E_POINTER;
       
  2938 
       
  2939     if (InitNew() != S_OK)
       
  2940 	return E_UNEXPECTED;
       
  2941 
       
  2942     bool error = false;
       
  2943     const QMetaObject *mo = qt.object->metaObject();
       
  2944     for (int prop = 0; prop < mo->propertyCount(); ++prop) {
       
  2945 	if (!isPropertyExposed(prop))
       
  2946 	    continue;
       
  2947 	QMetaProperty property = mo->property(prop);
       
  2948 	const char* pname = property.name();
       
  2949 	BSTR bstr = QStringToBSTR(QLatin1String(pname));
       
  2950 	VARIANT var;
       
  2951 	var.vt = VT_EMPTY;
       
  2952 	HRESULT res = bag->Read(bstr, &var, 0);
       
  2953 	if (property.isWritable() && var.vt != VT_EMPTY) {
       
  2954 	    if (res != S_OK || !qt.object->setProperty(pname, VARIANTToQVariant(var, property.typeName(), property.type())))
       
  2955 		error = true;
       
  2956 	}
       
  2957 	SysFreeString(bstr);
       
  2958     }
       
  2959 
       
  2960     updateGeometry();
       
  2961 
       
  2962     return /*error ? E_FAIL :*/ S_OK;
       
  2963 }
       
  2964 
       
  2965 /*
       
  2966     Save the properties of the Qt widget into the \a bag.
       
  2967 */
       
  2968 HRESULT WINAPI QAxServerBase::Save(IPropertyBag *bag, BOOL clearDirty, BOOL /*saveAll*/)
       
  2969 {
       
  2970     if (!bag)
       
  2971 	return E_POINTER;
       
  2972 
       
  2973     if (clearDirty)
       
  2974 	dirtyflag = false;
       
  2975     bool error = false;
       
  2976     const QMetaObject *mo = qt.object->metaObject();
       
  2977     for (int prop = 0; prop < mo->propertyCount(); ++prop) {
       
  2978 	if (!isPropertyExposed(prop))
       
  2979 	    continue;
       
  2980 	QMetaProperty property = mo->property(prop);
       
  2981         if (QByteArray(property.typeName()).endsWith('*'))
       
  2982             continue;
       
  2983 
       
  2984 	BSTR bstr = QStringToBSTR(QLatin1String(property.name()));
       
  2985 	QVariant qvar = qt.object->property(property.name());
       
  2986 	if (!qvar.isValid())
       
  2987 	    error = true;
       
  2988 	VARIANT var;
       
  2989 	QVariantToVARIANT(qvar, var);
       
  2990 	bag->Write(bstr, &var);
       
  2991 	SysFreeString(bstr);
       
  2992     }
       
  2993     return /*error ? E_FAIL :*/ S_OK;
       
  2994 }
       
  2995 
       
  2996 //**** IPersistFile
       
  2997 /*
       
  2998 */
       
  2999 HRESULT WINAPI QAxServerBase::SaveCompleted(LPCOLESTR fileName)
       
  3000 {
       
  3001     if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1)
       
  3002         return E_NOTIMPL;
       
  3003 
       
  3004     currentFileName = QString::fromWCharArray(fileName);
       
  3005     return S_OK;
       
  3006 }
       
  3007 
       
  3008 HRESULT WINAPI QAxServerBase::GetCurFile(LPOLESTR *currentFile)
       
  3009 {
       
  3010     if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1)
       
  3011         return E_NOTIMPL;
       
  3012 
       
  3013     if (currentFileName.isEmpty()) {
       
  3014         *currentFile = 0;
       
  3015         return S_FALSE;
       
  3016     }
       
  3017     IMalloc *malloc = 0;
       
  3018     CoGetMalloc(1, &malloc);
       
  3019     if (!malloc)
       
  3020         return E_OUTOFMEMORY;
       
  3021 
       
  3022     *currentFile = static_cast<wchar_t *>(malloc->Alloc(currentFileName.length() * 2));
       
  3023     malloc->Release();
       
  3024     memcpy(*currentFile, currentFileName.unicode(), currentFileName.length() * 2);
       
  3025 
       
  3026     return S_OK;
       
  3027 }
       
  3028 
       
  3029 HRESULT WINAPI QAxServerBase::Load(LPCOLESTR fileName, DWORD mode)
       
  3030 {
       
  3031     const QMetaObject *mo = qt.object->metaObject();
       
  3032     int mimeIndex = mo->indexOfClassInfo("MIME");
       
  3033     if (mimeIndex == -1)
       
  3034         return E_NOTIMPL;
       
  3035 
       
  3036     QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
       
  3037     if (!axb) {
       
  3038         qWarning() << class_name << ": No QAxBindable implementation for mime-type handling";
       
  3039         return E_NOTIMPL;
       
  3040     }
       
  3041 
       
  3042     QString loadFileName = QString::fromWCharArray(fileName);
       
  3043     QString fileExtension = loadFileName.mid(loadFileName.lastIndexOf(QLatin1Char('.')) + 1);
       
  3044     QFile file(loadFileName);
       
  3045 
       
  3046     QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value());
       
  3047     QStringList mimeTypes = mimeType.split(QLatin1Char(';'));
       
  3048     for (int m = 0; m < mimeTypes.count(); ++m) {
       
  3049         QString mime = mimeTypes.at(m);
       
  3050         if (mime.count(QLatin1Char(':')) != 2) {
       
  3051             qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
       
  3052             continue;
       
  3053         }
       
  3054 
       
  3055         mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type
       
  3056         if (mimeType.isEmpty()) {
       
  3057             qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
       
  3058             continue;
       
  3059         }
       
  3060         QString mimeExtension = mime.mid(mimeType.length() + 1);
       
  3061         mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':')));
       
  3062         if (mimeExtension != fileExtension)
       
  3063             continue;
       
  3064 
       
  3065         if (axb->readData(&file, mimeType)) {
       
  3066             currentFileName = loadFileName;
       
  3067             return S_OK;
       
  3068         }
       
  3069     }
       
  3070 
       
  3071     return E_FAIL;
       
  3072 }
       
  3073 
       
  3074 HRESULT WINAPI QAxServerBase::Save(LPCOLESTR fileName, BOOL fRemember)
       
  3075 {
       
  3076     const QMetaObject *mo = qt.object->metaObject();
       
  3077     int mimeIndex = mo->indexOfClassInfo("MIME");
       
  3078     if (mimeIndex == -1)
       
  3079         return E_NOTIMPL;
       
  3080 
       
  3081     QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable");
       
  3082     if (!axb) {
       
  3083         qWarning() << class_name << ": No QAxBindable implementation for mime-type handling";
       
  3084         return E_NOTIMPL;
       
  3085     }
       
  3086 
       
  3087     QString saveFileName = QString::fromWCharArray(fileName);
       
  3088     QString fileExtension = saveFileName.mid(saveFileName.lastIndexOf(QLatin1Char('.')) + 1);
       
  3089     QFile file(saveFileName);
       
  3090 
       
  3091     QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value());
       
  3092     QStringList mimeTypes = mimeType.split(QLatin1Char(';'));
       
  3093     for (int m = 0; m < mimeTypes.count(); ++m) {
       
  3094         QString mime = mimeTypes.at(m);
       
  3095         if (mime.count(QLatin1Char(':')) != 2) {
       
  3096             qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
       
  3097             continue;
       
  3098         }
       
  3099         mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type
       
  3100         if (mimeType.isEmpty()) {
       
  3101             qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME";
       
  3102             continue;
       
  3103         }
       
  3104         QString mimeExtension = mime.mid(mimeType.length() + 1);
       
  3105         mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':')));
       
  3106         if (mimeExtension != fileExtension)
       
  3107             continue;
       
  3108         if (axb->writeData(&file)) {
       
  3109             if (fRemember)
       
  3110                 currentFileName = saveFileName;
       
  3111             return S_OK;
       
  3112         }
       
  3113     }
       
  3114     return E_FAIL;
       
  3115 }
       
  3116 
       
  3117 //**** IViewObject
       
  3118 /*
       
  3119     Draws the widget into the provided device context.
       
  3120 */
       
  3121 HRESULT WINAPI QAxServerBase::Draw(DWORD dwAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
       
  3122 		HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL /*lprcWBounds*/,
       
  3123 		BOOL(__stdcall* /*pfnContinue*/)(ULONG_PTR), ULONG_PTR /*dwContinue*/)
       
  3124 {
       
  3125     if (!lprcBounds)
       
  3126 	return E_INVALIDARG;
       
  3127 
       
  3128     internalCreate();
       
  3129     if (!isWidget || !qt.widget)
       
  3130 	return OLE_E_BLANK;
       
  3131 
       
  3132     switch (dwAspect) {
       
  3133     case DVASPECT_CONTENT:
       
  3134     case DVASPECT_OPAQUE:
       
  3135     case DVASPECT_TRANSPARENT:
       
  3136 	break;
       
  3137     default:
       
  3138 	return DV_E_DVASPECT;
       
  3139     }
       
  3140     if (!ptd)
       
  3141 	hicTargetDev = 0;
       
  3142 
       
  3143     bool bDeleteDC = false;
       
  3144     if (!hicTargetDev) {
       
  3145 	hicTargetDev = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
       
  3146 	bDeleteDC = (hicTargetDev != hdcDraw);
       
  3147     }
       
  3148 
       
  3149     RECTL rc = *lprcBounds;
       
  3150     bool bMetaFile = GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE;
       
  3151     if (!bMetaFile)
       
  3152         ::LPtoDP(hicTargetDev, (LPPOINT)&rc, 2);
       
  3153 
       
  3154     QPixmap pm = QPixmap::grabWidget(qt.widget);
       
  3155     HBITMAP hbm = pm.toWinHBITMAP();
       
  3156     HDC hdc = CreateCompatibleDC(0);
       
  3157     SelectObject(hdc, hbm);
       
  3158     ::StretchBlt(hdcDraw, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0,pm.width(), pm.height(), SRCCOPY);
       
  3159     DeleteDC(hdc);
       
  3160     DeleteObject(hbm);
       
  3161 
       
  3162     if (bDeleteDC)
       
  3163 	DeleteDC(hicTargetDev);
       
  3164 
       
  3165     return S_OK;
       
  3166 }
       
  3167 
       
  3168 /*
       
  3169     Not implemented.
       
  3170 */
       
  3171 HRESULT WINAPI QAxServerBase::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
       
  3172 		HDC hicTargetDev, LOGPALETTE **ppColorSet)
       
  3173 {
       
  3174     return E_NOTIMPL;
       
  3175 }
       
  3176 
       
  3177 /*
       
  3178     Not implemented.
       
  3179 */
       
  3180 HRESULT WINAPI QAxServerBase::Freeze(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
       
  3181 {
       
  3182     return E_NOTIMPL;
       
  3183 }
       
  3184 
       
  3185 /*
       
  3186     Not implemented.
       
  3187 */
       
  3188 HRESULT WINAPI QAxServerBase::Unfreeze(DWORD dwFreeze)
       
  3189 {
       
  3190     return E_NOTIMPL;
       
  3191 }
       
  3192 
       
  3193 /*
       
  3194     Stores the provided advise sink.
       
  3195 */
       
  3196 HRESULT WINAPI QAxServerBase::SetAdvise(DWORD /*aspects*/, DWORD /*advf*/, IAdviseSink *pAdvSink)
       
  3197 {
       
  3198     if (m_spAdviseSink) m_spAdviseSink->Release();
       
  3199 
       
  3200     m_spAdviseSink = pAdvSink;
       
  3201     if (m_spAdviseSink) m_spAdviseSink->AddRef();
       
  3202     return S_OK;
       
  3203 }
       
  3204 
       
  3205 /*
       
  3206     Returns the advise sink.
       
  3207 */
       
  3208 HRESULT WINAPI QAxServerBase::GetAdvise(DWORD* /*aspects*/, DWORD* /*advf*/, IAdviseSink **ppAdvSink)
       
  3209 {
       
  3210     if (!ppAdvSink)
       
  3211 	return E_POINTER;
       
  3212 
       
  3213     *ppAdvSink = m_spAdviseSink;
       
  3214     if (*ppAdvSink)
       
  3215 	(*ppAdvSink)->AddRef();
       
  3216     return S_OK;
       
  3217 }
       
  3218 
       
  3219 //**** IViewObject2
       
  3220 /*
       
  3221     Returns the current size ONLY if the widget has already been sized.
       
  3222 */
       
  3223 HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwAspect, LONG /*lindex*/, DVTARGETDEVICE* /*ptd*/, LPSIZEL lpsizel)
       
  3224 {
       
  3225     if (!isWidget || !qt.widget || !qt.widget->testAttribute(Qt::WA_Resized))
       
  3226         return OLE_E_BLANK;
       
  3227 
       
  3228     return GetExtent(dwAspect, lpsizel);
       
  3229 }
       
  3230 
       
  3231 //**** IOleControl
       
  3232 /*
       
  3233     Not implemented.
       
  3234 */
       
  3235 HRESULT WINAPI QAxServerBase::GetControlInfo(LPCONTROLINFO)
       
  3236 {
       
  3237     return E_NOTIMPL;
       
  3238 }
       
  3239 
       
  3240 /*
       
  3241     Turns event firing on and off.
       
  3242 */
       
  3243 HRESULT WINAPI QAxServerBase::FreezeEvents(BOOL bFreeze)
       
  3244 {
       
  3245     // member of CComControl
       
  3246     if (bFreeze)
       
  3247 	freezeEvents++;
       
  3248     else
       
  3249 	freezeEvents--;
       
  3250 
       
  3251     return S_OK;
       
  3252 }
       
  3253 
       
  3254 /*
       
  3255     Not implemented.
       
  3256 */
       
  3257 HRESULT WINAPI QAxServerBase::OnMnemonic(LPMSG)
       
  3258 {
       
  3259     return E_NOTIMPL;
       
  3260 }
       
  3261 
       
  3262 /*
       
  3263     Update the ambient properties of the Qt widget.
       
  3264 */
       
  3265 HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID)
       
  3266 {
       
  3267     if (!m_spClientSite || !theObject)
       
  3268 	return S_OK;
       
  3269 
       
  3270     IDispatch *disp = 0;
       
  3271     m_spClientSite->QueryInterface(IID_IDispatch, (void**)&disp);
       
  3272     if (!disp)
       
  3273 	return S_OK;
       
  3274 
       
  3275     VARIANT var;
       
  3276     VariantInit(&var);
       
  3277     DISPPARAMS params = { 0, 0, 0, 0 };
       
  3278     disp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &params, &var, 0, 0);
       
  3279     disp->Release();
       
  3280     disp = 0;
       
  3281 
       
  3282     switch(dispID) {
       
  3283     case DISPID_AMBIENT_APPEARANCE:
       
  3284 	break;
       
  3285     case DISPID_AMBIENT_AUTOCLIP:
       
  3286 	break;
       
  3287     case DISPID_AMBIENT_BACKCOLOR:
       
  3288     case DISPID_AMBIENT_FORECOLOR:
       
  3289 	if (isWidget) {
       
  3290 	    long rgb;
       
  3291 	    if (var.vt == VT_UI4)
       
  3292 		rgb = var.ulVal;
       
  3293 	    else if (var.vt == VT_I4)
       
  3294 		rgb = var.lVal;
       
  3295 	    else
       
  3296 		break;
       
  3297 	    QPalette pal = qt.widget->palette();
       
  3298 	    pal.setColor(dispID == DISPID_AMBIENT_BACKCOLOR ? QPalette::Window : QPalette::WindowText,
       
  3299 		OLEColorToQColor(rgb));
       
  3300 	    qt.widget->setPalette(pal);
       
  3301 	}
       
  3302 	break;
       
  3303     case DISPID_AMBIENT_DISPLAYASDEFAULT:
       
  3304 	break;
       
  3305     case DISPID_AMBIENT_DISPLAYNAME:
       
  3306 	if (var.vt != VT_BSTR || !isWidget)
       
  3307 	    break;
       
  3308 	qt.widget->setWindowTitle(QString::fromWCharArray(var.bstrVal));
       
  3309 	break;
       
  3310     case DISPID_AMBIENT_FONT:
       
  3311 	if (var.vt != VT_DISPATCH || !isWidget)
       
  3312 	    break;
       
  3313 	{
       
  3314             QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font);
       
  3315             QFont qfont = qVariantValue<QFont>(qvar);
       
  3316             qt.widget->setFont(qfont);
       
  3317 	}
       
  3318 	break;
       
  3319     case DISPID_AMBIENT_LOCALEID:
       
  3320 	break;
       
  3321     case DISPID_AMBIENT_MESSAGEREFLECT:
       
  3322 	if (var.vt != VT_BOOL)
       
  3323 	    break;
       
  3324 	if (var.boolVal)
       
  3325 	    qt.widget->installEventFilter(this);
       
  3326 	else
       
  3327 	    qt.widget->removeEventFilter(this);
       
  3328 	break;
       
  3329     case DISPID_AMBIENT_PALETTE:
       
  3330 	break;
       
  3331     case DISPID_AMBIENT_SCALEUNITS:
       
  3332 	break;
       
  3333     case DISPID_AMBIENT_SHOWGRABHANDLES:
       
  3334 	break;
       
  3335     case DISPID_AMBIENT_SHOWHATCHING:
       
  3336 	break;
       
  3337     case DISPID_AMBIENT_SUPPORTSMNEMONICS:
       
  3338 	break;
       
  3339     case DISPID_AMBIENT_TEXTALIGN:
       
  3340 	break;
       
  3341     case DISPID_AMBIENT_UIDEAD:
       
  3342 	if (var.vt != VT_BOOL || !isWidget)
       
  3343 	    break;
       
  3344 	qt.widget->setEnabled(!var.boolVal);
       
  3345 	break;
       
  3346     case DISPID_AMBIENT_USERMODE:
       
  3347 	if (var.vt != VT_BOOL)
       
  3348 	    break;
       
  3349 	inDesignMode = !var.boolVal;
       
  3350 	break;
       
  3351     case DISPID_AMBIENT_RIGHTTOLEFT:
       
  3352 	if (var.vt != VT_BOOL)
       
  3353 	    break;
       
  3354 	qApp->setLayoutDirection(var.boolVal?Qt::RightToLeft:Qt::LeftToRight);
       
  3355 	break;
       
  3356     }
       
  3357 
       
  3358     return S_OK;
       
  3359 }
       
  3360 
       
  3361 //**** IOleWindow
       
  3362 /*
       
  3363     Returns the HWND of the control.
       
  3364 */
       
  3365 HRESULT WINAPI QAxServerBase::GetWindow(HWND *pHwnd)
       
  3366 {
       
  3367     if (!pHwnd)
       
  3368 	return E_POINTER;
       
  3369     *pHwnd = m_hWnd;
       
  3370     return S_OK;
       
  3371 }
       
  3372 
       
  3373 /*
       
  3374     Enters What's This mode.
       
  3375 */
       
  3376 HRESULT WINAPI QAxServerBase::ContextSensitiveHelp(BOOL fEnterMode)
       
  3377 {
       
  3378     if (fEnterMode)
       
  3379 	QWhatsThis::enterWhatsThisMode();
       
  3380     else
       
  3381 	QWhatsThis::leaveWhatsThisMode();
       
  3382     return S_OK;
       
  3383 }
       
  3384 
       
  3385 //**** IOleInPlaceObject
       
  3386 /*
       
  3387     Deactivates the control in place.
       
  3388 */
       
  3389 HRESULT WINAPI QAxServerBase::InPlaceDeactivate()
       
  3390 {
       
  3391     if (!isInPlaceActive)
       
  3392 	return S_OK;
       
  3393     UIDeactivate();
       
  3394 
       
  3395     isInPlaceActive = false;
       
  3396 
       
  3397     // if we have a window, tell it to go away.
       
  3398     if (m_hWnd) {
       
  3399 	if (::IsWindow(m_hWnd))
       
  3400 	    ::DestroyWindow(m_hWnd);
       
  3401 	m_hWnd = 0;
       
  3402     }
       
  3403 
       
  3404     if (m_spInPlaceSite)
       
  3405 	m_spInPlaceSite->OnInPlaceDeactivate();
       
  3406 
       
  3407     return S_OK;
       
  3408 }
       
  3409 
       
  3410 /*
       
  3411     Deactivates the control's user interface.
       
  3412 */
       
  3413 HRESULT WINAPI QAxServerBase::UIDeactivate()
       
  3414 {
       
  3415     // if we're not UIActive, not much to do.
       
  3416     if (!isUIActive || !m_spInPlaceSite)
       
  3417 	return S_OK;
       
  3418 
       
  3419     isUIActive = false;
       
  3420 
       
  3421     // notify frame windows, if appropriate, that we're no longer ui-active.
       
  3422     HWND hwndParent;
       
  3423     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) {
       
  3424 	if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
       
  3425 	m_spInPlaceFrame = 0;
       
  3426 	IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
       
  3427         RECT rcPos, rcClip;
       
  3428         OLEINPLACEFRAMEINFO frameInfo;
       
  3429         frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
       
  3430 
       
  3431 	m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
       
  3432 	if (spInPlaceUIWindow) {
       
  3433 	    spInPlaceUIWindow->SetActiveObject(0, 0);
       
  3434 	    spInPlaceUIWindow->Release();
       
  3435 	}
       
  3436 	if (m_spInPlaceFrame) {
       
  3437 	    removeMenu();
       
  3438             if (menuBar) {
       
  3439                 menuBar->removeEventFilter(this);
       
  3440                 menuBar = 0;
       
  3441             }
       
  3442             if (statusBar) {
       
  3443                 statusBar->removeEventFilter(this);
       
  3444 		const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)");
       
  3445 		QMetaObject::disconnect(statusBar, index, this, -1);
       
  3446 	        statusBar = 0;
       
  3447             }
       
  3448 	    m_spInPlaceFrame->SetActiveObject(0, 0);
       
  3449 	    m_spInPlaceFrame->Release();
       
  3450 	    m_spInPlaceFrame = 0;
       
  3451 	}
       
  3452     }
       
  3453     // we don't need to explicitly release the focus here since somebody
       
  3454     // else grabbing the focus is usually why we are getting called at all
       
  3455     m_spInPlaceSite->OnUIDeactivate(false);
       
  3456 
       
  3457     return S_OK;
       
  3458 }
       
  3459 
       
  3460 /*
       
  3461     Positions the control, and applies requested clipping.
       
  3462 */
       
  3463 HRESULT WINAPI QAxServerBase::SetObjectRects(LPCRECT prcPos, LPCRECT prcClip)
       
  3464 {
       
  3465     if (prcPos == 0 || prcClip == 0)
       
  3466 	return E_POINTER;
       
  3467 
       
  3468     if (m_hWnd) {
       
  3469 	// the container wants us to clip, so figure out if we really need to
       
  3470 	RECT rcIXect;
       
  3471 	BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
       
  3472 	HRGN tempRgn = 0;
       
  3473 	if (b && !EqualRect(&rcIXect, prcPos)) {
       
  3474 	    OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
       
  3475 	    tempRgn = CreateRectRgnIndirect(&rcIXect);
       
  3476 	}
       
  3477 
       
  3478 	::SetWindowRgn(m_hWnd, tempRgn, true);
       
  3479 	::SetWindowPos(m_hWnd, 0, prcPos->left, prcPos->top,
       
  3480             prcPos->right - prcPos->left, prcPos->bottom - prcPos->top,
       
  3481 	    SWP_NOZORDER | SWP_NOACTIVATE);
       
  3482     }
       
  3483 
       
  3484     //Save the new extent.
       
  3485     m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), int(prcPos->right - prcPos->left), qt.widget->maximumWidth());
       
  3486     m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), int(prcPos->bottom - prcPos->top), qt.widget->maximumHeight());
       
  3487 
       
  3488     return S_OK;
       
  3489 }
       
  3490 
       
  3491 /*
       
  3492     Not implemented.
       
  3493 */
       
  3494 HRESULT WINAPI QAxServerBase::ReactivateAndUndo()
       
  3495 {
       
  3496     return E_NOTIMPL;
       
  3497 }
       
  3498 
       
  3499 //**** IOleInPlaceActiveObject
       
  3500 
       
  3501 Q_GUI_EXPORT int qt_translateKeyCode(int);
       
  3502 
       
  3503 HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg)
       
  3504 {
       
  3505     if (pMsg->message != WM_KEYDOWN || !isWidget)
       
  3506         return S_FALSE;
       
  3507 
       
  3508     DWORD dwKeyMod = 0;
       
  3509     if (::GetKeyState(VK_SHIFT) < 0)
       
  3510         dwKeyMod |= 1;	// KEYMOD_SHIFT
       
  3511     if (::GetKeyState(VK_CONTROL) < 0)
       
  3512         dwKeyMod |= 2;	// KEYMOD_CONTROL
       
  3513     if (::GetKeyState(VK_MENU) < 0)
       
  3514         dwKeyMod |= 4;	// KEYMOD_ALT
       
  3515 
       
  3516     switch (LOWORD(pMsg->wParam)) {
       
  3517     case VK_TAB:
       
  3518         if (isUIActive) {
       
  3519             bool shift = ::GetKeyState(VK_SHIFT) < 0;
       
  3520             bool giveUp = true;
       
  3521             QWidget *curFocus = qt.widget->focusWidget();
       
  3522             if (curFocus) {
       
  3523                 if (shift) {
       
  3524                     if (!curFocus->isWindow()) {
       
  3525                         QWidget *nextFocus = curFocus->nextInFocusChain();
       
  3526                         QWidget *prevFocus = 0;
       
  3527                         QWidget *topLevel = 0;
       
  3528                         while (nextFocus != curFocus) {
       
  3529                             if (nextFocus->focusPolicy() & Qt::TabFocus) {
       
  3530                                 prevFocus = nextFocus;
       
  3531                                 topLevel = 0;
       
  3532                             } else if (nextFocus->isWindow()) {
       
  3533                                 topLevel = nextFocus;
       
  3534                             }
       
  3535                             nextFocus = nextFocus->nextInFocusChain();
       
  3536                         }
       
  3537 
       
  3538                         if (!topLevel) {
       
  3539                             giveUp = false;
       
  3540                             ((HackWidget*)curFocus)->focusNextPrevChild(false);
       
  3541                             curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
       
  3542                         }
       
  3543                     }
       
  3544                 } else {
       
  3545                     QWidget *nextFocus = curFocus;
       
  3546                     while (1) {
       
  3547                         nextFocus = nextFocus->nextInFocusChain();
       
  3548                         if (nextFocus->isWindow())
       
  3549                             break;
       
  3550                         if (nextFocus->focusPolicy() & Qt::TabFocus) {
       
  3551                             giveUp = false;
       
  3552                             ((HackWidget*)curFocus)->focusNextPrevChild(true);
       
  3553                             curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
       
  3554                             break;
       
  3555                         }
       
  3556                     }
       
  3557                 }
       
  3558             }
       
  3559             if (giveUp) {
       
  3560                 HWND hwnd = ::GetParent(m_hWnd);
       
  3561                 ::SetFocus(hwnd);
       
  3562             } else {
       
  3563                 return S_OK;
       
  3564             }
       
  3565 
       
  3566         }
       
  3567         break;
       
  3568 
       
  3569     case VK_LEFT:
       
  3570     case VK_RIGHT:
       
  3571     case VK_UP:
       
  3572     case VK_DOWN:
       
  3573         if (isUIActive)
       
  3574             return S_FALSE;
       
  3575         break;
       
  3576 
       
  3577     default:
       
  3578         if (isUIActive && qt.widget->focusWidget()) {
       
  3579             int state = Qt::NoButton;
       
  3580             if (dwKeyMod & 1)
       
  3581                 state |= Qt::ShiftModifier;
       
  3582             if (dwKeyMod & 2)
       
  3583                 state |= Qt::ControlModifier;
       
  3584             if (dwKeyMod & 4)
       
  3585                 state |= Qt::AltModifier;
       
  3586 
       
  3587             int key = pMsg->wParam;
       
  3588             if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9'))
       
  3589                 key = qt_translateKeyCode(pMsg->wParam);
       
  3590 
       
  3591             QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state);
       
  3592             override.ignore();
       
  3593             QApplication::sendEvent(qt.widget->focusWidget(), &override);
       
  3594             if (override.isAccepted())
       
  3595                 return S_FALSE;
       
  3596         }
       
  3597         break;
       
  3598     }
       
  3599 
       
  3600     if (!m_spClientSite)
       
  3601         return S_FALSE;
       
  3602 
       
  3603     IOleControlSite *controlSite = 0;
       
  3604     m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&controlSite);
       
  3605     if (!controlSite)
       
  3606         return S_FALSE;
       
  3607     bool resetUserData = false;
       
  3608     // set server type in the user-data of the window.
       
  3609 #ifdef GWLP_USERDATA
       
  3610     LONG_PTR serverType = QAX_INPROC_SERVER;
       
  3611 #else
       
  3612     LONG serverType = QAX_INPROC_SERVER;
       
  3613 #endif
       
  3614     if (qAxOutProcServer)
       
  3615         serverType = QAX_OUTPROC_SERVER;
       
  3616 #ifdef GWLP_USERDATA
       
  3617     LONG_PTR oldData = SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, serverType);
       
  3618 #else
       
  3619     LONG oldData = SetWindowLong(pMsg->hwnd, GWL_USERDATA, serverType);
       
  3620 #endif
       
  3621     HRESULT hres = controlSite->TranslateAcceleratorW(pMsg, dwKeyMod);
       
  3622     controlSite->Release();
       
  3623     // reset the user-data for the window.
       
  3624 #ifdef GWLP_USERDATA
       
  3625     SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, oldData);
       
  3626 #else
       
  3627     SetWindowLong(pMsg->hwnd, GWL_USERDATA, oldData);
       
  3628 #endif
       
  3629     return hres;
       
  3630 }
       
  3631 
       
  3632 HRESULT WINAPI QAxServerBase::TranslateAcceleratorA(MSG *pMsg)
       
  3633 {
       
  3634     return TranslateAcceleratorW(pMsg);
       
  3635 }
       
  3636 
       
  3637 HRESULT WINAPI QAxServerBase::OnFrameWindowActivate(BOOL fActivate)
       
  3638 {
       
  3639     if (fActivate) {
       
  3640 	if (wasUIActive)
       
  3641 	    ::SetFocus(m_hWnd);
       
  3642     } else {
       
  3643 	wasUIActive = isUIActive;
       
  3644     }
       
  3645     return S_OK;
       
  3646 }
       
  3647 
       
  3648 HRESULT WINAPI QAxServerBase::OnDocWindowActivate(BOOL fActivate)
       
  3649 {
       
  3650     return S_OK;
       
  3651 }
       
  3652 
       
  3653 HRESULT WINAPI QAxServerBase::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow)
       
  3654 {
       
  3655     return S_OK;
       
  3656 }
       
  3657 
       
  3658 HRESULT WINAPI QAxServerBase::EnableModeless(BOOL fEnable)
       
  3659 {
       
  3660     if (!isWidget)
       
  3661 	return S_OK;
       
  3662 
       
  3663     EnableWindow(qt.widget->winId(), fEnable);
       
  3664     return S_OK;
       
  3665 }
       
  3666 
       
  3667 //**** IOleObject
       
  3668 
       
  3669 static inline LPOLESTR QStringToOLESTR(const QString &qstring)
       
  3670 {
       
  3671     LPOLESTR olestr = (wchar_t*)CoTaskMemAlloc(qstring.length()*2+2);
       
  3672     memcpy(olestr, (ushort*)qstring.unicode(), qstring.length()*2);
       
  3673     olestr[qstring.length()] = 0;
       
  3674     return olestr;
       
  3675 }
       
  3676 
       
  3677 /*
       
  3678     \reimp
       
  3679 
       
  3680     See documentation of IOleObject::GetUserType.
       
  3681 */
       
  3682 HRESULT WINAPI QAxServerBase::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
       
  3683 {
       
  3684     if (!pszUserType)
       
  3685 	return E_POINTER;
       
  3686 
       
  3687     switch (dwFormOfType) {
       
  3688     case USERCLASSTYPE_FULL:
       
  3689 	*pszUserType = QStringToOLESTR(class_name);
       
  3690 	break;
       
  3691     case USERCLASSTYPE_SHORT:
       
  3692 	if (!qt.widget || !isWidget || qt.widget->windowTitle().isEmpty())
       
  3693 	    *pszUserType = QStringToOLESTR(class_name);
       
  3694 	else
       
  3695 	    *pszUserType = QStringToOLESTR(qt.widget->windowTitle());
       
  3696 	break;
       
  3697     case USERCLASSTYPE_APPNAME:
       
  3698 	*pszUserType = QStringToOLESTR(qApp->objectName());
       
  3699 	break;
       
  3700     }
       
  3701 
       
  3702     return S_OK;
       
  3703 }
       
  3704 
       
  3705 /*
       
  3706     Returns the status flags registered for this control.
       
  3707 */
       
  3708 HRESULT WINAPI QAxServerBase::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
       
  3709 {
       
  3710     return OleRegGetMiscStatus(qAxFactory()->classID(class_name), dwAspect, pdwStatus);
       
  3711 }
       
  3712 
       
  3713 /*
       
  3714     Stores the provided advise sink.
       
  3715 */
       
  3716 HRESULT WINAPI QAxServerBase::Advise(IAdviseSink* pAdvSink, DWORD* pdwConnection)
       
  3717 {
       
  3718     *pdwConnection = adviseSinks.count() + 1;
       
  3719     STATDATA data = { {0, 0, DVASPECT_CONTENT, -1, TYMED_NULL} , 0, pAdvSink, *pdwConnection };
       
  3720     adviseSinks.append(data);
       
  3721     pAdvSink->AddRef();
       
  3722     return S_OK;
       
  3723 }
       
  3724 
       
  3725 /*
       
  3726     Closes the control.
       
  3727 */
       
  3728 HRESULT WINAPI QAxServerBase::Close(DWORD dwSaveOption)
       
  3729 {
       
  3730     if (dwSaveOption != OLECLOSE_NOSAVE && m_spClientSite)
       
  3731 	m_spClientSite->SaveObject();
       
  3732     if (isInPlaceActive) {
       
  3733 	HRESULT hr = InPlaceDeactivate();
       
  3734 	if (FAILED(hr))
       
  3735 	    return hr;
       
  3736     }
       
  3737     if (m_hWnd) {
       
  3738 	if (IsWindow(m_hWnd))
       
  3739 	    DestroyWindow(m_hWnd);
       
  3740 	m_hWnd = 0;
       
  3741 	if (m_spClientSite)
       
  3742 	    m_spClientSite->OnShowWindow(false);
       
  3743     }
       
  3744 
       
  3745     if (m_spInPlaceSite) m_spInPlaceSite->Release();
       
  3746     m_spInPlaceSite = 0;
       
  3747 
       
  3748     if (m_spAdviseSink)
       
  3749 	m_spAdviseSink->OnClose();
       
  3750     for (int i = 0; i < adviseSinks.count(); ++i) {
       
  3751         adviseSinks.at(i).pAdvSink->OnClose();
       
  3752     }
       
  3753 
       
  3754     return S_OK;
       
  3755 }
       
  3756 
       
  3757 bool qax_disable_inplaceframe = true;
       
  3758 
       
  3759 /*
       
  3760     Executes the steps to activate the control.
       
  3761 */
       
  3762 HRESULT QAxServerBase::internalActivate()
       
  3763 {
       
  3764     if (!m_spClientSite)
       
  3765 	return S_OK;
       
  3766     if (!m_spInPlaceSite)
       
  3767         m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void**)&m_spInPlaceSite);
       
  3768     if (!m_spInPlaceSite)
       
  3769 	return E_FAIL;
       
  3770 
       
  3771     HRESULT hr = E_FAIL;
       
  3772     if (!isInPlaceActive) {
       
  3773 	BOOL bNoRedraw = false;
       
  3774 	hr = m_spInPlaceSite->CanInPlaceActivate();
       
  3775 	if (FAILED(hr))
       
  3776 	    return hr;
       
  3777 	if (hr != S_OK)
       
  3778 	    return E_FAIL;
       
  3779 	m_spInPlaceSite->OnInPlaceActivate();
       
  3780     }
       
  3781 
       
  3782     isInPlaceActive = true;
       
  3783     OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
       
  3784 
       
  3785     if (isWidget) {
       
  3786         IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
       
  3787         HWND hwndParent;
       
  3788         if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) {
       
  3789             // get location in the parent window, as well as some information about the parent
       
  3790             if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
       
  3791             m_spInPlaceFrame = 0;
       
  3792             RECT rcPos, rcClip;
       
  3793             OLEINPLACEFRAMEINFO frameInfo;
       
  3794             frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
       
  3795             m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
       
  3796             if (m_hWnd) {
       
  3797                 ::ShowWindow(m_hWnd, SW_SHOW);
       
  3798                 if (!::IsChild(m_hWnd, ::GetFocus()) && qt.widget->focusPolicy() != Qt::NoFocus)
       
  3799                     ::SetFocus(m_hWnd);
       
  3800             } else {
       
  3801                 create(hwndParent, rcPos);
       
  3802             }
       
  3803         }
       
  3804 
       
  3805 	// Gone active by now, take care of UIACTIVATE
       
  3806 	canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode;
       
  3807 	if (!canTakeFocus && !inDesignMode) {
       
  3808 	    QList<QWidget*> widgets = qFindChildren<QWidget*>(qt.widget);
       
  3809 	    for (int w = 0; w < widgets.count(); ++w) {
       
  3810 		QWidget *widget = widgets[w];
       
  3811 		canTakeFocus = widget->focusPolicy() != Qt::NoFocus;
       
  3812                 if (canTakeFocus)
       
  3813                     break;
       
  3814 	    }
       
  3815 	}
       
  3816 	if (!isUIActive && canTakeFocus) {
       
  3817 	    isUIActive = true;
       
  3818 	    hr = m_spInPlaceSite->OnUIActivate();
       
  3819 	    if (FAILED(hr)) {
       
  3820 		if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
       
  3821 		m_spInPlaceFrame = 0;
       
  3822 		if (spInPlaceUIWindow) spInPlaceUIWindow->Release();
       
  3823 		return hr;
       
  3824 	    }
       
  3825 
       
  3826 	    if (isInPlaceActive) {
       
  3827 		if (!::IsChild(m_hWnd, ::GetFocus()))
       
  3828 		    ::SetFocus(m_hWnd);
       
  3829 	    }
       
  3830 
       
  3831 	    if (m_spInPlaceFrame) {
       
  3832 		hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name));
       
  3833 		if (!FAILED(hr)) {
       
  3834 		    menuBar = (qt.widget && !qax_disable_inplaceframe) ? qFindChild<QMenuBar*>(qt.widget) : 0;
       
  3835 		    if (menuBar && !menuBar->isVisible()) {
       
  3836 			createMenu(menuBar);
       
  3837 			menuBar->hide();
       
  3838 			menuBar->installEventFilter(this);
       
  3839 		    }
       
  3840 		    statusBar = qt.widget ? qFindChild<QStatusBar*>(qt.widget) : 0;
       
  3841 		    if (statusBar && !statusBar->isVisible()) {
       
  3842 			const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)");
       
  3843 			QMetaObject::connect(statusBar, index, this, -1);
       
  3844 			statusBar->hide();
       
  3845 			statusBar->installEventFilter(this);
       
  3846 		    }
       
  3847 		}
       
  3848 	    }
       
  3849 	    if (spInPlaceUIWindow) {
       
  3850 		spInPlaceUIWindow->SetActiveObject(this, QStringToBSTR(class_name));
       
  3851 		spInPlaceUIWindow->SetBorderSpace(0);
       
  3852 	    }
       
  3853 	}
       
  3854         if (spInPlaceUIWindow) spInPlaceUIWindow->Release();
       
  3855 	ShowWindow(m_hWnd, SW_NORMAL);
       
  3856     }
       
  3857 
       
  3858     m_spClientSite->ShowObject();
       
  3859 
       
  3860     return S_OK;
       
  3861 }
       
  3862 
       
  3863 /*
       
  3864     Executes the "verb" \a iVerb.
       
  3865 */
       
  3866 HRESULT WINAPI QAxServerBase::DoVerb(LONG iVerb, LPMSG /*lpmsg*/, IOleClientSite* /*pActiveSite*/, LONG /*lindex*/,
       
  3867 			       HWND /*hwndParent*/, LPCRECT /*prcPosRect*/)
       
  3868 {
       
  3869     HRESULT hr = E_NOTIMPL;
       
  3870     switch (iVerb)
       
  3871     {
       
  3872     case OLEIVERB_SHOW:
       
  3873 	hr = internalActivate();
       
  3874 	if (SUCCEEDED(hr))
       
  3875 	    hr = S_OK;
       
  3876 	break;
       
  3877 
       
  3878     case OLEIVERB_PRIMARY:
       
  3879     case OLEIVERB_INPLACEACTIVATE:
       
  3880 	hr = internalActivate();
       
  3881 	if (SUCCEEDED(hr)) {
       
  3882 	    hr = S_OK;
       
  3883 	    update();
       
  3884 	}
       
  3885 	break;
       
  3886 
       
  3887     case OLEIVERB_UIACTIVATE:
       
  3888 	if (!isUIActive) {
       
  3889 	    hr = internalActivate();
       
  3890 	    if (SUCCEEDED(hr))
       
  3891 		hr = S_OK;
       
  3892 	}
       
  3893 	break;
       
  3894 
       
  3895     case OLEIVERB_HIDE:
       
  3896 	UIDeactivate();
       
  3897 	if (m_hWnd)
       
  3898 	    ::ShowWindow(m_hWnd, SW_HIDE);
       
  3899 	hr = S_OK;
       
  3900 	return hr;
       
  3901 
       
  3902     default:
       
  3903 	break;
       
  3904     }
       
  3905     return hr;
       
  3906 }
       
  3907 
       
  3908 /*
       
  3909     Not implemented.
       
  3910 */
       
  3911 HRESULT WINAPI QAxServerBase::EnumAdvise(IEnumSTATDATA** /*ppenumAdvise*/)
       
  3912 {
       
  3913     return E_NOTIMPL;
       
  3914 }
       
  3915 
       
  3916 /*
       
  3917     Returns an enumerator for the verbs registered for this class.
       
  3918 */
       
  3919 HRESULT WINAPI QAxServerBase::EnumVerbs(IEnumOLEVERB** ppEnumOleVerb)
       
  3920 {
       
  3921     if (!ppEnumOleVerb)
       
  3922 	return E_POINTER;
       
  3923     return OleRegEnumVerbs(qAxFactory()->classID(class_name), ppEnumOleVerb);
       
  3924 }
       
  3925 
       
  3926 /*
       
  3927     Returns the current client site..
       
  3928 */
       
  3929 HRESULT WINAPI QAxServerBase::GetClientSite(IOleClientSite** ppClientSite)
       
  3930 {
       
  3931     if (!ppClientSite)
       
  3932 	return E_POINTER;
       
  3933     *ppClientSite = m_spClientSite;
       
  3934     if (*ppClientSite)
       
  3935 	(*ppClientSite)->AddRef();
       
  3936     return S_OK;
       
  3937 }
       
  3938 
       
  3939 /*
       
  3940     Not implemented.
       
  3941 */
       
  3942 HRESULT WINAPI QAxServerBase::GetClipboardData(DWORD, IDataObject**)
       
  3943 {
       
  3944     return E_NOTIMPL;
       
  3945 }
       
  3946 
       
  3947 /*
       
  3948     Returns the current extent.
       
  3949 */
       
  3950 HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwDrawAspect, SIZEL* psizel)
       
  3951 {
       
  3952     if (dwDrawAspect != DVASPECT_CONTENT || !isWidget || !qt.widget)
       
  3953 	return E_FAIL;
       
  3954     if (!psizel)
       
  3955 	return E_POINTER;
       
  3956 
       
  3957     psizel->cx = MAP_PIX_TO_LOGHIM(m_currentExtent.width(), qt.widget->logicalDpiX());
       
  3958     psizel->cy = MAP_PIX_TO_LOGHIM(m_currentExtent.height(), qt.widget->logicalDpiY());
       
  3959     return S_OK;
       
  3960 }
       
  3961 
       
  3962 /*
       
  3963     Not implemented.
       
  3964 */
       
  3965 HRESULT WINAPI QAxServerBase::GetMoniker(DWORD, DWORD, IMoniker** )
       
  3966 {
       
  3967     return E_NOTIMPL;
       
  3968 }
       
  3969 
       
  3970 /*
       
  3971     Returns the CLSID of this class.
       
  3972 */
       
  3973 HRESULT WINAPI QAxServerBase::GetUserClassID(CLSID* pClsid)
       
  3974 {
       
  3975     if (!pClsid)
       
  3976 	return E_POINTER;
       
  3977     *pClsid = qAxFactory()->classID(class_name);
       
  3978     return S_OK;
       
  3979 }
       
  3980 
       
  3981 /*
       
  3982     Not implemented.
       
  3983 */
       
  3984 HRESULT WINAPI QAxServerBase::InitFromData(IDataObject*, BOOL, DWORD)
       
  3985 {
       
  3986     return E_NOTIMPL;
       
  3987 }
       
  3988 
       
  3989 /*
       
  3990     Not implemented.
       
  3991 */
       
  3992 HRESULT WINAPI QAxServerBase::IsUpToDate()
       
  3993 {
       
  3994     return S_OK;
       
  3995 }
       
  3996 
       
  3997 /*
       
  3998     Stores the client site.
       
  3999 */
       
  4000 HRESULT WINAPI QAxServerBase::SetClientSite(IOleClientSite* pClientSite)
       
  4001 {
       
  4002     // release all client site interfaces
       
  4003     if (m_spClientSite) m_spClientSite->Release();
       
  4004     if (m_spInPlaceSite) m_spInPlaceSite->Release();
       
  4005     m_spInPlaceSite = 0;
       
  4006     if (m_spInPlaceFrame) m_spInPlaceFrame->Release();
       
  4007     m_spInPlaceFrame = 0;
       
  4008 
       
  4009     m_spClientSite = pClientSite;
       
  4010     if (m_spClientSite) {
       
  4011         m_spClientSite->AddRef();
       
  4012 	m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
       
  4013     }
       
  4014 
       
  4015     return S_OK;
       
  4016 }
       
  4017 
       
  4018 /*
       
  4019     Not implemented.
       
  4020 */
       
  4021 HRESULT WINAPI QAxServerBase::SetColorScheme(LOGPALETTE*)
       
  4022 {
       
  4023     return E_NOTIMPL;
       
  4024 }
       
  4025 
       
  4026 
       
  4027 #ifdef QT_DLL // avoid conflict with symbol in static lib
       
  4028 bool qt_sendSpontaneousEvent(QObject *o, QEvent *e)
       
  4029 {
       
  4030     return QCoreApplication::sendSpontaneousEvent(o, e);
       
  4031 }
       
  4032 #endif
       
  4033 
       
  4034 /*
       
  4035     Tries to set the size of the control.
       
  4036 */
       
  4037 HRESULT WINAPI QAxServerBase::SetExtent(DWORD dwDrawAspect, SIZEL* psizel)
       
  4038 {
       
  4039     if (dwDrawAspect != DVASPECT_CONTENT)
       
  4040 	return DV_E_DVASPECT;
       
  4041     if (!psizel)
       
  4042 	return E_POINTER;
       
  4043 
       
  4044     if (!isWidget || !qt.widget) // nothing to do
       
  4045 	return S_OK;
       
  4046 
       
  4047     QSize proposedSize(MAP_LOGHIM_TO_PIX(psizel->cx, qt.widget->logicalDpiX()),
       
  4048         MAP_LOGHIM_TO_PIX(psizel->cy, qt.widget->logicalDpiY()));
       
  4049 
       
  4050     // can the widget be resized at all?
       
  4051     if (qt.widget->minimumSize() == qt.widget->maximumSize() && qt.widget->minimumSize() != proposedSize)
       
  4052         return E_FAIL;
       
  4053     //Save the extent, bound to the widget restrictions.
       
  4054     m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), proposedSize.width(), qt.widget->maximumWidth());
       
  4055     m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), proposedSize.height(), qt.widget->maximumHeight());
       
  4056 
       
  4057     resize(proposedSize);
       
  4058     return S_OK;
       
  4059 }
       
  4060 
       
  4061 /*
       
  4062     Not implemented.
       
  4063 */
       
  4064 HRESULT WINAPI QAxServerBase::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
       
  4065 {
       
  4066     return S_OK;
       
  4067 }
       
  4068 
       
  4069 /*
       
  4070     Not implemented.
       
  4071 */
       
  4072 HRESULT WINAPI QAxServerBase::SetMoniker(DWORD, IMoniker*)
       
  4073 {
       
  4074     return E_NOTIMPL;
       
  4075 }
       
  4076 
       
  4077 /*
       
  4078     Disconnects an advise sink.
       
  4079 */
       
  4080 HRESULT WINAPI QAxServerBase::Unadvise(DWORD dwConnection)
       
  4081 {
       
  4082     for (int i = 0; i < adviseSinks.count(); ++i) {
       
  4083         STATDATA entry = adviseSinks.at(i);
       
  4084         if (entry.dwConnection == dwConnection) {
       
  4085             entry.pAdvSink->Release();
       
  4086             adviseSinks.removeAt(i);
       
  4087             return S_OK;
       
  4088         }
       
  4089     }
       
  4090     return OLE_E_NOCONNECTION;
       
  4091 }
       
  4092 
       
  4093 /*
       
  4094     Not implemented.
       
  4095 */
       
  4096 HRESULT WINAPI QAxServerBase::Update()
       
  4097 {
       
  4098     return S_OK;
       
  4099 }
       
  4100 
       
  4101 //**** IDataObject
       
  4102 /*
       
  4103     Calls IViewObject::Draw after setting up the parameters.
       
  4104 */
       
  4105 HRESULT WINAPI QAxServerBase::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
       
  4106 {
       
  4107     if (!pmedium)
       
  4108 	return E_POINTER;
       
  4109     if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
       
  4110 	return DATA_E_FORMATETC;
       
  4111 
       
  4112     internalCreate();
       
  4113     if (!isWidget || !qt.widget)
       
  4114 	return E_UNEXPECTED;
       
  4115 
       
  4116     // Container wants to draw, but the size is not defined yet - ask container
       
  4117     if (m_spInPlaceSite && !qt.widget->testAttribute(Qt::WA_Resized)) {
       
  4118 	IOleInPlaceUIWindow *spInPlaceUIWindow = 0;
       
  4119         RECT rcPos, rcClip;
       
  4120         OLEINPLACEFRAMEINFO frameInfo;
       
  4121         frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
       
  4122 
       
  4123 	HRESULT hres = m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
       
  4124         if (hres == S_OK) {
       
  4125             QSize size(rcPos.right - rcPos.left, rcPos.bottom - rcPos.top);
       
  4126             resize(size);
       
  4127         } else {
       
  4128             qt.widget->adjustSize();
       
  4129         }
       
  4130         if (spInPlaceUIWindow) spInPlaceUIWindow->Release(); // no need for it
       
  4131     }
       
  4132 
       
  4133     int width = qt.widget->width();
       
  4134     int height = qt.widget->height();
       
  4135     RECTL rectl = {0, 0, width, height};
       
  4136 
       
  4137     HDC hdc = CreateMetaFile(0);
       
  4138     SaveDC(hdc);
       
  4139     SetWindowOrgEx(hdc, 0, 0, 0);
       
  4140     SetWindowExtEx(hdc, rectl.right, rectl.bottom, 0);
       
  4141 
       
  4142     Draw(pformatetcIn->dwAspect, pformatetcIn->lindex, 0, pformatetcIn->ptd, 0, hdc, &rectl, &rectl, 0, 0);
       
  4143 
       
  4144     RestoreDC(hdc, -1);
       
  4145     HMETAFILE hMF = CloseMetaFile(hdc);
       
  4146     if (!hMF)
       
  4147 	return E_UNEXPECTED;
       
  4148 
       
  4149     HGLOBAL hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
       
  4150     if (!hMem) {
       
  4151 	DeleteMetaFile(hMF);
       
  4152 	return ResultFromScode(STG_E_MEDIUMFULL);
       
  4153     }
       
  4154 
       
  4155     LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMem);
       
  4156     pMF->hMF = hMF;
       
  4157     pMF->mm = MM_ANISOTROPIC;
       
  4158     pMF->xExt = MAP_PIX_TO_LOGHIM(width, qt.widget->logicalDpiX());
       
  4159     pMF->yExt = MAP_PIX_TO_LOGHIM(height, qt.widget->logicalDpiY());
       
  4160     GlobalUnlock(hMem);
       
  4161 
       
  4162     memset(pmedium, 0, sizeof(STGMEDIUM));
       
  4163     pmedium->tymed = TYMED_MFPICT;
       
  4164     pmedium->hGlobal = hMem;
       
  4165     pmedium->pUnkForRelease = 0;
       
  4166 
       
  4167     return S_OK;
       
  4168 }
       
  4169 
       
  4170 /*
       
  4171     Not implemented.
       
  4172 */
       
  4173 HRESULT WINAPI QAxServerBase::DAdvise(FORMATETC *pformatetc, DWORD advf,
       
  4174 				      IAdviseSink *pAdvSink, DWORD *pdwConnection)
       
  4175 {
       
  4176     if (pformatetc->dwAspect != DVASPECT_CONTENT)
       
  4177         return E_FAIL;
       
  4178 
       
  4179     *pdwConnection = adviseSinks.count() + 1;
       
  4180     STATDATA data = {
       
  4181         {pformatetc->cfFormat,pformatetc->ptd,pformatetc->dwAspect,pformatetc->lindex,pformatetc->tymed},
       
  4182         advf, pAdvSink, *pdwConnection
       
  4183     };
       
  4184     adviseSinks.append(data);
       
  4185     pAdvSink->AddRef();
       
  4186     return S_OK;
       
  4187 }
       
  4188 
       
  4189 /*
       
  4190     Not implemented.
       
  4191 */
       
  4192 HRESULT WINAPI QAxServerBase::DUnadvise(DWORD dwConnection)
       
  4193 {
       
  4194     return Unadvise(dwConnection);
       
  4195 }
       
  4196 
       
  4197 /*
       
  4198     Not implemented.
       
  4199 */
       
  4200 HRESULT WINAPI QAxServerBase::EnumDAdvise(IEnumSTATDATA ** /*ppenumAdvise*/)
       
  4201 {
       
  4202     return E_NOTIMPL;
       
  4203 }
       
  4204 
       
  4205 /*
       
  4206     Not implemented.
       
  4207 */
       
  4208 HRESULT WINAPI QAxServerBase::GetDataHere(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */)
       
  4209 {
       
  4210     return E_NOTIMPL;
       
  4211 }
       
  4212 
       
  4213 /*
       
  4214     Not implemented.
       
  4215 */
       
  4216 HRESULT WINAPI QAxServerBase::QueryGetData(FORMATETC* /* pformatetc */)
       
  4217 {
       
  4218     return E_NOTIMPL;
       
  4219 }
       
  4220 
       
  4221 /*
       
  4222     Not implemented.
       
  4223 */
       
  4224 HRESULT WINAPI QAxServerBase::GetCanonicalFormatEtc(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
       
  4225 {
       
  4226     return E_NOTIMPL;
       
  4227 }
       
  4228 
       
  4229 /*
       
  4230     Not implemented.
       
  4231 */
       
  4232 HRESULT WINAPI QAxServerBase::SetData(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
       
  4233 {
       
  4234     return E_NOTIMPL;
       
  4235 }
       
  4236 
       
  4237 /*
       
  4238     Not implemented.
       
  4239 */
       
  4240 HRESULT WINAPI QAxServerBase::EnumFormatEtc(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
       
  4241 {
       
  4242     return E_NOTIMPL;
       
  4243 }
       
  4244 
       
  4245 
       
  4246 
       
  4247 static int mapModifiers(int state)
       
  4248 {
       
  4249     int ole = 0;
       
  4250     if (state & Qt::ShiftModifier)
       
  4251 	ole |= 1;
       
  4252     if (state & Qt::ControlModifier)
       
  4253 	ole |= 2;
       
  4254     if (state & Qt::AltModifier)
       
  4255 	ole |= 4;
       
  4256 
       
  4257     return ole;
       
  4258 }
       
  4259 
       
  4260 /*
       
  4261     \reimp
       
  4262 */
       
  4263 bool QAxServerBase::eventFilter(QObject *o, QEvent *e)
       
  4264 {
       
  4265     if (!theObject)
       
  4266 	return QObject::eventFilter(o, e);
       
  4267 
       
  4268     if ((e->type() == QEvent::Show || e->type() == QEvent::Hide) && (o == statusBar || o == menuBar)) {
       
  4269 	if (o == menuBar) {
       
  4270 	    if (e->type() == QEvent::Hide) {
       
  4271 		createMenu(menuBar);
       
  4272 	    } else if (e->type() == QEvent::Show) {
       
  4273 		removeMenu();
       
  4274 	    }
       
  4275 	} else if (statusBar) {
       
  4276 	    statusBar->setSizeGripEnabled(false);
       
  4277 	}
       
  4278 	updateGeometry();
       
  4279 	if (m_spInPlaceSite && qt.widget->sizeHint().isValid()) {
       
  4280             RECT rect = {0, 0, qt.widget->sizeHint().width(), qt.widget->sizeHint().height()};
       
  4281 	    m_spInPlaceSite->OnPosRectChange(&rect);
       
  4282 	}
       
  4283     }
       
  4284     switch (e->type()) {
       
  4285     case QEvent::ChildAdded:
       
  4286 	static_cast<QChildEvent*>(e)->child()->installEventFilter(this);
       
  4287 	break;
       
  4288     case QEvent::ChildRemoved:
       
  4289 	static_cast<QChildEvent*>(e)->child()->removeEventFilter(this);
       
  4290 	break;
       
  4291     case QEvent::KeyPress:
       
  4292 	if (o == qt.object && hasStockEvents) {
       
  4293 	    QKeyEvent *ke = (QKeyEvent*)e;
       
  4294 	    int key = ke->key();
       
  4295 	    int state = ke->modifiers();
       
  4296 	    void *argv[] = {
       
  4297 		0,
       
  4298 		&key,
       
  4299 		&state
       
  4300 	    };
       
  4301 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYDOWN, argv);
       
  4302 	    if (!ke->text().isEmpty())
       
  4303 		qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYPRESS, argv);
       
  4304 	}
       
  4305 	break;
       
  4306     case QEvent::KeyRelease:
       
  4307 	if (o == qt.object && hasStockEvents) {
       
  4308 	    QKeyEvent *ke = (QKeyEvent*)e;
       
  4309 	    int key = ke->key();
       
  4310 	    int state = ke->modifiers();
       
  4311 	    void *argv[] = {
       
  4312 		0,
       
  4313 		&key,
       
  4314 		&state
       
  4315 	    };
       
  4316 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYUP, argv);
       
  4317 	}
       
  4318 	break;
       
  4319     case QEvent::MouseMove:
       
  4320 	if (o == qt.object && hasStockEvents) {
       
  4321 	    QMouseEvent *me = (QMouseEvent*)e;
       
  4322             int button = me->buttons() & Qt::MouseButtonMask;
       
  4323 	    int state = mapModifiers(me->modifiers());
       
  4324 	    int x = me->x();
       
  4325 	    int y = me->y();
       
  4326 	    void *argv[] = {
       
  4327 		0,
       
  4328 		&button,
       
  4329 		&state,
       
  4330 		&x,
       
  4331 		&y
       
  4332 	    };
       
  4333 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEMOVE, argv);
       
  4334 	}
       
  4335 	break;
       
  4336     case QEvent::MouseButtonRelease:
       
  4337 	if (o == qt.object && hasStockEvents) {
       
  4338 	    QMouseEvent *me = (QMouseEvent*)e;
       
  4339 	    int button = me->button();
       
  4340 	    int state = mapModifiers(me->modifiers());
       
  4341 	    int x = me->x();
       
  4342 	    int y = me->y();
       
  4343 	    void *argv[] = {
       
  4344 		0,
       
  4345 		&button,
       
  4346 		&state,
       
  4347 		&x,
       
  4348 		&y
       
  4349 	    };
       
  4350 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEUP, argv);
       
  4351 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_CLICK, 0);
       
  4352 	}
       
  4353 	break;
       
  4354     case QEvent::MouseButtonDblClick:
       
  4355 	if (o == qt.object && hasStockEvents) {
       
  4356 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_DBLCLICK, 0);
       
  4357 	}
       
  4358 	break;
       
  4359     case QEvent::MouseButtonPress:
       
  4360         if (m_spInPlaceSite && !isUIActive) {
       
  4361             internalActivate();
       
  4362         }
       
  4363 	if (o == qt.widget && hasStockEvents) {
       
  4364 	    QMouseEvent *me = (QMouseEvent*)e;
       
  4365 	    int button = me->button();
       
  4366 	    int state = mapModifiers(me->modifiers());
       
  4367 	    int x = me->x();
       
  4368 	    int y = me->y();
       
  4369 	    void *argv[] = {
       
  4370 		0,
       
  4371 		&button,
       
  4372 		&state,
       
  4373 		&x,
       
  4374 		&y
       
  4375 	    };
       
  4376 	    qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEDOWN, argv);
       
  4377 	}
       
  4378 	break;
       
  4379     case QEvent::Show:
       
  4380 	if (m_hWnd && o == qt.widget)
       
  4381 	    ShowWindow(m_hWnd, SW_SHOW);
       
  4382 	updateMask();
       
  4383 	break;
       
  4384     case QEvent::Hide:
       
  4385 	if (m_hWnd && o == qt.widget)
       
  4386 	    ShowWindow(m_hWnd, SW_HIDE);
       
  4387 	break;
       
  4388 
       
  4389     case QEvent::EnabledChange:
       
  4390         if (m_hWnd && o == qt.widget)
       
  4391             EnableWindow(m_hWnd, qt.widget->isEnabled());
       
  4392         // Fall Through
       
  4393     case QEvent::FontChange:
       
  4394     case QEvent::ActivationChange:
       
  4395     case QEvent::StyleChange:
       
  4396     case QEvent::IconTextChange:
       
  4397     case QEvent::ModifiedChange:
       
  4398     case QEvent::Resize:
       
  4399 	updateMask();
       
  4400 	break;
       
  4401     case QEvent::WindowBlocked: {
       
  4402         if (!m_spInPlaceFrame)
       
  4403             break;
       
  4404         m_spInPlaceFrame->EnableModeless(FALSE);
       
  4405         MSG msg;
       
  4406         // Visual Basic 6.0 posts the message WM_USER+3078 from the EnableModeless().
       
  4407         // While handling this message, VB will disable all current top-levels. After 
       
  4408         // this we have to re-enable the Qt modal widget to receive input events. 
       
  4409         if (PeekMessage(&msg, 0, WM_USER+3078, WM_USER+3078, PM_REMOVE)) {
       
  4410             TranslateMessage(&msg);
       
  4411             DispatchMessage(&msg);
       
  4412             QWidget *modalWidget = QApplication::activeModalWidget();
       
  4413             if (modalWidget && modalWidget->isVisible() && modalWidget->isEnabled() 
       
  4414                 && !IsWindowEnabled(modalWidget->effectiveWinId()))
       
  4415                 EnableWindow(modalWidget->effectiveWinId(), TRUE);
       
  4416         }
       
  4417         break;
       
  4418         }
       
  4419     case QEvent::WindowUnblocked:
       
  4420         if (!m_spInPlaceFrame)
       
  4421             break;
       
  4422         m_spInPlaceFrame->EnableModeless(TRUE);
       
  4423         break;
       
  4424     default:
       
  4425 	break;
       
  4426     }
       
  4427     return QObject::eventFilter(o, e);
       
  4428 }
       
  4429 
       
  4430 QT_END_NAMESPACE
       
  4431 #endif // QT_NO_WIN_ACTIVEQT