Update ooo320-m1
[ooovba.git] / svtools / source / svdde / ddeml1.cxx
blobf2c627759a34ea3676a4a84551219f794dc6fe8c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ddeml1.cxx,v $
10 * $Revision: 1.5 $
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"
35 ToDo / Bugs:
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
43 - Codepage-Geraffel
45 #define INCL_DOSPROCESS
47 #include "ddemlimp.hxx"
49 #define LOGFILE
50 #define STATUSFILE
51 #define DDEDATAFILE
52 #include "ddemldeb.hxx"
55 #if defined (OS2) && defined (__BORLANDC__)
56 #pragma option -w-par
57 #endif
59 // static
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);
64 if( !bSuccess )
66 WRITELOG("WinDdePostMsg:Failed!")
67 if ( !(nFlags & DDEPM_NOFREE) )
69 MyDosFreeMem( pData,"MyWinDdePostMsg" );
72 return bSuccess;
76 // *********************************************************************
77 // ImpDdeMgr
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")
93 #endif
94 ImpConvWndData* pObj = (ImpConvWndData*)WinQueryWindowULong( hWnd, 0 );
95 return pObj->pThis->ConvWndProc( hWnd, nMsg, nPar1, nPar2 );
99 // Server-WndProc
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")
109 #endif
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;
120 if( pCallback )
121 hRet = (*pCallback)(nTransactionType, nClipboardFormat,
122 hConversationHandle, hsz1, hsz2, hData, nData1, nData2);
123 return hRet;
128 ImpDdeMgr::ImpDdeMgr()
130 nLastErrInstance = DMLERR_NO_ERROR;
131 pCallback = 0;
132 nTransactFilter = 0;
133 nServiceCount = 0;
134 pServices = 0;
135 pAppTable = 0;
136 pConvTable = 0;
137 pTransTable = 0;
138 bServFilterOn = TRUE;
139 bInSyncTrans = FALSE;
141 CreateServerWnd();
142 pData = InitAll();
143 if ( !pData )
144 nLastErrInstance = DMLERR_MEMORY_ERROR;
145 else
146 RegisterDDEMLApp();
149 ImpDdeMgr::~ImpDdeMgr()
151 CleanUp();
152 DestroyServerWnd();
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.
156 // if ( pData )
157 // DosFreeMem( pData );
161 BOOL ImpDdeMgr::IsSameInstance( HWND hWnd )
163 TID tid; PID pid;
164 WinQueryWindowProcess( hWnd, &pid, &tid );
165 return (BOOL)(pid == pidThis);
168 HSZ ImpDdeMgr::GetAppName( HWND hWnd )
170 return 0;
173 // static
174 ImpDdeMgr* ImpDdeMgr::GetImpDdeMgrInstance( HWND hWnd )
176 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
177 if( !pData )
178 return 0;
180 ImpDdeMgr* pResult = 0;
181 TID tid; PID pidApp;
182 WinQueryWindowProcess( hWnd, &pidApp, &tid );
183 HWND* pApp = ImpDdeMgr::GetAppTable( pData );
184 USHORT nCurApp = 0;
185 while( nCurApp < pData->nMaxAppCount )
187 HWND hCurWin = *pApp;
188 if( hCurWin )
190 PID pidCurApp;
191 WinQueryWindowProcess( hCurWin, &pidCurApp, &tid );
192 if( pidCurApp == pidApp )
194 pResult = (ImpDdeMgr*)WinQueryWindowULong( hCurWin, 0 );
195 break;
198 pApp++;
199 nCurApp++;
201 return pResult;
208 void ImpDdeMgr::CleanUp()
210 DisconnectAll();
211 ImpService* pPtr = pServices;
212 if( pPtr )
214 for( USHORT nIdx = 0; nIdx < nServiceCount; nIdx++, pPtr++ )
216 HSZ hStr = pPtr->hBaseServName;
217 if( hStr )
218 DdeFreeStringHandle( hStr );
219 hStr = pPtr->hInstServName;
220 if( hStr )
221 DdeFreeStringHandle( hStr );
223 nServiceCount = 0;
224 delete pServices;
225 pServices = 0;
227 bServFilterOn = TRUE; // default setting DDEML
228 UnregisterDDEMLApp();
231 void ImpDdeMgr::RegisterDDEMLApp()
233 HWND* pPtr = pAppTable;
234 HWND hCur;
235 USHORT nPos = 0;
236 while( nPos < pData->nMaxAppCount )
238 hCur = *pPtr;
239 if (hCur == (HWND)0 )
241 // in Tabelle stellen
242 *pPtr = hWndServer;
243 break;
245 nPos++;
246 pPtr++;
250 void ImpDdeMgr::UnregisterDDEMLApp()
252 HWND* pPtr = pAppTable;
253 USHORT nPos = 0;
254 while( nPos < pData->nMaxAppCount )
256 if (*pPtr == hWndServer )
258 *pPtr = 0;
259 break;
261 nPos++;
262 pPtr++;
266 // static
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");
272 return pData;
275 USHORT ImpDdeMgr::DdeGetLastError()
277 USHORT nErr;
278 if ( !pData )
279 nErr = DMLERR_DLL_NOT_INITIALIZED;
280 else if ( nLastErrInstance )
281 nErr = nLastErrInstance;
282 else
283 nErr = pData->nLastErr;
285 nLastErrInstance = 0;
286 pData->nLastErr = 0;
287 return nErr;
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;
309 // static
310 HWND ImpDdeMgr::NextFrameWin( HENUM hEnum )
312 char aBuf[ 10 ];
314 HWND hWnd = WinGetNextWindow( hEnum );
315 while( hWnd )
317 WinQueryClassName( hWnd, sizeof(aBuf)-1, (PCH)aBuf );
318 // Frame-Window ?
319 if( !strcmp( aBuf, "#1" ) ) // #define WC_FRAME ((PSZ)0xffff0001L)
320 break;
321 hWnd = WinGetNextWindow( hEnum );
323 return hWnd;
327 HCONV ImpDdeMgr::DdeConnectImp( HSZ hszService,HSZ hszTopic,CONVCONTEXT* pCC)
329 hCurConv = 0;
330 if( !pCC )
331 pCC = &aDefaultContext;
333 ULONG nBufLen;
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:");
338 aStr += pService;
339 aStr += " Topic:";
340 aStr += pTopic;
341 WRITELOG((char*)(const char*)aStr)
342 #endif
344 #if defined(OV_DEBUG)
345 if( !strcmp(pService,"oliver voeltz") )
347 WRITESTATUS("Table of connections");
348 MyDosFreeMem( pTopic,"DdeConnectImp" );
349 MyDosFreeMem( pService,"DdeConnectImp" );
350 return 0;
352 #endif
354 #if 0
355 // original pm-fkt benutzen
356 HWND hWndCurClient = CreateConversationWnd();
357 WinDdeInitiate( hWndCurClient, pService, pTopic, pCC );
358 if( GetConversationWndRefCount(hWndCurClient) == 0)
359 DestroyConversationWnd( hWndCurClient );
360 #else
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 )
378 break;
380 hWndCurSrv = NextFrameWin( hEnum );
383 if( GetConversationWndRefCount(hWndCurClient) == 0)
384 DestroyConversationWnd( hWndCurClient );
385 WinEndEnumWindows( hEnum );
386 #endif
388 if( !hCurConv )
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)";
395 else
396 aCStr += "(Failed)";
397 WRITELOG((char*)aCStr.GetStr())
398 #endif
400 MyDosFreeMem( pTopic,"DdeConnectImp" );
401 MyDosFreeMem( pService,"DdeConnectImp" );
402 return hCurConv;
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")
412 return hResult;
416 HCONVLIST ImpDdeMgr::DdeConnectList( HSZ hszService, HSZ hszTopic,
417 HCONVLIST hConvList, CONVCONTEXT* pCC )
419 nPrevConv = 0;
420 ////WRITESTATUS("Before DdeConnectList")
421 if( hConvList )
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;
431 return 0;
433 GetLastServer(pData, hConvList, hLastConvInList);
434 nPrevConv = (USHORT)hLastConvInList;
436 else
437 hCurListId = (HCONVLIST)WinCreateWindow( HWND_OBJECT, WC_FRAME,
438 CONVLISTNAME, 0,0,0,0,0, HWND_DESKTOP, HWND_BOTTOM, 0,0,0);
440 bListConnect = TRUE;
441 DdeConnectImp( hszService, hszTopic, pCC );
442 #if 0 && defined(OV_DEBUG)
443 WRITELOG("DdeConnectList:ConnectionList:")
444 HCONV hDebug = 0;
447 hDebug = DdeQueryNextServer( hCurListId, hDebug);
448 String aStr( (ULONG)hDebug );
449 WRITELOG((char*)(const char*)aStr)
450 } while( hDebug );
451 #endif
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();
462 if( hszService )
463 nLen1 = WinQueryAtomLength( hAtomTable, hszService );
464 if( hszTopic )
465 nLen2 = WinQueryAtomLength( hAtomTable, hszTopic );
466 nLen1++; nLen2++;
468 DDEINIT* pBuf = 0;
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 );
478 PID pid; TID tid;
479 WinQueryWindowProcess( hWndDestination, &pid, &tid );
480 APIRET nRet = DosGiveSharedMem( pBuf, pid, PAG_READ | PAG_WRITE );
483 pBuf->cb = nLen;
484 pBuf->offConvContext = sizeof( DDEINIT );
485 char* pBase = (char*)pBuf;
486 pBase += sizeof(DDEINIT);
487 if( pCC )
488 memcpy( pBase, pCC, sizeof(CONVCONTEXT) );
489 pBase += sizeof(CONVCONTEXT);
490 pBuf->pszAppName = pBase;
491 if( hszService )
492 WinQueryAtomName( hAtomTable, hszService, pBase, nLen1 );
493 pBase += nLen1;
494 pBuf->pszTopic = pBase;
495 if( hszTopic )
496 WinQueryAtomName( hAtomTable, hszTopic, pBase, nLen2 );
498 return pBuf;
503 void ImpDdeMgr::MyInitiateDde( HWND hWndSrv, HWND hWndClient,
504 HSZ hszService, HSZ hszTopic, CONVCONTEXT* pCC )
506 DDEINIT* pBuf = CreateDDEInitData( hWndSrv, hszService, hszTopic, pCC );
507 if( pBuf )
509 PID pid; TID tid;
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" );
517 // static
518 ImpHCONV* ImpDdeMgr::GetFirstServer(ImpDdeMgrData* pData, HCONVLIST hConvList,
519 HCONV& rhConv )
521 ImpHCONV* pPtr = GetConvTable( pData );
522 HCONV hConv;
523 if( !rhConv )
525 pPtr++;
526 hConv = 1;
528 else
530 // Startposition
531 pPtr += (USHORT)rhConv;
532 hConv = rhConv;
533 pPtr++; hConv++; // auf den naechsten
535 while( hConv < pData->nMaxConvCount )
537 if( pPtr->hConvList == hConvList )
539 rhConv = hConv;
540 return pPtr;
542 pPtr++;
543 hConv++;
545 rhConv = 0;
546 return 0;
549 // static
550 ImpHCONV* ImpDdeMgr::GetLastServer(ImpDdeMgrData* pData, HCONVLIST hConvList,
551 HCONV& rhConv )
553 ImpHCONV* pPtr = GetConvTable( pData );
554 pPtr += pData->nMaxConvCount;
555 pPtr--;
556 HCONV hConv = pData->nMaxConvCount;
557 hConv--;
558 while( hConv > 0 )
560 if( pPtr->hConvList == hConvList )
562 rhConv = hConv;
563 return pPtr;
565 pPtr--;
566 hConv--;
568 rhConv = 0;
569 return 0;
572 // static
573 BOOL ImpDdeMgr::CheckConvListId( HCONVLIST hConvListId )
575 HAB hAB = WinQueryAnchorBlock( (HWND)hConvListId );
576 if( hAB )
577 return WinIsWindow( hAB, (HWND)hConvListId );
578 return FALSE;
580 HAB hAB = WinQueryAnchorBlock( (HWND)hConvListId );
581 if( hAB )
583 char aBuf[ 16 ];
584 WinQueryWindowText( (HWND)hConvListId, sizeof(aBuf), aBuf );
585 if( strcmp(aBuf, CONVLISTNAME ) == 0 )
586 return TRUE;
588 return FALSE;
592 // static
593 HCONV ImpDdeMgr::DdeQueryNextServer(HCONVLIST hConvList, HCONV hConvPrev)
595 if( !CheckConvListId( hConvList ) )
596 return (HCONV)0;
597 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
598 GetFirstServer( pData, hConvList, hConvPrev );
599 return hConvPrev;
602 // static
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();
613 if ( !pData )
615 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
616 return FALSE;
618 ImpHCONV* pConv = GetConvTable(pData) + (USHORT)hConv;
620 if( (USHORT)hConv >= pData->nMaxConvCount || pConv->hWndThis==0 )
622 nLastErrInstance = DMLERR_NO_CONV_ESTABLISHED;
623 return FALSE;
626 PID pidApp; TID tid;
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
663 wurden.
665 WRITELOG("DdeDisconnect:Waiting for acknowledge...")
666 WinDdePostMsg( hWndPartner, hWndThis, WM_DDE_TERMINATE,
667 (PDDESTRUCT)0,DDEPM_RETRY);
669 QMSG aQueueMsg;
670 BOOL bContinue = TRUE;
671 while( bContinue )
673 if( WinGetMsg( hAB, &aQueueMsg, 0, 0, 0 ))
675 WinDispatchMsg( hAB, &aQueueMsg );
676 if( (!WinIsWindow( hAB, hWndPartner)) ||
677 (pConv->nStatus & ST_TERMACKREC) )
679 bContinue = FALSE;
680 if( pConv->nStatus & ST_TERMACKREC )
682 WRITELOG("DdeDisconnect: TermAck received")
684 else
686 WRITELOG("DdeDisconnect: Partner died")
690 else
691 bContinue = FALSE;
694 WinStopTimer( hAB, 0, nTimerId );
696 // WRITELOG("DdeDisconnect:Freeing data")
697 // Transaktionstabelle aufraeumen
698 FreeTransactions( pData, hConv );
699 if( hConvPartner )
700 FreeTransactions( pData, hConvPartner );
702 FreeConvHandle( pData, hConv );
704 WRITELOG("DdeDisconnect:End")
705 //WRITESTATUS("DdeDisconnect:End")
706 return TRUE;
709 // static
710 BOOL ImpDdeMgr::DdeDisconnectList( HCONVLIST hConvList )
712 if( !CheckConvListId( hConvList ) )
714 ImpDdeMgr::nLastErrInstance = DMLERR_INVALIDPARAMETER;
715 return FALSE;
718 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
719 if ( !pData )
721 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
722 return FALSE;
724 HCONV hConv = 0;
725 GetFirstServer( pData, hConvList, hConv );
726 while( hConv )
728 DdeDisconnect( hConv );
729 GetFirstServer( pData, hConvList, hConv );
731 WinDestroyWindow( (HWND)hConvList );
732 return TRUE;
737 // static
738 HCONV ImpDdeMgr::DdeReconnect(HCONV hConv)
740 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
741 if ( !pData )
743 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
744 return 0;
746 return 0;
749 // static
750 USHORT ImpDdeMgr::DdeQueryConvInfo(HCONV hConv, ULONG nTransId, CONVINFO* pCI)
752 if( !pCI || pCI->nSize == 0)
753 return 0;
754 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
755 if ( !pData )
757 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
758 return 0;
760 Transaction* pTrans;
761 if( nTransId != QID_SYNC )
763 pTrans = ImpDdeMgr::GetTransTable( pData );
764 pTrans += nTransId;
765 if( nTransId >= pData->nMaxTransCount || pTrans->hConvOwner == 0 )
767 ImpDdeMgr::nLastErrInstance = DMLERR_UNFOUND_QUEUE_ID;
768 return 0;
771 else
772 pTrans = 0;
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;
779 return 0;
782 USHORT nSize = pCI->nSize;
783 if( nSize > sizeof(CONVINFO) )
784 nSize = sizeof(CONVINFO);
785 CONVINFO aTempInfo;
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;
795 if( pTrans )
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 );
806 return nSize;
809 // static
810 BOOL ImpDdeMgr::DdeSetUserHandle(HCONV hConv, ULONG nTransId, ULONG hUser)
812 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
813 if ( !pData )
815 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
816 return FALSE;
818 Transaction* pTrans = GetTransTable( pData );
819 pTrans += nTransId;
820 if( !nTransId || !hConv || nTransId >= pData->nMaxTransCount ||
821 pTrans->hConvOwner != hConv )
823 ImpDdeMgr::nLastErrInstance = DMLERR_INVALIDPARAMETER;
824 return FALSE;
826 if( !pTrans->hConvOwner)
828 ImpDdeMgr::nLastErrInstance = DMLERR_UNFOUND_QUEUE_ID;
829 return FALSE;
831 pTrans->nUser = hUser;
832 return TRUE;
835 BOOL ImpDdeMgr::DdeAbandonTransaction( HCONV hConv, ULONG nTransId )
837 ////WRITELOG("DdeAbandonTransaction:Start")
838 if( !pData )
840 nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
841 return FALSE;
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;
849 return FALSE;
851 if( !hConv )
853 DBG_ASSERT(0,"DdeAbandonTransaction:NULL-hConv not supported");
854 nLastErrInstance = DMLERR_INVALIDPARAMETER;
855 return FALSE;
857 Transaction* pTrans = pTransTable;
858 pTrans += (USHORT)nTransId;
859 if( pTrans->hConvOwner != hConv )
861 nLastErrInstance = DMLERR_UNFOUND_QUEUE_ID;
862 return FALSE;
865 if( bInSyncTrans && nTransId == nSyncTransId )
867 bSyncAbandonTrans = TRUE;
868 return 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);
893 #else
894 DDESTRUCT* pOutDDEData = MakeDDEObject( pConv->hWndPartner,
895 pTrans->hszItem, 0, 0 /*pTrans->nFormat*/, 0, 0);
896 #endif
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")
903 return FALSE;
905 #ifdef SO_DDE_ABANDON_TRANSACTION_WAIT_ACK
906 WaitTransState( pTrans, nTransId, XST_UNADVACKRCVD, 0 );
907 #else
908 pTrans->nConvst = XST_UNADVACKRCVD;
909 #endif
911 #endif // DEUTSCHE_BANK
913 WRITELOG("DdeAbandTrans:Ack received->Freeing transaction")
914 FreeTransaction( pData, nTransId );
916 WRITELOG("DdeAbandonTransaction:End")
917 return TRUE;
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)
933 #endif
935 Transaction* pTrans = pTransTable;
936 pTrans++;
937 USHORT nCurTrans = 1;
938 USHORT nUsedTransactions = pData->nCurTransCount;
939 while( nUsedTransactions && nCurTrans < pData->nMaxTransCount )
941 HCONV hOwner = pTrans->hConvOwner;
942 if( hOwner )
944 nUsedTransactions--;
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;
958 pConv = pConvTable;
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)
969 #endif
970 DDESTRUCT* pOutDDEData;
971 if ( pTrans->nType & XTYPF_NODATA )
973 // Warm link
974 ////WRITELOG("DdePostAdvise:Warm link found")
975 pOutDDEData = MakeDDEObject( hWndClient, hszItem,
976 DDE_FNODATA, pTrans->nFormat, 0, 0 );
978 else
980 // Hot link
981 ////WRITELOG("DdePostAdvise:Hot link found")
982 pOutDDEData = Callback( XTYP_ADVREQ,
983 pTrans->nFormat, hOwner, hszTopic,
984 hszItem, (HDDEDATA)0, 1, 0 );
986 if( pOutDDEData )
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);
992 if( bSuccess )
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);
1003 else
1005 ////WRITELOG("DdePostAdvise:PostMsg failed")
1006 nLastErrInstance = DMLERR_POSTMSG_FAILED;
1009 else
1011 ////WRITELOG("DdePostAdvise:No data to send")
1016 nCurTrans++;
1017 pTrans++;
1019 ////WRITELOG("DdePostAdvise:End")
1020 return TRUE;
1023 BOOL ImpDdeMgr::DdeEnableCallback( HCONV hConv, USHORT wCmd)
1025 return FALSE;
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 )
1033 return 0;
1034 for( ULONG nIdx = 0; nIdx < nServiceCount; nIdx++, pPtr++ )
1036 if(( hszService == pPtr->hBaseServName ) ||
1037 ( hszService == pPtr->hInstServName ) )
1038 return pPtr;
1040 return 0;
1044 // legt Service in Service-Tabelle ab. Tabelle wird ggf. expandiert
1045 ImpService* ImpDdeMgr::PutService( HSZ hszService )
1047 if( !pServices )
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;
1055 USHORT nCurPos = 0;
1056 while( pPtr )
1058 if( pPtr->hBaseServName == 0 )
1059 break;
1060 nCurPos++;
1061 if( nCurPos < nServiceCount )
1062 pPtr++;
1063 else
1064 pPtr = 0;
1066 if( !pPtr )
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) );
1072 #ifdef DBG_UTIL
1073 memset( pServices, 0, nServiceCount * sizeof(ImpService) );
1074 #endif
1075 delete pServices;
1076 pServices = pPtr;
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 );
1090 aStr += pBuf;
1091 HSZ hszInstServ = DdeCreateStringHandle( (PSZ)(const char*)pBuf, 850 );
1092 delete pBuf;
1094 pPtr->hBaseServName = hszService;
1095 pPtr->hInstServName = hszInstServ;
1096 return pPtr;
1099 void ImpDdeMgr::BroadcastService( ImpService* pService, BOOL bRegistered )
1101 DBG_ASSERT(pService,"DDE:No Service");
1102 if( !pService )
1103 return;
1104 MPARAM aMp1 = (MPARAM)(pService->hBaseServName);
1105 MPARAM aMp2 = (MPARAM)(pService->hInstServName);
1106 ULONG nMsg;
1107 if( bRegistered )
1108 nMsg = WM_DDEML_REGISTER;
1109 else
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);
1131 if( bRegister )
1133 if( !pService )
1135 pService = PutService( hszService );
1136 BroadcastService( pService, TRUE );
1139 else
1141 if( pService )
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
1151 return hRet;
1155 // static
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);
1170 #endif
1172 if( pResult )
1173 *pResult = 0;
1175 ImpDdeMgrData* pData = ImpDdeMgr::AccessMgrData();
1176 if ( !pData )
1178 ImpDdeMgr::nLastErrInstance = DMLERR_DLL_NOT_INITIALIZED;
1179 return (HDDEDATA)0;
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 )
1193 bSync = TRUE;
1195 // Mapping transaction -> OS/2-Message
1196 USHORT nTimeoutErr, nMsg;
1197 switch ( nType )
1199 case XTYP_ADVSTART:
1200 nMsg = WM_DDE_ADVISE;
1201 nTimeoutErr = DMLERR_ADVACKTIMEOUT;
1203 nTimeout = 60000;
1204 #if 0 && defined(OV_DEBUG)
1205 char aBuf[ 128 ];
1206 ImpDdeMgr::DdeQueryString( hszItem,aBuf,127,850);
1207 String aXXStr("Establishing hotlink ");
1208 aXXStr += aBuf;
1209 WRITELOG((char*)aXXStr.GetStr());
1210 #endif
1213 break;
1215 case XTYP_ADVSTOP:
1216 nMsg = WM_DDE_UNADVISE;
1217 nTimeoutErr = DMLERR_UNADVACKTIMEOUT;
1218 break;
1220 case XTYP_REQUEST:
1221 nMsg = WM_DDE_REQUEST;
1222 nTimeoutErr = DMLERR_DATAACKTIMEOUT;
1223 break;
1225 case XTYP_POKE:
1226 nMsg = WM_DDE_POKE;
1227 nTimeoutErr = DMLERR_POKEACKTIMEOUT;
1228 break;
1230 case XTYP_EXECUTE:
1231 nMsg = WM_DDE_EXECUTE;
1232 nTimeoutErr = DMLERR_EXECACKTIMEOUT;
1233 break;
1235 default:
1236 nMsg = 0;
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 );
1245 return (HDDEDATA)0;
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 );
1261 return (HDDEDATA)0;
1264 Transaction* pTrans;
1266 BOOL bReqOnAdvLoop = FALSE;
1267 ULONG nTransId = GetTransaction( pData, hConv, hszItem, nFormat );
1268 if( nTransId )
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 );
1286 return (HDDEDATA)0;
1288 else if( nTransType == XTYP_ADVREQ )
1290 switch( nType )
1292 case XTYP_ADVSTOP:
1293 //WRITELOG("DdeClientTransaction:Stopping advise trans")
1294 pTrans->nType = XTYP_ADVSTOP;
1295 break;
1297 case XTYP_ADVSTART:
1298 //WRITELOG("DdeClientTransaction:Adj. Advise-Params")
1299 pTrans->nType = XTYP_ADVREQ;
1300 if( bNoData )
1301 pTrans->nType |= XTYPF_NODATA;
1302 if( bAckReq )
1303 pTrans->nType |= XTYPF_ACKREQ;
1304 if( pResult )
1305 *pResult = nTransId;
1306 return (HDDEDATA)TRUE;
1308 case XTYP_REQUEST:
1309 // WRITELOG("DdeClientTransaction:Using adv trans for req")
1310 // nConvst wird unten auf XST_WAITING_REQDATA gesetzt
1311 bReqOnAdvLoop = TRUE;
1312 break;
1314 default:
1315 WRITELOG("DdeClientTransaction:Invalid parameter")
1316 ImpDdeMgr::nLastErrInstance = DMLERR_INVALIDPARAMETER;
1317 if( bIsDdeHandle && !bAppOwnsHandle )
1318 DdeFreeDataHandle( (HDDEDATA)pDdeData );
1319 return (HDDEDATA)FALSE;
1323 else
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;
1339 if( bIsDdeHandle )
1341 if( bAppOwnsHandle )
1343 // wir muessen leider leider duplizieren, da uns OS/2
1344 // keine Chance laesst, diesen Status im Datenobjekt
1345 // zu versenken.
1346 ////WRITELOG("DdeClientTransaction:Copying handle")
1347 HDDEDATA pNew;
1348 HDDEDATA pData = (HDDEDATA)pDdeData;
1349 if( !(MyDosAllocSharedMem((PPVOID)&pNew, NULL, pData->cbData,
1350 PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | OBJ_ANY,
1351 "MakeDDEObject")))
1353 memcpy( pNew, pData, pData->cbData );
1354 pOutDDEData = pNew;
1356 else
1358 WRITELOG("DdeClientTransaction:No Memory")
1359 ImpDdeMgr::nLastErrInstance = DMLERR_LOW_MEMORY;
1360 return (HDDEDATA)0;
1363 else
1364 pOutDDEData = (HDDEDATA)pDdeData;
1366 else
1367 pOutDDEData=MakeDDEObject(hWndServer,hszItem,0,nFormat,pDdeData,cbData);
1369 pOutDDEData->fsStatus |= nTypeFlags;
1371 HDDEDATA pDDEInData = 0;
1372 if( bSync )
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,
1385 DDEPM_RETRY) )
1387 WRITELOG("DdeClientTransaction:PostMsg failed")
1388 nLastErrInstance = DMLERR_POSTMSG_FAILED;
1389 if( !bReqOnAdvLoop )
1390 FreeTransaction( pData, nTransId );
1391 else
1393 DBG_ASSERT(pTrans->nType==XTYP_ADVREQ,"DDE:Error!")
1394 pTrans->nConvst = 0;
1396 return FALSE;
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 );
1402 QMSG aQueueMsg;
1403 BOOL bLoop = TRUE;
1404 while( bLoop )
1406 if( pThis->nSyncResponseMsg )
1407 bLoop = FALSE;
1408 else
1410 if( WinGetMsg(hAB,&aQueueMsg,0,0,0 ))
1412 WinDispatchMsg( hAB, &aQueueMsg );
1414 else
1415 bLoop = FALSE;
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")
1431 return 0;
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!")
1443 return (HDDEDATA)0;
1445 switch( nMsg )
1447 case WM_TIMER:
1448 WRITELOG("DdeClientTransaction:Timeout!")
1449 nLastErrInstance = nTimeoutErr;
1450 if( bReqOnAdvLoop )
1451 // auf normalen Loop-Betrieb zurueckschalten
1452 pTrans->nConvst = XST_WAITING_ADVDATA;
1453 break;
1455 case WM_DDE_ACK:
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)
1465 char aBuf[ 128 ];
1466 ImpDdeMgr::DdeQueryString( pTrans->hszItem,aBuf,128,850);
1467 String aXXStr("Hotlink ");
1468 #endif
1470 if( bPositive )
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 ";
1480 aXXStr += aBuf;
1481 #endif
1485 #if 0 && defined(OV_DEBUG)
1486 else
1488 aXXStr += "failed ";
1489 aXXStr += aBuf;
1491 WRITELOG((char*)aXXStr.GetStr());
1492 #endif
1496 break;
1498 case WM_DDE_DATA:
1499 // WRITELOG("DdeClientTransaction:Data received")
1500 // WRITEDATA(pDDEInData)
1501 if( bReqOnAdvLoop )
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;
1508 break;
1510 default:
1511 WRITELOG("DdeClientTransaction:Unexpected msg")
1512 MyDosFreeMem( pDDEInData,"DdeClientTransaction" );
1513 pDDEInData = 0;
1515 pThis->bSyncAbandonTrans = FALSE;
1516 pThis->bInSyncTrans = FALSE;
1517 if( pThis->bSyncAbandonTrans && bReqOnAdvLoop )
1518 pThis->DdeAbandonTransaction( hConv, nTransId );
1520 else
1522 // WRITELOG("DdeClientTransaction:Starting async. trans.")
1523 pDDEInData = (HDDEDATA)MyWinDdePostMsg( hWndServer, hWndClient, nMsg,
1524 pOutDDEData, DDEPM_RETRY);
1525 if( !pDDEInData )
1527 WRITELOG("DdeClientTransaction:PostMsg failed")
1528 nLastErrInstance = DMLERR_POSTMSG_FAILED;
1529 if( !bReqOnAdvLoop )
1530 FreeTransaction( pData, nTransId );
1531 else
1533 DBG_ASSERT(pTrans->nType==XTYP_ADVREQ,"DDE:Error!")
1534 pTrans->nConvst = 0;
1537 else
1539 // WRITELOG("DdeClientTransaction:Async trans. success")
1540 if( pResult )
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);
1552 #endif
1553 //WRITELOG("DdeClientTransaction:End")
1554 //WRITESTATUS("DdeClientTransaction:End")
1555 return pDDEInData;
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);
1567 return nRet;
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);
1579 return nRet;
1582 MRESULT ImpDdeMgr::DdeTimeout( ImpWndProcParams* pParams )
1584 ////WRITELOG("DdeTimeout:Received")
1585 if( nSyncResponseMsg )
1587 ////WRITELOG("DdeTimeout:Trans already processed->ignoring timeout")
1588 return (MRESULT)1;
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");
1598 return (MRESULT)1;
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=");
1615 aMsg += nTransId;
1616 WRITELOG((char*)(const char*)aMsg)
1617 #endif
1619 else
1621 ////WRITELOG("DdeTimeout:Async transaction timed out")
1622 pTrans->nConvst = XST_TIMEOUT;
1624 return (MRESULT)1;
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)
1640 #endif
1641 ImpHCONV* pConv = pConvTable + (USHORT)hConv;
1642 if( 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 );
1679 else
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")
1691 #endif
1693 if( hConv )
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")
1703 #ifdef OV_DEBUG
1704 DBG_ASSERT(WinIsWindow( 0, hWndThis ),"hWndThis not valid");
1705 #endif
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 );
1714 return (MRESULT)0;
1719 Zuordnung des Conversationhandles:
1721 Verbindungsaufbau:
1722 Client: DdeInitiate( HWNDClient )
1723 Server: Post( WM_DDE_INITIATEACK( HWNDServer ))
1724 Client: CreateConvHandle( HWNDClient, HWNDServer )
1726 Datenaustausch:
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;
1740 switch( nMsg )
1743 #ifdef DBG_UTIL
1744 case WM_DDE_INITIATE :
1745 DBG_ASSERT(0,"dde:unexpected msg");
1746 nRet = (MRESULT)TRUE;
1747 break;
1748 #endif
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;
1761 return nRet;
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;
1773 switch( nMsg )
1775 #ifdef DBG_UTIL
1776 case WM_DDE_ACK :
1777 case WM_DDE_ADVISE :
1778 case WM_DDE_EXECUTE :
1779 case WM_DDE_POKE :
1780 case WM_DDE_REQUEST :
1781 case WM_DDE_UNADVISE :
1782 case WM_DDE_DATA :
1783 case WM_DDE_INITIATEACK :
1784 DBG_ASSERT(0,"dde:unexpected msg");
1785 nRet = (MRESULT)TRUE;
1786 break;
1787 #endif
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 );
1795 break;
1797 // eine ddeml-faehige App. hat einen Service (typ. AppName) [de]reg.
1798 case WM_DDEML_REGISTER :
1799 nRet = DdeRegister( &aParams );
1800 break;
1802 case WM_DDEML_UNREGISTER :
1803 nRet = DdeUnregister( &aParams );
1804 break;
1806 return nRet;
1810 MRESULT ImpDdeMgr::DdeAck( ImpWndProcParams* pParams )
1812 //WRITELOG("DdeAck:Start")
1813 HSZ hszItem;
1814 DDESTRUCT* pInDDEData = (DDESTRUCT*)(pParams->nPar2);
1815 if( pInDDEData )
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 ");
1822 if( bPositive )
1823 aDebStr += "(positive)";
1824 else
1825 aDebStr += "(negative)";
1826 if( bBusy )
1827 aDebStr += "(busy)";
1828 if( bNotProcessed )
1829 aDebStr += "(not processed)";
1830 WRITELOG((char*)(const char*)aDebStr)
1831 #endif
1832 // ein DDE_ACK niemals bestaetigen (um endlosschleifen zu vermeiden)
1833 pInDDEData->fsStatus &= (~DDE_FACKREQ);
1835 else
1837 //WRITELOG("DdeAck:Received (no data!)")
1838 return (MRESULT)0;
1841 HCONV hConv = CheckIncoming(pParams, 0, hszItem);
1842 #ifdef OV_DEBUG
1843 if( !hConv )
1845 WRITELOG("DdeAck:HCONV not found")
1847 #endif
1848 ULONG nTransId=GetTransaction(pData,hConv,hszItem,pInDDEData->usFormat);
1849 if( !nTransId )
1851 WRITELOG("DdeAck:Transaction not found")
1852 MyDosFreeMem( pInDDEData,"DdeAck" );
1853 return (MRESULT)0;
1856 BOOL bThisIsSync = (BOOL)( bInSyncTrans && nTransId == nSyncTransId );
1857 #if 0 && defined( OV_DEBUG )
1858 if( bThisIsSync)
1859 WRITELOG("DdeAck: sync transaction")
1860 else
1861 WRITELOG("DdeAck: async transaction")
1862 #endif
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 );
1875 return (MRESULT)0;
1877 if( pTrans->nConvst == XST_ADVDATASENT )
1879 //WRITELOG("DdeAck:AdvData-Ack received")
1880 pTrans->nConvst = XST_ADVDATAACKRCVD;
1881 MyDosFreeMem( pInDDEData,"DdeAck" );
1882 DdeFreeStringHandle( hszItem );
1883 return (MRESULT)0;
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)) );
1892 if( bFinished )
1894 if( !bThisIsSync )
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 );
1904 if( bThisIsSync )
1906 hSyncResponseData = pInDDEData;
1907 nSyncResponseMsg = WM_DDE_ACK;
1909 else
1911 MyDosFreeMem( pInDDEData,"DdeAck" );
1914 DdeFreeStringHandle( hszItem );
1916 return (MRESULT)0;
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())
1929 #endif
1932 // wenn wir weder loeschen noch die App benachrichtigen sollen,
1933 // koennen wir gleich wieder returnen
1934 if( !hConvServer || ( !bFree && !bCallApp ) )
1935 return 0;
1937 ImpHCONV* pConvSrv = pConvTable;
1938 pConvSrv += (USHORT)hConvServer;
1939 HSZ hszTopic = pConvSrv->hszTopic;
1941 Transaction* pTrans = pTransTable;
1942 pTrans++;
1943 USHORT nCurTransId = 1;
1944 USHORT nCurTransactions = pData->nCurTransCount;
1945 while( nCurTransactions && nCurTransId < pData->nMaxTransCount )
1947 if( pTrans->hConvOwner )
1948 nCurTransactions--;
1949 if( pTrans->hConvOwner == hConvServer &&
1950 (pTrans->nType & XTYP_ADVREQ) )
1952 if( !nFormat || (nFormat == pTrans->nFormat) )
1954 nTransFound++;
1955 if( bCallApp )
1957 //WRITELOG("SendUnadvises:Notifying App")
1958 Callback( XTYP_ADVSTOP, pTrans->nFormat, hConvServer,
1959 hszTopic, pTrans->hszItem, 0,0,0 );
1961 if( bFree )
1962 FreeTransaction( pData, (ULONG)nCurTransId );
1965 nCurTransId++;
1966 pTrans++;
1968 return nTransFound;
1973 HCONV ImpDdeMgr::CheckIncoming( ImpWndProcParams* pParams, ULONG nTransMask,
1974 HSZ& rhszItem )
1976 // ////WRITELOG("CheckIncoming")
1977 rhszItem = 0;
1978 DDESTRUCT* pInDDEData = (DDESTRUCT*)(pParams->nPar2);
1979 if( !pInDDEData )
1981 // ////WRITELOG("CheckIncoming:PDDESTRUCT==0")
1982 return (HCONV)0;
1985 HWND hWndThis = pParams->hWndReceiver;
1986 HWND hWndClient = (HWND)pParams->nPar1;
1988 BOOL bReject = (BOOL)(nTransactFilter & nTransMask);
1989 HCONV hConv;
1990 if( !bReject )
1991 hConv = GetConvHandle( pData, hWndThis, hWndClient );
1992 if ( bReject || !hConv )
1993 return (HCONV)0;
1995 rhszItem = DdeCreateStringHandle(
1996 ((char*)(pInDDEData)+pInDDEData->offszItemName), 850 );
1998 // ////WRITELOG("CheckIncoming:OK");
1999 return hConv;
2003 MRESULT ImpDdeMgr::DdeAdvise( ImpWndProcParams* pParams )
2005 ////WRITELOG("DdeAdvise:Received")
2006 HSZ hszItem;
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;
2011 if( !hConv )
2013 ////WRITELOG("DdeAdvise:Conversation not found")
2014 pInDDEData->fsStatus &= (~DDE_FACK);
2015 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2016 DdeFreeStringHandle( hszItem );
2017 return (MRESULT)0;
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);
2027 if( nTransId )
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 );
2046 return (MRESULT)0;
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 );
2054 return (MRESULT)0;
2058 if( !nTransId )
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")
2066 if( nTransId )
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;
2075 else
2077 ////WRITELOG("DdeAdvise:Cannot create Transaction")
2078 pInDDEData->fsStatus &= (~DDE_FACK);
2079 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2080 DdeFreeStringHandle( hszItem );
2081 return (MRESULT)0;
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);
2096 else
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 );
2106 return (MRESULT)0;
2109 MRESULT ImpDdeMgr::DdeData( ImpWndProcParams* pParams )
2111 WRITELOG("DdeData:Received")
2112 HSZ hszItem;
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())
2123 #endif
2125 BOOL bSendAck;
2126 if( pInDDEData && (pInDDEData->fsStatus & DDE_FACKREQ ))
2128 WRITELOG("DdeData: Ackn requested")
2129 bSendAck = TRUE;
2131 else
2133 WRITELOG("DdeData: Ackn not requested")
2134 bSendAck = FALSE;
2137 ULONG nTransId = GetTransaction(pData,hConv,hszItem,pInDDEData->usFormat);
2138 if( !nTransId )
2140 WRITELOG("DdeData:Transaction not found")
2141 WRITEDATA(pInDDEData)
2142 if( bSendAck )
2144 WRITELOG("DdeData: Posting Ackn")
2145 pInDDEData->fsStatus &= (~DDE_FACK); // NOTPROCESSED;
2146 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2148 else
2150 MyDosFreeMem( pInDDEData,"DdeData" );
2152 return (MRESULT)0;
2155 #if 0 && defined( OV_DEBUG )
2156 if( pInDDEData )
2158 WRITEDATA(pInDDEData)
2160 #endif
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")
2174 if( bSendAck )
2176 WRITELOG("DdeData: Posting Ackn")
2177 pInDDEData->fsStatus &= (~DDE_FACK); // NOTPROCESSED;
2178 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2180 else
2182 MyDosFreeMem( pInDDEData,"DdeData" );
2184 return (MRESULT)0;
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)));
2193 if( !bThisIsSync )
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 );
2204 else
2206 WRITELOG("DdeData:Advise-Loop -> calling client")
2207 HDDEDATA pToSend = pInDDEData;
2208 if( pTrans->nType & XTYPF_NODATA )
2210 pToSend = 0;
2211 // WRITELOG("DdeData:Is warm link")
2213 Callback( XTYP_ADVDATA, pInDDEData->usFormat, hConv,
2214 pConv->hszTopic, hszItem, pToSend, nTransId, 0 );
2216 if( bSendAck )
2218 WRITELOG("DdeData: Posting Ackn")
2219 pInDDEData->fsStatus = DDE_FACK;
2220 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2222 else
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;
2230 if( bSendAck )
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")
2241 return (MRESULT)0;
2244 MRESULT ImpDdeMgr::DdeExecute( ImpWndProcParams* pParams )
2246 ////WRITELOG("DdeExecute:Received")
2247 DDESTRUCT* pInDDEData = (DDESTRUCT*)(pParams->nPar2);
2248 HSZ hszItem;
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 )
2258 bSuccess = TRUE;
2260 else
2262 ////WRITELOG("DdeExecute:Not processed")
2264 if( pInDDEData )
2266 if( bSuccess )
2267 pInDDEData->fsStatus |= DDE_FACK;
2268 else
2269 pInDDEData->fsStatus &= (~DDE_FACK);
2270 MyWinDdePostMsg( pConv->hWndPartner, pConv->hWndThis, WM_DDE_ACK,
2271 pInDDEData, DDEPM_RETRY );
2273 DdeFreeStringHandle( hszItem );
2274 return (MRESULT)0;
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 );
2286 if(!hConv )
2287 return 0;
2288 BOOL bFreeDdeData = FALSE;
2289 if( !pDDEData )
2291 bFreeDdeData = TRUE;
2292 pDDEData = CreateDDEInitData( hWndClient,hszService,hszTopic, pCC );
2293 PID pid; TID tid;
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")
2303 if( bFreeDdeData )
2305 MyDosFreeMem( pDDEData,"ConnectWithClient" );
2307 FreeConvHandle( pData, hConv );
2308 return (HCONV)0;
2311 if( !(nTransactFilter & CBF_SKIP_CONNECT_CONFIRMS) )
2313 Callback( XTYP_CONNECT_CONFIRM, 0, hConv, hszTopic, hszService,
2314 0, 0, (ULONG)bSameInst );
2317 if( bFreeDdeData )
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")
2330 #endif
2331 pConv->nStatus = ST_CONNECTED;
2332 //WRITESTATUS("Server:Connected with client")
2333 //WRITELOG("ConnectWithClient:End")
2334 return hConv;
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 );
2383 else
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 );
2391 if( hList )
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)
2400 pPairs++;
2402 DdeFreeDataHandle( hList );
2406 #if 0 && defined(OV_DEBUG)
2407 else
2409 WRITELOG("DdeInitiate:Service filtered")
2411 #endif
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;
2454 if( bListConnect )
2456 ////WRITELOG("DdeInitiateAck:ListConnect/Connecting hConvs")
2457 // Status setzen & verketten
2458 pConv->hConvList = hCurListId;
2459 pConv->nPrevHCONV = nPrevConv;
2460 pConv->nStatus |= ST_INLIST;
2461 if( nPrevConv )
2463 pConv = pConvTable;
2464 pConv += nPrevConv;
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")
2482 HSZ hszItem = 0;
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 )
2493 bSuccess = TRUE;
2495 #if 0 && defined( OV_DEBUG )
2496 else
2498 WRITELOG("DdePoke:Not processed")
2500 #endif
2501 if( pInDDEData )
2503 if( bSuccess )
2504 pInDDEData->fsStatus |= DDE_FACK;
2505 else
2506 pInDDEData->fsStatus &= (~DDE_FACK);
2508 MyWinDdePostMsg( pConv->hWndPartner, pConv->hWndThis, WM_DDE_ACK,
2509 pInDDEData, DDEPM_RETRY );
2511 DdeFreeStringHandle( hszItem );
2512 return (MRESULT)0;
2515 MRESULT ImpDdeMgr::DdeRequest( ImpWndProcParams* pParams )
2517 ////WRITELOG("DdeRequest:Received")
2518 HSZ hszItem = 0;
2519 DDESTRUCT* pInDDEData = (DDESTRUCT*)(pParams->nPar2);
2520 if( pInDDEData )
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;
2526 if( hConv )
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 );
2534 if ( !pOutDDEData )
2536 ////WRITELOG("DdeRequest:Not processed")
2537 pInDDEData->fsStatus &= (~DDE_FACK);
2538 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2540 else
2542 ////WRITELOG("DdeRequest:Success")
2543 MyDosFreeMem( pInDDEData,"DdeRequest" );
2544 pOutDDEData->fsStatus |= DDE_FRESPONSE;
2545 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_DATA,pOutDDEData,DDEPM_RETRY);
2548 else
2550 pInDDEData->fsStatus &= (~DDE_FACK);
2551 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2554 DdeFreeStringHandle( hszItem );
2555 ////WRITELOG("DdeRequest:End")
2556 return (MRESULT)0;
2560 MRESULT ImpDdeMgr::DdeUnadvise( ImpWndProcParams* pParams )
2562 ////WRITELOG("DdeUnadvise:Received")
2564 HSZ hszItem;
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;
2570 if( hConv )
2572 USHORT nFormat = pInDDEData->usFormat;
2573 // alle Transaktionen des HCONVs loeschen ?
2574 if( !hszItem )
2576 // App benachrichtigen & Transaktionen loeschen
2577 nClosedTransactions = SendUnadvises( hConv, nFormat, TRUE );
2579 else
2581 ULONG nTransId = GetTransaction(pData, hConv, hszItem, nFormat);
2582 if( nTransId )
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)
2597 else
2599 WRITELOG("DdeUnadvise:Transaction not found")
2601 #endif
2604 #if defined(OV_DEBUG)
2605 else
2607 WRITELOG("DdeUnadvise:Conversation not found")
2609 #endif
2611 if( !nClosedTransactions )
2612 pInDDEData->fsStatus &= (~DDE_FACK);
2613 else
2614 pInDDEData->fsStatus |= DDE_FACK;
2616 MyWinDdePostMsg(hWndClient,hWndThis,WM_DDE_ACK,pInDDEData,DDEPM_RETRY);
2617 DdeFreeStringHandle( hszItem );
2618 return (MRESULT)0;
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 );
2629 QMSG aQueueMsg;
2631 // while( WinGetMsg( hAB, &aQueueMsg, 0, 0, 0 ) &&
2632 // WinIsWindow( hAB, pConv->hWndPartner) &&
2633 // pTrans->nConvst != nNewState )
2634 // {
2635 // WinDispatchMsg( hAB, &aQueueMsg );
2636 // }
2638 BOOL bContinue = TRUE;
2639 while( bContinue )
2641 if( WinGetMsg( hAB, &aQueueMsg, 0, 0, 0 ))
2643 WinDispatchMsg( hAB, &aQueueMsg );
2644 if( (!WinIsWindow( hAB, pConv->hWndPartner)) ||
2645 (pTrans->nConvst == nNewState) )
2647 bContinue = FALSE;
2650 else
2651 bContinue = FALSE;
2654 WinStopTimer( hAB, 0, nTimerId );
2655 ////WRITELOG("WaitTransState:End")
2656 return TRUE;