465 lines
12 KiB
C
465 lines
12 KiB
C
|
/****************************** 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);
|
||
|
}
|
||
|
|