home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / DDE21.ZIP / SERVER / SERVER.C < prev    next >
Text File  |  1993-04-09  |  21KB  |  507 lines

  1. /*
  2.   $Workfile:   server.c  $
  3.   $Revision:   1.1.1.0  $
  4.   $Date:   09 May 1991 18:11:26  $
  5.   $Logfile:   W:/dde/server.c_v  $
  6.   $Author:   mikem  $
  7.   $Modtime:   09 May 1991 18:07:04  $
  8.    Quote of the day server - Personal Systems Developer
  9.    Sample Server DDE application
  10.    Copyright (C) Personal Systems Developer, IBM Corporation 1991
  11.    Author: Michael R. MacFaden
  12.    Internet: macfaden@paloic1.vnet.ibm.com
  13.  
  14. */
  15.  
  16. #pragma  comment(compiler)
  17. #pragma  comment(user, "Copyright (C) IBM Corp 1991")
  18.  
  19. #define  INCL_WIN
  20. #define  INCL_ERRORS
  21. #define  INCL_DOS
  22. #include <os2.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "pmutils.h"
  27. #include "server.h"
  28. MRESULT EXPENTRY ClientWndProc(HWND,USHORT,MPARAM,MPARAM);
  29.  
  30. VOID EXPENTRY PaintWindow(HWND hwnd,CHAR *szMsg);
  31. PDDESTRUCT EXPENTRY MakeDDEDataSeg(USHORT usFormat,PSZ pszItemName,PVOID
  32.                                    pvData,USHORT cbData,USHORT fsStatus);
  33.  
  34. /* globals */
  35.  
  36. #define  MAX_MSG_SZ    300             // max size of text string
  37. #define  ID_MAINWND    256             // Frame window ID
  38. CHAR szClientClass[] = "DDE-Sample";
  39. HAB hab;
  40. HWND hwndFrame,hwndClient,hwndMenu,hwndDDEserver;
  41. USHORT cbQuote;                        // length of message
  42. USHORT ndx = 0;                        // index to quote struct
  43. CHAR szBuf[256];                       // temporary buffer
  44. PSZ szQuote[] =
  45.       {
  46.       "Play it again, Sam", "Peace in our time", "Step on it, Mac",
  47.       "Error free code", "All men are created equal", "It's Miller Time",
  48.       "Read my lips", "Come up and see me some time", "You only live twice",
  49.       "Land Ho!", "You can't get there from here",
  50.       "Please fasten you seat belts", "I like Ike", "He's dead Jim",
  51.       "...Talking 'bout my generation",
  52.       } ;
  53.  
  54. #define  CB_QUOTES     (sizeof szQuote / sizeof szQuote[0])
  55. #define  ID_TIMER      1
  56.  
  57. int main()
  58. {
  59.   static ULONG flFrameFlags = FCF_TITLEBAR|FCF_SYSMENU|FCF_SIZEBORDER|
  60.      FCF_MINMAX|FCF_TASKLIST;
  61.   HMQ hmq;
  62.   QMSG qmsg;
  63.  
  64.   hab = WinInitialize(0);
  65.   hmq = WinCreateMsgQueue(hab, 0);
  66.   WinRegisterClass(hab, szClientClass, ClientWndProc, 0L, 0);
  67.   hwndFrame = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &flFrameFlags,
  68.      szClientClass, NULL, 0L, (HMODULE)0, ID_MAINWND, &hwndClient);
  69.  
  70.   WinSendMsg(hwndFrame, WM_SETICON, WinQuerySysPointer(HWND_DESKTOP,
  71.      SPTR_APPICON, FALSE), NULL);
  72.  
  73.   while (WinGetMsg(hab, &qmsg,0, 0, 0))
  74.     WinDispatchMsg(hab, &qmsg);
  75.  
  76.   WinDestroyWindow(hwndFrame);
  77.   WinDestroyMsgQueue(hmq);
  78.   WinTerminate(hab);
  79.   return 0;
  80. }
  81.  
  82.  
  83. MRESULT EXPENTRY ClientWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  84. {
  85.   static USHORT usItem = 0;            // Menu item
  86.   static DDESRV ddesrv;                // Keep info on conversations
  87.   static BOOL fTimerOn = FALSE;        // Got a system timer
  88.   PDDEINIT pddei = NULL;               // DDE init struct ptr
  89.   PDDESTRUCT pddeIn = NULL,pddeOut = NULL; // DDE Transaction struct ptr
  90.   register int i;                      // work counter variable
  91.   static CONVCONTEXT Context;
  92.  
  93.   switch (msg)
  94.     {
  95.     case  WM_CREATE :
  96.       hwndFrame = WinQueryWindow(hwnd, QW_PARENT);
  97.       hwndMenu = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT),
  98.          FID_MENU);
  99.  
  100.       WinSetWindowText(hwndFrame, "...DDE Server Not Connected...");
  101.       /* place the window on the users screen */
  102.       WinSetWindowPos(hwndFrame,HWND_TOP,
  103.           350,  50,  /*  window position (x,y)*/
  104.           250, 250,  /*  window size (width/height) */
  105.           SWP_SIZE | SWP_MOVE | SWP_SHOW);
  106.  
  107.       /**********************************************************************/
  108.       /* DDE initialization                                                 */
  109.       /**********************************************************************/
  110.  
  111.       if (!WinStartTimer(hab, hwnd, ID_TIMER, 5000))
  112.         WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
  113.            "Try closing a few applications and restart", "Out of Timers!",
  114.            12, MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL|MB_MOVEABLE);
  115.       else
  116.         fTimerOn = TRUE;
  117.  
  118.       ddesrv.fAdvise = FALSE;          // hot link
  119.       ddesrv.fAck = FALSE;             // acknoledgement
  120.       ddesrv.fConnected = FALSE;       // conversation established
  121.                // let the all the know we exist and are ready...
  122.       WinDdeInitiate(hwnd, CV_DDEAPPNAME, CV_DDESYSTEMTOPIC,&Context);
  123.       return 0;
  124.  
  125.     case  WM_PAINT :
  126.       PaintWindow(hwnd, szQuote[ndx]);
  127.       return 0;
  128.  
  129.     case  WM_TIMER :   // change current quote every 5 seconds
  130.       if (++ndx == CB_QUOTES)       // increment to next quote or loop back
  131.         ndx = 0;
  132.       WinInvalidateRect(hwnd, NULL, FALSE);
  133.       if (ddesrv.fConnected)          // does a conversation exist?
  134.       if (strcmp(ddesrv.szTopic, "Quotes") == 0)        // ...on this topic?
  135.           if (ddesrv.fAdvise)       // if we have a      // ..and is hot linked?
  136.             {
  137.             if (ddesrv.fRefData) // No data required?
  138.               cbQuote = 0;
  139.             else
  140.               cbQuote =(USHORT) strlen(szQuote[ndx]) + (USHORT)1;
  141.             pddeOut = MakeDDEDataSeg(CF_TEXT, "Quote", (PVOID)
  142.               szQuote[ndx], (USHORT)cbQuote, 0);
  143.            WinDdePostMsg(ddesrv.hwndDDEClient, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  144.            }
  145.       return 0;
  146.  
  147.     case  WM_ERASEBACKGROUND :
  148.       return (MRESULT)1;
  149.  
  150.     case  WM_DDE_INITIATE : // A DDE client is broadcasting to find a server
  151.          // is this our own broadcast? then don't process it
  152.       if ((HWND)mp1 == hwnd)
  153.         break;
  154.          // create ptr to client's specified appplication and topic
  155.  
  156.       pddei = (PDDEINIT)mp2;
  157.  
  158.       if (!ddesrv.fConnected)          // Can we handle another client?
  159.         {
  160.         /* check to see if an the "application" is explicit or general */
  161.         if (strcmp(CV_DDEAPPNAME, pddei->pszAppName) == 0 ||
  162.            (pddei->pszAppName == NULL))
  163.           {
  164.            /* OK, now Check to see if what topic the conversion will use...
  165.               first check to see if it uses our default topic          */
  166.            sprintf(szBuf, "Request in for for appl: %s Topic: %s",
  167.              pddei->pszAppName, pddei->pszTopic);
  168.  
  169.            strlen(pddei->pszTopic);
  170.            WinAlarm(HWND_DESKTOP, WA_NOTE);
  171.            WinSetWindowText(hwndFrame, szBuf);
  172.  
  173.            if (strcmp("Quotes", pddei->pszTopic) == 0)
  174.              {                          /* Server and topic names matched    */
  175.              ddesrv.hwndDDEClient = (HWND)mp1; // store client window handle
  176.              WinDdeRespond((HWND)mp1, hwnd, CV_DDEAPPNAME, "Quotes",&Context);
  177.              strcpy(ddesrv.szTopic, "Quotes"); // record what topic is used
  178.              ddesrv.fConnected = TRUE;  // conversation established
  179.              WinSetWindowText(hwndFrame, "...Connected on \"Quotes\" Topic...");
  180.              }
  181.            else
  182.             // next, check to see if it wants to converse using the system topic
  183.             if (strcmp("System", pddei->pszTopic) == 0)
  184.               {                        /* Server and topic names matched    */
  185.               ddesrv.hwndDDEClient = (HWND)mp1; // store client window handle
  186.               WinDdeRespond((HWND) mp1, hwnd, CV_DDEAPPNAME, "System",&Context);
  187.               strcpy(ddesrv.szTopic, "System"); // record topic
  188.               ddesrv.fConnected = TRUE; // conversation established
  189.               WinSetWindowText(hwndFrame, "...Connected on System Topic...");
  190.               }
  191.         /* if both the appl and system topic are null respond with all topics?
  192.            this is different than using a conversation on the system topic
  193.            and responding to the item called Topics and Formats */
  194.           }
  195.         }
  196.       break;
  197.  
  198.     case  WM_DDE_REQUEST :             /* one time DDE data request         */
  199.       pddeIn = (PDDESTRUCT)mp2;
  200.       if (pddeIn == NULL)
  201.         break;        // no DDESTRUCT passed, ignore and don't bomb out
  202.          // Do we have an established conversation with this client?
  203.  
  204.       if (ddesrv.hwndDDEClient != (HWND)mp1)
  205.         {
  206.         break;
  207.         }
  208.  
  209.       if (strcmp(SZDDESYS_TOPIC, ddesrv.szTopic) == 0) // process system topic items
  210.         {
  211.             szDDEsysReply[0] = '\0';
  212.         // Check to see what item the client requires
  213.         if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDESYSITEMS) == 0)
  214.           {
  215.                // Return list of system items supported
  216.                // create a string with each item delimeted by tab char
  217.           for (i = 0; i < CB_SYSITEMS; ++i)
  218.             sprintf(szDDEsysReply,"%s\t%s", szDDEsysReply, szSysItems+i);
  219.           pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDESYSITEMS, (PVOID)
  220.              szDDEsysReply, (USHORT)strlen(szDDEsysReply)+(USHORT)1, 0);
  221.           WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  222.           break;
  223.           }
  224.         else
  225.           if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDESYSTOPICS) == 0)
  226.             {
  227.                // return list of current topics supported
  228.             for (i = 0; i < CB_DDETOPICS; ++i)
  229.               sprintf(szDDEsysReply, "%s\t%s", szDDEsysReply, szDDEtopics+i);
  230.             pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDESYSTOPICS, (PVOID)
  231.                szDDEsysReply, (USHORT)strlen(szDDEsysReply)+(USHORT)1, 0);
  232.             WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  233.             break;
  234.             }
  235.           else
  236.             if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDESYSRETURNMSG) == 0)
  237.               {
  238.                // additional detail for most recently issued WM_DDE_ACK
  239.                // build an error msg and return a string & number or whatever
  240.                     // this example just passes back an empty dde segment
  241.               pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDESYSRETURNMSG,
  242.                  (PVOID)NULL, (USHORT)0, 0);
  243.               WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  244.               break;
  245.               }
  246.             else
  247.               if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDESYSSTATUS) == 0)
  248.                 {
  249.                // Return string dumping contents of the DDESRV struct
  250.                // both DDESRV and the format of this item are application defined
  251.                 if (ddesrv.fConnected)
  252.                   {
  253.                   sprintf(szDDEsysReply, "%s", "Connected");
  254.                   sprintf(szDDEsysReply, "%s\tTopic is %s", szDDEsysReply,
  255.                             ddesrv.szTopic);
  256.                   }
  257.                 else
  258.                   sprintf(szDDEsysReply,"%s\tNot Connected", szDDEsysReply);
  259.                 if (ddesrv.fAdvise)
  260.                   sprintf(szDDEsysReply,"%s\tHot Link established", szDDEsysReply);
  261.                 else
  262.                   sprintf(szDDEsysReply,"%s\tNo hot link", szDDEsysReply);
  263.                 if (ddesrv.fAck)
  264.                   sprintf(szDDEsysReply, "%s\tAcknowledgement Required", szDDEsysReply);
  265.                 else
  266.                   sprintf(szDDEsysReply,"%s\tAcknowlegment Not Required", szDDEsysReply);
  267.                 if (ddesrv.fRefData)
  268.                   sprintf(szDDEsysReply,"%s\tReference to data only", szDDEsysReply);
  269.                 else
  270.                   sprintf(szDDEsysReply,"%s\tPass copy data", szDDEsysReply);
  271.                 sprintf(szDDEsysReply,"%s\tRender data as %d", szDDEsysReply,
  272.                              ddesrv.usFormat);
  273.  
  274.                 pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDESYSTOPICS,
  275.                    (PVOID)szDDEsysReply, (USHORT)strlen(szDDEsysReply)+(USHORT)1, 0);
  276.                 WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  277.                 break;
  278.                 }
  279.               else
  280.                 if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDEFORMATS) == 0)
  281.                   {
  282.  
  283.                   /**********************************************************/
  284.                   /* put each format number in the list, user formats should*/
  285.                   /* be registered first with the atom table per Microsoft  */
  286.                   /* Systems Journal Volume 4 Number 3 (May 89) pg 4-8      */
  287.                   /**********************************************************/
  288.  
  289.                   itoa((int)CF_TEXT, szBuf, 10);
  290.                   sprintf(szDDEsysReply, "%s", szDDEsysReply, szBuf);
  291.                   pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDEFORMATS,
  292.                      (PVOID)szDDEsysReply, (USHORT)strlen(szDDEsysReply)+(USHORT)1,
  293.                      0);
  294.                   WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  295.                   break;
  296.                   }
  297.         } // finished with "System" topics
  298.  
  299.       if (strcmp("Quotes", ddesrv.szTopic) == 0) // process application topic
  300.         {
  301.         if (strcmp(DDES_PSZITEMNAME(pddeIn), CV_DDEUSRITEM) == 0)
  302.           {
  303.             // data or message only?
  304.           if (pddeIn->fsStatus & DDE_FNODATA) // No data required?
  305.             cbQuote = 0;
  306.           else
  307.             {
  308.             cbQuote = (USHORT) strlen(szQuote[ndx])+ (USHORT)1;
  309.             }
  310.           pddeOut = MakeDDEDataSeg(CF_TEXT, CV_DDEUSRITEM, (PVOID)
  311.              szQuote[ndx], (USHORT)cbQuote, 0);
  312.           WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_DATA, pddeOut, TRUE);
  313.           break;
  314.           }
  315.         else
  316.           {
  317.  
  318.           /******************************************************************/
  319.           /* Data item requested isn't supported just change status bit and */
  320.           /* pass back same segment                                         */
  321.           /******************************************************************/
  322.  
  323.           pddeIn->fsStatus &= (~DDE_FACK);
  324.           WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_ACK, pddeIn, TRUE);
  325.           }
  326.         }
  327.       break;                           /* dde_request                       */
  328.     case  WM_DDE_ADVISE :              /* DDE "hot" link request            */
  329.       if (ddesrv.hwndDDEClient != (HWND)mp1)
  330.               break;
  331.       pddeIn = (PDDESTRUCT)mp2;
  332.  
  333.       if (ddesrv.fAdvise)              /* if Advise already active - signal
  334.                                           "busy"                            */
  335.         {
  336.         pddeIn->fsStatus &= (~DDE_FACK);
  337.         pddeIn->fsStatus |= DDE_FBUSY;
  338.         WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_ACK, pddeIn, TRUE);
  339.         }
  340.       else
  341.         {
  342.         if (pddeIn->usFormat == CF_TEXT)
  343.           {
  344.           ddesrv.fAdvise = TRUE;
  345.           ddesrv.fConnected = TRUE;
  346.  
  347.           if (pddeIn->fsStatus&DDE_FNODATA) // client requires data or just inform
  348.             {
  349.             ddesrv.fRefData = TRUE;
  350.             WinSetWindowText(hwndFrame, "...Advise - Reference data...");
  351.             }
  352.           else
  353.             {
  354.             ddesrv.fRefData = FALSE;
  355.             WinSetWindowText(hwndFrame, "...Advise - pass copy of data...");
  356.             }
  357.  
  358.           if (pddeIn->fsStatus&DDE_FACKREQ) // Does Client want an ACK?
  359.             {
  360.             ddesrv.fAck = TRUE;        /* Acknowledgement was requested     */
  361.             pddeIn->fsStatus |= DDE_FACK;
  362.             WinDdePostMsg(ddesrv.hwndDDEClient, hwnd, WM_DDE_ACK, pddeIn,
  363.                TRUE);
  364.             }
  365.           else
  366.             {
  367.             ddesrv.fAck = FALSE;       /* No acknowledgement was requested  */
  368.             }
  369.           }                            // if
  370.         else
  371.           {
  372.  
  373.           /******************************************************************/
  374.           /* Data format requested is not supported - send NAK              */
  375.           /******************************************************************/
  376.  
  377.           pddeIn->fsStatus &= (~DDE_FACK);
  378.           WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_ACK, pddeIn, TRUE);
  379.           }
  380.         }
  381.       break;                           /* dde_advise                        */
  382.     case  WM_DDE_UNADVISE :            /* Terminate DDE hot link request    */
  383.       if (ddesrv.hwndDDEClient != (HWND)mp1)
  384.               break;
  385.       pddeIn = (PDDESTRUCT)mp2;
  386.       if ((mp1 == ddesrv.hwndDDEClient) && (pddeIn->usFormat == CF_TEXT))
  387.         {
  388.         ddesrv.fConnected = FALSE;
  389.         ddesrv.fAdvise = FALSE;
  390.         pddeIn->fsStatus |= DDE_FACK;
  391.         WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_ACK, pddeIn, TRUE);
  392.         WinSetWindowText(hwndFrame, "...Connected ...");
  393.         }
  394.       else
  395.         {
  396.         pddeIn->fsStatus &= (~DDE_FACK);
  397.         WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_ACK, pddeIn, TRUE);
  398.         }
  399.       break;
  400.  
  401.     case  WM_DDE_ACK :                 /* DDE Acknowledgement               */
  402.       if (ddesrv.hwndDDEClient != (HWND)mp1)
  403.               break;
  404.       pddeIn = (PDDESTRUCT)mp2;
  405.       if ((mp1 == ddesrv.hwndDDEClient) && (pddeIn->fsStatus & DDE_FACK))
  406.         {
  407.         ddesrv.fAck = TRUE;
  408.         }
  409.       break;
  410.  
  411.     case  WM_DDE_TERMINATE :           /* DDE conversation termination
  412.                                           request                           */
  413.       if (ddesrv.hwndDDEClient != (HWND)mp1)
  414.               break;
  415.       ddesrv.hwndDDEClient = NULL;     // store client window handle
  416.       ddesrv.fAdvise = FALSE;             // terminate hot link
  417.       WinDdePostMsg((HWND)mp1, hwnd, WM_DDE_TERMINATE, NULL, TRUE);
  418.       ddesrv.fConnected = FALSE;
  419.       WinSetWindowText(hwndFrame, "...DDE Server Not Connected...");
  420.       break;
  421.  
  422.     case  WM_CLOSE : // bring down application gracefully, release resources
  423.       if (ddesrv.fConnected)
  424.         WinDdePostMsg(ddesrv.hwndDDEClient, hwnd, WM_DDE_TERMINATE, NULL,
  425.            TRUE);
  426.       if (fTimerOn)                    // release sytem timer
  427.         WinStopTimer(hab, hwnd, ID_TIMER);
  428.       WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  429.       return 0;
  430.  
  431.     }
  432.   return  WinDefWindowProc(hwnd, msg, mp1, mp2);
  433. }
  434.  
  435. // Post - writes szMsg in hwnd centered vertically and horizontally
  436.  
  437. VOID EXPENTRY PaintWindow(HWND hwnd,CHAR *szMsg)
  438. {
  439.   HPS hps = NULL;
  440.   RECTL rcl;
  441.  
  442.   hps = WinBeginPaint(hwnd, NULL, NULL);
  443.   if (!hps)
  444.     return ;
  445.   WinQueryWindowRect(hwnd, &rcl);
  446.   WinDrawText(hps, -1, szMsg, &rcl, CLR_NEUTRAL, CLR_BACKGROUND, DT_CENTER|
  447.      DT_VCENTER|DT_ERASERECT);
  448.  
  449.   WinEndPaint(hps);
  450. }  // PaintWindow()
  451.  
  452.  
  453. // pre - format, item name, and fsStatus are valid
  454. // post - a valid data segment for WM_DDE_DATA message is built
  455. //       and a pddestruct is returned else (error) null is returned
  456.  
  457. PDDESTRUCT EXPENTRY MakeDDEDataSeg(USHORT usFormat,PSZ pszItemName,PVOID
  458.                                    pvData,USHORT cbData,USHORT fsStatus)
  459. {
  460.   PDDESTRUCT pdde = NULL;              // ptr to dde data structure
  461.   ULONG rc = 0;                        // api return code holder
  462.   PULONG pulSharedObj = NULL;          // pointer to shared object
  463.   PCHAR psz = NULL;                    // string ptr for text format
  464.   USHORT cbObjSize = 0;                // count of bytes to request
  465.  
  466.  
  467.   /**************************************************************************/
  468.   /* 1) Allocate a givable memory block                                     */
  469.   /**************************************************************************/
  470.  
  471.   cbObjSize = (USHORT)strlen(pszItemName)+ (USHORT) 1;
  472.   rc = DosAllocSharedMem(&pulSharedObj, NULL, cbObjSize,
  473.              PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE);
  474.   if (rc && pulSharedObj)          // check api return code and ptr
  475.     return  NULL;
  476.  
  477.   /**************************************************************************/
  478.   /* Fill in the new DDE structure                                          */
  479.   /**************************************************************************/
  480.  
  481.   pdde = (PDDESTRUCT) pulSharedObj;
  482.   pdde->usFormat = usFormat;
  483.   pdde->offszItemName = (USHORT)sizeof(DDESTRUCT); // ptr to item name
  484.   strcpy(DDES_PSZITEMNAME(pdde), pszItemName); // item name
  485.   pdde->cbData = cbData;               // count of bytes of user data
  486.   pdde->offabData = (USHORT) pdde->offszItemName+ (USHORT)strlen(pszItemName)+(USHORT)1;
  487.   pdde->fsStatus = fsStatus;           // set status flags
  488.   if (usFormat == CF_TEXT)
  489.     {
  490.     if (pvData == NULL || cbData == 0)
  491.       psz = '\0';
  492.     else
  493.        psz = pvData;
  494.     strcpy(DDES_PABDATA(pdde), psz);
  495.     }
  496.   else
  497.     {
  498.       if (pvData != NULL || cbData != 0)
  499.        memcpy(DDES_PABDATA(pdde), pvData, (size_t)cbData);
  500.     }
  501.   return  pdde;
  502.  
  503. } // MakeDDEDataSeg()
  504.  
  505. /* $Workfile:   server.c  $ */
  506.  
  507.