home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / TSTAPP.PAK / DDECLNT.C next >
C/C++ Source or Header  |  1995-08-29  |  17KB  |  515 lines

  1. // Borland C++ - (C) Copyright 1991, 1992 by Borland International
  2.  
  3. //*******************************************************************
  4. //
  5. // program - DDEClnt.c
  6. // purpose - dde client interface routines. This file is part of the
  7. //           TSTAPP project.
  8. //
  9. //*******************************************************************
  10.  
  11. #define  STRICT
  12. #include <windows.h>
  13. #pragma hdrstop
  14. #include <dde.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include <windowsx.h>
  18.  
  19. #include "ddepack.h"
  20. #include "ddeclnt.h"
  21.  
  22. #define WW_SERVER  0
  23. #define ACK        0x8000
  24. #define BUSY       0x4000
  25.  
  26. #if defined(__FLAT__)
  27.   #define _fstrlen  strlen
  28.   #define _fstrcpy  strcpy
  29. #endif
  30.  
  31. #if defined(__WIN32__)
  32.   #define SetWindowServer(hWnd,hWndServer)\
  33.     SetWindowLong (hWnd, WW_SERVER, (LONG) (hWndServer))
  34.   #define GetWindowServer(hWnd)\
  35.     ((HWND) GetWindowLong (hWnd, WW_SERVER))
  36.   #define DDECommandHandle(hCommand)\
  37.     ((LPARAM)(hCommand))
  38. #else
  39.   #define SetWindowServer(hWnd,hWndServer)\
  40.     SetWindowWord (hWnd, WW_SERVER, (WORD) (hWndServer))
  41.   #define GetWindowServer(hWnd)\
  42.     ((HWND) GetWindowWord (hWnd, WW_SERVER))
  43.   #define DDECommandHandle(hCommand)\
  44.     ((LPARAM)(MAKELONG(0,(hCommand))))
  45. #endif
  46.  
  47. static int          nClientClassRegistered;
  48. static char         szClientClass[] = "ddeclient";
  49. static WORD         wLastDDEClientMsg;
  50. static int          nAckFlg;
  51. static int          nBusyFlg;
  52. static HANDLE       hData;
  53.  
  54. //*******************************************************************
  55. // DDEClientOpen - open a dde conversation with a server
  56. //
  57. // paramaters:
  58. //             hParentWnd    - The handle of the window trying to start
  59. //                             this dde conversation.
  60. //             szApp         - The name of the application to talk to.
  61. //             szTopic       - The name of the topic to talk about.
  62. //
  63. // returns:
  64. //             The handle of the channel to use to continue the conversation
  65. //                or
  66. //             NULL if conversation could not be opened.
  67. //
  68. //*******************************************************************
  69. HWND DDEClientOpen(HWND hParentWnd, char *szApp, char *szTopic)
  70. {
  71.     HINSTANCE hInst;
  72.     HWND     hChannel;
  73.     ATOM     aApp;
  74.     ATOM     aTopic;
  75.     WNDCLASS wclass;
  76.  
  77.     // Get parents instance to use in creating window to carry on
  78.     // dde conversation.
  79.     hInst = (HINSTANCE)GetWindowInstance(hParentWnd);
  80.     if (!hInst)
  81.         return(0);
  82.  
  83.     // If we have not already done it, register the window class to
  84.     // carry on this conversation.
  85.     if (!nClientClassRegistered)
  86.     {
  87.         wclass.style         = CS_HREDRAW | CS_VREDRAW;
  88.   wclass.lpfnWndProc   = DDEClientWndProc;
  89.         wclass.cbClsExtra    = 0;
  90.         wclass.cbWndExtra    = sizeof (HWND);
  91.         wclass.hInstance     = hInst;
  92.         wclass.hIcon         = 0;
  93.         wclass.hCursor       = 0;
  94.         wclass.hbrBackground = 0;
  95.         wclass.lpszMenuName  = 0;
  96.   wclass.lpszClassName = szClientClass;
  97.  
  98.         // Do not fail if register fails, because another app may have
  99.         // already registered this class.
  100.         RegisterClass(&wclass);
  101.  
  102.         // So we won't try to register again.
  103.         nClientClassRegistered = 1;
  104.     }
  105.  
  106.     // Create the window that will remain hidden but will carry on the
  107.     // conversation wih the dde server.
  108.     hChannel = CreateWindow(szClientClass,    // window class name
  109.                             NULL,             // window title
  110.                             WS_CHILD,         // window style
  111.                             CW_USEDEFAULT,    // window origin
  112.                             0,
  113.                             CW_USEDEFAULT,    // window size
  114.                             0,
  115.                             hParentWnd,       // window parent
  116.           NULL,             // window id
  117.                             hInst,            // window instance
  118.                             NULL);            // no parms
  119.  
  120.     // If create of window failed we cannot continue
  121.     if (!hChannel)
  122.         return(0);
  123.  
  124.     // Create atoms representing application and topic we want to talk about
  125.     aApp = GlobalAddAtom(szApp);
  126.     if (!aApp)
  127.         return(0);
  128.  
  129.     aTopic = GlobalAddAtom(szTopic);
  130.     if (!aTopic)
  131.     {
  132.         GlobalDeleteAtom(aApp);
  133.         return(0);
  134.     }
  135.  
  136.     // Remember the last dde message we sent, because the window proc we
  137.     // just created must know the last message sent by this application
  138.     // to properly respond to a dde response.
  139.     wLastDDEClientMsg = WM_DDE_INITIATE;
  140.  
  141.     // Broadcast a dde initiate to all apps on this system to see if any
  142.     // will talk to us about the requested application and topic.
  143.     SendMessage((HWND)-1, wLastDDEClientMsg, (WPARAM)hChannel, (LPARAM)MAKELONG(aApp, aTopic));
  144.  
  145.     // Get rid of the atoms because we don't need them any more.
  146.     GlobalDeleteAtom(aApp);
  147.     GlobalDeleteAtom(aTopic);
  148.  
  149.     // If no acknowledgement from any apps on the system to our initiate
  150.     // message, no server will talk on the application and topic we requested.
  151.     if (!nAckFlg)
  152.     {
  153.         DestroyWindow(hChannel);
  154.         hChannel = 0;
  155.     }
  156.  
  157.     nAckFlg = 0;
  158.  
  159.     return(hChannel);
  160. }
  161.  
  162. //*******************************************************************
  163. // DDEClientClose - close the dde conversation with a server
  164. //
  165. // paramaters:
  166. //             hChannel      - The handle of the window conducting
  167. //                             the dde conversation.
  168. //
  169. //*******************************************************************
  170. void DDEClientClose(HWND hChannel)
  171. {
  172.     HWND hServerWnd;
  173.  
  174.     // If the channel is still active.
  175.     if (IsWindow(hChannel))
  176.     {
  177.         wLastDDEClientMsg = WM_DDE_TERMINATE;
  178.  
  179.         // Get handle of server we were conversing with.
  180.         hServerWnd = GetWindowServer(hChannel);
  181.  
  182.         // If he is still active.
  183.         if (IsWindow(hServerWnd))
  184.             SendMessage(hServerWnd, wLastDDEClientMsg, (WPARAM)hChannel, (LPARAM)0L);
  185.     }
  186. }
  187.  
  188. //*******************************************************************
  189. // DDEExecute - request an action from server
  190. //
  191. // paramaters:
  192. //             hChannel      - The handle of the window conducting
  193. //                             the dde conversation.
  194. //             lpszCommand   - The command string to send to the
  195. //                             dde server.
  196. //             nWait         - The time to wait for a response to the
  197. //                             command.  If zero, will return immediatly.
  198. //
  199. // returns:
  200. //             1 - successful transmission.
  201. //             0 - error.
  202. //
  203. //*******************************************************************
  204. int DDEExecute(HWND hChannel, LPSTR lpszCommand, int nWait)
  205. {
  206.     int          len;
  207.     HANDLE       hCommand;
  208.     HWND         hServerWnd;
  209.     LPSTR        lpCommand;
  210.     int          nRc;
  211.  
  212.     nRc = 0;
  213.  
  214.     // Get the handle of server we were talking to.
  215.     hServerWnd = GetWindowServer(hChannel);
  216.  
  217.     // If he is no longer active we can't talk to him.
  218.     if (!IsWindow(hServerWnd))
  219.         return(nRc);
  220.  
  221.     // Get shared memory to put our request to server in.
  222.     len = _fstrlen(lpszCommand);
  223.     hCommand = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE,
  224.                            (DWORD) (len + 1));
  225.     if (hCommand)
  226.     {
  227.         // Lock it down to get address of memory.
  228.         lpCommand = GlobalLock(hCommand);
  229.         if (lpCommand)
  230.         {
  231.             // Copy the command into the shared memory.
  232.             _fstrcpy(lpCommand, lpszCommand);
  233.             GlobalUnlock(hCommand);
  234.  
  235.             // Post the message to the server.
  236.             wLastDDEClientMsg = WM_DDE_EXECUTE;
  237.  
  238.             if (!PostMessage(hServerWnd, wLastDDEClientMsg, (WPARAM)hChannel,
  239.                             DDECommandHandle(hCommand)))
  240.             {
  241.                 // If post failed.
  242.                 GlobalFree(hCommand);
  243.             }
  244.             else
  245.             {
  246.                 nRc = 1;
  247.     nAckFlg = 0;
  248.  
  249.                 // Wait if caller told us to.
  250.                 if (nWait)
  251.                     nRc = DDEWait(hChannel, nWait);
  252.             }
  253.         }
  254.     }
  255.  
  256.     nAckFlg = 0;
  257.  
  258.     return(nRc);
  259. }
  260.  
  261. //*******************************************************************
  262. // DDERead - read some data from the server
  263. //
  264. // paramaters:
  265. //             hChannel      - The handle of the window conducting
  266. //                             the dde conversation.
  267. //             szItem        - The item to get from server.
  268. //
  269. // returns:
  270. //             Global Handle - of item requested if successful.
  271. //               or
  272. //             0 - if error.
  273. //
  274. //*******************************************************************
  275. HANDLE DDERead(HWND hChannel, char *szItem, int nWait)
  276. {
  277.     HWND         hServerWnd;
  278.     DDEDATA FAR *lpData;
  279.     int          nReleaseFlg;
  280.     HANDLE       hOurData;
  281.     LPSTR        lpOurData;
  282.     ATOM         aItem;
  283.     int          len;
  284.  
  285.     hOurData = 0;
  286.  
  287.     // Get the handle of server we were talking to.
  288.     hServerWnd = GetWindowServer(hChannel);
  289.  
  290.     // If he is no longer active we can't talk to him.
  291.     if (!IsWindow(hServerWnd))
  292.         return(hOurData);
  293.  
  294.     // Create an atom representing the data item we want read.
  295.     aItem = GlobalAddAtom(szItem);
  296.     hData = 0;
  297.  
  298.     // Post the request to the server.
  299.     wLastDDEClientMsg = WM_DDE_REQUEST;
  300.     PostMessage(hServerWnd, wLastDDEClientMsg, (WPARAM)hChannel,
  301.                 (LPARAM)MAKELONG(CF_TEXT, aItem));
  302.  
  303.     // Wait for a dde message in response or time to expire.
  304.     DDEWait(hChannel, nWait);
  305.  
  306.     // If we have a handle to returned data.
  307.     if (hData)
  308.     {
  309.         // Lock it down to get address.
  310.         lpData = (DDEDATA FAR *) GlobalLock(hData);
  311.         if (lpData)
  312.         {
  313.             // Remember release flag to see if we release or server releases.
  314.             nReleaseFlg = lpData->fRelease;
  315.  
  316.             // Get memory for our local copy of data.
  317.             len = _fstrlen((char far *)lpData->Value);
  318.             hOurData = GlobalAlloc(GMEM_MOVEABLE, (DWORD) (len + 1));
  319.             if (hOurData)
  320.             {
  321.                 // Lock it down to get address.
  322.                 lpOurData = GlobalLock(hOurData);
  323.                 if (lpOurData)
  324.                 {
  325.                     // Copy it in.
  326.                     _fstrcpy(lpOurData, (char far *)lpData->Value);
  327.         GlobalUnlock(hOurData);
  328.                 }
  329.                 else
  330.                     hOurData = 0;
  331.             }
  332.  
  333.             GlobalUnlock(hData);
  334.         }
  335.  
  336.         // If server requested that we free shared memory.
  337.         if (nReleaseFlg)
  338.             GlobalFree(hData);
  339.     }
  340.  
  341.     // Return handle to our copy of data.
  342.     return(hOurData);
  343. }
  344.  
  345. //*******************************************************************
  346. // DDEWait - wait up to time for a dde messag
  347. //
  348. // paramaters:
  349. //             hChannel      - The handle of the window conducting
  350. //                             the dde conversation.
  351. //             nWait         - Length of time to wait for a dde msesage
  352. //                             in seconds.
  353. //
  354. // returns:
  355. //             1 - dde message recieved while waiting.
  356. //               or
  357. //             0 - time expired and no dde messages recieved.
  358. //
  359. //*******************************************************************
  360. int DDEWait(HWND hChannel, int nWait)
  361. {
  362.     time_t  t1;
  363.     time_t  t2;
  364.     int     nGotDDEMsg;
  365.     MSG     msg;
  366.  
  367.     time(&t1);
  368.     nGotDDEMsg = 0;
  369.  
  370.     do
  371.     {
  372.         if (PeekMessage(&msg, hChannel, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
  373.         {
  374.             DispatchMessage(&msg);
  375.             nGotDDEMsg = 1;
  376.         }
  377.     }
  378.     while (!nGotDDEMsg && ((time(&t2) - t1) < nWait));
  379.  
  380.     return(nGotDDEMsg);
  381. }
  382.  
  383. //*******************************************************************
  384. // DDESleep - wait for a time
  385. //
  386. // paramaters:
  387. //             nWait         - Length of time to wait in seconds
  388. //
  389. //*******************************************************************
  390. void DDESleep(int nWait)
  391. {
  392.     time_t  t1;
  393.     time_t  t2;
  394.     MSG     msg;
  395.  
  396.     time(&t1);
  397.  
  398.     do
  399.     {
  400.         PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
  401.     }
  402.     while ((time(&t2) - t1) < nWait);
  403. }
  404.  
  405. //*******************************************************************
  406. // DDEClientWndProc - window proc to manage interface with server
  407. //
  408. // paramaters:
  409. //             hWnd          - The window handle for this message
  410. //             message       - The message number
  411. //             wParam        - The WPARAM parameter for this message
  412. //             lParam        - The LPARAM parameter for this message
  413. //
  414. // returns:
  415. //             depends on message.
  416. //
  417. //*******************************************************************
  418. LRESULT CALLBACK _export DDEClientWndProc(HWND hWnd, UINT message,
  419.                                  WPARAM wParam, LPARAM lParam)
  420. {
  421.     HWND   hServerWnd;
  422.     WORD   wStatus;
  423.     HANDLE hMem;
  424.     ATOM   aItem;
  425.  
  426.     switch (message)
  427.     {
  428.         case WM_CREATE:              // create this window
  429.       // We will remember the handle of the server we are conversing
  430.             // with in the first extra window word, but for now we do not
  431.             // have a server.
  432.             SetWindowServer(hWnd, 0);
  433.             break;
  434.  
  435.         case WM_DDE_ACK:             // an ack from a server
  436.             switch (wLastDDEClientMsg)
  437.             {
  438.                 case WM_DDE_INITIATE:  // ack in response to initiate
  439.                     // Get rid of application and topic atoms used in
  440.                     // initiate request.
  441.                     GlobalDeleteAtom(LOWORD(lParam));
  442.                     GlobalDeleteAtom(HIWORD(lParam));
  443.  
  444.                     // Now we have a server for this conversation, so remember
  445.                     // who it is.
  446.                     SetWindowServer(hWnd, wParam);
  447.                     nAckFlg = 1;
  448.                     break;
  449.  
  450.                 case WM_DDE_EXECUTE:   // ack in response to execute
  451.                     // Server acknowledged our execute command.
  452.             DDEUnpack (WM_DDE_ACK, lParam, (UINT *)&wStatus, (UINT *)&hMem);
  453.                     nAckFlg = wStatus & ACK;
  454.                     if (!nAckFlg)
  455.                         nBusyFlg = wStatus & BUSY;
  456.                     GlobalFree((HGLOBAL)hMem);
  457.                     break;
  458.  
  459.                 case WM_DDE_REQUEST:   // ack in response to request
  460.                     // Get rid of item atom used in request.
  461.                     GlobalDeleteAtom(HIWORD(lParam));
  462.                     wStatus = LOWORD(lParam);
  463.                     nAckFlg = wStatus & ACK;
  464.                     if (!nAckFlg)
  465.                         nBusyFlg = wStatus & BUSY;
  466.                     break;
  467.             }
  468.             break;
  469.  
  470.         case WM_DDE_DATA:            // data from a server per request
  471.  
  472.             // Unpack handle to global data item and atom item
  473.         DDEUnpack (WM_DDE_DATA, lParam, (UINT *)&hData, (UINT *)&aItem);
  474.         
  475.             // Get rid of item atom used in request.
  476.             GlobalDeleteAtom(aItem);
  477.             break;
  478.  
  479.         case WM_DDE_TERMINATE:      // server says terminate conversation
  480.             // Get handle of server we are dealing with.
  481.             hServerWnd = GetWindowServer(hWnd);
  482.  
  483.             // Ignore if this terminate is not from that server.
  484.             if (wParam != (WPARAM)hServerWnd)
  485.                 return(0L);
  486.  
  487.             // Forget who server is.
  488.             SetWindowServer(hWnd, 0);
  489.  
  490.       // Tell our parent conversation with server is closed.
  491.             SendMessage(GetParent(hWnd), WMU_DDE_CLOSED, (WPARAM)hWnd, (LPARAM)0L);
  492.  
  493.             // Send terminate to server to acknowledge we recieved
  494.             // terminate,  if we did not initiate the termination ourselves.
  495.             if ((wLastDDEClientMsg != WM_DDE_TERMINATE) && IsWindow(hServerWnd))
  496.                 PostMessage(hServerWnd, WM_DDE_TERMINATE, (WPARAM)hWnd, (LPARAM)0L);
  497.  
  498.             // Terminate this child window.
  499.             DestroyWindow(hWnd);
  500.             break;
  501.  
  502.         case WM_DESTROY:            // destroy this window
  503.             // Terminate any ongoing conversation on our way out.
  504.             DDEClientClose(hWnd);
  505.             break;
  506.  
  507.         default:
  508.             return(DefWindowProc(hWnd, message, wParam, lParam));
  509.     }
  510.  
  511.     return(0L);
  512. }
  513.  
  514. //*******************************************************************
  515.