Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

callback.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: callback.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * DDE Manager callback related functions 00007 * 00008 * Created: 11/11/91 Sanford Staab 00009 * 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 /***************************************************************************\ 00016 * DoCallback 00017 * 00018 * Description: 00019 * Performs a synchronous callback to the given instance's callback proc. 00020 * 00021 * History: 00022 * 11-12-91 sanfords Created. 00023 \***************************************************************************/ 00024 HDDEDATA DoCallback( 00025 PCL_INSTANCE_INFO pcii, 00026 WORD wType, 00027 WORD wFmt, 00028 HCONV hConv, 00029 HSZ hsz1, 00030 HSZ hsz2, 00031 HDDEDATA hData, 00032 ULONG_PTR dw1, 00033 ULONG_PTR dw2) 00034 { 00035 HDDEDATA hDataRet; 00036 PCLIENTINFO pci; 00037 00038 CheckDDECritIn; 00039 00040 00041 /* 00042 * Zombie conversations don't generate callbacks! 00043 */ 00044 if (hConv && TypeFromHandle(hConv) == HTYPE_ZOMBIE_CONVERSATION) { 00045 return(0); 00046 } 00047 00048 pci = GetClientInfo(); 00049 pci->cInDDEMLCallback++; 00050 00051 pcii->cInDDEMLCallback++; 00052 LeaveDDECrit; 00053 CheckDDECritOut; 00054 00055 /* 00056 * Bug 246472 - joejo 00057 * fixup all DDE Callbacks since some apps make their callbacks 00058 * C-Style instead of PASCAL. 00059 */ 00060 hDataRet = UserCallDDECallback(*pcii->pfnCallback, (UINT)wType, (UINT)wFmt, hConv, hsz1, hsz2, 00061 hData, dw1, dw2); 00062 00063 EnterDDECrit; 00064 pcii->cInDDEMLCallback--; 00065 pci->cInDDEMLCallback--; 00066 00067 if (!(pcii->afCmd & APPCLASS_MONITOR) && pcii->MonitorFlags & MF_CALLBACKS) { 00068 PEVENT_PACKET pep; 00069 00070 pep = (PEVENT_PACKET)DDEMLAlloc(sizeof(EVENT_PACKET) - sizeof(DWORD) + 00071 sizeof(MONCBSTRUCT)); 00072 if (pep != NULL) { 00073 00074 pep->EventType = MF_CALLBACKS; 00075 pep->fSense = TRUE; 00076 pep->cbEventData = sizeof(MONCBSTRUCT); 00077 00078 #define pcbs ((MONCBSTRUCT *)&pep->Data) 00079 pcbs->cb = sizeof(MONCBSTRUCT); 00080 pcbs->dwTime = NtGetTickCount(); 00081 pcbs->hTask = (HANDLE)LongToHandle( pcii->tid ); 00082 pcbs->dwRet = HandleToUlong(hDataRet); 00083 pcbs->wType = wType; 00084 pcbs->wFmt = wFmt; 00085 pcbs->hConv = hConv; 00086 pcbs->hsz1 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1)); 00087 pcbs->hsz2 = (HSZ)LocalToGlobalAtom(LATOM_FROM_HSZ(hsz2)); 00088 pcbs->hData = hData; 00089 pcbs->dwData1 = dw1; 00090 pcbs->dwData2 = dw2; 00091 if (((wType == XTYP_CONNECT) || (wType == XTYP_WILDCONNECT)) && dw1) { 00092 RtlCopyMemory(&pcbs->cc, (PVOID)dw1, sizeof(CONVCONTEXT)); 00093 } 00094 00095 LeaveDDECrit; 00096 00097 if (wType & XCLASS_DATA) { 00098 if (hDataRet && hDataRet != CBR_BLOCK) { 00099 pcbs->cbData = DdeGetData(hDataRet, (LPBYTE)pcbs->Data, 32, 0); 00100 } 00101 } else if (hData) { 00102 pcbs->cbData = DdeGetData(hData, (LPBYTE)pcbs->Data, 32, 0); 00103 } 00104 00105 Event(pep); 00106 00107 EnterDDECrit; 00108 00109 GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz1)); 00110 GlobalDeleteAtom(LATOM_FROM_HSZ(pcbs->hsz2)); 00111 DDEMLFree(pep); 00112 #undef pcbs 00113 } 00114 } 00115 return (hDataRet); 00116 } 00117 00118 00119 00120 /***************************************************************************\ 00121 * _ClientEventCallback 00122 * 00123 * Description: 00124 * Called from the server side to perform event callbacks. 00125 * 00126 * History: 00127 * 11-12-91 sanfords Created. 00128 \***************************************************************************/ 00129 DWORD _ClientEventCallback( 00130 PCL_INSTANCE_INFO pcii, 00131 PEVENT_PACKET pep) 00132 { 00133 HDDEDATA hData; 00134 00135 EnterDDECrit; 00136 00137 switch (pep->EventType) { 00138 case 0: // MonitorFlags change event - everybody gets it 00139 pcii->MonitorFlags = pep->Data; 00140 break; 00141 00142 case MF_CALLBACKS: 00143 { 00144 MONCBSTRUCT mcb; 00145 00146 mcb = *((MONCBSTRUCT *)&pep->Data); 00147 mcb.hsz1 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz1)); 00148 mcb.hsz2 = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mcb.hsz2)); 00149 if ( mcb.wType == XTYP_REGISTER || 00150 mcb.wType == XTYP_UNREGISTER) { 00151 mcb.hsz2 = INST_SPECIFIC_HSZ_FROM_LATOM((LATOM)(ULONG_PTR)mcb.hsz2); 00152 } 00153 hData = InternalCreateDataHandle(pcii, (LPSTR)&mcb, 00154 pep->cbEventData, 0, 00155 HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0); 00156 if (hData) { 00157 DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L, 00158 pep->EventType); 00159 InternalFreeDataHandle((HDDEDATA)hData, TRUE); 00160 DeleteAtom(LATOM_FROM_HSZ(mcb.hsz1)); 00161 DeleteAtom(LATOM_FROM_HSZ(mcb.hsz2)); 00162 } 00163 } 00164 break; 00165 00166 case MF_LINKS: 00167 { 00168 MONLINKSTRUCT ml; 00169 00170 ml = *((MONLINKSTRUCT *)&pep->Data); 00171 ml.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszSvc)); 00172 ml.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszTopic)); 00173 ml.hszItem = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)ml.hszItem)); 00174 hData = InternalCreateDataHandle(pcii, (LPSTR)&ml, 00175 pep->cbEventData, 0, 00176 HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0); 00177 if (hData) { 00178 DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L, 00179 pep->EventType); 00180 InternalFreeDataHandle((HDDEDATA)hData, TRUE); 00181 DeleteAtom(LATOM_FROM_HSZ(ml.hszSvc)); 00182 DeleteAtom(LATOM_FROM_HSZ(ml.hszTopic)); 00183 DeleteAtom(LATOM_FROM_HSZ(ml.hszItem)); 00184 } 00185 } 00186 break; 00187 00188 case MF_CONV: 00189 { 00190 MONCONVSTRUCT mc; 00191 00192 mc = *((MONCONVSTRUCT *)&pep->Data); 00193 mc.hszSvc = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszSvc)); 00194 mc.hszTopic = NORMAL_HSZ_FROM_LATOM(GlobalToLocalAtom((GATOM)(ULONG_PTR)mc.hszTopic)); 00195 hData = InternalCreateDataHandle(pcii, (LPSTR)&mc, 00196 pep->cbEventData, 0, 00197 HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0); 00198 if (hData) { 00199 DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L, 00200 pep->EventType); 00201 InternalFreeDataHandle((HDDEDATA)hData, TRUE); 00202 DeleteAtom(LATOM_FROM_HSZ(mc.hszSvc)); 00203 DeleteAtom(LATOM_FROM_HSZ(mc.hszTopic)); 00204 } 00205 } 00206 break; 00207 00208 case MF_HSZ_INFO: 00209 if (!(pcii->flags & IIF_UNICODE)) { 00210 LPSTR pszAnsi; 00211 /* 00212 * Translate HSZ string back into ANSI 00213 */ 00214 if (WCSToMB(((PMONHSZSTRUCT)&pep->Data)->str, 00215 ((int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb) / sizeof(WCHAR), 00216 &pszAnsi, 00217 (int)pep->cbEventData - (int)((PMONHSZSTRUCT)&pep->Data)->cb, 00218 TRUE)) { 00219 strcpy(((PMONHSZSTRUCTA)&pep->Data)->str, pszAnsi); 00220 UserLocalFree(pszAnsi); 00221 } 00222 ((PMONHSZSTRUCT)&pep->Data)->cb = sizeof(MONHSZSTRUCTA); 00223 } 00224 // fall through 00225 case MF_SENDMSGS: 00226 case MF_POSTMSGS: 00227 if (pep->EventType == MF_POSTMSGS) { 00228 PMONMSGSTRUCT pmms = (PMONMSGSTRUCT)&pep->Data; 00229 BYTE buf[32]; 00230 00231 /* 00232 * We may need to translate the Execute string to/from 00233 * UNICODE depending on what type of monitor this is 00234 * going to. 00235 */ 00236 if (pmms->wMsg == WM_DDE_EXECUTE) { 00237 BOOL fUnicodeText; 00238 int flags; 00239 00240 flags = (IS_TEXT_UNICODE_UNICODE_MASK | 00241 IS_TEXT_UNICODE_REVERSE_MASK | 00242 (IS_TEXT_UNICODE_NOT_UNICODE_MASK & 00243 (~IS_TEXT_UNICODE_ILLEGAL_CHARS)) | 00244 IS_TEXT_UNICODE_NOT_ASCII_MASK); 00245 #ifdef ISTEXTUNICODE_WORKS 00246 fUnicodeText = RtlIsTextUnicode(pmms->dmhd.Data, 00247 min(32, pmms->dmhd.cbData), &flags); 00248 #else 00249 fUnicodeText = (*(LPSTR)pmms->dmhd.Data == '\0'); 00250 #endif 00251 00252 if (pcii->flags & IIF_UNICODE && !fUnicodeText) { 00253 /* Ascii->UNICODE */ 00254 RtlMultiByteToUnicodeN((LPWSTR)buf, 32, NULL, 00255 (LPSTR)&pmms->dmhd.Data, 00256 min(32, pmms->dmhd.cbData)); 00257 RtlCopyMemory(&pmms->dmhd.Data, buf, 32); 00258 } else if (!(pcii->flags & IIF_UNICODE) && fUnicodeText) { 00259 /* UNICODE->Ascii */ 00260 RtlUnicodeToMultiByteN((LPSTR)buf, 32, NULL, 00261 (LPWSTR)&pmms->dmhd.Data, 00262 min(32, pmms->dmhd.cbData)); 00263 RtlCopyMemory(&pmms->dmhd.Data, buf, 32); 00264 } 00265 } 00266 } 00267 case MF_ERRORS: 00268 hData = InternalCreateDataHandle(pcii, (LPSTR)&pep->Data, 00269 pep->cbEventData, 0, 00270 HDATA_NOAPPFREE | HDATA_READONLY | HDATA_EXECUTE, 0, 0); 00271 if (hData) { 00272 DoCallback(pcii, (WORD)XTYP_MONITOR, 0, 0, 0, 0, hData, 0L, 00273 pep->EventType); 00274 InternalFreeDataHandle((HDDEDATA)hData, TRUE); 00275 } 00276 break; 00277 } 00278 00279 LeaveDDECrit; 00280 return (0); 00281 } 00282 00283 00284 00285 /***************************************************************************\ 00286 * EnableEnumProc 00287 * 00288 * Description: 00289 * Helper function for applying pees->wCmd to each client and server 00290 * DDEML window. 00291 * 00292 * History: 00293 * 11-12-91 sanfords Created. 00294 \***************************************************************************/ 00295 BOOL EnableEnumProc( 00296 HWND hwnd, 00297 PENABLE_ENUM_STRUCT pees) 00298 { 00299 PCONV_INFO pcoi; 00300 00301 for (pcoi = (PCONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI); 00302 pcoi != NULL; pcoi = pcoi->next) { 00303 pcoi->cLocks++; 00304 *pees->pfRet |= SetEnableState(pcoi, pees->wCmd); 00305 if (pees->wCmd2) { 00306 /* 00307 * Only let ES_CHECKQUEUEONCE be done on one window but 00308 * don't stop the wCmd from getting to all the other 00309 * windows. 00310 */ 00311 if (SetEnableState(pcoi, pees->wCmd2) && 00312 pees->wCmd2 == EC_CHECKQUEUEONCE) { 00313 pees->wCmd2 = 0; 00314 } 00315 } 00316 pcoi->cLocks--; 00317 if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) { 00318 FreeConversationResources(pcoi); 00319 break; 00320 } 00321 } 00322 return (TRUE); 00323 } 00324 00325 00326 /***************************************************************************\ 00327 * DdeEnableCallback (DDEML API) 00328 * 00329 * Description: 00330 * Turns on and off asynchronous callbacks (BLOCKABLE). 00331 * 00332 * History: 00333 * 11-12-91 sanfords Created. 00334 \***************************************************************************/ 00335 BOOL DdeEnableCallback( 00336 DWORD idInst, 00337 HCONV hConv, 00338 UINT wCmd) 00339 { 00340 BOOL fRet = FALSE; 00341 PCL_INSTANCE_INFO pcii; 00342 PCONV_INFO pcoi; 00343 ENABLE_ENUM_STRUCT ees; 00344 00345 EnterDDECrit; 00346 00347 pcii = (PCL_INSTANCE_INFO)ValidateInstance((HANDLE)LongToHandle( idInst )); 00348 if (pcii == NULL) { 00349 BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); 00350 goto Exit; 00351 } 00352 00353 switch (wCmd) { 00354 case EC_QUERYWAITING: 00355 case EC_DISABLE: 00356 case EC_ENABLEONE: 00357 case EC_ENABLEALL: 00358 break; 00359 00360 default: 00361 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00362 goto Exit; 00363 } 00364 00365 if (hConv) { 00366 pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, 00367 HTYPE_CLIENT_CONVERSATION, InstFromHandle(idInst)); 00368 if (pcoi == NULL) { 00369 pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, 00370 HTYPE_SERVER_CONVERSATION, InstFromHandle(idInst)); 00371 } 00372 if (pcoi == NULL) { 00373 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); 00374 goto Exit; 00375 } 00376 pcoi->cLocks++; 00377 fRet = SetEnableState(pcoi, wCmd); 00378 switch (wCmd) { 00379 case EC_ENABLEALL: 00380 case EC_ENABLEONE: 00381 CheckForQueuedMessages(pcoi); 00382 } 00383 pcoi->cLocks--; 00384 if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) { 00385 FreeConversationResources(pcoi); 00386 } 00387 } else { 00388 if (wCmd == EC_ENABLEONE) { 00389 wCmd = EC_ENABLEONEOFALL; 00390 } 00391 switch (wCmd) { 00392 case EC_ENABLEONEOFALL: 00393 pcii->ConvStartupState = ST_BLOCKNEXT | ST_BLOCKALLNEXT; 00394 break; 00395 00396 case EC_DISABLE: 00397 pcii->ConvStartupState = ST_BLOCKED; 00398 break; 00399 00400 case EC_ENABLEALL: 00401 pcii->ConvStartupState = 0; 00402 break; 00403 } 00404 ees.pfRet = &fRet; 00405 ees.wCmd = (WORD)wCmd; 00406 switch (wCmd) { 00407 case EC_ENABLEALL: 00408 ees.wCmd2 = EC_CHECKQUEUE; 00409 break; 00410 00411 case EC_ENABLEONEOFALL: 00412 ees.wCmd2 = EC_CHECKQUEUEONCE; 00413 break; 00414 00415 default: 00416 ees.wCmd2 = 0; 00417 } 00418 EnumChildWindows(pcii->hwndMother, (WNDENUMPROC)EnableEnumProc, 00419 (LPARAM)&ees); 00420 } 00421 00422 Exit: 00423 LeaveDDECrit; 00424 return (fRet); 00425 } 00426 00427 00428 00429 /***************************************************************************\ 00430 * SetEnableState 00431 * 00432 * Description: 00433 * Sets the given conversation's enable state based on the EC_ flag 00434 * given. 00435 * 00436 * Returns: fSuccess/fProcessed. 00437 * 00438 * History: 00439 * 11-19-91 sanfords Created. 00440 \***************************************************************************/ 00441 BOOL SetEnableState( 00442 PCONV_INFO pcoi, 00443 UINT wCmd) 00444 { 00445 BOOL fRet = TRUE; 00446 00447 switch (wCmd) { 00448 case EC_CHECKQUEUEONCE: 00449 case EC_CHECKQUEUE: 00450 fRet = CheckForQueuedMessages(pcoi); 00451 break; 00452 00453 case EC_QUERYWAITING: 00454 fRet = !(pcoi->dmqOut == NULL || 00455 (pcoi->dmqOut->next == NULL && 00456 GetClientInfo()->CI_flags & CI_PROCESSING_QUEUE)); 00457 break; 00458 00459 case EC_DISABLE: 00460 pcoi->state |= ST_BLOCKED; 00461 pcoi->state &= ~(ST_BLOCKNEXT | ST_BLOCKALLNEXT); 00462 break; 00463 00464 case EC_ENABLEONE: 00465 pcoi->state &= ~ST_BLOCKED; 00466 pcoi->state |= ST_BLOCKNEXT; 00467 break; 00468 00469 case EC_ENABLEONEOFALL: 00470 pcoi->state &= ~ST_BLOCKED; 00471 pcoi->state |= (ST_BLOCKNEXT | ST_BLOCKALLNEXT); 00472 break; 00473 00474 case EC_ENABLEALL: 00475 pcoi->state &= ~(ST_BLOCKED | ST_BLOCKNEXT | ST_BLOCKALLNEXT); 00476 break; 00477 00478 default: 00479 return(FALSE); 00480 } 00481 return (fRet); 00482 } 00483 00484 00485 00486 00487 /***************************************************************************\ 00488 * _ClientGetDDEHookData 00489 * 00490 * Description: 00491 * Callback from server to extract data from lParam and place it into 00492 * the pdmhd for use by DDESPY apps. This does a very similar thing 00493 * to the CopyDDEDataIn/Out apis but this only grabs a limited amount 00494 * of the data suitable for posting to the DDESPY app(s). This should 00495 * be merged with the Copy APIs eventually. 00496 * 00497 * History: 00498 * 12-16-91 sanfords Created. 00499 \***************************************************************************/ 00500 DWORD _ClientGetDDEHookData( 00501 UINT message, 00502 LPARAM lParam, 00503 PDDEML_MSG_HOOK_DATA pdmhd) 00504 { 00505 PBYTE pb; 00506 HANDLE hDDE; 00507 00508 UnpackDDElParam(message, lParam, &pdmhd->uiLo, &pdmhd->uiHi); 00509 switch (message) { 00510 case WM_DDE_DATA: 00511 case WM_DDE_POKE: 00512 case WM_DDE_ADVISE: 00513 hDDE = (HANDLE)pdmhd->uiLo; 00514 break; 00515 00516 case WM_DDE_EXECUTE: 00517 hDDE = (HANDLE)pdmhd->uiHi; 00518 break; 00519 00520 case WM_DDE_ACK: 00521 case WM_DDE_REQUEST: 00522 case WM_DDE_UNADVISE: 00523 case WM_DDE_TERMINATE: 00524 pdmhd->cbData = 0; 00525 return (1); 00526 } 00527 00528 pdmhd->cbData = (DWORD)UserGlobalSize(hDDE); 00529 if (pdmhd->cbData) { 00530 USERGLOBALLOCK(hDDE, pb); 00531 if (pb == NULL) { 00532 pdmhd->cbData = 0; 00533 } else { 00534 RtlCopyMemory(&pdmhd->Data, pb, min(pdmhd->cbData, 00535 sizeof(DDEML_MSG_HOOK_DATA) - 00536 FIELD_OFFSET(DDEML_MSG_HOOK_DATA, Data))); 00537 USERGLOBALUNLOCK(hDDE); 00538 } 00539 } 00540 return (1); 00541 }

Generated on Sat May 15 19:39:21 2004 for test by doxygen 1.3.7