1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS user32.dll
4*c2c66affSColin Finck * PURPOSE: Dynamic Data Exchange
5*c2c66affSColin Finck * FILE: win32ss/user/user32/misc/dde.c
6*c2c66affSColin Finck * PROGRAMER:
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck #include <user32.h>
10*c2c66affSColin Finck
11*c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
12*c2c66affSColin Finck
13*c2c66affSColin Finck BOOL FASTCALL DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem);
14*c2c66affSColin Finck HGLOBAL FASTCALL DdeGetPair(HGLOBAL ServerMem);
15*c2c66affSColin Finck
16*c2c66affSColin Finck
17*c2c66affSColin Finck /* description of the data fields that need to be packed along with a sent message */
18*c2c66affSColin Finck struct packed_message
19*c2c66affSColin Finck {
20*c2c66affSColin Finck //union packed_structs ps;
21*c2c66affSColin Finck int count;
22*c2c66affSColin Finck const void *data;
23*c2c66affSColin Finck int size;
24*c2c66affSColin Finck };
25*c2c66affSColin Finck
26*c2c66affSColin Finck /* add a data field to a packed message */
push_data(struct packed_message * data,const void * ptr,int size)27*c2c66affSColin Finck static inline void push_data( struct packed_message *data, const void *ptr, int size )
28*c2c66affSColin Finck {
29*c2c66affSColin Finck data->data = ptr;
30*c2c66affSColin Finck data->size = size;
31*c2c66affSColin Finck data->count++;
32*c2c66affSColin Finck }
33*c2c66affSColin Finck
34*c2c66affSColin Finck /* pack a pointer into a 32/64 portable format */
pack_ptr(const void * ptr)35*c2c66affSColin Finck static inline ULONGLONG pack_ptr( const void *ptr )
36*c2c66affSColin Finck {
37*c2c66affSColin Finck return (ULONG_PTR)ptr;
38*c2c66affSColin Finck }
39*c2c66affSColin Finck
40*c2c66affSColin Finck /* unpack a potentially 64-bit pointer, returning 0 when truncated */
unpack_ptr(ULONGLONG ptr64)41*c2c66affSColin Finck static inline void *unpack_ptr( ULONGLONG ptr64 )
42*c2c66affSColin Finck {
43*c2c66affSColin Finck if ((ULONG_PTR)ptr64 != ptr64) return 0;
44*c2c66affSColin Finck return (void *)(ULONG_PTR)ptr64;
45*c2c66affSColin Finck }
46*c2c66affSColin Finck
47*c2c66affSColin Finck
48*c2c66affSColin Finck /***********************************************************************
49*c2c66affSColin Finck * post_dde_message
50*c2c66affSColin Finck *
51*c2c66affSColin Finck * Post a DDE message
52*c2c66affSColin Finck */
post_dde_message(struct packed_message * data,UINT message,LPARAM lParam,LPARAM * lp)53*c2c66affSColin Finck BOOL post_dde_message( struct packed_message *data, UINT message, LPARAM lParam , LPARAM *lp)
54*c2c66affSColin Finck {
55*c2c66affSColin Finck void* ptr = NULL;
56*c2c66affSColin Finck int size = 0;
57*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
58*c2c66affSColin Finck HGLOBAL hunlock = 0;
59*c2c66affSColin Finck ULONGLONG hpack;
60*c2c66affSColin Finck
61*c2c66affSColin Finck if (!UnpackDDElParam( message, lParam, &uiLo, &uiHi ))
62*c2c66affSColin Finck {
63*c2c66affSColin Finck ERR("Unpack failed %x\n",message);
64*c2c66affSColin Finck return FALSE;
65*c2c66affSColin Finck }
66*c2c66affSColin Finck
67*c2c66affSColin Finck *lp = lParam;
68*c2c66affSColin Finck switch (message)
69*c2c66affSColin Finck {
70*c2c66affSColin Finck /* DDE messages which don't require packing are:
71*c2c66affSColin Finck * WM_DDE_INITIATE
72*c2c66affSColin Finck * WM_DDE_TERMINATE
73*c2c66affSColin Finck * WM_DDE_REQUEST
74*c2c66affSColin Finck * WM_DDE_UNADVISE
75*c2c66affSColin Finck */
76*c2c66affSColin Finck case WM_DDE_ACK:
77*c2c66affSColin Finck if (HIWORD(uiHi))
78*c2c66affSColin Finck {
79*c2c66affSColin Finck /* uiHi should contain a hMem from WM_DDE_EXECUTE */
80*c2c66affSColin Finck HGLOBAL h = DdeGetPair( (HANDLE)uiHi );
81*c2c66affSColin Finck if (h)
82*c2c66affSColin Finck {
83*c2c66affSColin Finck hpack = pack_ptr( h );
84*c2c66affSColin Finck /* send back the value of h on the other side */
85*c2c66affSColin Finck push_data( data, &hpack, sizeof(hpack) );
86*c2c66affSColin Finck *lp = uiLo;
87*c2c66affSColin Finck TRACE( "send dde-ack %lx %08lx => %p\n", uiLo, uiHi, h );
88*c2c66affSColin Finck }
89*c2c66affSColin Finck }
90*c2c66affSColin Finck else
91*c2c66affSColin Finck {
92*c2c66affSColin Finck /* uiHi should contain either an atom or 0 */
93*c2c66affSColin Finck TRACE( "send dde-ack %lx atom=%lx\n", uiLo, uiHi );
94*c2c66affSColin Finck *lp = MAKELONG( uiLo, uiHi );
95*c2c66affSColin Finck }
96*c2c66affSColin Finck break;
97*c2c66affSColin Finck case WM_DDE_ADVISE:
98*c2c66affSColin Finck case WM_DDE_DATA:
99*c2c66affSColin Finck case WM_DDE_POKE:
100*c2c66affSColin Finck size = 0;
101*c2c66affSColin Finck if (uiLo)
102*c2c66affSColin Finck {
103*c2c66affSColin Finck size = GlobalSize( (HGLOBAL)uiLo ) ;
104*c2c66affSColin Finck TRACE("WM_DDE_A D P size %d\n",size);
105*c2c66affSColin Finck if ( (message == WM_DDE_ADVISE && size < sizeof(DDEADVISE)) ||
106*c2c66affSColin Finck (message == WM_DDE_DATA && size < FIELD_OFFSET(DDEDATA, Value)) ||
107*c2c66affSColin Finck (message == WM_DDE_POKE && size < FIELD_OFFSET(DDEPOKE, Value)) )
108*c2c66affSColin Finck return FALSE;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck else if (message != WM_DDE_DATA)
111*c2c66affSColin Finck {
112*c2c66affSColin Finck TRACE("WM_DDE uiLo 0\n");
113*c2c66affSColin Finck return FALSE;
114*c2c66affSColin Finck }
115*c2c66affSColin Finck
116*c2c66affSColin Finck *lp = uiHi;
117*c2c66affSColin Finck if (uiLo)
118*c2c66affSColin Finck {
119*c2c66affSColin Finck if ((ptr = GlobalLock( (HGLOBAL)uiLo) ))
120*c2c66affSColin Finck {
121*c2c66affSColin Finck DDEDATA *dde_data = ptr;
122*c2c66affSColin Finck TRACE("unused %d, fResponse %d, fRelease %d, fDeferUpd %d, fAckReq %d, cfFormat %d\n",
123*c2c66affSColin Finck dde_data->unused, dde_data->fResponse, dde_data->fRelease,
124*c2c66affSColin Finck dde_data->reserved, dde_data->fAckReq, dde_data->cfFormat);
125*c2c66affSColin Finck push_data( data, ptr, size );
126*c2c66affSColin Finck hunlock = (HGLOBAL)uiLo;
127*c2c66affSColin Finck }
128*c2c66affSColin Finck }
129*c2c66affSColin Finck TRACE( "send ddepack %u %lx\n", size, uiHi );
130*c2c66affSColin Finck break;
131*c2c66affSColin Finck case WM_DDE_EXECUTE:
132*c2c66affSColin Finck if (lParam)
133*c2c66affSColin Finck {
134*c2c66affSColin Finck if ((ptr = GlobalLock( (HGLOBAL)lParam) ))
135*c2c66affSColin Finck {
136*c2c66affSColin Finck size = GlobalSize( (HGLOBAL)lParam );
137*c2c66affSColin Finck push_data(data, ptr, size);
138*c2c66affSColin Finck /* so that the other side can send it back on ACK */
139*c2c66affSColin Finck *lp = lParam;
140*c2c66affSColin Finck hunlock = (HGLOBAL)lParam;
141*c2c66affSColin Finck TRACE("WM_DDE_EXECUTE text size %d\n",GlobalSize( (HGLOBAL)lParam ));
142*c2c66affSColin Finck }
143*c2c66affSColin Finck }
144*c2c66affSColin Finck break;
145*c2c66affSColin Finck }
146*c2c66affSColin Finck
147*c2c66affSColin Finck FreeDDElParam(message, lParam);
148*c2c66affSColin Finck
149*c2c66affSColin Finck if (hunlock) GlobalUnlock(hunlock);
150*c2c66affSColin Finck
151*c2c66affSColin Finck return TRUE;
152*c2c66affSColin Finck }
153*c2c66affSColin Finck
154*c2c66affSColin Finck /***********************************************************************
155*c2c66affSColin Finck * unpack_dde_message
156*c2c66affSColin Finck *
157*c2c66affSColin Finck * Unpack a posted DDE message received from another process.
158*c2c66affSColin Finck */
unpack_dde_message(HWND hwnd,UINT message,LPARAM * lparam,PVOID buffer,int size)159*c2c66affSColin Finck BOOL unpack_dde_message( HWND hwnd, UINT message, LPARAM *lparam, PVOID buffer, int size )
160*c2c66affSColin Finck {
161*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
162*c2c66affSColin Finck HGLOBAL hMem = 0;
163*c2c66affSColin Finck void* ptr;
164*c2c66affSColin Finck
165*c2c66affSColin Finck TRACE("udm : Size %d\n",size);
166*c2c66affSColin Finck
167*c2c66affSColin Finck switch (message)
168*c2c66affSColin Finck {
169*c2c66affSColin Finck case WM_DDE_ACK:
170*c2c66affSColin Finck if (size)
171*c2c66affSColin Finck {
172*c2c66affSColin Finck ULONGLONG hpack;
173*c2c66affSColin Finck /* hMem is being passed */
174*c2c66affSColin Finck if (size != sizeof(hpack)) return FALSE;
175*c2c66affSColin Finck if (!buffer) return FALSE;
176*c2c66affSColin Finck uiLo = *lparam;
177*c2c66affSColin Finck memcpy( &hpack, buffer, size );
178*c2c66affSColin Finck hMem = unpack_ptr( hpack );
179*c2c66affSColin Finck uiHi = (UINT_PTR)hMem;
180*c2c66affSColin Finck TRACE("recv dde-ack %lx mem=%lx[%lx]\n", uiLo, uiHi, GlobalSize( hMem ));
181*c2c66affSColin Finck }
182*c2c66affSColin Finck else
183*c2c66affSColin Finck {
184*c2c66affSColin Finck uiLo = LOWORD( *lparam );
185*c2c66affSColin Finck uiHi = HIWORD( *lparam );
186*c2c66affSColin Finck TRACE("recv dde-ack %lx atom=%lx\n", uiLo, uiHi);
187*c2c66affSColin Finck }
188*c2c66affSColin Finck *lparam = PackDDElParam( WM_DDE_ACK, uiLo, uiHi );
189*c2c66affSColin Finck break;
190*c2c66affSColin Finck case WM_DDE_ADVISE:
191*c2c66affSColin Finck case WM_DDE_DATA:
192*c2c66affSColin Finck case WM_DDE_POKE:
193*c2c66affSColin Finck if ((!buffer) && message != WM_DDE_DATA) return FALSE;
194*c2c66affSColin Finck uiHi = *lparam;
195*c2c66affSColin Finck if (size)
196*c2c66affSColin Finck {
197*c2c66affSColin Finck if (!(hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size )))
198*c2c66affSColin Finck return FALSE;
199*c2c66affSColin Finck if ((ptr = GlobalLock( hMem )))
200*c2c66affSColin Finck {
201*c2c66affSColin Finck memcpy( ptr, buffer, size );
202*c2c66affSColin Finck GlobalUnlock( hMem );
203*c2c66affSColin Finck }
204*c2c66affSColin Finck else
205*c2c66affSColin Finck {
206*c2c66affSColin Finck GlobalFree( hMem );
207*c2c66affSColin Finck return FALSE;
208*c2c66affSColin Finck }
209*c2c66affSColin Finck }
210*c2c66affSColin Finck uiLo = (UINT_PTR)hMem;
211*c2c66affSColin Finck
212*c2c66affSColin Finck *lparam = PackDDElParam( message, uiLo, uiHi );
213*c2c66affSColin Finck break;
214*c2c66affSColin Finck case WM_DDE_EXECUTE:
215*c2c66affSColin Finck if (size)
216*c2c66affSColin Finck {
217*c2c66affSColin Finck if (!buffer) return FALSE;
218*c2c66affSColin Finck if (!(hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size ))) return FALSE;
219*c2c66affSColin Finck if ((ptr = GlobalLock( hMem )))
220*c2c66affSColin Finck {
221*c2c66affSColin Finck memcpy( ptr, buffer, size );
222*c2c66affSColin Finck GlobalUnlock( hMem );
223*c2c66affSColin Finck TRACE( "exec: pairing c=%08lx s=%p\n", *lparam, hMem );
224*c2c66affSColin Finck if (!DdeAddPair( (HGLOBAL)*lparam, hMem ))
225*c2c66affSColin Finck {
226*c2c66affSColin Finck GlobalFree( hMem );
227*c2c66affSColin Finck TRACE("udm exec: GF 1\n");
228*c2c66affSColin Finck return FALSE;
229*c2c66affSColin Finck }
230*c2c66affSColin Finck }
231*c2c66affSColin Finck else
232*c2c66affSColin Finck {
233*c2c66affSColin Finck GlobalFree( hMem );
234*c2c66affSColin Finck TRACE("udm exec: GF 2\n");
235*c2c66affSColin Finck return FALSE;
236*c2c66affSColin Finck }
237*c2c66affSColin Finck }
238*c2c66affSColin Finck else
239*c2c66affSColin Finck {
240*c2c66affSColin Finck TRACE("udm exec: No Size\n");
241*c2c66affSColin Finck return FALSE;
242*c2c66affSColin Finck }
243*c2c66affSColin Finck
244*c2c66affSColin Finck TRACE( "exec: exit c=%08lx s=%p\n", *lparam, hMem );
245*c2c66affSColin Finck *lparam = (LPARAM)hMem;
246*c2c66affSColin Finck break;
247*c2c66affSColin Finck }
248*c2c66affSColin Finck return TRUE;
249*c2c66affSColin Finck }
250*c2c66affSColin Finck
251*c2c66affSColin Finck //
252*c2c66affSColin Finck // DDE Post kernel callback.
253*c2c66affSColin Finck //
254*c2c66affSColin Finck NTSTATUS
255*c2c66affSColin Finck WINAPI
User32CallDDEPostFromKernel(PVOID Arguments,ULONG ArgumentLength)256*c2c66affSColin Finck User32CallDDEPostFromKernel(PVOID Arguments, ULONG ArgumentLength)
257*c2c66affSColin Finck {
258*c2c66affSColin Finck struct packed_message data;
259*c2c66affSColin Finck BOOL Ret;
260*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
261*c2c66affSColin Finck PDDEPOSTGET_CALLBACK_ARGUMENTS Common = Arguments;
262*c2c66affSColin Finck
263*c2c66affSColin Finck data.data = 0;
264*c2c66affSColin Finck data.size = 0;
265*c2c66affSColin Finck TRACE("DDE Post CB\n");
266*c2c66affSColin Finck Ret = post_dde_message( &data, Common->message, Common->lParam, &Common->lParam);
267*c2c66affSColin Finck
268*c2c66affSColin Finck if (Ret)
269*c2c66affSColin Finck {
270*c2c66affSColin Finck Common->pvData = (PVOID)data.data;
271*c2c66affSColin Finck Common->size = data.size;
272*c2c66affSColin Finck TRACE("DDE Post CB size %d\n",data.size);
273*c2c66affSColin Finck }
274*c2c66affSColin Finck else
275*c2c66affSColin Finck {
276*c2c66affSColin Finck ERR("DDE Post CB Return bad msg 0x%x Size %d\n",Common->message,Common->size);
277*c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
278*c2c66affSColin Finck }
279*c2c66affSColin Finck
280*c2c66affSColin Finck return ZwCallbackReturn(Arguments, ArgumentLength, Status);
281*c2c66affSColin Finck }
282*c2c66affSColin Finck
283*c2c66affSColin Finck //
284*c2c66affSColin Finck // DDE Get/Peek kernel callback.
285*c2c66affSColin Finck //
286*c2c66affSColin Finck NTSTATUS
287*c2c66affSColin Finck WINAPI
User32CallDDEGetFromKernel(PVOID Arguments,ULONG ArgumentLength)288*c2c66affSColin Finck User32CallDDEGetFromKernel(PVOID Arguments, ULONG ArgumentLength)
289*c2c66affSColin Finck {
290*c2c66affSColin Finck BOOL Ret;
291*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
292*c2c66affSColin Finck PDDEPOSTGET_CALLBACK_ARGUMENTS Common = Arguments;
293*c2c66affSColin Finck
294*c2c66affSColin Finck TRACE("DDE Get CB size %d\n",Common->size);
295*c2c66affSColin Finck
296*c2c66affSColin Finck Ret = unpack_dde_message( Common->hwnd, Common->message, &Common->lParam, Common->buffer, Common->size );
297*c2c66affSColin Finck
298*c2c66affSColin Finck if (!Ret)
299*c2c66affSColin Finck {
300*c2c66affSColin Finck ERR("DDE Get CB Return bad msg 0x%x\n",Common->message);
301*c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
302*c2c66affSColin Finck }
303*c2c66affSColin Finck return ZwCallbackReturn(Arguments, ArgumentLength, Status);
304*c2c66affSColin Finck }
305*c2c66affSColin Finck
306*c2c66affSColin Finck
307*c2c66affSColin Finck /*
308*c2c66affSColin Finck * @unimplemented
309*c2c66affSColin Finck */
DdeGetQualityOfService(HWND hWnd,DWORD Reserved,PSECURITY_QUALITY_OF_SERVICE pqosPrev)310*c2c66affSColin Finck BOOL WINAPI DdeGetQualityOfService(HWND hWnd, DWORD Reserved, PSECURITY_QUALITY_OF_SERVICE pqosPrev)
311*c2c66affSColin Finck {
312*c2c66affSColin Finck UNIMPLEMENTED;
313*c2c66affSColin Finck return FALSE;
314*c2c66affSColin Finck }
315