2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Dynamic Data Exchange
5 * FILE: win32ss/user/ntuser/dde.c
13 DBG_DEFAULT_CHANNEL(UserMisc
);
16 // Default information used to support client impersonation.
18 SECURITY_QUALITY_OF_SERVICE gqosDefault
= {sizeof(SECURITY_QUALITY_OF_SERVICE
),SecurityImpersonation
,SECURITY_STATIC_TRACKING
,TRUE
};
20 typedef struct _DDEIMP
22 SECURITY_QUALITY_OF_SERVICE qos
;
23 SECURITY_CLIENT_CONTEXT ClientContext
;
28 typedef struct _DDE_DATA
33 } DDE_DATA
, *PDDE_DATA
;
35 typedef struct _DDE_PROP
40 } DDE_PROP
, *PDDE_PROP
;
44 // DDE Posting message callback to user side.
52 IN OUT LPARAM
*lParam
,
56 ULONG ArgumentLength
, ResultLength
;
57 PVOID Argument
, ResultPointer
;
58 PDDEPOSTGET_CALLBACK_ARGUMENTS Common
;
61 ResultLength
= ArgumentLength
= sizeof(DDEPOSTGET_CALLBACK_ARGUMENTS
);
63 Argument
= IntCbAllocateMemory(ArgumentLength
);
69 Common
= (PDDEPOSTGET_CALLBACK_ARGUMENTS
) Argument
;
73 Common
->hwnd
= UserHMGetHandle(pWnd
);
74 Common
->message
= Msg
;
75 Common
->wParam
= wParam
;
76 Common
->lParam
= *lParam
;
80 Status
= KeUserModeCallback(USER32_CALLBACK_DDEPOST
,
88 if (!NT_SUCCESS(Status
) || ResultPointer
== NULL
)
90 ERR("DDE Post callback failed!\n");
91 IntCbFreeMemory(Argument
);
95 RtlCopyMemory(Common
, ResultPointer
, ArgumentLength
);
98 *lParam
= Common
->lParam
;
99 *Buffer
= Common
->pvData
;
101 IntCbFreeMemory(Argument
);
103 return size
? size
: -1;
107 // DDE Get/Peek message callback to user side.
118 ULONG ArgumentLength
, ResultLength
;
119 PVOID Argument
, ResultPointer
;
120 PDDEPOSTGET_CALLBACK_ARGUMENTS Common
;
122 ResultPointer
= NULL
;
123 ResultLength
= ArgumentLength
= sizeof(DDEPOSTGET_CALLBACK_ARGUMENTS
)+size
;
125 Argument
= IntCbAllocateMemory(ArgumentLength
);
126 if (NULL
== Argument
)
131 Common
= (PDDEPOSTGET_CALLBACK_ARGUMENTS
) Argument
;
134 Common
->hwnd
= pMsg
->hwnd
;
135 Common
->message
= pMsg
->message
;
136 Common
->wParam
= pMsg
->wParam
;
137 Common
->lParam
= pMsg
->lParam
;
139 if (size
&& Buffer
) RtlCopyMemory(&Common
->buffer
, Buffer
, size
);
143 Status
= KeUserModeCallback(USER32_CALLBACK_DDEGET
,
151 if (!NT_SUCCESS(Status
) || ResultPointer
== NULL
)
153 ERR("DDE Get callback failed!\n");
154 IntCbFreeMemory(Argument
);
158 RtlMoveMemory(Common
, ResultPointer
, ArgumentLength
);
160 pMsg
->lParam
= Common
->lParam
;
162 IntCbFreeMemory(Argument
);
168 // DDE Post message hook, intercept DDE messages before going on to the target Processes Thread queue.
172 IntDdePostMessageHook(
176 IN OUT LPARAM
*lParam
,
177 IN OUT LONG_PTR
*ExtraInfo
)
182 HGDIOBJ Object
= NULL
;
183 PVOID userBuf
= NULL
;
187 if (pWnd
->head
.pti
->ppi
!= gptiCurrent
->ppi
)
189 TRACE("Posting long DDE 0x%x\n",Msg
);
190 // Initiate is sent only across borders.
191 if (Msg
== WM_DDE_INITIATE
)
196 pWndClient
= UserGetWindowObject((HWND
)wParam
);
197 if (pWndClient
== NULL
)
199 // This is terminating so post it.
200 if ( Msg
== WM_DDE_TERMINATE
)
202 TRACE("DDE Posted WM_DDE_TERMINATE\n");
205 TRACE("Invalid DDE Client Window handle\n");
209 if ( Msg
== WM_DDE_REQUEST
|| Msg
== WM_DDE_UNADVISE
)
211 // Do not bother to callback after validation.
215 if ( Msg
== WM_DDE_TERMINATE
)
217 //// FIXME Remove Stuff if any...
219 // Do not bother to callback.
223 if ( Msg
== WM_DDE_EXECUTE
&& *lParam
== 0)
225 // Do not bother to do a callback.
226 TRACE("DDE Post EXECUTE lParam 0\n");
231 if ((size
= IntDDEPostCallback(pWnd
, Msg
, wParam
, &lp
, &userBuf
)) == 0)
233 ERR("DDE Post Callback return 0 0x%x\n", Msg
);
244 // Set buffer with users data size.
245 Buffer
= ExAllocatePoolWithTag(PagedPool
, size
, USERTAG_DDE
);
248 ERR("Failed to allocate %i bytes.\n", size
);
251 // No SEH? Yes, the user memory is freed after the Acknowledgment or at Termination.
252 RtlCopyMemory(Buffer
, userBuf
, size
);
255 TRACE("DDE Post size %d 0x%x\n",size
, Msg
);
261 DDEPOKE
*pddePoke
= Buffer
;
262 NT_ASSERT(pddePoke
!= NULL
);
263 switch(pddePoke
->cfFormat
)
268 RtlCopyMemory(&Object
, pddePoke
->Value
, sizeof(HGDIOBJ
));
277 DDEDATA
*pddeData2
= Buffer
;
278 NT_ASSERT(pddeData2
!= NULL
);
279 switch(pddeData2
->cfFormat
)
284 RtlCopyMemory(&Object
, pddeData2
->Value
, sizeof(HGDIOBJ
));
297 // Give gdi object to the other process.
298 GreSetObjectOwner(Object
, pWnd
->head
.pti
->ppi
->W32Pid
);
301 pddeData
= ExAllocatePoolWithTag(PagedPool
, sizeof(DDE_DATA
), USERTAG_DDE5
);
302 if (pddeData
== NULL
)
304 ERR("Failed to allocate DDE_DATA\n");
305 ExFreePoolWithTag(Buffer
, USERTAG_DDE
);
309 pddeData
->cbSize
= size
;
310 pddeData
->pvBuffer
= Buffer
;
311 pddeData
->lParam
= lp
;
313 TRACE("DDE Post lParam c=%08lx\n",lp
);
316 // Attach this data packet to the user message.
317 *ExtraInfo
= (LONG_PTR
)pddeData
;
323 // DDE Get/Peek message hook, take preprocessed information and recombined it for the current Process Thread.
326 IntDdeGetMessageHook(PMSG pMsg
, LONG_PTR ExtraInfo
)
328 PWND pWnd
, pWndClient
;
333 pWnd
= UserGetWindowObject(pMsg
->hwnd
);
336 ERR("DDE Get Window is dead. %p\n", pMsg
->hwnd
);
340 if (pMsg
->message
== WM_DDE_TERMINATE
)
342 pddeProp
= (PDDE_PROP
)UserGetProp(pWnd
, AtomDDETrack
, TRUE
);
345 pWndClient
= UserGetWindowObject((HWND
)pMsg
->wParam
);
346 if (pWndClient
== NULL
)
348 ERR("DDE Get Client WM_DDE_TERMINATE\n");
351 UserRemoveProp(pWnd
, AtomDDETrack
, TRUE
);
352 ExFreePoolWithTag(pddeProp
, USERTAG_DDE1
);
357 TRACE("DDE Get Msg 0x%x\n",pMsg
->message
);
359 pddeData
= (PDDE_DATA
)ExtraInfo
;
363 TRACE("DDE Get size %d lParam c=%08lx lp c=%08lx\n",pddeData
->cbSize
, pMsg
->lParam
, pddeData
->lParam
);
366 Ret
= IntDDEGetCallback( pWnd
, pMsg
, pddeData
->pvBuffer
, pddeData
->cbSize
);
369 ERR("DDE Get CB failed\n");
372 if (pddeData
->pvBuffer
) ExFreePoolWithTag(pddeData
->pvBuffer
, USERTAG_DDE
);
374 ExFreePoolWithTag(pddeData
, USERTAG_DDE5
);
378 TRACE("DDE Get No DDE Data found!\n");
383 // DDE Send message hook, intercept DDE messages and associate them in a partnership with property.
386 IntDdeSendMessageHook(PWND pWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
391 if (pWnd
->head
.pti
->ppi
!= gptiCurrent
->ppi
)
393 TRACE("Sending long DDE 0x%x\n",Msg
);
395 // Allow only Acknowledge and Initiate to be sent across borders.
396 if (Msg
!= WM_DDE_ACK
)
398 if (Msg
== WM_DDE_INITIATE
) return TRUE
;
402 TRACE("Sending long WM_DDE_ACK\n");
404 pWndServer
= UserGetWindowObject((HWND
)wParam
);
405 if (pWndServer
== NULL
)
407 ERR("Invalid DDE Server Window handle\n");
411 // Setup property so this conversation can be tracked.
412 pddeProp
= ExAllocatePoolWithTag(PagedPool
, sizeof(DDE_PROP
), USERTAG_DDE1
);
413 if (pddeProp
== NULL
)
415 ERR("failed to allocate DDE_PROP\n");
419 pddeProp
->spwnd
= pWndServer
;
420 pddeProp
->spwndPartner
= pWnd
;
422 UserSetProp(pWndServer
, AtomDDETrack
, (HANDLE
)pddeProp
, TRUE
);
430 NtUserDdeGetQualityOfService(
433 OUT PSECURITY_QUALITY_OF_SERVICE pqosPrev
)
442 NtUserDdeSetQualityOfService(
444 IN PSECURITY_QUALITY_OF_SERVICE pqosNew
,
445 OUT PSECURITY_QUALITY_OF_SERVICE pqosPrev
)
454 NtUserImpersonateDdeClientWindow(