/* ********************************************************** session.c - Session DDE server for variable maintenance Placed in public domain by Horizon Technologies Inc. 1990 ***revision history*** 1 SESSION.C 29-Jan-90,10:23:54,`JMH' Base version 2 SESSION.C 19-Jun-90,10:51:18,`JMH' Version as of 6/25/90 ***revision history*** ********************************************************** */ #define MAIN #define NOCOMM #include "windows.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "dde.h" #include "ddelib.h" #include "session.h" /* Undocumented windows functions */ int FAR PASCAL lstrlen (LPSTR) ; LPSTR FAR PASCAL lstrcpy (LPSTR, LPSTR) ; LPSTR FAR PASCAL lstrcat (LPSTR, LPSTR) ; int FAR PASCAL lstrcmp (LPSTR, LPSTR) ; /* Globals */ static HANDLE ghInstance; static char *gszAppName = "Session"; static FARPROC glpfnAbout; static DDECALLBACK glpfnSession; /* Session Variables */ #define MAX_VARS 10 static struct { char szName[20]; char szValue[40]; } gVars[MAX_VARS]; /* Advise List */ #define MAX_ADVISE 10 static struct { char szName[20]; HANDLE hSession; BOOL bDeferUpd; BOOL bAckReq; } gAdvise[MAX_ADVISE]; /* Functions */ int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int); long FAR PASCAL SessionProc (HWND, unsigned, WORD, LONG); WORD FAR PASCAL Session (HWND, unsigned, LPSTR, HANDLE); void SetString (LPSTR, LPSTR); void GetString (LPSTR, LPSTR); void AdviseString (LPSTR, HANDLE, BOOL, BOOL); void UnadviseString (LPSTR, HANDLE); BOOL FAR PASCAL About (HWND, unsigned, WORD, LONG); int PASCAL WinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow) HANDLE hInstance; HANDLE hPrevInstance; LPSTR lpCmdLine; int nCmdShow; { WNDCLASS wndclass; MSG msg; HWND hWnd; ghInstance = hInstance; if (! hPrevInstance) { wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = SessionProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (hInstance, gszAppName); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = gszAppName; wndclass.lpszClassName = gszAppName; if (! RegisterClass (&wndclass)) return FALSE; } hWnd = CreateWindow (gszAppName, gszAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (! hWnd) return (NULL); ShowWindow (hWnd, SW_SHOWMINIMIZED); UpdateWindow (hWnd); while (GetMessage (&msg, NULL, NULL, NULL)) { TranslateMessage (&msg); DispatchMessage (&msg); } return (msg.wParam); } long FAR PASCAL SessionProc (hWnd, iMessage, wParam, lParam) HWND hWnd; unsigned iMessage; WORD wParam; LONG lParam; { static HANDLE hTopic; switch (iMessage) { case WM_CREATE: /* Provide callback addresses for DDE callback function */ glpfnSession = (DDECALLBACK) MakeProcInstance ((FARPROC) Session, ghInstance); /* Register the DDE Topic */ hTopic = DDERegisterTopic (hWnd, gszAppName, "Variables", glpfnSession); break; case WM_COMMAND: switch (wParam) { case IDM_EXIT: SendMessage (hWnd, WM_CLOSE, 0, 0L); break; case IDM_ABOUT: glpfnAbout = MakeProcInstance (About, ghInstance); DialogBox (ghInstance, "About", hWnd, glpfnAbout); FreeProcInstance (glpfnAbout); break; } break; case WM_CLOSE: /* Unregister the DDE Topic */ DDEUnregisterTopic (hTopic); return DefWindowProc (hWnd, iMessage, wParam, lParam); default: return DefWindowProc (hWnd, iMessage, wParam, lParam); } return 0L; } /* Callback routine to notify of client activity */ WORD FAR PASCAL Session (hSession, iMessage, lpszItem, hDataIn) HWND hSession; unsigned iMessage; LPSTR lpszItem; HANDLE hDataIn; { HANDLE hDataOut; DDEACK wAck; DDEDATA FAR *lpData; DDEPOKE FAR *lpPoke; DDEADVISE FAR *lpAdvise; LPSTR lpCommand; char szData[100]; /* Set up return value */ wAck.bAppReturnCode = 0; wAck.reserved = 0; wAck.fBusy = FALSE; wAck.fAck = TRUE; /* Switch on the message */ switch (iMessage) { case DDE_INITIATE: break; case DDE_TERMINATE: UnadviseString (NULL, hSession); break; case DDE_POKE: /* Get pointer to poke structure */ lpPoke = (DDEPOKE FAR *) GlobalLock (hDataIn); /* Accept only text */ if (lpPoke->cfFormat == CF_TEXT) SetString (lpszItem, lpPoke->Value); /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ GlobalUnlock (hDataIn); break; case DDE_REQUEST: /* Get pointer to advise structure */ lpAdvise = (DDEADVISE FAR *) GlobalLock (hDataIn); /* Accept only text */ if (lpAdvise->cfFormat == CF_TEXT) { /* Get the current value */ GetString (lpszItem, szData); /* Create a DDEDATA structure to send the client */ hDataOut = GlobalAlloc (GHND | GMEM_DDESHARE, (DWORD) sizeof (DDEDATA) + strlen (szData)); /* Set its members */ lpData = (DDEDATA FAR *) GlobalLock (hDataOut); lpData->fRelease = TRUE; lpData->fAckReq = FALSE; lpData->cfFormat = CF_TEXT; lstrcpy (lpData->Value, szData); GlobalUnlock (hDataOut); /* Send the data */ DDESendData (hSession, DDE_REQUEST, lpszItem, hDataOut); } /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ GlobalUnlock (hDataIn); break; case DDE_EXECUTE: /* Get pointer to command string */ lpCommand = GlobalLock (hDataIn); /* Ack ok */ wAck.fAck = TRUE; /* Clean up */ GlobalUnlock (hDataIn); break; case DDE_ADVISE: /* Get pointer to advise structure */ lpAdvise = (DDEADVISE FAR *) GlobalLock (hDataIn); /* Accept only text */ if (lpAdvise->cfFormat == CF_TEXT) AdviseString (lpszItem, hSession, lpAdvise->fDeferUpd, lpAdvise->fAckReq); /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ GlobalUnlock (hDataIn); break; case DDE_UNADVISE: UnadviseString (lpszItem, hSession); break; } return *(WORD *) &wAck; } /* Set the value of some string */ void SetString (lpszString, lpszValue) LPSTR lpszString; LPSTR lpszValue; { HANDLE hData; DDEDATA FAR *lpData; int iVar; int iEmpty = MAX_VARS; int iAdvise; /* Replace it if it exists */ for (iVar = 0; iVar < MAX_VARS; iVar++) { /* Found it: update and quit */ if (lstrcmp (gVars[iVar].szName, lpszString) == 0) { lstrcpy (gVars[iVar].szValue, lpszValue); break; } /* Found an empty slot, save its position */ if (iEmpty == MAX_VARS && strlen (gVars[iVar].szName) == 0) iEmpty = iVar; } /* Add it if it does not exist and there is room */ if (iVar == MAX_VARS && iEmpty != MAX_VARS) { iVar = iEmpty; lstrcpy (gVars[iVar].szName, lpszString); lstrcpy (gVars[iVar].szValue, lpszValue); } /* Update the world */ if (iVar != MAX_VARS) { /* Loop through the advise list */ for (iAdvise = 0; iAdvise < MAX_ADVISE; iAdvise++) { /* If waiting for this value */ if (lstrcmp (gVars[iVar].szName, gAdvise[iAdvise].szName) == 0) { /* If the client asked to defer updates */ if (gAdvise[iAdvise].bDeferUpd) { /* Create a DDEDATA structure to send the client */ hData = GlobalAlloc (GHND | GMEM_DDESHARE, (DWORD) sizeof (DDEDATA)); /* Set its members */ lpData = (DDEDATA FAR *) GlobalLock (hData); lpData->fRelease = TRUE; lpData->fAckReq = gAdvise[iAdvise].bAckReq; lpData->cfFormat = CF_TEXT; GlobalUnlock (hData); } /* Otherwise the client wants that data too */ else { /* Create a DDEDATA structure to send the client */ hData = GlobalAlloc (GHND | GMEM_DDESHARE, (DWORD) sizeof (DDEDATA) + lstrlen (lpszValue)); /* Set its members */ lpData = (DDEDATA FAR *) GlobalLock (hData); lpData->fRelease = TRUE; lpData->fAckReq = gAdvise[iAdvise].bAckReq; lpData->cfFormat = CF_TEXT; lstrcpy (lpData->Value, lpszValue); GlobalUnlock (hData); } /* Send the data */ DDESendData (gAdvise[iAdvise].hSession, DDE_ADVISE, lpszString, hData); } } } } /* Get the value of some string */ void GetString (lpszString, lpszValue) LPSTR lpszString; LPSTR lpszValue; { int iVar; /* Default to blank */ lstrcpy (lpszValue, ""); /* Find the value of some string */ for (iVar = 0; iVar < MAX_VARS; iVar++) { /* Found it */ if (lstrcmp (gVars[iVar].szName, lpszString) == 0) { lstrcpy (lpszValue, gVars[iVar].szValue); break; } } } /* Establish an advise circuit for a string */ void AdviseString (lpszString, hSession, bDeferUpd, bAckReq) LPSTR lpszString; HANDLE hSession; BOOL bDeferUpd; BOOL bAckReq; { int iAdvise; /* Loop through the advise list */ for (iAdvise = 0; iAdvise < MAX_ADVISE; iAdvise++) { /* If empty slot */ if (strlen (gAdvise[iAdvise].szName) == 0) { lstrcpy (gAdvise[iAdvise].szName, lpszString); gAdvise[iAdvise].hSession = hSession; gAdvise[iAdvise].bDeferUpd = bDeferUpd; gAdvise[iAdvise].bAckReq = bAckReq; break; } } } /* Terminate an advise circuit for a string */ void UnadviseString (lpszString, hSession) LPSTR lpszString; HANDLE hSession; { int iAdvise; /* Loop through the advise list */ for (iAdvise = 0; iAdvise < MAX_ADVISE; iAdvise++) { /* If empty slot */ if (gAdvise[iAdvise].hSession == hSession && (gAdvise[iAdvise].szName == NULL || lstrcmp (gAdvise[iAdvise].szName, lpszString) == 0)) { lstrcpy (gAdvise[iAdvise].szName, ""); gAdvise[iAdvise].hSession = 0; gAdvise[iAdvise].bDeferUpd = FALSE; gAdvise[iAdvise].bAckReq = FALSE; break; } } } /* About box */ BOOL FAR PASCAL About (hDlg, iMessage, wParam, lParam) HWND hDlg; unsigned iMessage; WORD wParam; LONG lParam; { switch(iMessage) { case WM_INITDIALOG: break; case WM_COMMAND: EndDialog (hDlg, FALSE); break; default: return FALSE; } return TRUE; }