Leaked source code of windows server 2003
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.
 
 
 
 
 
 

543 lines
16 KiB

/****************************** Module Header ******************************\
* Module Name: callback.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* DDE Manager callback related functions
*
* Created: 11/11/91 Sanford Staab
*
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* DoCallback
*
* Description:
* Performs a synchronous callback to the given instance's callback proc.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
HDDEDATA DoCallback(
PCL_INSTANCE_INFO pcii,
WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hData,
ULONG_PTR dw1,
ULONG_PTR dw2)
{
HDDEDATA hDataRet;
PCLIENTINFO pci;
CheckDDECritIn;
/*
* Zombie conversations don't generate callbacks!
*/
if (hConv && TypeFromHandle(hConv) == HTYPE_ZOMBIE_CONVERSATION) {
return(0);
}
pci = GetClientInfo();
pci->cInDDEMLCallback++;
pcii->cInDDEMLCallback++;
LeaveDDECrit;
CheckDDECritOut;
/*
* Bug 246472 - joejo
* fixup all DDE Callbacks since some apps make their callbacks
* C-Style instead of PASCAL.
*/
hDataRet = UserCallDDECallback(*pcii->pfnCallback, (UINT)wType, (UINT)wFmt, hConv, hsz1, hsz2,
hData, dw1, dw2);
EnterDDECrit;
pcii->cInDDEMLCallback--;
pci->cInDDEMLCallback--;
if (!(pcii->afCmd & APPCLASS_MONITOR) && pcii->MonitorFlags & MF_CALLBACKS) {
PEVENT_PACKET pep;
pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) +
sizeof(MONCBSTRUCT));
if (pep != NULL) {
pep->EventType = MF_CALLBACKS;
pep->fSense = TRUE;
pep->cbEventData = sizeof(MONCBSTRUCT);
#define pcbs ((MONCBSTRUCT *)&pep->Data)
pcbs->cb = sizeof(MONCBSTRUCT);
pcbs->dwTime = NtGetTickCount();
pcbs->hTask = (HANDLE)LongToHandle( pcii->tid );
pcbs->dwRet = HandleToUlong(hDataRet);
pcbs->wType = wType;
pcbs->wFmt = wFmt;
pcbs->hConv = hConv;
pcbs->hsz1 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1));
pcbs->hsz2 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz2));
pcbs->hData = hData;
pcbs->dwData1 = dw1;
pcbs->dwData2 = dw2;
if (((wType == XTYP_CONNECT) || (wType == XTYP_WILDCONNECT)) && dw1) {
RtlCopyMemory(&pcbs->cc, (PVOID)dw1, sizeof(CONVCONTEXT));
}
LeaveDDECrit;
if (wType & XCLASS_DATA) {
if (hDataRet && hDataRet != CBR_BLOCK) {
pcbs->cbData = DdeGetData(hDataRet, (LPBYTE)pcbs->Data, 32, 0);
}
} else if (hData) {
pcbs->cbData = DdeGetData(hData, (LPBYTE)pcbs->Data, 32, 0);
}
Event(pep);
EnterDDECrit;
GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz1));
GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz2));
DDEMLFree(pep);
#undef pcbs
}
}
return (hDataRet);
}
/***************************************************************************\
* _ClientEventCallback
*
* Description:
* Called from the server side to perform event callbacks.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
DWORD _ClientEventCallback(
PCL_INSTANCE_INFO pcii,
PEVENT_PACKET pep)
{
HDDEDATA hData;
EnterDDECrit;
switch (pep->EventType) {
case 0: // MonitorFlags change event - everybody gets it
pcii->MonitorFlags = pep->Data;
break;
case MF_CALLBACKS:
{
MONCBSTRUCT mcb;
mcb = *((MONCBSTRUCT *)&pep->Data);
mcb.hsz1 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz1));
mcb.hsz2 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz2));
if ( mcb.wType == XTYP_REGISTER ||
mcb.wType == XTYP_UNREGISTER) {
mcb.hsz2 = INST_SPECIFIC_HSZ_FROM_LATOM((LATOM)(ULONG_PTR)mcb.hsz2);
}
hData = InternalCreateDataHandle(pcii, (LPSTR)&mcb,
pep->cbEventData, 0,
HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
if (hData) {
DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
pep->EventType);
InternalFreeDataHandle((HDDEDATA)hData, TRUE);
DeleteAtom(LATOM_FROM_HSZ(mcb.hsz1));
DeleteAtom(LATOM_FROM_HSZ(mcb.hsz2));
}
}
break;
case MF_LINKS:
{
MONLINKSTRUCT ml;
ml = *((MONLINKSTRUCT *)&pep->Data);
ml.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszSvc));
ml.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszTopic));
ml.hszItem = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszItem));
hData = InternalCreateDataHandle(pcii, (LPSTR)&ml,
pep->cbEventData, 0,
HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
if (hData) {
DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
pep->EventType);
InternalFreeDataHandle((HDDEDATA)hData, TRUE);
DeleteAtom(LATOM_FROM_HSZ(ml.hszSvc));
DeleteAtom(LATOM_FROM_HSZ(ml.hszTopic));
DeleteAtom(LATOM_FROM_HSZ(ml.hszItem));
}
}
break;
case MF_CONV:
{
MONCONVSTRUCT mc;
mc = *((MONCONVSTRUCT *)&pep->Data);
mc.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszSvc));
mc.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszTopic));
hData = InternalCreateDataHandle(pcii, (LPSTR)&mc,
pep->cbEventData, 0,
HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
if (hData) {
DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
pep->EventType);
InternalFreeDataHandle((HDDEDATA)hData, TRUE);
DeleteAtom(LATOM_FROM_HSZ(mc.hszSvc));
DeleteAtom(LATOM_FROM_HSZ(mc.hszTopic));
}
}
break;
case MF_HSZ_INFO:
if (!(pcii->flags & IIF_UNICODE)) {
LPSTR pszAnsi;
/*
* Translate HSZ string back into ANSI
*/
if (WCSToMB(((PMONHSZSTRUCT)&pep->Data)->str,
((int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb) / sizeof(WCHAR),
&pszAnsi,
(int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb,
TRUE)) {
strcpy(((PMONHSZSTRUCTA)&pep->Data)->str, pszAnsi);
UserLocalFree(pszAnsi);
}
((PMONHSZSTRUCT)&pep->Data)->cb = sizeof(MONHSZSTRUCTA);
}
// fall through
case MF_SENDMSGS:
case MF_POSTMSGS:
if (pep->EventType == MF_POSTMSGS) {
PMONMSGSTRUCT pmms = (PMONMSGSTRUCT)&pep->Data;
BYTE buf[32];
/*
* We may need to translate the Execute string to/from
* UNICODE depending on what type of monitor this is
* going to.
*/
if (pmms->wMsg == WM_DDE_EXECUTE) {
BOOL fUnicodeText;
int flags;
flags = (IS_TEXT_UNICODE_UNICODE_MASK |
IS_TEXT_UNICODE_REVERSE_MASK |
(IS_TEXT_UNICODE_NOT_UNICODE_MASK &
(~IS_TEXT_UNICODE_ILLEGAL_CHARS)) |
IS_TEXT_UNICODE_NOT_ASCII_MASK);
#ifdef ISTEXTUNICODE_WORKS
fUnicodeText = RtlIsTextUnicode(pmms->dmhd.Data,
min(32, pmms->dmhd.cbData), &flags);
#else
fUnicodeText = (*(LPSTR)pmms->dmhd.Data == '\0');
#endif
if (pcii->flags & IIF_UNICODE && !fUnicodeText) {
/* Ascii->UNICODE */
RtlMultiByteToUnicodeN((LPWSTR)buf, 32, NULL,
(LPSTR)&pmms->dmhd.Data,
min(32, pmms->dmhd.cbData));
RtlCopyMemory(&pmms->dmhd.Data, buf, 32);
} else if (!(pcii->flags & IIF_UNICODE) && fUnicodeText) {
/* UNICODE->Ascii */
RtlUnicodeToMultiByteN((LPSTR)buf, 32, NULL,
(LPWSTR)&pmms->dmhd.Data,
min(32, pmms->dmhd.cbData));
RtlCopyMemory(&pmms->dmhd.Data, buf, 32);
}
}
}
case MF_ERRORS:
hData = InternalCreateDataHandle(pcii, (LPSTR)&pep->Data,
pep->cbEventData, 0,
HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0);
if (hData) {
DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L,
pep->EventType);
InternalFreeDataHandle((HDDEDATA)hData, TRUE);
}
break;
}
LeaveDDECrit;
return (0);
}
/***************************************************************************\
* EnableEnumProc
*
* Description:
* Helper function for applying pees->wCmd to each client and server
* DDEML window.
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
BOOL EnableEnumProc(
HWND hwnd,
PENABLE_ENUM_STRUCT pees)
{
PCONV_INFO pcoi;
for (pcoi = (PCONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI);
pcoi != NULL; pcoi = pcoi->next) {
pcoi->cLocks++;
*pees->pfRet |= SetEnableState(pcoi, pees->wCmd);
if (pees->wCmd2) {
/*
* Only let ES_CHECKQUEUEONCE be done on one window but
* don't stop the wCmd from getting to all the other
* windows.
*/
if (SetEnableState(pcoi, pees->wCmd2) &&
pees->wCmd2 == EC_CHECKQUEUEONCE) {
pees->wCmd2 = 0;
}
}
pcoi->cLocks--;
if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
FreeConversationResources(pcoi);
break;
}
}
return (TRUE);
}
/***************************************************************************\
* DdeEnableCallback (DDEML API)
*
* Description:
* Turns on and off asynchronous callbacks (BLOCKABLE).
*
* History:
* 11-12-91 sanfords Created.
\***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeEnableCallback, DWORD, idInst, HCONV, hConv, UINT, wCmd)
BOOL DdeEnableCallback(
DWORD idInst,
HCONV hConv,
UINT wCmd)
{
BOOL fRet = FALSE;
PCL_INSTANCE_INFO pcii;
PCONV_INFO pcoi;
ENABLE_ENUM_STRUCT ees;
EnterDDECrit;
pcii = (PCL_INSTANCE_INFO)ValidateInstance((HANDLE)LongToHandle( idInst ));
if (pcii == NULL) {
BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
goto Exit;
}
switch (wCmd) {
case EC_QUERYWAITING:
case EC_DISABLE:
case EC_ENABLEONE:
case EC_ENABLEALL:
break;
default:
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
goto Exit;
}
if (hConv) {
pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
HTYPE_CLIENT_CONVERSATION, InstFromHandle(idInst));
if (pcoi == NULL) {
pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
HTYPE_SERVER_CONVERSATION, InstFromHandle(idInst));
}
if (pcoi == NULL) {
SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
goto Exit;
}
pcoi->cLocks++;
fRet = SetEnableState(pcoi, wCmd);
switch (wCmd) {
case EC_ENABLEALL:
case EC_ENABLEONE:
CheckForQueuedMessages(pcoi);
}
pcoi->cLocks--;
if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) {
FreeConversationResources(pcoi);
}
} else {
if (wCmd == EC_ENABLEONE) {
wCmd = EC_ENABLEONEOFALL;
}
switch (wCmd) {
case EC_ENABLEONEOFALL:
pcii->ConvStartupState = ST_BLOCKNEXT | ST_BLOCKALLNEXT;
break;
case EC_DISABLE:
pcii->ConvStartupState = ST_BLOCKED;
break;
case EC_ENABLEALL:
pcii->ConvStartupState = 0;
break;
}
ees.pfRet = &fRet;
ees.wCmd = (WORD)wCmd;
switch (wCmd) {
case EC_ENABLEALL:
ees.wCmd2 = EC_CHECKQUEUE;
break;
case EC_ENABLEONEOFALL:
ees.wCmd2 = EC_CHECKQUEUEONCE;
break;
default:
ees.wCmd2 = 0;
}
EnumChildWindows(pcii->hwndMother, (WNDENUMPROC)EnableEnumProc,
(LPARAM)&ees);
}
Exit:
LeaveDDECrit;
return (fRet);
}
/***************************************************************************\
* SetEnableState
*
* Description:
* Sets the given conversation's enable state based on the EC_ flag
* given.
*
* Returns: fSuccess/fProcessed.
*
* History:
* 11-19-91 sanfords Created.
\***************************************************************************/
BOOL SetEnableState(
PCONV_INFO pcoi,
UINT wCmd)
{
BOOL fRet = TRUE;
switch (wCmd) {
case EC_CHECKQUEUEONCE:
case EC_CHECKQUEUE:
fRet = CheckForQueuedMessages(pcoi);
break;
case EC_QUERYWAITING:
fRet = !(pcoi->dmqOut == NULL ||
(pcoi->dmqOut->next == NULL &&
GetClientInfo()->CI_flags & CI_PROCESSING_QUEUE));
break;
case EC_DISABLE:
pcoi->state |= ST_BLOCKED;
pcoi->state &= ~(ST_BLOCKNEXT | ST_BLOCKALLNEXT);
break;
case EC_ENABLEONE:
pcoi->state &= ~ST_BLOCKED;
pcoi->state |= ST_BLOCKNEXT;
break;
case EC_ENABLEONEOFALL:
pcoi->state &= ~ST_BLOCKED;
pcoi->state |= (ST_BLOCKNEXT | ST_BLOCKALLNEXT);
break;
case EC_ENABLEALL:
pcoi->state &= ~(ST_BLOCKED | ST_BLOCKNEXT | ST_BLOCKALLNEXT);
break;
default:
return(FALSE);
}
return (fRet);
}
/***************************************************************************\
* _ClientGetDDEHookData
*
* Description:
* Callback from server to extract data from lParam and place it into
* the pdmhd for use by DDESPY apps. This does a very similar thing
* to the CopyDDEDataIn/Out apis but this only grabs a limited amount
* of the data suitable for posting to the DDESPY app(s). This should
* be merged with the Copy APIs eventually.
*
* History:
* 12-16-91 sanfords Created.
\***************************************************************************/
DWORD _ClientGetDDEHookData(
UINT message,
LPARAM lParam,
PDDEML_MSG_HOOK_DATA pdmhd)
{
PBYTE pb;
HANDLE hDDE;
UnpackDDElParam(message, lParam, &pdmhd->uiLo, &pdmhd->uiHi);
switch (message) {
case WM_DDE_DATA:
case WM_DDE_POKE:
case WM_DDE_ADVISE:
hDDE = (HANDLE)pdmhd->uiLo;
break;
case WM_DDE_EXECUTE:
hDDE = (HANDLE)pdmhd->uiHi;
break;
case WM_DDE_ACK:
case WM_DDE_REQUEST:
case WM_DDE_UNADVISE:
case WM_DDE_TERMINATE:
pdmhd->cbData = 0;
return (1);
}
pdmhd->cbData = (DWORD)UserGlobalSize(hDDE);
if (pdmhd->cbData) {
USERGLOBALLOCK(hDDE, pb);
if (pb == NULL) {
pdmhd->cbData = 0;
} else {
RtlCopyMemory(&pdmhd->Data, pb, min(pdmhd->cbData,
sizeof(DDEML_MSG_HOOK_DATA) -
FIELD_OFFSET(DDEML_MSG_HOOK_DATA, Data)));
USERGLOBALUNLOCK(hDDE);
}
}
return (1);
}