/* ********************************************************** 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 3 SESSION.C 25-Jun-90,14:48:04,`JMH' Version as of 6/25/90 4 SESSION.C 15-Sep-90,16:19:56,`JMH' Version 1.3 ***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; static HANDLE ghList = NULL; /* Session variables */ #define MAX_VARS 20 static struct { char szName[20]; char szValue[20]; } gVars[MAX_VARS]; /* 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); 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; } /* if ! hPrevInstance */ 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 ); } /* while GetMessage */ return ( msg.wParam ); } /* function WinMain */ 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; } /* switch wParam */ break; case WM_DESTROY: /* Unregister the DDE Topic */ DDEUnregisterTopic ( hTopic ); PostQuitMessage ( 0 ); break; default: return DefWindowProc ( hWnd, iMessage, wParam, lParam ); } /* switch iMessage */ return 0L; } /* function SessionProc */ /* 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; LPDDEDATA lpData; LPDDEPOKE lpPoke; LPDDEADVISE 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: ghList = DDEUnregisterAdvise ( ghList, hSession, NULL ); break; case DDE_POKE: /* Get pointer to poke structure */ lpPoke = (LPDDEPOKE) GlobalLock ( hDataIn ); /* Accept only text */ if ( lpPoke && lpPoke->cfFormat == CF_TEXT ) SetString ( lpszItem, lpPoke->Value ); /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ if ( lpPoke ) GlobalUnlock ( hDataIn ); break; case DDE_REQUEST: /* Get pointer to advise structure */ lpAdvise = (LPDDEADVISE) GlobalLock ( hDataIn ); /* Accept only text */ if ( lpAdvise && 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 = (LPDDEDATA) 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 ); } /* if lpAdvise */ /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ if ( lpAdvise ) GlobalUnlock ( hDataIn ); break; case DDE_EXECUTE: /* Get pointer to command string */ lpCommand = GlobalLock ( hDataIn ); /* Process command here */ /* Ack bad - we do not accept commands yet */ wAck.fAck = FALSE; /* Clean up */ if ( lpCommand ) GlobalUnlock ( hDataIn ); break; case DDE_ADVISE: /* Get pointer to advise structure */ lpAdvise = (LPDDEADVISE) GlobalLock ( hDataIn ); /* Accept only text */ if ( lpAdvise && lpAdvise->cfFormat == CF_TEXT ) ghList = DDERegisterAdvise ( ghList, hSession, lpszItem, lpAdvise->fAckReq, lpAdvise->fDeferUpd, CF_TEXT ); /* Reject all else */ else wAck.fAck = FALSE; /* Clean up */ if ( lpAdvise ) GlobalUnlock ( hDataIn ); break; case DDE_UNADVISE: ghList = DDEUnregisterAdvise ( ghList, hSession, lpszItem ); break; } /* switch iMessage */ return *(WORD *) &wAck; } /* function Session */ /* Set the value of some string */ void SetString (lpszString, lpszValue) LPSTR lpszString; LPSTR lpszValue; { HANDLE hData = NULL; LPDDEDATA lpData; int iVar; int iEmpty = MAX_VARS; int nItem = 0; HANDLE hSession; char szItem[20]; int fAckReq; int fDeferUpd; int cfFormat; /* 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; } /* if lstrcmp */ /* Found an empty slot, save its position */ if ( iEmpty == MAX_VARS && strlen ( gVars [iVar].szName ) == 0 ) iEmpty = iVar; } /* for 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 ); } /* if iVar */ /* Update the world */ if ( iVar != MAX_VARS ) { /* Loop through the advise list */ while ( DDEGetAdvise ( ghList, nItem++, &hSession, szItem, sizeof ( szItem ), &fAckReq, &fDeferUpd, &cfFormat ) != -1 ) { /* If advised on this variable */ if ( lstrcmp ( lpszString, szItem ) == 0 ) { /* If the client asked for a "hot" link */ if ( ! fDeferUpd ) { /* Create a DDEDATA structure to send the client */ hData = GlobalAlloc ( GHND | GMEM_DDESHARE, (DWORD) sizeof ( DDEDATA ) + lstrlen ( lpszValue ) ); /* Set its members */ lpData = (LPDDEDATA) GlobalLock ( hData ); lpData->fRelease = TRUE; lpData->fAckReq = fAckReq; lpData->cfFormat = cfFormat; lstrcpy ( lpData->Value, lpszValue ); GlobalUnlock ( hData ); } /* Send the data */ DDESendData ( hSession, DDE_ADVISE, lpszString, hData ); } /* if lstrcmp */ } /* for iAdvise */ } /* if iVar */ } /* function SetString */ /* 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; } /* if lstrcmp */ } /* for iVar */ } /* function GetString */ /* 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; } /* switch iMessage */ return TRUE; } /* function About */