|
|
#ifndef _SERVERDLL_INC
#define _SERVERDLL_INC
#ifdef __cplusplus
extern "C" { #endif
/***************************************************************************
Name : lmi.h
Comment : Defines the Logical Modem Interface.
Created : 9/9/93
Author : Sharad Mathur
Contribs :
Changes : 12/29/93: Changed UINTS to WORDS 12/29/93: Put min length restriction on String in LMI_AddModem 12/29/93: Changed display string comments to remove "Fax Modem on" 12/29/93: Changed NetAuthenticateDll API 8/4/94 : Defined FAXERROR 8/4/94 : Changed capabilities to bits & added new ones 8/4/94 : Changed SERVERSTATE to be a bitfield 8/4/94 : Changed NetReportRecv & LMI_ReportSends to return DWORD counts. 8/4/94 : Changed enum's to #define's 8/4/94 : Changed LPSTR to LPTSTR, & added fUnicode. 9/23/94 : Added Poll request support - LMIPOLLREQUEST, POLLTYPE, wszPollRequest(LMISENDJOB), dwPollContext(LMIRECVSTATUS), POLL_REQUEST capability 9/23/94 : Added Custom msg options support LMI_SetCustomMsgOptions, wrgbCustomOptionsOffset(LMISENDJOB), CUSTOM_MSG_OPTIONS capability. 9/23/94 : Added 4 ext error codes to T30_DIALFAIL. 9/23/94 : Added lpatError to LMI_CheckProvider. 9/26/94 : Added NRR_COMMITTED_RECEIVE to LMI_ReportReceives 10/6/94 : Added ABOVE64K_STRUCTURES to caps, and made total size & struct offsets in LMISENDJOB DWORDS. 10/6/94 : Made all structs DWORDS aligned. 10/6/94 : Added User request fields to LMI_ReportSends 10/6/94 : Added user request flags to LMI_GetQueueFile 10/6/94 : Changed dwNumEntries in LMIQUEUEFILEHEADER to dword 10/6/94 : Updated AtWork address definition to include \@ & | 10/7/94 : Consolidated all unsupported dialchar codes. 10/17/94: Added NCUDIAL_BADDIALSTRING 10/17/94: Moved lpatClientName from LMI_InitProvider to LMI_InitLogicalModem 10/17/94: Added LMIERR_PROVIDER_BUSY
03/16/95 (kentse) The big reorg. changed from Srvrdll to LMI. (A large change). 04/05/95 (kentse) Completed the big rewrite.
***************************************************************************/
#define MAX_SERVERNAME_SIZE 32
#define MAX_SUBJECT_SIZE 128
typedef ATOM FAR* LPATOM; typedef UINT FAR* LPUINT;
//////////////////////// OVERVIEWS ///////////////////////////////////////
/****
@doc EXTERNAL SRVRDLL OVERVIEW
@topic Introduction to the Logical Modem Interface | The Logical Modem Interface (LMI) was developed to facilitate the easy creation of a fax service provider for a Microsoft Fax transport running on a PC. Microsoft Fax is supported in Windows 95 and will be supported in the shell update release of Windows NT 3.51. There is also support in Windows for Workgroups<tm> 3.11 (where Microsoft Fax was known as Microsoft At Work <tm>). A fax service provider written to the LMI will work on all these platforms. For this discussion of the LMI, no distinction is made between operating environments.
The Logical Modem Interface divides Microsoft Fax support in Windows into two parts: a fax transport that sits above the LMI, and one or more LMI providers that sit underneath. The fax transport is a messaging provider integrated with mail (MAPI) that can expose faxing capabilities to the user in many ways. Most fundamentally, faxing capability is exposed through the Microsoft Mail or Microsoft Exchange Send Note form, where fax is treated as just another valid address type by the user. But faxing capability is also exposed to the user through a <lq>print to fax<rq> mechanism hooked into the printing system (this user interface is more typical for alternative fax packages). In the new Windows shell, fax is also exposed through a <lq>send fax wizard<rq>. Regardless of the method chosen by the user to compose a fax, once <lq>sent<rq> by the user the fax message ends up as a message in the mail store. In general, any outbound message in the store is extracted by MAPI, and, if addressed to one or more fax recipients, the message is handed over to the fax transport for delivery.
The fax transport performs several types of processing on a fax message after receiving it from MAPI. The objective of this processing is to create a data stream that contains the actual bits that need to be sent across the wire. (It is assumed that in most cases, a fax will be sent over a PSTN connection. This need not always be so, such as in the case of a NetFax server.) The format of this data might be one of the standard MH, MR, or MMR formats; or it might be the Microsoft Fax linearized file format, which allows multiple, binary attachments. The transport intelligently decides which format or formats to generate (more than one may be generated) based partly on cached (or unknown) capabilities of the recipient, and partly on preferences expressed by the user. Especially in cases where the transport cannot decide the best format, it may generate several, postponing the actual decision of which to send until run time. Once the appropriate formats have been generated, the main work of the fax transport is done. From that point, responsibility for sending the fax belongs to the active LMI provider. The user could have several LMI providers installed, such as a local modem and a network fax service provider, but only one can be active at a time.
The fax transport has no knowledge of any physical modem or phone line. It only knows about the existence of a <lq>logical modem<rq>. The transport can submit jobs to be sent over this modem without worrying about how they will be sent. An LMI provider can accept these jobs and complete them in any way, including by forwarding the data to a different machine (which could be running a custom operating system) where a physical fax modem is installed.
Once it completes sending the fax, the LMI provider must return the results of the send to the sending fax transport. Because sending faxes and communicating between machines can be time-consuming, the interface is completely asynchronous. None of the calls into the interface require blocking of the fax transport while the LMI provider performs some operation. The LMI provider benefits from this division of labor because all of the intelligence is kept common in the fax transport, including all knowledge about keeping capabilities, rendering attachments to the message, getting data from OLE objects, and so on.
The LMI is designed so that all structures and data passed through the interface are already marshaled into blocks of BYTES. This simplifies the implementation of the LMI provider in the case where the provider is used with a network front-end processor and where the actual fax call is not made in the same process context as the provider interface. The LMI provider must parse the structures, dial the numbers, and send the appropriate format across the connection. To communicate with other Microsoft Fax-enabled machines over a PSTN connection, the LMI provider must be able to talk the Microsoft Extended Fax Protocol (MEFP) on the wire. MEFP is a set of NSF extensions to the ITU T.30 protocol; the details of this protocol are documented elsewhere. The current document assumes that the LMI provider can talk to Microsoft Fax clients and decipher their capabilities in order to make intelligent decisions about which format is to be sent.
There is a wide range of functionality an LMI provider may choose to provide. At the simplest, an LMI provider can decide to only provide send-fax services, with no capability of queuing, scheduling, and so on. A more complex LMI provider can have it's own phone books, generate cover pages, print incoming faxes, do inbound routing of other faxes, do load balancing with multiple hardware phone lines, and much more. The LMI encourages vendors to differentiate their offerings. The same fax transport can talk to an LMI provider with any kind of functionality. The fax transport makes dynamic decisions based on capability flags that are part of the LMI.
Except for a few configuration functions, the interface is guaranteed to be called from a single process context. However, the client software can consist of multiple threads, each of which may call portions of this interface. It is possible for a second API to be called while still in the middle of a previous call (the calls would be in different thread contexts). This is important. It means that the LMI provider must protect itself from reentrancy issues.
A logical modem is treated as a single queue to which jobs can be sent. There is not necessarily a one-to-one correspondence between a logical modem and a physical modem. An implementation can hide several modems behind a single queue and do load balancing among the modems.
Important: Unless explicitly stated otherwise, an LMI provider should not present any user interface in any interface calls. Many of these calls are made in the background and are not expected to put up UI (including message boxes).
@topic Overview of the LMI Provider Interface | This document describes the services a fax provider must implement to act as a fax provider to a Microsoft Fax client through the LMI. The interface has several main components. The parts are installation, configuration, queue administration and status, sending faxes, receiving faxes, and uploading documents and cover pages. Each of these is covered in detail in the following sections.
It is useful to present a high-level overview of how the fax transport calls into the Logical Modem Interface. At first, the transport's configuration user interface calls <f LMI_AddModem> and <f LMI_RemoveModem> to control which modems exist in the list of available modems. It also calls <f LMI_ExchangeCaps> to make any necessary configuration decisions. When the fax transport initializes, it calls <f LMI_InitProvider> and <f LMI_InitLogicalModem>. The transport can then send faxes with <f LMI_SendFax>. The transport polls for the status of sent faxes with <f LMI_ReportSend> and looks at the provider's queue with <f LMI_GetQueueFile>. To abort or reschedule a fax that has been sent but has not yet left the queue, the transport can call <f LMI_AbortSendJob> and <f LMI_RescheduleSendJob>. The transport polls for received faxes with <f LMI_ReportReceives>. Finally, the transport calls <f LMI_DeinitLogicalModem> and <f LMI_DeinitProvider> when it is time to shut down.
A useful example to study for understanding the flow across the LMI is the simple case of a send on one machine leading to a receive on another. A send starts off as a note composed in a mail client by the user. In this example, the user types in some text and attaches a bitmap. The user addresses the note to a single fax recipient at the phone number 555-1234 and chooses to send the note in the best format possible at the cheap-rate time. When the note is ready, the user <lq>sends<rq> the note (this really just saves the message to the store).
The message is then picked up from the store and is handed to the fax transport, because the message has a fax recipient. The fax transport looks into its capability database for the number 555-1234, but (in this example) finds no entry. Because the user chose to send the message in the best format possible, the fax transport converts the message into two formats: a rendered, MMR version (images only) and a linearized file-format version (binary file). For the rendered version, the transport itself renders the text; calls Paintbrush to render the bitmap file; and finally generates a file combining the rendered images, to which it attaches a linearized header. For the linearized version, the transport calls the linearizer, which assembles the binary attachments as-is into a file with a linearized header.
After creating the two separate files, the fax transport calls <f LMI_SendFax> in the LMI provider. In the call, the transport passes in the details of the job as well as the file name for each of the two formats that were generated. In response to the call, the LMI provider examines the details of the send job. Seeing that the fax (in this example) is to be sent at cheap rates, it leaves the job on its internal queue. The fax transport periodically polls the LMI provider for the status of the fax.
When cheap times roll around, the LMI provider connects to 555-1234 using a local modem and sends the appropriate format (the MMR file if the receiver is a G3 fax machine, or the linearized file if the receiver uses Microsoft Fax). The next time the fax transport calls <f LMI_ReportSend> after the fax is sent over the wire, the LMI provider returns the final status of the send job. Upon receipt of this status, the fax transport passes it on to the user, typically generating a Non-Delivery Report (NDR) if there was an error, or moving the message into the Sent Mail folder if the send was successful.
Received faxes are available immediately to the LMI provider on the remote machine, since it is the one picking up the phone. The LMI provider then has to decide to which client the message needs to be routed. For reception of G3 faxes, intelligent decisions are not possible since there is no structured routing information; routing to some default client is probably best. For Microsoft Fax messages, the LMI provider can interpret the linearized header (using some helper functions) and extract the Microsoft Fax address of the recipient. If this address contains a routing name, the name can be matched to a list of clients and the fax can be easily routed.
Once the LMI provider has decided on the recipient client, it waits for that client's fax transport to regularly poll for new faxes. When polled (by a call to <f LMI_ReportReceives>), the provider creates a file with the received data in an appropriate format. If the fax was received from a G3 fax machine, the provider can use helper functions to construct a file starting with a linearized header, followed by AWG3 page headers, finally followed by the data. For linearized file-format faxes, the exact data received is passed in. Finally, the client fax transport parses the data file (of whichever format) and creates a new message in the mail client Inbox containing the data in a format the user can view. @topic Installation | Installing a new LMI provider module is a two step process. First, the installation program must create an entry in the MSATWORK.INF file as defined below.
MSATWORK.INF file format:
[External Devices]<nl> \<device name\>=\<description\><nl> .<nl> .<nl> \<device name\>=\<description\>
[\<device name\>]<nl> Display Name=\<name to show devices list box\><nl> DLL Name=\<name of the DLL for this device\><nl> Flags=\<see below\><nl>
[\<device name\>]<nl> Display Name=\<name to show devices list box\><nl> DLL Name=\<name of the DLL for this device\><nl> Flags=\<see below\>
Explanation:
\<device name\>: Name of the section of the below device.<nl> \<description\>: Description of the device, for INF-file purposes only, not used anywhere else.<nl> Display Name: Name of the device. This name will be displayed in the AddDevice dialog listbox.<nl> DLL Name: Name of the DLL that services this device.<nl> Flags: Currently will be zero. Can be used for various device capabilities, like whether this device allows setup, etc.
Example:
[External Devices]<nl> IFAX=An intelligent fax machine<nl> AcmeFax=A future fax provider
[IFAX]<nl> Display Name=Intelligent fax machine<nl> DLL Name=ifax32.dll<nl> Flags=0
[AcmeFax]<nl> DLL Name=acme32.dll
Next, when the user installs a new fax modem from the configuration interface, the user is presented with a list of all strings from the Display Name section of the MSATWORK.INF file. When the user chooses Display Name, <f LMI_AddModem> is called to allow the LMI provider to put up a dialog box that asks the user to choose a logical modem from that LMI provider.
<f LMI_AddModem> returns a string representing the logical modem the user has selected. This string is then displayed in the list of currently available modems. The user can choose the current default fax modem from this list.
@topic Configuration | The user is allowed to configure any of the available fax modems (logical modems). <f LMI_ConfigureModem> is called for the appropriate LMI provider. This function allows the user to do whatever remote configuration options are permitted. These may be divided into user-configurable and administrator-configurable options. In general, there should be very few user configurable options. For administrator options, this function should probably use some kind of password protection.
@topic Initialization | When the fax transport starts, the <f LMI_InitProvider> function is called for the appropriate LMI provider. Then, the <f LMI_InitLogicalModem> function is called for the modem the client wants to use. This function intializes the logical modem and return to the client a handle to the modem, as well as the modem�s capabilities. The capabilities include support for advanced features and are used by the client to decide what kind of operations are supported by the LMI provider. An example of an important capability is whether or not the modem is Microsoft Fax enabled. The phone number of the modem is some other information returned by this call. Several logical modems may be initialized at the same time. All operations on a modem use the handle returned by the <f LMI_InitLogicalModem> call.
@topic Queue Management | To allow the user to see up-to-date status for all the jobs of an LMI provider, functions have been defined to let the client monitor and administer the provider's queue. <f LMI_GetQueueFile> is called whenever the user wants to see the queue. This function gives access to a specific set of information about each job in the provider's queue. The information is displayed in a uniform manner by the fax transport. To allow value-added, extended-status displays, arbitrary binary information can also be passed back as part of the status. If the user wants detailed status on a particular job, <f LMI_DisplayCustomStatus> is called with this binary information to display more detailed status. If the user wants to cancel or reschedule jobs, the functions <f LMI_AbortSendJob> and <f LMI_RescheduleSendJob> may be called.
@topic Sending Faxes | When a fax is to be sent, the transport assumes all responsibility for rendering the appropriate formats for transmission. The transport maintains a cache of the capabilities for all fax machines it has talked to before and uses the database to attempt intelligent decisions about the most efficient format to be sent. The transport also takes into account explicit user preferences. There are three different formats that can be sent. The first is for sending to standard fax machines and consists of MH, MR or MMR data. The second format is a linearized EFAX message containing only image data. The third format is a linearized EFAX message containing binary data. All three formats are always preceded by a linearized header describing the file. See <lq>Microsoft At Work Linearized File Format<rq> for details of this header. Details of the fax file format are in <lq>AWG3 File Format<rq>.
When the fax has been sent, the LMI provider reports the final status for the job via <f LMI_ReportSend>. This function is polled periodically by the fax transport. Along with the final status, the Provider must return the newly found capabilities of all the recipients of the fax. The client can also ask for attention using the <f LMI_CheckProvider> function.
Poll requests are also submitted using LMI_SendFax. Fields in the LMISENDJOB structure provide the information for the poll request.
@topic Receiving Faxes| All received faxes need to be routed by the fax transport to the appropriate LMI provider. The Microsoft At Work fax transport polls for received faxes using the <f LMI_ReportReceives> function.
As with sent faxes, received faxes can be in any one of three formats. The header for the file describes the format and gives information about the recipients of this message. All formats MUST have a linearized header describing the format and contents of the message. See <lq>Microsoft At Work Linearized File Format<rq> for details of this header. Details of the Fax file format are in <lq>AWG3 File Format<rq>. ****/
/********
@doc EXTERNAL SRVRDLL DATATYPES
@topic Microsoft At Work Address |
This section describes the Microsoft At Work address format. In its most common form, this consists of a name and a phone number. The phone number is assumed to begin at the last @ in the address. In its more complex forms, the name could contain more routing information.
Ideally, the phone number in the address is in the canonical form. This consists of +\<country code\>[\<area code\>]\<local number\>[\|\<suffix\>].
Other important things to note: An @ can be escaped by using a backslash, and a suffix may be added to the canonical number by using a \| symbol after the number and following that with the suffix.
@ex Some Examples: | A simple Micsosoft At Work Address might look like
JohnDoe@+1(206)5551212|$999
which would indicate that after dialing the number, we should wait for a beep and dial a 999. THe receiving number would then route to JohnDoe. If the number is an IFAX machine, John would have an account with the login JohnDoe, or if the number was a PC, JohnDoe would be the email alias for his account. In general, the <name> part of the address must be interpreted by the receiving machine and can contain any routing information necessary for inbound routing by this machine.
*********/
/****
@doc EXTERNAL SRVRDLL OVERVIEW
@topic Constants| The following section contains a list of predefined return codes, error codes, and other predefined values used throughout this document.
****/
/********
@doc EXTERNAL SRVRDLL DATATYPES
@type NONE | LMI_RETURN | Return codes for LMI provider API's.
@emem LMI_SUCCESS | No error - function was successful.
@emem LMIERR_CONNECT_FAILED | Connection to Provider failed. Client should go offline.
@emem LMIERR_NOT_SUPPORTED | Some function/parameter was not supported by this LMI provider.
@emem LMIERR_OPERATION_FAILED | Generic failure code.
@emem LMIERR_OP_CANCELLED | Operation canceled by user.
@emem LMIERR_PROVIDER_BUSY | The Provider was temporarily unavailable to accept requests. This might be useful for Providers which have limits on the number of connections supported. The clients response to this error code should be to try and retry the operation if possible, particularly for API's like <f LMI_SendFax>. However, some clients may treat this as a failure.
@emem LMIERR_SERVER_RESOURCES_LOW | The Provider failed due to a low resource situation on a server.
********/
typedef DWORD LMI_RETURN;
#define LMI_SUCCESS 0
#define LMIERR_CONNECT_FAILED 1
#define LMIERR_NOT_SUPPORTED 2
#define LMIERR_OPERATION_FAILED 3
#define LMIERR_OP_CANCELLED 4
#define LMIERR_PROVIDER_BUSY 5
#define LMIERR_SERVER_RESOURCES_LOW 6
/********
@doc EXTERNAL SRVRDLL DATATYPES
@type NONE | FAXERROR | DWORD Error status codes returned in the <t LMIFORMAT>, <t LMIRECIPSTATUS>, <t LMISENDSTATUS>, and <t LMIRECVSTATUS> structures. This error consists of three parts: an error code, an extended error code, and error specific data (in some cases). The extended error code must be set to T30_UNKNOWN if the means for setting a more meaningful error are not available. A value of zero in the data field implies that there is no valid data for this error. In those cases where the extended error or data fields are unused, they must be set to zero. This is to allow these fields to be used in the future.
@emem Error Code | The low BYTE of the low word of the error is the error code. Use the macro GetErrCode(error) to extract this BYTE. The error codes defined are:
@flag T30_CALLFAIL | An error occured during actual transmission of the fax. Detailed error status can be determined from the extended error field. @flag T30_DIALFAIL | An error occured during dialing the fax number. Detailed error status can be determined from the extended error field. @flag T30_ANSWERFAIL | An error occured during answering of a phone call. Detailed error status can be determined from the extended error field. @flag T30_NOMODEM | The Provider could not find any hardware modem to send the fax over. This would typically indicate that the user had physically removed some hardware from the machine. @flag T30_FILE_ERROR | An error occured trying to read or parse the format files which were passed in. Detailed error status may be found in the extended error. @flag T30_MODEMERROR | An error occured while trying to talk with the hardware modem. @flag T30_PORTBUSY | The port on which the hardware modem was installed cannot be opened. Extended error status contains more details. @flag T30_MODEMDEAD | The hardware modem has stopped responding to any AT commands. This typically requires some human intervention, such as turning the power off and back on. @flag RES_NOMEMORY | The Provider ran out of memory resources. @flag RES_LOWDISK | The Provider ran out of disk space. @flag USER_ABORT | The job was cancelled on a user request. @flag RENDERING_FAILURE | For Provider's that do any rendering, this indicates the class of failures which result in the inability to render a final format to be sent. Extended errors give more details. @flag RES_LOW_SERVER | The Provider failed due to a low resource problem on a server. @flag CUSTOM_ERROR | If the Provider happens to get an error which does not fall into any of the classes specifically defined here, then it can pass back a custom error. In this case the data field contains a global atom which identifies a string describing the error in terms understandable to the user. NOTE: This error is not supported by Windows 95, but will be in a later release. @flag GENERAL_FAILURE | Indicates a serious internal error in the software.
@emem Extended error codes for T30_DIALFAIL | Any of the following could be the reason for a dial failure:
@flag NCUDIAL_ERROR | Detailed error is unknown. @flag NCUDIAL_BUSY | The called number was busy. @flag NCUDIAL_NOANSWER | The dialed number did not answer. @flag NCUDIAL_NODIALTONE | No dialtone could be detected. @flag NCUDIAL_MODEMERROR | There was some hardware problem in the modem while trying to dial. @flag NCUDIAL_BADDIALSTRING | The dial string was badly formed. In general, logical modems should try to be as robust as possible, ignoring characters which are not understood. This error code should only be used for cases where the string is so obviously malformed that there is no point even attempting to dial.
@emem Extended error codes for T30_ANSWERFAIL | The provider does not have to report receives which failed in the answering phase itself. However, if it chooses to do so, the following codes apply:
@flag NCUANSWER_ERROR | Detailed error is unknown. @flag NCUANSWER_NORING | No ring was detected. @flag NCUANSWER_MODEMERROR | There was some hardware problem in the modem while trying to answer.
@emem Extended error codes for T30_PORTBUSY | The port could be busy for two reasons:
@flag PORTBUSY_SELFUSE | The port is already being used by us. A common case causing this error is if a receive is in progress. The client will typically retry the call at a later time, transparently to the user. @flag PORTBUSY_OTHERAPP | The device or port is used by some other application.
@emem Extended error codes for T30_CALLFAIL | This is likely to be the most common error, and very detailed error codes are defined for it. The extended error can be any of the following:
@flag T30FAILS_T1 | Send T1 timeout (No NSF/DIS Received). @flag T30FAILS_TCF_DCN | Received DCN after TCF. @flag T30FAILS_3TCFS_NOREPLY | No reply to three attempts at training (TCF). @flag T30FAILS_3TCFS_DISDTC | Remote does not see our TCFs. @flag T30FAILS_TCF_UNKNOWN | Got garbage response to TCF. @flag T30FAILS_SENDMODE_PHASEC | Modem error or timeout at start of page. @flag T30FAILS_MODEMSEND_PHASEC | Modem error or timeout within page. @flag T30FAILS_MODEMSEND_ENDPHASEC | Modem error or timeout at end of page. @flag T30FAILSE_SENDMODE_PHASEC | Modem error or timeout at start of ECM page. @flag T30FAILSE_MODEMSEND_PHASEC | Modem error or timeout within ECM page. @flag T30FAILSE_MODEMSEND_ENDPHASEC | Modem error or timeout at end of ECM page. @flag T30FAILSE_BADPPR | Bad PPR received from receiver. @flag T30FAILS_3POSTPAGE_NOREPLY | No response after page: Probably receiver hungup during page transmit. @flag T30FAILS_POSTPAGE_DCN | Received DCN after page. @flag T30FAILSE_3POSTPAGE_NOREPLY | No response after page. Probably receiver hungup during page transmit. @flag T30FAILSE_POSTPAGE_DCN | Received DCN after ECM page. @flag T30FAILSE_POSTPAGE_UNKNOWN | Received garbage after ECM page. @flag T30FAILSE_RR_T5 | Receiver was not ready for more than 60 seconds during ECM flow-control. @flag T30FAILSE_RR_DCN | Received DCN after RR during ECM flow-control. @flag T30FAILSE_RR_3xT4 | No response from receiver during ECM flow-control. @flag T30FAILSE_CTC_3xT4 | No response from receiver after CTC (ECM baud-rate fallback). @flag T30FAILSE_CTC_UNKNOWN | Garbage response from receiver after CTC (ECM baud-rate fallback). @flag T30FAILR_PHASEB_DCN | Receiver: Sender decided we're incompatible. @flag T30FAILR_T1 | Receiver: Caller is not a fax machine or hung up. @flag T30FAILR_UNKNOWN_DCN1 | Receiver: Received DCN when command was expected. @flag T30FAILR_T2 | Receiver: No command was received for seven seconds. @flag T30FAILR_UNKNOWN_UNKNOWN2 | Receiver: Received garbage when command was expected. @flag T30FAILR_MODEMRECV_PHASEC | Receiver: Page not received, modem error or timeout at start of page. @flag T30FAILRE_MODEMRECV_PHASEC | Receiver: Data not received, modem error or timeout during page. @flag T30FAILRE_PPS_RNR_LOOP | Receiver: Timeout during ECM flow control after PPS. @flag T30FAILRE_EOR_RNR_LOOP | Receiver: Timeout during ECM flow control after EOR. @flag T30FAIL_NODEA_UNKNOWN | Sender: Garbage frames instead of DIS/DTC. @flag T30FAILS_POSTPAGE_UNKNOWN | Sender: Unknown response after page. @flag T30FAILS_POSTPAGE_OVER | Sender: We've sent a DCN (decided to end call). @flag T30FAILS_4PPR_ERRORS | Sender: Too many line errors in ECM mode. @flag T30FAILS_FTT_FALLBACK | Sender: Receiver doesn't like our training at all speeds. @flag T30FAILS_RTN_FALLBACK | Sender: Too many line errors in non-ECM mode even at 2400. @flag T30FAILS_4PPR_FALLBACK | Sender: Too many line errors in ECM mode even at 2400. @flag T30FAILS_MG3_NOFILE | Negotiation failed: Remote was G3 and there was no AWG3 format to send. @flag T30FAILS_NEGOT_ENCODING | Negotiation failed: Encoding mismatch. @flag T30FAILS_NEGOT_WIDTH | Negotiation failed: Paper Size Not Supported. @flag T30FAILS_NEGOT_LENGTH | Negotiation failed: Paper Size Not Supported. @flag T30FAILS_NEGOT_RES | Negotiation failed: Resolution Not Supported. @flag T30FAILS_EFX_BADFILE | Bad Linearized file was passed. @flag T30FAILS_MG3_BADFILE | Bad AWG3 file was passed in. @flag T30FAIL_ABORT | User abort @flag T30FAILS_SECURITY_NEGOT | Negotiation failed: Remote machine does not support security. If set, the error data contains the security version number supported by the recipient. @flag T30FAILS_NEGOT_MSGPROTOCOL | Negotiation failed: Remote machine does not support a compatible message protocol. If set, the error data contains the message protocol version number supported by the recipient. @flag T30FAILS_NEGOT_SECURITY | Negotiation failed: Remote machine does not support security. If set, the error data contains the security version number supported by the recipient. @flag T30FAILS_NEGOT_BINARYDATA | Negotiation failed: Remote machine does not support receiving binary data. @flag T30FAILS_NEGOT_COMPRESSION | Negotiation failed: Remote machine does not support a compatible version of compression. If set, the error data contains the compression version supported by the recipient. @flag T30FAILS_NEGOT_POLLING | Negotiation failed: Remote machine does not support polling. @flag T30FAILS_NEGOT_POLLBYNAME | Negotiation failed: Remote machine does not support poll by name. @flag T30FAILS_NEGOT_POLLBYRECIP | Negotiation failed: Remote machine does not support poll by recipient name. @flag T30FAILS_NEGOT_FILEPOLL | Negotiation failed: Remote machine does not support poll by filename.
@emem Error data values for T30_CALLFAIL | Error data must be zero for negotiation failures. For all other failures, the error data may be set to one of the following fields:
@flag T30_SENTNONE | Indicates that no pages were sent at all. @flag T30_SENTSOME | Indicates that some pages were successfuly transmitted and acknowledged by the remote machine. @flag T30_SENTALL | Indicates that all pages were successfuly sent. This should not really happen; it would generally indicate a successful transmission.
@emem Extended error codes for T30_FILE_ERROR | This error indicates a problem in one of the format files sent across the interface by the client. Different possible extended error codes are:
@flag AWG3_INVALID_LINHDR | The linearized header at the head of the AWG3 file was invalid. @flag AWG3_INVALID_AWG3HDR | An invalid AWG3 header was found in the file. @flag LIN_INVALIDHDR | A linearized file had an invalid header.
********/
typedef DWORD FAXERROR;
#define GetErrCode(fe) (LOBYTE(LOWORD(fe)))
#define GetExtErrCode(fe) (HIBYTE(LOWORD(fe)))
#define GetErrData(fe) (HIWORD(fe))
#define FormFaxError(ErrCode,ExtErrCode,ErrData) MAKELONG(MAKEWORD(ErrCode,ExtErrCode),ErrData)
// Error codes
#define T30_CALLFAIL 2
#define T30_DIALFAIL 4
#define T30_ANSWERFAIL 5
#define T30_NOMODEM 9
#define T30_FILE_ERROR 11
#define T30_MODEMERROR 15
#define T30_PORTBUSY 16
#define T30_MODEMDEAD 17
#define RES_NOMEMORY 64
#define RES_LOWDISK 65
#define USER_ABORT 66
#define RENDERING_FAILURE 67
#define RES_LOW_SERVER 68
#define CUSTOM_ERROR 254
#define GENERAL_FAILURE 255
// Extended Error codes
#define T30_UNKNOWN 0
// RENDERING_FAILURE
#define ATTACH_NOT_PRINTABLE 1
#define COVER_TEMPLATE_INVALID 2
// T30_FILE_ERROR
#define AWG3_INVALID_LINHDR 1
#define AWG3_INVALID_AWG3HDR 2
#define LIN_INVALIDHDR 3
// T30_DIALFAIL
#define NCUDIAL_ERROR 0
#define NCUDIAL_BUSY 2
#define NCUDIAL_NOANSWER 3
#define NCUDIAL_NODIALTONE 4
#define NCUDIAL_MODEMERROR 5
#define NCUDIAL_UNSUPPORTED_DIALCHAR 6
#define NCUDIAL_BADDIALSTRING 7
// Extended error code for T30_ANSWERFAIL
#define NCUANSWER_ERROR 0
#define NCUANSWER_NORING 8
#define NCUANSWER_MODEMERROR 5
// Extended error code for T30_PORTBUSY
#define PORTBUSY_SELFUSE 0
#define PORTBUSY_OTHERAPP 1
// Includes T30FAIL.H so that the values here (which should be a subset of
// those in T30FAIL.H) are kept in sync.
#include <t30fail.h>
// Extended error code for T30_CALLFAIL
#define T30FAILS_T1 6 // Send T1 timeout (No NSF/DIS Recvd)
#define T30FAILS_TCF_DCN 7 // Recvd DCN after TCF (weird...)
#define T30FAILS_3TCFS_NOREPLY 8 // No reply to 3 attempts at training (TCF)
#define T30FAILS_3TCFS_DISDTC 9 // Remote does not see our TCFs for some reason
#define T30FAILS_TCF_UNKNOWN 10 // Got garbage response to TCF
#define T30FAILS_SENDMODE_PHASEC 11 // Modem Error/Timeout at start of page
#define T30FAILS_MODEMSEND_PHASEC 12 // Modem Error/Timeout within page
#define T30FAILS_MODEMSEND_ENDPHASEC 14 // Modem Error/Timeout at end of page
#define T30FAILSE_SENDMODE_PHASEC 15 // Modem Error/Timeout at start of ECM page
#define T30FAILSE_MODEMSEND_PHASEC 17 // Modem Error/Timeout within ECM page
#define T30FAILSE_MODEMSEND_ENDPHASEC 19 // Modem Error/Timeout at end of ECM page
#define T30FAILSE_BADPPR 20 // Bad PPR recvd from Recvr (bug on recvr)
#define T30FAILS_3POSTPAGE_NOREPLY 21 // No response after page: Probably Recvr hungup during page transmit
#define T30FAILS_POSTPAGE_DCN 22 // Recvd DCN after page. (weird...)
#define T30FAILSE_3POSTPAGE_NOREPLY 23 // No response after page: Probably Recvr hungup during page transmit
#define T30FAILSE_POSTPAGE_DCN 24 // Recvd DCN after ECM page. (weird...)
#define T30FAILSE_POSTPAGE_UNKNOWN 25 // Recvd garbage after ECM page.
#define T30FAILSE_RR_T5 26 // Recvr was not ready for more than 60secs during ECM flow-control
#define T30FAILSE_RR_DCN 27 // Recvd DCN after RR during ECM flow-control(weird...)
#define T30FAILSE_RR_3xT4 28 // No response from Recvr during ECM flow-control
#define T30FAILSE_CTC_3xT4 29 // No response from Recvr after CTC (ECM baud-rate fallback)
#define T30FAILSE_CTC_UNKNOWN 30 // Garbage response from Recvr after CTC (ECM baud-rate fallback)
#define T30FAILR_PHASEB_DCN 35 // Recvr: Sender decided we're incompatible
#define T30FAILR_T1 36 // Recvr: Caller is not a fax machine or hung up
#define T30FAILR_UNKNOWN_DCN1 37 // Recvr: Recvd DCN when command was expected(1)
#define T30FAILR_T2 38 // Recvr: No command was recvd for 7 seconds
#define T30FAILR_UNKNOWN_UNKNOWN2 40 // Recvr: Recvd grabge when command was expected
#define T30FAILR_MODEMRECV_PHASEC 41 // Recvr: Page not received, modem error or timeout at start of page
#define T30FAILRE_MODEMRECV_PHASEC 42 // Recvr: Data not received, modem error or
#define T30FAILRE_PPS_RNR_LOOP 43 // Recvr: Timeout during ECM flow control after PPS (bug)
#define T30FAILRE_EOR_RNR_LOOP 44 // Recvr: Timeout during ECM flow control after EOR (bug)
#define T30FAIL_NODEA_UNKNOWN 45 // Sender: Garbage frames instead of DIS/DTC
#define T30FAILS_POSTPAGE_UNKNOWN 47 // Sender: Unknown response after page
#define T30FAILS_POSTPAGE_OVER 48 // Sender: We've sent a DCN (decided to end call)
#define T30FAILS_4PPR_ERRORS 50 // Sender: Too many line errors in ECM mode
#define T30FAILS_FTT_FALLBACK 51 // Sender: Recvr doesn't like our training at all speeds
#define T30FAILS_RTN_FALLBACK 52 // Sender: Too many line errors in non-ECM mode even at 2400
#define T30FAILS_4PPR_FALLBACK 53 // Sender: Too many line errors in ECM mode even at 2400
#define T30FAILS_MG3_NOFILE 63 // Negotiation failed: Remote in G3-only and no MG3 file *** Email Form Not Supported ***
#define T30FAILS_NEGOT_ENCODING 64 // Negotiation failed: Encoding mismatch
#define T30FAILS_NEGOT_WIDTH 66 // Negotiation failed: Send image too wide *** Paper Size Not Supported ***
#define T30FAILS_NEGOT_LENGTH 67 // Negotiation failed: Send image too long *** Paper Size Not Supported ***
#define T30FAILS_NEGOT_RES 68 // Negotiation failed: Resolution mismatch *** Resolution Not Supported ***
#define T30FAILS_EFX_BADFILE 69 // Bad EFX file
#define T30FAILS_MG3_BADFILE 71 // Bad MG3 file
#define T30FAIL_ABORT 87 // User abort
#define T30FAILS_SECURITY_NEGOT 110// Negotiation failed: Remote in G3-only and no MG3 file *** Email Form Not Supported ***
// New failure codes
#define T30FAILS_NEGOT_MSGPROTOCOL 128
#define T30FAILS_NEGOT_SECURITY 129
#define T30FAILS_NEGOT_BINARYDATA 130
#define T30FAILS_NEGOT_COMPRESSION 131
#define T30FAILS_NEGOT_COVERATTACH 132
#define T30FAILS_NEGOT_ADDRATTACH 133
#define T30FAILS_NEGOT_METAFILE 134
#define T30FAILS_NEGOT_POLLING 135
#define T30FAILS_NEGOT_POLLBYNAME 136
#define T30FAILS_NEGOT_POLLBYRECIP 137
#define T30FAILS_NEGOT_FILEPOLL 138
#define T30FAILS_NEGOT_RELAY 139
// Data word
// Data for T30_CALLFAIL - non negotiation errors
#define T30_UNKNOWN 0
#define T30_SENTALL 1
#define T30_SENTNONE 2
#define T30_SENTSOME 3
/********
@doc EXTERNAL SRVRDLL DATATYPES
@type NONE | FORMATTYPE | These are all the different kinds of formats that can be rendered for sending. It is typedef'd to a WORD.
@emem LMIFORMAT_G3 | A standard T4/T6 encoded file, with a linearizer header put on top of it. See <lq>AWG3 File Format<rq> for details.
@emem LMIFORMAT_LIN_IMAGE | A Linearized Microsoft At Work rendered image file.
@emem LMIFORMAT_LIN_BINARY | A linearized binary file.
********/
typedef WORD FORMATTYPE;
#define LMIFORMAT_G3 1
#define LMIFORMAT_LIN_IMAGE 2
#define LMIFORMAT_LIN_BINARY 3
#define LMIFORMAT_STORE_REF 4
/********
@doc EXTERNAL SRVRDLL DATATYPES
@type NONE | POLLTYPE | These are all the different kinds of poll requests that can be sent. It is typedef'd to a WORD.
@emem POLLREQ_ADDRESS | Polls for a document for a particular address. The Poll name is the address for which messages are desired, and a password can also be used. This feature is unimplemented and should not be used.
@emem POLLREQ_FILE | Polls for a directory or file on the recipient system. The poll name contains the file system path to be accessed, and a password can also be used. This feature is unimplemented and should not be used.
@emem POLLREQ_MSGNAME | Polls for a particular message name. The poll name contains the message name wanted, and a password can also be used.
@emem POLLREQ_G3 | Standard G3 compliant poll request. Polls for any file which has been stored at the recipient machine. Neither pollname or password are currently supported.
All poll types except POLLREQ G3 require both sender and receiver to be Microsoft Extended Fax Protocol (MEFP)-enabled. ********/
typedef WORD POLLTYPE;
#define POLLREQ_ADDRESS 1
#define POLLREQ_FILE 2
#define POLLREQ_MSGNAME 3
#define POLLREQ_G3 4
/********
@doc EXTERNAL SRVRDLL DATATYPES
@type NONE |SCHEDTYPE | Kinds of possible scheduling. Typedef'd to a WORD.
@emem SCHED_ASAP | Schedule immediately.
@emem SCHED_BEFORE | Schedule immediately, and fail if the specified time is past.
@emem SCHED_AFTER | Schedule any time after the specified time is past.
@emem SCHED_CHEAPTIMES | Schedule only between cheap time periods as specified by the Provider's local settings. Only the time of day, as specified by the start time and stop time elements of the <t SENDJOBTIME> structure, have any meaning. In fact, the day, date, month, and year are not guaranteed to be filled in.
********/
typedef WORD SCHEDTYPE;
#define SCHED_ASAP 1
#define SCHED_BEFORE 2
#define SCHED_AFTER 3
#define SCHED_CHEAPTIMES 4
/********
@doc EXTERNAL SRVRDLL
@type NONE | PROVIDERSTATE | A DWORD which describes the state of the Provider. Can consist of a combination of the following flags:
@emem PROVIDER_OK | Standard OK state - no action is required.
@emem PROVIDER_OFFLINE | Provider is offline - client should do the same. Offline indicates that the Provider is no longer actively able to send or receive jobs.
@emem PROVIDER_NO_RESPONSE | No response from Provider. Client should go offline.
@emem PROVIDER_BADERROR | Bad error at Provider. Client should go offline.
@emem PROVIDER_RECEIVES_WAITING | Client should poll for receives.
@emem PROVIDER_SENDS_COMPLETED | Client should poll for completed send status. ********/
typedef DWORD PROVIDERSTATE;
#define PROVIDER_OK 0x0000
#define PROVIDER_OFFLINE 0x0001
#define PROVIDER_NO_RESPONSE 0x0002
#define PROVIDER_BADERROR 0x0004
#define PROVIDER_RECEIVES_WAITING 0x0008
#define PROVIDER_SENDS_COMPLETED 0x0010
/********
@doc EXTERNAL SRVRDLL
@type NONE | JOBSTATE | A WORD identifying the state of a fax job.
@emem jstNewMsg | Just received from mail spooler. @emem jstProcessingRecipients | Deciding what needs to be sent. @emem jstRendering | Being rendered (Used internally by client). @emem jstReadyToSend | Waiting to be schedulable. @emem jstSchedulable | Ready to be transmitted. @emem jstTransmitting | Being transmitted. @emem jstWaitingForServer | Given to network Provider (Used internally by client). @emem jstWaitingForClient | Waiting for client to take back.
********/
typedef WORD JOBSTATE;
#define jstNewMsg 0
#define jstProcessingRecipients 1
#define jstRendering 2
#define jstReadyToSend 3
#define jstSchedulable 4
#define jstTransmitting 5
#define jstAllDone 6
#define jstWaitingForServer 7
#define jstWaitingForClient 8
/****
@doc EXTERNAL SRVRDLL OVERVIEW
@topic Data Structures | Most structures defined here are in a packed format; that is, there are no pointers to external objects. This is done so they can be easily stored in a file or transmitted as a block across the network.
Most structures have two size fields. The HeaderSize field gives the defined size of the structure, which is used for versioning the structure. If the structure is expanded in the future, this size can be used to maintain backward compatibility. The TotalSize field indicates the size of the whole structure along with all its data.
All strings and other variable-length data items such as structures are represented in the structure by an offset from the beginning of the structure. The actual data for these elements begins at that offset. The length of the data is indicated by the item itself. If it is a string, it is null-terminated. If it is another structure, the size fields will convey this information.
All files referenced in the structures are created in the spool directory specified in LMI_InitProvider.
****/
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMICUSTOMOPTION | Overlay of LMI Custom Option data. For MAPI 1.0, Win32 implementations, this structure is found in the MAPI message property PR_FAX_LMI_CUSTOM_OPTION (property tag value 0x4513.)
@field DWORD | dwTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wNumRecords | Number of records in the Custom Option data. This is also eqaul to the size of the dwOffsetTable.
@field DWORD | dwOffsetTable[] | Table of offsets to the records of type LMICUSTOMOPTIONRECORD. All offsets are from the top of the LMICUSTOMOPTION structure. The records should directly follow this array. ********/
#ifndef RC_INVOKED
#pragma warning (disable: 4200)
#endif
typedef struct _LMICUSTOMOPTION { DWORD dwTotalSize; WORD wHeaderSize; WORD wNumRecords; DWORD dwOffsetTable[0]; } LMICUSTOMOPTION, FAR *LPLMICUSTOMOPTION;
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMICUSTOMOPTIONRECORD | Record overlay of LMI Custom Option data.
@field DWORD | dwTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wPad | Keep DWORD alignment.
@field CHAR | szUniqueName[32] | Unique name specified by provider. This is used for identification of the provider's record within the LMICUSTOMOPTION and should contain some encoding of the provider developer company. eg, "Microsoft:Netfax". The string MUST be null terminated so that providers may do strcmp's to detect their own section.
@field BYTE | lpData[] | Here's the data.
********/ typedef struct _LMICUSTOMOPTIONRECORD { DWORD dwTotalSize; WORD wHeaderSize; WORD wPad; CHAR szUniqueName[32]; BYTE lpData[]; } LMICUSTOMOPTIONRECORD, FAR *LPLMICUSTOMOPTIONRECORD;
#ifndef RC_INVOKED
#pragma warning (default: 4200)
#endif
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMIFORMAT | Describes a format.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field FAXERROR | feError | Indicates if there were any errors while trying to generate this format. If this field is not set to zero, the format file pointed to by the szFileName field may be invalid and should not be used. This error value might need to be propagated into the <e LMIRECIPSTATUS.feError> field for recipients which fail as a result of this format not being ready.
@field CHAR | szFileName[16] | The filename containing the actual format data.
@field FORMATTYPE | ftFormatType | Which format this represents.
@field WORD | wPad | Keep DWORD alignment. ********/ typedef struct _LMIFORMAT { WORD wHeaderSize; WORD wTotalSize; FAXERROR feError; CHAR szFileName[16]; FORMATTYPE ftFormatType; WORD wPad; } LMIFORMAT, FAR *LPLMIFORMAT; #define MAXFORMATSIZE (sizeof(LMIFORMAT))
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMIPOLLREQUEST | Describes a poll request message.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wszRecipName | The name of this recipient. This is present only if this recipient is from a Provider implemented address book. In this case <e LMIRECIPIENT.wszAddressOffset> is zero.
@field WORD | wszAddressOffset | The Microsoft At Work address for this recipient. Not present for recipients implemented in the Provider's address book. See <t Microsoft At Work Address> for details.
@field DWORD | dwPollContext | The provider should report this value in the dwPollContext field of the LMIRECVSTATUS structure for all the messages received as a result of this poll request. This enables the client to associate the received messages (reported to the client via LMI_ReportReceives) with a particular poll request. A value of zero is valid, but not useful, because all non-polled receives reported by LMI_ReportReceives have zero as the dwPollContext in their LMIRECVSTATUS structure.
@field POLLTYPE | ptPollType | What type of a poll request this is.
@field WORD | wszPollNameOffset | The name to be sent along with the poll request. The specific semantic meaning depends on the poll type.
@field WORD | wszPollPasswordOffset | Offset to the password to be sent along with the poll request.
@field WORD | wPad | Keep DWORD alignment. ********/ typedef struct _LMIPOLLREQUEST { WORD wHeaderSize; WORD wTotalSize; WORD wszRecipName; WORD wszAddressOffset; DWORD dwPollContext; POLLTYPE ptPollType; WORD wszPollNameOffset; WORD wszPollPasswordOffset; WORD wPad; } LMIPOLLREQUEST, FAR *LPLMIPOLLREQUEST;
/********
@doc EXTERNAL SRVRDLL
@types LMIQUEUEDATA | Represents queue information about a single job.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field DWORD | dwUniqueID | This can be used by the Provider to pass in a context. Along with <e LMIQUEUEDATA.dwUniqueID2> and <e LMIQUEUEDATA.wszSenderMachineNameOffset> this must uniquely identify this job.
@field DWORD | dwUniqueID2 | See <e LMIQUEUEDATA.dwUniqueID>.
@field WORD | wszSenderMachineNameOffset | Points to a string which identifies the machine originating this job. Used for display in the queue. Also uniquely identifies the job along with the unique ID's. This should be the same as the string pointed to by the <e LMISENDJOB.wszSenderMachineNameOffset> field in <t LMISENDJOB>.
@field WORD | wszSubjectOffset | Offset to the subject of this message. This should be the same as the string pointed to by the <e LMISENDJOB.wszSubjectOffset> field in <t LMISENDJOB>.
@field DWORD | dwSize | This should be the same as what was passed in as <e LMISENDJOB.dwTotalFileSize> in <t LMISENDJOB>.
@field WORD | wNumRecipients | This should be the same as what was passed in as <e LMISENDJOB.wNumRecipients> in <t LMISENDJOB>.
@field JOBSTATE | jstState | Current overall status for this job.
@field WORD | wNumRecipDone | Number of recipients for which transmission has been completed, either succesfully or unsuccesfully.
@field WORD | wtmSendTimeOffset | Current scheduling state for this job. Offset to a <t SENDJOBTIME> structure.
@field WORD | wrgbCustomStatusOffset | Offset to Provider defined custom status information. This is passed to the <f LMI_DisplayCustomStatus> function when the user asks to see detailed status for this job.
@field WORD | wCustomDataSize | Size of the custom data pointed to by the <e LMISENDJOB.wrgbCustomStatusOffset> field.
********/
typedef struct _LMIQUEUEDATA { WORD wHeaderSize; WORD wTotalSize; DWORD dwUniqueID; DWORD dwUniqueID2; WORD wszSenderMachineNameOffset; WORD wszSubjectOffset; DWORD dwSize; WORD wNumRecipients; JOBSTATE jstState; WORD wNumRecipDone; WORD wtmSendTimeOffset; WORD wrgbCustomStatusOffset; WORD wCustomDataSize; } LMIQUEUEDATA, NEAR *NPLMIQUEUEDATA, FAR *LPLMIQUEUEDATA;
/********
@doc EXTERNAL SRVRDLL
@types LMIQUEUEFILEHEADER | A queue file consists of this header followed by the queue data.
@field DWORD | dwSig | This must be set to SIG_QUEUEFILE.
@field DWORD | dwSize | Must be set to the total file size.
@field DWORD | dwNumEntries | Number of queue entries in the file. The header is followed by this many <t LMIQUEUEDATA> structures. ********/
#define SIG_QUEUEFILE 0x56873
typedef struct _LMIQUEUEFILEHEADER { DWORD dwSig; // Should always be NQFH
DWORD dwSize; // Total file size
DWORD dwNumEntries; // Num of entries in the file
} LMIQUEUEFILEHEADER;
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMIRECIPIENT | Describes a recipient.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wszRecipName | The name of this recipient. This is present only if this recipient is from a Provider implemented address book. In this case <e LMIRECIPIENT.wszAddressOffset> is zero and <e LMIRECIPIENT.szCoverFile> is a reference to a template on the Provider.
@field WORD | wszAddressOffset | The Microsoft At Work address for this recipient. Not present for recipients implemented in the Provider's address book. See <lq>Microsoft At Work Address<rq> for details.
@field CHAR | szCoverFile[16] | The filename containing the cover page data if any for this recipient. This could be a reference to a previously uploaded template if this is a recipient from the Provider's address book. If the first word of this character array is 0 but the second word is non-null, then the second word represent a WORD offset into the LMIRECIPIENT structure where the fully qualified path may be found.
@field CHAR | szEncryptFile[16] | If one of the linearized formats pointed to by this recipient structure is a public key encrypted message being sent to multiple recipients, then this field contains the filename for a linearized format of the message encrypted with this recipients public key. This field will not be valid under any other circumstance.
@field WORD | wG3FormatIndex | If non-zero, this specifies a 1-based index into the format structure array. It implies that this recipient can accept this version of the G3 format. Note that there may still be some run time conversions necessary on this format at the time of sending. For instance, the format may be MMR, whereas on calling it may be discovered that the recipient only accepts MH. In this case, the Provider is responsible for converting this on the fly.
@field WORD | wLinImageFormatIndex | Index into the format array. Pointer to a linearized image format which can be sent to this recipient.
@field WORD | wLinBinaryFormatIndex | Index into the format array. Pointer to a linearized binary format which can be sent to this recipient.
@field WORD | wPad | Keep DWORD alignment. ********/
typedef struct _LMIRECIPIENT { WORD wHeaderSize; WORD wTotalSize; WORD wszRecipName; WORD wszAddressOffset; CHAR szCoverFile[16]; CHAR szEncryptFile[16]; WORD wG3FormatIndex; WORD wLinImageFormatIndex; WORD wLinBinaryFormatIndex; WORD wPad; } LMIRECIPIENT, FAR *LPLMIRECIPIENT; #define MAXRECIPIENTSIZE (sizeof(LMIRECIPIENT) + MAX_ADDRESS_LENGTH)
/*******
@doc EXTERNAL SRVRDLL DATATYPES
@types LMIRECIPSTATUS | Used to convey information for the final status of the completed send for a recipient.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wrcCapsOffset | An offset to a <t MACHINECAPS> structure containing the updated capabilites for this recipient.
@field FORMATTYPE | ftSentFormat | The format type which was finally sent to this recipient.
@field FAXERROR | feError | The final status for this recipient.
@field SYSTEMTIME | dtTransmitTime | The time at which the fax was last attempted to be sent.
@field DWORD | dwConnectTime | Connect time for the transmission in seconds.
*******/
typedef struct _LMIRECIPSTATUS { WORD wHeaderSize; WORD wTotalSize; WORD wrcCapsOffset; FORMATTYPE ftSentFormat; FAXERROR feError; DWORD dwConnectTime; SYSTEMTIME dtTransmitTime; } LMIRECIPSTATUS, FAR *LPLMIRECIPSTATUS;
/********
@doc EXTERNAL SRVRDLL
@types LMIRECVSTATUS | Gives the status for a received fax.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field FAXERROR | feError | The final status for this receive.
@field SYSTEMTIME | dtRecvTime | Should be filled with the time at which the fax was received.
@field DWORD | dwConnectTime | The connect time for the transmission in seconds.
@field DWORD | dwPollContext | If this receive was actually in response to a poll request, then this will be set to the same value which was passed in in the <t LMIPOLLREQUEST> structure sent along with the poll request.
@field ATOM | atFile | The filename containing the received fax file. This file should be in the spool directory agreed upon in the <f LMI_InitLogicalModem> call.
@field WORD | wPad | Keep DWORD alignment.
********/
typedef struct _LMIRECVSTATUS { WORD wHeaderSize; WORD wTotalSize; FAXERROR feError; SYSTEMTIME dtRecvTime; DWORD dwConnectTime; DWORD dwPollContext; ATOM atFile; WORD wPad; } LMIRECVSTATUS, FAR *LPLMIRECVSTATUS;
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMISENDJOB | Describes a new fax job. A fax job specifies a send to one or more recipients.
@field DWORD | dwTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | fUnicode | Indicates whether the string pointed to by <e LMISENDJOB.wszSenderMachineNameOffset> is a Unicode string or not. @field WORD | wszSenderMachineNameOffset | Points to a string which identifies the machine originating this job. Used for display in the queue. Also uniquely identifies the job along with the unique ID's.
@field WORD | wszSubjectOffset | Subject of the message. Used for display purposes in the queue.
@field DWORD | dwUniqueID | Used by the client to uniquely identify this send fax job along with <e LMISENDJOB.dwUniqueID2>.
@field DWORD | dwUniqueID2 | Used along with <e LMISENDJOB.dwUniqueID> to identify this job.
@field DWORD | dwBillingCode | Billing code for this job. This is to allow Providers to keep accurate billing logs.
@field DWORD | dwTotalFileSize | An approximation for the total size of the data required to be transmitted for this message for all recipients combined. Meant for display purposes in the queue to allow some idea of how long the job is likely to take.
@field WORD | wtmSendTimeOffset | Offset to a <t SENDJOBTIME> scheduling structure.
@field WORD | wprPollRequestOffset | Offset to a poll request structure. See <t LMIPOLLREQUEST> for details. If this offset is set, there are no recipient or format structures associated with this job. In other words, the rgwStructOffsets field will be zero.
@field WORD | wrgbCustomOptionOffset | Offset to custom message options set for this message. This is an offset to data returned by a call to <f LMI_SetCustomMsgOptions>. The first DWORD of the data indicates the size of the data.
@field WORD | wNumRecipients | The number of recipients for this job.
@field WORD | wNumFormats | The number of rendered formats associated with this job.
@field WORD | wPad | Keep DWORD alignment. @field DWORD | rgdwStructOffsets[] | Array of size <e LMISENDJOB.wNumFormats> and <e LMISENDJOB.wNumRecipients> offsets to format and recipient structures. The <t LMISENDJOB> structure is followed by all these structures. The <t LMIFORMAT> structures come first.
********/
#ifndef RC_INVOKED
#pragma warning (disable: 4200)
#endif
// The basic fax job structure for any send
typedef struct _LMISENDJOB { DWORD dwTotalSize; WORD wHeaderSize; WORD fUnicode; WORD wszSenderMachineNameOffset; WORD wszSubjectOffset; DWORD dwUniqueID; DWORD dwUniqueID2; DWORD dwBillingCode; DWORD dwTotalFileSize; WORD wtmSendTimeOffset; WORD wprPollRequestOffset; WORD wrgbCustomOptOffset; WORD wNumRecipients; WORD wNumFormats; WORD wPad; DWORD rgdwStructOffsets[]; } LMISENDJOB, FAR *LPLMISENDJOB;
#ifndef RC_INVOKED
#pragma warning (default: 4200)
#endif
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types LMISENDSTATUS | Conveys back status information at the end of a send job.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field FAXERROR | feJobError | Indicates any global error which caused all recipients to fail, such as cancellation by the user, or an out of memory situation. This should only be set if none of the recipients for this message were succesfully contacted.
@field DWORD | dwUniqueID | Used by the client to uniquely identify this send fax job along with <e LMISENDSTATUS.dwUniqueID2>. This should be the same as the one passed in the <t LMISENDJOB> structure.
@field DWORD | dwUniqueID2 | Used along with <e LMISENDSTATUS.dwUniqueID> to identify this job. Should be the same as the one passed in the <t LMISENDJOB> structure.
@field WORD | fUnicode | Indicates that the <e LMISENDSTATUS.szSenderMachineName> field contains a unicode string.
@field WORD | wPad | Keep DWORD alignment. @field CHAR | szSenderMachineName[MAX_SERVERNAME_SIZE * 2] | Points to a string which identifies the machine originating this job. This should be the same as the one passed in the <t LMISENDJOB> structure.
@field LMIRECIPSTATUS | rgnrsRecipStatus[] | An array of recipient status structures, one for each recipient of the message. These structures are not required if <e LMISENDSTATUS.feJobError> is set. If present, the order of recipients in this array must be the same as the order in which they were submitted in the <t LMISENDJOB> structure.
********/ #ifndef RC_INVOKED
#pragma warning (disable: 4200)
#endif
typedef struct _LMISENDSTATUS { WORD wHeaderSize; WORD wTotalSize; FAXERROR feJobError; DWORD dwUniqueID; DWORD dwUniqueID2; WORD fUnicode; WORD wPad; CHAR szSenderMachineName[MAX_SERVERNAME_SIZE*2]; LMIRECIPSTATUS rgnrsRecipStatus[]; } LMISENDSTATUS, FAR *LPLMISENDSTATUS;
#ifndef RC_INVOKED
#pragma warning (default: 4200)
#endif
/*******
@doc EXTERNAL SRVRDLL DATATYPES
@types MACHINECAPS | This structure describes the capabilites for a fax machine. It is used to return updated capabilities for any fax machine contacted and allows intelligent preprocessing the next time a fax is sent to the same number.
@field WORD | wHeaderSize | Gives the size for the fixed size header portion of the structure.
@field WORD | wTotalSize | Total number of BYTES occupied by the structure along with its concomitant variable sized data.
@field WORD | wbDISCapsOffset | Offset to a DIS frame containing capabilities of the machine. The format of the frame is defined by the <t FR> structure. @field WORD | wbNSFCapsOffset | Offset to a sequence of encrypted Microsoft At Work NSF frames containing At Work capabilities for the machine. The format of each frame is defined by the <t FR> structure. A frame with a null type and 0 length terminates the sequence. Valid for any Microsoft At Work enabled Provider. *******/
typedef struct { WORD wHeaderSize; WORD wTotalSize; WORD wbDISCapsOffset; WORD wbNSFCapsOffset; } MACHINECAPS, FAR *LPMACHINECAPS;
/********
@doc EXTERNAL SRVRDLL INITIALIZATION
@types MODEMCAPS | Specifies all the capabilities for a logical modem. When specified by the client (for example in LMI_ExchangeCaps), the structure represents the capabilities which are supported by the client.
@field WORD | wHeaderSize | Size of this structure.
@field WORD | wTotalSize | Total size with concomitant data.
@field DWORD | dwGenCaps | Lists general capabilities. The following flags can be set: @flag OWN_ADDRESS_BOOK | Indicates that the modem can maintain it's own address book. @flag ADVANCED_STORE | Indicates that the modem can manage its own store and upload messages to it. @flag COVER_PAGE_RENDERER | Indicates that the modem can render Microsoft At Work cover page templates. @flag REAL_TIME_STATUS | Indicates that real time status updates for the current job are supported. @flag MULTIPLE_RECIPIENTS | Indicatest that messages can be sent to multiple recipients. @flag PER_RECIP_COVER | Indicates that per recipient cover pages are supported. If this is not set, the <e LMIRECIPIENT.szCoverFile> field of the <t LMIRECIPIENT> structure will not be used. @flag PER_RECIP_ENCRYPTION | Indicates that key encrypted sends to multiple recipients are supported. If this is not set, the <e LMIRECIPIENT.szEncryptFile> field of the <t LMIRECIPIENT> structure will never be used. @flag CUSTOM_MSG_OPTIONS | Indicates that the modem supports setting of custom per message options. If not set, the function <f LMI_SetCustomMsgOptions> need not be implemented. @flag POLL_REQUEST | Indicates that poll requests using T30 fields is supported. If not, the <t LMIPOLLREQUEST> structure should not be used. @flag ABOVE64K_STRUCTURES | Indicates that the <t LMISENDJOB> structure can have a total size > 64K. For x86 based systems, this allows far pointers to be used instead of huge pointers.
@flag ALLOW_SHARING | Indicates that this device can be shared.
@flag PRECIOUS_RESOURCE | Indicates that this device is a precious resource on the local machine which may need to be shared with other MAPI providers. For example, a modem which may be used by another provider to access dial-up services for mail delivery. The MAPI transport will use this flag to determine if it should support MAPI's FlushQueues semantics.
@field DWORD | dwSchedCaps | Lists scheduling related capabilities. The following flags are defined:
@flag SUPPORT_QUEUEING | Indicates whether the modem can queue up multiple jobs at a time, or can only process them one at a time. @flag ALLOW_SCHED_ASAP | Indicates that jobs can be scheduled as ASAP. @flag ALLOW_SCHED_AFTER | Indicates that jobs can be scheduled as SCHED_AFTER. @flag ALLOW_SCHED_BEFORE | Indicates that jobs can be scheduled as SCHED_BEFORE. @flag ALLOW_SCHED_CHEAPTIMES | Indicates that jobs can be scheduled for cheap times. This capability assumes that the cheap times are defined by the Provider. @flag ALLOW_CLIENT_CHEAPTIMES | Allows the client to set the cheap times independently for each job. @flag USE_UTC_TIMES | Indicates that the times indicated in the <t SENDJOBTIME> structure are in UTC and not in local time. If any of the client or the Provider do not support this capability the times will revert to being local times.
@field WORD | wmcOffset | Offset to <t MACHINECAPS> structure which should be filled in with all the capabilities which this modem has: essentially what it would send back to a caller in the DIS and NSF frames.
@field WORD | wMaxRetries | Indicates the maximum number of retries permitted for a send. The client should not set the <e SENDJOBTIME.wNumRetries> field of the <t SENDJOBTIME> structure to a number greater than this.
@field WORD | wMinTimeBetweenRetries | Specifies the minimum amount of time that can be specified between retries. The client should never set the <e SENDJOBTIME.wMinBetweenRetries> field of the <t SENDJOBTIME> structure to anything less than this.
@field WORD | wPad | Keep DWORD alignment. ********/
typedef struct { WORD wHeaderSize; WORD wTotalSize; DWORD dwGenCaps; DWORD dwSchedCaps; WORD wmcOffset; WORD wMaxRetries; WORD wMinTimeBetweenRetries; WORD wPad; } MODEMCAPS, FAR *LPMODEMCAPS;
// General caps
#define OWN_ADDRESS_BOOK 0x0001
#define ADVANCED_STORE 0x0002
#define COVER_PAGE_RENDERER 0x0004
#define REAL_TIME_STATUS 0x0008
#define MULTIPLE_RECIPIENTS 0x0010
#define PER_RECIP_COVER 0x0020
#define PER_RECIP_ENCRYPTION 0x0040
#define CUSTOM_MSG_OPTIONS 0x0080
#define POLL_REQUEST 0x0100
#define ABOVE64K_STRUCTURES 0x0200
#define ALLOW_SHARING 0x0400
#define ALLOW_RESHARING 0x0800
#define PRECIOUS_RESOURCE 0x1000
// Sched caps
#define SUPPORT_QUEUEING 0x0001
#define ALLOW_SCHED_ASAP 0x0002
#define ALLOW_SCHED_AFTER 0x0004
#define ALLOW_SCHED_BEFORE 0x0008
#define ALLOW_SCHED_CHEAPTIMES 0x0010
#define ALLOW_CLIENT_CHEAPTIMES 0x0020
#define USE_UTC_TIMES 0x0040
/********
@doc EXTERNAL SRVRDLL DATATYPES
@types SENDJOBTIME | Contains all the scheduling informations for a job.
@field WORD | wHeaderSize | Size of this structure.
@field WORD | wNumRetries | Maximum number of retries for busy numbers.
@field WORD | wMinBetweenRetries | Minutes to be allowed to elapse between successive retries.
@field SCHEDTYPE | stSchedType | Type of scheduling required for this job.
@field SYSTEMTIME | dtStartTime | Time after which job is schedulable.
@field SYSTEMTIME | dtStopTime | Time after which job is not schedulable.
********/
typedef struct { WORD wHeaderSize; WORD wNumRetries; WORD wMinBetweenRetries; SCHEDTYPE stSchedType; SYSTEMTIME dtStopTime; SYSTEMTIME dtStartTime; } SENDJOBTIME, FAR *LPSENDJOBTIME;
/****
@doc EXTERNAL SRVRDLL
@topic The Logical Modem Interface | The following section details the functions that make up the Logical Modem Interface.
****/
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_AbortSendJob | Aborts the specified send job from the Provider's queue.
@parm DWORD | dwLogicalModem | The logical modem from whose queue the job is to be cancelled.
@parm LPTSTR | lpszSenderMachineName | String identifying the sender machine name. This parameter, along with the <p dwUniqueID> and <p dwUniqueID2> uniquely identify this job for the Provider. These all must be same as the values passed in the <t LMISENDJOB> structure passed into <f LMI_SendFax>.
@parm DWORD | dwUniqueID | See <p lpszSenderMachineName>.
@parm DWORD | dwUniqueID2 | See <p lpszSenderMachineName>.
@rdesc LMI_SUCCESS on success.
@comm The abort can be performed asynchronously by the Provider. Return from this function does not imply any guarantees as to the time within which the job will be aborted. The provider reports the final state of the job via LMI_ReportSend. The client will ensure that this function is only called to abort jobs which were initiated on its machine.
********/
LMI_RETURN FAR PASCAL LMI_AbortSendJob(DWORD dwLogicalModem, LPTSTR lpszSenderMachineName, DWORD dwUniqueID, DWORD dwUniqueID2); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_AbortSendJob)(DWORD dwLogicalModem, LPTSTR lpszSenderMachineName, DWORD dwUniqueID, DWORD dwUniqueID2);
/********
@doc EXTERNAL SRVRDLL INSTALLATION
@func LMI_RETURN | LMI_AddModem | Called to add a new logical modem to the list of current modems.
@parm HWND | hDlg | The window handle of the parent dialog box. This should be used as the parent for any new dialog boxes which are displayed.
@parm LPTSTR | modembuf | Pointer to the buffer where the call should return a zero-terminated string uniquely identifying the logical modem the user selected. <p buflen> gives the maximum length this string can be (including the zero termination).
@parm WORD | buflen | Length of the buffer pointed to by <p modembuf>. This is guaranteed to be at least 64 BYTES. @rdesc The dialog should handle notifying the user of errors if it can put its first dialog up.
@comm This function is called to put up a dialog box allowing the user to select a logical modem to add to the list of current modems. The function should return a displayable string that is shown in the user list. This is also the string which is passed in to identify the modem in the <f LMI_InitLogicalModem> call.
********/
LMI_RETURN FAR PASCAL LMI_AddModem(HWND hDlg, LPTSTR modembuf, WORD buflen); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_AddModem)(HWND hDlg, LPTSTR modembuf, WORD buflen);
/********
@doc EXTERNAL SRVRDLL
@api PROVIDERSTATE | LMI_CheckProvider | Pings the Provider to see if it is alive.
@rdesc Returns state of Provider. This return value can be used to make the client poll the Provider for events.
@comm This can be called periodically by the client and should be implemented in as efficient a manner as possible. It can be used by the client to decide whether it needs to go offline among other things.
It is not mandatory for this to return a completely accurate state of the Provider. If finding this information is very expensive, the Provider can, at its discretion, do this less frequently, and return the stale state in the intermediate polls.
@parm DWORD | dwLogicalModem | Handle representing the logical modem to be checked.
@parm LPATOM | lpatError | If there was an error and the Provider is having problems, a global atom containing a descriptive string for this error can be returned here. Any string returned will be displayed to the user at the client's discretion. The atom will be freed by the client. ********/
PROVIDERSTATE FAR PASCAL LMI_CheckProvider(DWORD dwLogicalModem, LPATOM lpatError); typedef PROVIDERSTATE (FAR PASCAL FAR *LPLMI_CheckProvider) (DWORD dwLogicalModem, LPATOM lpatError);
/*******
@doc EXTERNAL SRVRDLL CONFIGURATION
@api LMI_RETURN | LMI_ConfigureModem | Called to let the user configure a logical modem.
@parm HWND | hDlg | The window handle of the parent dialog box. This should be used as the parent for any new dialog boxes which are displayed.
@parm LPTSTR | lpszModem | Pointer to string representing the logical modem to be configured. This is the same string which was returned by <f LMI_AddModem>.
@rdesc Returns LMI_SUCCESS if successful.
*******/
LMI_RETURN FAR PASCAL LMI_ConfigureModem(HWND hDlg, LPTSTR lpszModem);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_DeinitLogicalModem | Deinitializes the specified logical modem.
@parm DWORD | dwLogicalModem | Handle representing the logical modem to be deinitialized.
@rdesc LMI_SUCCESS if successful. ********/
LMI_RETURN FAR PASCAL LMI_DeinitLogicalModem (DWORD dwLogicalModem); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_DeinitLogicalModem) (DWORD dwLogicalModem);
/********
@doc EXTERNAL SRVRDLL @api LMI_RETURN | LMI_DeinitProvider| Deinitializes the LMI provider.
@rdesc LMI_SUCCESS if successful. ********/
LMI_RETURN FAR PASCAL LMI_DeinitProvider (VOID); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_DeinitProvider) (VOID);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_DisplayCustomStatus | Displays extended status information for a job.
@parm HWND | hwndParent | Parent window handle which should be used for displaying any dialogs.
@parm LPBYTE | lpbCustomData | Pointer to the start of the custom data associated with this job.
@parm WORD | wCustomDataSize | Size in BYTES of the data pointed to by <p lpbCustomData>. *********/ LMI_RETURN FAR PASCAL LMI_DisplayCustomStatus(HWND hwndParent, LPBYTE lpbCustomData, WORD wCustomDataSize); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_DisplayCustomStatus)(HWND hwndParent, LPBYTE lpbCustomData, WORD wCustomDataSize); /********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_ExchangeCaps | Allows the client and the Provider to exchangde <t MODEMCAPS> structures without having to initialize the Provider or a logical modem. This is one of two calls which can be made without an initialized modem.
@parm LPTSTR | lpszLogicalModem | Pointer to string identifying logical modem the caps belong to.
@parm LPMODEMCAPS | lpmcClient | Pointer to a <t MODEMCAPS> structure that describes the capabilities of the client. This should be used by the Provider to decide which formats can be understood by the client. For instance, if the client only understands MH, then the Provider would need to convert any received faxes into MH before reporting them in <f LMI_ReportReceives>. Similarly, this can indicate to the Provider whether or not features such as uploading of messages and Provider address books are supported by this particular client implementation. If this pointer is null, it should be ignored.
@parm LPMODEMCAPS | lpmcProvider | Points to a <t MODEMCAPS> structure which should be filled in with the capabilities of this Provider. The size of the memory pointed to by this structure is filled in the wTotalSize field of the structure. If this pointer is null, no capabilities need to be returned.
@rdesc LMI_SUCCESS on success.
@comm It is perfectly valid for a Provider to return LMIERR_NOT_SUPPORTED for this call. A Provider may need to do this if it cannot determine the modem capabilities without actually initializing the modem. ********/
LMI_RETURN FAR PASCAL LMI_ExchangeCaps (LPTSTR lpszLogicalModem, LPMODEMCAPS lpmcClient, LPMODEMCAPS lpmcProvider); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_ExchangeCaps)(LPTSTR lpszLogicalModem, LPMODEMCAPS lpmcClient, LPMODEMCAPS lpmcProvider);
/********
@doc EXTERNAL SRVRDLL
@api DWORD | LMI_GetQueueFile | Retrieves the name of the queue file for a logical modem from the Provider.
@parm DWORD | dwLogicalModem | A handle to the logical modem for which the queue is desired. If a valid handle is supplied, the <p lpszLogicalModemName> parameter should be NULL.
@parm LPTSTR | lpszLogicalModemName | A string identifying the logical modem for which the user wants to see the queue, if this modem has not been initialized previously. This is one of two APIs which can be called without initializing a modem. If this parameter is used, the <p dwLogicalModem> parameter should be ignored.
@parm LPATOM | lpatFileName | The function should return a global atom containing a fully qualified path name to the queue file. This does not have to be on the local disk. The pathname should be such that it can be passed to a Windows CreateFile call.
@parm WORD | wFlags | Can be any combination of the following flags:
@flag NGQ_USER_REQUEST | Implies that the queue update request is being made due to an explicit user refresh request. Transports which have expensive updates can use this to divide the normal refresh rate while making sure that explicit requeusts do not get ignored.
@rdesc LMI_SUCCESS on success.
@comm Ideally the client should be able to retrieve the queue for any logical modem supported by this Provider, not necessarily the one which is currently initialized. This allows the client to choose a new modem intelligently if needed.
********/
#define NGQ_USER_REQUEST 0x0001
LMI_RETURN FAR PASCAL LMI_GetQueueFile (DWORD dwLogicalModem, LPTSTR lpszLogicalModemName, LPATOM lpatFileName, WORD wFlags); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_GetQueueFile)(DWORD dwLogicalModem, LPTSTR lpszLogicalModemName, LPATOM lpatFileName, WORD wFlags);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_InitLogicalModem | Used to initialize a particular logical modem.
@parm LPTSTR | lpszLogicalModem | String identifying the logical modem to be initialized.
@parm LPDWORD | lpdwLogicalModem | A DWORD handle representing this logical modem should be returned in this pointer if the function is successful. The handle is valid until the client calls LMI_DeinitLogicalModem with this handle.
@parm LPATOM | lpatClientName | A global atom containing an ASCII name identifying this client must be returned here. This string is used in the queue displays to identify jobs from this client on the Provider. It is used by clients to restrict the jobs which can be cancelled or rescheduled from their machines, so it should be unique enough to prevent security holes. All string comparisons using this name should be case-insensitive because case is not necessarily preserved when using atoms.
@parm LPATOM | lpatPhone | A global atom containing the canonical phone number for this logical modem. This is used to construct the client's Microsoft At Work Address, and is the number put into the FROM field of any messages sent. This needs to be filled in if a non-null pointer is passed in.
@parm LPMODEMCAPS | lpmc | Points to a <t MODEMCAPS> structure which should be filled in with the capabilities of this logical modem. The size of the memory pointed to by this structure is filled in the wTotalSize field of the structure. If this pointer is null, no capabilities need to be returned.
@rdesc LMI_SUCCESS if successful. A handle to the logical modem should be returned in <p lpdwLogicalModem>.
@comm Initializes a logical modem for further operations. The Provider should use this to set up any necessary connections, and to make sure that the Provider is up and running. The handle returned by this function is used by any subsequent functions invoked for this modem. Multiple modems may be initialized at the same time. The handle returned may be used in multiple process contexts, so the implementor should make sure any memory it references can be accessed in different process contexts. ********/
LMI_RETURN FAR PASCAL LMI_InitLogicalModem (LPTSTR lpszLogicalModem, LPDWORD lpdwLogicalModem, LPATOM lpatClientName, LPATOM lpatPhone, LPMODEMCAPS lpmc); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_InitLogicalModem) (LPTSTR lpszLogicalModem, LPDWORD lpdwLogicalModem, LPATOM lpatClientName, LPATOM lpatPhone, LPMODEMCAPS lpmc);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_InitProvider | Used to initialize the LMI provider.
@parm LPTSTR | lpszCurSpoolDir | Pointer to the current spool directory. The spool directory is where all intermediate format files get created, and where the client expects received fax files.
@parm LPMODEMCAPS | lpmcClient | Pointer to a <t MODEMCAPS> structure that describes the capabilities of the client. This should be used by the Provider to decide which formats can be understood by the client. For instance, if the client only understands MH, then the Provider would need to convert any received faxes into MH before reporting them in <f LMI_ReportReceives>. Similarly, this can indicate to the Provider whether or not features such as uploading of messages and Provider address books are supported by this particular client implementation.
@parm LPTSTR | lpszDefRecipAdd | For incoming G3 faxes for which the recipient is unknown, this address should be used. This typically happens for faxes received from G3 machines without a programmed CSI. In this case, this address should be put inside the linearized header on the AWG3 file. If this address ends in an <lq>@<rq> the Provider should append the phone number of the modem on which the fax was received, as well as any locally-obtained subaddressing information, using the Microsoft Fax Address format. For example, if the provider detects a DID string \<did\>, it should append <lq>\<local-phone-number>\|\<did\><rq> after the <lq>@<rq> sign.
@parm LPTSTR | lpszDefRecipName | Friendly name to be used for the default recipient. Goes along with <p lpszDefRecipAdd> to form an address pair.
@rdesc LMI_SUCCESS if successful.
@comm This call is made once per session. It is guaranteed to be the first call made to the Provider.
********/
LMI_RETURN FAR PASCAL LMI_InitProvider (LPTSTR lpszCurSpoolDir, LPMODEMCAPS lpmc, LPTSTR lpszDefRecipAdd, LPSTR lpszDefRecipName); typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_InitProvider) (LPTSTR lpszCurSpoolDir, LPMODEMCAPS lpmc, LPTSTR lpszDefRecipAdd, LPSTR lpszDefRecipName);
/********
@doc EXTERNAL SRVRDLL INSTALLATION
@func LMI_RETURN | LMI_RemoveModem | Called when a logical modem is removed from the list of current modems.
@parm LPTSTR | lpszModem | Pointer to the string identifying the logical modem being removed.
@rdesc Returns LMI_SUCCESS if successful.
@comm This call should be used to delete any context which has been cached for this logical modem. For instance, if in the <f LMI_AddModem> call, a lot of connection information had been stored in an ini file with the key being returned as the logical modem name, then this call would be used to delete this information.
********/
LMI_RETURN FAR PASCAL LMI_RemoveModem(LPTSTR lpszModem); typedef LMI_RETURN (FAR PASCAL FAR * LPLMI_RemoveModem)(LPTSTR lpszModem);
/********
@doc EXTERNAL SRVRDLL
@api DWORD | LMI_ReportReceives | Lets LMI provider report back received faxes.
@parm DWORD | dwLogicalModem | Handle representing the logical modem to be checked. If this is null, all logical modems owned by this Provider should be checked.
@parm WORD | wFlags | Can consist of a combination of the following flags:
@flag NRR_USER_REQUEST | This flag will be set if new faxes are being checked for on an explicit user request. This is meant for transports which tend to reduce the number of times they actually check for receives to reduce overhead. Providers should make sure to do the checks when this flag is set. @flag NRR_RETRIEVE_DATA | Set if the client wishes to process the 1st receive in the queue. If set, the provider fills out a LMIRECVSTATUS structure and specifies a pointer to it in *lplpnrtStatus. If the client makes successive calls specifying NRR_RETRIEVE_DATA (but not NRR_COMMITTED_RECV), information on the same receive (the 1st one on the queue) should be returned. Each time, a fresh atom needs to be allocated for the atFile field in LMIRECVSTATUS, and the client is responsible for freeing this atom. If this flag is not set, indicates that the client wants to simply find out if there are any receives waiting, and the provider should ignore lplpnrtStaus.
@flag NRR_COMMITTED_RECV | Indicates that the previous receive has been committed to permanent storage by the client and can be deleted by the Provider from its queue. It also indicates that the memory used for the LMIRECVSTATUS structure for that job can be freed or reused. Until this point, the Provider must not remove the received fax from its internal permanent storage. This helps avoid a fax being lost if the power goes off in the middle of the handoff. In the worst case, it causes two copies of the received fax to be processed instead of none. If this flag is specified, NRR_RETRIEVE_DATA is irrelevant and if specified should be ignored by the provider.
@parm LPDWORD | lpdwNumRecvs | Pointer to a DWORD which should be filled in with the number of new received faxes which are waiting to be picked up. If NRR_RETRIEVE_DATA is set in wFlags, the received fax being returned in the current call should not be included in this count. @parm LPLMIRECVSTATUS FAR* | lplpnrtStatus | Pointer to a pointer which should be set to point to a <t LMIRECVSTATUS> structure. The client assumes this pointer to point into accesible memory which is valid until the next call made with the flag NRR_COMMITTED_RECEIVE set. There can never be more than one pending receive, so a single piece of memory can be reused. This should be set only if <p wFlags> has the RETRIEVE_DATA flag set. The atom passed in this structure will be freed by the client. It should be set to null if there are no receives.
@rdesc Returns LMI_SUCCESS if succesful.
@comm It is possible for receives to be routed independent of this API directly to the client's mail store. This would happen if the client and Provider could communicate using another mail transport (such as Microsoft SFS) to do this more easily. ********/
#define NRR_USER_REQUEST 0x0001
#define NRR_RETRIEVE_DATA 0x0002
#define NRR_COMMITTED_RECV 0x0004
LMI_RETURN FAR PASCAL LMI_ReportReceives(DWORD dwLogicalModem, WORD wFlags, LPDWORD lpdwNumRecvs, LPLMIRECVSTATUS FAR *lplpnrtStatus);
typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_ReportReceives)(DWORD dwLogicalModem, WORD wFlags, LPDWORD lpdwNumRecvs, LPLMIRECVSTATUS FAR *lplpnrtStatus);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_ReportSend | Reports status of completed send jobs.
@parm DWORD | dwLogicalModem | Handle representing the logical modem to be checked. If this is null, all logical modems owned by this Provider should be checked.
@parm WORD | wFlags | Can consist of a combination of the following flags:
@flag NRS_USER_REQUEST | This flag will be set if the fax status is being checked for on an explicit user request. This is meant for transports which tend to reduce the number of times they actually check for receives to reduce overhead. Such transports should make sure to do the checks when this flag is set. @flag NRS_RETRIEVE_DATA | If set, indicates that the client wishes to process the status for the first one in the queue. If not set, indicates that the client wants to simply find out if there are any jobs completed.
@parm LPDWORD | lpdwNumDone | Pointer to a DWORD which should be filled in with the number of jobs which have been completed and are waiting to be picked up. If NRS_RETRIEVE_DATA flag is set, then this should be filled in with the number of jobs left not counting the one being returned in this call. @parm LPLMISENDSTATUS FAR* | lplpnstStatus | Pointer to a pointer which should be set to point to a <t LMISENDSTATUS> structure. The client assumes this pointer to be valid until the next call it makes to this function. It should be set to null if there are no completed sends. It should only be filled in if NRS_RETRIEVE_DATA is set in wFlags.
@rdesc Returns LMI_SUCCESS if succesful. ********/
#define NRS_USER_REQUEST 0x0001
#define NRS_RETRIEVE_DATA 0x0002
LMI_RETURN FAR PASCAL LMI_ReportSend(DWORD dwLogicalModem, WORD wFlags, LPDWORD lpdwNumDone, LPLMISENDSTATUS FAR *lplpnstStatus);
typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_ReportSend)(DWORD dwLogicalModem, WORD wFlags, LPDWORD lpdwNumDone, LPLMISENDSTATUS FAR *lplpnstStatus);
/********
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_RescheduleSendJob | Reschedules the specified send job from the Provider's queue.
@parm DWORD | dwLogicalModem | The logical modem in whose queue the job to be rescheduled lives. This does not have to be the currently active modem.
@parm LPTSTR | lpszSenderMachineName | Pointer to a string identifying the sender machine name. This parameter, along with the <p dwUniqueID> and <p dwUniqueID2> uniquely identify this job for the Provider. These all must be same as the values passed in the <t LMISENDJOB> structure passed into <f LMI_SendFax>.
@parm DWORD | dwUniqueID | See <p lpszSenderMachineName>.
@parm DWORD | dwUniqueID2 | See <p lpszSenderMachineName>.
@parm LPSENDJOBTIME | lpsjtNewTime | Pointer to a new <t SENDJOBTIME> structure containing the reschedule information.
@rdesc LMI_SUCCESS on success.
@comm The reschedule can be performed asyncronously by the Provider. Return from this function does not imply any guarantee as to the time within which the job will be rescheduled. The client will ensure that this function is only called to reschedule jobs which were initiated on its machine.
********/
LMI_RETURN FAR PASCAL LMI_RescheduleSendJob (DWORD dwLogicalModem, LPTSTR lpszSenderMachineName, DWORD dwUniqueID, DWORD dwUniqueID2, LPSENDJOBTIME lpsjtNewTime);
typedef LMI_RETURN (FAR PASCAL FAR *LPLMI_RescheduleSendJob) (DWORD dwLogicalModem, LPTSTR lpszSenderMachineName, DWORD dwUniqueID, DWORD dwUniqueID2, LPSENDJOBTIME lpsjtNewTime);
/*******
@doc EXTERNAL SRVRDLL
@api LMI_RETURN | LMI_SendFax | Accepts a job for sending. Job is already completely rendered.
@parm DWORD | dwLogicalModem | Handle representing the logical modem from which this should be sent.
@parm LPLMISENDJOB | lpnj | Points to a <t LMISENDJOB> structure containing all the pertinent information about this job. The structure is allocated by the client and is freed on return of this call.
@rdesc Returns LMI_SUCCESS if the job is accepted. A successful return of this function implies that the job has been queued for subsequent processing and transmission. This function should fail only if there is a general failure in the provider or a parameter validation failure. Processing or transmission failures should be returned in the appropriate <f LMI_ReportSend> call.
*******/
LMI_RETURN FAR PASCAL LMI_SendFax (DWORD dwLogicalModem, LPLMISENDJOB lpnj);
typedef LMI_RETURN (FAR PASCAL FAR * LPLMI_SendFax) (DWORD dwLogicalModem, LPLMISENDJOB lpnj);
/*******
@doc EXTERNAL SRVRDLL
@api LPBYTE | LMI_SetCustomMsgOptions | This function is called to allow the user to set custom per message options.
@parm DWORD | dwLogicalModem | Handle representing the logical modem which is currently in use.
@parm LPBYTE | lpbOld | Pointer to a previously returned piece of memory which needs to be freed. If this parameter is being used the function should simply free the memory and return without putting up any UI.
@rdesc Returns a pointer to a memory block containing all the custom information which has been set. The first DWORD of the block MUST contain the total size of the memory being used. This data will be passed along with the <t LMISENDJOB> structure when this message is finally submitted. The memory will be freed by calling this same API again with the memory pointer passed in as a parameter. @comm This function can be used to enable all kinds of advance options to the user. One example of this could be usage of TAPI locations and credit cards for calls. If the Provider can support these, it can allow the user to setup credit card calls and then use these when resolving the phone numbers into dialable strings. If the Provider is using the TAPI translation services, the user could select a specific outbound device or line for the call, and do a credit card ID override on cards setup on the Provider TAPI setup.
*******/
LPBYTE FAR PASCAL LMI_SetCustomMsgOptions(DWORD dwLogicalModem, LPBYTE lpbOld); typedef LPBYTE (FAR PASCAL FAR *LPLMI_SetCustomMsgOptions)(DWORD dwLogicalModem, LPBYTE lpbOld);
#ifdef __cplusplus
} // extern "C" {
#endif
#endif
|