xref: /AOO41X/main/svl/source/svdde/ddecli.cxx (revision 40df464ee80f942fd2baf5effc726656f4be12a0)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svl.hxx"
26 
27 #define UNICODE
28 #include <string.h> // memset
29 #include "ddeimp.hxx"
30 #include <svl/svdde.hxx>
31 
32 #include <osl/thread.h>
33 #include <tools/debug.hxx>
34 #include <tools/solarmutex.hxx>
35 #include <vos/mutex.hxx>
36 
37 // static DWORD        hDdeInst  = NULL;
38 // static short        nInstance = 0;
39 
40 // DdeConnections*     DdeConnection::pConnections = NULL;
41 
ImpInitInstData()42 DdeInstData* ImpInitInstData()
43 {
44     DdeInstData* pData = new DdeInstData;
45     memset( pData,0,sizeof(DdeInstData) );
46     DdeInstData** ppInst = (DdeInstData**)GetAppData( SHL_SVDDE );
47     *ppInst = pData;
48     return pData;
49 }
50 
ImpDeinitInstData()51 void ImpDeinitInstData()
52 {
53     DdeInstData** ppInst = (DdeInstData**)GetAppData( SHL_SVDDE );
54     delete (*ppInst);
55     *ppInst = 0;
56 }
57 
58 
59 struct DdeImp
60 {
61     HCONV   hConv;
62     long    nStatus;
63 };
64 
65 // --- DdeInternat::CliCallback() ----------------------------------
66 
CliCallback(WORD nCode,WORD nCbType,HCONV hConv,HSZ,HSZ hText2,HDDEDATA hData,DWORD nInfo1,DWORD)67 HDDEDATA CALLBACK DdeInternal::CliCallback(
68             WORD nCode, WORD nCbType, HCONV hConv, HSZ, HSZ hText2,
69             HDDEDATA hData, DWORD nInfo1, DWORD )
70 {
71     HDDEDATA nRet = DDE_FNOTPROCESSED;
72     DdeConnections&     rAll = (DdeConnections&)DdeConnection::GetConnections();
73     DdeConnection*      self = 0;
74 
75     DdeInstData* pInst = ImpGetInstData();
76     DBG_ASSERT(pInst,"SVDDE:No instance data");
77 
78     for ( self = rAll.First(); self; self = rAll.Next() )
79         if ( self->pImp->hConv == hConv )
80             break;
81 
82     if( self )
83     {
84         DdeTransaction* t;
85         sal_Bool bFound = sal_False;
86         for( t = self->aTransactions.First(); t; t = self->aTransactions.Next() )
87         {
88             switch( nCode )
89             {
90                 case XTYP_XACT_COMPLETE:
91                     if( (DWORD)t->nId == nInfo1 )
92                     {
93                         nCode = t->nType & (XCLASS_MASK | XTYP_MASK);
94                         t->bBusy = sal_False;
95                         t->Done( 0 != hData );
96                         bFound = sal_True;
97                     }
98                     break;
99 
100                 case XTYP_DISCONNECT:
101                     self->pImp->hConv = DdeReconnect( hConv );
102                     self->pImp->nStatus = self->pImp->hConv
103                                     ? DMLERR_NO_ERROR
104                                     : DdeGetLastError( pInst->hDdeInstCli );
105                     t = 0;
106                     nRet = 0;
107                     bFound = sal_True;
108                     break;
109 
110                 case XTYP_ADVDATA:
111                     bFound = sal_Bool( *t->pName == hText2 );
112                     break;
113             }
114             if( bFound )
115                 break;
116         }
117 
118         if( t )
119         {
120             switch( nCode )
121             {
122             case XTYP_ADVDATA:
123                 if( !hData )
124                 {
125                     ((DdeLink*) t)->Notify();
126                     nRet = (HDDEDATA)DDE_FACK;
127                     break;
128                 }
129                 // kein break;
130 
131             case XTYP_REQUEST:
132                 if( !hData && XTYP_REQUEST == nCode )
133                 {
134 
135                 }
136 
137                 DdeData d;
138                 d.pImp->hData = hData;
139                 d.pImp->nFmt  = DdeData::GetInternalFormat( nCbType );
140                 d.Lock();
141                 t->Data( &d );
142                 nRet = (HDDEDATA)DDE_FACK;
143                 break;
144             }
145         }
146     }
147     return nRet;
148 }
149 
150 // --- DdeConnection::DdeConnection() ------------------------------
151 
DdeConnection(const String & rService,const String & rTopic)152 DdeConnection::DdeConnection( const String& rService, const String& rTopic )
153 {
154     pImp = new DdeImp;
155     pImp->nStatus  = DMLERR_NO_ERROR;
156     pImp->hConv    = NULL;
157 
158     DdeInstData* pInst = ImpGetInstData();
159     if( !pInst )
160         pInst = ImpInitInstData();
161     pInst->nRefCount++;
162     pInst->nInstanceCli++;
163     if ( !pInst->hDdeInstCli )
164     {
165         pImp->nStatus = DdeInitialize( &pInst->hDdeInstCli,
166                                        (PFNCALLBACK)DdeInternal::CliCallback,
167                                        APPCLASS_STANDARD | APPCMD_CLIENTONLY |
168                                        CBF_FAIL_ALLSVRXACTIONS |
169                                        CBF_SKIP_REGISTRATIONS  |
170                                        CBF_SKIP_UNREGISTRATIONS, 0L );
171         pInst->pConnections = new DdeConnections;
172     }
173 
174     pService = new DdeString( pInst->hDdeInstCli, rService );
175     pTopic   = new DdeString( pInst->hDdeInstCli, rTopic );
176 
177     if ( pImp->nStatus == DMLERR_NO_ERROR )
178     {
179         pImp->hConv = DdeConnect( pInst->hDdeInstCli,*pService,*pTopic, NULL);
180         if( !pImp->hConv )
181             pImp->nStatus = DdeGetLastError( pInst->hDdeInstCli );
182     }
183 
184     if ( pInst->pConnections )
185         pInst->pConnections->Insert( this );
186 }
187 
188 // --- DdeConnection::~DdeConnection() -----------------------------
189 
~DdeConnection()190 DdeConnection::~DdeConnection()
191 {
192     if ( pImp->hConv )
193         DdeDisconnect( pImp->hConv );
194 
195     delete pService;
196     delete pTopic;
197 
198     DdeInstData* pInst = ImpGetInstData();
199     DBG_ASSERT(pInst,"SVDDE:No instance data");
200     if ( pInst->pConnections )
201         pInst->pConnections->Remove( this );
202 
203     pInst->nInstanceCli--;
204     pInst->nRefCount--;
205     if ( !pInst->nInstanceCli && pInst->hDdeInstCli )
206     {
207         if( DdeUninitialize( pInst->hDdeInstCli ) )
208         {
209             pInst->hDdeInstCli = NULL;
210             delete pInst->pConnections;
211             pInst->pConnections = NULL;
212             if( pInst->nRefCount == 0 )
213                 ImpDeinitInstData();
214         }
215     }
216     delete pImp;
217 }
218 
219 // --- DdeConnection::IsConnected() --------------------------------
220 
IsConnected()221 sal_Bool DdeConnection::IsConnected()
222 {
223     CONVINFO c;
224 #ifdef OS2
225     c.nSize = sizeof( c );
226 #else
227     c.cb = sizeof( c );
228 #endif
229     if ( DdeQueryConvInfo( pImp->hConv, QID_SYNC, &c ) )
230         return sal_True;
231     else
232     {
233         DdeInstData* pInst = ImpGetInstData();
234         pImp->hConv = DdeReconnect( pImp->hConv );
235         pImp->nStatus = pImp->hConv ? DMLERR_NO_ERROR : DdeGetLastError( pInst->hDdeInstCli );
236         return sal_Bool( pImp->nStatus == DMLERR_NO_ERROR );
237     }
238 }
239 
240 // --- DdeConnection::GetServiceName() -----------------------------
241 
GetServiceName()242 const String& DdeConnection::GetServiceName()
243 {
244     return (const String&)*pService;
245 }
246 
247 // --- DdeConnection::GetTopicName() -------------------------------
248 
GetTopicName()249 const String& DdeConnection::GetTopicName()
250 {
251     return (const String&)*pTopic;
252 }
253 
254 // --- DdeConnection::GetConvId() ----------------------------------
255 
GetConvId()256 long DdeConnection::GetConvId()
257 {
258     return (long)pImp->hConv;
259 }
260 
GetConnections()261 const DdeConnections& DdeConnection::GetConnections()
262 {
263     DdeInstData* pInst = ImpGetInstData();
264     DBG_ASSERT(pInst,"SVDDE:No instance data");
265     return *(pInst->pConnections);
266 }
267 
268 // --- DdeTransaction::DdeTransaction() ----------------------------
269 
DdeTransaction(DdeConnection & d,const String & rItemName,long n)270 DdeTransaction::DdeTransaction( DdeConnection& d, const String& rItemName,
271                                 long n ) :
272                     rDde( d )
273 {
274     DdeInstData* pInst = ImpGetInstData();
275     pName = new DdeString( pInst->hDdeInstCli, rItemName );
276     nTime = n;
277     nId   = 0;
278     nType = 0;
279     bBusy = sal_False;
280 
281     rDde.aTransactions.Insert( this );
282 }
283 
284 // --- DdeTransaction::~DdeTransaction() ---------------------------
285 
~DdeTransaction()286 DdeTransaction::~DdeTransaction()
287 {
288     if ( nId && rDde.pImp->hConv )
289     {
290         DdeInstData* pInst = ImpGetInstData();
291         DdeAbandonTransaction( pInst->hDdeInstCli, rDde.pImp->hConv, nId );
292     }
293 
294     delete pName;
295     rDde.aTransactions.Remove( this );
296 }
297 
298 // --- DdeTransaction::Execute() -----------------------------------
299 
Execute()300 void DdeTransaction::Execute()
301 {
302     HSZ     hItem = *pName;
303     void*   pData = (void*)(const void *)aDdeData;
304     DWORD   nData = (DWORD)(long)aDdeData;
305     sal_uLong   nIntFmt = aDdeData.pImp->nFmt;
306     UINT    nExtFmt  = DdeData::GetExternalFormat( nIntFmt );
307     DdeInstData* pInst = ImpGetInstData();
308 
309     if ( nType == XTYP_EXECUTE )
310         hItem = NULL;
311     if ( nType != XTYP_EXECUTE && nType != XTYP_POKE )
312     {
313         pData = NULL;
314         nData = 0L;
315     }
316     if ( nTime )
317     {
318         HDDEDATA hData = DdeClientTransaction( (unsigned char*)pData,
319                                                nData, rDde.pImp->hConv,
320                                                hItem, nExtFmt, (UINT)nType,
321                                                (DWORD)nTime, (DWORD FAR*)NULL );
322 
323         rDde.pImp->nStatus = DdeGetLastError( pInst->hDdeInstCli );
324         if( hData && nType == XTYP_REQUEST )
325         {
326             {
327                 DdeData d;
328                 d.pImp->hData = hData;
329                 d.pImp->nFmt = nIntFmt;
330                 d.Lock();
331                 Data( &d );
332             }
333             DdeFreeDataHandle( hData );
334         }
335     }
336     else
337     {
338         if ( nId && rDde.pImp->hConv )
339             DdeAbandonTransaction( pInst->hDdeInstCli, rDde.pImp->hConv, nId);
340         nId = 0;
341         bBusy = sal_True;
342         HDDEDATA hRet = DdeClientTransaction( (unsigned char*)pData, nData,
343                                             rDde.pImp->hConv, hItem, nExtFmt,
344                                             (UINT)nType, TIMEOUT_ASYNC,
345                                             (DWORD FAR *) ((long*) &nId) );
346         rDde.pImp->nStatus = hRet ? DMLERR_NO_ERROR
347                                   : DdeGetLastError( pInst->hDdeInstCli );
348     }
349 }
350 
351 // --- DdeTransaction::GetName() -----------------------------------
352 
GetName() const353 const String& DdeTransaction::GetName() const
354 {
355     return *pName;
356 }
357 
358 // --- DdeTransaction::Data() --------------------------------------
359 
360 
Data(const DdeData * p)361 void __EXPORT DdeTransaction::Data( const DdeData* p )
362 {
363     if ( ::tools::SolarMutex::Acquire() )
364     {
365         aData.Call( (void*)p );
366         ::tools::SolarMutex::Release();
367     }
368 }
369 
370 // --- DdeTransaction::Done() --------------------------------------
371 
Done(sal_Bool bDataValid)372 void __EXPORT DdeTransaction::Done( sal_Bool bDataValid )
373 {
374     aDone.Call( (void*)bDataValid );
375 }
376 
377 // --- DdeLink::DdeLink() ------------------------------------------
378 
DdeLink(DdeConnection & d,const String & aItemName,long n)379 DdeLink::DdeLink( DdeConnection& d, const String& aItemName, long n ) :
380             DdeTransaction (d, aItemName, n)
381 {
382 }
383 
384 // --- DdeLink::~DdeLink() -----------------------------------------
385 
~DdeLink()386 DdeLink::~DdeLink()
387 {
388     nType = (sal_uInt16)XTYP_ADVSTOP;
389     nTime = 0;
390 }
391 
392 // --- DdeLink::Notify() -----------------------------------------
393 
Notify()394 void __EXPORT DdeLink::Notify()
395 {
396     aNotify.Call( NULL );
397 }
398 
399 // --- DdeRequest::DdeRequest() ------------------------------------
400 
DdeRequest(DdeConnection & d,const String & i,long n)401 DdeRequest::DdeRequest( DdeConnection& d, const String& i, long n ) :
402                 DdeTransaction( d, i, n )
403 {
404     nType = XTYP_REQUEST;
405 }
406 
407 // --- DdeWarmLink::DdeWarmLink() ----------------------------------
408 
DdeWarmLink(DdeConnection & d,const String & i,long n)409 DdeWarmLink::DdeWarmLink( DdeConnection& d, const String& i, long n ) :
410                 DdeLink( d, i, n )
411 {
412     nType = XTYP_ADVSTART | XTYPF_NODATA;
413 }
414 
415 // --- DdeHotLink::DdeHotLink() ------------------------------------
416 
DdeHotLink(DdeConnection & d,const String & i,long n)417 DdeHotLink::DdeHotLink( DdeConnection& d, const String& i, long n ) :
418                 DdeLink( d, i, n )
419 {
420     nType = XTYP_ADVSTART;
421 }
422 
423 // --- DdePoke::DdePoke() ------------------------------------------
424 
DdePoke(DdeConnection & d,const String & i,const char * p,long l,sal_uLong f,long n)425 DdePoke::DdePoke( DdeConnection& d, const String& i, const char* p,
426                   long l, sal_uLong f, long n ) :
427             DdeTransaction( d, i, n )
428 {
429     aDdeData = DdeData( p, l, f );
430     nType = XTYP_POKE;
431 }
432 
433 // --- DdePoke::DdePoke() ------------------------------------------
434 
DdePoke(DdeConnection & d,const String & i,const String & rData,long n)435 DdePoke::DdePoke( DdeConnection& d, const String& i, const String& rData,
436                   long n ) :
437             DdeTransaction( d, i, n )
438 {
439 //  ByteString aByteStr( rData, osl_getThreadTextEncoding() );
440     aDdeData = DdeData( (void*) rData.GetBuffer(), sizeof(sal_Unicode) * (rData.Len()), CF_TEXT );
441     nType = XTYP_POKE;
442 }
443 
444 // --- DdePoke::DdePoke() ------------------------------------------
445 
DdePoke(DdeConnection & d,const String & i,const DdeData & rData,long n)446 DdePoke::DdePoke( DdeConnection& d, const String& i, const DdeData& rData,
447                   long n ) :
448             DdeTransaction( d, i, n )
449 {
450     aDdeData = rData;
451     nType = XTYP_POKE;
452 }
453 
454 // --- DdeExecute::DdeExecute() ------------------------------------
455 
DdeExecute(DdeConnection & d,const String & rData,long n)456 DdeExecute::DdeExecute( DdeConnection& d, const String& rData, long n ) :
457                 DdeTransaction( d, String(), n )
458 {
459 //  ByteString aByteStr( rData, osl_getThreadTextEncoding() );
460     aDdeData = DdeData( (void*)rData.GetBuffer(), sizeof(sal_Unicode) * (rData.Len() + 1), CF_TEXT );
461     nType = XTYP_EXECUTE;
462 }
463 
464 // --- DdeConnection::GetError() -----------------------------------
465 
GetError()466 long DdeConnection::GetError()
467 {
468     return pImp->nStatus;
469 }
470