home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / memsz331.zip / Source.zip / DDE.CPP < prev    next >
Text File  |  1995-08-03  |  27KB  |  600 lines

  1. /******************************************************************** DDE.CPP
  2.  *                                                                          *
  3.  *                      Dynamic Data Exchange Support                       *
  4.  *                                                                          *
  5.  ****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #define INCL_BASE
  12. #define INCL_PM
  13. #include <os2.h>
  14.  
  15. #include "Debug.h"
  16. #include "MemSize.h"
  17. #include "ReString.h"
  18. #include "Support.h"
  19.  
  20. #include "Dde.h"
  21.  
  22.  
  23. /****************************************************************************
  24.  *                                                                          *
  25.  *                        Definitions & Declarations                        *
  26.  *                                                                          *
  27.  ****************************************************************************/
  28.  
  29.    // Constants
  30.  
  31. #define DDESERVER_CLASS  "Dde_Server"
  32.  
  33.    // Type Definitions
  34.  
  35. typedef struct {
  36.    HWND Client ;
  37.    Dde_Topic *Topic ;
  38. } DDESERVER_PARMS ;
  39.  
  40.  
  41.    // Function Prototypes
  42.  
  43. static FNWP Dde_Processor ;
  44.  
  45. static PDDESTRUCT MakeDDEObject (
  46.    HWND Destination,                    // -> Destination window
  47.    PSZ Item,                            // -> Item name or NULL.
  48.    USHORT Status,                       // Status flags.
  49.    USHORT Format,                       // Data format
  50.    PVOID Data,                          // -> Data or NULL.
  51.    ULONG DataLen                        // Data length in bytes.
  52. ) ;
  53.  
  54.  
  55.  
  56. /****************************************************************************
  57.  *                                                                          *
  58.  *                         Dde_Server: Constructor                          *
  59.  *                                                                          *
  60.  ****************************************************************************/
  61.  
  62. Dde_Server::Dde_Server ( HAB Anchor, HMODULE Library, HWND Owner, char *AppName ) :
  63.    Ready(FALSE), Application(AppName) {
  64.  
  65.    if ( !WinRegisterClass ( Anchor, PSZ(DDESERVER_CLASS),
  66.       Dde_Processor, 0, sizeof(PVOID) ) ) {
  67.  
  68.       ERRORID Error = WinGetLastError ( Anchor ) ;
  69.       ResourceString Title ( Library, IDS_TITLE ) ;
  70.       ResourceString Format ( Library, IDS_ERROR_WINREGISTERCLASS ) ;
  71.       CHAR Message [200] ;
  72.       sprintf ( Message, PCHAR(Format), DDESERVER_CLASS, Error ) ;
  73.       Log ( "%s", Message ) ;
  74.       WinMessageBox ( HWND_DESKTOP, Owner, PSZ(Message),
  75.          PSZ(Title), 0, MB_ENTER | MB_ICONEXCLAMATION ) ;
  76.       return ;
  77.  
  78.    } /* endif */
  79.  
  80.    Ready = TRUE ;
  81. }
  82.  
  83. /****************************************************************************
  84.  *                                                                          *
  85.  *              Dde_Server: Process WM_DDE_INITIATE request.                *
  86.  *                                                                          *
  87.  ****************************************************************************/
  88.  
  89. void Dde_Server::Initiate ( HWND Owner, HWND Client, PDDEINIT pDdeInit ) {
  90.  
  91.   /**************************************************************************
  92.    * Prepare to respond with a WM_DDE_INITIATEACK.                          *
  93.    **************************************************************************/
  94.  
  95.    HMQ Queue = WinQueryWindowULong ( Owner, QWL_HMQ ) ;
  96.    char Text [10] ;
  97.    ULONG Size = 10 ;
  98.    int Country = 1 ;
  99.    if ( PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("iCountry"), Text, &Size ) )
  100.       Country = atoi ( Text ) ;
  101.  
  102.    CONVCONTEXT Conv ;
  103.    Conv.cb = sizeof(Conv) ;
  104.    Conv.fsContext = DDECTXT_CASESENSITIVE ;
  105.    Conv.idCountry = Country ;
  106.    Conv.usCodepage = WinQueryCp ( Queue ) ;
  107.    Conv.usLangID = 0 ;
  108.    Conv.usSubLangID = 0 ;
  109.  
  110.   /**************************************************************************
  111.    * Respond if appropriate.                                                *
  112.    **************************************************************************/
  113.  
  114.    Application.Initiate ( Owner, Client, pDdeInit, Conv ) ;
  115. }
  116.  
  117. /****************************************************************************
  118.  *                                                                          *
  119.  *            Dde_Application: Process WM_DDE_INITIATE request.             *
  120.  *                                                                          *
  121.  ****************************************************************************/
  122.  
  123. void Dde_Application::Initiate ( HWND Owner, HWND Client, PDDEINIT pDdeInit, CONVCONTEXT &Conv ) {
  124.  
  125.    // If not for this application, hold your peace.
  126.    if ( pDdeInit->pszAppName AND *pDdeInit->pszAppName AND strcmpi ( PCHAR(pDdeInit->pszAppName), Name ) )
  127.       return ;
  128.  
  129.    // Pass the initiate request to each of the topics.
  130.    Dde_Topic *Topic = First ;
  131.    while ( Topic ) {
  132.       Topic->Initiate ( Owner, Client, pDdeInit, Conv, Name ) ;
  133.       Topic = Topic->QueryNext() ;
  134.    } /* endwhile */
  135. }
  136.  
  137. /****************************************************************************
  138.  *                                                                          *
  139.  *               Dde_Topic: Process WM_DDE_INITIATE request.                *
  140.  *                                                                          *
  141.  ****************************************************************************/
  142.  
  143. void Dde_Topic::Initiate ( HWND Owner, HWND Client, PDDEINIT pDdeInit, CONVCONTEXT &Conv, char *AppName ) {
  144.  
  145.    // If not for this topic, hold your peace.
  146.    if ( pDdeInit->pszTopic AND *pDdeInit->pszTopic AND strcmpi ( PCHAR(pDdeInit->pszTopic), Name ) )
  147.       return ;
  148.  
  149.    // Find an empty slot in the server list.
  150.    for ( int i=0; i<sizeof(Servers)/sizeof(Servers[0]); i++ ) 
  151.       if ( Servers[i] == 0 ) 
  152.          break ;
  153.    if ( i >= sizeof(Servers)/sizeof(Servers[0]) ) 
  154.       return ;
  155.  
  156.    // Create the server window and add it to the list.
  157.    DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) malloc ( sizeof(DDESERVER_PARMS) ) ;
  158.    Parms->Client = Client ;
  159.    Parms->Topic = this ;
  160.    Servers[i] = WinCreateWindow ( HWND_OBJECT, PSZ(DDESERVER_CLASS),
  161.       0, 0, 0, 0, 0, 0, Owner, HWND_TOP, 0, Parms, 0 ) ;
  162.  
  163.    // Respond to the request.
  164.    WinDdeRespond ( Client, Servers[i], PSZ(AppName), PSZ(Name), &Conv ) ;
  165. }
  166.  
  167. /****************************************************************************
  168.  *                                                                          *
  169.  *               Dde_Topic: Process WM_DDE_REQUEST request.                 *
  170.  *                                                                          *
  171.  ****************************************************************************/
  172.  
  173. void Dde_Topic::Request ( HWND Server, HWND Client, char *ItemName ) {
  174.  
  175.    // Search for the item and ask it to reply.
  176.    Dde_Item *Item = First ;
  177.    while ( Item ) {
  178.       if ( !strcmpi ( ItemName, Item->QueryName() ) ) {
  179.          Item->Request ( Server, Client ) ;
  180.          return ;
  181.       } /* endif */
  182.       Item = Item->QueryNext() ;
  183.    } /* endwhile */
  184.  
  185.    // Reply with an error if the topic was not found.
  186.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  187.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  188. }
  189.  
  190. /****************************************************************************
  191.  *                                                                          *
  192.  *                 Dde_Topic: Process WM_DDE_POKE request.                  *
  193.  *                                                                          *
  194.  ****************************************************************************/
  195.  
  196. void Dde_Topic::Poke ( HWND Server, HWND Client, char *ItemName, int Format, PVOID Data, int Size ) {
  197.  
  198.    // Search for the item and ask it to reply.
  199.    Dde_Item *Item = First ;
  200.    while ( Item ) {
  201.       if ( !strcmpi ( ItemName, Item->QueryName() ) ) {
  202.          Item->Poke ( Server, Client, Format, Data, Size ) ;
  203.          return ;
  204.       } /* endif */
  205.       Item = Item->QueryNext() ;
  206.    } /* endwhile */
  207.  
  208.    // Reply with an error if the topic was not found.
  209.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  210.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  211. }
  212.  
  213. /****************************************************************************
  214.  *                                                                          *
  215.  *                 Dde_Topic: Process WM_DDE_ADVISE request.                *
  216.  *                                                                          *
  217.  ****************************************************************************/
  218.  
  219. void Dde_Topic::Advise ( HWND Server, HWND Client, char *ItemName, BOOL Hot ) {
  220.  
  221.    // Search for the item and ask it to reply.
  222.    Dde_Item *Item = First ;
  223.    while ( Item ) {
  224.       if ( !strcmpi ( ItemName, Item->QueryName() ) ) {
  225.          Item->Advise ( Server, Client, Hot ) ;
  226.          return ;
  227.       } /* endif */
  228.       Item = Item->QueryNext() ;
  229.    } /* endwhile */
  230.  
  231.    // Reply with an error if the topic was not found.
  232.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  233.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  234. }
  235.  
  236. /****************************************************************************
  237.  *                                                                          *
  238.  *                 Dde_Topic: Process WM_DDE_UNADVISE request.              *
  239.  *                                                                          *
  240.  ****************************************************************************/
  241.  
  242. void Dde_Topic::Unadvise ( HWND Server, HWND Client, char *ItemName ) {
  243.  
  244.    // Search for the item and ask it to reply.
  245.    Dde_Item *Item = First ;
  246.    while ( Item ) {
  247.       if ( !strcmpi ( ItemName, Item->QueryName() ) ) {
  248.          Item->Unadvise ( Server, Client ) ;
  249.          return ;
  250.       } /* endif */
  251.       Item = Item->QueryNext() ;
  252.    } /* endwhile */
  253.  
  254.    // Reply with an error if the topic was not found.
  255.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  256.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  257. }
  258.  
  259. /****************************************************************************
  260.  *                                                                          *
  261.  *                Dde_Topic: Process WM_DDE_EXECUTE request.                *
  262.  *                                                                          *
  263.  ****************************************************************************/
  264.  
  265. void Dde_Topic::Execute ( HWND Server, HWND Client, char *ItemName, int Format, PVOID Data, int Size ) {
  266.  
  267.    // Search for the item and ask it to reply.
  268.    Dde_Item *Item = First ;
  269.    while ( Item ) {
  270.       if ( !strcmpi ( ItemName, Item->QueryName() ) ) {
  271.          Item->Execute ( Server, Client, Format, Data, Size ) ;
  272.          return ;
  273.       } /* endif */
  274.       Item = Item->QueryNext() ;
  275.    } /* endwhile */
  276.  
  277.    // Reply with an error if the topic was not found.
  278.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  279.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  280. }
  281.  
  282. /****************************************************************************
  283.  *                                                                          *
  284.  *               Dde_Topic: Process WM_DDE_TERMINATE request.               *
  285.  *                                                                          *
  286.  ****************************************************************************/
  287.  
  288. void Dde_Topic::Terminate ( HWND Server, HWND Client, BOOL DestroyServer ) {
  289.  
  290.    // Echo the termination command to the client.
  291.    WinDdePostMsg ( Client, Server, WM_DDE_TERMINATE, 0, TRUE ) ;
  292.  
  293.    // Remove the server from the list.
  294.    for ( int i=0; i<sizeof(Servers)/sizeof(Servers[0]); i++ ) 
  295.       if ( Servers[i] == Server ) 
  296.          Servers[i] = 0 ;
  297.  
  298.    // Cancel any links.
  299.    Dde_Item *Item = First ;
  300.    while ( Item ) {
  301.       Item->Terminate ( Server, Client ) ;
  302.       Item = Item->QueryNext() ;
  303.    } /* endwhile */
  304.  
  305.    // If server window not already being destroyed, destroy it now.
  306.    if ( DestroyServer )
  307.       WinDestroyWindow ( Server ) ;
  308. }
  309.  
  310. /****************************************************************************
  311.  *                                                                          *
  312.  *               Dde_Item: Process WM_DDE_REQUEST request.                  *
  313.  *                                                                          *
  314.  ****************************************************************************/
  315.  
  316. void Dde_Item::Request ( HWND Server, HWND Client ) {
  317.  
  318.    // Reply with the item data.
  319.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), 0, Format, Data, Size ) ;
  320.    WinDdePostMsg ( Client, Server, WM_DDE_DATA, Response, DDEPM_RETRY ) ;
  321. }
  322.  
  323. /****************************************************************************
  324.  *                                                                          *
  325.  *                 Dde_Item: Process WM_DDE_POKE request.                   *
  326.  *                                                                          *
  327.  ****************************************************************************/
  328.  
  329. void Dde_Item::Poke ( HWND Server, HWND Client, int Format, PVOID Data, int Size ) {
  330.  
  331.    // Reply with an error, as we don't support this function.
  332.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  333.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  334. }
  335.  
  336. /****************************************************************************
  337.  *                                                                          *
  338.  *                 Dde_Item: Process WM_DDE_ADVISE request.                 *
  339.  *                                                                          *
  340.  ****************************************************************************/
  341.  
  342. void Dde_Item::Advise ( HWND Server, HWND Client, BOOL Hot ) {
  343.  
  344.    if ( Hot ) {
  345.       // Search for a matching entry in the hot link list.  Return if found.
  346.       for ( int i=0; i<sizeof(HotLinks)/sizeof(HotLinks[0]); i++ ) {
  347.          if ( ( HotLinks[i][0] == Server ) AND ( HotLinks[i][1] == Client ) ) {
  348.             Log ( "WARNING: Link already established." ) ;
  349.             PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_FACK, DDEFMT_TEXT, 0, 0 ) ;
  350.             WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  351.             return ;
  352.          } /* endif */
  353.       } /* endfor */
  354.       // Search for an empty entry in the hot link list.  Use if not found.
  355.       for ( i=0; i<sizeof(HotLinks)/sizeof(HotLinks[0]); i++ ) {
  356.          if ( ( HotLinks[i][0] == 0 ) AND ( HotLinks[i][1] == 0 ) ) {
  357.             HotLinks[i][0] = Server ;
  358.             HotLinks[i][1] = Client ;
  359.             PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_FACK, DDEFMT_TEXT, 0, 0 ) ;
  360.             WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  361.             return ;
  362.          } /* endif */
  363.       } /* endfor */
  364.  
  365.       Log ( "  WARNING: Hot link table full." ) ;
  366.  
  367.    } else {
  368.       // Search for a matching entry in the warm link list.  Return if found.
  369.       for ( int i=0; i<sizeof(WarmLinks)/sizeof(WarmLinks[0]); i++ ) {
  370.          if ( ( WarmLinks[i][0] == Server ) AND ( WarmLinks[i][1] == Client ) ) {
  371.             Log ( "WARNING: Link already established." ) ;
  372.             PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_FACK, DDEFMT_TEXT, 0, 0 ) ;
  373.             WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  374.             return ;
  375.          } /* endif */
  376.       } /* endfor */
  377.       // Search for an empty entry in the warm link list.  Use if not found.
  378.       for ( i=0; i<sizeof(WarmLinks)/sizeof(WarmLinks[0]); i++ ) {
  379.          if ( ( WarmLinks[i][0] == 0 ) AND ( WarmLinks[i][1] == 0 ) ) {
  380.             WarmLinks[i][0] = Server ;
  381.             WarmLinks[i][1] = Client ;
  382.             PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_FACK, DDEFMT_TEXT, 0, 0 ) ;
  383.             WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  384.             return ;
  385.          } /* endif */
  386.       } /* endfor */
  387.  
  388.       Log ( "  WARNING: Warm link table full." ) ;
  389.  
  390.    } /* endif */
  391.  
  392.    // Reply with an error.
  393.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  394.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  395. }
  396.  
  397. /****************************************************************************
  398.  *                                                                          *
  399.  *                 Dde_Item: Process WM_DDE_UNADVISE request.               *
  400.  *                                                                          *
  401.  ****************************************************************************/
  402.  
  403. void Dde_Item::Unadvise ( HWND Server, HWND Client ) {
  404.  
  405.    // Cancel any links on this item for this Server/Client pair.
  406.    Terminate ( Server, Client ) ;
  407.  
  408.    // Reply with an ACK.
  409.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_FACK, DDEFMT_TEXT, 0, 0 ) ;
  410.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  411. }
  412.  
  413. /****************************************************************************
  414.  *                                                                          *
  415.  *                Dde_Item: Process WM_DDE_EXECUTE request.                 *
  416.  *                                                                          *
  417.  ****************************************************************************/
  418.  
  419. void Dde_Item::Execute ( HWND Server, HWND Client, int Format, PVOID Data, int Size ) {
  420.  
  421.    // Reply with an error, as we don't support this function.
  422.    PDDESTRUCT Response = MakeDDEObject ( Client, PSZ(Name), DDE_NOTPROCESSED, DDEFMT_TEXT, 0, 0 ) ;
  423.    WinDdePostMsg ( Client, Server, WM_DDE_ACK, Response, DDEPM_RETRY ) ;
  424. }
  425.  
  426. /****************************************************************************
  427.  *                                                                          *
  428.  *               Dde_Item: Process WM_DDE_TERMINATE request.                *
  429.  *                                                                          *
  430.  ****************************************************************************/
  431.  
  432. void Dde_Item::Terminate ( HWND Server, HWND Client ) {
  433.  
  434.    // Search for and remove all hot links for this client/server pair.
  435.    for ( int i=0; i<sizeof(HotLinks)/sizeof(HotLinks[0]); i++ ) 
  436.       if ( ( HotLinks[i][0] == Server ) AND ( HotLinks[i][1] == Client ) ) 
  437.          HotLinks[i][0] = HotLinks[i][1] = 0 ;
  438.  
  439.    // Search for and remove all warm links for this client/server pair.
  440.    for ( i=0; i<sizeof(WarmLinks)/sizeof(WarmLinks[0]); i++ ) 
  441.       if ( ( WarmLinks[i][0] == Server ) AND ( WarmLinks[i][1] == Client ) ) 
  442.          WarmLinks[i][0] = WarmLinks[i][1] = 0 ;
  443. }
  444.  
  445. /****************************************************************************
  446.  *                                                                          *
  447.  *                       Dde_Item: Broadcast Update                         *
  448.  *                                                                          *
  449.  ****************************************************************************/
  450.  
  451. void Dde_Item::BroadcastUpdate ( ) {
  452.  
  453.    // Send data complete to all hot links.
  454.    for ( int i=0; i<sizeof(HotLinks)/sizeof(HotLinks[0]); i++ ) {
  455.       if ( HotLinks[i][0] ) {
  456.          PDDESTRUCT Message = MakeDDEObject ( HotLinks[i][1], PSZ(Name), 0, Format, Data, Size ) ;
  457.          WinDdePostMsg ( HotLinks[i][1], HotLinks[i][0], WM_DDE_DATA, Message, DDEPM_RETRY ) ;
  458.       } /* endif */
  459.    } /* endfor */
  460.  
  461.    // Send advisory to all warm links.
  462.    for ( i=0; i<sizeof(WarmLinks)/sizeof(WarmLinks[0]); i++ ) {
  463.       if ( WarmLinks[i][0] ) {
  464.          PDDESTRUCT Message = MakeDDEObject ( WarmLinks[i][1], PSZ(Name), DDE_FNODATA, Format, 0, 0 ) ;
  465.          WinDdePostMsg ( WarmLinks[i][1], WarmLinks[i][0], WM_DDE_DATA, Message, DDEPM_RETRY ) ;
  466.       } /* endif */
  467.    } /* endfor */
  468. }
  469.  
  470. /****************************************************************************
  471.  *                                                                          *
  472.  *                    Dde Server Object Window Class                        *
  473.  *                                                                          *
  474.  ****************************************************************************/
  475.  
  476. extern MRESULT APIENTRY Dde_Processor ( HWND Server, ULONG Msg, MPARAM mp1, MPARAM mp2 ) {
  477.  
  478.    switch ( Msg ) {
  479.  
  480.       case WM_CREATE: {
  481.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) mp1 ;
  482.          WinSetWindowPtr ( Server, QWL_USER, Parms ) ;
  483.          return ( 0 ) ; }
  484.  
  485.       case WM_DESTROY: {
  486.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  487.          Parms->Topic->Terminate ( Server, Parms->Client, FALSE ) ;
  488.          return ( 0 ) ; }
  489.  
  490.       case WM_DDE_REQUEST: {
  491.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  492.          HWND Client = HWNDFROMMP ( mp1 ) ;
  493.          PDDESTRUCT Request = PDDESTRUCT ( mp2 ) ;
  494.          PCHAR Item = PCHAR ( DDES_PSZITEMNAME ( Request ) ) ;
  495.          Parms->Topic->Request ( Server, Client, Item ) ;
  496.          DosFreeMem ( Request ) ;
  497.          return ( 0 ) ; }
  498.  
  499.       case WM_DDE_POKE: {
  500.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  501.          HWND Client = HWNDFROMMP ( mp1 ) ;
  502.          PDDESTRUCT Request = PDDESTRUCT ( mp2 ) ;
  503.          PCHAR Item = PCHAR ( DDES_PSZITEMNAME ( Request ) ) ;
  504.          int Format = int ( Request->usFormat ) ;
  505.          PVOID Data = PVOID ( DDES_PABDATA ( Request ) ) ;
  506.          int Size = int ( Request->cbData ) ;
  507.          Parms->Topic->Poke ( Server, Client, Item, Format, Data, Size ) ;
  508.          DosFreeMem ( Request ) ;
  509.          return ( 0 ) ; }
  510.  
  511.       case WM_DDE_ADVISE: {
  512.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  513.          HWND Client = HWNDFROMMP ( mp1 ) ;
  514.          PDDESTRUCT Request = PDDESTRUCT ( mp2 ) ;
  515.          PCHAR Item = PCHAR ( DDES_PSZITEMNAME ( Request ) ) ;
  516.          Parms->Topic->Advise ( Server, Client, Item, ! ( Request->fsStatus & DDE_FNODATA ) ) ;
  517.          DosFreeMem ( Request ) ;
  518.          return ( 0 ) ; }
  519.  
  520.       case WM_DDE_UNADVISE: {
  521.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  522.          HWND Client = HWNDFROMMP ( mp1 ) ;
  523.          PDDESTRUCT Request = PDDESTRUCT ( mp2 ) ;
  524.          PCHAR Item = PCHAR ( DDES_PSZITEMNAME ( Request ) ) ;
  525.          Parms->Topic->Unadvise ( Server, Client, Item ) ;
  526.          DosFreeMem ( Request ) ;
  527.          return ( 0 ) ; }
  528.  
  529.       case WM_DDE_EXECUTE: {
  530.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  531.          HWND Client = HWNDFROMMP ( mp1 ) ;
  532.          PDDESTRUCT Request = PDDESTRUCT ( mp2 ) ;
  533.          PCHAR Item = PCHAR ( DDES_PSZITEMNAME ( Request ) ) ;
  534.          int Format = int ( Request->usFormat ) ;
  535.          PVOID Data = PVOID ( DDES_PABDATA ( Request ) ) ;
  536.          int Size = int ( Request->cbData ) ;
  537.          Parms->Topic->Execute ( Server, Client, Item, Format, Data, Size ) ;
  538.          DosFreeMem ( Request ) ;
  539.          return ( 0 ) ; }
  540.  
  541.       case WM_DDE_TERMINATE: {
  542.          DDESERVER_PARMS *Parms = (DDESERVER_PARMS*) WinQueryWindowPtr ( Server, QWL_USER ) ;
  543.          Parms->Topic->Terminate ( Server, Parms->Client, TRUE ) ;
  544.          return ( 0 ) ; }
  545.  
  546.    } /* endswitch */
  547.  
  548.    return ( WinDefWindowProc ( Server, Msg, mp1, mp2 ) ) ;
  549. }
  550.  
  551. /****************************************************************************
  552.  *                                                                          *
  553.  *                        Allocate DDE Structure                            *
  554.  *                                                                          *
  555.  *  This function is straight from the "OS/2 2.0 Presentation Manager       *
  556.  *    Programming Guide", Copyright 1992, IBM.  Adapted to C++ from C.      *
  557.  *                                                                          *
  558.  ****************************************************************************/
  559.  
  560. static PDDESTRUCT MakeDDEObject (
  561.    HWND Destination,                    // -> Destination window
  562.    PSZ Item,                            // -> Item name or NULL.
  563.    USHORT Status,                       // Status flags.
  564.    USHORT Format,                       // Data format
  565.    PVOID Data,                          // -> Data or NULL.
  566.    ULONG DataLen                        // Data length in bytes.
  567. ) {
  568.  
  569.    ULONG ItemLen = Item ? strlen(PCHAR(Item))+1 : 1 ;
  570.  
  571.    PDDESTRUCT pBlock ;
  572.    if ( DosAllocSharedMem ( PPVOID(&pBlock), 0, sizeof(DDESTRUCT) + ItemLen + DataLen,
  573.       PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE ) )
  574.       return ( 0 ) ;
  575.  
  576.    pBlock->cbData = DataLen ;
  577.    pBlock->fsStatus = Status ;
  578.    pBlock->usFormat = Format ;
  579.    pBlock->offszItemName = sizeof(DDESTRUCT) ;
  580.  
  581.    if ( DataLen AND Data )
  582.       pBlock->offabData = USHORT ( sizeof(DDESTRUCT) + ItemLen ) ;
  583.    else
  584.       pBlock->offabData = 0 ;
  585.  
  586.    if ( Item )
  587.       strcpy ( PCHAR(DDES_PSZITEMNAME(pBlock)), PCHAR(Item) ) ;
  588.    else
  589.       strcpy ( PCHAR(DDES_PSZITEMNAME(pBlock)), "" ) ;
  590.  
  591.    if ( Data )
  592.       memcpy ( DDES_PABDATA(pBlock), Data, size_t(DataLen) ) ;
  593.  
  594.    PID pid ; TID tid ;
  595.    WinQueryWindowProcess ( Destination, &pid, &tid ) ;
  596.    DosGiveSharedMem( (PVOID)pBlock, pid, PAG_READ | PAG_WRITE) ;
  597.  
  598.    return ( pBlock ) ;
  599. }
  600.