xref: /trunk/main/svl/source/svdde/ddecli.cxx (revision c4c57a27)
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 sal_uIntPtr DdeConnection::GetConvId()
257 {
258 	return (sal_uIntPtr)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