"Fossies" - the Fresh Open Source Software Archive

Member "WINPMDDE.TXT" (9 Aug 1999, 28845 Bytes) of package /windows/mail/pegasus/winpmail/w16-312b.exe:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 Pegasus Mail for Windows DDE (Dynamic Data Exchange) Interface
    2 Copyright (c) 1997-1999, David Harris, All Rights Reserved.
    3 ----------------------------------------------------------------
    4 
    5 Revision history:
    6 * WinPMail v3.11: added IDENTITY and VOLATILE keywords to MESSAGE topic.
    7 * WinPMail v3.12: added RICHTEXT keyword to MESSAGE topic, and STATUS
    8   keyword to ENVIRONMENT topic
    9 
   10 Pegasus Mail v2.54 and later incorporates support for Windows DDE to allow
   11 interprocess communication. This document describes the topics supported by
   12 WinPMail and the syntax of the commands sent to them. It is not a tutorial
   13 on DDE, and assumes that you either understand how to use DDE, or are using
   14 an environment (such as Microsoft Word's WordBasic language) that
   15 simplifies the process of using DDE commands.
   16 
   17 One of the most powerful features of DDE is that it allows transparent
   18 communication between 16-bit and 32-bit applications: so, by using DDE, you
   19 can communicate with either the 16- or the 32-bit version of WinPMail
   20 without having to be worried about the differences between the two.
   21 
   22 Pegasus Mail's DDE interface has been designed to be as simple to use as
   23 possible, and depends on simple strings for commands. It should be possible
   24 to use DDE to interact with Pegasus Mail from almost any environment.
   25 
   26 
   27 
   28 Service and Topic Names
   29 -----------------------
   30 
   31 Under DDE, a "service name" is the name of an application that can accept
   32 DDE connections: when you connect to a service application, you specify a
   33 particular set of commands or operations in which you are interested - this
   34 set of commands is known as a "topic". Pegasus Mail uses the service name
   35 "WinPMail" and exports the following topics:
   36 
   37    "System"        The standard DDE system topic
   38    "Environment"   Accepts DDE Requests (transactions of type XTYP_REQUEST)
   39                    and returns information about the environment of the
   40                    running copy of WinPMail, such as directories and
   41                    usernames.
   42    "Message"       Accepts DDE Poke commands to create and send e-mail
   43                    messages. A DDE Client can either create and manipulate
   44                    standard Pegasus Mail message editor windows, filling
   45                    in whichever blanks are required, or it can create
   46                    messages without a window.
   47    "TCP"           Provides access via DDE Poke commands to WinPMail's
   48                    TCP/IP-based mail services.
   49 
   50 
   51 
   52 The "Environment" topic
   53 -----------------------
   54 
   55 The "Environment" DDE topic allows client applications to obtain
   56 information about the running copy of Pegasus Mail. To use this command,
   57 send a DDE Request command (a transaction of type XTYP_REQUEST) the the
   58 "Environment" topic with the "item" parameter set to the environment item
   59 you wish to retrieve, selected from the following list:
   60 
   61    USER           - Returns the name of the user running WinPMail 
   62    HOMEBOX        - Returns the full path to the user's home mail directory
   63    NEWBOX         - Returns the full path to the user's new mail directory
   64    MODE           - Returns either "Standalone" or "Network"
   65    VERSION        - Returns the version of WinPMail, expressed as a four
   66                     digit hexadecimal number ("0254" for v2.54) followed
   67                     by a space and either "16" or "32" to indicate the
   68                     version of WinPMail that is running.  
   69    BASEDIR        - The directory from which WinPMail was run
   70    TCP            - If WinPMail's TCP/IP services are available, returns
   71                     the path to the WINSOCK.DLL in use, otherwise returns
   72                     the single character "N".
   73    NEWMAIL        - Returns the number of mail messages in the user's new
   74                     mail folder.
   75    STATUS         - Returns the status of the last mail delivery operation
   76 
   77 -- Example: -----------------------------------
   78 
   79    In WordBasic (MS-Word 7) the following Macro opens a connection to
   80    WinPMail, retrieves the current version, and displays it:
   81 
   82       Sub MAIN
   83       channel = DDEInitiate("WinPMail", "Environment")
   84       a$ = DDERequest$(channel, "version")
   85       DDETerminate channel
   86       MsgBox a$
   87       End Sub
   88 
   89    A longer example in C is shown as Appendix A: in this document.
   90 
   91 
   92 
   93 The "Message" topic
   94 -------------------
   95 
   96 Client applications use the "Message" topic to create and send electronic
   97 mail messages using WinPMail. Once a connection has been established to the
   98 "Message" topic, the client Pokes data at WinPMail (using XTYP_POKE
   99 transactions). The string parameter in the Poke command should be set to
  100 "Message" - other values may be added in future. The data itself contains
  101 the commands and parameters.
  102 
  103 The following commands can be Poked as data to WinPMail:
  104 
  105    New : <"Message"> or <"Window">
  106       If the parameter is "Window", then WinPMail creates a standard
  107       message editing window, and subsequent message commands will change
  108       the controls and settings in that window. If the parameter is
  109       "Message", then a data structure representing the message is
  110       allocated internally and subsequent message commands will fill in the
  111       fields within that structure.
  112 
  113    Defaults : Y
  114       Tells WinPMail to apply the user's regular message setting default
  115       values to the message. This command is only valid when the
  116       "New: message" command has been sent - it has no effect on message
  117       editing windows created using "New: window", since they always use
  118       default values automatically.
  119 
  120    To : <address> [, <address> ...]
  121       Fills in the "To" field for the message or window. The parameter may
  122       be any address WinPMail would normally accept, and you may include
  123       more than one address by separating them with commas. The same rules
  124       apply to the Cc: and Bcc: fields.
  125 
  126    Cc : <address> [, <address> ...]
  127       Fills in the "Cc:" (Carbon Copy) field for the message.
  128 
  129    Bcc : <address> [, <address> ...]
  130       Fills in the "Bcc:" (Blind Carbon Copy) field for the message.
  131 
  132    Subject : <string>
  133       Fills in the subject field of the message.
  134 
  135    Reply-to : <address>
  136       Sets the optional reply address for the message.
  137 
  138    Copyself : <'Y'> or <'N'>
  139       Selects whether or not a copy-to-self should be made of the message.
  140 
  141    Confirm-delivery : <'Y'> or <'N'>
  142       Selects whether or not to request confirmation of delivery
  143 
  144    Confirm-reading : <'Y'> or <'N'>
  145       Selects whether or not to request confirmation of reading
  146 
  147    Urgent : <'Y'> or <'N'>
  148       Selects whether or not the message should be marked as "urgent"
  149       
  150    Encrypted : <encryptor-name><,><passphrase><,><flags>
  151       Chooses an encryption method for the message. "Encryptor-name" is
  152       the tagname of the encryptor you wish to use (use "PM-BUILTIN" to
  153       select Pegasus Mail's built-in encryptor). You can find the tagname
  154       for an encryptor in the "Form tagname" line of the encryptor's .FFF
  155       file. "passphrase" is the password for the message. If it contains
  156       a comma, then it must be quoted using " and ". "flags" is either
  157       1 to encrypt the message, 2 to sign the message, or 3 to encrypt
  158       and sign the message.
  159 
  160    Signature : <number>
  161       Chooses the signature you wish to attach to the message. "number"
  162       is 1 - 9, corresponding to the signature sets shown in WinPMail's
  163       Tools | Signatures preferences page, or 0 to disable signatures.
  164 
  165    Mime : <'Y'> or <'N'>
  166       Indicates whether or not MIME support should be turned on for
  167       this message. MIME support affects the way attachments and
  168       international characters are handled by WinPMail. We strongly
  169       recommend that you turn MIME on wherever possible.
  170 
  171    Attach : <path><,><filename><,><attachment-type><,><encoding>
  172       Attach a file to the message. "path" should be the full path
  173       to the file - do not assume that the current directory in your
  174       client application will be the same as the current directory in
  175       Pegasus Mail. "filename" is the name Pegasus Mail should include
  176       in the message as the real name of the file (you will typically
  177       use this when you have to create a temporary file but want to
  178       send it under the original file's name). If "filename" is "-",
  179       WinPMail will automatically use the filename portion of "path".
  180       "attachment-type" should be textual information describing the
  181       attachment; it must not contain spaces. If you set this field to
  182       a single dash ("-"), WinPMail will use its internal routines to
  183       try to work out the most appropriate type information for the
  184       file. "encoding" is used to select the type of encoding for the
  185       attachment: we strongly recommend that you set this value to 0,
  186       which will allow WinPMail to choose the most appropriate encoding
  187       for you. Possible values are:
  188          0 - Pegasus Mail decides.
  189          1 - No encoding - the file is not altered (local mail only)
  190          2 - ASCII encoding - the file is normalised to CR/LF line
  191              endings and is not otherwise encoded in transit.
  192          3 - UUencoding - the file is uuencoded
  193          4 - BinHex - the file is transformed using the BinHex 4.0 method.
  194          5 - MIME - the file is transformed using the MIME BASE64 method.
  195 
  196    File : <filename>
  197       Indicates the name of a file containing the text WinPMail should
  198       use as the body of the message. Note that this file is NOT an
  199       attachment - it is expected to be plain text.
  200 
  201    Data : <String>
  202       Adds "string" to the body of the message as a single line. Poke
  203       this command repeatedly to build up a message line by line.
  204       WinPMail automatically adds the CR/LF termination to each line.
  205       Poking this command with no <string> parameter will print a blank
  206       line in the message (but the ':' must still be present).
  207 
  208    Identity : <identity_name>
  209       Sets the identity Pegasus Mail should use when processing this
  210       message. For more information on Identities, see the Pegasus Mail
  211       help file. You can specify any valid identity name as the parameter
  212       to this command. The default is the user's current identity.
  213 
  214    Volatile : <'Y'> or <'N'>         (Default is 'Y')
  215       (Only meaningful when using Pegasus Mail's built-in SMTP mailer).
  216       Setting this flag to 'Y' tells Pegasus Mail that the message should
  217       be written straight into Final Form in the queue when it is sent.
  218       If you want your message to be reloadable from Pegasus Mail's
  219       "Review queued mail" option, you should set this to 'N'. If your
  220       message contains attachments that you plan to delete once the
  221       message has been sent, you must not set this field to 'N'.
  222 
  223    Richtext : <'Y'> or <'N'>         (Default is 'N')
  224       Set the "rich text" flag in the message.
  225 
  226    Send
  227       This command sends the message. Note that it has no parameters and
  228       no ':'. It has no effect when "Window" was used as the parameter to
  229       the "New:" command.
  230 
  231    Restore
  232       This command brings WinPMail to the top and activates the Message
  233       Editing Window created using the "New: Window" command. Note that it
  234       has no parameters and no ':'. For messages created using the
  235       "New: Message" command, this command will simply bring WinPMail to
  236       the top without taking any other action.
  237 
  238 
  239 -- Example: -----------------------------------
  240 
  241    In WordBasic (MS-Word 7) the following Macro opens a connection to
  242    WinPMail, and sends a message with no window.
  243 
  244       Sub MAIN
  245       channel = DDEInitiate("WinPMail", "Message")
  246       DDEPoke channel, "Message", "New: Message"
  247       DDEPoke channel, "Message", "Defaults: Y"
  248       DDEPoke channel, "Message", "To: David"
  249       DDEPoke channel, "Message", "Subject: Test from Word"
  250       DDEPoke channel, "Message", "Data: Hi there!"
  251       DDEPoke channel, "Message", "Send"
  252       DDETerminate channel
  253       End Sub
  254 
  255 
  256 
  257 The "TCP" topic
  258 ---------------
  259 
  260 The commands in this topic allow clients to control Pegasus Mail's
  261 built-in TCP/IP-based mail protocols. Before using these commands, a
  262 client should usually use the "TCP" request to the "Environment" topic to
  263 determine whether or not TCP/IP services are enabled and available.
  264 Clients interact with this topic by Poking data at it in a similar manner
  265 to that used to access the "Message" topic. The following commands can be
  266 poked at this topic:
  267 
  268    Get
  269       Tells Pegasus Mail to download mail using the current TCP/IP
  270       settings defined for the program.
  271 
  272    Send
  273       Tells Pegasus Mail to send any messages currently waiting in
  274       the queue to be sent out.
  275 
  276    Both
  277       Tells Pegasus Mail to check for new mail, then to send any messages
  278       currently waiting in the queue, in that order.
  279 
  280    Restore
  281       Brings Pegasus Mail to the front and gives it focus.
  282 
  283 
  284 -- Example: -----------------------------------
  285 
  286    In WordBasic (MS-Word 7) the following Macro opens a connection to
  287    WinPMail, tells it to download new mail, then brings it to the front:
  288 
  289       Sub MAIN
  290       channel = DDEInitiate("WinPMail", "TCP")
  291       DDEPoke channel, "TCP", "Get"
  292       DDEPoke channel, "TCP", "Restore"
  293       DDETerminate channel
  294       End Sub
  295 
  296 
  297 
  298 Pegasus Mail and the Windows Registry
  299 -------------------------------------
  300 
  301 Starting with v2.54, WinPMail updates the Windows registry with a certain
  302 amount of information each time it is run. DDE Client Applications can use
  303 this registry information to work out how to find a copy of Pegasus Mail to
  304 run if none is active, and what commandline is appropriate.
  305 
  306 The 32-bit version of WinPMail creates the following keys:
  307 
  308    HKEY_CURRENT_USER\Software\Pegasus Mail\Version
  309    HKEY_CURRENT_USER\Software\Pegasus Mail\BaseDir
  310    HKEY_CURRENT_USER\Software\Pegasus Mail\Command
  311 
  312 The "version" key contains the WinPMail version, expressed in exactly the
  313 same way as the return from the DDE "Environment" topic's "Version"
  314 request. The "BaseDir" key contains the directory where the WinPMail
  315 executable file is located, and the "command" key contains the full
  316 commandline that was used to invoke the most recently-run copy of Pegasus
  317 Mail.
  318 
  319 Both the 16- and 32-bit versions of WinPMail create the following keys:
  320 
  321    HKEY_CLASSES_ROOT\Software\Pegasus Mail\Version
  322    HKEY_CLASSES_ROOT\Software\Pegasus Mail\BaseDir
  323    HKEY_CLASSES_ROOT\Software\Pegasus Mail\Command
  324 
  325 These keys are formatted in exactly the same way as those shown above.
  326 32-bit applications should always attempt to find the HKEY_CURRENT_USER
  327 keys before the HKEY_CLASSES_ROOT keys, since doing so ensures that
  328 multiple user configurations are respected under Windows 95 and NT.
  329 
  330 
  331 
  332 Appendix A: Using DDE from C programs
  333 -------------------------------------
  334 
  335 The source code shown here can be used as a model for interacting with
  336 any DDE-aware application. It presents a simple dialog with "Service",
  337 "Topic" and "Command" fields, request selector radio buttons that allow
  338 the user to select between XTYP_EXECUTE, XTYP_REQUEST and XTYP_POKE
  339 transactions, and three buttons - one to open/close a connection, a
  340 "quit" button, and a "Do it" button, that sends the command. If a
  341 connection is established using the "Open" button, then the "Do it"
  342 button will send the command to that connection, otherwise it will
  343 establish a connection, send the command, then close the connection.
  344 
  345 This code was written for Borland C++ v4.52 and should be linked using
  346 Borland's BWCC.LIB or BWCC32.LIB in order to present the proper dialog
  347 appearance.
  348 
  349 
  350 --------------- DDECLI.C --------------------------------------------
  351 #include <windows.h>
  352 #include <windowsx.h>
  353 #include <stdlib.h>
  354 #include <string.h>
  355 #include <ddeml.h>
  356 
  357 DWORD idInst = 0L;      // DDE instance identifier
  358 HINSTANCE hInstance;
  359 HCONV mconv;
  360 HSZ ghszServSrv;
  361 HSZ ghszServTop;
  362 
  363 #pragma warn -par
  364 #pragma warn -use
  365 
  366 
  367 HDDEDATA EXPENTRY DDECallback (WORD wType,   // transaction type
  368    WORD     wFmt,    // clipboard format
  369    HCONV    hConv,   // handle of the conversation
  370 	HSZ      hsz1,    // handle of a string
  371    HSZ      hsz2,    // handle of a string
  372    HDDEDATA hData,   // handle of a global memory object
  373    DWORD    dwData1, // transaction-specific data
  374    DWORD    dwData2) // transaction-specific data
  375    {
  376    // Nothing need be done here...
  377    return (HDDEDATA) NULL;
  378    }
  379 
  380 
  381 BOOL SendShellCommand (DWORD idInst, char *service, char *topic, LPSTR lpCommand)
  382    {
  383    HSZ      hszServSrv;    // Service is "DDESERV"
  384    HSZ      hszServTop;    // Topic is "MAIL"
  385    HCONV    hconv;         // handle of conversation
  386    int      nLen;          // length of command string
  387    HDDEDATA hData;         // return value of DdeClientTransaction
  388    DWORD    dwResult;      // result of transaction
  389    BOOL     bResult=FALSE; // TRUE if this function is successful
  390 
  391    if (mconv == NULL)
  392       {
  393       // create string handle to service/topic
  394       hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
  395       hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
  396 
  397       // attempt to start conversation with server app
  398 	   hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
  399       }
  400    else
  401       hconv = mconv;
  402 
  403    if (hconv != NULL)
  404       {
  405       // get length of the command string
  406       nLen = lstrlen ((LPSTR) lpCommand);
  407 
  408       // send command to server app
  409       hData = DdeClientTransaction (
  410          (LPBYTE) lpCommand, // data to pass
  411          nLen + 1,           // length of data
  412          hconv,              // handle of conversation
  413          NULL,               // handle of name-string
  414          CF_TEXT,            // clipboard format
  415          XTYP_EXECUTE,       // transaction type
  416          20000,              // timeout duration
  417          &dwResult);         // points to transaction result
  418 
  419       if (hData)
  420          bResult = TRUE;
  421 
  422       if (mconv == NULL)
  423          // end conversation
  424          DdeDisconnect (hconv);
  425       }
  426 
  427    if (mconv == NULL)
  428       {
  429       // free service/topic string handle
  430       DdeFreeStringHandle(idInst, hszServSrv);
  431       DdeFreeStringHandle(idInst, hszServTop);
  432       }
  433 
  434    if (bResult == FALSE)
  435       MessageBox (NULL, "SendShellCommand failed", "DDE Client", MB_OK);
  436 
  437    return bResult;
  438    }
  439 
  440 
  441 BOOL SendPoke (DWORD idInst, char *service, char *topic, LPSTR lpCommand)
  442    {
  443    HSZ      hszServSrv;    // Service is "DDESERV"
  444    HSZ      hszServTop;    // Topic is "MAIL"
  445    HCONV    hconv;         // handle of conversation
  446    int      nLen;          // length of command string
  447    HDDEDATA hData;         // return value of DdeClientTransaction
  448    DWORD    dwResult;      // result of transaction
  449    BOOL     bResult=FALSE; // TRUE if this function is successful
  450 
  451    if (mconv == NULL)
  452       {
  453       // create string handle to service/topic
  454       hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
  455       hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
  456 
  457       // attempt to start conversation with server app
  458 	   hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
  459       }
  460    else
  461       hconv = mconv;
  462 
  463    if (hconv != NULL)
  464       {
  465       // get length of the command string
  466       nLen = lstrlen ((LPSTR) lpCommand);
  467 
  468       // send command to server app
  469       hData = DdeClientTransaction (
  470          (LPBYTE) lpCommand, // data to pass
  471          nLen + 1,           // length of data
  472          hconv,              // handle of conversation
  473          hszServTop,         // handle of name-string
  474          CF_TEXT,            // clipboard format
  475          XTYP_POKE,          // transaction type
  476          20000,              // timeout duration
  477          &dwResult);         // points to transaction result
  478 
  479       if (hData)
  480          bResult = TRUE;
  481 
  482       if (mconv == NULL)
  483          // end conversation
  484          DdeDisconnect (hconv);
  485       }
  486 
  487    if (mconv == NULL)
  488       {
  489       // free service/topic string handle
  490       DdeFreeStringHandle(idInst, hszServSrv);
  491       DdeFreeStringHandle(idInst, hszServTop);
  492       }
  493 
  494    if (bResult == FALSE)
  495       MessageBox (NULL, "SendPoke failed", "DDE Client", MB_OK);
  496 
  497    return bResult;
  498    }
  499 
  500 
  501 BOOL SendShellRequest (DWORD idInst, char *service, char *topic, char *cmd)
  502    {
  503    HSZ      hszServSrv;    // Service is "DDESERV"
  504    HSZ      hszServTop;    // Topic is "MAIL"
  505    HSZ      item;
  506    HCONV    hconv;         // handle of conversation
  507    int      nLen;          // length of command string
  508    HDDEDATA hData;         // return value of DdeClientTransaction
  509    DWORD    dwResult;      // result of transaction
  510    BOOL     bResult=FALSE; // TRUE if this function is successful
  511    char     *str;
  512    DWORD    x;
  513 
  514    if (mconv == NULL)
  515       {
  516       // create string handle to service/topic
  517       hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
  518       hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
  519 
  520       // attempt to start conversation with server app
  521 	   hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
  522       }
  523    else
  524       hconv = mconv;
  525 
  526    if (hconv != NULL)
  527       {
  528       // send command to server app
  529       item = DdeCreateStringHandle (idInst, cmd, CP_WINANSI);
  530       hData = DdeClientTransaction (
  531          NULL,               // data to pass
  532          0,                  // length of data
  533          hconv,              // handle of conversation
  534          item,               // handle of name-string
  535          CF_TEXT,            // clipboard format
  536          XTYP_REQUEST,       // transaction type
  537          20000,              // timeout duration
  538          &dwResult);         // points to transaction result
  539 
  540       if (hData)
  541          {
  542          if ((str = (char *) DdeAccessData (hData, &x)) != NULL)
  543             {
  544             strcpy (cmd, str);
  545             bResult = TRUE;
  546             DdeUnaccessData (hData);
  547             }
  548 
  549          DdeFreeDataHandle (hData);
  550          }
  551 
  552       DdeFreeStringHandle (idInst, item);
  553 
  554       if (mconv == NULL)
  555          // end conversation
  556          DdeDisconnect (hconv);
  557       }
  558 
  559    if (mconv == NULL)
  560       {
  561       // free service/topic string handle
  562       DdeFreeStringHandle (idInst, hszServSrv);
  563       DdeFreeStringHandle (idInst, hszServTop);
  564       }
  565 
  566    return bResult;
  567    }
  568 
  569 
  570 int FAR PASCAL _export dummy_proc (HWND hDialog, UINT wMsg,
  571    WPARAM wParam, LPARAM lParam)
  572    {
  573    BOOL fProcessed = TRUE;
  574    DWORD dwResult;
  575    RECT r;
  576    HWND hControl;
  577    char buffer [256], service [80], topic [80];
  578 
  579    switch (wMsg)
  580       {
  581       case WM_INITDIALOG :
  582          CheckRadioButton (hDialog, 104, 106, 104);
  583          break;
  584 
  585       case WM_SETFOCUS :
  586          SetFocus (GetDlgItem (hDialog, 101));
  587          break;
  588 
  589       case WM_COMMAND :
  590          if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
  591             {
  592             EndDialog (hDialog, IDCANCEL);
  593             break;
  594             }
  595 
  596          if (GET_WM_COMMAND_ID(wParam, lParam) == 120)
  597             {
  598             if (mconv == NULL)
  599                {
  600                GetDlgItemText (hDialog, 101, service, sizeof (service));
  601                GetDlgItemText (hDialog, 102, topic, sizeof (topic));
  602                ghszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
  603                ghszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
  604 
  605                // attempt to start conversation with server app
  606 	            mconv = DdeConnect (idInst, ghszServSrv, ghszServTop, NULL);
  607                if (mconv == NULL)
  608                   MessageBox (NULL, "Connection failed!", "DDE Client", 
  609                      MB_OK | MB_ICONEXCLAMATION);
  610                else
  611                   SetDlgItemText (hDialog, 120, "Close");
  612                }
  613             else
  614                {
  615                DdeDisconnect (mconv);
  616                mconv = NULL;
  617                DdeFreeStringHandle (idInst, ghszServSrv);
  618                DdeFreeStringHandle (idInst, ghszServTop);
  619                SetDlgItemText (hDialog, 120, "Open");
  620                }
  621             break;
  622             }
  623 
  624          if (GET_WM_COMMAND_ID(wParam, lParam) == IDOK)
  625             {
  626             GetDlgItemText (hDialog, 101, service, sizeof (service));
  627             GetDlgItemText (hDialog, 102, topic, sizeof (topic));
  628             GetDlgItemText (hDialog, 103, buffer, sizeof (buffer));
  629             hControl = GetDlgItem (hDialog, 107);
  630             if (IsDlgButtonChecked (hDialog, 105))   //  Request
  631                {
  632                if (SendShellRequest (idInst, service, topic, buffer))
  633                   {
  634                   Edit_ReplaceSel (hControl, "Request successful:\r\n   ");
  635                   Edit_ReplaceSel (hControl, buffer);
  636                   Edit_ReplaceSel (hControl, "\r\n");
  637                   }
  638                else
  639                   Edit_ReplaceSel (hControl, "Request failed.\r\n");
  640                }
  641             else if (IsDlgButtonChecked (hDialog, 104))
  642                {
  643                if (SendShellCommand (idInst, service, topic, buffer))
  644                   Edit_ReplaceSel (hControl, "Command successful.\r\n");
  645                else
  646                   Edit_ReplaceSel (hControl, "Command failed.\r\n");
  647                }
  648             else
  649                {
  650                if (SendPoke (idInst, service, topic, buffer))
  651                   Edit_ReplaceSel (hControl, "Poke successful.\r\n");
  652                else
  653                   Edit_ReplaceSel (hControl, "Poke failed.\r\n");
  654                Edit_SetSel (GetDlgItem (hDialog, 103), 0, 999);
  655                }
  656             }
  657          break;
  658 
  659       default:
  660          fProcessed = FALSE;
  661          break;
  662       }
  663 
  664    return fProcessed;
  665    }
  666 
  667 
  668 int PASCAL WinMain (HINSTANCE __hInstance, HINSTANCE hPrevInstance,
  669    LPSTR lpszCmdLine, int nCmdShow)
  670    {
  671    MSG msg;
  672    HWND hWndFrame;
  673    WNDCLASS wc;
  674    FARPROC DDEProc, dlgProc;
  675 
  676    if (hPrevInstance != NULL)
  677       return 0;
  678 
  679    hInstance = __hInstance;
  680 
  681    // get proc instance for our DDEML callback
  682    DDEProc = MakeProcInstance ((FARPROC) DDECallback, hInstance);
  683 
  684    // register this app with the DDEML
  685    if (DdeInitialize (&idInst,   // receives instance ID
  686       (PFNCALLBACK) DDEProc,     // address of callback function
  687       APPCMD_CLIENTONLY,         // this is a client app
  688       0L))                       // reserved
  689       {
  690 #ifndef __FLAT__        //  FreeProcInstance is obsolete under Win32
  691       FreeProcInstance (DDEProc);
  692 #endif
  693       return FALSE;
  694       }
  695 
  696    dlgProc = MakeProcInstance ((FARPROC) dummy_proc, hInstance);
  697    DialogBox (hInstance, "CLIENT", NULL, dlgProc);
  698    DdeUninitialize (idInst);
  699    return 0;
  700    }
  701 
  702 --------------- DDECLI.DEF ----------------------------------------
  703 NAME           DDECLI
  704 DESCRIPTION    'DDE Test Client'
  705 EXETYPE        WINDOWS
  706 DATA           MOVEABLE MULTIPLE PRELOAD
  707 CODE           MOVEABLE DISCARDABLE
  708 HEAPSIZE       27500
  709 STACKSIZE      16500
  710 
  711 --------------- DDECLI.RC -----------------------------------------
  712 
  713 CLIENT DIALOG 180, 121, 246, 168
  714 STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
  715 CLASS "bordlg"
  716 CAPTION "DDE Test Client"
  717 FONT 8, "MS Sans Serif"
  718 {
  719  RTEXT "Service name:", -1, 15, 15, 60, 8
  720  CONTROL "winpmail", 101, "EDIT", ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, 83, 13, 102, 12
  721  RTEXT "Topic name:", -1, 15, 30, 60, 8
  722  CONTROL "message", 102, "EDIT", ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, 83, 28, 102, 12
  723  RTEXT "Command/request:", -1, 14, 45, 61, 8
  724  EDITTEXT 103, 83, 43, 102, 12, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
  725  RTEXT "Transaction type:", -1, 15, 65, 60, 8
  726  CONTROL "Execute", 104, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 85, 64, 47, 10
  727  CONTROL "Request", 105, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 133, 64, 43, 10
  728  CONTROL "Poke", 106, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 64, 32, 10
  729  LTEXT "Results / Diagnostics", -1, 12, 82, 78, 8
  730  EDITTEXT 107, 10, 92, 228, 69, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
  731  DEFPUSHBUTTON "Do it", IDOK, 192, 12, 43, 14
  732  PUSHBUTTON "Quit", IDCANCEL, 192, 42, 43, 14
  733  CONTROL "", -1, "BorShade", BSS_GROUP | BSS_CAPTION | BSS_LEFT | WS_CHILD | WS_VISIBLE, -5, -7, 257, 180
  734  PUSHBUTTON "Open", 120, 192, 27, 43, 14
  735 }
  736