/* ddeproxy.h Used by ddeproxy.cpp ddeDO.cpp ddeOO.cpp Author: Jason Fuller jasonful 24-July-1992 */ #ifndef fDdeProxy_h #define fDdeProxy_h // // One of the oleint.h routines redefines GlobalAlloc and friends // to perform some memory tracking functions. // // This doesn't work in these files, since the tracking functions // add tail checking, and size to the data structures. GlobalSize // is a common function to use to determine how much data to // serialize, plus it turns out that the other side of a DDE // connection will often be the caller to free the memory. // // Therefore, OLE_DDE_NO_GLOBAL_TRACKING is used to disable this in the // global header file ih\memapi.hxx. Check to insure this // flag is set on the compile line // #if !defined(OLE_DDE_NO_GLOBAL_TRACKING) error OLE_DDE_OLE_DDE_NO_GLOBAL_TRACKING must be defined to build this directory #endif #include #include #include #include #include #include #include // For fDdeCodeInOle2Dll flag #include #include #include #ifdef OLE_DEBUG_EXT #include #endif OLE_DEBUG_EXT #include "ddechc.hxx" #define LPCALLINFO LPVOID #include "ddeerr.h" #include "cnct_tbl.h" #define MAX_STR 256 // number of .01 mm per inch #define HIMETRIC_PER_INCH 2540 //#define fDebugOutput // callback notifications #define ON_CHANGE 0 #define ON_SAVE 1 #define ON_CLOSE 2 #define ON_RENAME 3 // AwaitAck values #define AA_NONE 0 #define AA_REQUEST 1 #define AA_ADVISE 2 #define AA_POKE 3 #define AA_EXECUTE 4 #define AA_UNADVISE 5 #define AA_INITIATE 6 #define AA_TERMINATE 7 // A DDE_REQUEST to see if a format is available, not to keep the data. #define AA_REQUESTAVAILABLE 8 // Bits for Positive WM_DDE_ACK //#define POSITIVE_ACK 0x8000 //#define NEGATIVE_ACK 0x0000 typedef DWORD CHK; const DWORD chkDdeObj = 0xab01; // magic cookie typedef struct tagDDE_CHANNEL : public CPrivAlloc { ULONG AddReference() { return ++m_cRefs; } ULONG ReleaseReference() { if (--m_cRefs == 0) { delete this; return(0); } return(m_cRefs); } ULONG m_cRefs; HWND hwndCli; HWND hwndSvr; BOOL bTerminating; int iExtraTerms; WORD wTimer; DWORD dwStartTickCount; WORD msgFirst; WORD msgLast; HWND msghwnd; // BOOL fRejected; // because fBusy flag set in DDE_ACK WORD wMsg; LONG lParam; int iAwaitAck; HRESULT hres; HANDLE hopt; // Memory blocks I may have to free for DDE_ADVISE HANDLE hDdePoke; // for DDE_POKE HANDLE hCommands; // for DDE_EXECUTE WORD wChannelDeleted; PCALLDATA pCD; PCALLCONTROL pCallCont; CDdeChannelControl *pChanCont; } DDE_CHANNEL; #define Channel_InModalloop 1 #define Channel_DeleteNow 2 typedef DDE_CHANNEL * LPDDE_CHANNEL; extern BOOL bWndClassesRegistered; #define hinstSO g_hmodOLE2 extern HMODULE g_hmodOLE2; extern INTERNAL_(BOOL) wRegisterClasses (void); #ifndef _MAC extern CLIPFORMAT g_cfNative; extern CLIPFORMAT g_cfBinary; #endif #ifdef _CHICAGO_ //Note:POSTPPC // // DelayDelete is used to delay deleting the CDdeObject // Guard will set it to DelayIt // UnGuard will reset it to NoDelay or delete the object // if state is ReadyToDelete // typedef enum { NoDelay = 0, // normal state DelayIt = 1, // object is protected and deleting will be delayed ReadyToDelete = 2 // object was is DelayIt state and can be deleted } DelayDelete; #endif // _CHICAGO_ /* * Definition of CDdeObject * */ class CMsgFilterInfo; class CDdeObject; class CDdeObject : public CPrivAlloc { public: static INTERNAL_(LPUNKNOWN) Create (IUnknown * pUnkOuter, REFCLSID clsidClass, ULONG ulObjType = OT_EMBEDDED, ATOM aTopic = NULL, LPOLESTR szItem = NULL, CDdeObject * * ppdde = NULL, BOOL fAllowNullClsid = FALSE); INTERNAL_(void) OnInitAck (LPDDE_CHANNEL pChannel, HWND hwndSvr); INTERNAL_(BOOL) OnAck (LPDDE_CHANNEL pChannel, LONG lParam); INTERNAL_(void) OnTimer (LPDDE_CHANNEL pChannel); INTERNAL OnData (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem); INTERNAL OnDataAvailable (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem); INTERNAL OnTerminate (LPDDE_CHANNEL pChannel, HWND hwndPost); INTERNAL_(LPDDE_CHANNEL) GetSysChannel(void) { return m_pSysChannel; } INTERNAL_(LPDDE_CHANNEL) GetDocChannel(void) { return m_pDocChannel; } INTERNAL_(BOOL) AllocDdeChannel(LPDDE_CHANNEL * lpChannel, LPSTR lpszWndClass); INTERNAL_(BOOL) InitSysConv (void); INTERNAL_(void) SetTopic (ATOM aTopic); INTERNAL SendOnDataChange (int iAdvOpt); INTERNAL OleCallBack (int iAdvOpt,LPDDE_CHANNEL pChannel); #ifdef _CHICAGO_ //Note:POSTPPC INTERNAL_(void) Guard() { intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete is set to 'DelayIt'\n", this)); _DelayDelete = DelayIt; } INTERNAL_(BOOL) UnGuard() { if (_DelayDelete == ReadyToDelete) { intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete it set 'ReadyToDelete'\n", this)); delete this; intrDebugOut((DEB_IWARN ,"CDdeObject: %x was deleted\n", this)); return TRUE; } else { intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete set to 'NoDelay'\n", this)); _DelayDelete = NoDelay; } return FALSE; } #endif // _CHICAGO_ BOOL m_fDoingSendOnDataChange; ULONG m_cRefCount; private: CDdeObject (IUnknown * pUnkOuter); ~CDdeObject (void); INTERNAL TermConv (LPDDE_CHANNEL pChannel, BOOL fWait=TRUE); INTERNAL_(void) DeleteChannel (LPDDE_CHANNEL pChannel); INTERNAL_(BOOL) LaunchApp (void); INTERNAL MaybeUnlaunchApp (void); INTERNAL UnlaunchApp (void); INTERNAL Execute (LPDDE_CHANNEL pChannel, HANDLE hdata, BOOL fStdCloseDoc=FALSE, BOOL fWait=TRUE, BOOL fDetectTerminate = TRUE); INTERNAL Advise(void); INTERNAL AdviseOn (CLIPFORMAT cfFormat, int iAdvOn); INTERNAL UnAdviseOn (CLIPFORMAT cfFormat, int iAdvOn); INTERNAL Poke (ATOM aItem, HANDLE hDdePoke); INTERNAL PostSysCommand (LPDDE_CHANNEL pChannel, LPCSTR szCmd, BOOL bStdNew=FALSE, BOOL fWait=TRUE); #ifdef _CHICAGO_ //POSTPPC INTERNAL_(BOOL) CanMakeOutCall(LPDDE_CHANNEL pChannel); #endif INTERNAL WaitForReply (LPDDE_CHANNEL pChannel, int iAwaitAck, BOOL fStdCloseDoc = FALSE, BOOL fDetectTerminate = TRUE); INTERNAL KeepData (LPDDE_CHANNEL pChannel, HANDLE hDdeData); INTERNAL ChangeTopic (LPSTR lpszTopic); INTERNAL_(void) ChangeItem (LPSTR lpszItem); INTERNAL IsFormatAvailable (LPFORMATETC); INTERNAL_(BOOL) CanCallBack(LPINT); INTERNAL RequestData (CLIPFORMAT); INTERNAL SetTargetDevice (const DVTARGETDEVICE *); INTERNAL DocumentLevelConnect (LPBINDCTX pbc); INTERNAL SendOnClose (void); INTERNAL UpdateAdviseCounts (CLIPFORMAT cf, int iAdvOn, signed int cDelta); INTERNAL DeclareVisibility (BOOL fVisible, BOOL fCallOnShowIfNec=TRUE); INTERNAL Save (LPSTORAGE); INTERNAL Update (BOOL fRequirePresentation); implementations: STDUNKDECL(CDdeObject,DdeObject) STDDEBDECL(CDdeObject,DdeObject) implement COleObjectImpl : IOleObject { public: COleObjectImpl (CDdeObject * pDdeObject) { m_pDdeObject = pDdeObject; } // *** IUnknown methods *** STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj); STDMETHOD_(ULONG,AddRef) (); STDMETHOD_(ULONG,Release) (); // *** IOleObject methods *** STDMETHOD(SetClientSite) ( LPOLECLIENTSITE pClientSite); STDMETHOD(GetClientSite) ( LPOLECLIENTSITE * ppClientSite); STDMETHOD(SetHostNames) ( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj); STDMETHOD(Close) ( DWORD reserved); STDMETHOD(SetMoniker) ( DWORD dwWhichMoniker, LPMONIKER pmk); STDMETHOD(GetMoniker) ( DWORD dwAssign, DWORD dwWhichMoniker,LPMONIKER * ppmk); STDMETHOD(InitFromData) ( LPDATAOBJECT pDataObject,BOOL fCreation,DWORD dwReserved); STDMETHOD(GetClipboardData) ( DWORD dwReserved,LPDATAOBJECT * ppDataObject); STDMETHOD(DoVerb) ( LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, const RECT * lprcPosRect); STDMETHOD(EnumVerbs) ( IEnumOLEVERB * * ppenumOleVerb); STDMETHOD(Update) (); STDMETHOD(IsUpToDate) (); STDMETHOD(GetUserClassID) ( CLSID * pClsid); STDMETHOD(GetUserType) ( DWORD dwFormOfType, LPOLESTR * pszUserType); STDMETHOD(SetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel); STDMETHOD(GetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel); STDMETHOD(Advise)( IAdviseSink * pAdvSink, DWORD * pdwConnection) ; STDMETHOD(Unadvise) ( DWORD dwConnection); STDMETHOD(EnumAdvise) ( LPENUMSTATDATA * ppenumAdvise); STDMETHOD(GetMiscStatus) ( DWORD dwAspect, DWORD * pdwStatus); STDMETHOD(SetColorScheme) ( LPLOGPALETTE lpLogpal); private: CDdeObject * m_pDdeObject; }; implement CDataObjectImpl : IDataObject { public: CDataObjectImpl (CDdeObject * pDdeObject) { m_pDdeObject = pDdeObject; } // *** IUnknown methods *** STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj); STDMETHOD_(ULONG,AddRef) () ; STDMETHOD_(ULONG,Release) (); STDMETHOD(GetData) ( LPFORMATETC pformatetcIn,LPSTGMEDIUM pmedium ); STDMETHOD(GetDataHere) ( LPFORMATETC pformatetc,LPSTGMEDIUM pmedium ); STDMETHOD(QueryGetData) ( LPFORMATETC pformatetc ); STDMETHOD(GetCanonicalFormatEtc) ( LPFORMATETC pformatetc,LPFORMATETC pformatetcOut); STDMETHOD(SetData) ( LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease); STDMETHOD(EnumFormatEtc) ( DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc); STDMETHOD(DAdvise) ( FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection) ; STDMETHOD(DUnadvise) ( DWORD dwConnection) ; STDMETHOD(EnumDAdvise) ( LPENUMSTATDATA * ppenumAdvise) ; private: CDdeObject * m_pDdeObject; }; implement CPersistStgImpl : IPersistStorage { public: CPersistStgImpl (CDdeObject * pDdeObject) { m_pDdeObject = pDdeObject; } STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj); STDMETHOD_(ULONG,AddRef) (); STDMETHOD_(ULONG,Release) (); STDMETHOD(GetClassID) ( LPCLSID pClassID); STDMETHOD(IsDirty) (void); STDMETHOD(InitNew) ( LPSTORAGE pstg); STDMETHOD(Load) ( LPSTORAGE pstg); STDMETHOD(Save) ( LPSTORAGE pstgSave, BOOL fSameAsLoad); STDMETHOD(SaveCompleted) ( LPSTORAGE pstgNew); STDMETHOD(HandsOffStorage) (void); private: CDdeObject * m_pDdeObject; }; implement CProxyManagerImpl : IProxyManager { public: CProxyManagerImpl (CDdeObject * pDdeObject) { m_pDdeObject = pDdeObject; } STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj); STDMETHOD_(ULONG,AddRef) (); STDMETHOD_(ULONG,Release) (); STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv); STDMETHOD_(BOOL, IsConnected)(void); STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases); STDMETHOD_(void, Disconnect)(); STDMETHOD(Connect)(OID oid, REFCLSID rclsid); STDMETHOD(EstablishIID)(REFIID iid, LPVOID FAR* ppv); STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv, REFCLSID rclsidHandler, IID iidSrv, void **ppv, IID iidClnt, void *pClientSiteInterface); private: CDdeObject * m_pDdeObject; }; implement COleItemContainerImpl : IOleItemContainer { public: COleItemContainerImpl (CDdeObject * pDdeObject) { m_pDdeObject = pDdeObject; } STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj); STDMETHOD_(ULONG,AddRef) (); STDMETHOD_(ULONG,Release) (); // IParseDisplayName method STDMETHOD(ParseDisplayName) ( LPBC pbc, LPOLESTR lpszDisplayName, ULONG * pchEaten, LPMONIKER * ppmkOut) ; // IOleContainer methods STDMETHOD(EnumObjects) ( DWORD grfFlags,LPENUMUNKNOWN * ppenumUnk); STDMETHOD(LockContainer) (BOOL fLock); // IOleItemContainer methods STDMETHOD(GetObject) ( LPOLESTR lpszItem, DWORD dwSpeedNeeded, LPBINDCTX pbc, REFIID riid, LPVOID * ppvObject) ; STDMETHOD(GetObjectStorage) ( LPOLESTR lpszItem, LPBINDCTX pbc, REFIID riid, LPVOID * ppvStorage) ; STDMETHOD(IsRunning) ( LPOLESTR lpszItem) ; private: CDdeObject * m_pDdeObject; }; DECLARE_NC(CDdeObject, COleObjectImpl) DECLARE_NC(CDdeObject, CDataObjectImpl) DECLARE_NC(CDdeObject, CPersistStgImpl) DECLARE_NC(CDdeObject, CProxyManagerImpl) DECLARE_NC(CDdeObject, COleItemContainerImpl) COleObjectImpl m_Ole; CDataObjectImpl m_Data; CPersistStgImpl m_PersistStg; CProxyManagerImpl m_ProxyMgr; COleItemContainerImpl m_OleItemContainer; shared_state: ULONG m_refs; #ifdef _CHICAGO_ //Note:POSTPPC DelayDelete _DelayDelete; #endif // _CHICAGO_ ULONG m_ulObjType; CLSID m_clsid; ATOM m_aClass; ATOM m_aExeName; ATOM m_aTopic; ATOM m_aItem; BOOL m_bRunning; IUnknown * m_pUnkOuter; IOleClientSite * m_pOleClientSite; LPSTORAGE m_pstg; BOOL m_bInitNew; BOOL m_bOldSvr; HANDLE m_hNative; HANDLE m_hPict; HANDLE m_hExtra; CLIPFORMAT m_cfPict; CLIPFORMAT m_cfExtra; BOOL m_fDidSendOnClose; BOOL m_fNoStdCloseDoc; BOOL m_fDidStdCloseDoc; BOOL m_fDidStdOpenDoc; BOOL m_fDidGetObject; BOOL m_fDidLaunchApp; BOOL m_fUpdateOnSave; BOOL m_fGotCloseData; #ifdef OLE1INTEROP BOOL m_fOle1interop; #endif // Invisible update stuff ULONG m_cLocks; // PM::LockConnection lock count (init 1) BOOL m_fVisible; // is server visible (as best we know)? BOOL m_fWasEverVisible; BOOL m_fCalledOnShow; // Did we call IOleClientSite::OnShow CHK m_chk; DVTARGETDEVICE * m_ptd; // m_iAdvClose and m_iAdvSave are counts (1 or 2) of the number of formats // that have advise connections of a given type (Save or Close) int m_iAdvClose; int m_iAdvSave; int m_iAdvChange; BOOL m_fDidAdvNative; // Extent info #ifdef OLD long m_cxContentExtent; long m_cyContentExtent; #endif // terminate info - only used to detect a premature WM_DDE_TERMINATE WORD m_wTerminate; IDataAdviseHolder * m_pDataAdvHolder; IOleAdviseHolder * m_pOleAdvHolder; CDdeConnectionTable m_ConnectionTable; // DDE window related stuff LPDDE_CHANNEL m_pSysChannel; LPDDE_CHANNEL m_pDocChannel; friend INTERNAL DdeBindToObject (LPCOLESTR szFile, REFCLSID clsid, BOOL fPackageLink, REFIID iid, LPLPVOID ppv); friend INTERNAL DdeIsRunning (CLSID clsid, LPCOLESTR szFile, LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER pmkNewlyRunning); #ifdef OLE_DEBUG_EXT #endif OLE_DEBUG_EXT }; // // Note: WM_DDE_TERMINATE // A state machine is used to delay the executing of a premature WM_DDE_TERMINTE // message, which is send by some apps instead of WM_DDE_ACK (or alike). // The code is in WaitForReply() and in OnTerminate() typedef enum { Terminate_None = 0, // default state - terminate code is executed Terminate_Detect = 1, // window proc will NOT execute terminate code Terminate_Received = 2 // wait loop does not need to run, execute terminate code now } TERMINATE_DOCUMENT; INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel, WORD wMsg, LONG lParam, BOOL fFreeOnError); INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid); INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid); INTERNAL_(BOOL) wIsWindowValid (HWND hwnd); INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat, BOOL fFreeNonGdiHandle=TRUE); INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh); INTERNAL wScanItemOptions (ATOM aItem, int * lpoptions); INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel); INTERNAL_(HANDLE) wStdCloseDocumentHandle (void); INTERNAL_(ATOM) wExtendAtom (ATOM aIitem, int iAdvOn); INTERNAL_(int) wAtomLen (ATOM atom); INTERNAL_(int) wAtomLenA (ATOM atom); INTERNAL_(LPDDE_CHANNEL) wAllocDdeChannel(void); INTERNAL_(HANDLE) wHandleFromDdeData(HANDLE hDdeData); INTERNAL_(BOOL) wIsOldServer (ATOM aClass); INTERNAL_(LPSTR) wAllocDdePokeBlock (DWORD dwSize, CLIPFORMAT cfFormat,LPHANDLE phDdePoke); INTERNAL_(void) wFreePokeData (LPDDE_CHANNEL pChannel, BOOL fMSDrawBug); INTERNAL_(HANDLE) wPreparePokeBlock (HANDLE hData, CLIPFORMAT cfFormat, ATOM aClass, BOOL bOldSvr); INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb); INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf); INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc); INTERNAL wGetRequestResponse (LPDDE_CHANNEL pChannel, CLIPFORMAT cf, ATOM aItem); INTERNAL wGetItemFromClipboard (ATOM * paItem); INTERNAL GetDefaultIcon (REFCLSID clsidIn, LPCOLESTR szFile, HANDLE * phmfp); INTERNAL_(BOOL) wTerminateIsComing (LPDDE_CHANNEL); INTERNAL wTimedGetMessage (LPMSG pmsg, HWND hwnd, WORD wFirst, WORD wLast); INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz); INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz); INTERNAL wVerifyFormatEtc (LPFORMATETC pformatetc); INTERNAL wNormalize (LPFORMATETC pfetc, LPFORMATETC pfetcOut); INTERNAL wTransferHandle (LPHANDLE phDst, LPHANDLE phSrc, CLIPFORMAT cf); INTERNAL wClassesMatch (REFCLSID clsidIn, LPOLESTR szFile); #if DBG == 1 INTERNAL_(BOOL) wIsValidHandle (HANDLE h, CLIPFORMAT cf); INTERNAL_(BOOL) wIsValidAtom (ATOM a); #endif const char achStdCloseDocument[]="[StdCloseDocument]"; const char achStdOpenDocument[]="StdOpenDocument"; const char achStdExit[]="StdExit"; const char achStdNewDocument[]="StdNewDocument"; const char achStdEditDocument[]="StdEditDocument"; #endif // ddeproxy.h