test: connect.c File Reference

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

# connect.c File Reference

`#include "precomp.h"`
`#include "nddeagnt.h"`

Go to the source code of this file.

## Classes

struct | tagINIT_ENUM

## Defines

#define | ValidateConvList(h)
#define | ValidateAllConvLists()
#define | ORPATH(x)

## Typedefs

typedef tagINIT_ENUM | INIT_ENUM
typedef tagINIT_ENUM * | PINIT_ENUM

## Functions

BOOL | InitiateEnumerationProc (HWND hwndTarget, PINIT_ENUM pie)
VOID | DisconnectConv (PCONV_INFO pcoi)
HCONV | DdeConnect (DWORD idInst, HSZ hszService, HSZ hszTopic, PCONVCONTEXT pCC)
HCONVLIST | DdeConnectList (DWORD idInst, HSZ hszService, HSZ hszTopic, HCONVLIST hConvList, PCONVCONTEXT pCC)
HCONV | DdeReconnect (HCONV hConv)
BOOL | ValidateConnectParameters (HANDLE hInst, PCL_INSTANCE_INFO *ppcii, HSZ *phszService, HSZ hszTopic, LATOM *plaNormalSvcName, PCONVCONTEXT *ppCC, HWND *phwndTarget, HCONVLIST hConvList)
PCL_CONV_INFO | ConnectConv (PCL_INSTANCE_INFO pcii, LATOM laService, LATOM laTopic, HWND hwndTarget, HWND hwndSkip, PCONVCONTEXT pCC, HCONVLIST hConvList, DWORD clst)
VOID | SetCommonStateFlags (HWND hwndUs, HWND hwndThem, PWORD pwFlags)
HCONV | DdeQueryNextServer (HCONVLIST hConvList, HCONV hConvPrev)
BOOL | DdeDisconnect (HCONV hConv)
BOOL | DdeDisconnectList (HCONVLIST hConvList)
VOID | ShutdownConversation (PCONV_INFO pcoi, BOOL fMakeCallback)
VOID | UnlinkConvFromOthers (PCONV_INFO pcoi, BOOL gGoingZombie)
VOID | FreeConversationResources (PCONV_INFO pcoi)
BOOL | WaitForZombieTerminate (HANDLE hData)

## Variables

CONVCONTEXT | TempConvContext
CONVCONTEXT | DefConvContext

## Define Documentation

#define ORPATH | ( | x |  | ) |

| Referenced by UnlinkConvFromOthers().

#define ValidateAllConvLists | (

)

| Definition at line 103 of file connect.c. Referenced by UnlinkConvFromOthers().

#define ValidateConvList | ( | h |  | ) |

| Definition at line 102 of file connect.c. Referenced by DdeConnectList(), DdeDisconnectList(), and UnlinkConvFromOthers().

## Typedef Documentation

typedef struct tagINIT_ENUM INIT_ENUM

typedef struct tagINIT_ENUM * PINIT_ENUM

## Function Documentation

PCL_CONV_INFO ConnectConv | ( | PCL_INSTANCE_INFO | pcii,
|  | LATOM | laService,
|  | LATOM | laTopic,
|  | HWND | hwndTarget,
|  | HWND | hwndSkip,
|  | PCONVCONTEXT | pCC,
|  | HCONVLIST | hConvList,
|  | DWORD | clst
| ) |

Definition at line 607 of file connect.c.

References tagSERVERINFO::atomSysClass, CheckDDECritIn, CheckDDECritOut, tagCL_CONV_INFO::ci, tagINIT_ENUM::clst, CLST_CONNECTED, DWORD, EnterDDECrit, EnumWindows(), Error, tagCL_INSTANCE_INFO::flags, GATOM, GetWindowLongPtr(), gpsi, GWL_CONVSTATE, GWLP_CHINST, GWLP_PCI, GWLP_SHINST, tagINIT_ENUM::hConvList, tagCL_INSTANCE_INFO::hInstClient, tagCL_INSTANCE_INFO::hInstServer, tagINIT_ENUM::hwndClient, tagCL_INSTANCE_INFO::hwndMother, tagCL_CONV_INFO::hwndReconnect, tagINIT_ENUM::hwndSkip, ICLS_DDEMLCLIENTA, ICLS_DDEMLCLIENTW, IIF_UNICODE, IncLocalAtomCount(), InitiateEnumerationProc(), L, tagINIT_ENUM::laServiceRequested, tagCONV_INFO::laServiceRequested, tagINIT_ENUM::laTopic, LeaveDDECrit, LocalToGlobalAtom(), tagINIT_ENUM::lParam, LPVOID, MONCONV, tagCL_INSTANCE_INFO::MonitorFlags, tagCONV_INFO::next, NtUserDdeSetQualityOfService(), NtUserDestroyWindow(), NULL, SendMessage(), SetConvContext(), SetLastDDEMLError(), SetWindowLongPtr(), and TRUE.

Referenced by DdeConnect(), DdeConnectList(), and DdeReconnect().

    00616 {
    00617     INIT_ENUM ie;
    00618     PCL_CONV_INFO pci;
    00619     PCONV_INFO pcoi;
    00620     GATOM gaService, gaTopic;
    00621
    00622     CheckDDECritIn;
    00623
    00624     if (hwndTarget && hwndTarget == hwndSkip) {
    00625         return(NULL);
    00626     }
    00627
    00628     LeaveDDECrit;
    00629     CheckDDECritOut;
    00630
    00631     if (pcii->flags & IIF_UNICODE) {
    00632         ie.hwndClient = CreateWindowW((LPWSTR)(gpsi->atomSysClass[ICLS_DDEMLCLIENTW]),
    00633                                      L"",
    00634                                      WS_CHILD,
    00635                                      0, 0, 0, 0,
    00636                                      pcii->hwndMother,
    00637                                      (HMENU)0,
    00638                                      (HANDLE)0,
    00639                                      (LPVOID)NULL);
    00640     } else {
    00641         ie.hwndClient = CreateWindowA((LPSTR)(gpsi->atomSysClass[ICLS_DDEMLCLIENTA]),
    00642                                      "",
    00643                                      WS_CHILD,
    00644                                      0, 0, 0, 0,
    00645                                      pcii->hwndMother,
    00646                                      (HMENU)0,
    00647                                      (HANDLE)0,
    00648                                      (LPVOID)NULL);
    00649     }
    00650
    00651     EnterDDECrit;
    00652
    00653     if (ie.hwndClient == 0) {
    00654         return (NULL);
    00655     }
    00656
    00657     if (pCC != NULL) {
    00658         if (!NtUserDdeSetQualityOfService(ie.hwndClient, &(pCC->qos), NULL)) {
    00659             SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
    00660             goto Error;
    00661         }
    00662     }
    00663     /*
    00664      * Note that a pci will be created and allocated for each ACK recieved.
    00665      */
    00666     SetConvContext(ie.hwndClient, (LONG *)pCC);
    00667     SetWindowLong(ie.hwndClient, GWL_CONVSTATE, clst);
    00668     SetWindowLongPtr(ie.hwndClient, GWLP_SHINST, (LONG_PTR)pcii->hInstServer);
    00669     SetWindowLongPtr(ie.hwndClient, GWLP_CHINST, (LONG_PTR)pcii->hInstClient);
    00670
    00671     gaService = LocalToGlobalAtom(laService);
    00672     gaTopic = LocalToGlobalAtom(laTopic);
    00673     ie.lParam = MAKELONG(gaService, gaTopic);
    00674     if (!hwndTarget) {
    00675         ie.hwndSkip = hwndSkip;
    00676         ie.laServiceRequested = laService;
    00677         ie.laTopic = laTopic;
    00678         ie.hConvList = hConvList;
    00679         ie.clst = clst;
    00680     }
    00681
    00682     LeaveDDECrit;
    00683
    00684     if (hwndTarget) {
    00685         SendMessage(hwndTarget, WM_DDE_INITIATE, (WPARAM)ie.hwndClient,
    00686                 ie.lParam);
    00687     } else {
    00688         /*
    00689          * Send this message to the nddeagnt app first so it can start
    00690          * the netdde services BEFORE we do an enumeration of windows.
    00691          * This lets things work the first time.  NetDDEAgent caches
    00692          * service status so this is the fastest way to do this.
    00693          */
    00694         HWND hwndAgent = FindWindowW(SZ_NDDEAGNT_CLASS, SZ_NDDEAGNT_TITLE);
    00695         if (hwndAgent) {
    00696             SendMessage(hwndAgent,
    00697                 WM_DDE_INITIATE, (WPARAM)ie.hwndClient, ie.lParam);
    00698         }
    00699         EnumWindows((WNDENUMPROC)InitiateEnumerationProc, (LPARAM)&ie);
    00700     }
    00701
    00702     EnterDDECrit;
    00703     /*
    00704      * hConvList may have been destroyed during the enumeration but we are
    00705      * done with it now so no need to revalidate.
    00706      */
    00707
    00708 #if DBG
    00709     {
    00710         WCHAR sz[10];
    00711
    00712         if (gaService && GlobalGetAtomName(gaService, sz, 10) == 0) {
    00713             RIPMSG1(RIP_ERROR, "Bad Service Atom after Initiate phase: %lX", (DWORD)gaService);
    00714         }
    00715         if (gaTopic && GlobalGetAtomName(gaTopic, sz, 10) == 0) {
    00716             RIPMSG1(RIP_ERROR, "Bad Topic Atom after Initiate phase: %lX", (DWORD)gaTopic);
    00717         }
    00718     }
    00719 #endif // DBG
    00720
    00721     GlobalDeleteAtom(gaService);
    00722     GlobalDeleteAtom(gaTopic);
    00723
    00724     //
    00725     // Get the first pci allocated when a WM_DDE_ACK was recieved.
    00726     //
    00727     pci = (PCL_CONV_INFO)GetWindowLongPtr(ie.hwndClient, GWLP_PCI);
    00728     if (pci == NULL) {
    00729 Error:
    00730         LeaveDDECrit;
    00731         NtUserDestroyWindow(ie.hwndClient);
    00732         EnterDDECrit;
    00733         return (NULL);
    00734     }
    00735
    00736     SetWindowLong(ie.hwndClient, GWL_CONVSTATE, CLST_CONNECTED);
    00737     if (hwndTarget) {
    00738         /*
    00739          * If hwndTarget was NULL, the enumeration proc took care of this.
    00740          */
    00741         pci->hwndReconnect = hwndTarget;
    00742         UserAssert(pci->ci.next == NULL);
    00743         pci->ci.laServiceRequested = laService;
    00744         IncLocalAtomCount(laService); // pci copy
    00745     }
    00746
    00747     if (pcii->MonitorFlags & MF_CONV) {
    00748         for (pcoi = (PCONV_INFO)pci; pcoi; pcoi = pcoi->next) {
    00749             MONCONV(pcoi, TRUE);
    00750         }
    00751     }
    00752     return (pci);
    00753 }

HCONV DdeConnect | ( | DWORD | idInst,
|  | HSZ | hszService,
|  | HSZ | hszTopic,
|  | PCONVCONTEXT | pCC
| ) |

Definition at line 146 of file connect.c.

References tagCL_INSTANCE_INFO::afCmd, tagCL_CONV_INFO::ci, CLST_SINGLE_INITIALIZING, ConnectConv(), EnterDDECrit, tagCONV_INFO::hConv, tagCL_INSTANCE_INFO::hwndMother, LATOM, LATOM_FROM_HSZ, LeaveDDECrit, NULL, SetLastDDEMLError(), and ValidateConnectParameters().

    00151 {
    00152     PCL_INSTANCE_INFO pcii;
    00153     PCL_CONV_INFO pci;
    00154     HCONV hConvRet = 0;
    00155     HWND hwndTarget = 0;
    00156     LATOM aNormalSvcName = 0;
    00157
    00158     EnterDDECrit;
    00159
    00160     if (!ValidateConnectParameters((HANDLE)LongToHandle( idInst ), &pcii, &hszService, hszTopic,
    00161             &aNormalSvcName, &pCC, &hwndTarget, 0)) {
    00162         goto Exit;
    00163     }
    00164     pci = ConnectConv(pcii, LATOM_FROM_HSZ(hszService), LATOM_FROM_HSZ(hszTopic),
    00165             hwndTarget,
    00166             (pcii->afCmd & CBF_FAIL_SELFCONNECTIONS) ? pcii->hwndMother : 0,
    00167             pCC, 0, CLST_SINGLE_INITIALIZING);
    00168     if (pci == NULL) {
    00169         SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
    00170         goto Exit;
    00171     } else {
    00172         hConvRet = pci->ci.hConv;
    00173     }
    00174
    00175 Exit:
    00176     if (aNormalSvcName) {
    00177         GlobalDeleteAtom(aNormalSvcName);
    00178     }
    00179     LeaveDDECrit;
    00180     return (hConvRet);
    00181 }

HCONVLIST DdeConnectList | ( | DWORD | idInst,
|  | HSZ | hszService,
|  | HSZ | hszTopic,
|  | HCONVLIST | hConvList,
|  | PCONVCONTEXT | pCC
| ) |

Definition at line 195 of file connect.c.

References tagCL_INSTANCE_INFO::afCmd, tagCONVLIST::ahwnd, CheckDDECritOut, tagCONVLIST::chwnd, CLST_MULT_INITIALIZING, ConnectConv(), CONVLIST, CreateHandle(), DDEMLAlloc, DDEMLFree, DDEMLReAlloc, DestroyHandle(), DisconnectConv(), EnterDDECrit, FALSE, GetHandleData(), GetWindowLongPtr(), GWLP_PCI, tagCL_INSTANCE_INFO::hInstClient, HTYPE_CONVERSATION_LIST, tagCONV_INFO::hwndConv, tagCL_INSTANCE_INFO::hwndMother, InstFromHandle, LATOM, LATOM_FROM_HSZ, LeaveDDECrit, tagCONV_INFO::next, NULL, SetHandleData(), SetLastDDEMLError(), ShutdownConversation(), tagCONV_INFO::state, ValidateConnectParameters(), and ValidateConvList.

    00201 {
    00202     PCL_INSTANCE_INFO pcii;
    00203     PCONV_INFO pcoi, pcoiNew, pcoiExisting, pcoiNext;
    00204     HCONVLIST hConvListRet = 0;
    00205     HWND hwndTarget = 0;
    00206     LATOM aNormalSvcName = 0;
    00207     PCONVLIST pcl = NULL;
    00208     HCONVLIST hConvListOld;
    00209     int i;
    00210
    00211     CheckDDECritOut;
    00212
    00213     EnterDDECrit;
    00214
    00215     if (!ValidateConnectParameters((HANDLE)LongToHandle( idInst ), &pcii, &hszService, hszTopic,
    00216             &aNormalSvcName, &pCC, &hwndTarget, hConvList)) {
    00217         goto Exit;
    00218     }
    00219
    00220     ValidateConvList(hConvList);
    00221
    00222     hConvListOld = hConvList;
    00223     pcoi = (PCONV_INFO)ConnectConv(pcii,
    00224             LATOM_FROM_HSZ(hszService),
    00225             LATOM_FROM_HSZ(hszTopic),
    00226             hwndTarget,
    00227             (pcii->afCmd & (CBF_FAIL_SELFCONNECTIONS | CBF_FAIL_CONNECTIONS)) ?
    00228                 pcii->hwndMother : 0,
    00229             pCC,
    00230             hConvListOld,
    00231             CLST_MULT_INITIALIZING);
    00232
    00233     if (pcoi == NULL) {
    00234         /*
    00235          * no new connections made
    00236          */
    00237         SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
    00238         hConvListRet = hConvListOld;
    00239         goto Exit;
    00240     }
    00241
    00242     /*
    00243      * allocate or reallocate the hConvList hwnd list for later addition
    00244      * If we already have a valid list, reuse the handle so we don't have
    00245      * to alter the preexisting pcoi->hConvList values.
    00246      */
    00247     if (hConvListOld == 0) {
    00248         pcl = (PCONVLIST)DDEMLAlloc(sizeof(CONVLIST));
    00249         if (pcl == NULL) {
    00250             SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
    00251             DisconnectConv(pcoi);
    00252             goto Exit;
    00253         }
    00254         // pcl->chwnd = 0; LPTR zero inits.
    00255
    00256         hConvList = (HCONVLIST)CreateHandle((ULONG_PTR)pcl,
    00257                 HTYPE_CONVERSATION_LIST, InstFromHandle(pcii->hInstClient));
    00258         if (hConvList == 0) {
    00259             DDEMLFree(pcl);
    00260             SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
    00261             DisconnectConv(pcoi);
    00262             goto Exit;
    00263         }
    00264     } else {
    00265         pcl = (PCONVLIST)GetHandleData((HANDLE)hConvList);
    00266         pcl = DDEMLReAlloc(pcl, sizeof(CONVLIST) + sizeof(HWND) * pcl->chwnd);
    00267         if (pcl == NULL) {
    00268             SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR);
    00269             hConvListRet = hConvListOld;
    00270             DisconnectConv(pcoi);
    00271             goto Exit;
    00272         }
    00273         SetHandleData((HANDLE)hConvList, (ULONG_PTR)pcl);
    00274     }
    00275
    00276     ValidateConvList(hConvListOld);
    00277
    00278     if (hConvListOld) {
    00279         /*
    00280          * remove duplicates from new conversations
    00281          *
    00282          * Although we tried to prevent duplicates from happening
    00283          * within the initiate enumeration code, wild initiates or
    00284          * servers responding with different service names than
    00285          * requested could cause duplicates.
    00286          */
    00287
    00288         /* For each client window... */
    00289
    00290         for (i = 0; i < pcl->chwnd; i++) {
    00291
    00292         /* For each existing conversation in that window... */
    00293
    00294             for (pcoiExisting = (PCONV_INFO)
    00295                         GetWindowLongPtr(pcl->ahwnd[i], GWLP_PCI);
    00296                     pcoi != NULL && pcoiExisting != NULL;
    00297                     pcoiExisting = pcoiExisting->next) {
    00298
    00299                 if (!(pcoiExisting->state & ST_CONNECTED))
    00300                     continue;
    00301
    00302         /* For each new conversation... */
    00303
    00304                 for (pcoiNew = pcoi; pcoiNew != NULL; pcoiNew = pcoiNext) {
    00305
    00306                     pcoiNext = pcoiNew->next;
    00307
    00308         /* see if the new conversation duplicates the existing one */
    00309
    00310                     if (!(pcoiNew->state & ST_CONNECTED))
    00311                         continue;
    00312
    00313                     UserAssert(((PCL_CONV_INFO)pcoiExisting)->hwndReconnect);
    00314                     UserAssert(((PCL_CONV_INFO)pcoiNew)->hwndReconnect);
    00315
    00316                     if (((PCL_CONV_INFO)pcoiExisting)->hwndReconnect ==
    00317                                 ((PCL_CONV_INFO)pcoiNew)->hwndReconnect &&
    00318                             pcoiExisting->laTopic == pcoiNew->laTopic &&
    00319                             pcoiExisting->laService == pcoiNew->laService) {
    00320                         /*
    00321                          * duplicate conversation - disconnection causes an unlink
    00322                          */
    00323                         if (pcoiNew == pcoi) {
    00324                             /*
    00325                              * We are freeing up the head of the list,
    00326                              * Reset the head to the next guy.
    00327                              */
    00328                             pcoi = pcoiNext;
    00329                         }
    00330                         ValidateConvList(hConvList);
    00331                         ShutdownConversation(pcoiNew, FALSE);
    00332                         ValidateConvList(hConvList);
    00333                         break;
    00334                     }
    00335                 }
    00336             }
    00337         }
    00338
    00339         for (pcoiExisting = pcoi; pcoiExisting != NULL; pcoiExisting = pcoiExisting->next) {
    00340             /*
    00341              * if these are all zombies - we DONT want to link it in!
    00342              * This is possible because ShutdownConversation() leaves the critical section
    00343              * and could allow responding terminates to come through.
    00344              */
    00345             if (pcoiExisting->state & ST_CONNECTED) {
    00346                 goto FoundOne;
    00347             }
    00348         }
    00349         pcoi = NULL;    // abandon this guy - he will clean up in time.
    00350 FoundOne:
    00351         /*
    00352          * add new pcoi (if any are left) hwnd to ConvList hwnd list.
    00353          */
    00354         if (pcoi != NULL) {
    00355             UserAssert(pcoi->hwndConv);
    00356             pcl->ahwnd[pcl->chwnd] = pcoi->hwndConv;
    00357             pcl->chwnd++;
    00358             hConvListRet = hConvList;
    00359         } else {
    00360             hConvListRet = hConvListOld;
    00361             if (!hConvListOld) {
    00362                 DestroyHandle((HANDLE)hConvList);
    00363             }
    00364         }
    00365
    00366
    00367     } else {    // no hConvListOld
    00368
    00369         UserAssert(pcoi->hwndConv);
    00370         pcl->ahwnd[0] = pcoi->hwndConv;
    00371         pcl->chwnd = 1;
    00372         hConvListRet = hConvList;
    00373     }
    00374
    00375     if (pcoi != NULL) {
    00376         /*
    00377          * set hConvList field for all remaining new conversations.
    00378          */
    00379         UserAssert(hConvListRet);
    00380         for (pcoiNew = pcoi; pcoiNew != NULL; pcoiNew = pcoiNew->next) {
    00381             if (pcoiNew->state & ST_CONNECTED) {
    00382                 ((PCL_CONV_INFO)pcoiNew)->hConvList = hConvListRet;
    00383             }
    00384         }
    00385     }
    00386
    00387 Exit:
    00388     if (aNormalSvcName) {
    00389         DeleteAtom(aNormalSvcName);
    00390     }
    00391     ValidateConvList(hConvListRet);
    00392     LeaveDDECrit;
    00393     return (hConvListRet);
    00394 }

BOOL DdeDisconnect | ( | HCONV | hConv | ) |

Definition at line 1008 of file connect.c.

References BestSetLastDDEMLError(), BOOL, CheckDDECritOut, EnterDDECrit, FALSE, HINST_ANY, HTYPE_CLIENT_CONVERSATION, HTYPE_SERVER_CONVERSATION, LeaveDDECrit, NULL, PciiFromHandle(), ShutdownConversation(), tagCONV_INFO::state, TRUE, and ValidateCHandle().

Referenced by DdeUninitialize().

    01010 {
    01011     BOOL fRet = FALSE;
    01012     PCONV_INFO pcoi;
    01013     PCL_INSTANCE_INFO pcii;
    01014
    01015     CheckDDECritOut;
    01016     EnterDDECrit;
    01017
    01018     pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
    01019             HTYPE_CLIENT_CONVERSATION, HINST_ANY);
    01020     if (pcoi == NULL) {
    01021         pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv,
    01022                 HTYPE_SERVER_CONVERSATION, HINST_ANY);
    01023     }
    01024     if (pcoi == NULL) {
    01025         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    01026         goto Exit;
    01027     }
    01028     pcii = PciiFromHandle((HANDLE)hConv);
    01029     if (pcii == NULL) {
    01030         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    01031         goto Exit;
    01032     }
    01033     if (pcoi->state & ST_CONNECTED) {
    01034         ShutdownConversation(pcoi, FALSE);
    01035     }
    01036     fRet = TRUE;
    01037
    01038 Exit:
    01039     LeaveDDECrit;
    01040     return (fRet);
    01041 }

BOOL DdeDisconnectList | ( | HCONVLIST | hConvList | ) |

Definition at line 1053 of file connect.c.

References tagCONVLIST::ahwnd, BestSetLastDDEMLError(), BOOL, CheckDDECritOut, tagCONVLIST::chwnd, DDEMLFree, DestroyHandle(), EnterDDECrit, FALSE, GetWindowLongPtr(), GWLP_PCI, HINST_ANY, HTYPE_CONVERSATION_LIST, LeaveDDECrit, tagCONV_INFO::next, NULL, PciiFromHandle(), ShutdownConversation(), tagCONV_INFO::state, TRUE, ValidateCHandle(), and ValidateConvList.

Referenced by DdeUninitialize().

    01055 {
    01056     BOOL fRet = FALSE;
    01057     PCL_INSTANCE_INFO pcii;
    01058     PCONVLIST pcl;
    01059     PCONV_INFO pcoi, pcoiNext;
    01060     int i;
    01061
    01062     CheckDDECritOut;
    01063     EnterDDECrit;
    01064
    01065     pcl = (PCONVLIST)ValidateCHandle((HANDLE)hConvList,
    01066             HTYPE_CONVERSATION_LIST, HINST_ANY);
    01067     if (pcl == NULL) {
    01068         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    01069         goto Exit;
    01070     }
    01071     ValidateConvList(hConvList);
    01072     pcii = PciiFromHandle((HANDLE)hConvList);
    01073     if (pcii == NULL) {
    01074         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    01075         goto Exit;
    01076     }
    01077
    01078     for(i = pcl->chwnd - 1; i >= 0; i--) {
    01079         pcoi = (PCONV_INFO)GetWindowLongPtr(pcl->ahwnd[i], GWLP_PCI);
    01080         while (pcoi != NULL && pcoi->state & ST_CONNECTED) {
    01081             pcoiNext = pcoi->next;
    01082             ShutdownConversation(pcoi, FALSE);  // may unlink pcoi!
    01083             pcoi = pcoiNext;
    01084         }
    01085     }
    01086
    01087     DestroyHandle((HANDLE)hConvList);
    01088     DDEMLFree(pcl);
    01089     fRet = TRUE;
    01090
    01091 Exit:
    01092     LeaveDDECrit;
    01093     return (fRet);
    01094 }

HCONV DdeQueryNextServer | ( | HCONVLIST | hConvList,
|  | HCONV | hConvPrev
| ) |

Definition at line 906 of file connect.c.

References tagCONVLIST::ahwnd, BestSetLastDDEMLError(), tagCONVLIST::chwnd, tagCL_CONV_INFO::ci, EnterDDECrit, GetWindowLongPtr(), GWLP_PCI, tagCONV_INFO::hConv, tagCL_CONV_INFO::hConvList, HINST_ANY, HTYPE_CLIENT_CONVERSATION, HTYPE_CONVERSATION_LIST, HTYPE_ZOMBIE_CONVERSATION, tagCONV_INFO::hwndConv, InstFromHandle, tagCL_INSTANCE_INFO::LastError, LeaveDDECrit, tagCONV_INFO::next, NULL, PciiFromHandle(), SetLastDDEMLError(), TypeFromHandle, and ValidateCHandle().

    00909 {
    00910     HCONV hConvRet = 0;
    00911     PCONVLIST pcl;
    00912     HWND *phwnd;
    00913     int i;
    00914     PCL_CONV_INFO pci;
    00915     PCL_INSTANCE_INFO pcii;
    00916
    00917     EnterDDECrit;
    00918
    00919     pcl = (PCONVLIST)ValidateCHandle((HANDLE)hConvList,
    00920             HTYPE_CONVERSATION_LIST, HINST_ANY);
    00921     if (pcl == NULL) {
    00922         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    00923         goto Exit;
    00924     }
    00925     if (!pcl->chwnd) {      // empty list
    00926         goto Exit;
    00927     }
    00928     pcii = PciiFromHandle((HANDLE)hConvList);
    00929     if (pcii == NULL) {
    00930         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    00931         goto Exit;
    00932     }
    00933
    00934     pcii->LastError = DMLERR_NO_ERROR;
    00935
    00936     do {
    00937
    00938         hConvRet = 0;
    00939
    00940         if (hConvPrev == 0) {
    00941             pci = (PCL_CONV_INFO)GetWindowLongPtr(pcl->ahwnd[0], GWLP_PCI);
    00942             if (pci == NULL) {
    00943                 goto Exit;  // Must have all conversations zombied.
    00944             }
    00945             hConvPrev = hConvRet = pci->ci.hConv;
    00946             continue;
    00947         }
    00948
    00949         pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConvPrev,
    00950                 HTYPE_CLIENT_CONVERSATION, InstFromHandle(hConvList));
    00951         if (pci == NULL) {
    00952             pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConvPrev,
    00953                     HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(hConvList));
    00954             if (pci == NULL) {
    00955                 SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
    00956                 break;
    00957             } else {
    00958                 goto ZombieSkip;
    00959             }
    00960         }
    00961
    00962         if (pci->hConvList != hConvList) {
    00963             SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
    00964             break;
    00965         }
    00966
    00967 ZombieSkip:
    00968
    00969         if (pci->ci.next == NULL) {
    00970
    00971             /*
    00972              * end of list for this window, go to next window
    00973              */
    00974             for (phwnd = pcl->ahwnd, i = 0; (i + 1) < pcl->chwnd; i++) {
    00975                 if (phwnd[i] == pci->ci.hwndConv) {
    00976                     pci = (PCL_CONV_INFO)GetWindowLongPtr(phwnd[i + 1], GWLP_PCI);
    00977                     if (pci == NULL) {
    00978                         break;
    00979                     }
    00980                     hConvPrev = hConvRet = pci->ci.hConv;
    00981                     break;
    00982                 }
    00983             }
    00984         } else {
    00985
    00986             hConvPrev = hConvRet = pci->ci.next->hConv; // next conv for this window.
    00987         }
    00988
    00989     } while (hConvRet && TypeFromHandle(hConvRet) == HTYPE_ZOMBIE_CONVERSATION);
    00990 Exit:
    00991     LeaveDDECrit;
    00992     return (hConvRet);
    00993 }

HCONV DdeReconnect | ( | HCONV | hConv | ) |

Definition at line 409 of file connect.c.

References tagCONV_INFO::aLinks, BestSetLastDDEMLError(), tagCL_CONV_INFO::ci, tagCONV_INFO::cLinks, CLST_SINGLE_INITIALIZING, ClStartAdvise(), ConnectConv(), DDEMLAlloc, DDEMLFree, EnterDDECrit, tagXACT_INFO::flags, tagXACT_INFO::gaItem, GetConvContext(), tagCONV_INFO::hConv, HINST_ANY, HTYPE_CLIENT_CONVERSATION, tagCONV_INFO::hwndConv, tagCL_CONV_INFO::hwndReconnect, tagADVISE_LINK::laItem, tagCONV_INFO::laService, tagCONV_INFO::laTopic, LeaveDDECrit, LocalToGlobalAtom(), NULL, PADVISE_LINK, PciiFromHandle(), tagXACT_INFO::pcoi, SetLastDDEMLError(), tagCONV_INFO::state, ValidateCHandle(), tagADVISE_LINK::wFmt, tagXACT_INFO::wFmt, tagADVISE_LINK::wType, tagXACT_INFO::wType, XACT_INFO, and XIF_ABANDONED.

    00411 {
    00412     PCL_INSTANCE_INFO pcii;
    00413     PCL_CONV_INFO pci, pciNew;
    00414     HCONV hConvRet = 0;
    00415     CONVCONTEXT cc;
    00416
    00417     EnterDDECrit;
    00418
    00419     pcii = PciiFromHandle((HANDLE)hConv);
    00420     if (pcii == NULL) {
    00421         BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER);
    00422         goto Exit;
    00423     }
    00424     pci = (PCL_CONV_INFO)ValidateCHandle((HANDLE)hConv,
    00425             HTYPE_CLIENT_CONVERSATION, HINST_ANY);
    00426     if (pci == NULL) {
    00427         SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER);
    00428         goto Exit;
    00429     }
    00430
    00431     if (pci->ci.state & ST_CONNECTED) {
    00432         goto Exit;
    00433     }
    00434
    00435     GetConvContext(pci->ci.hwndConv, (LONG *)&cc);
    00436     pciNew = ConnectConv(pcii, pci->ci.laService, pci->ci.laTopic,
    00437             pci->hwndReconnect, 0, &cc, 0, CLST_SINGLE_INITIALIZING);
    00438     if (pciNew == NULL) {
    00439         SetLastDDEMLError(pcii, DMLERR_NO_CONV_ESTABLISHED);
    00440         goto Exit;
    00441     } else {
    00442         hConvRet = pciNew->ci.hConv;
    00443         if (pci->ci.cLinks) {
    00444             PXACT_INFO pxi;
    00445             int iLink;
    00446             PADVISE_LINK paLink;
    00447
    00448             /*
    00449              * reestablish advise links
    00450              */
    00451
    00452             for (paLink = pci->ci.aLinks, iLink = pci->ci.cLinks;
    00453                     iLink; paLink++, iLink--) {
    00454
    00455                 pxi = (PXACT_INFO)DDEMLAlloc(sizeof(XACT_INFO));
    00456                 if (pxi == NULL) {
    00457                     break;              // abort relinking
    00458                 }
    00459                 pxi->pcoi = (PCONV_INFO)pciNew;
    00460                 pxi->gaItem = LocalToGlobalAtom(paLink->laItem); // pxi copy
    00461                 pxi->wFmt = paLink->wFmt;
    00462                 pxi->wType = (WORD)((paLink->wType >> 12) | XTYP_ADVSTART);
    00463                 if (ClStartAdvise(pxi)) {
    00464                     pxi->flags |= XIF_ABANDONED;
    00465                 } else {
    00466                     GlobalDeleteAtom(pxi->gaItem);
    00467                     DDEMLFree(pxi);
    00468                 }
    00469             }
    00470         }
    00471     }
    00472
    00473 Exit:
    00474     LeaveDDECrit;
    00475     return (hConvRet);
    00476 }

VOID DisconnectConv | ( | PCONV_INFO | pcoi | ) |

Definition at line 759 of file connect.c.

References FALSE, tagCONV_INFO::next, ShutdownConversation(), and VOID().

Referenced by DdeConnectList().

    00761 {
    00762     PCONV_INFO pcoiNext;
    00763
    00764     for (; pcoi; pcoi = pcoiNext) {
    00765         pcoiNext = pcoi->next;
    00766         ShutdownConversation(pcoi, FALSE);
    00767     }
    00768 }

VOID FreeConversationResources | ( | PCONV_INFO | pcoi | ) |

Definition at line 1354 of file connect.c.

References tagCONV_INFO::aLinks, CheckDDECritIn, tagCONV_INFO::cLinks, tagCONV_INFO::cLocks, CreateHandle(), DDEMLFree, DeleteLinkCount(), DestroyHandle(), tagCONV_INFO::dmqIn, tagCONV_INFO::dmqOut, DumpDDEMessage(), FALSE, tagXACT_INFO::flags, tagCONV_INFO::hConv, HTYPE_ZOMBIE_CONVERSATION, tagCONV_INFO::hwndConv, tagCONV_INFO::hwndPartner, InstFromHandle, tagADVISE_LINK::laItem, tagCONV_INFO::laService, tagCONV_INFO::laServiceRequested, tagCONV_INFO::laTopic, LocalToGlobalAtom(), tagDDE_MESSAGE_QUEUE::lParam, MONLINK, tagDDE_MESSAGE_QUEUE::msg, tagXACT_INFO::next, tagDDE_MESSAGE_QUEUE::next, NULL, tagCONV_INFO::pcii, tagXACT_INFO::pfnResponse, tagADVISE_LINK::pLinkCount, PostMessage(), tagCONV_INFO::pxiOut, tagCONV_INFO::state, TID_TIMEOUT, TRUE, UnlinkConvFromOthers(), VOID(), tagADVISE_LINK::wFmt, tagADVISE_LINK::wType, and XIF_SYNCHRONOUS.

Referenced by DdeClientTransaction(), DdeEnableCallback(), DdePostAdvise(), EnableEnumProc(), ProcessAsyncDDEMsg(), ProcessSyncDDEMessage(), and ShutdownConversation().

    01356 {
    01357     PADVISE_LINK paLink;
    01358     PDDE_MESSAGE_QUEUE pdmq;
    01359     PXACT_INFO pxi;
    01360
    01361     CheckDDECritIn;
    01362
    01363     /*
    01364      * Don't free resources on locked conversations.
    01365      */
    01366     if (pcoi->cLocks > 0) {
    01367         pcoi->state |= ST_FREE_CONV_RES_NOW;
    01368         return;
    01369     }
    01370
    01371     /*
    01372      * Don't free resources if a synchronous transaction is in effect!
    01373      */
    01374     pxi = pcoi->pxiOut;
    01375     while (pxi != NULL) {
    01376         if (pxi->flags & XIF_SYNCHRONOUS) {
    01377             /*
    01378              * This conversation is in a synchronous transaction.
    01379              * Shutdown the modal loop FIRST, then call this when
    01380              * the loop exits.
    01381              */
    01382             PostMessage(pcoi->hwndConv, WM_TIMER, TID_TIMEOUT, 0);
    01383             pcoi->state |= ST_FREE_CONV_RES_NOW;
    01384             return;
    01385         }
    01386         pxi = pxi->next;
    01387     }
    01388
    01389     /*
    01390      * If this is an Intra-Process conversation that hasn't yet received
    01391      * a terminate message, make it a zombie.  We will call this routine
    01392      * again once the terminate arrives or when WaitForZombieTerminate() has
    01393      * timed out waiting.
    01394      */
    01395     if (pcoi->state & ST_INTRA_PROCESS && !(pcoi->state & ST_TERMINATE_RECEIVED)) {
    01396         DestroyHandle((HANDLE)pcoi->hConv);
    01397         pcoi->hConv = (HCONV)CreateHandle((ULONG_PTR)pcoi, HTYPE_ZOMBIE_CONVERSATION,
    01398                 InstFromHandle(pcoi->hConv));
    01399         UnlinkConvFromOthers(pcoi, TRUE);
    01400         return;
    01401     }
    01402
    01403     /*
    01404      * remove any transactions left in progress
    01405      */
    01406     while (pcoi->pxiOut != NULL) {
    01407         (pcoi->pxiOut->pfnResponse)(pcoi->pxiOut, 0, 0);
    01408     }
    01409
    01410     /*
    01411      * Throw away any incoming queued DDE messages.
    01412      */
    01413     while (pcoi->dmqOut != NULL) {
    01414
    01415         pdmq = pcoi->dmqOut;
    01416         DumpDDEMessage(!(pcoi->state & ST_INTRA_PROCESS), pdmq->msg, pdmq->lParam);
    01417         pcoi->dmqOut = pcoi->dmqOut->next;
    01418         if (pcoi->dmqOut == NULL) {
    01419             pcoi->dmqIn = NULL;
    01420         }
    01421         DDEMLFree(pdmq);
    01422     }
    01423
    01424     //
    01425     // Remove all link info
    01426     //
    01427     paLink = pcoi->aLinks;
    01428     while (pcoi->cLinks) {
    01429         if (pcoi->state & ST_CLIENT) {
    01430             MONLINK(pcoi->pcii, FALSE, paLink->wType & XTYPF_NODATA,
    01431                     pcoi->laService, pcoi->laTopic,
    01432                     LocalToGlobalAtom(paLink->laItem),
    01433                     paLink->wFmt, FALSE,
    01434                     (HCONV)pcoi->hwndPartner, (HCONV)pcoi->hwndConv);
    01435         } else {
    01436             MONLINK(pcoi->pcii, FALSE, paLink->wType & XTYPF_NODATA,
    01437                     pcoi->laService, pcoi->laTopic,
    01438                     LocalToGlobalAtom(paLink->laItem),
    01439                     paLink->wFmt, TRUE,
    01440                     (HCONV)pcoi->hwndConv, (HCONV)pcoi->hwndPartner);
    01441         }
    01442         if (!(pcoi->state & ST_CLIENT)) {
    01443             DeleteLinkCount(pcoi->pcii, paLink->pLinkCount);
    01444         }
    01445         DeleteAtom(paLink->laItem); // link structure copy
    01446         paLink++;
    01447         pcoi->cLinks--;
    01448     }
    01449     if (pcoi->aLinks) {
    01450         DDEMLFree(pcoi->aLinks);
    01451     }
    01452
    01453     //
    01454     // free atoms associated with this conv
    01455     //
    01456     DeleteAtom(pcoi->laService);
    01457     DeleteAtom(pcoi->laTopic);
    01458     if (pcoi->laServiceRequested) {
    01459         DeleteAtom(pcoi->laServiceRequested);
    01460     }
    01461
    01462     UnlinkConvFromOthers(pcoi, FALSE);
    01463
    01464     /*
    01465      * invalidate app's conversation handle
    01466      */
    01467     DestroyHandle((HANDLE)pcoi->hConv);
    01468
    01469     DDEMLFree(pcoi);
    01470 }

BOOL InitiateEnumerationProc | ( | HWND | hwndTarget,
|  | PINIT_ENUM | pie
| ) |

Definition at line 784 of file connect.c.

References tagCONVLIST::ahwnd, BOOL, CheckDDECritOut, tagCONVLIST::chwnd, tagCL_CONV_INFO::ci, tagINIT_ENUM::clst, CLST_MULT_INITIALIZING, CLST_SINGLE_INITIALIZING, EnterDDECrit, GetWindowLongPtr(), GWLP_PCI, tagINIT_ENUM::hConvList, HINST_ANY, HTYPE_CONVERSATION_LIST, tagINIT_ENUM::hwndClient, tagCL_CONV_INFO::hwndReconnect, tagINIT_ENUM::hwndSkip, IncLocalAtomCount(), tagCONV_INFO::laService, tagCONV_INFO::laServiceRequested, tagINIT_ENUM::laServiceRequested, tagCONV_INFO::laTopic, tagINIT_ENUM::laTopic, LeaveDDECrit, tagINIT_ENUM::lParam, tagCONV_INFO::next, NULL, SendMessage(), tagCONV_INFO::state, TRUE, and ValidateCHandle().

Referenced by ConnectConv().

    00787 {
    00788     PCL_CONV_INFO pci;
    00789
    00790     CheckDDECritOut;
    00791
    00792     if (hwndTarget == pie->hwndSkip) {
    00793         return (TRUE);
    00794     }
    00795
    00796     if (pie->hConvList && pie->laTopic && pie->laServiceRequested) {
    00797         /*
    00798          * Head off duplicates BEFORE we send the WM_DDE_INITIATE messages!
    00799          */
    00800         PCONVLIST pcl;
    00801         PCONV_INFO pcoiExisting;
    00802         int i;
    00803
    00804         EnterDDECrit;
    00805         /*
    00806          * We revalidate hConvList here because we left the critical section.
    00807          */
    00808         pcl = (PCONVLIST)ValidateCHandle((HANDLE)pie->hConvList,
    00809                 HTYPE_CONVERSATION_LIST, HINST_ANY);
    00810         if (pcl != NULL) {
    00811             for (i = 0; i < pcl->chwnd; i++) {
    00812                 for (pcoiExisting = (PCONV_INFO)GetWindowLongPtr(pcl->ahwnd[i], GWLP_PCI);
    00813                         pcoiExisting != NULL;
    00814                         pcoiExisting = pcoiExisting->next) {
    00815                     if (pcoiExisting->state & ST_CONNECTED &&
    00816                             ((PCL_CONV_INFO)pcoiExisting)->hwndReconnect == hwndTarget &&
    00817                             pcoiExisting->laTopic == pie->laTopic &&
    00818                             pcoiExisting->laService == pie->laServiceRequested) {
    00819                         LeaveDDECrit;
    00820                         return(TRUE);
    00821                     }
    00822                 }
    00823             }
    00824         }
    00825         LeaveDDECrit;
    00826     }
    00827
    00828     CheckDDECritOut;
    00829
    00830     SendMessage(hwndTarget, WM_DDE_INITIATE, (WPARAM)pie->hwndClient,
    00831             pie->lParam);
    00832
    00833     EnterDDECrit;
    00834
    00835     //
    00836     // During the initiate process, any acks received cause more pci's
    00837     // to become linked together under the same hwndClient. Once
    00838     // the SendMessage() returns, we set the parts of the new pci's
    00839     // that hold initiate context information.
    00840     //
    00841     pci = (PCL_CONV_INFO)GetWindowLongPtr(pie->hwndClient, GWLP_PCI);
    00842     if (pci == NULL) {
    00843         LeaveDDECrit;
    00844         return (TRUE);
    00845     }
    00846
    00847     while (pci != NULL) {
    00848         if (pci->hwndReconnect == 0) {  // this one needs updating
    00849             pci->hwndReconnect = hwndTarget;
    00850             if (pie->laServiceRequested) {
    00851                 pci->ci.laServiceRequested = pie->laServiceRequested;
    00852                 IncLocalAtomCount(pie->laServiceRequested); // pci copy
    00853             }
    00854         }
    00855         if (pie->clst == CLST_SINGLE_INITIALIZING) {
    00856             break;
    00857         }
    00858         pci = (PCL_CONV_INFO)pci->ci.next;
    00859     }
    00860     LeaveDDECrit;
    00861     return (pie->clst == CLST_MULT_INITIALIZING);
    00862 }

VOID SetCommonStateFlags | ( | HWND | hwndUs,
|  | HWND | hwndThem,
|  | PWORD | pwFlags
| ) |

Definition at line 876 of file connect.c.

References DWORD, GetWindowThreadProcessId(), IsWindowUnicode(), and VOID().

Referenced by DDEMLClientWndProc(), and ProcessDDEMLInitiate().

    00880 {
    00881     DWORD pidUs, pidThem;
    00882
    00883     GetWindowThreadProcessId(hwndUs, &pidUs);
    00884     GetWindowThreadProcessId(hwndThem, &pidThem);
    00885     if (pidUs == pidThem) {
    00886         *pwFlags |= ST_INTRA_PROCESS;
    00887     }
    00888
    00889     if (IsWindowUnicode(hwndUs) && IsWindowUnicode(hwndThem)) {
    00890         *pwFlags |= ST_UNICODE_EXECUTE;
    00891     }
    00892 }

VOID ShutdownConversation | ( | PCONV_INFO | pcoi,
|  | BOOL | fMakeCallback
| ) |

Definition at line 1109 of file connect.c.

References tagCL_INSTANCE_INFO::afCmd, CheckDDECritIn, DoCallback(), FALSE, FreeConversationResources(), tagCONV_INFO::hConv, tagCONV_INFO::hwndConv, tagCONV_INFO::hwndPartner, IsWindow(), L, MONCONV, tagCONV_INFO::pcii, PostMessage(), tagCONV_INFO::state, and VOID().

Referenced by DdeConnectList(), DdeDisconnect(), DdeDisconnectList(), DisconnectConv(), ProcessTerminateMsg(), and SpontaneousClientMessage().

    01112 {
    01113     CheckDDECritIn;
    01114
    01115     if (pcoi->state & ST_CONNECTED) {
    01116         pcoi->state &= ~ST_CONNECTED;
    01117
    01118         if (IsWindow(pcoi->hwndPartner)) {
    01119             PostMessage(pcoi->hwndPartner, WM_DDE_TERMINATE,
    01120                     (WPARAM)pcoi->hwndConv, 0);
    01121         }
    01122         if (fMakeCallback && !(pcoi->pcii->afCmd & CBF_SKIP_DISCONNECTS)) {
    01123             DoCallback(pcoi->pcii, (WORD)XTYP_DISCONNECT, 0, pcoi->hConv,
    01124                     0, 0, 0, 0, (pcoi->state & ST_ISSELF) ? 1L : 0L);
    01125         }
    01126         MONCONV(pcoi, FALSE);
    01127     }
    01128
    01129     FreeConversationResources(pcoi);
    01130 }

VOID UnlinkConvFromOthers | ( | PCONV_INFO | pcoi,
|  | BOOL | gGoingZombie
| ) |

Definition at line 1153 of file connect.c.

References tagCONVLIST::ahwnd, tagCL_INSTANCE_INFO::aServerLookup, BOOL, CheckDDECritIn, tagCONVLIST::chwnd, tagCL_INSTANCE_INFO::cServerLookupAlloc, DDEMLFree, DWORD, EnterDDECrit, FALSE, GetAppCompatFlags2(), GetHandleData(), GetWindowLongPtr(), GWLP_PCI, tagCONV_INFO::hConv, HTYPE_ZOMBIE_CONVERSATION, tagCONV_INFO::hwndConv, tagSERVER_LOOKUP::hwndServer, tagSERVER_LOOKUP::laService, tagSERVER_LOOKUP::laTopic, LeaveDDECrit, tagCONV_INFO::next, NtUserDestroyWindow(), NULL, ORPATH, path, tagCONV_INFO::pcii, PCL_CONV_INFO, SetWindowLongPtr(), tagCONV_INFO::state, TRUE, TypeFromHandle, ValidateAllConvLists, ValidateConvList, and VOID().

Referenced by FreeConversationResources().

    01156 {
    01157     PCONV_INFO pcoiPrev, pcoiFirst, pcoiNow;
    01158     PCONVLIST pcl;
    01159     int i, cActiveInList = 0;
    01160 #ifdef TESTING
    01161     DWORD path = 0;
    01162 #define ORPATH(x) path |= x;
    01163 #else
    01164 #define ORPATH(x)
    01165 #endif // TESTING
    01166
    01167     CheckDDECritIn;
    01168
    01169     /*
    01170      * Scan pcoi linked list to get key pointers.
    01171      */
    01172     pcoiPrev = NULL;
    01173     pcoiFirst = pcoiNow = (PCONV_INFO)GetWindowLongPtr(pcoi->hwndConv, GWLP_PCI);
    01174
    01175 #ifdef TESTING
    01176     /*
    01177      * verify that pcoi is in the conv list for this window.
    01178      */
    01179     while (pcoiNow != NULL) {
    01180         if (pcoiNow == pcoi) {
    01181             goto FoundIt;
    01182         }
    01183         pcoiNow = pcoiNow->next;
    01184     }
    01185     DebugBreak();
    01186 FoundIt:
    01187     pcoiNow = pcoiFirst;
    01188 #endif // TESTING
    01189
    01190     UserAssert(pcoiFirst);
    01191     while (pcoiNow != NULL) {
    01192         if (TypeFromHandle(pcoiNow->hConv) != HTYPE_ZOMBIE_CONVERSATION) {
    01193             ORPATH(1);
    01194             cActiveInList++;
    01195         }
    01196         if (pcoiNow->next == pcoi) {
    01197             pcoiPrev = pcoiNow;
    01198         }
    01199         pcoiNow = pcoiNow->next;
    01200     }
    01201
    01202     ValidateAllConvLists();
    01203
    01204     /*
    01205      * Unlink conversation unless its going Zombie.
    01206      */
    01207     if (!gGoingZombie) {
    01208         ORPATH(2);
    01209         if (TypeFromHandle(pcoi->hConv) != HTYPE_ZOMBIE_CONVERSATION) {
    01210             ORPATH(4);
    01211             cActiveInList--;
    01212         }
    01213
    01214         if (pcoiPrev == NULL) {
    01215             ORPATH(8);
    01216             pcoiFirst = pcoi->next;
    01217             SetWindowLongPtr(pcoi->hwndConv, GWLP_PCI, (LONG_PTR)pcoiFirst);
    01218         } else {
    01219             pcoiPrev->next = pcoi->next;
    01220         }
    01221     }
    01222
    01223     UserAssert(pcoiFirst != NULL || !cActiveInList);
    01224
    01225     if (cActiveInList == 0) {
    01226         ORPATH(0x10);
    01227         if (pcoi->state & ST_CLIENT) {
    01228             ORPATH(0x20);
    01229             if (((PCL_CONV_INFO)pcoi)->hConvList) {
    01230                 /*
    01231                  * Remove pcoi's hwnd from its hConvList.
    01232                  */
    01233                 pcl = (PCONVLIST)GetHandleData((HANDLE)((PCL_CONV_INFO)pcoi)->hConvList);
    01234                 for (i = 0; i < pcl->chwnd; i++) {
    01235                     if (pcl->ahwnd[i] == pcoi->hwndConv) {
    01236                         ORPATH(0x40);
    01237                         pcl->chwnd--;
    01238                         UserAssert(pcl->ahwnd[pcl->chwnd]);
    01239                         pcl->ahwnd[i] = pcl->ahwnd[pcl->chwnd];
    01240                         ValidateConvList(((PCL_CONV_INFO)pcoi)->hConvList);
    01241                         break;
    01242                     }
    01243                 }
    01244                 ORPATH(0x80);
    01245             }
    01246         } else {  // SERVER
    01247             /*
    01248              * remove server window from the service/topic lookup table.
    01249              */
    01250             ORPATH(0x100);
    01251             for (i = 0; i < pcoi->pcii->cServerLookupAlloc; i++) {
    01252                 if (pcoi->pcii->aServerLookup[i].hwndServer == pcoi->hwndConv) {
    01253                     ORPATH(0x200);
    01254
    01255                     /*
    01256                      * Check for appcompat hack
    01257                      */
    01258                     if (GetAppCompatFlags2(VERMAX) & GACF2_DDE) {
    01259                         DeleteAtom(pcoi->pcii->aServerLookup[i].laService); // delete laService
    01260                         DeleteAtom(pcoi->pcii->aServerLookup[i].laTopic);   // delete laTopic
    01261                     }
    01262
    01263                     if (--(pcoi->pcii->cServerLookupAlloc)) {
    01264                         ORPATH(0x400);
    01265                         pcoi->pcii->aServerLookup[i] =
    01266                                 pcoi->pcii->aServerLookup[pcoi->pcii->cServerLookupAlloc];
    01267                     } else {
    01268                         DDEMLFree(pcoi->pcii->aServerLookup);
    01269                         pcoi->pcii->aServerLookup = NULL;
    01270                     }
    01271                     break;
    01272                 }
    01273             }
    01274         }
    01275     }
    01276 #ifdef TESTING
    01277       else {
    01278         /*
    01279          * make sure at this point we have at least one non-zombie
    01280          */
    01281         pcoiNow = pcoiFirst;
    01282         while (pcoiNow != NULL) {
    01283             if (TypeFromHandle(pcoiNow->hConv) != HTYPE_ZOMBIE_CONVERSATION) {
    01284                 goto Out;
    01285             }
    01286             pcoiNow = pcoiNow->next;
    01287         }
    01288         DebugBreak();
    01289 Out:
    01290         ;
    01291     }
    01292 #endif // TESTING
    01293
    01294     ValidateAllConvLists();
    01295     ORPATH(0x800);
    01296
    01297     /*
    01298      * In any case remove hConvList references from client conversation.
    01299      */
    01300     if (pcoi->state & ST_CLIENT) {
    01301 #ifdef TESTING
    01302         /*
    01303          * Verify that the hConvList that is being removed, doesn't reference
    01304          * this window.
    01305          */
    01306         if (((PCL_CONV_INFO)pcoi)->hConvList && !cActiveInList) {
    01307             BOOL fFound = FALSE;
    01308
    01309             pcl = (PCONVLIST)GetHandleData((HANDLE)((PCL_CONV_INFO)pcoi)->hConvList);
    01310             for (i = 0; i < pcl->chwnd; i++) {
    01311                 if (pcl->ahwnd[i] == pcoi->hwndConv) {
    01312                     fFound = TRUE;
    01313                     break;
    01314                 }
    01315             }
    01316             UserAssert(!fFound);
    01317         }
    01318 #endif // TESTING
    01319         ((PCL_CONV_INFO)pcoi)->hConvList = 0;
    01320         pcoi->state &= ~ST_INLIST;
    01321     }
    01322
    01323     /*
    01324      * last one out turns out the lights.
    01325      */
    01326     if (pcoiFirst == NULL) {
    01327         /*
    01328          * If the pcoi list is empty, this window can go away.
    01329          */
    01330         LeaveDDECrit;
    01331         NtUserDestroyWindow(pcoi->hwndConv);
    01332         EnterDDECrit;
    01333     }
    01334 }

BOOL ValidateConnectParameters | ( | HANDLE | hInst,
|  | PCL_INSTANCE_INFO * | ppcii,
|  | HSZ * | phszService,
|  | HSZ | hszTopic,
|  | LATOM * | plaNormalSvcName,
|  | PCONVCONTEXT * | ppCC,
|  | HWND * | phwndTarget,
|  | HCONVLIST | hConvList
| ) |

Definition at line 491 of file connect.c.

References BOOL, DefConvContext, DWORD, FALSE, hInst, HSZT_INST_SPECIFIC, HSZT_INVALID, HTYPE_CONVERSATION_LIST, IIF_UNICODE, InstFromHandle, LATOM_FROM_HSZ, NORMAL_HSZ_FROM_LATOM, NULL, ParseInstSpecificAtom(), SetLastDDEMLError(), TempConvContext, TRUE, ValidateCHandle(), ValidateHSZ(), and ValidateInstance().

Referenced by DdeConnect(), and DdeConnectList().

    00500 {
    00501     DWORD hszType;
    00502     BOOL fError = FALSE;
    00503
    00504     *ppcii = ValidateInstance(hInst);
    00505     if (*ppcii == NULL) {
    00506         return (FALSE);
    00507     }
    00508     hszType = ValidateHSZ(*phszService);
    00509     if (hszType == HSZT_INVALID || ValidateHSZ(hszTopic) == HSZT_INVALID) {
    00510         SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
    00511         return (FALSE);
    00512     }
    00513     if (hszType == HSZT_INST_SPECIFIC) {
    00514         *phwndTarget = ParseInstSpecificAtom(LATOM_FROM_HSZ(*phszService),
    00515             plaNormalSvcName);
    00516         if (*plaNormalSvcName == 0) {
    00517             SetLastDDEMLError(*ppcii, DMLERR_SYS_ERROR);
    00518             return (FALSE);
    00519         }
    00520         *phszService = NORMAL_HSZ_FROM_LATOM(*plaNormalSvcName);
    00521     }
    00522     if (*ppCC == NULL) {
    00523         *ppCC = &DefConvContext;
    00524         if ((*ppcii)->flags & IIF_UNICODE) {
    00525             (*ppCC)->iCodePage = CP_WINUNICODE;
    00526         } else {
    00527             (*ppCC)->iCodePage = CP_WINANSI;
    00528         }
    00529     } else try {
    00530         if ((*ppCC)->cb > sizeof(CONVCONTEXT)) {
    00531             SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
    00532             fError = TRUE;
    00533         } else if ((*ppCC)->cb < sizeof(CONVCONTEXT)) {
    00534             TempConvContext = DefConvContext;
    00535             /*
    00536              * we can use this static temp because we are synchronized.
    00537              */
    00538             RtlCopyMemory(&TempConvContext, *ppCC, (*ppCC)->cb);
    00539             *ppCC = &TempConvContext;
    00540         }
    00541     } except(W32ExceptionHandler(FALSE, RIP_WARNING)) {
    00542         SetLastDDEMLError(*ppcii, DMLERR_INVALIDPARAMETER);
    00543         fError = TRUE;
    00544     }
    00545     if (fError) {
    00546         return(FALSE);
    00547     }
    00548     if (hConvList != 0 &&
    00549             !ValidateCHandle((HANDLE)hConvList, HTYPE_CONVERSATION_LIST,
    00550             (DWORD)InstFromHandle((*ppcii)->hInstClient))) {
    00551         return (FALSE);
    00552     }
    00553     return (TRUE);
    00554 }

BOOL WaitForZombieTerminate | ( | HANDLE | hData | ) |

Definition at line 1474 of file connect.c.

References BOOL, CheckDDECritOut, DispatchMessage(), DWORD, EnterDDECrit, FALSE, HTYPE_ZOMBIE_CONVERSATION, tagCONV_INFO::hwndConv, tagCONV_INFO::hwndPartner, InstFromHandle, LeaveDDECrit, msg, MsgWaitForMultipleObjectsEx(), NULL, PeekMessage(), ProcessTerminateMsg(), tagCONV_INFO::state, TRUE, and ValidateCHandle().

Referenced by DdeUninitialize().

    01476 {
    01477     PCONV_INFO pcoi;
    01478     MSG msg;
    01479     HWND hwnd;
    01480     BOOL fTerminated;
    01481     DWORD fRet = 0;
    01482
    01483     CheckDDECritOut;
    01484     EnterDDECrit;
    01485
    01486     fTerminated = FALSE;
    01487     while ((pcoi = (PCONV_INFO)ValidateCHandle(hData,
    01488             HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(hData))) != NULL &&
    01489             !(pcoi->state & ST_TERMINATE_RECEIVED)) {
    01490         hwnd = pcoi->hwndConv;
    01491         LeaveDDECrit;
    01492         while (PeekMessage(&msg, hwnd, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE)) {
    01493             DispatchMessage(&msg);
    01494             if (msg.message == WM_DDE_TERMINATE) {
    01495                 fTerminated = TRUE;
    01496             }
    01497         }
    01498         if (!fTerminated) {
    01499             fRet = MsgWaitForMultipleObjectsEx(0, NULL, 100, QS_POSTMESSAGE, 0);
    01500             if (fRet == 0xFFFFFFFF) {
    01501                 RIPMSG0(RIP_WARNING, "WaitForZombieTerminate: I give up - faking terminate.");
    01502                 ProcessTerminateMsg(pcoi, pcoi->hwndPartner);
    01503                 EnterDDECrit;
    01504                 return(FALSE);
    01505             }
    01506         }
    01507         EnterDDECrit;
    01508     }
    01509     LeaveDDECrit;
    01510     return(TRUE);
    01511 }

## Variable Documentation

CONVCONTEXT DefConvContext

Initial value:

     {
        sizeof(CONVCONTEXT),
        0,
        0,
        CP_WINANSI,
        0L,
        0L,
        {
            sizeof(SECURITY_QUALITY_OF_SERVICE),
            SecurityImpersonation,
            SECURITY_STATIC_TRACKING,
            TRUE
        }
    }

Definition at line 107 of file connect.c.

Referenced by DdeQueryConvInfo(), and ValidateConnectParameters().

CONVCONTEXT TempConvContext

| Definition at line 106 of file connect.c. Referenced by ValidateConnectParameters().