//
//  WPMFORMS.H
//  Definitions and constants for the Pegasus Mail for Windows
//  Extensions Manager interface.
//
//  Copyright (c) 1994-95, David Harris, all rights reserved.
//

//  Next available offset -
//    -  For WM_FM_*      =   10    (22 Jan '95)
//    -  For WM_F_*       =   67    (30 Apr '95)

//  Flag constants:

#define WPM_STARTUP     1     // Extension wants to be loaded at startup
#define WPM_NOLIST      2     // Do not show extension in Form Manager list
#define WPM_HIDDEN      4     // Do not display extension's parent window
#define WPM_LOGGING     8     // Extension wants to receive logging events
#define WPM_ONEONLY     16    // Disallow multiple simultaneous instances

#define WPM_PROHIBIT    0x9999L

//  Form dialogs and callbacks: a form DLL can export a function
//  which WinPMail's form manager will call with Windows messages
//  destined for the form's dialog or window (such as menu selections
//  and so forth). The function takes the following form:

typedef long FAR PASCAL (*FORM_CALLBACK) (HWND hWnd, WORD wMsg,
   WPARAM wParam, LPARAM lParam);

//  The return from a form callback is passed back through the
//  Windows call chain if non-zero, otherwise the default window
//  proc is called.

//  Minimum interface: the minimum interface a form DLL must provide
//  is a routine called "FORMINIT" which is exported by name. "FORMINIT"
//  has the following prototype:

typedef WORD FAR PASCAL (*FN_FORMINIT) (WORD version, int variant, 
   HWND hParent, char *data, HWND *hDialog, char *callback_name);

//  "version" is passed in with the version of the WinPMail forms
//     manager which is running.
//  "variant" indicates what type of form is required - the following
//     values are currently defined:
//       0: Create a form for composing a message
//       1: Create a form for reading a message
//  "hParent" contains the handle of the WinPMail MDI child window
//     which is to contain the form.
//  "data" contains any string defined as being required for the
//     form in the menu interface.
//  "hDialog" should be filled in with the window handle of the
//     modeless dialog created within the MDI child window. If the
//     value returned is NULL, then the MDI child window will be
//     hidden and will never actually interact directly with the
//     user, but the extension will still receive messages from the
//     Form Manager and can still send messages to its parent for
//     access to API functions.
//  "callback_name" (optional) should be filled in with the name of the
//     function in the DLL of the exported function to which messages
//     should be sent or NULL if there is none. If NULL, messages are
//     sent to the dialog returned in "hDialog". You will use an
//     indirect callback of this kind when your extension does not
//     create a dialog within the enclosing parent window.
//
//  When FORMINIT is called, the DLL should create the dialog within
//  the MDI parent window and set it to the correct size. On return
//  WinPMail will resize the parent window to enclose the dialog
//  correctly. The DLL should NOT make the dialog visible - WinPMail
//  will do that as required.

//
// +--------------------------------------------------------------------+
// |  SECTION 1:                                                        |
// |  Messages the Extension Manager can send to an extension:          |
// +--------------------------------------------------------------------+
//

#define WM_FM_FORMBASE           (WM_USER + 1800)

//  Sent by the manager after the MDI parent window has been created
//  and FORMINIT has been called, but before any positioning has been
//  done. At the time this message arrives, the window will not be
//  visible on the screen. An extension may send any extension manager
//  message while processing this message and at any time afterwards.
#define WM_FM_INIT               (WM_FM_FORMBASE + 1)

//  Sent by the manager when the enclosing MDI window is resized.
//  The parameters from the WM_SIZE message passed by windows are
//  sent through unaltered. If an extension contains a dialog, it
//  should resize the dialog to the MDI parent window size in
//  response to this message.
#define WM_FM_SIZE               (WM_FM_FORMBASE + 2)

//  Sent by the manager when Windows asks it for the limits on a
//  window resize operation. See the Windows documentation for
//  WM_GETMINMAXINFO for more details (the manager passes the
//  parameters through unmodified).
#define WM_FM_GETMINMAXINFO      (WM_FM_FORMBASE + 3)

//  Sent by the forms manager after creating the form dialog but before
//  displaying the MDI child window; asks where the form would like its
//  window placed on the screen. lParam points to a POINT structure;
//  if 1 is returned, the position it contains will be used. The position
//  should be expressed in units from the top left corner of WinPMail's
//  main client area. If 0 is returned, WinPMail will stagger the window
//  like any other of its own windows. If 2 is returned, WinPMail will
//  centre the window in the client area.
#define WM_FM_WHEREYAWANNIT       (WM_FM_FORMBASE + 4)

//  Sent by the manager at the end of Window creation, after the
//  window has been made visible. The dialog should set focus to
//  whichever control it wishes.
#define WM_FM_INITFOCUS           (WM_FM_FORMBASE + 5)

//  Sent by the manager any time the window should restore its
//  focus to the last active control. This curiosity is needed
//  because of a glitch in the way Windows handles focus for
//  dialogs embedded in MDI children. Dialogs should record the
//  last active control by trapping EN_SETFOCUS messages from
//  the controls they contain.
#define WM_FM_RESTOREFOCUS        (WM_FM_FORMBASE + 6)

//  The Manager generates a WM_FM_COMMAND message any time it
//  receives a WM_COMMAND message which it cannot itself handle.
//  In almost all cases, this will occur with menu selections
//  from the main WinPMail menu. The format of this command is
//  exactly the same as a WM_COMMAND message.
#define WM_FM_COMMAND             (WM_FM_FORMBASE + 7)

//  The following predefined values should be used to decode
//  WM_FM_COMMAND messages: you should avoid using any of these
//  values in any menu you create.
#define IDM_PRINT            107      //  Print the current contents
#define IDM_UNDO             131      //  User selected "undo"
#define IDM_CUT              132      //  User selected "cut"
#define IDM_COPY             133      //  User selected "copy"
#define IDM_PASTE            134      //  User selected "paste"
#define IDM_CLEAR            135      //  User selected "clear"
#define IDM_SELECTALL        136      //  User selected "select all"
#define IDM_SPELLING         137      //  User asked to check spelling
#define IDM_TODISK           230      //  User clicked the "to disk" bp icon
#define IDM_FROMDISK         231      //  User clicked the "from disk" bp icon
#define IDM_FONT             299      //  User clicked the "font" bp icon

//
// +--------------------------------------------------------------------+
// |  SECTION 2:                                                        |
// |  Messages a form can send to the Forms Manager to access           |
// |  internal Pegasus Mail messaging services:                         |
// +--------------------------------------------------------------------+
//

#define WM_F_FORMBASE            (WM_USER + 2000)

//  Open the Recent address list and allow the user to select
//  addresses from it. Any addresses selected are pasted into the
//  EDIT control specified in wParam.
//  ** PARAMETERS: wParam = Active edit control;  lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_QUICKADDRESS        (WM_F_FORMBASE + 1)

//  Create a new message ready to be filled out. NOTE: this does not
//  mean "open a new mail composition window", it merely means "I am
//  about to generate a message for you to send - get ready", and
//  causes the Extension Manager to create internal data structures.
//  Note that this function will also "reset" the message structure
//  associated with an extension window if a message has already been
//  started or sent, clearing all addresses, custom headers and other
//  defined fields.
//  ** PARAMETERS: None
//  ** RETURNS:    1 on success, 0 on failure (out of memory)
//  ** WARNING:    You MUST send this message before attempting to
//                 fill out any fields in a message.
#define WM_F_NEWMESSAGE          (WM_F_FORMBASE + 2)

//  Set the "To" field of the message
//  ** PARAMETERS: wParam = unused; lParam = address to set
//  ** RETURNS:    Nothing
#define WM_F_TO                  (WM_F_FORMBASE + 3)

//  Set the "Cc" field of the message
//  ** PARAMETERS: wParam = unused; lParam = address to set
//  ** RETURNS:    Nothing
#define WM_F_CC                  (WM_F_FORMBASE + 4)

//  Set the "BCc" field of the message
//  ** PARAMETERS: wParam = unused; lParam = address to set
//  ** RETURNS:    Nothing
#define WM_F_BCC                 (WM_F_FORMBASE + 5)

//  Set the "Subject" field of the message
//  ** PARAMETERS: wParam = unused; lParam = text to set
//  ** RETURNS:    Nothing
#define WM_F_SUBJECT             (WM_F_FORMBASE + 6)

//  Set the message's Copy-to-self flag
//  ** PARAMETERS: wParam = 1 or 0; lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_COPYSELF            (WM_F_FORMBASE + 7)

//  Set the message's Confirm-reading flag
//  ** PARAMETERS: wParam = 1 or 0; lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_CONFIRMREADING      (WM_F_FORMBASE + 8)

//  Set the message's Confirm-delivery flag
//  ** PARAMETERS: wParam = 1 or 0; lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_CONFIRMDELIVERY     (WM_F_FORMBASE + 9)

//  Set the message's Urgent flag
//  ** PARAMETERS: wParam = 1 or 0; lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_URGENT              (WM_F_FORMBASE + 10)

//  Set the message's Use-MIME flag
//  ** PARAMETERS: wParam = 1 (use MIME) or 0 (Don't); lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_MIME                (WM_F_FORMBASE + 11)

//  Set/unset the flag which controls whether or not a message
//  can be sent via Internet transports using raw 8-bit data.
//  ** PARAMETERS: wParam = 1 (allow 8 bits) or 0 (don't); lParam = unused
//  ** RETURNS:    Nothing
//  Note: 8-bit data is officially illegal in Internet mail - you are
//    <<strongly>> urged not to use this option unless you have no other
//    choice and understand very clearly what you are doing. The author
//    accepts no responsibility whatsoever for abuse of this feature and
//    reserves the right to remove or disable it in future releases of
//    the program if it is indiscriminately or carelessly used.
#define WM_F_8BITDATA            (WM_F_FORMBASE + 62)

//  Set the "Reply-to" field of the message
//  ** PARAMETERS: wParam = unused; lParam = address to set
//  ** RETURNS:    Nothing
#define WM_F_REPLYTO             (WM_F_FORMBASE + 12)

//  Add an attachment to the message:
//  ** PARAMETERS: wParam = unused;
//     lParam points to a record of the following type:
#ifndef WINPMAIL
typedef struct
   {
   char file_to_attach [144];
   char attachment_type [32];
   char encoding;
   } ATTACHMENT;
#endif
//  "encoding" can be:
//     0: Best guess - WinPMail chooses the most appropriate encoding
//     1: No encoding (use with EXTREME care)
//     2: ASCII text
//     3: UUencoding
//     4: BinHex
//     5: MIME encoding (BASE64)
//  You are <<strongly>> encouraged to set "encoding" to 0 unless you
//  are VERY sure of what you are doing.
//  ** RETURNS:    Nothing
#define WM_F_ATTACH              (WM_F_FORMBASE + 13)

//  Set the encryption key for the message; if 0-length, the message
//  is not encrypted.
//  ** PARAMETERS: wParam = unused; lParam points to encryption key
//  ** RETURNS:    Nothing
#define WM_F_ENCRYPTIONKEY       (WM_F_FORMBASE + 14)

//  Set the message's No-signature flag; wParam = 1 or 0
//  ** PARAMETERS: wParam = 1 (no signature) or 0; lParam = unused
//  ** RETURNS:    Nothing
//  ** Note the reversed sense of the wParam parameter.
#define WM_F_NOSIG               (WM_F_FORMBASE + 15)

//  Indicate the full path to a file containing the text Pegasus Mail
//  should use as the body of the mail message.
//  ** PARAMETERS: wParam = unused; lParam = pointer to path (C string)
//  ** RETURNS:    Nothing
//  ** Note: this message and WM_F_MESSAGETEXT are mutually exclusive.
//  ** Note 2: the variable pointed to by lParam should be persistent -
//     that is, its value should remain valid until the message is sent.
//     Pegasus Mail stores the pointer, not a copy of the data, so if you
//     allocate the path on the stack the return from the function where
//     it is declared, it will be trashed. In general, either allocate
//     memory for it explicitly or declare it static. If you allocate
//     memory for it, remember to release it, since WinPMail will not.
#define WM_F_MESSAGEFILE         (WM_F_FORMBASE + 16)

//  Set the text of the mail message body to a block contained in memory.
//  Lines should end in LF characters only. lParam points to the text,
//  which must be nul-terminated.
//  ** PARAMETERS: wParam = unused; lParam = pointer to textual data.
//  ** RETURNS:    Nothing
//  ** Note: this message and WM_F_MESSAGEFILE are mutually exclusive.
//  ** Note 2: you can get text from an edit control formatted in the
//     proper way for this message using the WM_F_GETTEXT message.
#define WM_F_MESSAGETEXT         (WM_F_FORMBASE + 17)

//  Set the expiration date of the message
//  ** PARAMETERS: wParam = unused; lParam = pointer to a 7-byte
//     date format record described under WM_F_GETDATETIME below.
//  ** RETURNS:    Nothing
#define WM_F_EXPIRATION          (WM_F_FORMBASE + 18)

//  Initialize a message created using the WM_F_NEWMESSAGE menu to
//  the values stored in the user's preferences file. You should send
//  this message after sending WM_F_NEWMESSAGE but before sending any
//  other messagefield-related message.
//  ** PARAMETERS: wParam = unused; lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_SETDEFAULTS         (WM_F_FORMBASE + 19)

//  Set a custom header in the outgoing message. lParam points to
//  the header data, and wParam is either 0 if the header is suitable
//  for use in RFC822 messages or 1 if the header is intended for use
//  in MHS messages. This routine cannot be used to alter the following
//  headers in the message: "From:", "To:", "Reply-to:", "Cc:", "Bcc:",
//  "Subject:", "Date:", "X-To:", "Copies-to:", "Organization:",
//  "Priority:", "Importance:", or "Sender:" - attempting to do so will
//  return an error code. Any other legally formatted header may be
//  added, though; the header may contain LFs to indicate line breaks
//  (note, do NOT add the CR) but must follow proper line folding rules
//  for the destination transport. The header need not end with a newline
//  character but may (WinPMail will add it if necessary).
//  ** PARAMETERS: wParam = 0 (RFC822) or 1 (MHS); lParam = header.
//  ** RETURNS:    1=Success, 0=illegal header, -1 = out of memory.
//  ** WARNING:    This message is extremely specialised and should not
//                 be needed in the vast majority of cases. You should
//                 only use this message if you have expert knowledge
//                 of the message transport for with the header you are
//                 adding is intended.
#define WM_F_SETHEADER           (WM_F_FORMBASE + 61)

//  Send a message created using the interface defined in the
//  preceding messages. It is legal to call this message repeatedly
//  for the same message definition - so, if you wanted to send the
//  same message to 20 different users, you could set it up the way
//  you want it then call WM_F_TO after each WM_F_SENDMESSAGE call
//  to change the recipient.
//  ** PARAMETERS: wParam = unused; lParam = unused
//  ** RETURNS:    0 on failure, 1 on success.
#define WM_F_SENDMESSAGE         (WM_F_FORMBASE + 20)

//
// +--------------------------------------------------------------------+
// |  Section 3:                                                        |
// |  Simple TCP/IP interface routines                                  |
// +--------------------------------------------------------------------+
//
// The extensions manager provides a simplified TCP/IP interface to
// extensions, suitable for simple question-and-answer style protocols
// such as POP3, SMTP, Finger, LDAP or PH. The TCP/IP connection is
// fully buffered and quite robust, but offers nothing fancy. An
// extension can have up to five TCP/IP connections open at any time.
// If you need more than this interface offers (UDP support, for
// instance), you should load WINSOCK.DLL using your own instance
// handle and access its services directly.
//
// Note: WinPMail's socket handling is fully non-blocking so you can
// open multiple sockets simultaneously without contention problems.
// The exception to this is name resolution calls, which may block,
// and which may therefore cause transient failures. This will be
// addressed in future, but for now the easiest way to avoid this
// as a problem is to use numeric IP addresses instead of names
// wherever possible.

//  Open a TCP/IP connection
//  ** PARAMETERS: wParam = host port; lParam = pointer to host
//     address in either domain name or dotted-IP format.
//  ** RETURNS:    -1 on failure
#define WM_F_TCPOPEN             (WM_F_FORMBASE + 29)

//  Get a line of data from an open TCP/IP port. The terminating LF or
//  CR/LF is not removed from the returned data.
//  ** PARAMETERS: wParam = length of buffer; lParam = pointer to buffer
//  ** RETURNS:    > 0 = OK; 0 = timeout; < 0; TCP/IP error
#define WM_F_TCPGETS             (WM_F_FORMBASE + 34)

//  Write a line of data to an open TCP/IP port; does not add CRLF. The
//  data is presumed to be a nul-terminated C string.
//  ** PARAMETERS: wParam = unused; lParam = pointer to data to write
//  ** RETURNS:    > 0 = OK; 0 = timeout; < 0; TCP/IP error
#define WM_F_TCPPUTS             (WM_F_FORMBASE + 35)

//  Close an open TCP/IP connection
//  ** PARAMETERS: wParam = unused; lParam = unused
//  ** RETURNS:    -1 on failure
#define WM_F_TCPCLOSE            (WM_F_FORMBASE + 36)

//  Determine whether TCP/IP services are available and configured
//  ** PARAMETERS: wParam = unused; lParam = unused
//  ** RETURNS:    1 = OK to use TCP/IP services; 0 = no TCP/IP services
#define WM_F_TCPPRESENT          (WM_F_FORMBASE + 37)

//  Return the domain name of the current machine. If no domain name
//  can be determined, return the machine's IP address in dotted format.
//  ** PARAMETERS: wParam = length of buffer; lParam = pointer to buffer
//  ** RETURNS:    Nothing
#define WM_F_TCPMYNAME           (WM_F_FORMBASE + 38)

//  Set the socket which will be used in subsequent TCP/IP calls.
//  The default socket is 0, so if you only ever have a single
//  connection open at any time you will never need to use this
//  message. Each extension (or instance of an extension) can have up
//  to five connections open simultaneously and can select the one you
//  are interested in using this message
//  ** PARAMETERS: wParam = desired socket (0..4); lParam = unused
//  ** RETURNS:    Nothing
#define WM_F_TCPSETSOCKET        (WM_F_FORMBASE + 49)

//  Initiate a regular POP3 connection and download mail to the
//  local machine. If wParam is 0, a progress dialog will be put
//  up during the transaction. If lParam is 0 (NULL) then the
//  standard host configuration provided by the user will be used
//  for host and username information; alternatively, lParam can
//  point to a copy of the following structure:
#ifndef PROFILE_INCLUDED
#define MAXHOST 80
typedef struct
   {
   char pop3host [MAXHOST];   //  POP3 server address
   char smtphost [MAXHOST];   //  SMTP server address
   char username [48];        //  POP3 account name
   char password [48];        //  POP3 account password
   char mask [64];            //  Path and filespec to find SMTP files
   char mailbox [80];         //  Where to place incoming POP3 messages
   long threshhold;           //  Largest message to download, in bytes
   int delete_mail;           //  If NZ, delete successfully downloaded mail
   long wflags;
   char from_field [MAXHOST]; //  Contents of the message's "from" field
   int timeout;               //  TCP/IP timeout (seconds)
   char memory_file [14];     //  State info file when leaving mail on server
   } POPDEF;
#endif
//  ** PARAMETERS: wParam = 0/NZ;dialog/none; lParam = NULL/see above
//  ** RETURNS:    None
#define WM_F_TCPPOP3             (WM_F_FORMBASE + 52)

//  Initiate a regular POP3 connection but ONLY check that the
//  user and password information supplied is valid. No actual
//  mail transaction is performed. A dialog is never put up for
//  this routine, although messages may appear on the statusline.
//    If wParam is non-zero, the POP3 code will establish a con-
//  nection to the POP3 server, will authenticate the user, and
//  will then return control in the open state. If you use this
//  feature, it is up to you to issue proper POP3 commands to
//  manage the session and close it down gracefully.
//    If lParam is 0 (NULL) then the standard host configuration
//  provided by the user will be used for host and username
//  information; alternatively, lParam can point to a copy of
//  the POPDEF structure shown above.
//  ** PARAMETERS: wParam = unused; lParam = NULL/see above
//  ** RETURNS:    1 if the information is valid, 0 if not.
//  ** Note: it is not possible to determine in any meaningful way
//  which of the username or password was incorrect if verification
//  fails, because most POP3 servers accept any username for security
//  reasons.
#define WM_F_TCPOP3VERIFY        (WM_F_FORMBASE + 55)

//  Initiate a regular POP3 connection but ONLY count the number
//  of messages waiting on the account. No actual mail download is
//  performed and a dialog is never put up although messages may
//  appear on the statusline. If lParam is 0 (NULL) then the
//  standard host configuration provided by the user will be used
//  for host and username information; alternatively, lParam can
//  point to a copy of the POPDEF structure shown above.
//  ** PARAMETERS: wParam = unused; lParam = NULL/see above
//  ** RETURNS:    -1 on error, message count otherwise
#define WM_F_TCPOP3COUNT         (WM_F_FORMBASE + 56)

//  Initiate a regular SMTP connection using the built-in client.
//    If wParam is 0, a progress dialog will be put up during the
//  transaction. As with WM_F_TCPPOP3, you can pass a POPDEF
//  structure pointer in lParam to specify an alternative host.
//  ** PARAMETERS: wParam = 0/NZ;dialog/none; lParam = NULL/see above
//  ** RETURNS:    None
//  ** Note: for security reasons, WinPMail will only send mail using
//  the SMTP protocol if it can verify your POP3 information by
//  connecting to the specified POP3 server; no verification, no send.
#define WM_F_TCPSMTP             (WM_F_FORMBASE + 53)

//  Read raw data from a TCP/IP port. lParam points to a buffer where
//  the data should be written: if wParam is non-zero, then it is
//  whichever is the lesser of the size of the buffer, or the maximum
//  number of bytes to read. If wParam is zero, then the buffer must
//  be 1024 bytes long and the routine will wait until any data appears
//  on the port then return it, up to 1024 bytes in length. This latter
//  application is useful when dealing with protocols where you don't
//  necessarily know how much data you are going to receive in advance.
//  ** PARAMETERS: wParam = 0, or bufsize/maxdata; lParam = buffer address
//  ** RETURNS:    The actual number of bytes read; < 0 indicates an
//                 error; 0 indicates either socket closed or timeout.
#define WM_F_TCPREAD             (WM_F_FORMBASE + 59)

//  Write raw data to a TCP/IP port. lParam points to the data to write,
//  and wParam points to the length of the data. The data is written
//  without any modification. This routine never blocks, and enters an
//  internal message processing loop while waiting for the data to clear.
//  ** PARAMETERS: wParam = length of data; lParam = pointer to data
//  ** RETURNS:    -1 on hard error; 0 on timeout; >0 on success (the
//                   number of bytes actually written).
#define WM_F_TCPWRITE            (WM_F_FORMBASE + 60)

//
// +--------------------------------------------------------------------+
// |  Section 4:                                                        |
// |  Calls available only to READER extensions                         |
// +--------------------------------------------------------------------+
//

//  A reader extension can call this to open the original message
//  passed to it at startup.
//  ** PARAMETERS: wParam = unused; lParam = unused
//  ** RETURNS:    1 if successfully opened; 0 on failure.
#define WM_F_OPENMESSAGE         (WM_F_FORMBASE + 42)

//  Read a line from the original message. The message must have been
//  opened successfully by calling WM_F_OPENMESSAGE before calling this
//  routine.
//  ** PARAMETERS: wParam = maximum length to read; lParam = pointer to buffer
//  ** RETURNS:    1 if data was read, 0 on failure (usually EOF).
#define WM_F_READLINE            (WM_F_FORMBASE + 43)

//  Close a message file opened with WM_F_OPENMESSAGE.
//  ** PARAMETERS: wParam = unused; lParam = unused.
//  ** RETURNS:    Nothing.
#define WM_F_CLOSEMESSAGE        (WM_F_FORMBASE + 44)

//  Get the flag longword for the message. The message does NOT have to
//  be open in order for this call to succeed.
//  ** PARAMETERS: wParam = unused; lParam = unused.
//  ** RETURNS:    Flag longword (32 bits)
#define WM_F_GETFLAGS            (WM_F_FORMBASE + 45)

//  Set the flag longword for the message. The message does NOT have
//  to be open in order for this call to succeed. Note; this function
//  is only provided to allow you to alter the "has been read", "replied",
//  "forwarded" and "is annotated" flags. Changing or setting any other
//  bit in the flag longword may have unexpected consequences and should
//  only be done if you're absolutely sure of what you're doing.
//  ** PARAMETERS: wParam = unused; lParam = Flag longword.
//  ** RETURNS:    Nothing
#define WM_F_SETFLAGS            (WM_F_FORMBASE + 46)

//  The flag longword is a 32-bit bitmap which can consist of the
//  following values:
#ifndef WINPMAIL
#define FILE_MAILED     1           // Message has local-style PMF attachments
#define UUENCODED       2           // "   "   "   uuencoded attachments
#define FILE_ATTACHED   0x800003L   // Use this as an attachment mask.
#define ENCRYPTED       4           // Message is encrypted.
#define EXPIRED         16          // Message is past its expiry date
#define HAS_BEEN_READ   128         // The reader has opened the message
#define CONFIRMATION    8192        // Sender wants confirmation of reading
#define COPYSELF       0x20000L     // Message is a copy to self
#define DELETED        0x40000L     // Message has been deleted.
#define MIME           0x80000L     // Message is a MIME transmission
#define REPLIED       0x100000L     // Message has been replied to.
#define FORWARDED     0x200000L     // Message has been forwarded.
#define URGENT        0x400000L     // Message is urgent/high priority.
#define BINHEX        0x800000L     // Message contains BinHex-encoded data
#define IS_MHS       0x1000000L     // Message originates from MHS
#define IS_SMTP      0x2000000L     // Message originates from SMTP
#define IS_ANNOTATED 0x4000000L     // The message has an annotation
#define ENCLOSURE    0x8000000L     // The message has enclosures
#endif

//  Get details about an attachment from a message. wParam should
//  indicate the index to the attachment for which data is required 
//  (numbering from 0 as the first attachment) or -1 if you only want
//  it to return a count of the number of attachments. lParam should
//  point to an ATTACHMENT structure as defined in the WM_F_ATTACH
//  message. You should generally only call this routine if the flag
//  longword for the message indicates that attachments are present,
//  although this routine does a much more thorough examination of the
//  message for enclosures than the standard message parser and may
//  pick up some which it misses.
//  ** PARAMETERS: wParam = index or -1; lParam = pointer to ATTACHMENT
//  ** RETURNS:    Number of attachments to message, or -1 on error
//  ** Note:       This call cannot be used to handle components of
//                 multipart MIME messages, since they are not necessarily
//                 attachments. Pegasus Mail's own multipart browser is
//                 capable of loading reader extensions for individual
//                 components, but if you want to write your own multipart
//                 browser to replace the built-in browser, you will have
//                 handle the MIME sub-parsing yourself.
#define WM_F_ATTACHMENTINFO      (WM_F_FORMBASE + 47)

//  Extract an attachment from a message into a specified file. wParam
//  should indicate the index to the attachment required. lParam should
//  point to a filename string; if lParam is NULL or if the first char
//  in the filename string is an ASCII NUL (0), then WinPMail will
//  prompt the user for a filename, and if lParam is non-NULL, will
//  return it in lParam (allocate at least 128 characters). All decoding
//  of the message is performed automatically, including MIME translations.
#define WM_F_EXTRACTATTACHMENT   (WM_F_FORMBASE + 48)


//
// +--------------------------------------------------------------------+
// |  Section 5:                                                        |
// |  Logging messages                                                  |
// +--------------------------------------------------------------------+
//
// Extensions can indicate an interest in logging events by setting the
// WPM_LOGGING bit in the flags field of their form fact file. An extension
// which has set the logging bit will receive messages from WinPMail about
// a number of events which can occur in a user session, including mail
// being sent, files being created and deleted, and so on.
//
// Logging extensions can also inhibit certain events from happening by
// returning WPM_PROHIBIT instead of 0; note that if an extension prohibits
// an action, it is up to the extension to indicate an error message or
// warning explaining to the user why it has done so (if appropriate) -
// WinPMail will not do so.
//
// There are no limitations on what a logging extension can do, although
// in almost every case they will set the WPM_STARTUP bit to load at
// runtime. Logging extensions may generate mail messages at any time.
//

//  WinPMail generates this message when the user sends a mail message,
//  before any actual processing is done on the message itself. When a
//  logging extension receives this message, it can call 
//  WM_F_GETMESSAGEFIELD as shown below to retrieve message fields 
//  until the time it returns. A logging extension can prohibit sending a
//  message by returning WPM_PROHIBIT when it receives this message.
#define WM_FM_SENDMAIL           (WM_FM_FORMBASE + 8)

//  WinPMail generates this message to cover a variety of system
//  events. In most cases, returning WPM_PROHIBIT will prevent the
//  action from occurring.
//  ** PARAMETERS: wParam = event type; lParam = string descriptor
//    wParam can have the following values:
//                      wParam      lParam                            Prohibit?
#define WLOG_OPEN_FILE    1     //  Filename of book to be opened         Y
#define WLOG_DEL_FILE     2     //  "   "   "   "   "   be deleted        Y
#define WLOG_NEW_FILE     3     //  Unused                                Y
#define WLOG_REN_FILE     4     //  Old filename of book to be renamed    Y
#define WLOG_OPEN_FOLDER  5     //  Path to folder to be opened           Y
#define WLOG_DEL_FOLDER   6     //  "   "   "   "   "   be deleted        Y
#define WLOG_NEW_FOLDER   7     //  Unused                                Y
#define WLOG_REN_FOLDER   8     //  Old filename of folder to be renamed  Y
#define WLOG_EDIT_FILE    9     //  Filename of dlist to be edited        Y
#define WLOG_ACTIVATE     10    //  1=activating, 0=minimizing            Y
//  WLOG_NEWMESSAGE is sent before the window is actually
//  created and displayed; WLOG_NEWMESSAGE1 is sent after the
//  window has been completely created.
#define WLOG_NEWMESSAGE   11    //  Unused                                Y
#define WLOG_NEWMESSAGE2  12    //  HWND of new message                   N
//  WLOG_ENTERPREFS is called before entering any of the preferences
//  dialogs in WinPMail, using one of the following values in lParam
enum
   {
   WPREF_GENERAL, WPREF_ADVANCED, WPREF_SMF, WPREF_HOMEBOX,
   WPREF_EXTENDED, WPREF_SIGS, WPREF_BPANEL, WPREF_NETCONFIG
   };
#define WLOG_ENTERPREFS    13   //  Code from list above                  Y
//  WLOG_GETMAIL is sent prior to downloading mail via POP3
#define WLOG_GETMAIL       14   //  Unused                                Y
//  WLOG_SMTPSEND is sent before opening an outgoing SMTP connection
#define WLOG_SMTPSEND      15   //  Unused                                Y
//  WLOG_NEWEXTENSION is sent before an extension is loaded
#define WLOG_NEWEXTENSION  16   //  Path to extension file                Y
#define WLOG_ERROR         17   //  Integer - ID of error message         Y
#define WLOG_WARNING       18   //  Integer - ID of warning message       Y
//  WLOG_LOADEXTENSION is sent AFTER an extension has been loaded
#define WLOG_LOADEXTENSION 19   //  HWND - window containing new form     N
#define WLOG_OPENNEWMAIL   20   //  Unused
#define WLOG_PARSENEW      21   //  Path to new message file              Y
//
//  Detecting when menus are loaded: WLOG_LOADMENU is generated when an
//  MDI window in WinPMail loads a menu. The completed menu is passed to
//  the extension in an LMENU structure, and while the extension cannot
//  suppress the loading of the menu, it can modify the menu. Note that
//  each menu is a complete copy of the entire menu system, including
//  File, Edit, Addresses, and Window submenus as well as the specific
//  menu for the subwindow itself.
//
typedef struct
   {
   HMENU hMenu;
   int menu_id;
   } LMENU;
//  "menu_id" can have the following values:
//
#ifndef WINPMAIL
enum
   {
   MN_FRAME = 1,        //  Pegasus Mail's frame (main window) menu
   MN_EDMAIL,           //  Message editor menu ("Message")
   MN_READER,           //  Message reader menu ("Reader")
   MN_BROWSE,           //  Folder browser menu ("Folder")
   MN_DLIST,            //  DList editor menu (no specific menu entry)
   MN_ADDRBOOK,         //  Addressbook menu ("Addressbook")
   MN_FOLMAN,           //  Floating Folder Manager menu ("Folders")
   MN_FORMS,            //  Extensions Manager menu (no specific entry)
   MN_NB                //  Noticeboards menu.
   };
#endif
//
#define WLOG_LOADMENU      22   //  Pointer to LMENU structure (above)    N
#define WLOG_SENDERROR     23   //  Locus of delivery failure             N
//  Indicates that a new mail filtering rule has been triggered
//  for application to a message. lParam points to the following
//  structure:
typedef struct
   {
   int action;
   char *param;
   void *imessage;
   int fol_id;
   } RULE_EVENT;
#define WLOG_APPLYRULE     24   //  Pointer to RULE_EVENT structure       Y

#define WM_FM_LOGEVENT           (WM_FM_FORMBASE + 9)


//  Retrieve a field from a message. This message can only be sent
//  after a logging extension receives a WM_FM_SENDMAIL message but
//  before it returns from processing it.
//  ** PARAMETERS: wParam = field of interest
//  ** RETURNS:    pointer to data in every case.
//
//  wParam can be set to the following values:
//      wParam value:          type      pointer to
#define WMSG_TO       1    //  string    raw to: data
#define WMSG_SUBJECT  2    //  string    subject: field
#define WMSG_CC       3    //  string    cc: field
#define WMSG_BCC      4    //  string    bcc: field
#define WMSG_REPLYTO  5    //  string    reply-to: field
#define WMSG_DATA     6    //  string    message, NULL if file.
#define WMSG_FILE     7    //  string    filename, NULL if data
#define WMSG_ENCRYPT  8    //  char      NZ if encrypted, Z if not
#define WMSG_COPYSELF 9    //  char      NZ if copying to self
#define WMSG_READING  10   //  char      NZ if reading confirm required
#define WMSG_DELIVERY 11   //  char      NZ if delivery confirm required
#define WMSG_URGENT   12   //  char      NZ if urgent
#define WMSG_NOSIG    13   //  char      NZ if no signature to be attached
#define WMSG_EXPIRES  14   //  byte [7]  expiration, NetWare date format
#define WMSG_KEY      15   //  string    encryption key
//
//  Note that the returned value is ALWAYS a pointer, which allows a
//  logging extension to change message field values before they are
//  sent. Extensions are discouraged from modifying fields casually -
//  fields should only be changed when you are sure of what you are
//  doing.
#define WM_F_GETMESSAGEFIELD     (WM_F_FORMBASE + 50)


//
// +--------------------------------------------------------------------+
// |  Section 6:                                                        |
// |  File system, message store and informational services             |
// +--------------------------------------------------------------------+
//
// Extensions can access the user's message store and also have access
// to a great deal of the internal system information WinPMail maintains.
//

//  Get the full path to the user's new mail folder.
//  lParam points to a buffer into which the path should be copied,
//  and wParam is the maximum length of the string to copy, including
//  the terminating nul. You should allocate at least 128 characters.
//  The string returned is a full path normalized to "\" separators
//  and does not have a trailing "\" character.
//  ** Note: do NOT assume that this is a DOS path: it may just as
//  well be supplied in UNC or NetWare formats depending on the system.
//  ** PARAMETERS: wParam = max length; lParam = pointer to buffer
//  ** RETURNS:    Nothing
#define WM_F_GETNEWMAILBOX       (WM_F_FORMBASE + 21)

//  Get the full path to the user's home mailbox directory.
//  lParam points to a buffer into which the path should be copied,
//  and wParam is the maximum length of the string to copy, including
//  the terminating nul. You should allocate at least 128 characters.
//  The string returned is a full path normalized to "\" separators
//  and does not have a trailing "\" character.
//  ** PARAMETERS: wParam = max length; lParam = pointer to buffer
//  ** RETURNS:    Nothing
//  ** Note: do NOT assume that this is a DOS path: it may just as
//  well be supplied in UNC or NetWare formats depending on the system.
#define WM_F_GETHOMEBOX          (WM_F_FORMBASE + 22)

//  Get the full path to the recommended temporary files directory.
//  lParam points to a buffer into which the path should be copied,
//  and wParam is the maximum length of the string to copy, including
//  the terminating nul. You should allocate at least 128 characters.
//  The string returned is a full path normalized to "\" separators
//  and does not have a trailing "\" character.
//  ** PARAMETERS: wParam = max length; lParam = pointer to buffer
//  ** RETURNS:    Nothing
#define WM_F_GETTEMPDIR          (WM_F_FORMBASE + 23)

//  Get the full path to the directory from which WINPMAIL.EXE was
//  run. lParam points to a buffer into which the path should be
//  copied and wParam is the maximum length of the string to copy,
//  including the terminating nul. You should allocate at least 128
//  characters. The string returned is a full path in DOS format
//  and does not have a trailing "\" character.
#define WM_F_GETBASEDIR          (WM_F_FORMBASE + 65)

//  Get the fully-qualified path name of a temporary file which
//  is guaranteed not to exist, and to be writable. wParam contains
//  the maximum length allocated for the filename including the
//  terminating Nul, while lParam points to the location where the
//  filename should be written.
//  ** PARAMETERS: wParam = max length; lParam = pointer to buffer
//  ** RETURNS:    Nothing
#define WM_F_TEMPFILE            (WM_F_FORMBASE + 24)

//  Get the number of new mail messages currently in the user's
//  new mail box. If wParam is 0, WinPMail returns the value from the
//  last periodic scan it made; if wParam is non-zero, WinPMail is
//  forced to rescan the new mail box immediately - depending on
//  the number of messages already in the new mail box, this may
//  result in a considerable impact on system performance. Returns
//  the number of messages.
//  ** PARAMETERS: wParam = (see above); lParam = unused
//  ** RETURNS:    Total number of new messages in mailbox
#define WM_F_NEWMAIL             (WM_F_FORMBASE + 28)

//  Prompt the user to select a WinPMail file. The standard WinPMail
//  selector dialog is opened and control is not returned until the
//  user either selects an item or cancels it.
//  ** PARAMETERS: 
//     wParam can have the following values:
//        0 - select a folder
//        1 - select an address book
//        2 - select a distribution list
//        3 - select a message draft
//     lParam = points to a char buffer at least 128 characters long
//        - the buffer is filled with the full path name to the selected
//          file. For address books, the .PMR file is returned. For
//          folders, the .PMM file is returned.
//  ** RETURNS: 1 if the user selected an item, 0 for no selection.
#define WM_F_SELECTOR            (WM_F_FORMBASE + 39)

//  Open one of the standard Pegasus Mail file types. lParam must point
//  to the full path to the file (as returned by WM_F_SELECTOR), and
//  wParam must be set to:
//        0 - File is a mail folder
//        1 - File is an address book
//        2 - File is a distribution list
//        3 - File is a message draft
//        4 - File is a message queued for delivery
//      255 - No file - simply start a new message
//  Note that for Folders you must pass the path to the folder's PMM
//  file, and for Addressbooks to the book's .PMR file. The extensions
//  for the various types of files are:
//     Folders            - .PMM
//     Addressbooks       - .PMR
//     Distribution lists - .PML
//     Message drafts     - .PMO
//     Queued mail        - .PMW
//  ** PARAMETERS: wParam (see above); lParam = file to open.
//  ** RETURNS:    hWnd of newly-opened MDI window, NULL on failure.
#define WM_F_OPENFILE            (WM_F_FORMBASE + 66)

//  Preferences services. Get or set the value of an entry in the
//  user's preferences (PMAIL.INI) file. Examine the file WPMPREFS.H
//  for documentation on the possible values you can pass in these
//  calls.
//  ** PARAMETERS:
//     - WM_F_SETPREF: wParam = item to set; lParam = value
//     - WM_F_GETPREF: wParam = item to get; lParam = buffer pointer
//  ** RETURNS:
//     - WM_F_SETPREF: Nothing
//     - WM_F_GETPREF: Value (for scalar types).
#define WM_F_GETPREF             (WM_F_FORMBASE + 40)
#define WM_F_SETPREF             (WM_F_FORMBASE + 41)

//  Get the name of the user at the current workstation. wParam can
//  have the following values:
//    0: return the basic username (login name under NetWare)
//    1: return the user's name as a full Internet address
//    2: return the user's name as an MHS address
//  lParam should point to a buffer at least 256 characters in length.
//  ** PARAMETERS: wParam = (see above); lParam = pointer to buffer
//  ** RETURNS:    1 on success; 0 if the address form is unavailable.
#define WM_F_GETUSERNAME         (WM_F_FORMBASE + 58)


//
// +--------------------------------------------------------------------+
// |  Section 7:                                                        |
// |  Miscellaneous services                                            |
// +--------------------------------------------------------------------+
//

//  Return the current date and time in NetWare format - ie, an
//  array of seven bytes arranged as follows:
//
//     Byte 0  - Year modulus 100 (if less than 80 assume 20xx)
//     Byte 1  - Month - 1 (ie, January == 0)
//     Byte 2  - Day (1 .. 31)
//     Byte 3  - Hour (0 - 24)
//     Byte 4  - Minute (0 - 59)
//     Byte 5  - Second (0 - 60)
//     Byte 6  - Day of week (Sunday == 0)
//
//  The function returns a correctly-formatted value whether or not
//  you are actually attached to a NetWare system, and deals correctly
//  with shell problems under Windows Standard mode which can result
//  in NetWare returning garbage times. Where possible, this function
//  gets the time from the file server instead of from the local
//  workstation.
//  ** PARAMETERS: wParam = unused; lParam = pointer to 7-byte buffer area
//  ** RETURNS:    Nothing
#define WM_F_GETDATETIME         (WM_F_FORMBASE + 25)

//  Return a date and time string in legal RFC822 format. You can
//  either set lParam to point to a 7-byte structure as described in
//  WM_F_GETDATETIME above, or else you can set lParam to 0 to get
//  a legal RFC822 representation of the current time. The return
//  from this message is a pointer to a static buffer in memory
//  containing the formatted string. You must NEVER directly alter
//  this buffer or you may crash WinPMail. The buffer is overwritten
//  on each call, and may be overwritten indirectly by other internal
//  WinPMail routines, so if you do not intend to use this string
//  immediately, you would be well advised to copy it to a local buffer.
//  ** PARAMETERS: wParam = unused; lParam = (optional) 7-byte date structure
//  ** RETURNS:    Read-only far pointer to character array containing date.
#define WM_F_GETRFC822DATETIME   (WM_F_FORMBASE + 26)

//  Reduce an e-mail address to its minimum form, by removing any
//  Ctext or Qtext components - so, the address
//      "David Harris" <david@pmail.gen.nz> (Pegasus Mail Author)
//  would be reduced to
//       david@pmail.gen.nz
//  lParam should point to the raw address, which is overwritten with
//  the reduced form. The returned value is guaranteed never to be
//  longer than the value passed in.
//  ** PARAMETERS: wParam = unused; lParam = raw address data
//  ** RETURNS:    -1 on invalid address (unbalanced '()' or '<>' pairs)
//  ** Note: this function works equally well for both RFC822 and
//  MHS addresses, but you should be aware that comments in '()' pairs
//  are sometimes significant to some MHS gateways.
#define WM_F_PARSEADDRESS        (WM_F_FORMBASE + 27)

//  Allocate memory in WinPMail's heap. This call is specialised and
//  is generally not needed. wParam contains the number of bytes to
//  allocate; the return value is NULL on failure, or a pointer on
//  success. Note that memory obtained this way must ONLY be freed
//  using the WM_F_FREE message.
//  ** PARAMETERS: wParam = bytes to allocate; lParam = unused
//  ** RETURNS:    Pointer, or NULL on failure
#define WM_F_MALLOC              (WM_F_FORMBASE + 30)

//  Free a block of memory obtained using WM_F_MALLOC
//  ** PARAMETERS: wParam = unused; lParam = pointer returned by WM_F_MALLOC
//  ** RETURNS:    Nothing
#define WM_F_FREE                (WM_F_FORMBASE + 31)

//  A handy function to retrieve the text from a standard Windows
//  edit control in a format ready to be dumped to a file or passed
//  to WinPMail for delivery; pass the ID of the control in the
//  current dialog in wParam and WinPMail will return the text from
//  that control, properly formatted, with all carriage returns
//  stripped (ie, as a C string). The pointer returned is allocated
//  using the WM_F_MALLOC message and must be freed using WM_F_FREE.
//  ** PARAMETERS: wParam = edit control ID; lParam = unused
//  ** RETURNS:    Pointer to formatted textual data or NULL on failure
#define WM_F_GETTEXT             (WM_F_FORMBASE + 32)

//  Change the active dialog in the window. This function is needed
//  if your DLL can produce more than one dialog in the MDI child
//  window and can change between them (presumably in response to
//  user input, much like the WinPMail message editor dialog). When
//  the dialog active in the window changes and the window is in the
//  foreground, you should call this function to ensure that WinPMail
//  directs messages to the correct dialog. Pass the address of the
//  new dialog in lParam.
//  ** PARAMETERS: wParam = unused; lParam = HWND of new dialog
//  ** RETURNS:    Nothing
#define WM_F_SETDIALOG           (WM_F_FORMBASE + 33)

//  Set text on the statusline. Four text areas can be set on the
//  statusline:
//     0: The basic text area at the left-hand end of the bar
//     1: The text in the username/server panel of the bar
//     2: The text in the newmail panel of the bar
//     3: A double-size text area overlaid over 0 and 1
//  You can also reset the statusbar by setting wParam to 0 and
//  passing a pointer to a NULL string
//  ** PARAMETERS: wParam = panel to set; lParam = text to set
//  ** RETURNS:    Nothing.
#define WM_F_SETSTATUS           (WM_F_FORMBASE + 51)

//  Paste an arbitrary string of data into the last active control
//  (which will almost always be one of the addressing Edit fields).
//  Using this call allows you to duplicate the behaviour of the
//  WinPMail local user list or address books when the user clicks
//  the "paste" button. If wParam is non-zero, WinPMail will add a
//  newline (CRLF) to the data if the target control is capable of
//  supporting multiple lines; this is a handy way of allowing the
//  user to paste your data either into single address fields or into
//  distribution lists without you having to be worried about the
//  distinction. If wParam is zero, the data will be pasted as-is.
//  ** PARAMETERS: wParam = see above; lParam = (char *) text to paste
//  ** RETURNS:    0 if no pasting was possible, 1 on success.
#define WM_F_PASTEDATA           (WM_F_FORMBASE + 54)

//  Get a core WinPMail window. This function allows you to obtain
//  the HWND for either the WinPMail Frame window (the main application
//  window itself) or the MDI Client window maintained inside it. This
//  function is extremely specialised and is really only useful if you
//  are brave enough to want to enumerate the program's child windows
//  (possibly to send them all messages or to find all windows of a
//  particular type). You should avoid using this message if you can,
//  since it may impair the portability of your extension. WinPMail's
//  author offers no guarantee that windows will retain the same class
//  names or other information throughout the life of the program.
//  wParam can have the following values for this call:
//     0 - return the WinPMail main frame window
//     1 - return the WinPMail MDI client window
//     2 - return the currently active MDI child window
//     3 - return the dialog contained in the currently active MDI window
//     4 - return the toolbar window (note - ONLY if currently a toolbar)
//  ** PARAMETERS: wParam = see above; lParam = unused.
//  ** RETURNS:    The HWND for the specified window.
#define WM_F_GETWINDOW           (WM_F_FORMBASE + 57)

//  Get a core WinPMail menu. This function lets you retrieve any
//  of the menu handles associated with each type of WinPMail MDI
//  window. wParam should contain one of the MN_* selector values
//  defined for the WLOG_LOADMENU logging event (above). The return
//  value is the menu handle for that window, which may be NULL if
//  no instance of that type of window has been opened yet.
//  ** PARAMETERS: wParam = MN_* selector value; lParam = unused
//  ** RETURNS:    menu handle (may be NULL)
#define WM_F_GETMENU             (WM_F_FORMBASE + 63)

//  Load and execute a new extension. lParam must point to an instance
//  of the following parameter block:
typedef struct
   {
   char dll_path [128];
   int variant;
   char commandline [128];
   char title [64];
   unsigned int flags;
   } FORM_PARAM;
//
//  "dll_name" is the fully-qualified path to the DLL containing the
//     extension's executable code. It may contain valid command
//     substitutions (such as ~a for the Pegasus Mail base directory).
//  "variant" is 0 for a Composer extension, or 1 for a Reader extension.
//     Note that until advised in future, only Composer extensions can
//     be loaded with this call.
//  "commandline" is whatever parameters should be passed to the extension
//     at startup.
//  "title" is the title of the new extension's enclosing MDI window
//  "flags" is a bitmap comprised of the following values:
//     WPM_HIDDEN    4      Hide the parent MDI window on loading
//     WPM_LOGGING   8      Extension wants to receive logging events
//     WPM_ONEONLY   16     Only allow one running instance at any time
//
//  ** PARAMETERS: wParam = unused; lParam = pointer to FORM_PARAM
//  ** RETURNS:    HWND of new extension's MDI window or NULL on failure
#define WM_F_LOADEXTENSION       (WM_F_FORMBASE + 64)

