- 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
This commit is contained in:
James Tabor 2015-01-08 00:56:51 +00:00
parent 418366bf44
commit 2d94b2173f
11 changed files with 671 additions and 159 deletions

View file

@ -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 */

View file

@ -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;

View file

@ -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

View file

@ -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(

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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 ***************/

View file

@ -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
*/

View file

@ -203,6 +203,8 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
User32CallCopyImageFromKernel,
User32CallSetWndIconsFromKernel,
User32DeliverUserAPC,
User32CallDDEPostFromKernel,
User32CallDDEGetFromKernel,
};

View file

@ -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;