/****************************** Module Header ******************************\ * Module Name: STDINIT.C * * This module contains functions used in the involved initiate sequence. * * Created: 3/21/91 Sanfords * * Copyright (c) 1991 Microsoft Corporation \***************************************************************************/ #include "ddemlp.h" /* * WM_CREATE ClientWndProc processing */ long ClientCreate( HWND hwnd, PAPPINFO pai) { PCLIENTINFO pci; static DWORD defid = (DWORD)QID_SYNC; static XFERINFO defXferInfo = { &defid, 1L, XTYP_CONNECT, DDEFMT_TEXT, 0L, 0L, }; /* * allocate and initialize the client window info. */ SEMENTER(); if(!(pci = (PCLIENTINFO)FarAllocMem(pai->hheapApp, sizeof(CLIENTINFO)))) { SEMLEAVE(); SETLASTERROR(pai, DMLERR_MEMORY_ERROR); return(1); /* aboart creation - low memory */ } SetWindowLong(hwnd, GWL_PCI, (DWORD)pci); SetWindowWord(hwnd, GWW_CHECKVAL, ++hwInst); pci->ci.pai = pai; // pci->ci.xad.hUser = 0L; pci->ci.xad.state = XST_NULL; pci->ci.xad.pXferInfo = &defXferInfo; //??? pci->ci.fs = ST_CLIENT | (pai->wFlags & AWF_DEFCREATESTATE ? ST_BLOCKED : 0); if (GetWindowLong(GetParent(hwnd), GWL_WNDPROC) == (LONG)ConvListWndProc) pci->ci.fs |= ST_INLIST; // pci->ci.hConvPartner = NULL; // pci->ci.hszServerApp = NULL; // pci->ci.hszTopic = NULL; pci->pQ = NULL; /* don't create until we need one */ pci->pClientAdvList = CreateLst(pai->hheapApp, sizeof(ADVLI)); SEMLEAVE(); } /***************************** Private Function ****************************\ * This routine returns the hwnd of a newly created and connected DDE * client or NULL if failure. * * History: created 1/6/89 sanfords \***************************************************************************/ HWND GetDDEClientWindow( PAPPINFO pai, HWND hwndParent, HWND hwndSend, // NULL -> broadcast HSZ hszSvc, ATOM aTopic, PCONVCONTEXT pCC) { HWND hwnd; PCLIENTINFO pci; SEMCHECKOUT(); if(!(hwnd = CreateWindow(SZCLIENTCLASS, szNull, WS_CHILD, 0, 0, 0, 0, hwndParent, NULL, hInstance, &pai))) { return(NULL); } pci = (PCLIENTINFO)GetWindowLong(hwnd, GWL_PCI); SEMENTER(); /* * we need to set this info BEFORE we do the synchronous initiate * so the INITIATEACK msg is done correctly. */ pci->ci.xad.state = XST_INIT1; pci->ci.xad.LastError = DMLERR_NO_ERROR; pci->ci.hszSvcReq = hszSvc; pci->ci.aServerApp = LOWORD(hszSvc); pci->ci.aTopic = aTopic; pci->ci.CC = pCC ? *pCC : CCDef; SEMLEAVE(); if (hwndSend) { pci->hwndInit = hwndSend; SendMessage(hwndSend, WM_DDE_INITIATE, hwnd, MAKELONG((ATOM)hszSvc, aTopic)); } else { IE ie = { hwnd, pci, aTopic }; EnumWindows(InitEnum, (LONG)(IE FAR *)&ie); } if (pci->ci.xad.state == XST_INIT1) { // no connections? DestroyWindow(hwnd); return(NULL); } pci->ci.xad.state = XST_CONNECTED; // fully ready now. pci->ci.fs |= ST_CONNECTED; return(hwnd); } BOOL FAR PASCAL InitEnum( HWND hwnd, IE FAR *pie) { pie->pci->hwndInit = hwnd; SendMessage(hwnd, WM_DDE_INITIATE, pie->hwnd, MAKELONG((ATOM)pie->pci->ci.hszSvcReq, pie->aTopic)); return((pie->pci->ci.fs & ST_INLIST) || pie->pci->ci.xad.state == XST_INIT1); } void ServerFrameInitConv( PAPPINFO pai, HWND hwndFrame, HWND hwndClient, ATOM aApp, ATOM aTopic) { HSZPAIR hp[2]; PHSZPAIR php; DWORD dwRet; LPBYTE pdata; HWND hwndServer; BOOL fWild, fIsLocal, fIsSelf = FALSE; PCLIENTINFO pci; SEMCHECKOUT(); if (pai->afCmd & CBF_FAIL_CONNECTIONS) { return; } /* * If we are filtering and no app names are registered, quit. */ if ((pai->afCmd & APPCMD_FILTERINITS) && QPileItemCount(pai->pAppNamePile) == 0) { return; } fIsLocal = ((FARPROC)GetWindowLong(hwndClient,GWL_WNDPROC) == (FARPROC)ClientWndProc); if (fIsLocal) { pci = (PCLIENTINFO)GetWindowLong(hwndClient, GWL_PCI); fIsSelf = (pci->ci.pai == pai); /* * filter out inits from ourselves */ if (pai->afCmd & CBF_FAIL_SELFCONNECTIONS && fIsSelf) { return; } } hp[0].hszSvc = (HSZ)aApp; /* * filter out unwanted app names. */ if (aApp && (pai->afCmd & APPCMD_FILTERINITS) && !FindPileItem(pai->pAppNamePile, CmpWORD, (LPBYTE)&aApp, 0)) return; hp[0].hszTopic = aTopic; hp[1].hszSvc = hp[1].hszTopic = 0L; fWild = (hp[0].hszSvc == 0L || hp[0].hszTopic == 0L); dwRet = DoCallback(pai, NULL, hp[0].hszTopic, hp[0].hszSvc, 0, (fWild ? XTYP_WILDCONNECT : XTYP_CONNECT), 0L, fIsLocal ? (DWORD)&pci->ci.CC : 0L, fIsSelf ? 1 : 0); if (dwRet == NULL) return; if (fWild) { pdata = GLOBALLOCK(HIWORD(dwRet)); php = (PHSZPAIR)pdata; } else { php = &hp[0]; pdata = NULL; } /* * now php points to a 0 terminated list of hszpairs to respond to. */ SEMENTER(); while (QueryHszLength(php->hszSvc) && QueryHszLength(php->hszTopic)) { PSERVERINFO psi; SEMLEAVE(); if ((hwndServer = CreateServerWindow(pai, (ATOM)php->hszTopic, fIsLocal ? &pci->ci.CC : &CCDef)) == 0) return; SEMENTER(); /* * have the server respond */ psi = (PSERVERINFO)GetWindowLong(hwndServer, GWL_PCI); psi->ci.hConvPartner = fIsLocal ? MAKEHCONV(hwndClient) : (HCONV)hwndClient; psi->ci.hwndFrame = hwndFrame; psi->ci.fs |= ST_CONNECTED; if (fIsSelf) { psi->ci.fs |= ST_ISSELF; pci->ci.fs |= ST_ISSELF; } psi->ci.xad.state = XST_CONNECTED; psi->ci.hszSvcReq = (HSZ)aApp; psi->ci.aServerApp = (ATOM)php->hszSvc; psi->ci.aTopic = (ATOM)php->hszTopic; MONCONN(psi->ci.pai, psi->ci.aServerApp, psi->ci.aTopic, hwndClient, hwndServer, TRUE); IncHszCount(aApp); // for server window to keep IncHszCount(LOWORD(php->hszSvc)); IncHszCount(LOWORD(php->hszTopic)); IncHszCount(LOWORD(php->hszSvc)); // for client to remove on ack IncHszCount(LOWORD(php->hszTopic)); #ifdef DEBUG cAtoms -= 2; // we are giving these away #endif SEMLEAVE(); SendMessage(hwndClient, WM_DDE_ACK, hwndServer, MAKELONG(LOWORD(php->hszSvc), LOWORD(php->hszTopic))); /* * confirm initialization to server app - synchronously */ DoCallback(pai, MAKEHCONV(hwndServer), php->hszTopic, php->hszSvc, 0, XTYP_CONNECT_CONFIRM, 0L, 0L, fIsSelf ? 1 : 0); SEMENTER(); php++; } if (pdata) { GLOBALUNLOCK(HIWORD(dwRet)); FreeDataHandle(pai, dwRet, TRUE); } SEMLEAVE(); SEMCHECKOUT(); } HWND CreateServerWindow( PAPPINFO pai, ATOM aTopic, PCONVCONTEXT pCC) { HWND hwndServer; SEMCHECKOUT(); /* * make a server root window if needed.... */ if (pai->hwndSvrRoot == 0) { /* * NO - make one. */ if ((pai->hwndSvrRoot = CreateWindow(SZCONVLISTCLASS, szNull, WS_CHILD, 0, 0, 0, 0, pai->hwndDmg, NULL, hInstance, 0L)) == NULL) { SETLASTERROR(pai, DMLERR_SYS_ERROR); return(NULL); } } /* * Create the server window */ if ((hwndServer = CreateWindow(SZSERVERCLASS, szNull, WS_CHILD, 0, 0, 0, 0, pai->hwndSvrRoot, NULL, hInstance, &pai)) == NULL) { SETLASTERROR(pai, DMLERR_SYS_ERROR); return(NULL); } ((PSERVERINFO)GetWindowLong(hwndServer, GWL_PCI))->ci.CC = *pCC; return(hwndServer); } /* * WM_CREATE ServerWndProc processing */ long ServerCreate( HWND hwnd, PAPPINFO pai) { PSERVERINFO psi; /* * allocate and initialize the server window info. */ SEMENTER(); if (!(psi = (PSERVERINFO)FarAllocMem(pai->hheapApp, sizeof(SERVERINFO)))) { SETLASTERROR(pai, DMLERR_MEMORY_ERROR); return(1); } SEMLEAVE(); psi->ci.pai = pai; // psi->ci.xad.hUser = 0L; psi->ci.xad.state = XST_NULL; psi->ci.fs = pai->wFlags & AWF_DEFCREATESTATE ? ST_BLOCKED : 0; SetWindowLong(hwnd, GWL_PCI, (DWORD)psi); SetWindowWord(hwnd, GWW_CHECKVAL, ++hwInst); return(0); } /* * Client response to a WM_DDE_ACK message when ACK to INITIATE expected. */ BOOL ClientInitAck(hwnd, pci, hwndServer, aApp, aTopic) HWND hwnd; PCLIENTINFO pci; HWND hwndServer; ATOM aApp; ATOM aTopic; { HWND hwndClient; PCLIENTINFO pciNew; #ifdef DEBUG cAtoms += 2; // the incomming atoms need to be accounted for. #endif SEMCHECKOUT(); switch (pci->ci.xad.state) { case XST_INIT1: /* * first one back... lock in! */ pci->ci.xad.state = XST_INIT2; MONCONN(pci->ci.pai, aApp, aTopic, hwnd, hwndServer, TRUE); if (GetWindowLong(hwndServer, GWL_WNDPROC) == (LONG)ServerWndProc) { pci->ci.fs |= ST_ISLOCAL; pci->ci.hConvPartner = MAKEHCONV(hwndServer); } else { pci->ci.hConvPartner = (HCONV)hwndServer; if (aApp == aProgmanHack) { // PROGMAN HACK!!!! IncHszCount(aApp); IncHszCount(aTopic); #ifdef DEBUG cAtoms -= 2; #endif } } pci->ci.aServerApp = aApp; pci->ci.aTopic = aTopic; if (!pci->ci.hwndFrame) // remember the frame this was sent to. pci->ci.hwndFrame = pci->hwndInit; IncHszCount(LOWORD(pci->ci.hszSvcReq)); // keep this for ourselves break; case XST_INIT2: // Extra ack... // throw away if from our partner or if we are not in a list. if (hwndServer == (HWND)pci->ci.hConvPartner || GetParent(hwnd) == pci->ci.pai->hwndDmg) { Abort: TRACETERM((szT, "ClientInitAck: Extra ack terminate: %x->%x\n", hwndServer, hwnd)); PostMessage(hwndServer, WM_DDE_TERMINATE, hwnd, 0L); FreeHsz(aApp); FreeHsz(aTopic); break; } if (GetWindowLong(hwndServer, GWL_WNDPROC) != (LONG)ServerWndProc) { // Non Local Extra Ack... terminate and attempt reconnection. TRACETERM((szT, "ClientInitAck: Extra ack terminate and reconnect: %x->%x\n", hwndServer, hwnd)); PostMessage(hwndServer, WM_DDE_TERMINATE, hwnd, 0L); GetDDEClientWindow(pci->ci.pai, GetParent(hwnd), pci->hwndInit, aApp, aTopic, &pci->ci.CC); // PROGMAN HACK!!!! if (aApp != aProgmanHack) { FreeHsz(aApp); FreeHsz(aTopic); } break; } // Local Extra Ack... create a client window, set it up to be talking // to the server window and tell the server window to change // partners. hwndClient = CreateWindow(SZCLIENTCLASS, szNull, WS_CHILD, 0, 0, 0, 0, GetParent(hwnd), NULL, hInstance, &(pci->ci.pai)); if (!hwndClient) { SETLASTERROR(pci->ci.pai, DMLERR_SYS_ERROR); goto Abort; } pciNew = (PCLIENTINFO)GetWindowLong(hwndClient, GWL_PCI); pciNew->ci.xad.state = XST_CONNECTED; pciNew->ci.xad.LastError = DMLERR_NO_ERROR; pciNew->ci.aServerApp = aApp; pciNew->ci.hszSvcReq = pci->ci.hszSvcReq; IncHszCount(LOWORD(pciNew->ci.hszSvcReq)); pciNew->ci.aTopic = aTopic; pciNew->ci.hConvPartner = MAKEHCONV(hwndServer); pciNew->ci.hwndFrame = pci->hwndInit; pciNew->ci.fs |= ST_CONNECTED | ST_ISLOCAL; MONCONN(pciNew->ci.pai, aApp, aTopic, hwnd, hwndServer, TRUE); SendMessage(hwndServer, UMSR_CHGPARTNER, hwndClient, 0L); break; } return(TRUE); }