Spooler Callbacks - Microsoft Windows Messaging Subsystem Transport Service Provider Interface mapi version 0

Spooler Callbacks
When the transport provider is initialized, the Spooler passes in to the transport provider a jump table with the addresses of routines in the Spooler. These routines may be called by the transport provider. The layout of the jump table is TBD.
SpoolerYield()
The SpoolerYield() call indicates to the Spooler that the transport provider is doing a long operation and is at a good point to be interrupted. The Spooler will perform maintenance tasks and yield back to the system. This allows foreground applications to run in the midst of long operations performed by the transport provider.
ulResult = SpoolerYield([in] ulFlags)
ULONG ulFlags Flag word. Reserved for future use. Must be zero.
The Spooler may detect, during the processing of this call, a number of conditions which it will signal to the transport provider in the result code:
MAPI_W_CANCEL_SEND The user wants to abort the sending of an outgoing message, regardless of how many recipients might already have received it. The transport provider should clean up any current operations and return to the Spooler. The transport provider can expect an EndMessage() call with a cancel parameter as its next call.
SpoolerAllocate()
The SpoolerAllocate() call allocates a memory buffer in the Spooler's memory space.
ulResult = SpoolerAllocate([in] ulSize, [out] lppvData)
ULONG ulSize Size (in bytes) of the memory to be allocated.
LPVOID * lppvData Address of variable in which the pointer to the allocated memory will be placed.
The Spooler will allocate a memory buffer, starting on an address that is a multiple of 4, and return its address to the transport provider.
This call is commonly used by transport providers to allocate a memory buffer that will be later be freed up by the Spooler. It may also be used for allocating internal memory for the transport provider's own use, in which case the transport provider should eventually release the memory with SpoolerFree().
SpoolerAllocateMore()
The SpoolerAllocateMore() call allocates a memory buffer in the Spooler's memory space. The new memory buffer is linked to an existing one. The new one is not freed by itself, but only in conjunction with freeing the original buffer.
ulResult = SpoolerAllocateMore([in] ulSize, [in] lpvOriginal, [out] lppvData)
ULONG ulSize Size (in bytes) of the memory to be allocated.
LPVOID lpvOriginal Pointer to original buffer that the new one should be linked to.
LPVOID * lppvData Address of variable in which the pointer to the newly allocated memory will be placed.
The Spooler will allocate a memory buffer, starting on an address that is a multiple of 4, and return its address to the transport provider. The Spooler will link the newly allocated buffer buffer internally to the original buffer, and free both when the original buffer is freed.
This call is commonly used by transport providers to make a guess as to how much memory it needs to return a structure, and then find out later that they need a bit more.
SpoolerFree()
The SpoolerAllocate() call releases a memory buffer in the Spooler's memory space.
ulResult = SpoolerFree([in] lpvData)
LPVOID lpvData Address of buffer which should be freed.
This call releases a memory buffer that has been allocated in the Spooler's memory space. If additional buffers have been linked to this one they are freed as well.
SpoolerNotify()
The SpoolerNotify() call informs the spooler of an important event in the life of the transport..
ulResult = SpoolerNotify([in] ulFlags)
ULONG ulFlags Flags, see below.
This call can be made any time by the transport provider.
The bits in ulFlags are defined as:
NOTIFY_NEWMAIL The transport provider has new incoming mail which it would like the Spooler to ask for pretty soon.
Transport SPI
The transport SPI specification defines calls that the Spooler makes to a transport provider. Transport providers implement these routines in a DLL. The only direct entry point in the DLL is for the InitTransport() call. All other routines are called via a jump table returned on the InitTransport call.
The Spooler passes a jump table to the transport provider for callback routines. These are routines in the Spooler which the transport provider may call.
Initialization InitTransport()
ulResult = InitTransport([in] aCallBacks, [in] ulFlags,
[in] ulSpoolerVer, [out] lpulTransportVer,
[out] lpulCharsetCode, [out] lpaEntryPoints)
LPFARPROC lpaCallBacks Address of an array containing the jump table for callback functions within the Spooler. This array will remain valid until the DeinitTransport() function is called.
ULONG ulFlags Flags. For future use. May be ignored for now.
ULONG ulSpoolerVer Identifies the version of the Transport SPI used by the spooler.
ULONG * lpulTransportVer Address of ULONG in which the transport should return the version number of the Transport SPI it supports.
ULONG * lpulCharsetCode Address of ULONG in which the transport should return its desired character set translation code.
LPFARPROC * lpaEntryPoints Address of a variable in which the transport should return a pointer to a jump table with its entry point addresses. The jump table should remain valid until the DeinitTransport() call is made. The values within the table should not be changed during operations.
This call gives the transport DLL a chance to set itself up. It will precede any other SPI calls. The call allows spooler and transport to exchange version numbers.
The SPI version number checking is designed to allow the SPI to expand to meet future requirements while still allowing as much compatibility as possible between software made by different companies at different times. The burden of compatibility checking is placed on the software with the higher version number, as it is the one that know the capabilities of both versions.
If the transport provider's version of the SPI is the same or lower than the version of the SPI that the Spooler passes in, it should initialize itself and return SUCCESS_SUCCESS.
If the transport provider's number is higher and it is capable of working with this Spooler it should return SUCCESS_SUCCESS. If, however, the transport requires a higher version of the SPI than the Spooler uses, it should not initialize itself and should return the error code MAPI_E_VERSION.
If the transport provider returns a lower number to the Spooler than the SPI version the Spooler uses, the Spooler has a choice of limiting itself to the version the transport uses or generating an error itself. If it generates an error it will DeinitTransport() the transport DLL.
The character set translation code indicates what character set the transport would like all strings to be presented to it. This code affects all property value strings. It does not affect property names, which are always in UNICODE. Valid Character Set codes include:
0 UNICODE
1 ANSI
850 CP-850
The transport provider should not call any of the callback functions during this call, as the Spooler does not yet know the version number of the transport provider.
DeinitTransport()
ulResult = DeinitTransport([in] ulFlags)
ULONG ulFlags Flag word. See below.
The transport should release all its resources. If it has allocated any memory with SpoolerAllocate() it should free the memory.
The transport provider should be prepared to accept this call at any time between other calls.
Bits in ulFlags indicate:
DEINIT_NORMAL The transport provider may take time to log off of network resources, hang up phone lines, and other actions that take long enough to require callbacks to SpoolerYield().
DEINIT_HURRY Sorry, its an emergency. Take no time at all.
AddressTypes()
This call allows the transport provider to indicate to the Spooler what types of Email-Addresses it can handle. With multiple transport providers installed the Spooler does rudamentary routing to determine which providers should handle which recipients. This message splitting is based on a prefix string match on the Email-Address string.
ulResult = AddressTypes([in] ulFlags, [out] lppPrefixArray)
ULONG ulFlags Flags. For future use. May be ignored for now.
LPSTR ** lppPrefixArray Address of variable in which the transport provider will place a pointer to an array of string pointers.
The transport provider should return a pointer to an array of string pointers. The Spooler will use each of the strings in a comparison test when deciding which transport should handle which recipients of an outbound message. The transport providers are installed with a priority order indicated, in the event multiple transport providers can handle the same type of recipient.
The prefix string will commonly include up to and including the ":" in the Email-Address (see MAPI document for details). For example: "FAX:", "MacMail:", and "SNADS:" would be common.
This call will commonly be made after the transport provider is initialized and before login occurs.
A transport provider which wants to handle any type of recipient may return NIL in *ppPrefixArray. LAN-based email systems that support a variety of gateways will commonly do this. Such a transport should be installed last in the priority order of transports.
The memory used for the prefix array structure should remain in memory till the DeinitTransport() call is performed, at which time the transport provider can free the memory if it wishes.
TransportLogin()
This function establishes a login session for a particular user with the transport provider. The transport provider is allowed to present dialog boxes as needed to establish the session. At the provider's request, the Message Spooler can remember information about the login session (credentials) to be passed in the next time.
ulResult = TransportLogin([in] lpszLocalUserName,
[in/out] lpcbSysData, [in/out] lppSysData,
[in/out] lppszUserName, [in/out] lppszUserPassword,
[in/out] lpulFlags, [out] lpulLoginHandle)
LPSTR lpszLocalUserName String with the local name of the user. Typically this is used in error dialogs by transports that allow multiple logins. Some transport providers will also remember this to use as the "Display-Name" for the user.
ULONG * lpcbSysData Address of count of data bytes in *ppSysData. Passed in and out.
LPBYTE * lppSysData Provider-specific binary data passed in and out.
LPSTR * lpszUserName Address of variable pointing to a string containing the name of this user on this transport. Passed in and out.
LPSTR * lpszUserPassword Address of variable pointing to a string containing the password of this user on this transport.
ULONG * lpulFlags Flags. Passed in and out.
ULONG * lpulLoginHandle Opaque handle assigned by the transport provider for this login session.
This call deals with three pieces of data. The SysData binary information is typically used by the transport to remember the network location of a server, but can really be used for anything the transport wants. As binary data, any information can be remembered here. (In fact, the user's name and password could be stored encrypted in this data if the transport provider chooses to do so.) Some transports will let the user decide whether to retain credentials, in which case the state of the Login checkbox "Remember password" can be stored in this binary data. Transport provider implementers that anticipate future revisions to their provider will also store a version number within the binary data to indicate what format the binary data is in.
The UserName and UserPassword fields may be used by the transport provider to have the Spooler remember name & password information.
In all cases, the Spooler will pass in at login time whatever values it remembers from the last login. The transport provider can use the information and log in silently to the underlying messaging system, or can present any dialogs it wishes to establish the connection. Commonly dialogs will be presented if any of the remembered values are no longer valid and the transport provider wants the user to reselect the server or enter corrected name or password. Dialogs might also be presented if a password were about to expire, for example.
If there is no remembered information, the Spooler will pass in zero-length binary data or zero-length strings. It will remember whatever information is passed back. If the transport provider does not want to change part of the remembered information it can leave the fields unchanged or can set the appropriate pointers to NIL.
If the transport provider wants to remember different data it should pass back valid pointers to appropriate data (zero-length or longer). For each local user the Spooler will remember a set of transport-specific information for each installed transport provider. If a transport provider establishes multiple network connections it is its own responsibility to package whatever information it needs to retain in the binary portion of the remembered data.
The transport provider allocates memory it passes back by calling the SpoolerAllocate() callback routine. The Spooler will free any buffers passed back. The transport provider should not change the data in the buffers passed in by the Spooler.
The *lpulFlags variable is passed in with the following bits:
LOGIN_SETUP A setup program has indicated that the login dialog should be presented even if the credentials are correct. This typically is used at initial setup before any data is remembered and when the user wants to change a remembered server selection or password.
LOGIN_CHANGED The user's local password was cleared or changed by an administrative override program. The transport provider is invited to ask the user to revalidate his credentials for better security.
LOGIN_NO_DIALOG A background program indicates that no dialog should be put up even if the credentials are invalid or are insufficient for login. An error should be returned instead.
LOGIN_OVERRIDE The credential set presented has been specified by a program instead of by what the transport provider saved previously. Commonly used in conjunction with LOGIN_NO_DIALOG by background mail applications. If the credential set is invalid the transport provider is invited to take whatever actions it wishes to discourage programmatic guessing of passwords. (Delaying based on the frequency of bad credentials is suggested.)
The *lpulFlags variable is passed back with the following bits:
LOGIN_SP_PROMPT If set, the name and/or password is invalid and the transport provider wants the Spooler to prompt for corrected name/password. This is provided as a convenience for transport providers satisfied with the default dialog.
LOGIN_SP_IDLE If set, the Spooler will frequently call the Idle() routine of the transport provider
LOGIN_SP_POLL If set, the Spooler will frequently poll the transport provider to check for new mail
If login is successful, the transport provider should return a ULONG with an (opaque) 32-bit handle to the session. This can be any value the transport provider wants, but is typically an internal pointer to a data area where the transport provider maintains session information. The Spooler will pass this handle back in on subsequent calls.
TransportLogoff()
This function terminates a session with the transport for a particular user.
ulResult = TransportLogoff([in] ulLoginHandle, [in] ulFlags)
ULONG ulLoginHandle 32-bit opaque handle assigned by the transport provider for this login session.
ULONG ulFlags Flags. For future use. May be ignored for now.
Idle()
ulResult = Idle([in] ulLoginHandle, [in] ulFlags)
ULONG ulLoginHandle 32-bit opaque handle assigned by the transport provider for this login session.
ULONG ulFlags Flags. For future use. May be ignored for now.
If requested on the TransportLogin() call, the Spooler will repeated call the transport provider's Idle() routine at system idle time.
|