home *** CD-ROM | disk | FTP | other *** search
- WINDS Remote Transport
-
-
- SUMMARY
- =======
-
- The Remote.Xp sample is a remote transport provider (XPWDSR) implemented
- in C++. This transport demonstrates the following extended MAPI features:
-
- - Support for the REMOTE interface for slow-link connection to a remote host.
- This includes implementation of the IMAPIFolder methods needed to interact
- with a client remote viewer application.
- - Support for deferred delivery mechanism for scheduled message submission to
- a remote host at a user-settable upload time.
- - Support for forced immediate connection and submission (using the
- FlushQueues method implemented in the IMAPIStatus object) in response to
- Deliver Mail Now and Transfer Mail in the Microsoft Exchange Client.
- - How to implement server-based messaging.
- - Real-world working mail transport which sends messages to a Windows NT
- workstation or server running the Windows Developer Support (WINDS) Sample
- Server Messaging Host included with this and other MAPI samples.
- - Use of the Transport Neutral Encapsulation Format (TNEF) interface to
- encapsulate ALL the message properties.
- - How to implement the IMAPIStatus interface for client access to transport
- status.
- - Multithread safe.
- - Configuration dialogs.
- - Generation of delivery and non-delivery reports.
- - Support for the profile Wizard for interactive profile configuration.
- - Support for the WINDS address type.
- - Support for background download and FlushQueues spooler interaction for
- spooler-marshalled remote connections.
- - Single binary file for Windows NT and Windows 95.
-
- MORE INFORMATION
- ================
-
- This program requires:
-
- Windows NT 3.51 (or later) or Windows 95,
- The MAPI 1.0 SDK included in the Win32 SDK,
- Microsoft Visual C++ version 2.1 (or later.)
-
- Optionally, the Win32 SDK tools with the MIDL compiler.
-
- This sample uses RPCs over named pipes to establish connections with the
- remote server. For convenience to customers without the full Win32 SDK, we
- have provided the MIDL compiler-generated C and header files (WINDS.H,
- WINDS_S.C, and WINDS_C.C) along with the IDL and ACF files. If you make changes
- to the IDL or ACF, you'll NEED to recompile them using the MIDL compiler
- available only in the Win32 SDK and Visual C++ 4.0 and later.
-
- Building the Sample Code
- ------------------------
-
- The sample remote transport provider has only been compiled and tested under
- Windows NT 3.51 and Windows 95, there are no plans for a Windows 3.1x (16-bit)
- release of this sample.
-
- Users should update the project file dependencies as soon as the files are
- copied to your machine. Use the PROJECTS.UPDATE DEPENDENCIES options in the
- Visual C++ Developer Studio.
-
- This sample was developed using Microsoft Visual C++ 2.x. Its associated
- makefile is XPWDSR32.MAK. Traces can be enabled for Release builds by defining
- ENABLE_DEBUG_OUTPUT in the preprocessor symbols define in the project settings
- menu.
-
- A command-line compiler-independent MAKE file has been provided for users of
- command-line tools.
-
- Configuration
- -------------
-
- Use the MERGEINI.EXE utility from the MAPI PDK to merge this transport's
- message service INF file, XPWDSR.INF, with the MAPISVC.INF file:
-
- MERGEINI {full-path}\XPWDSR.INF -m -q
-
- for example:
-
- MERGEINI C:\SAMPLES\MAPI\XPWDSR\XPWDSR.INF -m -q
-
- You will then need to configure a profile that includes this transport. When
- you create a new profile, the Profile Wizard will detect this transport and set
- the initial properties through the wizard pages.
-
- XPWDSR has two property sheets for interactive configuration which are
- accessible through the service provider logon, through the ServiceEntry call
- and through the IMAPIStatus::SettingsDialog method. The sample also defines
- custom properties for the configuration options so they may be set and
- retrieved programmatically.
-
- User Account Configuration Page
- -------------------------------
-
- Server Name: This is the network UNC (Universal Naming Convention) name of
- the machine where the user account is. The server machine MUST be running the
- WINDS Sample Server Messaging Host application prior to the provider setup.
-
- Mailbox Name: The mailbox name is the name of the account on the remote server.
- To select a mailbox or change the current one, click on Browse and select a
- name from the list that will appear. Once selected, you will be asked to enter
- the password for the mailbox. For new mailboxes, the default password is
- PASSWORD. If the list of mailboxes is empty or you don't find the one for you,
- then a new account must be created on the server program. This field cannot be
- edited manually by the user.
-
- Full Name: This is the complete name of the owner of the mailbox selected. This
- field is updated automatically when a new mailbox is selected. This information
- cannot be edited manually.
-
- Change Mailbox Password: Click on this button to change the password for this
- mailbox. You will be asked to type the old password, a new password, and then
- confirm the new password.
-
- Using Local Network (LAN): This is the option to use if the machine is directly
- hooked to on the network there is a connection to the server machine at all
- times. If this option is selected, when running, the provider will install
- notification links with the remote system allowing the provider to update
- internal data dynamically as the data changes on the server, and to react to
- changes or commands from the server.
-
- Remote - With Local Address Book Directory: This setting instructs the provider
- to adjust itself to use local data and to defer communication with the server
- until the user changes the connection mode. This mode is useful if the server
- or the clientmachine are not on a persistent connection link with each other.
- If this option is selected the provider will not know of changes that occur on
- the server to cached data.
-
- Message Transport Configuration Page
- ------------------------------------
-
- Automatic Remote Uploads At: The daily time when the transport will submit
- all the messages it has deferred. At this time it will connect to the server
- and submit all the messages in a batch. The time must be entered in the
- 24-hour format, i.e. 12:00 AM is 0:00. 10:30 PM is 22:30, etc.
-
- When Connected: If this option is selected, after the messages have been
- uploaded at the scheduled time, the transport will request to update the
- message headers.
-
- Note: Prior to installing this transport into a profile, the WINDS Sample
- Server Messaging Host should be running in the remote (or local) computer.
- See the readme file in the above sample for instructions on compiling,
- installing, and using it.
-
- Address Format
- --------------
-
- This transport supports the address type WINDS. When creating new one-off
- entries in an address book (i.e. the Personal Address Book), this is the
- value for the Address Type field. Email addresses for this transport look
- like this:
-
- \\server-name\mailbox-name
-
- The backslashes are literals, while the server-name and mailbox-name should
- be replaced with the server and mailbox name you wish to send to.
-
- Note: When typing one-off addresses in the Exchange client, you must double
- the backslashes, like this:
-
- [WINDS:\\\\myserver\\mymailbox]
-
- This is because the client treats the backslash as an escape character.
-
- Remote Access
- -------------
-
- The main difference between this transport and a non-remote transport is the
- ability to schedule mail transmission and to preview the header information
- of messages residing in a user's remote mailbox. Outgoing messages aren't
- transmitted at time of submission, but are queued by the spooler until the
- scheduled delivery time occurs. This is known as deferred submission. As long
- as the message is deferred, it stays in the user's local message store and the
- spooler retains responsibility. The spooler maintains an internal queue of
- deferred messages which it empties at the scheduled upload time, passing each
- message in sequence to the transport for delivery.
-
- Inbound messages stay in the user's mailbox on the remote server until
- explicitly downloaded. This transport supports the Remote Viewer semantics,
- where the user can request the transport to connect to the server and
- retrieve a table of mail headers of messages in the user's remote mailbox. The
- remote viewer lets the user mark those rows of the header table he wishes to
- download. Rows are marked for move, delete, or copy operations according to
- which operation the user wants to perform on the corresponding message.
- Downloads are started explicitly, not scheduled, since the user has to
- explicitly mark the rows of the table that are to be downloaded.
-
- The download table is a contents table of a MAPI folder that is returned by
- the IMAPIStatus object. This folder has no objects in it, but only exists to
- provide the contents table. When the user marks messages for download in the
- Remote Viewer, the corresponding row in the table has the PR_MSG_STATUS
- property set to a bitmask indicating the requested operation. To obtain the
- data for the header table, the transport makes an RPC to the server
- requesting the name of a named pipe. The server creates the pipe and
- returns the name. The transport then opens its end of the pipe and streams
- the actual data over it. This data is used to populate the contents table.
-
- Download Semantics
- ------------------
-
- A user request to start downloading marked messages causes the transport's
- IMAPIStatus::ValidateState method to be called with the
- PROCESS_XP_HEADER_CACHE flag passed. At this point the download table is
- walked and each marked entry is added to a list of messages to be
- downloaded. When the list has been constructed, an RPC is made to the server
- to obtain the name of a named pipe over which to stream the data.
-
- The transport opens the pipe and requests the first message in the to-download
- list. The transport uses a simple form of handshaking: control messages are
- passed first to tell the server what the operation is, ACK the request, and get
- the size of the following stream. Transmission errors can be reported in these
- messages also. An error causes the message-in-transit to be dropped and the
- next one started.
-
- When a message is downloaded, its storage is backed by a temporary file which
- is created on the fly to hold the incoming stream. When the message stream
- arrives successfully on the client side, its to-download list node is moved
- to a just-downloaded list. If the user logs off the session before the
- just-dowloaded list is processed, the downloaded file is kept in a to-do
- directory which will be processed in the next session logon.
-
- Processing the just-downloaded list occurs in the same manner as for a
- non-deferred message; each message is pumped through the spooler's
- StartMessage loop. The spooler is notified that new mail has arrived by
- setting the STATUS_INBOUND_FLUSH in the PR_STATUS_CODE bit in the status table
- row. This causes the spooler to start requesting messages from the XP (by
- calling StartMessage). We stream the message in from the temp file, decode the
- TNEF stream into the passed MAPI message object, remove the non-transmittable
- properties, set the transport computed properties, delete the temporary file,
- and remove that message's node from the just-downloaded list. When the list is
- empty, we signal the spooler to stop requesting incoming messages by clearing
- the STATUS_INBOUND_FLUSH bit and passing back the untouched message object in
- StartMessage.
-
- Upload Semantics
- ----------------
-
- Uploading messages works in a similar fashion except that we initiate the
- process based on the time of day. The user configuration specifies a daily
- upload time which is saved in the profile section. The XP can be in several
- states with respect to the upload operation. When the upload time arrives, the
- state changes from WAITING to PROCESSING_TIMER_EVENT.
-
- When a message is submitted by the user, SubmitMessage is called and the
- message is passed to us by the spooler. If our state is WAITING, we return
- without doing anything. In the subsequent call to EndMessage, we check the
- state and if we're WAITING, pass back END_DONT_RESEND. This signals the
- spooler to queue this message until later requested.
-
- A timer event is initialized on logon with the interval between the current
- time and the upload time. When the timer expires, the spooler is notified to
- start submitting the earlier deferred messages from its internal queue. We get
- called again at SubmitMessage and are passed each message that's dequeued.
- In SubmitMessage, we check our state, recognize that we're being called this
- time to send the message, take responsibility (PR_RESPONSIBILITY), and go ahead
- and deliver it. We also change our status to STATUS_OUTBOUND_FLUSH to signal
- the spooler to keep calling our SubmitMessage method as long as it's queue is
- not empty. In the subsequent EndMessage, we check our state, realize that a
- message has just been dequeued and sent, decrement our counter and pass back
- 0. When the spooler has dequeued the last message, it callls TranportNotify,
- passing NOTIFY_END_OUTBOUND_FLUSH and we change state back to WAITING.
-
- After the transport has finished uploading the messages at the scheduled time,
- we also request to get a new table of message headers on the server. This table
- is downloaded to the local file and if the remote viewer is displayed, the
- table of contents is refreshed.
-
- Aborting Message Delivery
- -------------------------
-
- Once deferred, a message can be aborted any time before the actual delivery.
- This happens if the user opens or deletes the message before it's sent. The
- XP gets called at TransportNotify with NOTIFY_ABORT_DEFERRED. The spooler
- will remove this message from its internal queue and we won't be called at
- SubmitMessage for it.
-
- Debug Traces and Asserts
- ------------------------
-
- This sample uses several output debug string functions in the Win32
- environment to avoid attaching the DLL to any debugger. By default, the trace
- messages are output to a debug terminal attached to COM1 with settings at
- 9600, N, 8, 1. The debug messages can also be written to a log file whose
- default location is C:\MAPILOG.TXT. The file TRACES.CPP defines some macros
- that can be easily modified for different communications settings, output port,
- and log file name. It also implements a macro (ASSERT) and function that test
- the validity of a given statement. If the assertion fails, the user/developer
- has the opportunity to break into the debugger at the exact point where the
- assertion occurred.
-
- The debug routines are found in the TRACES.CPP and TRACES.H files.
-
- To enable the TRACExx functions in the TRACES.CPP files, define the
- ENABLE_DEBUG_OUTPUT macro during compilation. These functions work in DEBUG or
- RELEASE builds. You can only enable/disable traces at compile time through
- ENABLE_DEBUG_OUTPUT. There is no run time switch to enable or disable the
- traces.
-
- TRACES.CPP implements an ASSERT macro which test a evaluates an expression
- expecting a TRUE result, i.e. ASSERT (expression) will interrupt execution if the expression is NOT TRUE (non-zero).
-
- The ASSERT macro informs the line and source code file name where the assertion
- failed and writes the result to a debug trace. The assert information is also
- written to the log file.
-
- Also the this file implements a variation of assert: ASSERTMSG (expression,
- user-message) which behaves identical to ASSERT except that is the assertion
- fails, the message string is printed along with the assertion line and file
- information.
-
- By default, if an assertion fails, a dialog will come up and interrupt
- execution until a selection is made to break into the debugger or ignore the
- assertion.
-