From 2d94b2173fe69f15da2d39b5f1555800e38a3de9 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Thu, 8 Jan 2015 00:56:51 +0000 Subject: [PATCH] [Win32s] - Implement DDE from wine. Leaving debug errors on the run and later move to trace. See CORE-7447. - Use callbacks to User32 to convert the data and track it in Win32k. - Add a new Quality of Service atom. - Add things to class.c. - Shell32 tests run now too, or only 4 run. This might be fixed too, since locating a lParam write back issue. svn path=/trunk/; revision=66000 --- reactos/win32ss/include/callback.h | 16 +- reactos/win32ss/include/ntuser.h | 18 +- reactos/win32ss/user/ntuser/class.c | 3 +- reactos/win32ss/user/ntuser/dde.c | 368 ++++++++++++++++-- reactos/win32ss/user/ntuser/message.c | 15 +- reactos/win32ss/user/ntuser/ntuser.c | 12 +- reactos/win32ss/user/ntuser/ntuser.h | 2 + reactos/win32ss/user/ntuser/userfuncs.h | 4 +- reactos/win32ss/user/user32/misc/dde.c | 280 +++++++++++++ reactos/win32ss/user/user32/misc/dllmain.c | 2 + reactos/win32ss/user/user32/windows/message.c | 110 +----- 11 files changed, 671 insertions(+), 159 deletions(-) diff --git a/reactos/win32ss/include/callback.h b/reactos/win32ss/include/callback.h index dbfa6d589b1..55cd51ae276 100644 --- a/reactos/win32ss/include/callback.h +++ b/reactos/win32ss/include/callback.h @@ -14,7 +14,9 @@ #define USER32_CALLBACK_COPYIMAGE (10) #define USER32_CALLBACK_SETWNDICONS (11) #define USER32_CALLBACK_DELIVERUSERAPC (12) -#define USER32_CALLBACK_MAXIMUM (12) +#define USER32_CALLBACK_DDEPOST (13) +#define USER32_CALLBACK_DDEGET (14) +#define USER32_CALLBACK_MAXIMUM (14) typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS { @@ -115,6 +117,14 @@ typedef struct _SETWNDICONS_CALLBACK_ARGUMENTS HICON hIconWindows; } SETWNDICONS_CALLBACK_ARGUMENTS, *PSETWNDICONS_CALLBACK_ARGUMENTS; +typedef struct _DDEPOSTGET_CALLBACK_ARGUMENTS +{ + INT Type; + MSG; + int size; + BYTE buffer[1]; +} DDEPOSTGET_CALLBACK_ARGUMENTS, *PDDEPOSTGET_CALLBACK_ARGUMENTS; + NTSTATUS WINAPI User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength); NTSTATUS WINAPI @@ -141,4 +151,8 @@ NTSTATUS WINAPI User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength); NTSTATUS WINAPI User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS WINAPI +User32CallDDEPostFromKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS WINAPI +User32CallDDEGetFromKernel(PVOID Arguments, ULONG ArgumentLength); #endif /* __INCLUDE_USER32_CALLBACK_H */ diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 1265a4d458f..154849984fc 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -301,6 +301,12 @@ C_ASSERT(sizeof(CLIENTINFO) <= sizeof(((PTEB)0)->Win32ClientInfo)); #define GetWin32ClientInfo() ((PCLIENTINFO)(NtCurrentTeb()->Win32ClientInfo)) +typedef struct tagDDEPACK +{ + UINT_PTR uiLo; + UINT_PTR uiHi; +} DDEPACK, *PDDEPACK; + #define HRGN_NULL ( (HRGN) 0) // NULL empty region #define HRGN_WINDOW ( (HRGN) 1) // region from window rcWindow #define HRGN_MONITOR ( (HRGN) 2) // region from monitor region. @@ -3417,19 +3423,7 @@ DWORD NTAPI NtUserYieldTask(VOID); -/* lParam of DDE messages */ -typedef struct tagKMDDEEXECUTEDATA -{ - HWND Sender; - HGLOBAL ClientMem; - /* BYTE Data[DataSize] */ -} KMDDEEXECUTEDATA, *PKMDDEEXECUTEDATA; -typedef struct tagDDEPACK -{ - UINT_PTR uiLo; - UINT_PTR uiHi; -} DDEPACK, *PDDEPACK; diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index 1b80823ff05..c437d745309 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -1052,6 +1052,7 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, /* FIXME: The class was created before being connected to a desktop. It is possible for the desktop window, but should it be allowed for any other case? */ + TRACE("This CLASS has no Desktop to heap from! Atom %d\n",Atom); Class = UserHeapAlloc(ClassSize); } @@ -2367,7 +2368,7 @@ UserGetClassInfo(IN PCLS Class, } // -// ??? +// Register System Classes.... // BOOL FASTCALL diff --git a/reactos/win32ss/user/ntuser/dde.c b/reactos/win32ss/user/ntuser/dde.c index 5076fdf2ecd..e383b2a357b 100644 --- a/reactos/win32ss/user/ntuser/dde.c +++ b/reactos/win32ss/user/ntuser/dde.c @@ -5,39 +5,167 @@ DBG_DEFAULT_CHANNEL(UserMisc); - -BOOL FASTCALL -IntDdeSendMessageHook(PWND pWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +typedef struct _DDE_DATA { - PWND pWndServer; + LPARAM lParam; + int cbSize; + PVOID pvBuffer; +} DDE_DATA, *PDDE_DATA; - if (pWnd->head.pti->ppi != gptiCurrent->ppi) +typedef struct _DDE_PROP +{ + PWND spwnd; + PWND spwndPartner; +} DDE_PROP, *PDDE_PROP; + + + +int +APIENTRY +IntDDEPostCallback( + IN PWND pWnd, + IN UINT Msg, + IN WPARAM wParam, + IN OUT LPARAM *lParam, + IN PVOID Buffer, + IN int size) +{ + NTSTATUS Status; + ULONG ArgumentLength, ResultLength; + PVOID Argument, ResultPointer; + PDDEPOSTGET_CALLBACK_ARGUMENTS Common; + int origSize = size; + + ResultPointer = NULL; + ResultLength = ArgumentLength = sizeof(DDEPOSTGET_CALLBACK_ARGUMENTS)+size; + + Argument = IntCbAllocateMemory(ArgumentLength); + if (NULL == Argument) { - // Allow only Acknowledge and Initiate to be sent across borders. - if (Msg != WM_DDE_ACK ) - { - if (Msg == WM_DDE_INITIATE) return TRUE; - return FALSE; - } - - pWndServer = UserGetWindowObject((HWND)wParam); - if (pWndServer == NULL) - { - ERR("Invalid DDE Server Window handle\n"); - return FALSE; - } - ERR("Sending DDE 0x%x\n",Msg); + return FALSE; } + + Common = (PDDEPOSTGET_CALLBACK_ARGUMENTS) Argument; + + Common->size = size; + Common->hwnd = UserHMGetHandle(pWnd); + Common->message = Msg; + Common->wParam = wParam; + Common->lParam = *lParam; + RtlCopyMemory(&Common->buffer, Buffer, size); + + UserLeaveCo(); + + Status = KeUserModeCallback(USER32_CALLBACK_DDEPOST, + Argument, + ArgumentLength, + &ResultPointer, + &ResultLength); + + UserEnterCo(); + + if (!NT_SUCCESS(Status) || ResultPointer == NULL ) + { + ERR("DDE Post callback failed!\n"); + IntCbFreeMemory(Argument); + return 0; + } + + RtlCopyMemory(Common, ResultPointer, ArgumentLength); + + if (Common->size != 0 && size <= origSize) + { + RtlCopyMemory(Buffer, &Common->buffer, size); // ResultLength); + } + + size = Common->size; + *lParam = Common->lParam; + + IntCbFreeMemory(Argument); + + return size ? size : -1; +} + +BOOL +APIENTRY +IntDDEGetCallback( + IN PWND pWnd, + IN OUT PMSG pMsg, + IN PVOID Buffer, + IN int size) +{ + NTSTATUS Status; + ULONG ArgumentLength, ResultLength; + PVOID Argument, ResultPointer; + PDDEPOSTGET_CALLBACK_ARGUMENTS Common; + + ResultPointer = NULL; + ResultLength = ArgumentLength = sizeof(DDEPOSTGET_CALLBACK_ARGUMENTS)+size; + + Argument = IntCbAllocateMemory(ArgumentLength); + if (NULL == Argument) + { + return FALSE; + } + + Common = (PDDEPOSTGET_CALLBACK_ARGUMENTS) Argument; + + Common->size = size; + Common->hwnd = pMsg->hwnd; + Common->message = pMsg->message; + Common->wParam = pMsg->wParam; + Common->lParam = pMsg->lParam; + + if (size && Buffer) RtlCopyMemory(&Common->buffer, Buffer, size); + + + UserLeaveCo(); + + Status = KeUserModeCallback(USER32_CALLBACK_DDEGET, + Argument, + ArgumentLength, + &ResultPointer, + &ResultLength); + + UserEnterCo(); + + if (!NT_SUCCESS(Status) || ResultPointer == NULL ) + { + ERR("DDE Get callback failed!\n"); + IntCbFreeMemory(Argument); + return FALSE; + } + + RtlMoveMemory(Common, ResultPointer, ArgumentLength); + + pMsg->lParam = Common->lParam; + + IntCbFreeMemory(Argument); + return TRUE; } -BOOL FASTCALL -IntDdePostMessageHook(PWND pWnd, UINT Msg, WPARAM wParam, LPARAM lParam) + + +BOOL +APIENTRY +IntDdePostMessageHook( + IN PWND pWnd, + IN UINT Msg, + IN WPARAM wParam, + IN OUT LPARAM *lParam, + IN OUT LONG_PTR *ExtraInfo) { PWND pWndClient; + PDDE_DATA pddeData; + HGDIOBJ Object = NULL; + PVOID Buffer = NULL; + int size = 128; + LPARAM lp = *lParam; if (pWnd->head.pti->ppi != gptiCurrent->ppi) { + ERR("Posting long DDE 0x%x\n",Msg); // Initiate is sent only across borders. if (Msg == WM_DDE_INITIATE) { @@ -47,26 +175,206 @@ IntDdePostMessageHook(PWND pWnd, UINT Msg, WPARAM wParam, LPARAM lParam) pWndClient = UserGetWindowObject((HWND)wParam); if (pWndClient == NULL) { - // This is terminating so post it. - if ( Msg == WM_DDE_TERMINATE) return TRUE; - ERR("Invalid DDE Client Window handle\n"); - return FALSE; + // This is terminating so post it. + if ( Msg == WM_DDE_TERMINATE) + { + ERR("DDE Posted WM_DDE_TERMINATE\n"); + return TRUE; + } + ERR("Invalid DDE Client Window handle\n"); + return FALSE; } - ERR("Posting and do CB DDE 0x%x\n",Msg); + + if (Msg == WM_DDE_TERMINATE ) + { + //// FIXME Remove Stuff if any... + + // Do not bother to callback. + return TRUE; + } + + Buffer = ExAllocatePoolWithTag(PagedPool, size, USERTAG_DDE); + + if ((size = IntDDEPostCallback(pWnd, Msg, wParam, &lp, Buffer, size)) == 0) + { + ERR("DDE Post Callback return 0 0x%x\n", Msg); + } + + if (size != -1 && size > 128) + { + ERR("FIXME: DDE Post need more bytes %d\n",size); + } + + if (size == -1) + { + size = 0; + ExFreePoolWithTag(Buffer, USERTAG_DDE); + Buffer = NULL; + } + + ERR("DDE Post size %d 0x%x\n",size, Msg); + + switch(Msg) + { + case WM_DDE_POKE: + { + DDEPOKE *pddePoke = Buffer; + switch(pddePoke->cfFormat) + { + case CF_BITMAP: + case CF_DIB: + case CF_PALETTE: + RtlCopyMemory(&Object, pddePoke->Value, sizeof(HGDIOBJ)); + break; + default: + break; + } + break; + } + case WM_DDE_DATA: + { + DDEDATA *pddeData = Buffer; + switch(pddeData->cfFormat) + { + case CF_BITMAP: + case CF_DIB: + case CF_PALETTE: + RtlCopyMemory(&Object, pddeData->Value, sizeof(HGDIOBJ)); + break; + default: + break; + } + break; + + } + default: + break; + } + + if (Object) + { + // Give gdi object to the other process. + GreSetObjectOwner(Object, pWnd->head.pti->ppi->W32Pid); + } + + pddeData = ExAllocatePoolWithTag(PagedPool, sizeof(DDE_DATA), USERTAG_DDE2); + + pddeData->cbSize = size; + pddeData->pvBuffer = Buffer; + pddeData->lParam = lp; + + ERR("DDE Post lParam c=%08lx\n",lp); + *lParam = lp; + + // Attach this data packet to the user message. + *ExtraInfo = (LONG_PTR)pddeData; } return TRUE; } -VOID FASTCALL -IntDdeGetMessageHook(PMSG pMsg) +VOID APIENTRY +IntDdeGetMessageHook(PMSG pMsg, LONG_PTR ExtraInfo) { - if (pMsg->message == WM_DDE_TERMINATE) + PWND pWnd, pWndClient; + PDDE_DATA pddeData; + PDDE_PROP pddeProp; + BOOL Ret; + + pWnd = UserGetWindowObject(pMsg->hwnd); + if (pWnd == NULL) { + ERR("DDE Get Window is dead. %p\n", pMsg->hwnd); return; } - ERR("Do Callback Msg 0x%x\n",pMsg->message); + + if (pMsg->message == WM_DDE_TERMINATE) + { + pddeProp = (PDDE_PROP)UserGetProp(pWnd, AtomDDETrack); + if (pddeProp) + { + pWndClient = UserGetWindowObject((HWND)pMsg->wParam); + if (pWndClient == NULL) + { + ERR("DDE Get Client WM_DDE_TERMINATE\n"); + } + + IntRemoveProp(pWnd, AtomDDETrack); + ExFreePoolWithTag(pddeProp, USERTAG_DDE1); + } + return; + } + + ERR("DDE Get Msg 0x%x\n",pMsg->message); + + pddeData = (PDDE_DATA)ExtraInfo; + + if ( pddeData ) + { + ERR("DDE Get 1 size %d lParam c=%08lx lp c=%08lx\n",pddeData->cbSize, pMsg->lParam, pddeData->lParam); + + pMsg->lParam = pddeData->lParam; // This might be a hack... Need to backtrace lParam from post queue. + + Ret = IntDDEGetCallback( pWnd, pMsg, pddeData->pvBuffer, pddeData->cbSize); + if (!Ret) + { + ERR("DDE Get CB failed\n"); + } + + ERR("DDE Get 2 size %d lParam c=%08lx\n",pddeData->cbSize, pMsg->lParam); + + if (pddeData->pvBuffer) ExFreePoolWithTag(pddeData->pvBuffer, USERTAG_DDE); + + ExFreePoolWithTag(pddeData, USERTAG_DDE2); + + return; + } + ERR("DDE Get No DDE Data found!\n"); + return; } +BOOL FASTCALL +IntDdeSendMessageHook(PWND pWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PWND pWndServer; + PDDE_PROP pddeProp; + + if (Msg == WM_DDE_ACK) + { + ERR("Sending WM_DDE_ACK Client hwnd %p\n",pWnd->head.h); + } + + if (pWnd->head.pti->ppi != gptiCurrent->ppi) + { + ERR("Sending long DDE 0x%x\n",Msg); + + // Allow only Acknowledge and Initiate to be sent across borders. + if (Msg != WM_DDE_ACK ) + { + if (Msg == WM_DDE_INITIATE) return TRUE; + return FALSE; + } + + ERR("Sending long WM_DDE_ACK\n"); + + pWndServer = UserGetWindowObject((HWND)wParam); + if (pWndServer == NULL) + { + ERR("Invalid DDE Server Window handle\n"); + return FALSE; + } + + // Setup property so this conversation can be tracked. + pddeProp = ExAllocatePoolWithTag(PagedPool, sizeof(DDE_PROP), USERTAG_DDE1); + + pddeProp->spwnd = pWndServer; + pddeProp->spwndPartner = pWnd; + + IntSetProp(pWndServer, AtomDDETrack, (HANDLE)pddeProp); + } + return TRUE; +} + + BOOL APIENTRY NtUserDdeGetQualityOfService( diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index 9b1837c7f9f..3a45e8baea8 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -122,8 +122,6 @@ MSGMEMORY, *PMSGMEMORY; static MSGMEMORY g_MsgMemory[] = { { WM_CREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, - { WM_DDE_ACK, sizeof(DDEPACK), MMS_FLAG_READ }, - { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ }, { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE }, { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE }, { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE }, @@ -1014,14 +1012,12 @@ co_IntGetPeekMessage( PMSG pMsg, bGMSG ); if (Present) { + /* GetMessage or PostMessage must never get messages that contain pointers */ + ASSERT(FindMsgMemory(pMsg->message) == NULL); + if ( pMsg->message >= WM_DDE_FIRST && pMsg->message <= WM_DDE_LAST ) { - IntDdeGetMessageHook(pMsg); - } - else - { - /* GetMessage or PostMessage must never get messages that contain pointers */ - ASSERT(FindMsgMemory(pMsg->message) == NULL); + IntDdeGetMessageHook(pMsg, ExtraInfo); } if (pMsg->message != WM_PAINT && pMsg->message != WM_QUIT) @@ -1206,11 +1202,12 @@ UserPostMessage( HWND Wnd, if ( Msg >= WM_DDE_FIRST && Msg <= WM_DDE_LAST ) { - if (!IntDdePostMessageHook(Window, Msg, wParam, lParam)) + if (!IntDdePostMessageHook(Window, Msg, wParam, &lParam, &ExtraInfo)) { ERR("Posting Exit DDE 0x%x\n",Msg); return FALSE; } + ERR("DDE Post lParam c=%08lx\n",lParam); } if (WM_QUIT == Msg) diff --git a/reactos/win32ss/user/ntuser/ntuser.c b/reactos/win32ss/user/ntuser/ntuser.c index 1546e849687..754b97a68a0 100644 --- a/reactos/win32ss/user/ntuser/ntuser.c +++ b/reactos/win32ss/user/ntuser/ntuser.c @@ -1,4 +1,4 @@ -/* +ATOM AtomQOS;/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: ntuser init. and main funcs. @@ -15,11 +15,12 @@ BOOL FASTCALL RegisterControlAtoms(VOID); PTHREADINFO gptiCurrent = NULL; PPROCESSINFO gppiInputProvider = NULL; ERESOURCE UserLock; -ATOM AtomMessage; // Window Message atom. -ATOM AtomWndObj; // Window Object atom. -ATOM AtomLayer; // Window Layer atom. +ATOM AtomMessage; // Window Message atom. +ATOM AtomWndObj; // Window Object atom. +ATOM AtomLayer; // Window Layer atom. ATOM AtomFlashWndState; // Window Flash State atom. -ATOM AtomDDETrack; // Window DDE Tracking atom. +ATOM AtomDDETrack; // Window DDE Tracking atom. +ATOM AtomQOS; // Window DDE Quality of Service atom. HINSTANCE hModClient = NULL; BOOL ClientPfnInit = FALSE; ATOM gaGuiConsoleWndClass; @@ -52,6 +53,7 @@ InitUserAtoms(VOID) gpsi->atomFrostedWindowProp = IntAddGlobalAtom(L"SysFrostedWindow", TRUE); AtomDDETrack = IntAddGlobalAtom(L"SysDT", TRUE); + AtomQOS = IntAddGlobalAtom(L"SysQOS", TRUE); /* * FIXME: AddPropW uses the global kernel atom table, thus leading to conflicts if we use diff --git a/reactos/win32ss/user/ntuser/ntuser.h b/reactos/win32ss/user/ntuser/ntuser.h index 88203c2f6eb..06db1c2fb2a 100644 --- a/reactos/win32ss/user/ntuser/ntuser.h +++ b/reactos/win32ss/user/ntuser/ntuser.h @@ -15,6 +15,8 @@ extern PPROCESSINFO gppiList; extern PPROCESSINFO ppiScrnSaver; extern PPROCESSINFO gppiInputProvider; extern ATOM gaGuiConsoleWndClass; +extern ATOM AtomDDETrack; +extern ATOM AtomQOS; INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID); VOID FASTCALL CleanupUserImpl(VOID); diff --git a/reactos/win32ss/user/ntuser/userfuncs.h b/reactos/win32ss/user/ntuser/userfuncs.h index d26602566ce..aee51df5b1f 100644 --- a/reactos/win32ss/user/ntuser/userfuncs.h +++ b/reactos/win32ss/user/ntuser/userfuncs.h @@ -43,8 +43,8 @@ PWND FASTCALL IntGetWindowObject(HWND hWnd); /*************** DDE.C ****************/ BOOL FASTCALL IntDdeSendMessageHook(PWND,UINT,WPARAM,LPARAM); -BOOL FASTCALL IntDdePostMessageHook(PWND,UINT,WPARAM,LPARAM); -VOID FASTCALL IntDdeGetMessageHook(PMSG); +BOOL APIENTRY IntDdePostMessageHook(IN PWND,IN UINT,IN WPARAM,IN OUT LPARAM*,IN OUT LONG_PTR*); +VOID APIENTRY IntDdeGetMessageHook(PMSG,LONG_PTR); /*************** MAIN.C ***************/ diff --git a/reactos/win32ss/user/user32/misc/dde.c b/reactos/win32ss/user/user32/misc/dde.c index 7df1b0b9e61..fe1ff8338ce 100644 --- a/reactos/win32ss/user/user32/misc/dde.c +++ b/reactos/win32ss/user/user32/misc/dde.c @@ -4,6 +4,286 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddeml); + +BOOL FASTCALL DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem); +HGLOBAL FASTCALL DdeGetPair(HGLOBAL ServerMem); + + +/* description of the data fields that need to be packed along with a sent message */ +struct packed_message +{ + //union packed_structs ps; + int count; + const void *data; + int size; +}; + +/* add a data field to a packed message */ +static inline void push_data( struct packed_message *data, const void *ptr, int size ) +{ + data->data = ptr; + data->size = size; + data->count++; +} + +/* pack a pointer into a 32/64 portable format */ +static inline ULONGLONG pack_ptr( const void *ptr ) +{ + return (ULONG_PTR)ptr; +} + +/* unpack a potentially 64-bit pointer, returning 0 when truncated */ +static inline void *unpack_ptr( ULONGLONG ptr64 ) +{ + if ((ULONG_PTR)ptr64 != ptr64) return 0; + return (void *)(ULONG_PTR)ptr64; +} + + +/*********************************************************************** + * post_dde_message + * + * Post a DDE message + */ +BOOL post_dde_message( struct packed_message *data, UINT message, LPARAM lParam , LPARAM *lp) +{ + void* ptr = NULL; + int size = 0; + UINT_PTR uiLo, uiHi; + HGLOBAL hunlock = 0; + ULONGLONG hpack; + + if (!UnpackDDElParam( message, lParam, &uiLo, &uiHi )) + { + ERR("Unpack failed %x\n",message); + return FALSE; + } + + *lp = lParam; + switch (message) + { + /* DDE messages which don't require packing are: + * WM_DDE_INITIATE + * WM_DDE_TERMINATE + * WM_DDE_REQUEST + * WM_DDE_UNADVISE + */ + case WM_DDE_ACK: + if (HIWORD(uiHi)) + { + /* uiHi should contain a hMem from WM_DDE_EXECUTE */ + HGLOBAL h = DdeGetPair( (HANDLE)uiHi ); + if (h) + { + hpack = pack_ptr( h ); + /* send back the value of h on the other side */ + push_data( data, &hpack, sizeof(hpack) ); + *lp = uiLo; + ERR( "send dde-ack %lx %08lx => %p\n", uiLo, uiHi, h ); + } + } + else + { + /* uiHi should contain either an atom or 0 */ + ERR( "send dde-ack %lx atom=%lx\n", uiLo, uiHi ); + *lp = MAKELONG( uiLo, uiHi ); + } + break; + case WM_DDE_ADVISE: + case WM_DDE_DATA: + case WM_DDE_POKE: + size = 0; + if (uiLo) + { + size = GlobalSize( (HGLOBAL)uiLo ) ; + if ( (message == WM_DDE_ADVISE && size < sizeof(DDEADVISE)) || + (message == WM_DDE_DATA && size < FIELD_OFFSET(DDEDATA, Value)) || + (message == WM_DDE_POKE && size < FIELD_OFFSET(DDEPOKE, Value)) ) + return FALSE; + } + else if (message != WM_DDE_DATA) return FALSE; + + *lp = uiHi; + if (uiLo) + { + if ((ptr = GlobalLock( (HGLOBAL)uiLo) )) + { + DDEDATA *dde_data = ptr; + ERR("unused %d, fResponse %d, fRelease %d, fDeferUpd %d, fAckReq %d, cfFormat %d\n", + dde_data->unused, dde_data->fResponse, dde_data->fRelease, + dde_data->reserved, dde_data->fAckReq, dde_data->cfFormat); + push_data( data, ptr, size ); + hunlock = (HGLOBAL)uiLo; + } + } + ERR( "send ddepack %u %lx\n", size, uiHi ); + break; + case WM_DDE_EXECUTE: + if (lParam) + { + if ((ptr = GlobalLock( (HGLOBAL)lParam) )) + { + size = GlobalSize( (HGLOBAL)lParam ); + push_data(data, ptr, size); + /* so that the other side can send it back on ACK */ + *lp = lParam; + hunlock = (HGLOBAL)lParam; + ERR("WM_DDE_EXECUTE text size %d\n",GlobalSize( (HGLOBAL)lParam )); + } + } + break; + } + + FreeDDElParam(message, lParam); + + if (hunlock) GlobalUnlock(hunlock); + + return TRUE; +} + +/*********************************************************************** + * unpack_dde_message + * + * Unpack a posted DDE message received from another process. + */ +BOOL unpack_dde_message( HWND hwnd, UINT message, LPARAM *lparam, PVOID buffer, int size ) +{ + UINT_PTR uiLo, uiHi; + HGLOBAL hMem = 0; + void* ptr; + + ERR("udm : Size %d\n",size); + + switch (message) + { + case WM_DDE_ACK: + if (size) + { + ULONGLONG hpack; + /* hMem is being passed */ + if (size != sizeof(hpack)) return FALSE; + if (!buffer) return FALSE; + uiLo = *lparam; + memcpy( &hpack, buffer, size ); + hMem = unpack_ptr( hpack ); + uiHi = (UINT_PTR)hMem; + ERR("recv dde-ack %lx mem=%lx[%lx]\n", uiLo, uiHi, GlobalSize( hMem )); + } + else + { + uiLo = LOWORD( *lparam ); + uiHi = HIWORD( *lparam ); + ERR("recv dde-ack %lx atom=%lx\n", uiLo, uiHi); + } + *lparam = PackDDElParam( WM_DDE_ACK, uiLo, uiHi ); + break; + case WM_DDE_ADVISE: + case WM_DDE_DATA: + case WM_DDE_POKE: + if ((!buffer) && message != WM_DDE_DATA) return FALSE; + uiHi = *lparam; + if (size) + { + if (!(hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size ))) + return FALSE; + if ((ptr = GlobalLock( hMem ))) + { + memcpy( ptr, buffer, size ); + GlobalUnlock( hMem ); + } + else + { + GlobalFree( hMem ); + return FALSE; + } + } + uiLo = (UINT_PTR)hMem; + + *lparam = PackDDElParam( message, uiLo, uiHi ); + break; + case WM_DDE_EXECUTE: + if (size) + { + if (!buffer) return FALSE; + if (!(hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size ))) return FALSE; + if ((ptr = GlobalLock( hMem ))) + { + memcpy( ptr, buffer, size ); + GlobalUnlock( hMem ); + ERR( "exec: pairing c=%08lx s=%p\n", *lparam, hMem ); + if (!DdeAddPair( (HGLOBAL)*lparam, hMem )) + { + GlobalFree( hMem ); + ERR("udm exec: GF 1\n"); + return FALSE; + } + } + else + { + GlobalFree( hMem ); + ERR("udm exec: GF 2\n"); + return FALSE; + } + } + else + { + ERR("udm exec: No Size\n"); + return FALSE; + } + + ERR( "exec: exit c=%08lx s=%p\n", *lparam, hMem ); + *lparam = (LPARAM)hMem; + break; + } + return TRUE; +} + +NTSTATUS +WINAPI +User32CallDDEPostFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + struct packed_message data; + BOOL Ret; + PDDEPOSTGET_CALLBACK_ARGUMENTS Common = Arguments; + + data.data = 0; + data.size = 0; + ERR("DDE Post CB\n"); + Ret = post_dde_message( &data, Common->message, Common->lParam, &Common->lParam); + + if (Ret) + { + if (Common->size >= data.size) + { + if (data.data) RtlCopyMemory(&Common->buffer, data.data, data.size); + } + Common->size = data.size; + ERR("DDE Post CB size %d\n",data.size); + } + else + { + ERR("Return bad msg 0x%x Size %d\n",Common->message,Common->size); + } + + return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); +} + +NTSTATUS +WINAPI +User32CallDDEGetFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + BOOL Ret; + PDDEPOSTGET_CALLBACK_ARGUMENTS Common = Arguments; + + ERR("DDE Get CB size %d\n",Common->size); + + Ret = unpack_dde_message( Common->hwnd, Common->message, &Common->lParam, Common->buffer, Common->size ); + + return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); +} + + + /* * @unimplemented */ diff --git a/reactos/win32ss/user/user32/misc/dllmain.c b/reactos/win32ss/user/user32/misc/dllmain.c index da8a767a351..29285600fdc 100644 --- a/reactos/win32ss/user/user32/misc/dllmain.c +++ b/reactos/win32ss/user/user32/misc/dllmain.c @@ -203,6 +203,8 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] = User32CallCopyImageFromKernel, User32CallSetWndIconsFromKernel, User32DeliverUserAPC, + User32CallDDEPostFromKernel, + User32CallDDEGetFromKernel, }; diff --git a/reactos/win32ss/user/user32/windows/message.c b/reactos/win32ss/user/user32/windows/message.c index 751754dbcb0..fe9bbbb9737 100644 --- a/reactos/win32ss/user/user32/windows/message.c +++ b/reactos/win32ss/user/user32/windows/message.c @@ -163,7 +163,7 @@ static unsigned DdeNumAlloc = 0; static unsigned DdeNumUsed = 0; static CRITICAL_SECTION DdeCrst; -static BOOL FASTCALL +BOOL FASTCALL DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem) { unsigned i; @@ -213,7 +213,7 @@ DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem) return TRUE; } -static HGLOBAL FASTCALL +HGLOBAL FASTCALL DdeGetPair(HGLOBAL ServerMem) { unsigned i; @@ -357,67 +357,12 @@ MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted) switch (UMMsg->message) { - case WM_DDE_ACK: - { - PDDEPACK DdeLparam; - DdeLparam = HeapAlloc(GetProcessHeap(), 0, sizeof(DDEPACK)); - if (!DdeLparam || - !UnpackDDElParam( UMMsg->message, UMMsg->lParam, &DdeLparam->uiLo, &DdeLparam->uiHi)) - return FALSE; - /* - If this is a reply to WM_DDE_EXECUTE then - uiHi will contain a hMem, hence >= 0x10000. - Otherwise, it will be be an atom, a 16-bit value. - */ - if (!IS_ATOM(DdeLparam->uiHi)) - { - HGLOBAL h = DdeGetPair((HGLOBAL)(ULONG_PTR)DdeLparam->uiHi); - if (h) - { - GlobalFree((HGLOBAL)(ULONG_PTR)DdeLparam->uiHi); - DdeLparam->uiHi = (UINT_PTR) h; - } - } - FreeDDElParam(UMMsg->message, UMMsg->lParam); - KMMsg->lParam = (LPARAM) DdeLparam; - } - break; - - case WM_DDE_EXECUTE: - { - SIZE_T Size; - PKMDDEEXECUTEDATA KMDdeExecuteData; - PVOID Data; - - Size = GlobalSize((HGLOBAL) UMMsg->lParam); - Data = GlobalLock((HGLOBAL) UMMsg->lParam); - if (!Data) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - KMDdeExecuteData = HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA) + Size); - if (!KMDdeExecuteData) - { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - KMDdeExecuteData->Sender = (HWND) UMMsg->wParam; - KMDdeExecuteData->ClientMem = (HGLOBAL) UMMsg->lParam; - memcpy((PVOID) (KMDdeExecuteData + 1), Data, Size); - KMMsg->wParam = sizeof(KMDDEEXECUTEDATA) + Size; - KMMsg->lParam = (LPARAM) KMDdeExecuteData; - GlobalUnlock((HGLOBAL) UMMsg->lParam); - } - break; - case WM_COPYDATA: { PCOPYDATASTRUCT pUMCopyData = (PCOPYDATASTRUCT)UMMsg->lParam; PCOPYDATASTRUCT pKMCopyData; - pKMCopyData = HeapAlloc(GetProcessHeap(), 0, - sizeof(COPYDATASTRUCT) + pUMCopyData->cbData); + pKMCopyData = HeapAlloc(GetProcessHeap(), 0, sizeof(COPYDATASTRUCT) + pUMCopyData->cbData); if (!pKMCopyData) { SetLastError(ERROR_OUTOFMEMORY); @@ -428,8 +373,7 @@ MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted) pKMCopyData->cbData = pUMCopyData->cbData; pKMCopyData->lpData = pKMCopyData + 1; - RtlCopyMemory(pKMCopyData + 1, pUMCopyData->lpData, - pUMCopyData->cbData); + RtlCopyMemory(pKMCopyData + 1, pUMCopyData->lpData, pUMCopyData->cbData); KMMsg->lParam = (LPARAM)pKMCopyData; } @@ -448,8 +392,6 @@ MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg) { switch (KMMsg->message) { - case WM_DDE_ACK: - case WM_DDE_EXECUTE: case WM_COPYDATA: HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam); break; @@ -465,6 +407,8 @@ MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg) { *UMMsg = *KMMsg; + if (KMMsg->lParam == 0) return TRUE; + switch (UMMsg->message) { case WM_CREATE: @@ -488,43 +432,6 @@ MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg) } break; - case WM_DDE_ACK: - { - PDDEPACK DdeLparam = (PDDEPACK) KMMsg->lParam; - UMMsg->lParam = PackDDElParam(KMMsg->message, DdeLparam->uiLo, DdeLparam->uiHi); - } - break; - - case WM_DDE_EXECUTE: - { - PKMDDEEXECUTEDATA KMDdeExecuteData; - HGLOBAL GlobalData; - PVOID Data; - - KMDdeExecuteData = (PKMDDEEXECUTEDATA) KMMsg->lParam; - GlobalData = GlobalAlloc(GMEM_MOVEABLE, KMMsg->wParam - sizeof(KMDDEEXECUTEDATA)); - if (!GlobalData) - { - return FALSE; - } - Data = GlobalLock(GlobalData); - if (!Data) - { - GlobalFree(GlobalData); - return FALSE; - } - memcpy(Data, (PVOID) (KMDdeExecuteData + 1), KMMsg->wParam - sizeof(KMDDEEXECUTEDATA)); - GlobalUnlock(GlobalData); - if (!DdeAddPair(KMDdeExecuteData->ClientMem, GlobalData)) - { - GlobalFree(GlobalData); - return FALSE; - } - UMMsg->wParam = (WPARAM) KMDdeExecuteData->Sender; - UMMsg->lParam = (LPARAM) GlobalData; - } - break; - case WM_COPYDATA: { PCOPYDATASTRUCT pKMCopyData = (PCOPYDATASTRUCT)KMMsg->lParam; @@ -2967,6 +2874,11 @@ User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) KMMsg.lParam = (LPARAM) ((char *) CallbackArgs + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)); switch(KMMsg.message) { + case WM_SYSTIMER: + { + ERR("WM_SYSTIMER %p\n",KMMsg.hwnd); + break; + } case WM_SIZING: { PRECT prect = (PRECT) KMMsg.lParam;