1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ddeml1.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
37 - DdeInitiate: Eigener Thread?
38 - Timeout bei Disconnects (IBM:nicht auf Ack warten!)
39 - Konzept Errorhandling (globale/lokale Fehler)
40 - Bedeutung/Anwendung Conversation-Contexte
41 - Bei Zugriffen auf ConversationHandles WindowHandles checken
42 - Namen der Partner-App ermitteln
45 #define INCL_DOSPROCESS
47 #include "ddemlimp.hxx"
52 #include "ddemldeb.hxx"
55 #if defined (OS2) && defined (__BORLANDC__)
60 inline BOOL
ImpDdeMgr::MyWinDdePostMsg( HWND hWndTo
, HWND hWndFrom
,
61 USHORT nMsg
, PDDESTRUCT pData
, ULONG nFlags
)
63 BOOL bSuccess
= WinDdePostMsg( hWndTo
,hWndFrom
,nMsg
,pData
,nFlags
);
66 WRITELOG("WinDdePostMsg:Failed!")
67 if ( !(nFlags
& DDEPM_NOFREE
) )
69 MyDosFreeMem( pData
,"MyWinDdePostMsg" );
76 // *********************************************************************
78 // *********************************************************************
80 USHORT
ImpDdeMgr::nLastErrInstance
= 0;
83 // Conversation-WndProc
84 // Steuert Transaktionen eines Conversationhandles
86 MRESULT EXPENTRY
ConvWndProc(HWND hWnd
,ULONG nMsg
,MPARAM nPar1
,MPARAM nPar2
)
88 #if defined(DBG_UTIL) && defined(OV_DEBUG)
89 if( nMsg
>= WM_DDE_FIRST
&& nMsg
<= WM_DDE_LAST
)
91 ////WRITELOG("::ConvWndProc:DDE-Msg received")
94 ImpConvWndData
* pObj
= (ImpConvWndData
*)WinQueryWindowULong( hWnd
, 0 );
95 return pObj
->pThis
->ConvWndProc( hWnd
, nMsg
, nPar1
, nPar2
);
100 // DDE-Server-Window der App
102 MRESULT EXPENTRY
ServerWndProc(HWND hWnd
,ULONG nMsg
,MPARAM nPar1
,MPARAM nPar2
)
104 #if defined(DBG_UTIL) && defined(OV_DEBUG)
105 if( nMsg
>= WM_DDE_FIRST
&& nMsg
<= WM_DDE_LAST
)
107 ////WRITELOG("::ServerWndProc:DDE-Msg received")
110 ImpDdeMgr
* pObj
= (ImpDdeMgr
*)WinQueryWindowULong( hWnd
, 0 );
111 return pObj
->SrvWndProc( hWnd
, nMsg
, nPar1
, nPar2
);
115 inline HDDEDATA
ImpDdeMgr::Callback( USHORT nTransactionType
,
116 USHORT nClipboardFormat
, HCONV hConversationHandle
, HSZ hsz1
,
117 HSZ hsz2
, HDDEDATA hData
, ULONG nData1
, ULONG nData2
)
119 HDDEDATA hRet
= (HDDEDATA
)0;
121 hRet
= (*pCallback
)(nTransactionType
, nClipboardFormat
,
122 hConversationHandle
, hsz1
, hsz2
, hData
, nData1
, nData2
);
128 ImpDdeMgr::ImpDdeMgr()
130 nLastErrInstance
= DMLERR_NO_ERROR
;
138 bServFilterOn
= TRUE
;
139 bInSyncTrans
= FALSE
;
144 nLastErrInstance
= DMLERR_MEMORY_ERROR
;
149 ImpDdeMgr::~ImpDdeMgr()
153 // Named Shared Mem vom BS loeschen lassen, da nicht bekannt ist,
154 // wieviele DDEML-Instanzen die App erzeugt hat, und OS/2
155 // keinen App-Referenzzaehler fuer shared mem fuehrt.
157 // DosFreeMem( pData );
161 BOOL
ImpDdeMgr::IsSameInstance( HWND hWnd
)
164 WinQueryWindowProcess( hWnd
, &pid
, &tid
);
165 return (BOOL
)(pid
== pidThis
);
168 HSZ
ImpDdeMgr::GetAppName( HWND hWnd
)
174 ImpDdeMgr
* ImpDdeMgr::GetImpDdeMgrInstance( HWND hWnd
)
176 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
180 ImpDdeMgr
* pResult
= 0;
182 WinQueryWindowProcess( hWnd
, &pidApp
, &tid
);
183 HWND
* pApp
= ImpDdeMgr::GetAppTable( pData
);
185 while( nCurApp
< pData
->nMaxAppCount
)
187 HWND hCurWin
= *pApp
;
191 WinQueryWindowProcess( hCurWin
, &pidCurApp
, &tid
);
192 if( pidCurApp
== pidApp
)
194 pResult
= (ImpDdeMgr
*)WinQueryWindowULong( hCurWin
, 0 );
208 void ImpDdeMgr::CleanUp()
211 ImpService
* pPtr
= pServices
;
214 for( USHORT nIdx
= 0; nIdx
< nServiceCount
; nIdx
++, pPtr
++ )
216 HSZ hStr
= pPtr
->hBaseServName
;
218 DdeFreeStringHandle( hStr
);
219 hStr
= pPtr
->hInstServName
;
221 DdeFreeStringHandle( hStr
);
227 bServFilterOn
= TRUE
; // default setting DDEML
228 UnregisterDDEMLApp();
231 void ImpDdeMgr::RegisterDDEMLApp()
233 HWND
* pPtr
= pAppTable
;
236 while( nPos
< pData
->nMaxAppCount
)
239 if (hCur
== (HWND
)0 )
241 // in Tabelle stellen
250 void ImpDdeMgr::UnregisterDDEMLApp()
252 HWND
* pPtr
= pAppTable
;
254 while( nPos
< pData
->nMaxAppCount
)
256 if (*pPtr
== hWndServer
)
267 ImpDdeMgrData
* ImpDdeMgr::AccessMgrData()
269 ImpDdeMgrData
* pData
= 0;
270 APIRET nRet
= DosGetNamedSharedMem((PPVOID
)&pData
,DDEMLDATA
,PAG_READ
|PAG_WRITE
);
271 DBG_ASSERT(!nRet
,"DDE:AccessMgrData failed");
275 USHORT
ImpDdeMgr::DdeGetLastError()
279 nErr
= DMLERR_DLL_NOT_INITIALIZED
;
280 else if ( nLastErrInstance
)
281 nErr
= nLastErrInstance
;
283 nErr
= pData
->nLastErr
;
285 nLastErrInstance
= 0;
292 USHORT
ImpDdeMgr::DdeInitialize( PFNCALLBACK pCallbackProc
, ULONG nTransactionFilter
)
294 if ( !nLastErrInstance
)
296 if ( !pCallbackProc
)
298 nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
299 return nLastErrInstance
;
301 pCallback
= pCallbackProc
;
302 nTransactFilter
= nTransactionFilter
;
303 nTransactFilter
|= CBF_FAIL_SELFCONNECTIONS
;
305 return nLastErrInstance
;
310 HWND
ImpDdeMgr::NextFrameWin( HENUM hEnum
)
314 HWND hWnd
= WinGetNextWindow( hEnum
);
317 WinQueryClassName( hWnd
, sizeof(aBuf
)-1, (PCH
)aBuf
);
319 if( !strcmp( aBuf
, "#1" ) ) // #define WC_FRAME ((PSZ)0xffff0001L)
321 hWnd
= WinGetNextWindow( hEnum
);
327 HCONV
ImpDdeMgr::DdeConnectImp( HSZ hszService
,HSZ hszTopic
,CONVCONTEXT
* pCC
)
331 pCC
= &aDefaultContext
;
334 PSZ pService
= AllocAtomName( (ATOM
)hszService
, nBufLen
);
335 PSZ pTopic
= AllocAtomName( (ATOM
)hszTopic
, nBufLen
);
336 #if 0 && defined(OV_DEBUG)
337 String
aStr("DdeConnectImp Service:");
341 WRITELOG((char*)(const char*)aStr
)
344 #if defined(OV_DEBUG)
345 if( !strcmp(pService
,"oliver voeltz") )
347 WRITESTATUS("Table of connections");
348 MyDosFreeMem( pTopic
,"DdeConnectImp" );
349 MyDosFreeMem( pService
,"DdeConnectImp" );
355 // original pm-fkt benutzen
356 HWND hWndCurClient
= CreateConversationWnd();
357 WinDdeInitiate( hWndCurClient
, pService
, pTopic
, pCC
);
358 if( GetConversationWndRefCount(hWndCurClient
) == 0)
359 DestroyConversationWnd( hWndCurClient
);
361 // eigener Verbindungsaufbau
362 HENUM hEnum
= WinBeginEnumWindows( HWND_DESKTOP
);
363 HWND hWndCurSrv
= NextFrameWin( hEnum
);
364 HWND hWndCurClient
= CreateConversationWnd();
365 while( hWndCurSrv
&& !hCurConv
)
367 if( hWndCurSrv
!= hWndServer
||
368 ((nTransactFilter
& CBF_FAIL_SELFCONNECTIONS
)==0 ))
370 // pro DDE-Server ein Conversation-Window erzeugen
371 if( GetConversationWndRefCount(hWndCurClient
) >= 2)
373 DestroyConversationWnd( hWndCurClient
);
374 hWndCurClient
= CreateConversationWnd();
376 MyInitiateDde(hWndCurSrv
,hWndCurClient
,hszService
,hszTopic
,pCC
);
377 if( !bListConnect
&& hCurConv
)
380 hWndCurSrv
= NextFrameWin( hEnum
);
383 if( GetConversationWndRefCount(hWndCurClient
) == 0)
384 DestroyConversationWnd( hWndCurClient
);
385 WinEndEnumWindows( hEnum
);
389 nLastErrInstance
= DMLERR_NO_CONV_ESTABLISHED
;
391 #if 0 && defined(OV_DEBUG)
392 String
aCStr( "DdeConnectImp:End ");
393 if( nLastErrInstance
!= DMLERR_NO_CONV_ESTABLISHED
)
394 aCStr
+= "(Success)";
397 WRITELOG((char*)aCStr
.GetStr())
400 MyDosFreeMem( pTopic
,"DdeConnectImp" );
401 MyDosFreeMem( pService
,"DdeConnectImp" );
405 HCONV
ImpDdeMgr::DdeConnect( HSZ hszService
, HSZ hszTopic
, CONVCONTEXT
* pCC
)
407 ////WRITELOG("DdeConnect:Start")
408 bListConnect
= FALSE
;
409 HCONV hResult
= DdeConnectImp( hszService
, hszTopic
, pCC
);
410 ////WRITELOG("DdeConnect:End")
411 ////WRITESTATUS("DdeConnect:End")
416 HCONVLIST
ImpDdeMgr::DdeConnectList( HSZ hszService
, HSZ hszTopic
,
417 HCONVLIST hConvList
, CONVCONTEXT
* pCC
)
420 ////WRITESTATUS("Before DdeConnectList")
423 HCONV hLastConvInList
;
425 hCurListId
= hConvList
;
426 ImpHCONV
* pConv
= pConvTable
;
427 pConv
+= (USHORT
)hConvList
;
428 if( (USHORT
)hConvList
>= pData
->nMaxConvCount
||pConv
->hWndThis
==0 )
430 nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
433 GetLastServer(pData
, hConvList
, hLastConvInList
);
434 nPrevConv
= (USHORT
)hLastConvInList
;
437 hCurListId
= (HCONVLIST
)WinCreateWindow( HWND_OBJECT
, WC_FRAME
,
438 CONVLISTNAME
, 0,0,0,0,0, HWND_DESKTOP
, HWND_BOTTOM
, 0,0,0);
441 DdeConnectImp( hszService
, hszTopic
, pCC
);
442 #if 0 && defined(OV_DEBUG)
443 WRITELOG("DdeConnectList:ConnectionList:")
447 hDebug
= DdeQueryNextServer( hCurListId
, hDebug
);
448 String
aStr( (ULONG
)hDebug
);
449 WRITELOG((char*)(const char*)aStr
)
452 ////WRITESTATUS("After DdeConnectList")
453 return (HCONVLIST
)hCurListId
;
456 DDEINIT
* ImpDdeMgr::CreateDDEInitData( HWND hWndDestination
, HSZ hszService
,
457 HSZ hszTopic
, CONVCONTEXT
* pCC
)
459 ULONG nLen1
= 0, nLen2
= 0;
460 HATOMTBL hAtomTable
= WinQuerySystemAtomTable();
463 nLen1
= WinQueryAtomLength( hAtomTable
, hszService
);
465 nLen2
= WinQueryAtomLength( hAtomTable
, hszTopic
);
470 ULONG nLen
= sizeof(DDEINIT
) + nLen1
+ nLen2
+ sizeof(CONVCONTEXT
);
471 if( !(MyDosAllocSharedMem((PPVOID
)&pBuf
, NULL
, nLen
,
472 PAG_COMMIT
| PAG_READ
| PAG_WRITE
| OBJ_GIVEABLE
| OBJ_ANY
,
473 "CreateDDEInitData")))
475 memset( pBuf
, 0, nLen
);
479 WinQueryWindowProcess( hWndDestination, &pid, &tid );
480 APIRET nRet = DosGiveSharedMem( pBuf, pid, PAG_READ | PAG_WRITE );
484 pBuf
->offConvContext
= sizeof( DDEINIT
);
485 char* pBase
= (char*)pBuf
;
486 pBase
+= sizeof(DDEINIT
);
488 memcpy( pBase
, pCC
, sizeof(CONVCONTEXT
) );
489 pBase
+= sizeof(CONVCONTEXT
);
490 pBuf
->pszAppName
= pBase
;
492 WinQueryAtomName( hAtomTable
, hszService
, pBase
, nLen1
);
494 pBuf
->pszTopic
= pBase
;
496 WinQueryAtomName( hAtomTable
, hszTopic
, pBase
, nLen2
);
503 void ImpDdeMgr::MyInitiateDde( HWND hWndSrv
, HWND hWndClient
,
504 HSZ hszService
, HSZ hszTopic
, CONVCONTEXT
* pCC
)
506 DDEINIT
* pBuf
= CreateDDEInitData( hWndSrv
, hszService
, hszTopic
, pCC
);
510 WinQueryWindowProcess( hWndSrv
, &pid
, &tid
);
511 APIRET nRet
= DosGiveSharedMem( pBuf
, pid
, PAG_READ
| PAG_WRITE
);
512 WinSendMsg( hWndSrv
,WM_DDE_INITIATE
,(MPARAM
)hWndClient
,(MPARAM
)pBuf
);
513 MyDosFreeMem( pBuf
,"MyInitiateDde" );
518 ImpHCONV
* ImpDdeMgr::GetFirstServer(ImpDdeMgrData
* pData
, HCONVLIST hConvList
,
521 ImpHCONV
* pPtr
= GetConvTable( pData
);
531 pPtr
+= (USHORT
)rhConv
;
533 pPtr
++; hConv
++; // auf den naechsten
535 while( hConv
< pData
->nMaxConvCount
)
537 if( pPtr
->hConvList
== hConvList
)
550 ImpHCONV
* ImpDdeMgr::GetLastServer(ImpDdeMgrData
* pData
, HCONVLIST hConvList
,
553 ImpHCONV
* pPtr
= GetConvTable( pData
);
554 pPtr
+= pData
->nMaxConvCount
;
556 HCONV hConv
= pData
->nMaxConvCount
;
560 if( pPtr
->hConvList
== hConvList
)
573 BOOL
ImpDdeMgr::CheckConvListId( HCONVLIST hConvListId
)
575 HAB hAB
= WinQueryAnchorBlock( (HWND
)hConvListId
);
577 return WinIsWindow( hAB
, (HWND
)hConvListId
);
580 HAB hAB = WinQueryAnchorBlock( (HWND)hConvListId );
584 WinQueryWindowText( (HWND)hConvListId, sizeof(aBuf), aBuf );
585 if( strcmp(aBuf, CONVLISTNAME ) == 0 )
593 HCONV
ImpDdeMgr::DdeQueryNextServer(HCONVLIST hConvList
, HCONV hConvPrev
)
595 if( !CheckConvListId( hConvList
) )
597 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
598 GetFirstServer( pData
, hConvList
, hConvPrev
);
604 // Idee: DisconnectAll uebergibt das ServerWindow. Zu jedem HCONV
605 // wird das Creator-Server-Wnd gespeichert. Disconnect braucht
606 // dann nur noch die Window-Handles zu vergleichen
607 BOOL
ImpDdeMgr::DdeDisconnect( HCONV hConv
)
609 WRITELOG("DdeDisconnect:Start")
610 ////WRITESTATUS("DdeDisconnect:Start")
612 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
615 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
618 ImpHCONV
* pConv
= GetConvTable(pData
) + (USHORT
)hConv
;
620 if( (USHORT
)hConv
>= pData
->nMaxConvCount
|| pConv
->hWndThis
==0 )
622 nLastErrInstance
= DMLERR_NO_CONV_ESTABLISHED
;
627 HWND hWndDummy
= WinCreateWindow( HWND_OBJECT
, WC_FRAME
,
628 "Bla", 0, 0,0,0,0, HWND_DESKTOP
, HWND_BOTTOM
, 0, 0, 0 );
629 WinQueryWindowProcess( hWndDummy
, &pidApp
, &tid
);
630 WinDestroyWindow( hWndDummy
);
631 PID pidThis
; PID pidPartner
;
633 HWND hWndThis
= pConv
->hWndThis
;
634 HWND hWndPartner
= pConv
->hWndPartner
;
636 WinQueryWindowProcess( hWndThis
, &pidThis
, &tid
);
637 WinQueryWindowProcess( hWndPartner
, &pidPartner
, &tid
);
638 if( pidApp
!= pidThis
&& pidApp
!= pidPartner
)
639 return TRUE
; // gehoert nicht der App -> ueberspringen
641 HCONV hConvPartner
= pConv
->hConvPartner
;
643 // die App benachrichtigen, dass alle offenen Advise-Loops
644 // beendet werden, egal ob sie vom Server oder Client
645 // initiiert wurden. Die Dinger aber nicht loeschen, da sie evtl.
646 // noch vom Partner gebraucht werden.
647 ImpConvWndData
* pObj
=
648 (ImpConvWndData
*)WinQueryWindowULong( pConv
->hWndThis
, 0 );
649 ImpDdeMgr
* pThis
= pObj
->pThis
;
650 pThis
->SendUnadvises( hConv
, 0, FALSE
); // alle Formate & NICHT loeschen
651 pThis
->SendUnadvises( hConvPartner
, 0, FALSE
); // alle Formate & NICHT loeschen
653 pConv
->nStatus
|= ST_TERMINATED
;
655 HAB hAB
= WinQueryAnchorBlock( pConv
->hWndThis
);
656 // um die MessageQueue inne Gaenge zu halten
657 ULONG nTimerId
= WinStartTimer( hAB
, 0, 0, 50 );
660 Die Partner-App muss ein DDE_TERMINATE posten, auf das
661 wir warten muessen, um alle Messages zu bearbeiten, die
662 _vor_ dem DdeDisconnect von der Partner-App gepostet
665 WRITELOG("DdeDisconnect:Waiting for acknowledge...")
666 WinDdePostMsg( hWndPartner
, hWndThis
, WM_DDE_TERMINATE
,
667 (PDDESTRUCT
)0,DDEPM_RETRY
);
670 BOOL bContinue
= TRUE
;
673 if( WinGetMsg( hAB
, &aQueueMsg
, 0, 0, 0 ))
675 WinDispatchMsg( hAB
, &aQueueMsg
);
676 if( (!WinIsWindow( hAB
, hWndPartner
)) ||
677 (pConv
->nStatus
& ST_TERMACKREC
) )
680 if( pConv
->nStatus
& ST_TERMACKREC
)
682 WRITELOG("DdeDisconnect: TermAck received")
686 WRITELOG("DdeDisconnect: Partner died")
694 WinStopTimer( hAB
, 0, nTimerId
);
696 // WRITELOG("DdeDisconnect:Freeing data")
697 // Transaktionstabelle aufraeumen
698 FreeTransactions( pData
, hConv
);
700 FreeTransactions( pData
, hConvPartner
);
702 FreeConvHandle( pData
, hConv
);
704 WRITELOG("DdeDisconnect:End")
705 //WRITESTATUS("DdeDisconnect:End")
710 BOOL
ImpDdeMgr::DdeDisconnectList( HCONVLIST hConvList
)
712 if( !CheckConvListId( hConvList
) )
714 ImpDdeMgr::nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
718 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
721 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
725 GetFirstServer( pData
, hConvList
, hConv
);
728 DdeDisconnect( hConv
);
729 GetFirstServer( pData
, hConvList
, hConv
);
731 WinDestroyWindow( (HWND
)hConvList
);
738 HCONV
ImpDdeMgr::DdeReconnect(HCONV hConv
)
740 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
743 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
750 USHORT
ImpDdeMgr::DdeQueryConvInfo(HCONV hConv
, ULONG nTransId
, CONVINFO
* pCI
)
752 if( !pCI
|| pCI
->nSize
== 0)
754 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
757 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
761 if( nTransId
!= QID_SYNC
)
763 pTrans
= ImpDdeMgr::GetTransTable( pData
);
765 if( nTransId
>= pData
->nMaxTransCount
|| pTrans
->hConvOwner
== 0 )
767 ImpDdeMgr::nLastErrInstance
= DMLERR_UNFOUND_QUEUE_ID
;
774 ImpHCONV
* pConv
= ImpDdeMgr::GetConvTable( pData
);
775 pConv
+= (ULONG
)hConv
;
776 if( hConv
>= pData
->nMaxConvCount
|| pConv
->hWndThis
== 0 )
778 ImpDdeMgr::nLastErrInstance
= DMLERR_NO_CONV_ESTABLISHED
;
782 USHORT nSize
= pCI
->nSize
;
783 if( nSize
> sizeof(CONVINFO
) )
784 nSize
= sizeof(CONVINFO
);
786 memset( &aTempInfo
, 0, sizeof(CONVINFO
) );
787 aTempInfo
.nSize
= pCI
->nSize
;
788 aTempInfo
.hConvPartner
= pConv
->hConvPartner
;
789 aTempInfo
.hszPartner
= pConv
->hszPartner
;
790 aTempInfo
.hszServiceReq
= pConv
->hszServiceReq
;
791 aTempInfo
.hszTopic
= pConv
->hszTopic
;
792 aTempInfo
.nStatus
= pConv
->nStatus
;
793 aTempInfo
.hConvList
= pConv
->hConvList
;
794 aTempInfo
.aConvCtxt
= pConv
->aConvContext
;
797 aTempInfo
.nUser
= pTrans
->nUser
;
798 aTempInfo
.hszItem
= pTrans
->hszItem
;
799 aTempInfo
.nFormat
= pTrans
->nFormat
;
800 aTempInfo
.nType
= pTrans
->nType
;
801 aTempInfo
.nConvst
= pTrans
->nConvst
;
802 aTempInfo
.nLastError
= pTrans
->nLastError
;
804 memcpy( pCI
, &aTempInfo
, nSize
);
810 BOOL
ImpDdeMgr::DdeSetUserHandle(HCONV hConv
, ULONG nTransId
, ULONG hUser
)
812 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
815 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
818 Transaction
* pTrans
= GetTransTable( pData
);
820 if( !nTransId
|| !hConv
|| nTransId
>= pData
->nMaxTransCount
||
821 pTrans
->hConvOwner
!= hConv
)
823 ImpDdeMgr::nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
826 if( !pTrans
->hConvOwner
)
828 ImpDdeMgr::nLastErrInstance
= DMLERR_UNFOUND_QUEUE_ID
;
831 pTrans
->nUser
= hUser
;
835 BOOL
ImpDdeMgr::DdeAbandonTransaction( HCONV hConv
, ULONG nTransId
)
837 ////WRITELOG("DdeAbandonTransaction:Start")
840 nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
843 ImpHCONV
* pConv
= pConvTable
;
844 pConv
+= (USHORT
)hConv
;
845 if( nTransId
< 1 || nTransId
>= pData
->nMaxTransCount
||
846 hConv
< 1 || hConv
>= pData
->nMaxConvCount
|| !pConv
->hWndThis
)
848 nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
853 DBG_ASSERT(0,"DdeAbandonTransaction:NULL-hConv not supported");
854 nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
857 Transaction
* pTrans
= pTransTable
;
858 pTrans
+= (USHORT
)nTransId
;
859 if( pTrans
->hConvOwner
!= hConv
)
861 nLastErrInstance
= DMLERR_UNFOUND_QUEUE_ID
;
865 if( bInSyncTrans
&& nTransId
== nSyncTransId
)
867 bSyncAbandonTrans
= TRUE
;
870 USHORT nTempType
= pTrans
->nType
;
871 nTempType
&= (~XTYPF_MASK
);
872 if( nTempType
== (XTYP_ADVREQ
& ~(XTYPF_NOBLOCK
)))
874 ////WRITELOG("DdeAbandTrans:Advise Loop")
876 // ----------------------------------------------------------------------
877 // Der von der Deutschen Bank eingesetzte DDE-Server
878 // "Invision V2.71 Build 36 Mar 12 1999 V4.8.2" hat einen Bug, der
879 // dazu fuehrt, dass auf per WM_DDE_TERMINATE geschlossene Verbindungen
880 // nicht mit einem WM_DDE_TERMINATE geantwortet wird, wenn der
881 // entsprechende Link vorher per WM_DDE_UNADVISE beendet wurde. Dieser
882 // Bug tritt ab zwei parallel laufenden Links auf. Auf Wunsch der DB
883 // wurde das folgende Workaround eingebaut.
884 // ----------------------------------------------------------------------
885 #define DEUTSCHE_BANK
886 #ifndef DEUTSCHE_BANK
888 // Acknowledge ist beim Unadvise nicht ueblich
889 //#define SO_DDE_ABANDON_TRANSACTION_WAIT_ACK
890 #ifdef SO_DDE_ABANDON_TRANSACTION_WAIT_ACK
891 DDESTRUCT
* pOutDDEData
= MakeDDEObject( pConv
->hWndPartner
,
892 pTrans
->hszItem
, DDE_FACKREQ
, 0 /*pTrans->nFormat*/, 0, 0);
894 DDESTRUCT
* pOutDDEData
= MakeDDEObject( pConv
->hWndPartner
,
895 pTrans
->hszItem
, 0, 0 /*pTrans->nFormat*/, 0, 0);
897 WRITELOG("DdeAbandTrans:Waiting for acknowledge...")
898 pTrans
->nConvst
= XST_UNADVSENT
;
899 if ( !MyWinDdePostMsg( pConv
->hWndPartner
, pConv
->hWndThis
,
900 WM_DDE_UNADVISE
, pOutDDEData
, DDEPM_RETRY
) )
902 WRITELOG("DdeAbandTrans:PostMsg Failed")
905 #ifdef SO_DDE_ABANDON_TRANSACTION_WAIT_ACK
906 WaitTransState( pTrans
, nTransId
, XST_UNADVACKRCVD
, 0 );
908 pTrans
->nConvst
= XST_UNADVACKRCVD
;
911 #endif // DEUTSCHE_BANK
913 WRITELOG("DdeAbandTrans:Ack received->Freeing transaction")
914 FreeTransaction( pData
, nTransId
);
916 WRITELOG("DdeAbandonTransaction:End")
920 // wird von einem Server aufgerufen, wenn sich die Daten des
921 // Topic/Item-Paars geaendert haben. Diese Funktion fordert
922 // dann den Server auf, die Daten zu rendern (bei Hotlinks) und
923 // benachrichtigt die Clients
924 BOOL
ImpDdeMgr::DdePostAdvise( HSZ hszTopic
, HSZ hszItem
)
926 ////WRITELOG("DdePostAdvise:Start")
927 ////WRITESTATUS("DdePostAdvise:Start")
929 #if 0 && defined( OV_DEBUG )
930 String
aDebStr("DdePostAdvise:Item ");
931 aDebStr
+= (ULONG
)hszItem
;
932 WRITELOG((char*)(const char*)aDebStr
)
935 Transaction
* pTrans
= pTransTable
;
937 USHORT nCurTrans
= 1;
938 USHORT nUsedTransactions
= pData
->nCurTransCount
;
939 while( nUsedTransactions
&& nCurTrans
< pData
->nMaxTransCount
)
941 HCONV hOwner
= pTrans
->hConvOwner
;
945 USHORT nTempType
= pTrans
->nType
;
946 nTempType
&= (~XTYPF_MASK
);
947 if( nTempType
== (XTYP_ADVREQ
& (~XTYPF_NOBLOCK
) ) )
949 ImpHCONV
* pConv
= pConvTable
;
950 pConv
+= (USHORT
)hOwner
;
951 if(hszItem
== pTrans
->hszItem
&& pConv
->hszTopic
== hszTopic
)
953 if( pConv
->hConvPartner
)
955 // Transaktionen werden immer vom Client erzeugt
956 // -> auf Server-HCONV umschalten
957 hOwner
= pConv
->hConvPartner
;
959 pConv
+= (USHORT
)hOwner
;
961 HWND hWndClient
= pConv
->hWndPartner
;
962 HWND hWndServer
= pConv
->hWndThis
;
963 #if 0 && defined( OV_DEBUG )
964 String
aDebStr("DdePostAdvise: Server:");
965 aDebStr
+= (ULONG
)hWndServer
;
966 aDebStr
+= " Client:";
967 aDebStr
+= (ULONG
)hWndClient
;
968 WRITELOG((char*)(const char*)aDebStr
)
970 DDESTRUCT
* pOutDDEData
;
971 if ( pTrans
->nType
& XTYPF_NODATA
)
974 ////WRITELOG("DdePostAdvise:Warm link found")
975 pOutDDEData
= MakeDDEObject( hWndClient
, hszItem
,
976 DDE_FNODATA
, pTrans
->nFormat
, 0, 0 );
981 ////WRITELOG("DdePostAdvise:Hot link found")
982 pOutDDEData
= Callback( XTYP_ADVREQ
,
983 pTrans
->nFormat
, hOwner
, hszTopic
,
984 hszItem
, (HDDEDATA
)0, 1, 0 );
988 // todo: FACK_REQ in Out-Data setzen, wenn pTrans->nType & XTYPF_ACKREQ
989 ////WRITELOG("DdePostAdvise:Sending data/notification")
990 BOOL bSuccess
= MyWinDdePostMsg( hWndClient
,
991 hWndServer
,WM_DDE_DATA
, pOutDDEData
, DDEPM_RETRY
);
994 // auf Acknowledge des Partners warten ?
995 if( pTrans
->nType
& XTYPF_ACKREQ
)
997 pTrans
->nConvst
= XST_ADVDATASENT
;
998 // Impl. ist falsch! => korrekt: XST_ADVDATAACKRCVD
999 WaitTransState(pTrans
, nCurTrans
,
1000 XST_UNADVACKRCVD
, 0);
1005 ////WRITELOG("DdePostAdvise:PostMsg failed")
1006 nLastErrInstance
= DMLERR_POSTMSG_FAILED
;
1011 ////WRITELOG("DdePostAdvise:No data to send")
1019 ////WRITELOG("DdePostAdvise:End")
1023 BOOL
ImpDdeMgr::DdeEnableCallback( HCONV hConv
, USHORT wCmd
)
1028 // Rueckgabe: 0==Service nicht registriert; sonst Pointer auf Service-Eintrag
1029 ImpService
* ImpDdeMgr::GetService( HSZ hszService
)
1031 ImpService
* pPtr
= pServices
;
1032 if( !pPtr
|| !hszService
)
1034 for( ULONG nIdx
= 0; nIdx
< nServiceCount
; nIdx
++, pPtr
++ )
1036 if(( hszService
== pPtr
->hBaseServName
) ||
1037 ( hszService
== pPtr
->hInstServName
) )
1044 // legt Service in Service-Tabelle ab. Tabelle wird ggf. expandiert
1045 ImpService
* ImpDdeMgr::PutService( HSZ hszService
)
1049 DBG_ASSERT(nServiceCount
==0,"DDE:Bad ServiceCount");
1050 pServices
= new ImpService
[ DDEMLSERVICETABLE_INISIZE
];
1051 memset( pServices
, 0, DDEMLSERVICETABLE_INISIZE
* sizeof(ImpService
));
1052 nServiceCount
= DDEMLSERVICETABLE_INISIZE
;
1054 ImpService
* pPtr
= pServices
;
1058 if( pPtr
->hBaseServName
== 0 )
1061 if( nCurPos
< nServiceCount
)
1068 // Tabelle vergroessern
1069 pPtr
= new ImpService
[ nServiceCount
+ DDEMLSERVICETABLE_INISIZE
];
1070 memset( pPtr
, 0, DDEMLSERVICETABLE_INISIZE
* sizeof(ImpService
));
1071 memcpy( pPtr
, pServices
, nServiceCount
* sizeof(ImpService
) );
1073 memset( pServices
, 0, nServiceCount
* sizeof(ImpService
) );
1077 pPtr
+= nServiceCount
; // zeigt auf erste neue Position
1078 nServiceCount
+= DDEMLSERVICETABLE_INISIZE
;
1080 DBG_ASSERT(pPtr
->hBaseServName
==0,"DDE:Service not empty");
1081 DBG_ASSERT(pPtr
->hInstServName
==0,"DDE:Service not empty");
1083 DdeKeepStringHandle( hszService
);
1085 USHORT nStrLen
= (USHORT
)DdeQueryString( hszService
, 0, 0, 0);
1086 char* pBuf
= new char[ nStrLen
+ 1 ];
1087 DdeQueryString(hszService
, pBuf
, nStrLen
, 850 /* CodePage*/ );
1088 pBuf
[ nStrLen
] = 0;
1089 String
aStr( (ULONG
)hWndServer
);
1091 HSZ hszInstServ
= DdeCreateStringHandle( (PSZ
)(const char*)pBuf
, 850 );
1094 pPtr
->hBaseServName
= hszService
;
1095 pPtr
->hInstServName
= hszInstServ
;
1099 void ImpDdeMgr::BroadcastService( ImpService
* pService
, BOOL bRegistered
)
1101 DBG_ASSERT(pService
,"DDE:No Service");
1104 MPARAM aMp1
= (MPARAM
)(pService
->hBaseServName
);
1105 MPARAM aMp2
= (MPARAM
)(pService
->hInstServName
);
1108 nMsg
= WM_DDEML_REGISTER
;
1110 nMsg
= WM_DDEML_UNREGISTER
;
1112 HWND
* pPtr
= pAppTable
;
1113 for( USHORT nPos
= 0; nPos
< pData
->nMaxAppCount
; nPos
++, pPtr
++ )
1115 HWND hWndCurWin
= *pPtr
;
1116 if ( hWndCurWin
&& hWndCurWin
!= hWndServer
)
1117 WinSendMsg( hWndCurWin
, nMsg
, aMp1
, aMp2
);
1121 HDDEDATA
ImpDdeMgr::DdeNameService( HSZ hszService
, USHORT afCmd
)
1123 HDDEDATA hRet
= (HDDEDATA
)1;
1125 if( afCmd
& DNS_FILTERON
)
1126 bServFilterOn
= TRUE
;
1127 else if( afCmd
& DNS_FILTEROFF
)
1128 bServFilterOn
= FALSE
;
1129 ImpService
* pService
= GetService( hszService
);
1130 BOOL bRegister
= (BOOL
)(afCmd
& DNS_REGISTER
);
1135 pService
= PutService( hszService
);
1136 BroadcastService( pService
, TRUE
);
1143 BroadcastService( pService
, FALSE
);
1144 DdeFreeStringHandle( pService
->hBaseServName
);
1145 pService
->hBaseServName
= 0;
1146 DdeFreeStringHandle( pService
->hInstServName
);
1147 pService
->hInstServName
= 0;
1149 hRet
= (HDDEDATA
)0; // Service nicht gefunden
1156 HDDEDATA
ImpDdeMgr::DdeClientTransaction(void* pDdeData
, ULONG cbData
,
1157 HCONV hConv
, HSZ hszItem
, USHORT nFormat
, USHORT nType
,
1158 ULONG nTimeout
, ULONG
* pResult
)
1160 //WRITELOG("DdeClientTransaction:Start")
1162 #if 0 && defined(OV_DEBUG)
1163 if( nType
== XTYP_REQUEST
)
1165 WRITELOG("Start XTYP_REQUEST");
1166 WinMessageBox(HWND_DESKTOP
,HWND_DESKTOP
,
1167 "Start XTYP_REQUEST","DdeClientTransaction",
1168 HWND_DESKTOP
,MB_OK
);
1175 ImpDdeMgrData
* pData
= ImpDdeMgr::AccessMgrData();
1178 ImpDdeMgr::nLastErrInstance
= DMLERR_DLL_NOT_INITIALIZED
;
1182 BOOL bIsDdeHandle
= (BOOL
)(pDdeData
&& cbData
==0xffffffff);
1183 BOOL bAppOwnsHandle
= (BOOL
)( bIsDdeHandle
&&
1184 (((DDESTRUCT
*)pDdeData
)->fsStatus
& IMP_HDATAAPPOWNED
) );
1186 BOOL bNoData
= (BOOL
)(nType
& XTYPF_NODATA
)!=0;
1187 BOOL bAckReq
= (BOOL
)(nType
& XTYPF_ACKREQ
)!=0;
1188 USHORT nTypeFlags
= nType
& XTYPF_MASK
;
1189 nType
&= (~XTYPF_MASK
);
1191 BOOL bSync
= (BOOL
)( nTimeout
!= TIMEOUT_ASYNC
) != 0;
1192 if( nType
== XTYP_ADVSTART
)
1195 // Mapping transaction -> OS/2-Message
1196 USHORT nTimeoutErr
, nMsg
;
1200 nMsg
= WM_DDE_ADVISE
;
1201 nTimeoutErr
= DMLERR_ADVACKTIMEOUT
;
1204 #if 0 && defined(OV_DEBUG)
1206 ImpDdeMgr::DdeQueryString( hszItem
,aBuf
,127,850);
1207 String
aXXStr("Establishing hotlink ");
1209 WRITELOG((char*)aXXStr
.GetStr());
1216 nMsg
= WM_DDE_UNADVISE
;
1217 nTimeoutErr
= DMLERR_UNADVACKTIMEOUT
;
1221 nMsg
= WM_DDE_REQUEST
;
1222 nTimeoutErr
= DMLERR_DATAACKTIMEOUT
;
1227 nTimeoutErr
= DMLERR_POKEACKTIMEOUT
;
1231 nMsg
= WM_DDE_EXECUTE
;
1232 nTimeoutErr
= DMLERR_EXECACKTIMEOUT
;
1238 if(!hConv
|| (USHORT
)hConv
>= pData
->nMaxConvCount
|| !nType
|| !nMsg
||
1239 (nType
!= XTYP_EXECUTE
&& (!hszItem
|| !nFormat
)) )
1241 WRITELOG("DdeClientTransaction:Invalid parameter")
1242 ImpDdeMgr::nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
1243 if( bIsDdeHandle
&& !bAppOwnsHandle
)
1244 DdeFreeDataHandle( (HDDEDATA
)pDdeData
);
1248 // ueber den Conversation handle das ImpDdeMgr-Objekt holen
1249 ImpHCONV
* pConv
= GetConvTable( pData
);
1250 pConv
+= (USHORT
)hConv
;
1251 ImpConvWndData
* pObj
=
1252 (ImpConvWndData
*)WinQueryWindowULong( pConv
->hWndThis
, 0 );
1253 ImpDdeMgr
* pThis
= pObj
->pThis
;
1255 if( bSync
&& pThis
->bInSyncTrans
)
1257 WRITELOG("DdeClientTransaction:Already in sync. transaction")
1258 ImpDdeMgr::nLastErrInstance
= DMLERR_REENTRANCY
;
1259 if( bIsDdeHandle
&& !bAppOwnsHandle
)
1260 DdeFreeDataHandle( (HDDEDATA
)pDdeData
);
1264 Transaction
* pTrans
;
1266 BOOL bReqOnAdvLoop
= FALSE
;
1267 ULONG nTransId
= GetTransaction( pData
, hConv
, hszItem
, nFormat
);
1270 // WRITELOG("DdeClientTransaction:Transaction found")
1271 pTrans
= GetTransTable( pData
);
1272 pTrans
+= (USHORT
)nTransId
;
1273 USHORT nTransType
= pTrans
->nType
;
1274 nTransType
&= (~XTYPF_MASK
);
1275 if( (nType
!= XTYP_REQUEST
&& nTransType
== nType
) ||
1276 // wird Advise-Loop schon zum requesten missbraucht ?
1277 (nType
== XTYP_REQUEST
&&
1278 nTransType
== XTYP_ADVREQ
&&
1279 pTrans
->nConvst
== XST_WAITING_REQDATA
))
1281 // dieser Kanal ist dicht!
1282 WRITELOG("DdeClientTransaction:Transaction already used")
1283 ImpDdeMgr::nLastErrInstance
= DMLERR_REENTRANCY
;
1284 if( bIsDdeHandle
&& !bAppOwnsHandle
)
1285 DdeFreeDataHandle( (HDDEDATA
)pDdeData
);
1288 else if( nTransType
== XTYP_ADVREQ
)
1293 //WRITELOG("DdeClientTransaction:Stopping advise trans")
1294 pTrans
->nType
= XTYP_ADVSTOP
;
1298 //WRITELOG("DdeClientTransaction:Adj. Advise-Params")
1299 pTrans
->nType
= XTYP_ADVREQ
;
1301 pTrans
->nType
|= XTYPF_NODATA
;
1303 pTrans
->nType
|= XTYPF_ACKREQ
;
1305 *pResult
= nTransId
;
1306 return (HDDEDATA
)TRUE
;
1309 // WRITELOG("DdeClientTransaction:Using adv trans for req")
1310 // nConvst wird unten auf XST_WAITING_REQDATA gesetzt
1311 bReqOnAdvLoop
= TRUE
;
1315 WRITELOG("DdeClientTransaction:Invalid parameter")
1316 ImpDdeMgr::nLastErrInstance
= DMLERR_INVALIDPARAMETER
;
1317 if( bIsDdeHandle
&& !bAppOwnsHandle
)
1318 DdeFreeDataHandle( (HDDEDATA
)pDdeData
);
1319 return (HDDEDATA
)FALSE
;
1325 // WRITELOG("DdeClientTransaction:Creating transaction")
1326 nTransId
= CreateTransaction(pData
, hConv
, hszItem
, nFormat
, nType
);
1329 pTrans
= GetTransTable( pData
);
1330 pTrans
+= (USHORT
)nTransId
;
1331 pTrans
->nConvst
= XST_WAITING_ACK
;
1332 if( nType
== XTYP_REQUEST
)
1333 pTrans
->nConvst
= XST_WAITING_REQDATA
;
1335 HWND hWndServer
= pConv
->hWndPartner
;
1336 HWND hWndClient
= pConv
->hWndThis
;
1338 HDDEDATA pOutDDEData
;
1341 if( bAppOwnsHandle
)
1343 // wir muessen leider leider duplizieren, da uns OS/2
1344 // keine Chance laesst, diesen Status im Datenobjekt
1346 ////WRITELOG("DdeClientTransaction:Copying handle")
1348 HDDEDATA pData
= (HDDEDATA
)pDdeData
;
1349 if( !(MyDosAllocSharedMem((PPVOID
)&pNew
, NULL
, pData
->cbData
,
1350 PAG_COMMIT
| PAG_READ
| PAG_WRITE
| OBJ_GIVEABLE
| OBJ_ANY
,
1353 memcpy( pNew
, pData
, pData
->cbData
);
1358 WRITELOG("DdeClientTransaction:No Memory")
1359 ImpDdeMgr::nLastErrInstance
= DMLERR_LOW_MEMORY
;
1364 pOutDDEData
= (HDDEDATA
)pDdeData
;
1367 pOutDDEData
=MakeDDEObject(hWndServer
,hszItem
,0,nFormat
,pDdeData
,cbData
);
1369 pOutDDEData
->fsStatus
|= nTypeFlags
;
1371 HDDEDATA pDDEInData
= 0;
1374 if( nType
!= XTYP_REQUEST
)
1375 pOutDDEData
->fsStatus
|= DDE_FACKREQ
;
1377 // WRITELOG("DdeClientTransaction:Starting sync. trans.")
1378 pThis
->hSyncResponseData
= (HDDEDATA
)0;
1379 pThis
->nSyncResponseMsg
= 0;
1380 pThis
->bInSyncTrans
= TRUE
;
1381 pThis
->nSyncTransId
= nTransId
;
1382 pThis
->bSyncAbandonTrans
= FALSE
;
1384 if ( !MyWinDdePostMsg( hWndServer
, hWndClient
, nMsg
, pOutDDEData
,
1387 WRITELOG("DdeClientTransaction:PostMsg failed")
1388 nLastErrInstance
= DMLERR_POSTMSG_FAILED
;
1389 if( !bReqOnAdvLoop
)
1390 FreeTransaction( pData
, nTransId
);
1393 DBG_ASSERT(pTrans
->nType
==XTYP_ADVREQ
,"DDE:Error!")
1394 pTrans
->nConvst
= 0;
1398 HAB hAB
= WinQueryAnchorBlock( hWndClient
);
1399 ULONG nDummyTimer
= WinStartTimer( hAB
, 0, 0, 50 );
1400 ULONG nTimeoutId
= TID_USERMAX
- nTransId
;
1401 WinStartTimer( hAB
, hWndClient
, nTimeoutId
, nTimeout
);
1406 if( pThis
->nSyncResponseMsg
)
1410 if( WinGetMsg(hAB
,&aQueueMsg
,0,0,0 ))
1412 WinDispatchMsg( hAB
, &aQueueMsg
);
1419 WinStopTimer( hAB
, hWndClient
, nTimeoutId
);
1420 WinStopTimer( hAB
, 0, nDummyTimer
);
1423 // Der Speicherblock pOutDDEData muss vom Server geloescht worden sein!
1424 // Ueberlegen: Nochmal loeschen, falls Server buggy ist, ansonsten
1425 // platzt uns bald der Adressraum!
1427 if( !pThis
->nSyncResponseMsg
)
1429 // unsere App wurde beendet
1430 ////WRITELOG("DdeClientTransaction:App terminated")
1433 pDDEInData
= pThis
->hSyncResponseData
;
1434 nMsg
= pThis
->nSyncResponseMsg
;
1435 pThis
->hSyncResponseData
= 0;
1436 pThis
->nSyncResponseMsg
= 0;
1437 pThis
->bInSyncTrans
= FALSE
;
1438 pThis
->nSyncTransId
= 0;
1439 if( !pDDEInData
&& nMsg
!= WM_TIMER
)
1441 DBG_ASSERT(0,"Dde:No data!");
1442 WRITELOG("DdeClientTransaction: No Data!")
1448 WRITELOG("DdeClientTransaction:Timeout!")
1449 nLastErrInstance
= nTimeoutErr
;
1451 // auf normalen Loop-Betrieb zurueckschalten
1452 pTrans
->nConvst
= XST_WAITING_ADVDATA
;
1457 // WRITELOG("DdeClientTransaction:Ack received")
1458 BOOL bPositive
= (BOOL
)(pDDEInData
->fsStatus
& DDE_FACK
);
1459 MyDosFreeMem( pDDEInData
,"DdeClientTransaction" );
1460 pDDEInData
= (HDDEDATA
)bPositive
;
1461 if( nType
== XTYP_ADVSTART
&& pDDEInData
)
1464 #if 0 && defined(OV_DEBUG)
1466 ImpDdeMgr::DdeQueryString( pTrans
->hszItem
,aBuf
,128,850);
1467 String
aXXStr("Hotlink ");
1472 pTrans
->nType
= XTYP_ADVREQ
;
1473 // Hot/Warmlink, Ack
1474 pTrans
->nType
|= nTypeFlags
;
1475 // XST_WAITING_ACK ==> XST_WAITING_ADVDATA
1476 pTrans
->nConvst
= XST_WAITING_ADVDATA
;
1478 #if 0 && defined(OV_DEBUG)
1479 aXXStr
+= "established ";
1485 #if 0 && defined(OV_DEBUG)
1488 aXXStr
+= "failed ";
1491 WRITELOG((char*)aXXStr
.GetStr());
1499 // WRITELOG("DdeClientTransaction:Data received")
1500 // WRITEDATA(pDDEInData)
1503 DBG_ASSERT(pTrans
->nConvst
==XST_WAITING_REQDATA
,"DDE:Bad state");
1504 DBG_ASSERT(pTrans
->nType
==XTYP_ADVREQ
,"DDE:Bad state");
1505 // auf Loop-Betrieb umschalten
1506 pTrans
->nConvst
= XST_WAITING_ADVDATA
;
1511 WRITELOG("DdeClientTransaction:Unexpected msg")
1512 MyDosFreeMem( pDDEInData
,"DdeClientTransaction" );
1515 pThis
->bSyncAbandonTrans
= FALSE
;
1516 pThis
->bInSyncTrans
= FALSE
;
1517 if( pThis
->bSyncAbandonTrans
&& bReqOnAdvLoop
)
1518 pThis
->DdeAbandonTransaction( hConv
, nTransId
);
1522 // WRITELOG("DdeClientTransaction:Starting async. trans.")
1523 pDDEInData
= (HDDEDATA
)MyWinDdePostMsg( hWndServer
, hWndClient
, nMsg
,
1524 pOutDDEData
, DDEPM_RETRY
);
1527 WRITELOG("DdeClientTransaction:PostMsg failed")
1528 nLastErrInstance
= DMLERR_POSTMSG_FAILED
;
1529 if( !bReqOnAdvLoop
)
1530 FreeTransaction( pData
, nTransId
);
1533 DBG_ASSERT(pTrans
->nType
==XTYP_ADVREQ
,"DDE:Error!")
1534 pTrans
->nConvst
= 0;
1539 // WRITELOG("DdeClientTransaction:Async trans. success")
1541 *pResult
= nTransId
;
1544 #if 0 && defined( OV_DEBUG )
1545 if( nType
== XTYP_REQUEST
)
1547 WRITELOG("End XTYP_REQUEST");
1548 WinMessageBox(HWND_DESKTOP
,HWND_DESKTOP
,
1549 "End XTYP_REQUEST","DdeClientTransaction",
1550 HWND_DESKTOP
,MB_OK
);
1553 //WRITELOG("DdeClientTransaction:End")
1554 //WRITESTATUS("DdeClientTransaction:End")
1558 MRESULT
ImpDdeMgr::DdeRegister( ImpWndProcParams
* pParams
)
1560 MRESULT nRet
= (MRESULT
)0;
1561 if ( !(nTransactFilter
& CBF_SKIP_REGISTRATIONS
) )
1563 HSZ hSBaseName
= (HSZ
)pParams
->nPar1
;
1564 HSZ hIBaseName
= (HSZ
)pParams
->nPar2
;
1565 nRet
=(MRESULT
)Callback(XTYP_REGISTER
,0,0,hSBaseName
,hIBaseName
,0,0,0);
1570 MRESULT
ImpDdeMgr::DdeUnregister( ImpWndProcParams
* pParams
)
1572 MRESULT nRet
= (MRESULT
)0;
1573 if ( !(nTransactFilter
& CBF_SKIP_UNREGISTRATIONS
) )
1575 HSZ hSBaseName
= (HSZ
)pParams
->nPar1
;
1576 HSZ hIBaseName
= (HSZ
)pParams
->nPar2
;
1577 nRet
=(MRESULT
)Callback(XTYP_UNREGISTER
,0,0,hSBaseName
,hIBaseName
,0,0,0);
1582 MRESULT
ImpDdeMgr::DdeTimeout( ImpWndProcParams
* pParams
)
1584 ////WRITELOG("DdeTimeout:Received")
1585 if( nSyncResponseMsg
)
1587 ////WRITELOG("DdeTimeout:Trans already processed->ignoring timeout")
1590 ULONG nTimerId
= (ULONG
)pParams
->nPar1
;
1591 ULONG nTransId
= TID_USERMAX
- nTimerId
;
1592 Transaction
* pTrans
= pTransTable
;
1593 pTrans
+= (USHORT
)nTransId
;
1594 if( nTransId
< 1 || nTransId
>= pData
->nMaxTransCount
||
1595 pTrans
->hConvOwner
== 0 )
1597 DBG_ASSERT(0,"DdeTimeout:Invalid TransactionId");
1600 if( bInSyncTrans
&& nTransId
== nSyncTransId
)
1602 USHORT nTempType
= pTrans
->nType
;
1603 nTempType
&= (~XTYPF_MASK
);
1604 // advise-loops koennen nur innerhalb synchroner
1605 // requests timeouts bekommen. die transaktion wird
1606 // in diesem fall nicht geloescht.
1607 if( nTempType
!= (XTYP_ADVREQ
& (~XTYPF_NOBLOCK
) ))
1609 ////WRITELOG("DdeTimeout:Freeing transaction")
1610 FreeTransaction( pData
, nTransId
);
1612 nSyncResponseMsg
= WM_TIMER
;
1613 #if 0 && defined( OV_DEBUG )
1614 String
aMsg("DdeTimeout:Transaction=");
1616 WRITELOG((char*)(const char*)aMsg
)
1621 ////WRITELOG("DdeTimeout:Async transaction timed out")
1622 pTrans
->nConvst
= XST_TIMEOUT
;
1629 MRESULT
ImpDdeMgr::DdeTerminate( ImpWndProcParams
* pParams
)
1631 WRITELOG("DdeTerminate:Received")
1632 HWND hWndThis
= pParams
->hWndReceiver
;
1633 HWND hWndPartner
= (HWND
)(pParams
->nPar1
);
1635 HCONV hConv
= GetConvHandle( pData
, hWndThis
, hWndPartner
);
1636 #if 0 && defined( OV_DEBUG )
1637 String
strDebug("DdeTerminate:ConvHandle=");
1638 strDebug
+= (USHORT
)hConv
;
1639 WRITELOG((char*)(const char*)strDebug
)
1641 ImpHCONV
* pConv
= pConvTable
+ (USHORT
)hConv
;
1644 // warten wir auf ein DDE_TERMINATE Acknowledge ?
1645 if( pConv
->nStatus
& ST_TERMINATED
)
1647 ////WRITELOG("DdeTerminate:TERMINATE-Ack received")
1648 pConv
->nStatus
|= ST_TERMACKREC
;
1649 return (MRESULT
)0; // DdeDisconnect raeumt jetzt auf
1652 // sind wir Server?, wenn ja: die App benachrichtigen,
1653 // dass die Advise loops gestoppt wurden und die
1654 // Transaktionen loeschen
1656 // OV 26.07.96: Die das TERMINATE empfangende App muss
1657 // die Transaction-Tabelle abraeumen, egal ob Server oder Client!!
1658 // Es muessen alle Trans geloescht werden, die als Owner den
1659 // Client oder den Server haben!
1660 // if( !(pConv->nStatus & ST_CLIENT ) )
1661 SendUnadvises( hConv
, 0, FALSE
); // alle Formate & nicht loeschen
1662 SendUnadvises( pConv
->hConvPartner
, 0, FALSE
);
1664 // wir werden von draussen gekillt
1665 if ( !(nTransactFilter
& CBF_SKIP_DISCONNECTS
) )
1667 Callback( XTYP_DISCONNECT
, 0, hConv
, 0, 0, 0,
1668 0, (ULONG
)IsSameInstance(hWndPartner
));
1671 // kann unsere Partner-App DDEML ?
1672 if( !(pConv
->hConvPartner
) )
1674 // nein, deshalb Transaktionstabelle selbst loeschen
1675 ////WRITELOG("DdeTerminate:Freeing transactions")
1676 FreeTransactions( pData
, hConv
);
1680 nLastErrInstance
= DMLERR_NO_CONV_ESTABLISHED
;
1682 #if 0 && defined(OV_DEBUG)
1683 if( !WinIsWindow(0,hWndPartner
))
1685 WRITELOG("DdeTerminate:hWndPartner not valid")
1687 if(!WinIsWindow(0,hWndThis
))
1689 WRITELOG("DdeTerminate:hWndThis not valid")
1695 // hWndThis nicht loeschen, da wir den Handle noch fuer
1696 // das Acknowledge brauchen
1697 ////WRITELOG("DdeTerminate:Freeing conversation")
1698 FreeConvHandle( pData
, hConv
, FALSE
);
1701 ////WRITELOG("DdeTerminate:Acknowledging DDE_TERMINATE")
1704 DBG_ASSERT(WinIsWindow( 0, hWndThis
),"hWndThis not valid");
1707 if( !WinDdePostMsg( hWndPartner
, hWndThis
, WM_DDE_TERMINATE
, 0, DDEPM_RETRY
))
1709 ////WRITELOG("DdeTerminate:Acknowledging DDE_TERMINATE failed")
1711 // jetzt hWndThis loeschen
1712 DestroyConversationWnd( hWndThis
);
1719 Zuordnung des Conversationhandles:
1722 Client: DdeInitiate( HWNDClient )
1723 Server: Post( WM_DDE_INITIATEACK( HWNDServer ))
1724 Client: CreateConvHandle( HWNDClient, HWNDServer )
1727 Server: Post(WM_DDE_ACK( HWNDSender ))
1728 Client: GetConvHandle( HWNDClient, HWNDSender )
1731 MRESULT
ImpDdeMgr::ConvWndProc( HWND hWnd
,ULONG nMsg
,MPARAM nPar1
,MPARAM nPar2
)
1733 ImpWndProcParams aParams
;
1735 MRESULT nRet
= (MRESULT
)0;
1736 aParams
.hWndReceiver
= hWnd
;
1737 aParams
.nPar1
= nPar1
;
1738 aParams
.nPar2
= nPar2
;
1744 case WM_DDE_INITIATE
:
1745 DBG_ASSERT(0,"dde:unexpected msg");
1746 nRet
= (MRESULT
)TRUE
;
1750 case WM_DDE_INITIATEACK
: nRet
= DdeInitiateAck(&aParams
); break;
1751 case WM_DDE_ACK
: nRet
= DdeAck( &aParams
); break;
1752 case WM_DDE_ADVISE
: nRet
= DdeAdvise( &aParams
); break;
1753 case WM_DDE_DATA
: nRet
= DdeData( &aParams
); break;
1754 case WM_DDE_EXECUTE
: nRet
= DdeExecute( &aParams
); break;
1755 case WM_DDE_POKE
: nRet
= DdePoke( &aParams
); break;
1756 case WM_DDE_REQUEST
: nRet
= DdeRequest( &aParams
); break;
1757 case WM_DDE_TERMINATE
: nRet
= DdeTerminate( &aParams
); break;
1758 case WM_DDE_UNADVISE
: nRet
= DdeUnadvise( &aParams
); break;
1759 case WM_TIMER
: nRet
= DdeTimeout( &aParams
); break;
1764 MRESULT
ImpDdeMgr::SrvWndProc( HWND hWnd
,ULONG nMsg
,MPARAM nPar1
,MPARAM nPar2
)
1766 MRESULT nRet
= (MRESULT
)0;
1768 ImpWndProcParams aParams
;
1769 aParams
.hWndReceiver
= hWnd
;
1770 aParams
.nPar1
= nPar1
;
1771 aParams
.nPar2
= nPar2
;
1777 case WM_DDE_ADVISE
:
1778 case WM_DDE_EXECUTE
:
1780 case WM_DDE_REQUEST
:
1781 case WM_DDE_UNADVISE
:
1783 case WM_DDE_INITIATEACK
:
1784 DBG_ASSERT(0,"dde:unexpected msg");
1785 nRet
= (MRESULT
)TRUE
;
1789 case WM_DDE_TERMINATE
:
1790 break; // DDE_INITIATE wurde im DDE_INITIATEACK terminiert
1792 // ein Client will was von uns
1793 case WM_DDE_INITIATE
:
1794 nRet
= DdeInitiate( &aParams
);
1797 // eine ddeml-faehige App. hat einen Service (typ. AppName) [de]reg.
1798 case WM_DDEML_REGISTER
:
1799 nRet
= DdeRegister( &aParams
);
1802 case WM_DDEML_UNREGISTER
:
1803 nRet
= DdeUnregister( &aParams
);
1810 MRESULT
ImpDdeMgr::DdeAck( ImpWndProcParams
* pParams
)
1812 //WRITELOG("DdeAck:Start")
1814 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
1817 BOOL bPositive
= (BOOL
)(pInDDEData
->fsStatus
& DDE_FACK
) != 0;
1818 BOOL bBusy
= bPositive
? FALSE
: (BOOL
)(pInDDEData
->fsStatus
& DDE_FBUSY
) != 0;
1819 BOOL bNotProcessed
= (BOOL
)(pInDDEData
->fsStatus
& DDE_NOTPROCESSED
) != 0;
1820 #if 0 && defined( OV_DEBUG )
1821 String
aDebStr("DdeAck:Received ");
1823 aDebStr
+= "(positive)";
1825 aDebStr
+= "(negative)";
1827 aDebStr
+= "(busy)";
1829 aDebStr
+= "(not processed)";
1830 WRITELOG((char*)(const char*)aDebStr
)
1832 // ein DDE_ACK niemals bestaetigen (um endlosschleifen zu vermeiden)
1833 pInDDEData
->fsStatus
&= (~DDE_FACKREQ
);
1837 //WRITELOG("DdeAck:Received (no data!)")
1841 HCONV hConv
= CheckIncoming(pParams
, 0, hszItem
);
1845 WRITELOG("DdeAck:HCONV not found")
1848 ULONG nTransId
=GetTransaction(pData
,hConv
,hszItem
,pInDDEData
->usFormat
);
1851 WRITELOG("DdeAck:Transaction not found")
1852 MyDosFreeMem( pInDDEData
,"DdeAck" );
1856 BOOL bThisIsSync
= (BOOL
)( bInSyncTrans
&& nTransId
== nSyncTransId
);
1857 #if 0 && defined( OV_DEBUG )
1859 WRITELOG("DdeAck: sync transaction")
1861 WRITELOG("DdeAck: async transaction")
1863 // pruefen, ob die Transaktion abgeschlossen ist.
1864 Transaction
* pTrans
= pTransTable
;
1865 pTrans
+= (USHORT
)nTransId
;
1866 ImpHCONV
* pConv
= pConvTable
;
1867 pConv
+= (USHORT
)hConv
;
1869 if( pTrans
->nConvst
== XST_UNADVSENT
)
1871 //WRITELOG("DdeAck:Unadvise-Ack received")
1872 pTrans
->nConvst
= XST_UNADVACKRCVD
;
1873 MyDosFreeMem( pInDDEData
,"DdeAck" );
1874 DdeFreeStringHandle( hszItem
);
1877 if( pTrans
->nConvst
== XST_ADVDATASENT
)
1879 //WRITELOG("DdeAck:AdvData-Ack received")
1880 pTrans
->nConvst
= XST_ADVDATAACKRCVD
;
1881 MyDosFreeMem( pInDDEData
,"DdeAck" );
1882 DdeFreeStringHandle( hszItem
);
1886 USHORT nType
= pTrans
->nType
;
1887 nType
&= (~XTYPF_MASK
);
1888 // beginn einer advise-loop oder request auf advise-loop ?
1889 // wenn ja: transaktion nicht loeschen
1890 BOOL bFinished
= (BOOL
)(nType
!= XTYP_ADVSTART
&&
1891 nType
!= (XTYP_ADVREQ
& (~XTYPF_NOBLOCK
)) );
1896 ////WRITELOG("DdeAck:Transaction completed")
1897 Callback( XTYP_XACT_COMPLETE
, pInDDEData
->usFormat
, hConv
,
1898 pConv
->hszTopic
, hszItem
, (HDDEDATA
)0, nTransId
, 0 );
1900 ////WRITELOG("DdeAck:Freeing transaction")
1901 FreeTransaction( pData
, nTransId
);
1906 hSyncResponseData
= pInDDEData
;
1907 nSyncResponseMsg
= WM_DDE_ACK
;
1911 MyDosFreeMem( pInDDEData
,"DdeAck" );
1914 DdeFreeStringHandle( hszItem
);
1920 USHORT
ImpDdeMgr::SendUnadvises(HCONV hConvServer
,USHORT nFormat
,BOOL bFree
)
1922 USHORT nTransFound
= 0;
1923 BOOL bCallApp
= (BOOL
)(!(nTransactFilter
& CBF_FAIL_ADVISES
));
1924 #if 0 && defined( OV_DEBUG )
1925 String
aStr("Unadvising transactions for HCONV=");
1926 aStr
+= (ULONG
)hConvServer
;
1927 aStr
+= " CallApp:"; aStr
+= (USHORT
)bCallApp
;
1928 WRITELOG((char*)aStr
.GetStr())
1932 // wenn wir weder loeschen noch die App benachrichtigen sollen,
1933 // koennen wir gleich wieder returnen
1934 if( !hConvServer
|| ( !bFree
&& !bCallApp
) )
1937 ImpHCONV
* pConvSrv
= pConvTable
;
1938 pConvSrv
+= (USHORT
)hConvServer
;
1939 HSZ hszTopic
= pConvSrv
->hszTopic
;
1941 Transaction
* pTrans
= pTransTable
;
1943 USHORT nCurTransId
= 1;
1944 USHORT nCurTransactions
= pData
->nCurTransCount
;
1945 while( nCurTransactions
&& nCurTransId
< pData
->nMaxTransCount
)
1947 if( pTrans
->hConvOwner
)
1949 if( pTrans
->hConvOwner
== hConvServer
&&
1950 (pTrans
->nType
& XTYP_ADVREQ
) )
1952 if( !nFormat
|| (nFormat
== pTrans
->nFormat
) )
1957 //WRITELOG("SendUnadvises:Notifying App")
1958 Callback( XTYP_ADVSTOP
, pTrans
->nFormat
, hConvServer
,
1959 hszTopic
, pTrans
->hszItem
, 0,0,0 );
1962 FreeTransaction( pData
, (ULONG
)nCurTransId
);
1973 HCONV
ImpDdeMgr::CheckIncoming( ImpWndProcParams
* pParams
, ULONG nTransMask
,
1976 // ////WRITELOG("CheckIncoming")
1978 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
1981 // ////WRITELOG("CheckIncoming:PDDESTRUCT==0")
1985 HWND hWndThis
= pParams
->hWndReceiver
;
1986 HWND hWndClient
= (HWND
)pParams
->nPar1
;
1988 BOOL bReject
= (BOOL
)(nTransactFilter
& nTransMask
);
1991 hConv
= GetConvHandle( pData
, hWndThis
, hWndClient
);
1992 if ( bReject
|| !hConv
)
1995 rhszItem
= DdeCreateStringHandle(
1996 ((char*)(pInDDEData
)+pInDDEData
->offszItemName
), 850 );
1998 // ////WRITELOG("CheckIncoming:OK");
2003 MRESULT
ImpDdeMgr::DdeAdvise( ImpWndProcParams
* pParams
)
2005 ////WRITELOG("DdeAdvise:Received")
2007 HCONV hConv
= CheckIncoming(pParams
, CBF_FAIL_ADVISES
, hszItem
);
2008 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2009 HWND hWndThis
= pParams
->hWndReceiver
;
2010 HWND hWndClient
= (HWND
)pParams
->nPar1
;
2013 ////WRITELOG("DdeAdvise:Conversation not found")
2014 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2015 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2016 DdeFreeStringHandle( hszItem
);
2020 Transaction
* pTrans
= pTransTable
;
2021 ImpHCONV
* pConv
= pConvTable
;
2022 pConv
+= (USHORT
)hConv
;
2024 // existiert schon ein Link auf Topic/Item/Format-Vektor ?
2026 ULONG nTransId
=GetTransaction(pData
,hConv
,hszItem
,pInDDEData
->usFormat
);
2029 ////WRITELOG("DdeAdvise:Transaction already exists")
2030 pTrans
+= (USHORT
)nTransId
;
2031 // ist es eine AdviseLoop ?
2032 USHORT nTempType
= pTrans
->nType
;
2033 nTempType
&= (~XTYPF_MASK
);
2034 if( nTempType
== XTYP_ADVREQ
)
2036 // Flags der laufenden Advise-Loop aktualisieren
2037 ////WRITELOG("DdeAdvise:Adjusting Advise-Params")
2038 pTrans
->nType
= XTYP_ADVREQ
;
2039 if( pInDDEData
->fsStatus
& DDE_FNODATA
)
2040 pTrans
->nType
|= XTYPF_NODATA
;
2041 if( pInDDEData
->fsStatus
& DDE_FACKREQ
)
2042 pTrans
->nType
|= XTYPF_ACKREQ
;
2043 pInDDEData
->fsStatus
|= DDE_FACK
;
2044 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2045 DdeFreeStringHandle( hszItem
);
2048 else if( nTempType
!= XTYP_ADVSTART
)
2050 ////WRITELOG("DdeAdvise:Not a advise transaction")
2051 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2052 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2053 DdeFreeStringHandle( hszItem
);
2060 ////WRITELOG("DdeAdvise:Creating Transaction")
2061 ////WRITESTATUS("DdeAdvise:Creating Transaction")
2062 nTransId
= CreateTransaction( pData
, hConv
, hszItem
,
2063 pInDDEData
->usFormat
, XTYP_ADVREQ
);
2064 ////WRITESTATUS("DdeAdvise:Created Transaction")
2068 pTrans
= pTransTable
;
2069 pTrans
+= (USHORT
)nTransId
;
2070 if( pInDDEData
->fsStatus
& DDE_FNODATA
)
2071 pTrans
->nType
|= XTYPF_NODATA
;
2072 if( pInDDEData
->fsStatus
& DDE_FACKREQ
)
2073 pTrans
->nType
|= XTYPF_ACKREQ
;
2077 ////WRITELOG("DdeAdvise:Cannot create Transaction")
2078 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2079 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2080 DdeFreeStringHandle( hszItem
);
2084 ////WRITELOG("DdeAdvise:Calling Server")
2086 if ( Callback( XTYP_ADVSTART
, pInDDEData
->usFormat
,
2087 hConv
, pConv
->hszTopic
, hszItem
, (HDDEDATA
)0, 0, 0 ) )
2090 // ServerApp erlaubt AdviseLoop
2092 ////WRITELOG("DdeAdvise:Advise loop established")
2093 pInDDEData
->fsStatus
|= DDE_FACK
;
2094 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2098 ////WRITELOG("DdeAdvise:Advise loop not established")
2099 FreeTransaction( pData
, nTransId
);
2100 pInDDEData
->fsStatus
&= (~DDE_FACK
); // DDE_FNOTPROCESSED;
2101 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2103 ////WRITESTATUS("DdeAdvise:End")
2104 ////WRITELOG("DdeAdvise:End")
2105 DdeFreeStringHandle( hszItem
);
2109 MRESULT
ImpDdeMgr::DdeData( ImpWndProcParams
* pParams
)
2111 WRITELOG("DdeData:Received")
2113 HCONV hConv
= CheckIncoming(pParams
, 0, hszItem
);
2114 HWND hWndThis
= pParams
->hWndReceiver
;
2115 HWND hWndClient
= (HWND
)pParams
->nPar1
;
2116 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2117 #if 0 && defined( OV_DEBUG )
2119 String
aStr("DdeData Address:");
2120 aStr
+= (ULONG
)pInDDEData
;
2121 WRITELOG((char*)aStr
.GetStr())
2126 if( pInDDEData
&& (pInDDEData
->fsStatus
& DDE_FACKREQ
))
2128 WRITELOG("DdeData: Ackn requested")
2133 WRITELOG("DdeData: Ackn not requested")
2137 ULONG nTransId
= GetTransaction(pData
,hConv
,hszItem
,pInDDEData
->usFormat
);
2140 WRITELOG("DdeData:Transaction not found")
2141 WRITEDATA(pInDDEData
)
2144 WRITELOG("DdeData: Posting Ackn")
2145 pInDDEData
->fsStatus
&= (~DDE_FACK
); // NOTPROCESSED;
2146 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2150 MyDosFreeMem( pInDDEData
,"DdeData" );
2155 #if 0 && defined( OV_DEBUG )
2158 WRITEDATA(pInDDEData
)
2162 BOOL bThisIsSync
= (BOOL
)( bInSyncTrans
&& nTransId
== nSyncTransId
);
2164 // pruefen, ob die Transaktion abgeschlossen ist.
2165 Transaction
* pTrans
= pTransTable
;
2166 pTrans
+= (USHORT
)nTransId
;
2168 if( pTrans
->nConvst
== XST_WAITING_ACK
)
2170 // dieser Fall kann eintreten, wenn ein Server innerhalb
2171 // einer WM_DDE_ADVISE-Msg. oder bevor beim Client das
2172 // Ack eintrifft, Advise-Daten sendet.
2173 WRITELOG("DdeData:Ignoring unexpected data")
2176 WRITELOG("DdeData: Posting Ackn")
2177 pInDDEData
->fsStatus
&= (~DDE_FACK
); // NOTPROCESSED;
2178 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2182 MyDosFreeMem( pInDDEData
,"DdeData" );
2187 ImpHCONV
* pConv
= pConvTable
;
2188 pConv
+= (USHORT
)hConv
;
2190 USHORT nType
= pTrans
->nType
;
2191 nType
&= (~XTYPF_MASK
);
2192 BOOL bNotAdviseLoop
= (BOOL
)(nType
!= (XTYP_ADVREQ
& (~XTYPF_NOBLOCK
)));
2195 // WRITELOG("DdeData:Is async transaction")
2196 if( bNotAdviseLoop
)
2198 // WRITELOG("DdeData:Transaction completed -> calling client")
2199 Callback( XTYP_XACT_COMPLETE
, pInDDEData
->usFormat
, hConv
,
2200 pConv
->hszTopic
, hszItem
, pInDDEData
, nTransId
, 0 );
2201 // WRITELOG("DdeData:Freeing transaction")
2202 FreeTransaction( pData
, nTransId
);
2206 WRITELOG("DdeData:Advise-Loop -> calling client")
2207 HDDEDATA pToSend
= pInDDEData
;
2208 if( pTrans
->nType
& XTYPF_NODATA
)
2211 // WRITELOG("DdeData:Is warm link")
2213 Callback( XTYP_ADVDATA
, pInDDEData
->usFormat
, hConv
,
2214 pConv
->hszTopic
, hszItem
, pToSend
, nTransId
, 0 );
2218 WRITELOG("DdeData: Posting Ackn")
2219 pInDDEData
->fsStatus
= DDE_FACK
;
2220 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2223 MyDosFreeMem( pInDDEData
,"DdeData" );
2225 else // synchrone Transaktion (Datenhandle nicht freigeben!)
2227 // WRITELOG("DdeData:Is sync transaction")
2228 hSyncResponseData
= pInDDEData
;
2229 nSyncResponseMsg
= WM_DDE_DATA
;
2232 pInDDEData
->fsStatus
|= DDE_FACK
;
2233 WRITELOG("DdeData: Posting Ackn")
2234 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,
2235 DDEPM_RETRY
| DDEPM_NOFREE
);
2239 DdeFreeStringHandle( hszItem
);
2240 // WRITELOG("DdeData:End")
2244 MRESULT
ImpDdeMgr::DdeExecute( ImpWndProcParams
* pParams
)
2246 ////WRITELOG("DdeExecute:Received")
2247 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2249 HCONV hConv
= CheckIncoming(pParams
, 0, hszItem
);
2250 BOOL bSuccess
= FALSE
;
2251 ImpHCONV
* pConv
= pConvTable
;
2252 pConv
+= (USHORT
)hConv
;
2253 if ( hConv
&& !(nTransactFilter
& CBF_FAIL_EXECUTES
) && pInDDEData
)
2255 if ( Callback( XTYP_EXECUTE
, pInDDEData
->usFormat
, hConv
,
2256 pConv
->hszTopic
, hszItem
, pInDDEData
, 0, 0 )
2257 == (DDESTRUCT
*)DDE_FACK
)
2262 ////WRITELOG("DdeExecute:Not processed")
2267 pInDDEData
->fsStatus
|= DDE_FACK
;
2269 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2270 MyWinDdePostMsg( pConv
->hWndPartner
, pConv
->hWndThis
, WM_DDE_ACK
,
2271 pInDDEData
, DDEPM_RETRY
);
2273 DdeFreeStringHandle( hszItem
);
2277 HCONV
ImpDdeMgr::ConnectWithClient( HWND hWndClient
,
2278 HSZ hszPartner
, HSZ hszService
, HSZ hszTopic
, BOOL bSameInst
,
2279 DDEINIT
* pDDEData
, CONVCONTEXT
* pCC
)
2281 ////WRITELOG("ConnectWithClient:Start")
2282 HWND hWndSrv
= CreateConversationWnd();
2283 IncConversationWndRefCount( hWndSrv
);
2284 HCONV hConv
= CreateConvHandle( pData
, pidThis
, hWndSrv
, hWndClient
,
2285 hszPartner
, hszService
, hszTopic
);
2288 BOOL bFreeDdeData
= FALSE
;
2291 bFreeDdeData
= TRUE
;
2292 pDDEData
= CreateDDEInitData( hWndClient
,hszService
,hszTopic
, pCC
);
2294 WinQueryWindowProcess( hWndClient
, &pid
, &tid
);
2295 DosGiveSharedMem( pDDEData
, pid
, PAG_READ
| PAG_WRITE
);
2297 HAB hAB
= WinQueryAnchorBlock( hWndSrv
);
2298 WinGetLastError( hAB
); // fehlercode zuruecksetzen
2299 WinSendMsg(hWndClient
,WM_DDE_INITIATEACK
,(MPARAM
)hWndSrv
,(MPARAM
)pDDEData
);
2300 if( WinGetLastError( hAB
) )
2302 // ////WRITELOG("DdeConnectWithClient:Client died")
2305 MyDosFreeMem( pDDEData
,"ConnectWithClient" );
2307 FreeConvHandle( pData
, hConv
);
2311 if( !(nTransactFilter
& CBF_SKIP_CONNECT_CONFIRMS
) )
2313 Callback( XTYP_CONNECT_CONFIRM
, 0, hConv
, hszTopic
, hszService
,
2314 0, 0, (ULONG
)bSameInst
);
2319 MyDosFreeMem( pDDEData
,"ConnectWithClient" );
2321 // HCONV der PartnerApp suchen & bei uns eintragen
2322 ImpHCONV
* pConv
= pConvTable
;
2323 pConv
+= (USHORT
)hConv
;
2324 pConv
->hConvPartner
= GetConvHandle( pData
, hWndClient
, hWndSrv
);
2325 #if 0 && defined(OV_DEBUG)
2326 if( !pConv
->hConvPartner
)
2328 WRITELOG("DdeConnectWithClient:Partner not found")
2331 pConv
->nStatus
= ST_CONNECTED
;
2332 //WRITESTATUS("Server:Connected with client")
2333 //WRITELOG("ConnectWithClient:End")
2337 MRESULT
ImpDdeMgr::DdeInitiate( ImpWndProcParams
* pParams
)
2339 ////WRITELOG("DdeInitiate:Received")
2340 HWND hWndClient
= (HWND
)(pParams
->nPar1
);
2341 // BOOL bSameInst = IsSameInstance( hWndClient );
2342 BOOL bSameInst
= (BOOL
)(hWndClient
==hWndServer
);
2343 DDEINIT
* pDDEData
= (DDEINIT
*)pParams
->nPar2
;
2345 if ( ( nTransactFilter
& (CBF_FAIL_CONNECTIONS
| APPCMD_CLIENTONLY
)) ||
2346 (( nTransactFilter
& CBF_FAIL_SELFCONNECTIONS
) && bSameInst
)
2349 MyDosFreeMem( pDDEData
,"DdeInitiate" );
2350 return (MRESULT
)FALSE
; // narda
2353 HSZ hszService
= (HSZ
)0;
2354 if( *(pDDEData
->pszAppName
) != '\0' )
2356 hszService
= DdeCreateStringHandle( pDDEData
->pszAppName
, 850 );
2357 ////WRITELOG(pDDEData->pszAppName);
2359 HSZ hszTopic
= (HSZ
)0;
2360 if( *(pDDEData
->pszTopic
) != '\0' )
2362 hszTopic
= DdeCreateStringHandle( pDDEData
->pszTopic
, 850 );
2363 ////WRITELOG(pDDEData->pszTopic);
2365 HSZ hszPartner
= GetAppName( hWndClient
);
2367 // nur weitermachen, wenn Service registriert oder
2368 // Service-Name-Filtering ausgeschaltet.
2369 if( !bServFilterOn
|| GetService(hszService
) )
2371 // XTYP_CONNECT-Transaktionen erfolgen nur mit
2372 // Services & Topics ungleich 0!
2373 if( hszService
&& hszTopic
)
2375 if( IsConvHandleAvailable(pData
) && Callback( XTYP_CONNECT
,
2376 0, 0, hszTopic
,hszService
, 0, 0, (ULONG
)bSameInst
))
2378 // App erlaubt Verbindung mit Client
2379 ConnectWithClient( hWndClient
, hszPartner
,
2380 hszService
, hszTopic
, bSameInst
, pDDEData
);
2385 // ** Wildcard-Connect **
2386 ////WRITELOG("DdeInitiate:Wildconnect")
2387 // vom Server eine Liste aller Service/Topic-Paare anfordern
2388 CONVCONTEXT
* pCC
=(CONVCONTEXT
*)(pDDEData
+pDDEData
->offConvContext
);
2389 DDESTRUCT
* hList
= Callback( XTYP_WILDCONNECT
, 0, (HCONV
)0,
2390 hszTopic
,hszService
, (HDDEDATA
)0, (ULONG
)pCC
, (ULONG
)bSameInst
);
2393 HSZPAIR
* pPairs
= (HSZPAIR
*)((char*)hList
+hList
->offabData
);
2394 while( pPairs
->hszSvc
)
2396 ////WRITELOG("DdeInitiate:Wildconnect.Connecting")
2397 ConnectWithClient( hWndClient
, hszPartner
,
2398 pPairs
->hszSvc
, pPairs
->hszTopic
, bSameInst
, 0, pCC
);
2399 // Stringhandles gehoeren der App! (nicht free-en)
2402 DdeFreeDataHandle( hList
);
2406 #if 0 && defined(OV_DEBUG)
2409 WRITELOG("DdeInitiate:Service filtered")
2412 DdeFreeStringHandle( hszTopic
);
2413 DdeFreeStringHandle( hszService
);
2414 DdeFreeStringHandle( hszPartner
);
2415 MyDosFreeMem( pDDEData
,"DdeInitiate" );
2416 ////WRITELOG("DdeInitiate:End")
2417 return (MRESULT
)TRUE
;
2420 MRESULT
ImpDdeMgr::DdeInitiateAck( ImpWndProcParams
* pParams
)
2422 ////WRITELOG("DdeInitiateAck:Received")
2423 DDEINIT
* pDDEData
= (DDEINIT
*)(pParams
->nPar2
);
2425 if( !bListConnect
&& hCurConv
)
2427 ////WRITELOG("DdeInitiateAck:Already connected")
2428 MyDosFreeMem( pDDEData
,"DdeInitiateAck" );
2429 WinPostMsg( hWndServer
, WM_DDE_TERMINATE
, (MPARAM
)hWndServer
, 0 );
2430 return (MRESULT
)FALSE
;
2433 HWND hWndThis
= pParams
->hWndReceiver
;
2434 // Referenz-Count unseres Client-Windows inkrementieren
2435 IncConversationWndRefCount( hWndThis
);
2437 HWND hWndSrv
= (HWND
)(pParams
->nPar1
);
2438 HSZ hszService
= DdeCreateStringHandle( pDDEData
->pszAppName
, 850 );
2439 HSZ hszTopic
= DdeCreateStringHandle( pDDEData
->pszTopic
, 850 );
2440 HSZ hszPartnerApp
= GetAppName( hWndSrv
);
2442 hCurConv
= CreateConvHandle( pData
, pidThis
, hWndThis
, hWndSrv
,
2443 hszPartnerApp
, hszService
, hszTopic
, 0 );
2445 ImpHCONV
* pConv
= pConvTable
;
2446 pConv
+= (USHORT
)hCurConv
;
2448 // HCONV der PartnerApp suchen & bei uns eintragen
2449 pConv
->hConvPartner
= GetConvHandle( pData
, hWndSrv
, hWndThis
);
2450 // nicht asserten, da ja non-ddeml-Partner moeglich
2451 // DBG_ASSERT(pConv->hConvPartner,"DDE:Partner not found");
2452 pConv
->nStatus
= ST_CONNECTED
| ST_CLIENT
;
2456 ////WRITELOG("DdeInitiateAck:ListConnect/Connecting hConvs")
2457 // Status setzen & verketten
2458 pConv
->hConvList
= hCurListId
;
2459 pConv
->nPrevHCONV
= nPrevConv
;
2460 pConv
->nStatus
|= ST_INLIST
;
2465 pConv
->nNextHCONV
= (USHORT
)hCurConv
;
2467 nPrevConv
= (USHORT
)hCurConv
;
2470 DdeFreeStringHandle( hszService
);
2471 DdeFreeStringHandle( hszTopic
);
2472 DdeFreeStringHandle( hszPartnerApp
);
2473 MyDosFreeMem( pDDEData
,"DdeInitiateAck" );
2474 ////WRITESTATUS("After DdeInitiateAck")
2475 ////WRITELOG("DdeInitiateAck:End")
2476 return (MRESULT
)TRUE
;
2479 MRESULT
ImpDdeMgr::DdePoke( ImpWndProcParams
* pParams
)
2481 ////WRITELOG("DdePoke:Received")
2483 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2484 HCONV hConv
= CheckIncoming( pParams
, CBF_FAIL_REQUESTS
, hszItem
);
2485 BOOL bSuccess
=FALSE
;
2486 ImpHCONV
* pConv
= pConvTable
;
2487 pConv
+= (USHORT
)hConv
;
2488 if ( hConv
&& !(nTransactFilter
& CBF_FAIL_POKES
) && pInDDEData
)
2490 if( Callback( XTYP_POKE
, pInDDEData
->usFormat
, hConv
,
2491 pConv
->hszTopic
, hszItem
, pInDDEData
, 0, 0 )
2492 == (DDESTRUCT
*)DDE_FACK
)
2495 #if 0 && defined( OV_DEBUG )
2498 WRITELOG("DdePoke:Not processed")
2504 pInDDEData
->fsStatus
|= DDE_FACK
;
2506 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2508 MyWinDdePostMsg( pConv
->hWndPartner
, pConv
->hWndThis
, WM_DDE_ACK
,
2509 pInDDEData
, DDEPM_RETRY
);
2511 DdeFreeStringHandle( hszItem
);
2515 MRESULT
ImpDdeMgr::DdeRequest( ImpWndProcParams
* pParams
)
2517 ////WRITELOG("DdeRequest:Received")
2519 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2521 // ist fuer Requests nicht definiert
2522 pInDDEData
->fsStatus
= 0;
2523 HCONV hConv
= CheckIncoming( pParams
, CBF_FAIL_REQUESTS
, hszItem
);
2524 HWND hWndThis
= pParams
->hWndReceiver
;
2525 HWND hWndClient
= (HWND
)pParams
->nPar1
;
2528 ImpHCONV
* pConv
= pConvTable
;
2529 pConv
+= (USHORT
)hConv
;
2531 DDESTRUCT
* pOutDDEData
= Callback( XTYP_REQUEST
, pInDDEData
->usFormat
,
2532 hConv
, pConv
->hszTopic
, hszItem
, (HDDEDATA
)0, 0, 0 );
2536 ////WRITELOG("DdeRequest:Not processed")
2537 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2538 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2542 ////WRITELOG("DdeRequest:Success")
2543 MyDosFreeMem( pInDDEData
,"DdeRequest" );
2544 pOutDDEData
->fsStatus
|= DDE_FRESPONSE
;
2545 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_DATA
,pOutDDEData
,DDEPM_RETRY
);
2550 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2551 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2554 DdeFreeStringHandle( hszItem
);
2555 ////WRITELOG("DdeRequest:End")
2560 MRESULT
ImpDdeMgr::DdeUnadvise( ImpWndProcParams
* pParams
)
2562 ////WRITELOG("DdeUnadvise:Received")
2565 HCONV hConv
= CheckIncoming( pParams
, 0, hszItem
);
2566 DDESTRUCT
* pInDDEData
= (DDESTRUCT
*)(pParams
->nPar2
);
2567 HWND hWndThis
= pParams
->hWndReceiver
;
2568 HWND hWndClient
= (HWND
)pParams
->nPar1
;
2569 USHORT nClosedTransactions
= 0;
2572 USHORT nFormat
= pInDDEData
->usFormat
;
2573 // alle Transaktionen des HCONVs loeschen ?
2576 // App benachrichtigen & Transaktionen loeschen
2577 nClosedTransactions
= SendUnadvises( hConv
, nFormat
, TRUE
);
2581 ULONG nTransId
= GetTransaction(pData
, hConv
, hszItem
, nFormat
);
2584 ////WRITELOG("DdeUnadvise:Transaction found")
2585 Transaction
* pTrans
= pTransTable
;
2586 pTrans
+= (USHORT
)nTransId
;
2587 ImpHCONV
* pConv
= pConvTable
;
2588 pConv
+= (USHORT
)hConv
;
2589 nClosedTransactions
= 1;
2590 if( !(nTransactFilter
& CBF_FAIL_ADVISES
) )
2591 Callback( XTYP_ADVSTOP
, nFormat
, hConv
,
2592 pConv
->hszTopic
, hszItem
, 0, 0, 0 );
2593 if( !pConv
->hConvPartner
)
2594 FreeTransaction( pData
, nTransId
);
2596 #if defined(OV_DEBUG)
2599 WRITELOG("DdeUnadvise:Transaction not found")
2604 #if defined(OV_DEBUG)
2607 WRITELOG("DdeUnadvise:Conversation not found")
2611 if( !nClosedTransactions
)
2612 pInDDEData
->fsStatus
&= (~DDE_FACK
);
2614 pInDDEData
->fsStatus
|= DDE_FACK
;
2616 MyWinDdePostMsg(hWndClient
,hWndThis
,WM_DDE_ACK
,pInDDEData
,DDEPM_RETRY
);
2617 DdeFreeStringHandle( hszItem
);
2621 BOOL
ImpDdeMgr::WaitTransState( Transaction
* pTrans
, ULONG nTransId
,
2622 USHORT nNewState
, ULONG nTimeout
)
2624 ////WRITELOG("WaitTransState:Start")
2625 ImpHCONV
* pConv
= pConvTable
;
2626 pConv
+= pTrans
->hConvOwner
;
2627 HAB hAB
= WinQueryAnchorBlock( pConv
->hWndThis
);
2628 ULONG nTimerId
= WinStartTimer( hAB
, 0, 0, 50 );
2631 // while( WinGetMsg( hAB, &aQueueMsg, 0, 0, 0 ) &&
2632 // WinIsWindow( hAB, pConv->hWndPartner) &&
2633 // pTrans->nConvst != nNewState )
2635 // WinDispatchMsg( hAB, &aQueueMsg );
2638 BOOL bContinue
= TRUE
;
2641 if( WinGetMsg( hAB
, &aQueueMsg
, 0, 0, 0 ))
2643 WinDispatchMsg( hAB
, &aQueueMsg
);
2644 if( (!WinIsWindow( hAB
, pConv
->hWndPartner
)) ||
2645 (pTrans
->nConvst
== nNewState
) )
2654 WinStopTimer( hAB
, 0, nTimerId
);
2655 ////WRITELOG("WaitTransState:End")