README.TXT
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.