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

ddemlwp.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: ddemlwp.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * DDE Manager client side window procedures 00007 * 00008 * Created: 11/3/91 Sanford Staab 00009 \***************************************************************************/ 00010 00011 #include "precomp.h" 00012 #pragma hdrstop 00013 00014 VOID ProcessDDEMLInitiate(PCL_INSTANCE_INFO pcii, HWND hwndClient, 00015 GATOM aServer, GATOM aTopic); 00016 00017 /***************************************************************************\ 00018 * DDEMLMotherWndProc 00019 * 00020 * Description: 00021 * Handles WM_DDE_INITIATE messages for DDEML and holds all the other windows 00022 * for a DDEML instance. 00023 * 00024 * History: 00025 * 12-29-92 sanfords Created. 00026 \***************************************************************************/ 00027 LRESULT DDEMLMotherWndProc( 00028 HWND hwnd, 00029 UINT message, 00030 WPARAM wParam, 00031 LPARAM lParam) 00032 { 00033 switch (message) { 00034 case UM_REGISTER: 00035 case UM_UNREGISTER: 00036 return(ProcessRegistrationMessage(hwnd, message, wParam, lParam)); 00037 00038 case WM_DDE_INITIATE: 00039 ProcessDDEMLInitiate((PCL_INSTANCE_INFO)GetWindowLongPtr(hwnd, GWLP_PCI), 00040 (HWND)wParam, (ATOM)LOWORD(lParam), (ATOM)HIWORD(lParam)); 00041 return(0); 00042 00043 } 00044 return(DefWindowProc(hwnd, message, wParam, lParam)); 00045 } 00046 00047 00048 00049 /***************************************************************************\ 00050 * ProcessDDEMLInitiate 00051 * 00052 * Description: 00053 * 00054 * WM_DDE_INITIATE messages are processed here. 00055 * 00056 * History: 00057 * 12-29-92 sanfords Created. 00058 \***************************************************************************/ 00059 VOID ProcessDDEMLInitiate( 00060 PCL_INSTANCE_INFO pcii, 00061 HWND hwndClient, 00062 GATOM aServer, 00063 GATOM aTopic) 00064 { 00065 CONVCONTEXT cc = { 00066 sizeof(CONVCONTEXT), 00067 0, 00068 0, 00069 CP_WINANSI, 00070 0L, 00071 0L, 00072 { 00073 sizeof(SECURITY_QUALITY_OF_SERVICE), 00074 SecurityImpersonation, 00075 SECURITY_STATIC_TRACKING, 00076 TRUE 00077 } 00078 }; 00079 BOOL flags = ST_INLIST; 00080 BOOL fWild; 00081 HDDEDATA hData; 00082 HWND hwndServer; 00083 PSERVER_LOOKUP psl; 00084 PHSZPAIR php; 00085 HSZPAIR hp[2]; 00086 LATOM laService, laFree1 = 0; 00087 LATOM laTopic, laFree2 = 0; 00088 PSVR_CONV_INFO psi; 00089 LATOM *plaNameService; 00090 PWND pwndClient; 00091 PCLS pcls; 00092 00093 if (pcii == NULL) { 00094 return; // we aren't done being initiated yet. 00095 } 00096 00097 EnterDDECrit; 00098 00099 if (pcii->afCmd & CBF_FAIL_CONNECTIONS || !IsWindow(hwndClient)) { 00100 goto Exit; 00101 } 00102 00103 pwndClient = ValidateHwnd(hwndClient); 00104 if (pwndClient == NULL) goto Exit; 00105 00106 pcls = (PCLS)REBASEALWAYS(pwndClient, pcls); 00107 if (!TestWF(pwndClient, WFANSIPROC)) { 00108 if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLCLIENTW]) { 00109 flags |= ST_ISLOCAL; 00110 } 00111 } else { 00112 if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLCLIENTA]) { 00113 flags |= ST_ISLOCAL; 00114 } 00115 } 00116 00117 if (flags & ST_ISLOCAL) { 00118 /* 00119 * Make sure other guy allows self-connections if that's what this is. 00120 */ 00121 if (pcii->hInstServer == (HANDLE)GetWindowLongPtr(hwndClient, GWLP_SHINST)) { 00122 if (pcii->afCmd & CBF_FAIL_SELFCONNECTIONS) { 00123 goto Exit; 00124 } 00125 flags |= ST_ISSELF; 00126 } 00127 00128 GetConvContext(hwndClient, (LONG *)&cc); 00129 if (GetWindowLong(hwndClient, GWL_CONVSTATE) & CLST_SINGLE_INITIALIZING) { 00130 flags &= ~ST_INLIST; 00131 } 00132 } else { 00133 NtUserDdeGetQualityOfService(hwndClient, NULL, &cc.qos); 00134 } 00135 00136 /***************************************************************************\ 00137 * 00138 * Server window creation is minimized by only creating one window per 00139 * Instance/Service/Topic set. This should be all that is needed and 00140 * duplicate connections (ie where the server/client window pair is identical 00141 * to another conversation) should not happen. However, if some dumb 00142 * server app attempts to create a duplicate conversation by having 00143 * duplicate service/topic pairs passed back from a XTYP_WILD_CONNECT 00144 * callback we will not honor the request. 00145 * 00146 * The INSTANCE_INFO structure holds a pointer to an array of SERVERLOOKUP 00147 * structures each entry of which references the hwndServer that supports 00148 * all conversations on that service/topic pair. The hwndServer windows 00149 * in turn have window words that reference the first member in a linked 00150 * list of SVR_CONV_INFO structures, one for each conversation on that 00151 * service/topic pair. 00152 * 00153 \***************************************************************************/ 00154 00155 laFree1 = laService = GlobalToLocalAtom(aServer); 00156 laFree2 = laTopic = GlobalToLocalAtom(aTopic); 00157 00158 plaNameService = pcii->plaNameService; 00159 if (!laService && pcii->afCmd & APPCMD_FILTERINITS && *plaNameService == 0) { 00160 /* 00161 * no WILDCONNECTS to servers with no registered names while filtering. 00162 */ 00163 goto Exit; 00164 } 00165 if ((pcii->afCmd & APPCMD_FILTERINITS) && laService) { 00166 /* 00167 * if we can't find the aServer in this instance's service name 00168 * list, don't bother the server. 00169 */ 00170 while (*plaNameService != 0 && *plaNameService != laService) { 00171 plaNameService++; 00172 } 00173 if (*plaNameService == 0) { 00174 goto Exit; 00175 } 00176 } 00177 hp[0].hszSvc = NORMAL_HSZ_FROM_LATOM(laService); 00178 hp[0].hszTopic = NORMAL_HSZ_FROM_LATOM(laTopic); 00179 hp[1].hszSvc = 0; 00180 hp[1].hszTopic = 0; 00181 fWild = !laService || !laTopic; 00182 00183 hData = DoCallback(pcii, 00184 (WORD)(fWild ? XTYP_WILDCONNECT : XTYP_CONNECT), 00185 0, 00186 (HCONV)0, 00187 hp[0].hszTopic, 00188 hp[0].hszSvc, 00189 (HDDEDATA)0, 00190 flags & ST_ISLOCAL ? (ULONG_PTR)&cc : 0, 00191 (DWORD)(flags & ST_ISSELF) ? 1 : 0); 00192 00193 if (!hData) { 00194 goto Exit; 00195 } 00196 00197 if (fWild) { 00198 php = (PHSZPAIR)DdeAccessData(hData, NULL); 00199 if (php == NULL) { 00200 goto Exit; 00201 } 00202 } else { 00203 php = hp; 00204 } 00205 00206 while (php->hszSvc && php->hszTopic) { 00207 00208 psi = (PSVR_CONV_INFO)DDEMLAlloc(sizeof(SVR_CONV_INFO)); 00209 if (psi == NULL) { 00210 break; 00211 } 00212 00213 laService = LATOM_FROM_HSZ(php->hszSvc); 00214 laTopic = LATOM_FROM_HSZ(php->hszTopic); 00215 00216 hwndServer = 0; 00217 if (pcii->cServerLookupAlloc) { 00218 int i; 00219 /* 00220 * See if there already exists a server window for this 00221 * aServer/aTopic pair 00222 */ 00223 for (i = pcii->cServerLookupAlloc; i; i--) { 00224 if (pcii->aServerLookup[i - 1].laService == laService && 00225 pcii->aServerLookup[i - 1].laTopic == laTopic) { 00226 PSVR_CONV_INFO psiT; 00227 PCONV_INFO pcoi; 00228 00229 hwndServer = pcii->aServerLookup[i - 1].hwndServer; 00230 /* 00231 * Now make sure this window isn't some bogus idiot 00232 * trying to create a second conversation from the 00233 * same client window that is already talking to 00234 * our existing server window. 00235 */ 00236 psiT = (PSVR_CONV_INFO)GetWindowLongPtr(hwndServer, GWLP_PSI); 00237 for (pcoi = &psiT->ci; pcoi != NULL; pcoi = pcoi->next) { 00238 if (pcoi->hwndPartner == hwndClient) { 00239 hwndServer = NULL; 00240 break; 00241 } 00242 } 00243 break; 00244 } 00245 } 00246 } 00247 00248 if (hwndServer == 0) { 00249 00250 // no server window exists - make one. 00251 00252 LeaveDDECrit; 00253 if (pcii->flags & IIF_UNICODE) { 00254 hwndServer = CreateWindowW((LPWSTR)(gpsi->atomSysClass[ICLS_DDEMLSERVERW]), 00255 L"", 00256 WS_CHILD, 00257 0, 0, 0, 0, 00258 pcii->hwndMother, 00259 (HMENU)0, 00260 0, 00261 (LPVOID)NULL); 00262 } else { 00263 hwndServer = CreateWindowA((LPSTR)(gpsi->atomSysClass[ICLS_DDEMLSERVERA]), 00264 "", 00265 WS_CHILD, 00266 0, 0, 0, 0, 00267 pcii->hwndMother, 00268 (HMENU)0, 00269 0, 00270 (LPVOID)NULL); 00271 } 00272 EnterDDECrit; 00273 00274 if (hwndServer == 0) { 00275 DDEMLFree(psi); 00276 break; 00277 } 00278 // SetWindowLongPtr(hwndServer, GWLP_PSI, (LONG)NULL); // Zero init. 00279 00280 // put the window into the lookup list 00281 00282 if (pcii->aServerLookup == NULL) { 00283 psl = (PSERVER_LOOKUP)DDEMLAlloc(sizeof(SERVER_LOOKUP)); 00284 } else { 00285 psl = (PSERVER_LOOKUP)DDEMLReAlloc(pcii->aServerLookup, 00286 sizeof(SERVER_LOOKUP) * (pcii->cServerLookupAlloc + 1)); 00287 } 00288 if (psl == NULL) { 00289 RIPMSG1(RIP_WARNING, "ProcessDDEMLInitiate:hwndServer (%x) destroyed due to low memory.", hwndServer); 00290 NtUserDestroyWindow(hwndServer); 00291 DDEMLFree(psi); 00292 break; 00293 } 00294 00295 IncLocalAtomCount(laService); // for SERVER_LOOKUP 00296 psl[pcii->cServerLookupAlloc].laService = laService; 00297 IncLocalAtomCount(laTopic); // for SERVER_LOOKUP 00298 psl[pcii->cServerLookupAlloc].laTopic = laTopic; 00299 psl[pcii->cServerLookupAlloc].hwndServer = hwndServer; 00300 pcii->aServerLookup = psl; 00301 pcii->cServerLookupAlloc++; 00302 // DumpServerLookupTable("After addition:", hwndServer, psl, pcii->cServerLookupAlloc); 00303 } 00304 00305 psi->ci.next = (PCONV_INFO)GetWindowLongPtr(hwndServer, GWLP_PSI); 00306 SetWindowLongPtr(hwndServer, GWLP_PSI, (LONG_PTR)psi); 00307 psi->ci.pcii = pcii; 00308 // psi->ci.hUser = 0; 00309 psi->ci.hConv = (HCONV)CreateHandle((ULONG_PTR)psi, 00310 HTYPE_SERVER_CONVERSATION, InstFromHandle(pcii->hInstClient)); 00311 psi->ci.laService = laService; 00312 IncLocalAtomCount(laService); // for server window 00313 psi->ci.laTopic = laTopic; 00314 IncLocalAtomCount(laTopic); // for server window 00315 psi->ci.hwndPartner = hwndClient; 00316 psi->ci.hwndConv = hwndServer; 00317 psi->ci.state = (WORD)(flags | ST_CONNECTED | pcii->ConvStartupState); 00318 SetCommonStateFlags(hwndClient, hwndServer, &psi->ci.state); 00319 psi->ci.laServiceRequested = laFree1; 00320 IncLocalAtomCount(psi->ci.laServiceRequested); // for server window 00321 // psi->ci.pxiIn = NULL; 00322 // psi->ci.pxiOut = NULL; 00323 // psi->ci.dmqIn = NULL; 00324 // psi->ci.dmqOut = NULL; 00325 // psi->ci.aLinks = NULL; 00326 // psi->ci.cLinks = 0; 00327 // psi->ci.cLocks = 0; 00328 00329 LeaveDDECrit; 00330 CheckDDECritOut; 00331 SendMessage(hwndClient, WM_DDE_ACK, (WPARAM)hwndServer, 00332 MAKELONG(LocalToGlobalAtom(laService), LocalToGlobalAtom(laTopic))); 00333 EnterDDECrit; 00334 00335 if (!(pcii->afCmd & CBF_SKIP_CONNECT_CONFIRMS)) { 00336 DoCallback(pcii, 00337 (WORD)XTYP_CONNECT_CONFIRM, 00338 0, 00339 psi->ci.hConv, 00340 (HSZ)laTopic, 00341 (HSZ)laService, 00342 (HDDEDATA)0, 00343 0, 00344 (flags & ST_ISSELF) ? 1L : 0L); 00345 } 00346 00347 MONCONV((PCONV_INFO)psi, TRUE); 00348 00349 if (!(flags & ST_INLIST)) { 00350 break; // our partner's only gonna take the first one anyway. 00351 } 00352 php++; 00353 } 00354 00355 if (fWild) { 00356 DdeUnaccessData(hData); 00357 InternalFreeDataHandle(hData, FALSE); 00358 } 00359 00360 Exit: 00361 DeleteAtom(laFree1); 00362 DeleteAtom(laFree2); 00363 LeaveDDECrit; 00364 return; 00365 } 00366 00367 /***************************************************************************\ 00368 * DDEMLClientWndProc 00369 * 00370 * Description: 00371 * Handles DDE client messages for DDEML. 00372 * 00373 * History: 00374 * 11-12-91 sanfords Created. 00375 \***************************************************************************/ 00376 LRESULT DDEMLClientWndProc( 00377 HWND hwnd, 00378 UINT message, 00379 WPARAM wParam, 00380 LPARAM lParam) 00381 { 00382 PCL_CONV_INFO pci, pciNew; 00383 LONG lState; 00384 LRESULT lRet = 0; 00385 PWND pwnd; 00386 PCLS pcls; 00387 00388 EnterDDECrit; 00389 00390 pci = (PCL_CONV_INFO)GetWindowLongPtr(hwnd, GWLP_PCI); 00391 UserAssert(pci == NULL || pci->ci.hwndConv == hwnd); 00392 00393 switch (message) { 00394 case WM_DDE_ACK: 00395 lState = GetWindowLong(hwnd, GWL_CONVSTATE); 00396 if (lState != CLST_CONNECTED) { 00397 00398 // Initiation mode 00399 00400 pciNew = (PCL_CONV_INFO)DDEMLAlloc(sizeof(CL_CONV_INFO)); 00401 if (pciNew == NULL || 00402 (pci != NULL && lState == CLST_SINGLE_INITIALIZING)) { 00403 PostMessage((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, 0); 00404 goto Exit; 00405 } 00406 00407 // PCL_CONV_INFO initialization 00408 00409 pciNew->ci.pcii = ValidateInstance((HANDLE)GetWindowLongPtr(hwnd, GWLP_CHINST)); 00410 00411 if (pciNew->ci.pcii == NULL) { 00412 DDEMLFree(pciNew); 00413 goto Exit; 00414 } 00415 00416 pciNew->ci.next = (PCONV_INFO)pci; // pci may be NULL 00417 // 00418 // Seting GWLP_PCI gives feedback to ConnectConv() which issued 00419 // the WM_DDE_INITIATE message. 00420 // 00421 SetWindowLongPtr(hwnd, GWLP_PCI, (LONG_PTR)pciNew); 00422 // pciNew->hUser = 0; // Zero init. 00423 00424 // BUG: If this fails we can have some nasty problems 00425 pciNew->ci.hConv = (HCONV)CreateHandle((ULONG_PTR)pciNew, 00426 HTYPE_CLIENT_CONVERSATION, InstFromHandle(pciNew->ci.pcii->hInstClient)); 00427 00428 pciNew->ci.laService = GlobalToLocalAtom(LOWORD(lParam)); // pci copy 00429 GlobalDeleteAtom(LOWORD(lParam)); 00430 pciNew->ci.laTopic = GlobalToLocalAtom(HIWORD(lParam)); // pci copy 00431 GlobalDeleteAtom(HIWORD(lParam)); 00432 pciNew->ci.hwndPartner = (HWND)wParam; 00433 pciNew->ci.hwndConv = hwnd; 00434 pciNew->ci.state = (WORD)(ST_CONNECTED | ST_CLIENT | 00435 pciNew->ci.pcii->ConvStartupState); 00436 SetCommonStateFlags(hwnd, (HWND)wParam, &pciNew->ci.state); 00437 00438 pwnd = ValidateHwnd((HWND)wParam); 00439 00440 if (pwnd == NULL) goto Exit; 00441 pcls = (PCLS)REBASEALWAYS(pwnd, pcls); 00442 00443 if (!TestWF(pwnd, WFANSIPROC)) { 00444 if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLSERVERW]) { 00445 pciNew->ci.state |= ST_ISLOCAL; 00446 } 00447 } else { 00448 if (pcls->atomClassName == gpsi->atomSysClass[ICLS_DDEMLSERVERA]) { 00449 pciNew->ci.state |= ST_ISLOCAL; 00450 } 00451 } 00452 00453 // pciNew->ci.laServiceRequested = 0; // Set by InitiateEnumerationProc() 00454 // pciNew->ci.pxiIn = 0; 00455 // pciNew->ci.pxiOut = 0; 00456 // pciNew->ci.dmqIn = 0; 00457 // pciNew->ci.dmqOut = 0; 00458 // pciNew->ci.aLinks = NULL; 00459 // pciNew->ci.cLinks = 0; 00460 // pciNew->ci.cLocks = 0; 00461 goto Exit; 00462 } 00463 // fall through to handle posted messages here. 00464 00465 case WM_DDE_DATA: 00466 ProcessAsyncDDEMsg((PCONV_INFO)pci, message, (HWND)wParam, lParam); 00467 goto Exit; 00468 00469 case WM_DDE_TERMINATE: 00470 case WM_DESTROY: 00471 { 00472 ProcessTerminateMsg((PCONV_INFO)pci, (HWND)wParam); 00473 break; 00474 } 00475 } 00476 00477 lRet = DefWindowProc(hwnd, message, wParam, lParam); 00478 00479 Exit: 00480 LeaveDDECrit; 00481 return (lRet); 00482 } 00483 00484 00485 00486 00487 /***************************************************************************\ 00488 * DDEMLServerWndProc 00489 * 00490 * Description: 00491 * Handles DDE server messages. 00492 * 00493 * History: 00494 * 11-12-91 sanfords Created. 00495 \***************************************************************************/ 00496 LRESULT DDEMLServerWndProc( 00497 HWND hwnd, 00498 UINT message, 00499 WPARAM wParam, 00500 LPARAM lParam) 00501 { 00502 PSVR_CONV_INFO psi; 00503 LRESULT lRet = 0; 00504 00505 EnterDDECrit; 00506 00507 psi = (PSVR_CONV_INFO)GetWindowLongPtr(hwnd, GWLP_PSI); 00508 UserAssert(psi == NULL || psi->ci.hwndConv == hwnd); 00509 00510 switch (message) { 00511 case WM_DDE_REQUEST: 00512 case WM_DDE_POKE: 00513 case WM_DDE_ADVISE: 00514 case WM_DDE_EXECUTE: 00515 case WM_DDE_ACK: 00516 case WM_DDE_UNADVISE: 00517 ProcessAsyncDDEMsg((PCONV_INFO)psi, message, (HWND)wParam, lParam); 00518 goto Exit; 00519 00520 case WM_DDE_TERMINATE: 00521 case WM_DESTROY: 00522 ProcessTerminateMsg((PCONV_INFO)psi, (HWND)wParam); 00523 break; 00524 } 00525 lRet = DefWindowProc(hwnd, message, wParam, lParam); 00526 Exit: 00527 LeaveDDECrit; 00528 return (lRet); 00529 } 00530 00531 00532 00533 00534 /***************************************************************************\ 00535 * ProcessTerminateMsg 00536 * 00537 * Description: 00538 * Handles WM_DDE_TERMINATE messages for both sides. 00539 * 00540 * History: 00541 * 11-26-91 sanfords Created. 00542 \***************************************************************************/ 00543 PCONV_INFO ProcessTerminateMsg( 00544 PCONV_INFO pcoi, 00545 HWND hwndFrom) 00546 { 00547 while (pcoi != NULL && pcoi->hwndPartner != hwndFrom) { 00548 pcoi = pcoi->next; 00549 } 00550 if (pcoi != NULL) { 00551 pcoi->state |= ST_TERMINATE_RECEIVED; 00552 ShutdownConversation(pcoi, TRUE); 00553 } 00554 return (pcoi); 00555 } 00556 00557 00558 00559 /***************************************************************************\ 00560 * ProcessAsyncDDEMsg 00561 * 00562 * Description: 00563 * Handles incoming DDE messages by either calling ProcessSyncDDEMessage() 00564 * if the conversation is able to handle callbacks, or by queuing the 00565 * incoming message into the conversations message queue. Doing this 00566 * allows simpler code in that no message is processed unless the code 00567 * can perform synchronous callbacks. 00568 * 00569 * History: 00570 * 11-26-91 sanfords Created. 00571 \***************************************************************************/ 00572 VOID ProcessAsyncDDEMsg( 00573 PCONV_INFO pcoi, 00574 UINT msg, 00575 HWND hwndFrom, 00576 LPARAM lParam) 00577 { 00578 PDDE_MESSAGE_QUEUE pdmq; 00579 #if DBG 00580 HWND hwndT = pcoi->hwndConv; 00581 #endif // DBG 00582 00583 while (pcoi != NULL && pcoi->hwndPartner != hwndFrom) { 00584 pcoi = pcoi->next; 00585 } 00586 if (pcoi == NULL) { 00587 RIPMSG3(RIP_WARNING, 00588 "Bogus DDE message %x received from %x by %x. Dumping.", 00589 msg, hwndFrom, hwndT); 00590 DumpDDEMessage(FALSE, msg, lParam); 00591 return ; 00592 } 00593 if (pcoi->state & ST_CONNECTED) { 00594 00595 if (pcoi->dmqOut == NULL && 00596 !(pcoi->state & ST_BLOCKED) 00597 // && !PctiCurrent()->cInDDEMLCallback 00598 ) { 00599 00600 if (ProcessSyncDDEMessage(pcoi, msg, lParam)) { 00601 return; // not blocked, ok to return. 00602 } 00603 } 00604 00605 // enter into queue 00606 00607 pdmq = DDEMLAlloc(sizeof(DDE_MESSAGE_QUEUE)); 00608 if (pdmq == NULL) { 00609 00610 // insufficient memory - we can't process this msg - we MUST 00611 // terminate. 00612 00613 if (pcoi->state & ST_CONNECTED) { 00614 PostMessage(pcoi->hwndPartner, WM_DDE_TERMINATE, 00615 (WPARAM)pcoi->hwndConv, 0); 00616 pcoi->state &= ~ST_CONNECTED; 00617 } 00618 DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam); 00619 return ; 00620 } 00621 pdmq->pcoi = pcoi; 00622 pdmq->msg = msg; 00623 pdmq->lParam = lParam; 00624 pdmq->next = NULL; 00625 00626 // dmqOut->next->next->next->dmqIn->NULL 00627 00628 if (pcoi->dmqIn != NULL) { 00629 pcoi->dmqIn->next = pdmq; 00630 } 00631 pcoi->dmqIn = pdmq; 00632 if (pcoi->dmqOut == NULL) { 00633 pcoi->dmqOut = pcoi->dmqIn; 00634 } 00635 pcoi->cLocks++; 00636 CheckForQueuedMessages(pcoi); 00637 pcoi->cLocks--; 00638 if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) { 00639 FreeConversationResources(pcoi); 00640 } 00641 } else { 00642 DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam); 00643 } 00644 } 00645 00646 00647 00648 00649 00650 00651 00652 /***************************************************************************\ 00653 * CheckForQueuedMessages 00654 * 00655 * Description: 00656 * Handles processing of DDE messages held in the given conversaion's 00657 * DDE message queue. 00658 * 00659 * Returns: fProcessed. 00660 * 00661 * History: 00662 * 11-12-91 sanfords Created. 00663 \***************************************************************************/ 00664 BOOL CheckForQueuedMessages( 00665 PCONV_INFO pcoi) 00666 { 00667 PDDE_MESSAGE_QUEUE pdmq; 00668 BOOL fRet = FALSE; 00669 PCLIENTINFO pci; 00670 00671 CheckDDECritIn; 00672 00673 if (pcoi->state & ST_PROCESSING) { // recursion prevention 00674 return(FALSE); 00675 } 00676 00677 UserAssert(pcoi->cLocks); 00678 00679 pci = GetClientInfo(); 00680 00681 pcoi->state |= ST_PROCESSING; 00682 while (!(pcoi->state & ST_BLOCKED) && 00683 pcoi->dmqOut != NULL && 00684 !pci->cInDDEMLCallback) { 00685 pci->CI_flags |= CI_PROCESSING_QUEUE; 00686 if (ProcessSyncDDEMessage(pcoi, pcoi->dmqOut->msg, pcoi->dmqOut->lParam)) { 00687 fRet = TRUE; 00688 pdmq = pcoi->dmqOut; 00689 pcoi->dmqOut = pcoi->dmqOut->next; 00690 if (pcoi->dmqOut == NULL) { 00691 pcoi->dmqIn = NULL; 00692 } 00693 DDEMLFree(pdmq); 00694 } 00695 pci->CI_flags &= ~CI_PROCESSING_QUEUE; 00696 } 00697 pcoi->state &= ~ST_PROCESSING; 00698 return(fRet); 00699 } 00700 00701 00702 00703 00704 /***************************************************************************\ 00705 * DumpDDEMessage 00706 * 00707 * Description: 00708 * Used to clean up resources referenced by DDE messages that for some 00709 * reason could not be processed. 00710 * 00711 * History: 00712 * 11-12-91 sanfords Created. 00713 \***************************************************************************/ 00714 VOID DumpDDEMessage( 00715 BOOL fFreeData, 00716 UINT msg, 00717 LPARAM lParam) 00718 { 00719 UINT_PTR uiLo, uiHi; 00720 00721 RIPMSG2(RIP_WARNING, "Dump DDE msg %x lParam %x", msg, lParam); 00722 00723 switch (msg) { 00724 case WM_DDE_ACK: 00725 case WM_DDE_DATA: 00726 case WM_DDE_POKE: 00727 case WM_DDE_ADVISE: 00728 UnpackDDElParam(msg, lParam, &uiLo, &uiHi); 00729 switch (msg) { 00730 case WM_DDE_DATA: 00731 case WM_DDE_POKE: 00732 if (uiLo) { 00733 if (fFreeData) { 00734 FreeDDEData((HANDLE)uiLo, FALSE, TRUE); 00735 } 00736 GlobalDeleteAtom((ATOM)uiHi); 00737 } 00738 break; 00739 00740 case WM_DDE_ADVISE: 00741 if (uiLo) { 00742 if (fFreeData) { 00743 FreeDDEData((HANDLE)uiLo, FALSE, TRUE); 00744 } 00745 GlobalDeleteAtom((ATOM)uiHi); 00746 } 00747 break; 00748 00749 case WM_DDE_ACK: 00750 // could be EXEC Ack - cant know what to do exactly. 00751 break; 00752 } 00753 FreeDDElParam(msg, lParam); 00754 break; 00755 00756 case WM_DDE_EXECUTE: 00757 if (fFreeData) { 00758 WOWGLOBALFREE((HANDLE)lParam); 00759 } 00760 break; 00761 00762 case WM_DDE_REQUEST: 00763 case WM_DDE_UNADVISE: 00764 GlobalDeleteAtom((ATOM)HIWORD(lParam)); 00765 break; 00766 } 00767 } 00768 00769 00770 00771 00772 /***************************************************************************\ 00773 * ProcessSyncDDEMessage 00774 * 00775 * Description: 00776 * Handles processing of a received DDE message. TRUE is returned if 00777 * the message was handled. FALSE implies CBR_BLOCK. 00778 * 00779 * History: 00780 * 11-19-91 sanfords Created. 00781 \***************************************************************************/ 00782 BOOL ProcessSyncDDEMessage( 00783 PCONV_INFO pcoi, 00784 UINT msg, 00785 LPARAM lParam) 00786 { 00787 BOOL fNotBlocked = TRUE; 00788 PCL_INSTANCE_INFO pcii; 00789 ENABLE_ENUM_STRUCT ees; 00790 BOOL fRet; 00791 00792 CheckDDECritIn; 00793 00794 /* 00795 * lock the conversation so its resources don't go away till we are 00796 * done with them. This function could generate a callback which could 00797 * disconnect the conversation. 00798 */ 00799 pcoi->cLocks++; 00800 00801 if (pcoi->state & ST_BLOCKNEXT) { 00802 pcoi->state ^= ST_BLOCKNEXT | ST_BLOCKED; 00803 } 00804 if (pcoi->state & ST_BLOCKALLNEXT) { 00805 ees.pfRet = &fRet; 00806 ees.wCmd = EC_DISABLE; 00807 ees.wCmd2 = 0; 00808 EnumChildWindows(pcoi->pcii->hwndMother, (WNDENUMPROC)EnableEnumProc, 00809 (LPARAM)&ees); 00810 } 00811 00812 if (pcoi->state & ST_CONNECTED) { 00813 if (pcoi->pxiOut == NULL) { 00814 if (pcoi->state & ST_CLIENT) { 00815 fNotBlocked = SpontaneousClientMessage((PCL_CONV_INFO)pcoi, msg, lParam); 00816 } else { 00817 fNotBlocked = SpontaneousServerMessage((PSVR_CONV_INFO)pcoi, msg, lParam); 00818 } 00819 } else { 00820 UserAssert(pcoi->pxiOut->hXact == (HANDLE)0 || 00821 ValidateCHandle(pcoi->pxiOut->hXact, HTYPE_TRANSACTION, 00822 HINST_ANY) 00823 == (ULONG_PTR)pcoi->pxiOut); 00824 fNotBlocked = (pcoi->pxiOut->pfnResponse)(pcoi->pxiOut, msg, lParam); 00825 } 00826 } else { 00827 DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), msg, lParam); 00828 } 00829 if (!fNotBlocked) { 00830 pcoi->state |= ST_BLOCKED; 00831 pcoi->state &= ~ST_BLOCKNEXT; 00832 } 00833 00834 pcii = pcoi->pcii; // save this incase unlocking makes pcoi go away. 00835 00836 pcoi->cLocks--; 00837 if (pcoi->cLocks == 0 && pcoi->state & ST_FREE_CONV_RES_NOW) { 00838 FreeConversationResources(pcoi); 00839 } 00840 00841 /* 00842 * Because callbacks are capable of blocking DdeUninitialize(), we check 00843 * before exit to see if it needs to be called. 00844 */ 00845 if (pcii->afCmd & APPCMD_UNINIT_ASAP && 00846 !(pcii->flags & IIF_IN_SYNC_XACT) && 00847 !pcii->cInDDEMLCallback) { 00848 DdeUninitialize(HandleToUlong(pcii->hInstClient)); 00849 return(FALSE); 00850 } 00851 return (fNotBlocked); 00852 }

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