mirror of
https://github.com/reactos/reactos.git
synced 2025-04-04 04:26:32 +00:00
[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
This commit is contained in:
parent
418366bf44
commit
2d94b2173f
11 changed files with 671 additions and 159 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ***************/
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -203,6 +203,8 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
|
|||
User32CallCopyImageFromKernel,
|
||||
User32CallSetWndIconsFromKernel,
|
||||
User32DeliverUserAPC,
|
||||
User32CallDDEPostFromKernel,
|
||||
User32CallDDEGetFromKernel,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue