/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #ifndef _DDEMLIMP_HXX #define _DDEMLIMP_HXX #include #include #include "ddemlos2.h" #define DDEMLSERVICETABLE_INISIZE 8 // Bezeichner der systemglobalen DDEML-Tabelle #define DDEMLDATA "\\SHAREMEM\\OV_DDEML.DAT" // vorlaeufig konstante Tabellengroessen #define CONVTABLECOUNT 2048 /* max count conversations */ #define TRANSTABLECOUNT 2048 /* transactions */ #define DDEMLAPPCOUNT 16 /* max count simultaniously running */ /* ddeml (StarDivision) applications */ #define ST_TERMACKREC 0x8000 /* wird im Conversationhandle gesetzt, */ /* wenn die Partner-App DDE_TERMINATE */ /* bestaetigt hat */ #define XST_TIMEOUT 17 /* Trans. hat Timeout ueberschritten */ #define XST_WAITING_ACK 18 /* Trans. wartet auf Acknowledge */ #define XST_WAITING_ADVDATA 19 /* Trans. wartet auf Advise-Daten */ #define XST_WAITING_REQDATA 20 /* Trans. wartet auf angeforderte Daten */ /* User-Flags DDESTRUCT */ #define IMP_HDATAAPPOWNED 0x8000 #define CONVLISTNAME "DdeConvListId" #define XTYPF_MASK (XTYPF_NOBLOCK | XTYPF_NODATA | XTYPF_ACKREQ) // // DDEML-Messages; werden nur an registrierte DDEML-Apps gesendet // // Msg: WM_DDEML_REGISTER // Empfaenger: wird allen DDEML-Applikationen nach Registrierung // eines neuen Services gesendet // Params: nPar1: hszBaseServName // nPar2: hszInstServName #define WM_DDEML_REGISTER WM_USER+1 // Msg: WM_DDEML_UNREGISTER // Empfaenger: wird allen DDEML-Applikationen nach Deregistrierung // eines Services gesendet // Params: nPar1: hszBaseServName // nPar2: hszInstServName #define WM_DDEML_UNREGISTER WM_USER+2 // // // struct ImpHCONV { HCONV hConvPartner; HSZ hszPartner; // Name of partner application HSZ hszServiceReq; // Service name HSZ hszTopic; // Topic name USHORT nStatus; // ST_* of conversation HCONVLIST hConvList; // ConvListId , wenn in ConvList CONVCONTEXT aConvContext; // Conversation context // private HWND hWndThis; // 0 == Handle not used HWND hWndPartner; PID pidOwner; // PID des DdeManagers, der // den Conv-Handle erzeugt hat. USHORT nPrevHCONV; // 0 == no previous hConv or not in list USHORT nNextHCONV; // 0 == no next hconv or not in list }; struct Transaction { HSZ hszItem; // Item name USHORT nFormat; // Data format USHORT nType; // Transaction type (XTYP_*) // XTYP_ADVREQ [|XTYPF_NODATA] == Advise-Loop // [|XTYPF_ACKREQ] // XTYP_EXECUTE == laufendes Execute // XTYP_REQUEST // XTYP_POKE // XTYP_ADVSTOP // XTYP_ADVSTART USHORT nConvst; // Conversation state (XST_*) // 0 == idle // XST_REQSENT (fuer XTYP_ADVREQ) // XST_TIMEOUT (fuer alle Typen!) // XST_WAITING (alle ausser XTYP_ADVREQ) USHORT nLastError; // last err in transaction ULONG nUser; // Userhandle // private HCONV hConvOwner; // 0 == Transaction not used }; struct ImpWndProcParams { HWND hWndReceiver; MPARAM nPar1; MPARAM nPar2; }; struct ImpService { HSZ hBaseServName; // Basis-Name des Service HSZ hInstServName; // Basis-Name + DDEML-Server-HWND der App }; class ImpDdeMgr; // Daten eines Conversation-Windows struct ImpConvWndData { ImpDdeMgr* pThis; USHORT nRefCount; // Zahl Conversations auf diesem Window }; // systemglobale Daten der Library (liegen in named shared memory) struct ImpDdeMgrData { ULONG nTotalSize; ULONG nOffsAppTable; ULONG nOffsConvTable; ULONG nOffsTransTable; USHORT nMaxAppCount; USHORT nMaxConvCount; USHORT nMaxTransCount; USHORT nLastErr; USHORT nReserved; USHORT nCurTransCount; USHORT nCurConvCount; HWND aAppTable[ 1 ]; // fuer Broadcast-Messages ImpHCONV aConvTable[ 1 ]; Transaction aTransTable[ 1 ]; }; class ImpDdeMgr { friend MRESULT EXPENTRY ConvWndProc(HWND hWnd,ULONG nMsg,MPARAM nPar1,MPARAM nPar2); friend MRESULT EXPENTRY ServerWndProc(HWND hWnd,ULONG nMsg,MPARAM nPar1,MPARAM nPar2); friend void ImpWriteDdeStatus(char*,char*); friend void ImpAddHSZ( HSZ, String& ); static PSZ AllocAtomName( ATOM hString, ULONG& rBufLen ); static PDDESTRUCT MakeDDEObject( HWND hwnd, ATOM hItemName, USHORT fsStatus, USHORT usFormat, PVOID pabData, ULONG usDataLen ); static APIRET AllocNamedSharedMem( PPVOID ppBaseAddress, PSZ pName, ULONG nElementSize, ULONG nElementCount ); HWND hWndServer; PID pidThis; PFNCALLBACK pCallback; ULONG nTransactFilter; CONVCONTEXT aDefaultContext; ImpDdeMgrData* pData; ImpService* pServices; USHORT nServiceCount; ImpHCONV* pConvTable; // liegt in pData (nicht deleten!) Transaction* pTransTable; // liegt in pData (nicht deleten!) HWND* pAppTable; // liegt in pData (nicht deleten!) static ImpHCONV* GetConvTable( ImpDdeMgrData* ); static Transaction* GetTransTable( ImpDdeMgrData* ); static HWND* GetAppTable( ImpDdeMgrData* ); static HWND NextFrameWin( HENUM hEnum ); void CreateServerWnd(); void DestroyServerWnd(); HWND CreateConversationWnd(); // Fktn. duerfen nur fuer HCONVs aufgerufen werden, die // in der eigenen Applikation erzeugt wurden static void DestroyConversationWnd( HWND hWndConv ); static USHORT GetConversationWndRefCount( HWND hWndConv ); static USHORT IncConversationWndRefCount( HWND hWndConv ); MRESULT SrvWndProc(HWND hWnd,ULONG nMsg,MPARAM nPar1,MPARAM nPar2); MRESULT ConvWndProc(HWND hWnd,ULONG nMsg,MPARAM nPar1,MPARAM nPar2); void RegisterDDEMLApp(); void UnregisterDDEMLApp(); void CleanUp(); ImpDdeMgrData* InitAll(); static BOOL MyWinDdePostMsg( HWND, HWND, USHORT, PDDESTRUCT, ULONG ); void MyInitiateDde( HWND hWndServer, HWND hWndClient, HSZ hszService, HSZ hszTopic, CONVCONTEXT* pCC ); DDEINIT* CreateDDEInitData( HWND hWndDest, HSZ hszService, HSZ hszTopic, CONVCONTEXT* pCC ); // wenn pDDEData==0, muss pCC gesetzt sein HCONV ConnectWithClient( HWND hWndClient, HSZ hszPartner, HSZ hszService, HSZ hszTopic, BOOL bSameInst, DDEINIT* pDDEData, CONVCONTEXT* pCC = 0); HCONV CheckIncoming( ImpWndProcParams*, ULONG nTransMask, HSZ& rhszItem ); // fuer Serverbetrieb. Ruft Callback-Fkt fuer alle offenen Advises // auf, deren Owner der uebergebene HCONV ist. // bFreeTransactions==TRUE: loescht die Transaktionen // gibt Anzahl der getrennten Transaktionen zurueck USHORT SendUnadvises( HCONV hConv, USHORT nFormat, // 0==alle BOOL bFreeTransactions ); BOOL WaitTransState( Transaction* pTrans, ULONG nTransId, USHORT nNewState, ULONG nTimeout ); // DDEML ruft Callback mit XTYP_CONNECT-Transaction nur auf, // wenn die App den angeforderten Service registriert hat // Standardeinstellung: TRUE BOOL bServFilterOn; // Fehlercode muss noch systemglobal werden (Atom o. ae.) static USHORT nLastErrInstance; // wenn 0, dann gilt globaler Fehlercode static ImpDdeMgrData* AccessMgrData(); static HCONV CreateConvHandle( ImpDdeMgrData* pBase, PID pidOwner, HWND hWndThis, HWND hWndPartner, HSZ hszPartner, HSZ hszServiceReq, HSZ hszTopic, HCONV hPrevHCONV = 0 ); static HCONV IsConvHandleAvailable( ImpDdeMgrData* pBase ); static HCONV GetConvHandle( ImpDdeMgrData* pBase, HWND hWndThis, HWND hWndPartner ); static void FreeConvHandle( ImpDdeMgrData*, HCONV, BOOL bDestroyHWndThis = TRUE ); static ULONG CreateTransaction( ImpDdeMgrData* pBase, HCONV hOwner, HSZ hszItem, USHORT nFormat, USHORT nTransactionType ); static ULONG GetTransaction( ImpDdeMgrData* pBase, HCONV hOwner, HSZ hszItem, USHORT nFormat ); static void FreeTransaction( ImpDdeMgrData*, ULONG nTransId ); BOOL DisconnectAll(); // Transaktionen muessen _vor_ den Konversationen geloescht werden! static void FreeTransactions( ImpDdeMgrData*, HWND hWndThis, HWND hWndPartner ); static void FreeTransactions( ImpDdeMgrData*, HCONV hConvOwner ); static void FreeConversations( ImpDdeMgrData*,HWND hWndThis, HWND hWndPartner ); ImpService* GetService( HSZ hszService ); ImpService* PutService( HSZ hszService ); void BroadcastService( ImpService*, BOOL bRegistered ); // rh: Startposition(!) & gefundener Handle static ImpHCONV* GetFirstServer( ImpDdeMgrData*, HCONVLIST, HCONV& rh); static ImpHCONV* GetLastServer( ImpDdeMgrData*, HCONVLIST, HCONV& ); static BOOL CheckConvListId( HCONVLIST hConvListId ); BOOL IsSameInstance( HWND hWnd ); HSZ GetAppName( HWND hWnd ); // Transactions MRESULT DdeAck( ImpWndProcParams* pParams ); MRESULT DdeAdvise( ImpWndProcParams* pParams ); MRESULT DdeData( ImpWndProcParams* pParams ); MRESULT DdeExecute( ImpWndProcParams* pParams ); MRESULT DdeInitiate( ImpWndProcParams* pParams ); MRESULT DdeInitiateAck( ImpWndProcParams* pParams ); MRESULT DdePoke( ImpWndProcParams* pParams ); MRESULT DdeRequest( ImpWndProcParams* pParams ); MRESULT DdeTerminate( ImpWndProcParams* pParams ); MRESULT DdeUnadvise( ImpWndProcParams* pParams ); MRESULT DdeRegister( ImpWndProcParams* pParams ); MRESULT DdeUnregister( ImpWndProcParams* pParams ); MRESULT DdeTimeout( ImpWndProcParams* pParams ); HDDEDATA Callback( USHORT nTransactionType, USHORT nClipboardFormat, HCONV hConversationHandle, HSZ hsz1, HSZ hsz2, HDDEDATA hData, ULONG nData1, ULONG nData2 ); HCONV DdeConnectImp( HSZ hszService,HSZ hszTopic,CONVCONTEXT* pCC); // connection data HCONV hCurConv; // wird im DdeInitiateAck gesetzt HCONVLIST hCurListId; // fuer DdeConnectList USHORT nPrevConv; // .... "" .... BOOL bListConnect; // synchr. transaction data BOOL bInSyncTrans; ULONG nSyncTransId; HDDEDATA hSyncResponseData; ULONG nSyncResponseMsg; // WM_DDE_ACK, WM_DDE_DATA, WM_TIMER // TRUE==nach Ende der synchronen Transaktion eine evtl. benutzte // asynchrone Transaktion beenden (typisch synchroner Request auf // Advise-Loop) BOOL bSyncAbandonTrans; public: ImpDdeMgr(); ~ImpDdeMgr(); USHORT DdeInitialize( PFNCALLBACK pCallbackProc, ULONG nTransactionFilter ); USHORT DdeGetLastError(); HCONV DdeConnect( HSZ hszService, HSZ hszTopic, CONVCONTEXT* ); HCONVLIST DdeConnectList( HSZ hszService, HSZ hszTopic, HCONVLIST hConvList, CONVCONTEXT* ); static BOOL DdeDisconnect( HCONV hConv ); static BOOL DdeDisconnectList( HCONVLIST hConvList ); static HCONV DdeReconnect(HCONV hConv); static HCONV DdeQueryNextServer(HCONVLIST hConvList, HCONV hConvPrev); static USHORT DdeQueryConvInfo(HCONV hConv, ULONG idTrans,CONVINFO* pCI); static BOOL DdeSetUserHandle(HCONV hConv, ULONG id, ULONG hUser); BOOL DdeAbandonTransaction( HCONV hConv, ULONG idTransaction); BOOL DdePostAdvise( HSZ hszTopic, HSZ hszItem); BOOL DdeEnableCallback( HCONV hConv, USHORT wCmd); HDDEDATA DdeNameService( HSZ hszService, USHORT afCmd); static HDDEDATA DdeClientTransaction(void* pData, ULONG cbData, HCONV hConv, HSZ hszItem, USHORT wFmt, USHORT wType, ULONG dwTimeout, ULONG* pdwResult); // Data handles HDDEDATA DdeCreateDataHandle( void* pSrc, ULONG cb, ULONG cbOff, HSZ hszItem, USHORT wFmt, USHORT afCmd); static BYTE* DdeAccessData(HDDEDATA hData, ULONG* pcbDataSize); static BOOL DdeUnaccessData(HDDEDATA hData); static BOOL DdeFreeDataHandle(HDDEDATA hData); static HDDEDATA DdeAddData(HDDEDATA hData,void* pSrc,ULONG cb,ULONG cbOff); static ULONG DdeGetData(HDDEDATA hData,void* pDst,ULONG cbMax,ULONG cbOff); // String handles static HSZ DdeCreateStringHandle( PSZ pStr, int iCodePage); static ULONG DdeQueryString(HSZ hsz,PSZ pStr,ULONG cchMax,int iCPage); static BOOL DdeFreeStringHandle( HSZ hsz ); static BOOL DdeKeepStringHandle( HSZ hsz ); static int DdeCmpStringHandles(HSZ hsz1, HSZ hsz2); // mit dieser Funktion kann geprueft werden, ob eine // Applikation schon eine DDEML-Instanz angelegt hat. // Die aktuelle Impl. unterstuetzt nur eine DDEML-Instanz // pro Applikation (wg. synchroner Transaktionen) static ImpDdeMgr* GetImpDdeMgrInstance( HWND hWnd ); // gibt TRUE zurueck, wenn mind. ein lebender HCONV // von diesem DdeMgr erzeugt wurde BOOL OwnsConversationHandles(); }; // static inline ImpHCONV* ImpDdeMgr::GetConvTable( ImpDdeMgrData* pData ) { ImpHCONV* pRet; if( pData ) pRet = (ImpHCONV*)((ULONG)(pData) + pData->nOffsConvTable); else pRet = 0; return pRet; } // static inline Transaction* ImpDdeMgr::GetTransTable( ImpDdeMgrData* pData ) { Transaction* pRet; if( pData ) pRet = (Transaction*)((ULONG)(pData) + pData->nOffsTransTable); else pRet = 0; return pRet; } // static inline HWND* ImpDdeMgr::GetAppTable( ImpDdeMgrData* pData ) { HWND* pRet; if( pData ) pRet = (HWND*)((ULONG)(pData) + pData->nOffsAppTable); else pRet = 0; return pRet; } #endif