You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
9.3 KiB
327 lines
9.3 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: event.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* DDE Manager event module - this is a fancy way of allowing interprocess
|
|
* communication across security contexts. This is needed because the
|
|
* DDE Access Object security may be different than hwnd security so
|
|
* straight messages arn't good enough.
|
|
*
|
|
* Created: 8/27/91 Sanford Staab
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
DWORD MonitorFlags = 0; // current filter flags being monitored by someone.
|
|
|
|
typedef struct tagMONITOR_COUNT {
|
|
int iCount;
|
|
DWORD flag;
|
|
} MONITOR_COUNT, *PMONITOR_COUNT;
|
|
|
|
#define C_MONITOR_COUNT 10
|
|
|
|
MONITOR_COUNT aMonitorCount[C_MONITOR_COUNT] = {
|
|
{ 0, MF_HSZ_INFO },
|
|
{ 0, MF_SENDMSGS },
|
|
{ 0, MF_POSTMSGS },
|
|
{ 0, MF_CALLBACKS },
|
|
{ 0, MF_ERRORS },
|
|
{ 0, MF_LINKS },
|
|
{ 0, MF_CONV },
|
|
{ 0, CBF_SKIP_REGISTRATIONS },
|
|
{ 0, CBF_SKIP_UNREGISTRATIONS },
|
|
{ 0, MF_INTERNAL },
|
|
};
|
|
|
|
#define MONITORED_FLAGS \
|
|
MF_HSZ_INFO | \
|
|
MF_SENDMSGS | \
|
|
MF_POSTMSGS | \
|
|
MF_CALLBACKS | \
|
|
MF_ERRORS | \
|
|
MF_LINKS | \
|
|
MF_CONV | \
|
|
CBF_SKIP_REGISTRATIONS | \
|
|
CBF_SKIP_UNREGISTRATIONS | \
|
|
MF_INTERNAL
|
|
|
|
|
|
/***************************************************************************\
|
|
* ChangeMonitorFlags
|
|
*
|
|
* Description:
|
|
* Updates the global MonitorFlags variable to reflect the union of all
|
|
* event types being monitored by DDEML applications.
|
|
*
|
|
* History:
|
|
* 11-26-91 sanfords Created.
|
|
\***************************************************************************/
|
|
VOID xxxChangeMonitorFlags(
|
|
PSVR_INSTANCE_INFO psii,
|
|
DWORD afCmdNew)
|
|
{
|
|
int i;
|
|
DWORD dwChangedFlags;
|
|
DWORD OldMonitorFlags;
|
|
|
|
CheckCritIn();
|
|
|
|
dwChangedFlags = psii->afCmd ^ afCmdNew;
|
|
/*
|
|
* Due to the way MONITORED_FLAGS was defined, this if stmt is always
|
|
* false. Since it's been this way since day 1, it's now a feature.
|
|
* Bug #105937.
|
|
*
|
|
* if (!(dwChangedFlags & MONITORED_FLAGS)) {
|
|
* return;
|
|
* }
|
|
*/
|
|
psii->afCmd = afCmdNew;
|
|
|
|
OldMonitorFlags = MonitorFlags;
|
|
MonitorFlags = 0;
|
|
for (i = 0; i < C_MONITOR_COUNT; i++) {
|
|
if (dwChangedFlags & aMonitorCount[i].flag) {
|
|
if (aMonitorCount[i].flag & afCmdNew) {
|
|
aMonitorCount[i].iCount++;
|
|
} else {
|
|
aMonitorCount[i].iCount--;
|
|
}
|
|
}
|
|
if (aMonitorCount[i].iCount) {
|
|
MonitorFlags |= aMonitorCount[i].flag;
|
|
}
|
|
}
|
|
if (OldMonitorFlags != MonitorFlags) {
|
|
EVENT_PACKET ep;
|
|
|
|
ep.EventType = 0;
|
|
ep.fSense = FALSE;
|
|
ep.cbEventData = sizeof(DWORD);
|
|
ep.Data = MonitorFlags;
|
|
xxxCsEvent(&ep, sizeof(DWORD));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* xxxCsEvent
|
|
*
|
|
* Description:
|
|
* Handles broadcasting of all types of DDEML events.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
* 10-28-97 FritzS added cbEventData as a passed-in parameter. This was
|
|
done because the EVENT_PACKET may be client-side and
|
|
we capture the count to keep a hostile app from changing
|
|
the size after data probing.
|
|
\***************************************************************************/
|
|
DWORD xxxCsEvent(
|
|
PEVENT_PACKET pep, WORD cbEventData)
|
|
{
|
|
PSVR_INSTANCE_INFO psiiT;
|
|
PEVENT_PACKET pep2;
|
|
HWND *ahwndEvent = NULL;
|
|
PWND pwnd;
|
|
int cHwndAllocated, i, cTargets;
|
|
TL tlpwnd;
|
|
TL tlpep2;
|
|
TL tlahwndEvent;
|
|
ULONG cbEventPacket;
|
|
PTHREADINFO pti = PtiCurrent();
|
|
|
|
CheckCritIn();
|
|
|
|
/*
|
|
* Copy pep info to a server side stable area
|
|
*/
|
|
cbEventPacket = cbEventData + sizeof(EVENT_PACKET) - sizeof(DWORD);
|
|
pep2 = (PEVENT_PACKET)UserAllocPoolWithQuota(cbEventPacket, TAG_DDE5);
|
|
if (pep2 == NULL) {
|
|
return DMLERR_MEMORY_ERROR;
|
|
}
|
|
try {
|
|
RtlCopyMemory((LPSTR)pep2, (LPSTR)pep, cbEventPacket);
|
|
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
|
|
UserFreePool(pep2);
|
|
return DMLERR_INVALIDPARAMETER;
|
|
}
|
|
|
|
pep2->cbEventData = cbEventData;
|
|
cTargets = 0;
|
|
cHwndAllocated = 0;
|
|
|
|
for (psiiT = psiiList; psiiT != NULL; psiiT = psiiT->next) {
|
|
//
|
|
// Don't bother with event windows for instances who's flags
|
|
// indicate they're not interrested in the event.
|
|
//
|
|
if (((psiiT->afCmd & pep2->EventType) && !pep2->fSense) ||
|
|
(!(psiiT->afCmd & pep2->EventType) && pep2->fSense)) {
|
|
continue;
|
|
}
|
|
|
|
if (cTargets >= cHwndAllocated) {
|
|
if (ahwndEvent == NULL) {
|
|
cHwndAllocated = 8;
|
|
ahwndEvent = (HWND *)UserAllocPoolWithQuota(
|
|
sizeof(HWND) * cHwndAllocated,
|
|
TAG_DDE6);
|
|
} else {
|
|
DWORD dwSize = cHwndAllocated * sizeof(HWND);
|
|
HWND *ahwndEventT = ahwndEvent;
|
|
|
|
cHwndAllocated += 8;
|
|
ahwndEvent = (HWND *)UserReAllocPoolWithQuota(ahwndEvent, dwSize,
|
|
sizeof(HWND) * cHwndAllocated, TAG_DDE7);
|
|
if (ahwndEvent == NULL) {
|
|
UserFreePool(ahwndEventT);
|
|
}
|
|
}
|
|
if (ahwndEvent == NULL) {
|
|
UserFreePool(pep2);
|
|
return DMLERR_MEMORY_ERROR;
|
|
}
|
|
}
|
|
ahwndEvent[cTargets++] = PtoH(psiiT->spwndEvent);
|
|
}
|
|
|
|
ThreadLockPool(pti, pep2, &tlpep2);
|
|
if (ahwndEvent != NULL) {
|
|
ThreadLockPool(pti, ahwndEvent, &tlahwndEvent);
|
|
for (i = 0; i < cTargets; i++) {
|
|
/*
|
|
* We need to change contexts for the callback
|
|
*/
|
|
pwnd = ValidateHwnd(ahwndEvent[i]);
|
|
if (pwnd != NULL) {
|
|
ThreadLockAlwaysWithPti(pti, pwnd, &tlpwnd);
|
|
xxxSendMessage(pwnd, WM_DDEMLEVENT, 0, (LPARAM)pep2);
|
|
ThreadUnlock(&tlpwnd);
|
|
}
|
|
}
|
|
ThreadUnlockAndFreePool(pti, &tlahwndEvent);
|
|
}
|
|
ThreadUnlockAndFreePool(pti, &tlpep2);
|
|
|
|
return DMLERR_NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* xxxEventWndProc
|
|
*
|
|
* Description:
|
|
* Window proc for DDEML event windows. These windows serve to get user
|
|
* into the proper context for callbacks to DDEML applications.
|
|
*
|
|
* History:
|
|
* 11-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
LRESULT xxxEventWndProc(
|
|
PWND pwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PSVR_INSTANCE_INFO psii;
|
|
|
|
CheckCritIn();
|
|
CheckLock(pwnd);
|
|
|
|
psii = HMValidateHandleNoRip((HANDLE)_GetWindowLongPtr(pwnd, GWLP_PSII),
|
|
TYPE_DDEACCESS);
|
|
if (psii == NULL) {
|
|
goto CallDWP;
|
|
}
|
|
|
|
switch (message) {
|
|
case WM_DDEMLEVENT:
|
|
#define pep ((PEVENT_PACKET)lParam)
|
|
if (((psii->afCmd & pep->EventType) && pep->fSense) ||
|
|
(!(psii->afCmd & pep->EventType) && !pep->fSense)) {
|
|
ClientEventCallback(psii->pcii, pep);
|
|
}
|
|
#undef pep
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
xxxChangeMonitorFlags(psii, 0);
|
|
break;
|
|
|
|
default:
|
|
CallDWP:
|
|
return xxxDefWindowProc(pwnd, message, wParam, lParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************\
|
|
* xxxMessageEvent
|
|
*
|
|
* Description: Called when a hooked DDE message is sent or posted. flags
|
|
* specifies the applicable MF_ flag. This is called in the server side
|
|
* context of the sender or poster which may or may not be a DDEML process.
|
|
* pdmhd contains DDE data extracted and copied from the client side.
|
|
*
|
|
* History:
|
|
* 12-1-91 sanfords Created.
|
|
\***************************************************************************/
|
|
VOID xxxMessageEvent(
|
|
PWND pwndTo,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
DWORD flag,
|
|
PDDEML_MSG_HOOK_DATA pdmhd)
|
|
{
|
|
PEVENT_PACKET pep;
|
|
PWND pwndFrom;
|
|
TL tlpep;
|
|
PTHREADINFO pti;
|
|
|
|
CheckCritIn();
|
|
|
|
pep = (PEVENT_PACKET)UserAllocPoolWithQuota(sizeof(EVENT_PACKET) -
|
|
sizeof(DWORD) + sizeof(MONMSGSTRUCT), TAG_DDE8);
|
|
if (pep == NULL) {
|
|
return;
|
|
}
|
|
pep->EventType = flag;
|
|
pep->fSense = TRUE;
|
|
pep->cbEventData = sizeof(MONMSGSTRUCT);
|
|
#define pmsgs ((MONMSGSTRUCT *)&pep->Data)
|
|
pmsgs->cb = sizeof(MONMSGSTRUCT);
|
|
pmsgs->hwndTo = PtoH(pwndTo);
|
|
pmsgs->dwTime = NtGetTickCount();
|
|
|
|
pwndFrom = RevalidateHwnd((HWND)wParam);
|
|
if (pwndFrom != NULL) {
|
|
pmsgs->hTask = GETPTIID(GETPTI(pwndFrom));
|
|
} else {
|
|
pmsgs->hTask = 0;
|
|
}
|
|
|
|
pmsgs->wMsg = message;
|
|
pmsgs->wParam = wParam;
|
|
pmsgs->lParam = lParam;
|
|
if (pdmhd != NULL) {
|
|
pmsgs->dmhd = *pdmhd;
|
|
}
|
|
#undef pmsgs
|
|
pti = PtiCurrent();
|
|
ThreadLockPool(pti, pep, &tlpep);
|
|
xxxCsEvent(pep, sizeof(MONMSGSTRUCT));
|
|
ThreadUnlockAndFreePool(pti, &tlpep);
|
|
}
|