传真服务

类别:VC语言 点击:0 评论:0 推荐:

这个又是先贴到记事本然后贴过来的,格式没有了,呵呵

这个也是很久以前的东西,如果有地方不准确的话,还请大家见谅!

里面的插图大家可以看msdn(这里不能直接拷贝进来图形,好麻烦,sorry)

传真服务篇
第1章 微软传真服务简介
微软®传真服务是使网络用户可以从应用程序中收发传真的一种兼容TAPI(电话应用程序接口)的系统服务,此服务可在微软®Windows® 2000及以后版本获得并具有以下特点:
⑴传送传真
⑵灵活的接收传真
⑶存档已发送的传真文件
⑷服务器和设备配置管理
下表详细列出了可用来开发传真客户程序和扩展传真服务的应用程序接口(API)。        
传真服务客户API 软件开发者能在客户应用程序里合并基本的传真函数,包括输出传真服务、查询和管理传真作业及传真设备。
传真路由扩展API 第三方的软件供应商通过定义输入传真路由扩展来扩展传真服务。此扩展提供了一种灵活的方法以连接接收传真的应用程序,如:打印、保存传真,变换传真图形图像到文本文件等。
传真服务供应商API 传真设备制造商提供符合国际电信联盟(ITU)T.30 规范的非调制解调器电话设备支持的传真服务供应商。(微软调制解调器传真服务供应商提供 的T.30传真协议支持带有传真服务调制解调器设备。)
下图显示了传真服务的基本结构
 
传真服务供应商和传真路由扩展动态链接库(DLLs)由微软®或设备制造商(OEM)提供。
第2章 传真服务客户应用程序接口( API )
传真服务客户API允许客户在其应用程序中合并基本传真功能。此项技术适用于运行windows 2000及更高版本的计算机。API包括win32函数和COM双重接口实现。
本章第一部分构画使用传真服务客户 API可以实现的任务及支持该功能所需的组件,同时也描述了传真服务的安全性,最后对传真端口、传送传真、传真封面和传真路由方法进行了简洁讨论。第二部分讨论win32和COM实现环境下传真程序的差别。还讨论了传真客户函数、COM双重接口以及下列有关的编程任务。
⑴连接到传真服务器
⑵传真服务器配置管理
⑶传真设备管理
⑷管理传真路由数据
⑸发送传真
⑹管理传真作业
⑺释放传真资源
⑻断开与传真服务器的连接
注:在阅读本篇之前,应该对电话应用编程接口( TAPI )和微软®电话服务供应商( TSPI ) 有所熟悉,如果计划使用传真客户的COM实现,也应该熟悉COM (部件对象模型)和自动化编程概念。
2.1、传真服务客户 API 简介
微软®的传真服务为在本地网(LAN)上的客户提供传真服务。传真服务客户 API 允许开发者在其应用程序里合并服务并激活基本传真功能。传真服务客户API 包括Win32 函数接口和 COM 接口。
⑴Win32 环境
Win32 函数作为动态链接库 WinFax.dll文件被实现。这是一种客户机/服务器实现模式,允许远程计算机上的传真客户与使用 RPC 的传真服务器进行通讯。客户机可以使用共享网络传真打印机访问输出传真服务,或者应用程序可以调用传真服务客户 API中的函数连接一台远程传真服务器进行传真传送。        
⑵ COM 实现环境
COM 接口作为双重接口被VB和C/C++程序员接纳与实现。本文为两种编程语言均提供参考资料。
下图显示了传真客户应用程序的概貌:
 
要实现传真服务,必须在原代码文件中包含WinFax.h 头文件,而要使用微软支持的传真客户COM实现则必须包含 FaxCom.h头文件。                             
2.1.1、传真服务客户API功能
   传真服务客户 API使传真客户应用程序可以执行下列任务:
  ⑴传送一个存储于计算机中的文档。应用程序能把文档作为一份传真传送到一个或广播到多个程序定义的接受者。
  ⑵传送一张封面页。用户可以用传真传送一张封面页,该封面可为服务器上的公用封面页,也可以是一张个人的封面页。
  ⑶通过将打印文档为设备上下文来传送活动文档。基于文档的应用程序可以阻止传真发送向导的显示。程序能够直接为传真客户图形设备接口(GDI)提供传送信息,并且将它打印到一个传真设备上下文来传送一份活动文档。
⑷传送一份传真文档到活动调用。使用已经存在的输入链接线路来传送文档可以节约发送传真的费用,这就是所谓的“Faxback服务”。
⑸使用传真发送向导发送活动文档。用户可以通过把文档打印到传真打印机来传送该文档。传真发送向导会收集用户的传送信息,而开发者则只需使用打印功能即可。
⑹改变传真设备和传真服务器的配置。应用程序可提供配置管理或可使用微软管理控制台( MMC ) 插件组件中的传真配置服务管理应用程序来进行配置。
2.1.2、传真服务客户 API 软件要求
下列组件被要求支持传真服务客户API的功能 :
⑴ 传真服务( FaxSvc.exe )。支持传真服务的应用程序可以管理传真设备、配置数据、提供打印服务并收发传真文件。通过传真路由扩展传真服务也可以初始化和重发输出传真路由方法。
⑵winFax.lab。包含传真服务客户 API功能的静态链接库。
⑶winFax.dll。包含传真服务客户 API 功能的动态链接库。
此外,必须在源代码文件中包括 WinFax.h 头文件;而使用微软支持的传真客户 COM 实现,则须包括 FaxCOM.h头文件。
传真服务可以与使用 RPC 的网络客户机进行通讯。尽管不需要在每台客户计算机上安装传真服务,但服务一定要可以由 RPC访问到客户计算机。
2.1.3、传真服务可执行文件和相关文件
下列表格描述了与传真服务相关的可执行文件、 DLL和头文件。
文件名 描述
FaxSvr.exe 管理传真设备、配置数据、提供打印服务和收发传真文件的传真服务支持应用程序,
FaxAdmin.dll 微软管理控制台( MMC )插件组件之一的传真服务管理应用程序,提供配置管理功能。
FaxMon.dll 包含传真打印监视器的动态链接库
WinFax.dll 包含传真服务客户API功能的动态链接库
WinFax.lib 包含传真服务客户API功能的静态链接库  
FaxCom.dll 传真服务客户API的COM接口
FaxCover.exe 传真封面页编辑应用程序
FaxExt32.dll 包含 MAPI用户接口扩展的动态链接库
FaxXp32.dll 包含传真邮件传送功能的动态链接库。 
FaxRoute.dll 包含微软®传真路由扩展的动态链接库。
FaxDev.h 包含传真服务供应商 API 原型的头文件。
FaxRoute.h 包含传真路由扩展API 原型的头文件
WinFax.h 包含传真客户服务 API Win32环境原型的头文件
FaxT30.dll 包含微软®调制解调器传真服务提供商的动态链接库
FaxDrv.dll 传真打印机驱动程序动态链接库
FaxUi.dll 传真打印机驱动程序动态链接库
2.1.4、设备和配置管理
传真服务提供的传真服务管理应用程序是微软管理控制台( MMC )插件组件之一,传真客户程序可以进行配置管理或使用管理程序进行下列配置管理任务:
 ⑴指定收发传真的器件
 ⑵指定可在端口上执行的路由方法
 ⑶配置全局服务数据
2.1.5、传真端口
本章中,传真端口始终被看作是一台传真设备以及与设备相联系的配置和与输入信息路由,传真服务为用户提供一个或多个传真端口作为传真传送的终点。
传真虚拟设备也存在传真端口,这就意味着传真可以输出到连接至传真服务器的非严格物理设备终端。支持互联网传送传真的传真服务供应商即是使用虚拟传真设备的供应商的例子。
2.1.6、传真端口的访问级别
传真服务客户 API 允许应用程序查询和修改传真端口的配置数据。
⑴Win32环境
为了使用户能访问个端口的配置数据, 传真客户应用程序在调用 FaxOpenPort函数时,必须指定正确的传真端口访问级别。FaxOpenPort 返回传真端口句柄并根据指定的访问级别打开端口。应用程序根据用户的需求和许可,可查询下列值:
值 意义
PORT_OPEN_QUERY 调用FaxGetPort、 FaxEnumPort和FaxGetDeviceStatus 函数查询传真端口信息的端口访问级别
PORT_OPEN_MODIFY 调用FaxSetPort 函数修改传真端口配置的端口访问级别,默认为是与PORT_OPEN_QUERY访问级别联系的访问权限。
除了要求端口用恰当的访问级别打开之外,传真服务也要求用户查询并且修改端口数据时,要有恰当的访问权限。要获得传真端口句柄和查询端口数据,用户必须获得FAX_PORT_QUERY许可;要修改端口数据,用户必须获得 FAX_PORT_SET 许可。
传真客户应用程序可以调用 FaxAccessCheck函数查询用户的访问权限。也可使用微软管理控制台( MMC )插件组件之一的传真服务管理应用程序来修改用户端口访问权限。
⑵COM实现环境
在应用程序调用修改FaxPort属性的方法之前,须调用 IFaxPort::get CanModiFy方法(检索 V B 中FaxPort对象的CanModify 属性)以确保客户有权修改端口的配置。
2.1.7、传真客户程序的用户访问权限
传真服务是一种安全的服务。在 Win32 环境下,用户必须拥有访问权限以成功调用某一传真客户程序函数,每次客户程序调用传真客户程序函数前服务均进行访问权限检查。应用程序可以由调用 FaxAccessCheck 函数来检查用户的访问权限,。
如果使用微软®的 COM 实现,则此时传真客户应用程序无法获得该项功能。若客户没有执行特定任务的访问权限,则方法或函数失败且返回HRESULT_FROM_WIN32 ( ERROR_ACCESS_DENIED )。
微软管理控制台( MMC )插件组件之一传真服务管理应用程序,为用户提供查询和修改作业访问权限、端口访问权限和全局配置数据访问权限。
下面就详细叙述传真访问权限的内容。
  2.1.7.1、特定传真访问权限
如果使用微软 COM 实现,则此时传真客户应用程序无法利用此项功能。
传真服务客户API 定义下列特定访问权限,为用户查询和管理传真作业、传真设备和传真文档提供安全保障。        
值 意义
FAX_CONFIG_QUERY 允许在传真服务器级查询配置和路由方法数据
FAX_CONFIG_SET 允许在传真服务器级修改配置和路由方法数据
FAX_JOB_MANAGE 允许在程序中终止传真作业或改变传真作业队列的状态
FAX_JOB_QUERY 允许查询队列中和活动传真作业
FAX_JOB_SUBMIT 允许发送传真到一个或多个接收者
FAX_PORT_QUERY 允许在端口级查询配置、状态和路由算法数据;此访问权限有获取和关闭传真端口句柄的能力
FAX_PORT_SET 允许在端口级修改配置和路由方法数据;此权限有启用或屏蔽传真路由算法的能力
2.1.7.2、通用传真访问权限
如果使用微软 COM 实现,则此时传真客户应用程序无法利用此项功能。
传真服务客户API 定义下列通用传真访问权限,公共权限默认用户有特定传真访问权限:
值 意义
FAX_READ 包含由由特定访问权限FAX_JOB_QUERY、FAX_CONFIG_QUERY 和 FAX_PORT_QUERY认可的只读权限
FAX_WRITE 此访问等同于FAX_JOB_SUBMIT特定访问权限认可的许可。注意此权限不包括在端口或服务器级修改数据许可。
FAX_ALL_ACCESS 包括由下列特定访问权限认可的所有的读写许可: FAX_CONFIG_QUERY、 FAX_CONFIG_SET、FAX_JOB_MANAGE、FAX_JOB_QUERY、FAX_JOB_SUBMIT、FAX_PORT_QUERY和FAX_PORT_SET
2.1.7.3、函数要求的传真访问权
下列表格列出了win32环境下,用户成功地调用某个传真客户函数后可获得的访问权限。
访问权限 函数
FAX_CONFIG_QUERY(传真配置查询) FaxEnumGlobalRoutingInFo
 FaxGetConFiguration
 FaxGetLoggingCategories
FAX_CONFIG_SET(传真配置设置) FaxSetConFiguration 
 FaxSetGlobalRoutingInFo 
 FaxSetLoggingCategories
FAX_JOB_QUERY(传真作业查询) FaxEnumJobs
 FaxGetJob
 FaxGetPageData
FAX_JOB_SET(传真作业设置) FaxAbort
 FaxSetJob
FAX_JOB_SUBMIT(传真作业提交) FaxSendDocument
 FaxSendDocumentForBroadcast
FAX_PORT_QUERY(传真端口查询) FaxClose
 FaxEnumPorts*
 FaxEnumRoutingMethods
 FaxEnumRoutingMethods
 FaxGetDeviceStatus*
 FaxGetPort*
 FaxGetRoutingInFo
 FaxOpenPort
FAX_PORT_SET(传真端口设置) FaxEnableRoutingMethod 
 FaxSetPort* 
 FaxSetRoutingInFo
*此函数要求特定传真端口访问级。   
注意:FAX_JOB_MANAGE 访问级别允许用户调用FaxAbort 函数和FaxSetJob 函数。                                                           2.1.8、传送传真
传送输出传真有以下要点:
⑴文档文件。传真服务转换数据为传真的标签图象文件格式F类格式(TIFF 6.0 F类)。
⑵发送信息。该信息包括传真序号、发送者和接收者数据、可选的账单编码方式以及作业安排信息。在 Win32 环境下,如果将应用程序打印到设备上下文,则FAX_PRINT_INFO结构会包含此信息否则由FAX_JOB_PARAM 结构包含信息。如果使用微软®COM 实现方式,可以设置 FaxJob对象的多重属性来指定发传信息。
⑶可选封面页文件。在 Win32 环境下,FAX_COVERPAGE_INFO 结构包含此数据,该结构提供封面页模板文件名 (.cov)及用户自定义的模板信息。如果使用微软®COM 实现,可设置FaxDoc对象的多重属性来指定封面页息。
2.1.9、封面页
封面页是一个封面页模板文件( .cov )和传真传送时提供给模板的用户自定义信息。
传真服务客户 API 支持封面页打印。封面页可为存储在本地计算机上的个人封面页文件,或为存储在传真服务器上存储的公共封面页。要获取封面页,用户必须提供应封面页文件的完整合法路径或公共封面页文件的相对路径。
典型情况下,管理器将公共封面页文件存储在如下的位置:
\\SERVERNAME\FAX$\Coverpg
在个人计算机系统上,公共封面页文件存储于:
CSIDL_APPDATA\MicrosoFt\Windows NT\MSFax\coverpg
用户能够通过使用传真控制面板应用程序来添加个人封面页文件,但此文件必须存储于用户“我的文档”标准文件夹的如下位置:
CSIDL_PERSONAL\Fax\Personal Coverpages
此外,在 Win32 环境下,如果用户要指定一个公共封面页文件,就必须设置 FAX_COVERPAGE_INFO结构的UseServerCoverPage 成员为真。而在COM 实现环境下,则须设置FaxDoc对象的ServerCoverpage属性为真。
一个传真客户应用程序可以调用 FaxPrintCoverPage 函数将封面页打印到传真打印机设备上下文。
2.1.10、传真路由方法
传真路由方法是由传真路由扩展动态链接库(DLL)定义的一种程序。当传真端口收到输入传真时,按照优先级顺序执行传真路由方法。
由于以下原因,我们需要使用GUID来确定传真路由方法:
⑴一个传真路由扩展DLL可以支持多个路由方法。
⑵一个传真路由扩展DLL 可以为每个路由方法和传真设备提供唯一的配置数据。
⑶多重传真路由扩展 DLLs可用相同的名字输出路由方法。
2.1.11、传真客户API编程任务
下面我们就具体描述在传真客户应用程序中,要求合并传真服务客户 API功能的典型任务。
2.1.11.1、win32传真客户编程任务
以下步骤总结了在win32编程环境下,编写一份传真客户应用程序需要合并传真服务客户API功能的典型编程任务。 
⑴调用FaxconnectFaxsever函数连接到传真服务器。注意除非服务器是本地计算机,否则应用程序必须提供服务器名。
⑵必要时,可调用一个或多个传真服务枚举函数。这些函数允许用户查看与传真服务器相连的传真端口和与端口相连的路由信息,也允许用户查看活动传真作业列表。这些枚举函数包括FaxEnumGlobalRoutingInFo、 FaxEnumJobs、 FaxEnumPorts和FaxEnumRoutingMethods函数。
⑶调用FaxOpenPort函数获取传真端口句柄。
⑷必要时,可调用FaxGetRoutingInFo、FaxSetRoutingInFo和FaxEnableRoutingMethod函数之一或多个来查询和修改传真端口的路由信息。
⑸可以调用FaxSendDocument或 FaxSendDocumentForBroadcast 函数来传送传真文件。注意应用程序必须提供诸如传真序号和接收者数据之类的传送信息。
⑹调用FaxFreebuFFer函数来释放应用程序调用FaxCOMpletejobparams函数以及Faxenum或Faxget开始的函数时所分配的资源。
⑺分两次调用FaxClose 函数。第一次调用断开应用程序与传真端口的连接,第二次调用则断开应用程序与传真服务器的连接。
此外,应用程序需要调用其它函数来查询设备或服务器配置数据、管理传真作业以及打印传真。
2.1.11.2、在C/C++程序中使用 COM 实现
以下步骤总结了COM实现环境下,用C/C++编写一份传真客户应用程序需要合并传真服务客户API功能的典型编程任务。
⑴调用CoCreateInstance函数创建一个FaxServer对象实例,然后调用IFaxServer::Connect 接口方法连接到活动传真服务器。
⑵调用下列iFaxsever接口方法中的一个或多个来创建所需对象:
a.调用IFaxServer::GetJobs 方法创建一个 FaxJobs对象,然后使用此对象创造 FaxJob 对象并枚举与所连结传真服务器的相关传真作业。
b.调用IFaxServer::Getports方法创建一个 Faxports对象,然后使用此对象创造 Faxport 对象并枚举与所连结传真服务器的相关传真端口配置信息。
c.调用IFaxServer::CreateDocument方法创建一个Faxdoc对象,然后使用此对象来发送传真以及检索和设置Faxdoc对象属性。
⑶在为特定端口创建FaxPort对象实例之后,即可调用 IFaxPort::GetRoutingMethods 接口方法创建FaxRoutingMethod对象,当然也可调用IFaxRoutingMethods::get_Item 接口方法创建FaxRoutingMethod对象。FaxRoutingMethod对象允许程序员查询和修改传真端口的传真路由信息。
⑷调用IFaxPort::GetStatus接口方法即可创建Faxstatus对象,该对象允许程序员提供关于端口的实时状态信息。
⑸在创建好Faxdoc对象实例之后,就可以调用IFaxDoc::Send 接口方法来发送一份传真文件。注意,应用程序必须提供诸如传真序号和将发送文件的名称之类的信息。用户也能通过设置Faxdoc对象的多种属性来提供其它需要显示在封面页上的数据。
⑹调用sysFreestring函数即可释放以get_PropertyName结束的所有接口方法分配的资源。
⑺调用IFaxServer::Disconnect 接口方法终止与传真服务器的连接,然后调用IUnknown::Release 方法释放FaxServer 对象自身。
此外, 要查询设备或服务器配置数据、管理传真作业和销毁附加接口指针应用程序需要调用其它接口方法,而用户若要检索传真服务已发送或接收的文件信息则需创建一个FaxTiFF 对象实例及调用IFaxTiFF接口方法。
注意客户应用程序必须调用CoCreateInstance函数来创建FaxServer 或 FaxTiFF对象的实例。但是,不能调用CoCreateInstance函数来创建 FaxDoc 、 FaxJobs 、 FaxJob 、 FaxPorts 、 FaxPort 、 FaxStatus 、FaxRoutingMethods或FaxRoutingMethod对象。
 2.1.11.3、在VB程序中使用 COM 实现
以下步骤总结了COM实现环境下,用VB编写一份传真客户应用程序需要合并传真服务客户API功能的典型编程任务。
⑴调用VB的CreateObject函数创建一个FaxServer对象实例,然后调用对象的Connect方法连接到活动传真服务器。
⑵可调用下面FaxServer对象方法的一个或多个来创建所需的其它对象:
a.调用GetJobs方法创造一个 FaxJobs对象后,即可使用该对象创建FaxJob对象和枚举与所连接传真服务器相关的传真作业。
b.调用GetPorts方法创建一个 FaxPorts对象后,即可使用该对象创建 FaxPort对象和枚举所连接传真服务器的传真端口配置信息。
c.调用CreateDocument后方法创建一个 FaxDoc对象,即可使用该对象来传送传真以及检索和设置 FaxDoc对象属性。
⑶为特定端口创建一个FaxPort对象实例后,调用该对象的GetRoutingMethods方法即可创建FaxRoutingMethods对象。
⑷调用 FaxRoutingMethods 对象的Item方法即可创建FaxRoutingMethod对象,该对象允许用户查询和修改传真端口的传真路由信息。
⑸调用FaxPort对象的 GetStatus方法可以创建FaxStatus对象,该对象允许用户提供实时的传真端口状态信息。
⑹创建好FaxDoc对象的实例后,即可调用对象的Send方法传送一份传真文件。注意应用程序必须提供诸如传真序号和传送文件名之类的信息。客户也可以通过设置 FaxDoc 对象的不同属性,提供在封面页上出现的其它数据。
⑺调用FaxServer对象的Disconnect方法可终止与服务器的连接。
此外,要查询服务器和设备配置参数以及管理传真作业应用程序就需要设置其它的属性和调用其它方法,而用户若要检索有关传真服务已经收发文件的信息则需创建一个FaxtiFF对象实例来完成该任务。
2.1.12、连接到传真服务器
大多数情况下,传真客户应用程序在使用传真特性前必须连接到传真服务器。
⑴ win32环境
要连接到传真服务器,传真客户应用程序在调用其它任何传真客户函数前,必须首先成功调用 FaxConnectFaxServer 函数。该函数返回调用其它传真客户函数所要求的传真服务器句柄。
注意,到传真服务器的连接并不要求把传真文档打印到传真打印机设备上下文。程序能直接给传真客户图形设备接口( GDI )函数提供传送信息,并通过打印到打印机设备上下文来传送活动文档。传真客户GDI函数包括FaxStartPrintJob和FaxPrintCoverpage函数。
调用FaxClose函数断开到传真服务器的连接并释放FaxConnectFaxServer函数返回的句柄。
⑵COM实现环境
在C/C++应用程序中,开发者须调用CoCreateInstance函数来检索指向IFaxServer接口的指针并创建一个FaxServer对象实例。随后调用IFaxServer::Connect方法初始化与活动传真服务器的连接。在应用程序可以访问以iFax开始的大多数接口之前,要求其必须连接到服务器。(若访问iFaxtiFF接口则不必连接到传真服务器。)
在vb应用程序中,开发者则须调用vbCreateObject函数创建一个 FaxServer 对象实例,然后调用FaxServer对象的Connect方法初始化与活动传真服务器的连接。在应用程序可以访问以Fax开始的大多数对象之前,要求其必须连接到服务器。(若访问FaxtiFF接口则不必连接到传真服务器。)  
2.1.12、传真服务器配置管理
传真服务客户 API支持对传真服务器配置数据进行改变,并提供服务器级别的配置选项。
2.1.12.1、管理全局配置数据
必须与活动传真服务器连接才能检索和改变其配置信息,这些信息包括对传送、标记、存档和封面页的设置以及贴现率周期和传真服务器状态队列。
⑴. Win32环境下
FaxGetConFiguration 函数允许传真客户应用程序查询传真服务器的全局配置设置。函数在FAX_CONFIGURATION 结构中返回查询信息。
FaxGetConFiguration函数分配FAX_CONFIGURATION 结构所要求的内存,因此应用程序必须调用FaxFreeBuFFer函数来释放已分配的资源。应用程序可调用 FaxSetConFiguration 函数,来修改传真服务器的全局配置设置。
注意;应用程序在调用 FaxGetConFiguration函数和FaxSetConFiguration函数前,须先调用 FaxConnectFaxServer函数以获取传真服务器的句柄。
⑵.COM实现环境
在检索和设置有关FaxServer 对象的信息前,须先连接到活动的传真服务器。
C/C++应用程序中,可使用 IFaxServer 接口的属性方法检索和设置 FaxServer对象的全局信息;vb应用程序中,可直接检索和设置 FaxServer对象的属性。
2.1.12.2、管理日志分类
当前此功能仅在Win32 环境下可用;对 COM 实现环境则不可用。
日志分类决定错误类型或传真服务器记载在应用程序事件记录文件中的其它事件类型。日志等级描述传真服务器记载的事件严重性的轻重。FaxGetLoggingCategories函数允许传真客户程序查询传真服务器的当前日志分类。函数会在一个或多个的FAX_LOG_CATEGORY结构中返回查询信息,每个结构描述一个当前日志分类。数据包括记日志分类的描述名、分类序号和当前日志级别。由FaxGetLoggingCategories 函数分配 FAX_LOG_CATEGORY结构所要求的内存,因此应用程序必须调用FaxFreeBuFFer函数来释放这些资源。应用程序可通过调用 FaxSetLoggingCategories函数,来修改传真服务器的全局配置设置。
注意:在调用 FaxGetConFiguration函数和 FaxSetConFiguration函数前,应用程序必须先调用 FaxConnectFaxServer函数以获得传真服务器句柄。
2.1.13、传真设备管理
传真服务客户 API 支持对传真路由和设备配置数据进行改变,并提供端口级别的配置选项信息。
2.1.13.1、查询传真端口数据(Win32 环境)
传真客户应用程序调用FaxEnumPorts函数即可显示目前所有与传真服务器相连接的传真设备,而若要查询单独的传真设备,则须调用FaxGetPort 函数。两函数通过FAX_PORT_INFO 结构返回详细的设备信息,一台设备对应一个结构。数据包括永久线路标识符、当前端口的状态和兼容性。注意:应用程序在调用 FaxGetPort函数之前须先调用 FaxOpenPort函数并指定PORT_OPEN_QUERY端口的访问级,。
可以调用 FaxGetDeviceStatus 函数,来显示与当前传真服务器连接的某台传真设备的状态,函数在 FAX_DEVICE_STATUS 结构中返回数据。结构包括当前设备状态标志位、设备及其位置标识符、发送和接收者名以及传真路由信息。
注意应用程序在调用 FaxEnumPorts 函数前,必须先调用 FaxConnectFaxServer 函数以获得传真服务器句柄;而应用程序在调用FaxGetDeviceStatus函数和FaxGetPort 函数前,须先调用 FaxOpenPort 函数指定 PORT_OPEN_QUERY端口的访问级别并获得传真端口句柄。
因为以FaxGet 和 FaxEnum 开始的函数会分配数据缓冲区所要求的内存,故应用程序必须调用 FaxFreeBuFFer 函数以释放这些资源。
应用程序可以调用 FaxSetPort 函数来修改一台传真设备的配置设置。
2.1.13.2、查询传真端口数据(COM实现)
FaxPort对象为传真客户应用程序提供查询端口和端口当前状态的永久线路标识符,也可以检索分配到端口的优先传送权。在端口响应调用前,输入传真调用的响铃处于等待状态,而不论当前端口是否启用传送和接受传真。
创建FaxPort对象实例后,即可调用 IFaxPort::GetStatus方法(VB 中用 FaxPort 对象的Status方法)创建FaxStatus 对象。使用 FaxStatus 对象检索父FaxPort对象的实时状态信息。
调用FaxPort::GetRoutingMethods方法创建FaxRoutingMethods 对象。(VB中用FaxPort对象的GetRoutingMethods方法)然后能使用此对象创建一个 FaxRoutingMethod对象实例。使用FaxRoutingMethod对象可为连结到传真服务器上的传真端口检索传真路由配置信息。
在C/C++应用程序中,在为指定的传真创建FaxPort对象以后,可以调用IFaxPort接口方法来检索端口的属性;而VB应用程序中,为指定的传真端口创建FaxPort对象以后,即可检索端口的多个属性。
2.1.13.3、修改传真端口数据
传真客户应用程序能修改传真端口的某个配置数据,这些数据包括分配到端口的传送优先权和端口响应调用前输入传真调用须等待的振铃次数,还包括端口的当前状态和功能以及传送和调用位置的标识符。
⑴WIN32环境下
传真客户应用程序可以调用 FaxSetPort 函数来改变与传真服务器相连接的传真端口的配置。
注意;应用程序在调用 FaxSetPort函数之前,须先调用 FaxOpenPort以指定 PORT_OPEN_MODIFY端口访问级别来获得传真端口句柄。
⑵.COM实现环境
创建FaxPort对象的实例后,可调用IFaxPort::GetRoutingMethods方法(VB 中可调用 FaxPort对象的GetRoutingMethods方法)来创建FaxRoutingMethod对象。此对象随后被用来创建FaxRoutingMethod 对象的实例。使用 FaxRoutingMethod 对象可在特定传真端口上启用或屏蔽传真路由方法。
注意,在应用程序调用修改FaxPort属性的方法前,可先调用IFaxPort::get_CanModiFy方法(在VB中是检索FaxPort对象的CanModify属性)确认客户程序有权修改端口配置。
C/C++的应用程序中,在为指定传真端口创建FaxPort对象后,即可调用IFaxPort接口方法来改变端口的属性。
VB的应用程序中,在为指定传真端口创建FaxPort对象后,就能马上检索对象的多种属性。   
2.1.14、管理传真路由数据
一些路由方法属性,如方法优先权,可在传真服务器级设置并适用于所有连接到传真服务器的端口,而其它的传真路由方法属性在端口级设置。
下面就详细讨论管理传真路由数据的有关内容。
    2.1.14.1、管理全局传真路由数据
当前,此功能仅在Win32 环境可用,在 COM 实现环境不可用。
一个传真客户应用程序可以调用 FaxEnumGlobalRoutingInFo 函数来查询全局路由方法数据,函数在FAX_GLOBAL_ROUTING_INFO结构中返回数据,返回信息包括传真路由方法的优先权和输出此路由方法的 DLL名,还包括 GUID 和确定传真路由方法的函数名以及方法的友好用户名。
应用程序调用FaxEnumGlobalRoutingInFo函数为FAX_GLOBAL_ROUTING_INFO结构来分配所要求的内存,因此程序须调用FaxFreeBuFFer函数来释放已分配的资源。
程序调用FaxSetGlobalRoutingInFo 函数修改全局路由方法数据。(当前路由方法优先权是应用程序能修改的唯一全局值。)
注意:应用程序在调用FaxEnumGlobalRoutingInFo函数和FaxSetGlobalRoutingInFo函数前,必须首先调用 FaxConnectFaxServer 函数以获得传真服务器句柄。
 2.1.14.2、管理单独端口的传真路由数据(WIN32环境)
传真管理应用程序可以调用 FaxEnumRoutingMethods 函数来显示与特定设备相关联的所有传真路由方法;调用 FaxGetRoutingInFo函数来查询与设备相关联的单个方法。两个函数都由FAX_ROUTING_METHOD 结构返回调用的详细信息,每个结构对应一种方法。返回数据包括传真路由方法是否被启用的指示和输出路由方法的 DLL名,还包括GUID 和唯一确定路由方法的函数名及方法的友好用户名。
程序调用FaxSetRoutingInFo函数即可改变特定传真路由方法的路由数据。
注意:应用程序在调用FaxEnumGlobalRoutingInFo函数、FaxSetGlobalRoutingInFo函数和FAXGETROUTINGINFO前,须先调用 FaxOPENPORT函数以获得传真服务器句柄。由于以FAXGET和FAXENUM开始的函数为数据缓存分配内存,故应用程序须调用 FaxFreeBuFFer 函数来释放这些资源。
2.1.14.3、管理单独端口的传真路由数据(COM实现)
除了在特定传真端口上启用或屏蔽传真路由方法,传真客户应用程序还可以检索有关方法的数据,这些数据包括输出方法的DLL名、GUID 和唯一指定路由方法的函数名以及方法的友好用户名。
C/C++程序中,在指定端口为传真路由方法创建FaxRoutingMethod 对象后,即可调用 IFaxRoutingMethod接口方法。这些方法能检索路由方法的属性并在端口上启用或屏蔽一个路由方法; VB应用程序中,在指定端口为传真路由方法创建FaxRoutingMethod 对象后,即可检索对象的多种的性质。当然也可以在端口上启用或屏蔽一个路由方法。           
2.1.14.4、启用或屏蔽传真路由方法
传真路由方法是每次在端口上收到传真后执行的行为。传真服务仅执行发送输入传真时端口启用的路由方法。
⑴Win32 环境
传真客户应用程序可以调用 FaxEnableRoutingMethod 函数为特定传真设备启用一个传真路由方法,也能调用函数来屏蔽因调用FaxEnableRoutingMethod或传真服务管理应用程序而启用的路由方法。应用程序调用FaxEnumRoutingMethods函数来查询当前传真路由方法是否启用。
注意,在调用FaxEnableRoutingMethod 或FaxEnumRoutingMethods前,应用程序须先调用FaxOpenPort 函数以获得传真端口句柄。
⑵COM的实现环境
C/C++应用程序中,可调用IFaxRoutingMethod::put_Enable属性方法在特定端口上启用或屏蔽传真路由方法。若要启用传真路由方法,传真客户程序须传递“真”值到IFaxRoutingMethod::put_Enable方法。IFaxRoutingMethod::get_Enable方法为FaxRoutingMethod对象检索Enable属性。在创建FaxRoutingMethod 对象前,须为FaxPort 对象检索指向IDispatch 接口的指针; vb程序中,可以设定 FaxRoutingMethod 对象的Enable属性,从而在特定端口启用或屏蔽传真路由方法。如果此属性为“真”,则端口启用路由方法。不过在创建FaxRoutingMethod对象以前,须先创建一个FaxPort对象实例。
2.1.15、传送传真
传真客户应用程序可以传送任何一个文件,但文件必须是正确的注册文件类型,同时传真服务器必须能够访问该文件。
    2.1.15.1、发送一个封面页
传真服务客户API支持打印可选封面页,客户端能在传真文档中传送一个公共封面页或者是私人封面页.
如果要求发送一个封面页,则用户必须提供完整的封面页文件路径,或公共封面页文件的相对路径。
⑴发送封面页(win32环境下)
可以在发送传真时传送服务器上的个人或公共封面页。要传送封面页就须调用FaxSendDocument函数或FaxSendDocumentForBroadcast函数。
当调用FaxSendDocument函数传送传真,必须提供指向FAX_COVERPAGE_INFO 结构的指针。该结构提供了封面页模板文件名和文件位于本地或传真服务器的指示,结构同时也提供用户支持的封面页信息。
a、发送公共封面页
①调用FaxSendDocument 函数时,提供指向FAX_COVERPAGE_INFO结构的指针。
②设定FAX_COVERPAGE_INFO结构的UseServerCoverPage成员为真。
③在FAX_COVERPAGE_INFO结构的UseServerCoverPage成员指定有效的公共封面页文件.
b、发送一个个人封面页
①调用FaxSendDocument函数时, 提供指向FAX_COVERPAGE_INFO结构的指针。
②设定FAX_COVERPAGE_INFO结构的UseServerCoverPage成员为假。
③指定一份传真服务器在FAX_COVERPAGE_INFO结构的CoverpageName成员中访问的有效个人封面页文件。
可以调用FaxGetConFiguration 函数确定传真服务器是否允许设置个人封面页。如果应用程序调用FaxSendDocumentForBroadcast函数传送一份传真到多个的接收者,此函数就须调用 FAX_RECIPIENT_CALLBACK函数。而在调用FAX_RECIPIENT_CALLBACK及设置上文提及的成员时,程序必须提供一个指向 FAX_COVERPAGE_INFO 结构的指针。回调函数能为每个特定传真接收者检索指定用户的封面页信息。   
⑵发送封面页(COM实现环境)
通过设定以下的FAXDOC对象属性,即可在传真中发送公共封面页或个人封面页.
a、发送公共封面页
  ①设定SENDCOVERPAGE属性为真。
  ②设定SERVERCOVERPAGE属性为真。
  ③设定封面页名属性为有效公共封面页文件。
b、发送个人封面页
   ①设定SENDCOVERPAGE属性为真。
   ②设定SERVERCOVERPAGE属性为假。
   ③设定封面页名属性为有效公共封面页文件。
可调用IFaxServer::get_ServerCoverpage方法来确定传真服务是否允许设置个人封面页。
要在传真中传送封面页,可以调用 IFaxDoc::Send 方法(VB中是FaxDoc对象的Send方法)。
2.1.15.2、发送传真到一个接收者(WIN32环境)
传真客户应用程序调用 FaxSendDocument函数来指定存储于磁盘上的文件,从而排列将要发送到一个接受者的传真作业。
程序必须指定传送文件并提供指向 FAX_JOB_PARAM 结构的指针。传真服务器将根据FAX_JOB_PARAM指定的细节来排列传真作业。该结构包括接受者的传真号码、发送和接受的数据、可选账号和作业排列信息。
要发送一份封面页,应用程序必须提供一个指向 FAX_COVERPAGE_INFO 结构的指针,此结构包含将显示在传真封面页上的数据。
程序在调用FaxSendDocument 函数前须先调用 FaxCOMpleteJobParams 函数。FaxCOMpleteJobParams函数为 FAX_COVERPAGE_INFO和FAX_JOB_PARAM 结构的成员提供数据。调用FaxFreeBuFFer 函数来释放与这些结构关联的内存。
要有效地将一份传真文件发送到若干接收者,应用程序应该调用 FaxSendDocumentForBroadcast 函数,而非多次调用FaxSendDocument 函数。注意:应用程序在调用 FaxSendDocument 函数和 FaxSendDocumentForBroadcast 函数前须先调用 FaxConnectFaxServer 函数以获得传真服务器句柄。
2.1.15.3、发送一份传真到一个接收者(COM实现环境)
如果程序使用传真客户COM 实现,除非用现存的连接线路来设置属性以启用传真发送,传送一份传真需要有FileName属性和FaxNumber 属性,。传送传真时,用户也可以指定其它的可选属性,如封面页设置、传真接收和发送者信息以及一些仅在封面页显示的数据。
C/C++应用程序中,在与活动传真服务器连接好以后,即可调用 IFaxServer::CreateDocument方法创建一个 FaxDoc对象。随后调用多种IFxDoc接口方法来设置对象的可选或必须属性。最后调用 IFaxDoc::Send 方法来传送文件。
在VB应用程序中,调用VB中的CreateObject 函数创建一个FaxServer对象。然后调用该对象的 CreateDocument 方法创建一个 FaxDoc 对象,并设置FaxDoc对象的必须和可选属性。最后调用FaxDoc对象的Send方法发送传真文件。
2.1.15.4、广播传真到多个接收者
当前此功能只在WIN32环境下可用,而COM环境下不可用。
FaxSendDocumentForBroadcast 函数排列传真作业,这些作业把存储在磁盘上的文件传递到多个接受者。程序必须指定要传送的文件。一旦指定了传真接收者,FaxSendDocumentForBroadcast 函数就会多次调用 FAX_RECIPIENT_CALLBACK 函数来检索排列的信息,每次对应一个接收者,若有要求则信息也包含封面信息。
程序在调用 FAX_RECIPIENT_CALLBACK 函数前,须先调用FaxCompleteJobParams 函数。FaxCompleteJobParams 函数为 FAX_COVERPAGE_INFO 和 FAX_JOB_PARAM 结构的成员提供数据。可以调用FaxFreeBuffer 函数来释放与这些结构相关联的内存。
注意程序在调用 FaxSendDocument和FaxSendDocumentForBroadcast函数之前,必须先调用 FaxConnectFaxServer 函数来获得传真服务器的句柄。
2.1.15.5、传递传真到活动的输入调用
使用现存的输入线路连接来传递传真文件可以节约传真的费用,即所谓的"faxback 服务"。若要使用现存的输入线路连接成功传递文件, 调用须处于LINECALLSTATE_CONNECTED 状态。
⑴、WIN32 环境
若要使用现存的线路连接来传递传真,在调用FaxSendDocument 或 FaxSendDocumentForBroadcast函数时,需指定 FAX_JOB_PARAM 结构的CallHandle成员。调用句柄必须是TAPI LINE_CALLSTATE检索到的消息之一。如果指定CallHandle成员, 程序会使用现存的连接进行传真传递而不是初始化一个新调用。
⑵、COM 实现环境
C/C++ 程序中, 可设置 CallHandle或ConnectionObject 属性启用现存连接线路来传递传真。如果要传递传真到活动输入TAPI 2.x 调用,可以调用 IFaxDoc::put_CallHandle接口方法。若要在FaxDoc对象中存储TAPI调用对象的引用, 则须调用IFaxDoc::putref_ConnectionObject方法。使用现存线路连接传递传真时,ConnectionObject属性提供基于COM的全部的功能。在VB程序中,可设置FaxDoc对象的ConnectionObject属性,在使用现存连接线路传递传真时,该属性提供基于COM的全部功能。
2.1.15.6、打印传真到设备上下文
当前此功能只在WIN32环境下可用,而COM环境不可用。
传真客户程序不要求到传真服务器的连接将传真打印至打印设备上下文(DC)。不必调用FaxSendDocument或FaxSendDocumentForBroadcast 函数, 程序可直接向传真客户服务API提供的图形设备接口函数(GDI)提供传递信息。这就使程序可以由直接打印到打印机DC来传递活动文本。传真客户的GDI 函数包括FaxStartPrintJob 和FaxPrintCoverpage 函数。
由于传真GDI函数使用传真打印机设备, 故调用FaxStartPrintJob 函数时,必须指定所连接的传真打印机名。打印机可为本地打印机如“printername”或远程打印机如“\\machinename\printername”。若将NULL PrinterName 参数传递到FaxStartPrintJob,则指本地打印机,FaxStartPrintJob函数返回打印机DC的句柄。
注意:传真客户程序不应调用 CreateDC Win32 GDI函数来创建传真打印机DC,也不应调用 StartDoc打印函数来启动文本打印。相反,程序应调用FaxStartPrintJob函数。
打印传真到设备上下文的步骤:
(1)调用FaxStartPrintJob 函数检索传真打印机DC的句柄。函数在FAX_CONTEXT_INFO 结构中返回句柄。
(2)若传真要求有封面,可调用FaxPrintCoverpage函数来传递指向FaxStartPrintJob函数返回的FAX_CONTEXT_INFO结构的指针。
(3)以常规方式打印传真文档到打印机DC时,要给DC传递FaxStartPrintJob函数返回的句柄,此过程包括调用StartPage 和 EndPage Win32 GDI 函数。
(4)调用EndDoc或AbortDoc 函数,向FaxStartPrintJob函数返回的DC传递句柄,这将关闭文档和结束传真打印作业。
(5)调用DeleteDC函数释放分配到DC的句柄。
2.1.16、管理传真作业
传真服务客户API支持灵活的队列管理和活动传真作业管理。下面就详细描述输出传送的管理。
2.1.16.1、查询传真作业
传真客户程序可以查询与传真作业相关的传真序号、传真接收者和发送者信息,也可检索作业的类型、状态和唯一标示符;时序、作业顺序和传递页的数目。
⑴Win32 环境
FaxEnumJobs函数允许传真客户应用程序检索指定传真服务器上的传真作业队列列表。调用FaxGetJob函数可查询单独的传真作业。两个函数均可返回FAX_JOB_ENTRY结构中作业的详细信息,一个结构对应一个作业。
因为FaxEnumJobs和FaxGetJob函数为FAX_JOB_ENTRY结构分配其所要求的内存,故应用程序须调用 FaxFreeBuffer 函数来释放这些资源。
注意:应用程序在调用 FaxEnumJobs和FaxGetJob函数前,须先调用 FaxConnectFaxServer函数获得传真服务器句柄。
⑵COM实现环境
C/C++应用程序中,在为指定传真作业创建FaxJob对象后,可调用IFaxJob接口方法来查询作业的性质;在VB应用程序中,在为指定传真作业创建FaxJob对象后, 即可查询对象的多种性质。
2.1.16.2、显示传真作业队列中的文档
当前此功能仅在 Win32 环境可用;在 COM 实现环境不可用。
程序可调用FaxGetPageData函数来管理传真队列中的文档。函数以F类的标签图像文件格式(TIFF 6.0 Class F)返回传真数据的第一页。调用函数必须解码数据流。调用FaxFreeBuffer 函数可释放由FaxGetPageData函数分配的资源
2.1.16.3、修改传真作业
传真客户应用程序在传真作业被排序后,无法对传送传真的性质或属性进行修改。
⑴win32环境
传真客户应用程序在传真作业排序后无法对传真的性质进行修改,是因为许多与作业关联的FAX_JOB_ENTRY 结构所包含的属性在文本传送开始后是无法改变的。应用程序可以调用FaxSetJob函数来暂停、恢复、取消或重启队列传真作业。
注意:应用程序在调用FaxSetJob函数前须先调用FaxConnectFaxServer函数来获得传真服务器句柄。
⑵ COM实现环境
C/C++应用程序中,在创建FaxJob 对象后,即可调用IFaxJob::SetStatus 方法来暂停、恢复、取消或重启作业;在VB应用程序中,创建FaxJob 对象以后,可调用对象的 SetStatus 方法暂停、恢复、取消或重启作业。
2.1.16.4、终止传真作业
传真客户应用程序能终止正在传送中的传真。
⑴ Win32 环境下
传真客户应用程序能调用 FaxSetJob 函数或 FaxAbort 函数取消正在传送的传真。注意应用程序在调用 FaxAbort 函数或 FaxSetJob 函数前须先调用FaxConnectFaxServer函数来获得传真服务器的句柄。
⑵COM 实现环境
C/C++应用程序中,在创建 FaxJob 对象后,即可调用 IFaxJob::SetStatus方法终止传真作业,但必须在Command(命令)参数中指定JC_DELETE。vb应用程序中,创建 FaxJob 对象后,调用对象的SetStatus 方法,由指定JC_DELETE常数即可取消传真作业,但应注意的是,必须先定义这个常数。
2.1.17、释放传真资源
在某些情形下,调用传真客户应用程序可以管理分配资源,这对指 COM 实现环境的C/C++应用程序和Win32 环境的程序均适用。
⑴ Win32环境
传真客户应用程序必须调用特定的传真客户函数来释放资源。这包括调用FaxCompleteJobParams 函数和以FaxEnum 或 FaxGet开始的函数。调用 FaxFreeBuffer函数即可释放这些资源。如果应用程序已调用 FaxFreeBuffer函数解除引用,数据就不能再被引用。
⑵COM实现环境
C/C++应用程序中,必须调用SysFreeString 函数来释放与由所有pVal 参数指向的缓冲区相关联的资源。这是因为检索属性的所有属性方法(以get_PropertyName 结束)为缓冲区分配所要求内存。VB应用程序则不必释放资源。
2.1.18、断开与传真服务器的连接
只有调用传真客户应用程序才能断开与传真服务器的连接。
⑴Win32 环境
传真客户应用程序须在其被终止前调用 FaxClose 函数作为最后一个函数。函数由释放下列句柄从传真服务器断开调用程序:
a.调用FaxConnectFaxServer函数返回传真服务器句柄。
b.调用FaxOpenPort 函数返回传真端口句柄。
⑵COM实现环境
C/C++应用程序中,可调用IFaxServer::Disconnect 方法来终止与传真服务器的连接。然后调用 IUnknown::Release 方法使FaxServer对象释放自己。也可能需要再次调用IUnknown::Release 来肃清附加接口的指针。在VB应用程序中,在应用程序终止以前,须调用FaxServer 对象的Disconnect方法断开与传真服务器的连接。
2.1.19、通用传真客户编程任务
下面叙述开发传真客户应用程序所需的附加信息。
2.1.19.1、检查用户的访问权限
微软传真服务是一种安全的服务。传真服务管理应用程序,是一种微软管理控制台( MMC) 插件组件,使用户可以查询和修改作业、端口和全局的配置数据的权限。
⑴Win32 环境
用户要成功调用特定传真服务函数必须有特定的访问权限,可以调用FaxAccessCheck函数来查询用户的传真访问权限。
⑵COM实现环境
C/C++应用程序中,须保证客户有修改指定端口的权限。可以在调用以IFaxPort::put_开始的方法前,首先调用IFaxPort::get_CanModify 方法来指定传真端口。在VB应用程序中,可由检索 FaxPort对象的 CanModify性质决定用户是否有修改传真端口配置信息的权限。
2.1.19.2、启动应用程序接收传真事件通知
当前此功能仅在Win32 环境可用,在 COM 实现环境不可用。
调用FaxInitializeEventQueue函数为传真客户应用程序创建一个传真事件队列。队列使应用程序能够从传真服务器收到异步的事件的通知。应用程序能指定传真服务器如何通知事件的客户应用程序。应用程序能要求传真服务器按照I/O完备端口排列I/O完备包,或指定传真服务通知发送消息。
传真客户应用程序在一次传真服务期间,只能调用传真服务会议 FaxInitializeEventQueue函数一次(当服务发送 FEI_FAXSVC_STARTED 消息时,传真服务开始;传送 FEI_FAXSVC_ENDED 消息时传真结束)。这样就可以防止传真服务给客户计算机发送副本消息。如果在一次发送期间多次调用FaxInitializeEventQueue,函数会失败并返回错误代码ERROR_INVALID_DATA。在应用程序关闭传真服务器句柄后,传真客户应用程序还可以继续接收传真服务的传真事件。
⑴从传真服务收到通知消息
当前此功能仅在 Win32 环境可用,在 COM 实现环境不可用。
客户应用程序调用 FaxInitializeEventQueue函数时,使用通知消息而不是I/O 完备包来指定通知。应用程序会指定hWnd 参数的有效窗口句柄和MessageStart参数值来完成此工作。
传真服务调用PostMessage 函数发送通知消息到hWnd 参数中客户应用程序指定的目的地窗口。客户应用程序的窗口程序处理收到的消息。另外,开发者必须考虑下列的因素以保证客户应用程序能够收到通知消息。
a.在LocalSystem帐户下运行传真服务
传真服务和本地登录用户在不同的桌面上运行传真客户应用程序。因为通知消息不能跨越桌面,故控制面板的服务应用程序必须在本地计算机的 LocalSystem 帐号下使Allow Service To Interact With Desktop传真服务选项被选中。这就允许传真服务可以访问客户的桌面,并使服务能够给客户发送消息。
b.在用户帐户下运行传真服务
用户可以配置运行在用户帐户而不是LocalSystem 帐户下的传真服务,如激活MAPI 功能。这种状况下,Allow Service To Interact With Desktop(允许服务与桌面交互)选项将不被传真服务选中。要启用接收通知消息,传真服务须为传真客户应用程序打开访问标志。当客户调用 FaxInitializeEventQueue 函数时,服务打开标志并指定通知消息。当传真服务要传递消息到客户,服务模仿客户并发送消息到客户。开发者不需要在客户应用程序中合并任何代码来启用以上功能。
然而,当传真服务在用户帐号下面运行时,应用程序必须合并代码以使客户能够成功地注销。这是因为如果传真服务有客户桌面的打开句柄,用户就不能注销了。当客户应用程序收到 WM_ENDSESSION或 WM_DESTROY 消息时,必须再次调用FaxInitializeEventQueue 函数,指定初始时由 hWnd参数指定的同一窗口句柄。然而,程序必须在CompletionKey 参数里指定一个-1值来通知客户正在注销并且服务应该关上为客户打开道德访问标志,这就使得客户可以注销。注意:传真服务不需要在 LocalSystem 帐目下面运行以启用此特征。
为优化性能,当用户试图注销传真服务时,应使客户应用程序能决定传真服务是否正在运行。如果客户收到FEI_FAXSVC_ENDED 消息,则传真服务不在运行。由于服务关闭了为客户打开的访问标志,客户不再需要调用 FaxInitializeEventQueue 函数。
 ⑵从传真服务接收I/O完备包
当前此功能仅在Win32 环境可用,在 COM 实现环境不可用。
当客户应用程序调用FaxInitializeEventQueue 函数时,可用I/O 完备包来替代通知消息指定通知。应用程序由在 CompletionPort参数中把有效句柄传递给I/O 完备端口和传递CompletionKey 参数值来完成此项工作。如果应用程序指定 I/O 完备包,则传真服务不为应用程序打开标志。这种状况是没有必要附加编码的,因为完备包可以和桌面进行交互。传真服务调用 PostQueuedCompletionStatus 函数,通知异步的事件的客户。客户必须调用 GetQueuedCompletionStatus 函数来检索包含 FAX_EVENT 结构的I/O 完备包。
2.1.19.3、在传真客户应用程序中启用MAPI功能
传真服务支持与MAPI-aware集成的两个等级的客户应用程序:概要传递方法和电子邮件传递方法。当传真服务器发送或接收传真传送时,可以使用这些传递方法之一来传送传递报告(ndrs)和非传递报告( NDRs )。
传真服务可以不要求有传递报告,应用程序可指定没有非传送报告被发送。防止传送报告的传送方法如下:
a.Win32 环境
调用 FaxSendDocument 函数或 FaxSendDocumentForBroadcast 函数并在 FAX_JOB_PARAM 结构的 DeliveryReportType 项指定 DRT_NONE;或调用FaxStartPrintJob 函数并指定 FAX_PRINT_INFO 结构的DrProfileName和DrEmailAddress成员为NULL。
b.COM 实现环境
毋须设置 FaxDoc 对象的 EmailAddress 性质;也毋须设置 FaxServer对象的ServerMapiProfile性质。
⑴概要传递报告
当前此功能仅在 Win32 环境可用,在 COM 实现环境不可用。
如果系统有主要用户或系统不在网络中,则传真传送报告的概要传送方法 (DRs)及未传送报告( NDRs )是可行的。
传真客户应用程序能用下列方法之一请求DRs和 NDRs 的概要传送:
a.调用FaxStartPrintJob 函数并且在 FAX_PRINT_INFO 结构的 DrProfileName 成员中指定有效的MAPI 简介, DrEmailAddress成员一定要为空。
b.调用 FaxSendDocument 函数或 FaxSendDocumentForBroadcast 函数并在FAX_JOB_PARAM 结构的 DeliveryReportAddress成员中指定有效的 MAPI简介。也须指定DeliveryReportType成员的DRT_INBOX。
当传真服务器使用此方法传送报告时,在指定MAPI用户简介文件的默认消息存储位置放置报告,典型情况下,为用户本地个人信息存储的收件箱文件夹。
如果在网络环境中指定简介传送报告,缺省消息存储于微软®Exchange Server上的收件箱。传真服务器须允许对存储的默认消息读写,使用微软管理控制台插件组件Manage Computer/Services(计算机管理/服务申请)可以改变传真服务帐目。
⑵电子邮件传送报告
如果系统有多个用户或系统处于网络中,用传送传真的电子邮件传送方法传送报告(drs)和未传送报告( NDRs )是合适的方法的。一个多用户的例程是连结到一个或多个客户机的传真服务器系统。
电子邮件DRs和 NDRs 的传送,传真服务器要求有下列项目:
a.详尽的 MAPI简介,由此传真服务器产生电子邮件;
b.到微软®Exchange 服务器的连接;
c.传真服务器传送电子邮件到Exchange服务器的邮箱名或别名
请求电子邮件DRs和 NDRs传送, 传真客户程序必须执行以下 Win32 和 COM 实现的步骤。
a.Win32 环境
①调用 FaxSetConfiguration 函数并在FAX_CONFIGURATION 结构的 InboundProfile 成员指定有效的MAPI用户简介文件。传真服务必须能访问指定的简介文件(要求使用微软管理控制台插件组件Manage Computer/Services(管理计算机/服务器)程序改变传真服务帐目)。
②调用ChangeServiceConfig 函数改变传真服务帐号的配置参数(另外也可使用微软管理控制台插件组件系统服务管理应用程序来改变传真服务帐目) 。
③使用传真的微软管理控制台(MMC)插件组件服务监视应用程序重启传真服务或调用 StartService 函数。
④下列步骤之一可要求电子邮件DRs和 NDRs传送:
l 调用 FaxStartPrintJob 函数并指定 FAX_PRINT_INFO 结构的 DREmailAdDRess成员。指定的电子邮件地址必须是Microsoft Exchange 服务器全局地址列表(gal)中的有效地址名或别名;
l 调用 FaxSendDocument 函数或 FaxSendDocumentForBroadcast 函数并且在FAX_JOB_PARAM结构的 DeliveryReportAdDRess成员指定一个有效的电子邮件地址,同时也必须在 DeliveryReportType成员指定 DRT_EMAIL。
 传真服务器由步骤①的InboundProfile成员指定的地址传送电子邮件的DRs或NDR到步骤④ 的DREmailAdDRess或 DeliveryReportAdDRess 成员指定的地址。
b.COM 实现环境
①设置FaxServer对象的 ServerMapiProfile性质,该性质必须指定有效的 MAPI简介文件。
②设置 FaxDoc对象的EmailAdDRess性质。电子邮件地址必须是Microsoft Exchange 服务器的全局地址表(gal)的一个有效地址名或别名。
以下步骤同Win32 环境。
服务器将从ServerMapiProfile性质指定的电子邮件地址传送电子邮件DRs或NDR送到EmailAdDRess 性质指定的电子邮件地址。
2.1.19.4、检索传真文件数据
当前此功能仅在COM实现环境可用,在Win32环境不可用。
传真服务变换处理的文件为F类传真的标签图象文件格式 ( TIFF6.0 F 类 )。服务在文件中嵌入定制的 TIFF 标签存储传真传播的信息。传真客户应用程序使用 FaxTiff 对象检索传真服务传送或接收的文件信息。
应用程序能查询FaxTiff 对象的性质。该性质包括设备和状态标识符、传真序号和发送者和接受者名字。在创建FaxTiff 对象的例程前,不需要提前创建一个 FaxServer对象。
C/C++应用程序中,为传真文件创建FaxTiff 对象后,即可调用 IFaxTiff 接口方法查询文件的性质; VB应用程序中,为指定文件的传真创建 FaxTiff 对象后,就能检索对象的多种性质。

2.1.19.5、传真路由扩展的本地注册
传真路由扩展能直接安装在传真服务器上 (本地安装)或从网络上的某台计算机安装(远程安装)。推荐使用本地安装。在本地注册传真服务推荐使用传真路由扩展DLL来施行下列步步骤非直接访问注册表。
a.拷贝路由扩展DLL到FaxRegisterRoutingExtension 函数的ImageName参数指定的地址。
b. 要获得到本地的服务器的传真服务器句柄,可调用 FaxConnectFaxServer 函数为MachineName参数指定一根NULL指针。
c.调用FaxRegisterRoutingExtension函数注册传真服务的路由扩展 DLL。函数在传真路由扩展 DLL中为每个传真路由方法调用一遍 FAX_ROUTING_INSTALLATION_CALLBACK 函数。
如果调用 FaxRegisterRoutingExtension 函数来安装传真路由扩展,必须使用该扩展输出的传真路由方法来重启传真服务。
2.1.19.6、传真服务供应商的本地注册
传真服务供应商能直接安装在传真服务器 (本地安装)或网络计算机(远程安装) 上。但推荐用本地安装。
为了在本地注册传真服务,推荐传真服务供应商执行下列步骤而不是直接访问注册表。
a.为抽象设备安装电话服务供应商。电话服务供应商指定传真服务供应商控制的所有传真设备并使传真服务能够使用外部的传真设备。
b.拷贝服务供应商 DLL到FaxRegisterServiceProvider函数的ImageName参数指定的位置。
c.调用 FaxRegisterServiceProvider 函数为传真服务用户配置新设备及为传真服务供应商注册传真服务动态链接库( DLL )。
2.1.20、 使用传真客户COM实现
除了传真服务客户API Win32函数,微软®还为传真客户应用程序开发者提供了COM实现的接口。并为用VB、VBScript 、Jscript和Java工作的程序员提供双接口访问以及C/C++程序员提供VTable 访问,接口使用 ActiveX®模板库以提高性能并使要求大小减至最小。
本章,传真服务客户API简介,概述了Win32 环境与COM 实现环境下运行的传真客户程序之间的差别。
为C/C++开发者提供的COM 实现的参考材料是围绕单个COM 接口组织的;为vb开发者提供的COM 实现的参考材料是围绕传真客户对象模型组织的。
注意: C/C++程序不能实现以IFax 开始的任何接口;而 vb程序不能实现以Fax开始的任何类。微软标准实现会提供完整功能。要支持传真客户 COM 实现的功能, 要求有FaxCom.h和FaxCom.dll文件。
2.1.20.1、传真客户对象模型
大多数传真客户对象模型的对象以分层方式组织。但FaxTiff 对象除外,它是一个非标准对象。
下列图表说明此层次。可存在多个FaxJob、FaxPort和 FaxRoutingMethod对象
 
大多数传真服务器客户API的COM接口从本质上说是分层的。例如,客户应用程序在访问以IFax开始的接口或其它传真客户对象前,必须调用 IFaxServer::Connect 方法(或FaxServer 对象的Connect VB方法),建立与传真服务器的连接。(FaxTiff 对象为一个例外,连接的传真服务器不要求访问FaxTiff 对象)。
在客户应用程序通过RPC 建立到活动传真服务器的连接后,应用程序即可调用其它接口方法了。这是因为活动的 FaxServer 对象“知道”它连结的传真服务。例如,程序能调用下列方法之一:
a.调用IFaxServer::GetJobs 方法(或 FaxServer 对象的GetJobs VB方法)创建一个 FaxJobs 对象并检索与所连结的传真服务器关联的传真作业列表 。
b.调用FaxServer::GetPorts 方法(或 FaxServer 对象的 GetPorts  VB 方法) 创建一个FaxPorts对象并检索与所连联接传真服务器关联的端口列表。
c.调用IFaxServer::CreateDocument 方法(或 FaxServer 对象的 CreateDocument VB 方法) 创建FaxDoc 对象并且传送一份传真。
客户应用程序不能调用CoCreateInstance 函数去创造这些对象或由其导出对象。                   
2.1.20.2、使用VB实现传真客户COM接口
VB程序员使用的传真服务客户API COM接口文档按照传真客户对象模型组织。每个对象文档都包括对象功能的详细描述列表,对象属性和方法列表,访问属性和调用对象方法的VB例程。
注意;相应的C/C++接口方法主题会包含VB 程序员感兴趣的信息。例如,这些等价主题提供相关联的话题间的交叉引用,并且包含详细的参数描述。C/C++接口方法名以IFax开始。
第三章 传真服务供应商应用程序接口
传真服务API允许将传真设备集成到微软传真服务中去。
本章的第一部分描述支持传真服务供应商API的组件及API功能,也包括虚拟传真服务和错误控制的简短讨论;最后,构画出传真服务供应商注册要求并且描述开发一个传真服务供应商活动链接库( DLL )的编程指南。
本章的第二部分包括怎样创建并发送传真服务供应商状态变化到传真服务的代码示例,同时也描述了怎样使用虚拟传真设备传送传真。
在阅读概述之前,应熟悉电话应用程序编程接口( TAPI )和微软电话服务供应商( TSPI )的有关概念。
3.1、传真服务供应商结构
下图提供了传真服务供应商环境的纵览:
 
必须在源代码文件中包含传真服务供应商头文件(FaxDev.h)
3.2、传真服务供应商 API 简介
传真服务供应商 API支持多个传真设备并且为实现传真提供独立设备接口。下列组件被要求支持传真服务供应商API功能。
a.传真设备制造商必须为传真服务提供已定义接口的传真服务供应商动态链接库( DLL )。每个传真设备系列至少要有一个传真服务供应商DLL。
b.传真服务( FaxSvc.exe )。这个支持服务的应用程序为传真服务供应商 DLL 提供执行上下文。传真服务用DLL同传真服务供应商进行通信。传真服务管理传真设备和配置数据,提供打印服务并传送和接收传真文件。传真服务为所有的传真文档创建F类传真标签图象格式的文件( TIFF 类 F )。
c.电话应用程序接口( TAPI )建立出、入传真的调用,并提供传真设备的细目、状态和通知变化。
d.仅提供物理传真设备的传真服务提供商也必须为电话服务供应商提供设备抽象。电话服务供应商确定传真服务供应商控制的所有传真设备,并使传真服务能够使用传真设备。如果传真服务供应商提供虚拟传真设备,则不需要一个电话服务供应商。
另外,必须在源代码文件包括传真服务供应商头文件FaxDev.h,该文件包含函数原型、结构定义和传真状态常数。传真服务供应商负责存储所有的客户接口特征和配置。
3.2.1、传真业务纵览
传真业务是传真操作的集合,传真操作包括发送和接收操作。在每次传真业务的开始,传真服务调用FaxDevStartJob为传真服务供应商执行调用安装提供机会并初始化一个新的传真业务。由于每个传真操作是在分开的线程执行所以传真服务也在每次传真操作开始时调用FaxDevStartJob函数。
下图显示了在传真发送操作时传真服务进行函数调用的顺序,传真服务供应商必须输出这些函数 。
 
传真服务在同步线程中依次调用以下函数:
a.FaxDevStartJob。 初始化传真业务和发出传真操作开始信号。
b.FaxDevSend (或 FaxDevReceive)。通知传真服务供应商初始化输出传真传递(或接收一个输入传真传递)。
c.FaxDevReportStatus。向传真服务供应商查询活动传真操作的状态信息。
d. FaxDevEndJob。关闭活动传真业务。
传真服务在发送或接收操作期间,在独立于传真操作的执行线程中异步调用FaxDevReportStatus 和FaxDevAbortOperation 函数, FaxDevAbortOperation会要求传真服务供应商终止对活动操作。
3.2.2、初始化传真服务供应商
每次传真服务开始时,会调用TAPI lineInitializeEx 函数来检索线路上可获得设备的数目。在初始化期间,传真服务检查FaxDevVirtualDeviceCreation函数的传真服务供应商DLL。如果供应商输出可选函数FaxDevVirtualDeviceCreation,传真服务会期望传真服务供应商提供一个或多个虚拟传真设备。
传真服务也在每次服务开始初始化服务与传真服务供应商DLL间的通信时调用 FaxDevInitialize函数 。当传真服务调用FaxDevInitialize时,通过提供函数指针,传真服务供应商必须注册T FAX_LINECALLBACK 函数。 服务调用FAX_LINECALLBACK 以为传真服务供应商传递TAPI事件。传真服务供应商必须输出FaxDevInitialize 和FaxDevStartJob。
下列图表演示了初始化传真服务供应商时的通用事件流:
 
一旦初始化完传真服务供应商,供应商就可以在其支持的设备上收发传真了。
3.2.3、传送传真
传真服务调用FaxDevSend 函数通知传真服务供应商DLL必须初始化输出传真。除非 FAX_SEND 结构的CallHandle 成员指定一个有效的TAPI调用句柄,供应商必须调用函数来发送传真数据流和终止调用。在这种状况下,供应商应该使用存在的连接而不是初始化新调用来传送传真。 FAX_SEND结构用来指定包含输出传真文档的文件并包含调用和接收传真设备的信息。
传真服务提供指向 FAX_SEND_CALLBACK 函数的指针。传真服务供应商调用FAX_SEND_CALLBACK 函数通知传真服务输出传真调用正在进行。发送TAPI消息必须要有FAX_SEND_CALLBACK 函数。
传真服务调用 FaxDevReceive 函数通知传真服务供应商 DLL何时有输入传真。供应商必须接受输入调用并存储传真数据流。FAX_RECEIVE 结构确定传真服务供应商存储输入传真数据流的文件,并包含接收传真设备的信息。传真服务供应商必须输出 FaxDevSend 和 FaxDevReceive 函数。
3.2.4、终止传真
传真服务调用FaxDevEndJob 函数在传真操作完成后,可顺利关闭传真作业。此时,传真服务供应商应该释放在作业初始化期间由 FaxDevStartJob 函数分配的特定作业的实例数据。
传真服务异步调用 FaxDevAbortOperation 函数请求传真服务供应商终止仍然活动的默认传送或接收传真操作。即使FaxDevAbortOperation终止了操作,传真服务仍然可以调用 FaxDevEndJob 函数。传真服务供应商必须输出FaxDevEndJob 和 FaxDevAbortOperation 函数。
3.2.5、获得传真状态
传真服务异步地调用FaxDevReportStatus 函数为活动传真操作查询传真服务供应商 DLL的状态信息或传真操作失败后的状态信息。FAX_DEV_STATUS 结构包含状态错误代码、 Win32 错误代码和传真操作传送信息。传真服务供应商必须输出FaxDevReportStatus 函数。
3.2.6、传真操作错误控制
传真服务调用FaxDevStartJob 函数来标记传真服务供应商传真操作的开始。如果传真操作开始,但是传真服务供应商不能访问传真服务指示的线路,这状况种称为glare。此时,传真服务供应商应该都采取下列步骤:
a.从 FaxDevSend 或 FaxDevReceive 函数调用中返回0值。
b.设置FAX_DEV_STATUS 结构的 StatusId 成员为FS_LINE_UNAVAILABLE 状态。
当传真服务调用 FaxDevReportStatus 函数时,将检测到线路不可用。传真服务将会选择另外的线路并且再次调用传真操作。
 3.2.7、 传真服务供应商注册
一个传真服务供应商能直接安装在传真服务器上 (本地安装)或网络计算机上(远程安装)。推荐使用本地安装。
⑴本地安装
传真服务本地注册,供应商应施行下列步骤而非直接访问注册表。
a.为抽象设备安装一个电话服务供应商。电话服务供应商指定传真服务供应商控制的所有传真设备,并且使传真服务能够使用传真设备。
b.复制传真服务供应商 DLL到FaxRegisterServiceProvider 函数的 ImageName参数指定的位置。
c.调用 FaxRegisterServiceProvider 函数设置新设备来使用传真服务。
⑵远程安装
在远程安装期间,每个传真服务供应商 DLL 必须由远程计算机注册表的下列键提供的信息来注册传真服务:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fax\ Service Providers\OEM
要注册 DLL,在此关键字下设置应下表中的3个值:
值 描述
FriendlyName 为传真服务供应商dll包含友好客户显示名的REG_SZ字符串
ImageName 为传真服务供应商dll包含所有路径和文件名的REG_EXPAND_SZ字符串
ProviderName 包含电话服务供应商名的REG_SZ字符串
推荐存储此键下面所指定的传真服务供应商的注册表数据。因为传真服务供应商负责配置的数据在此键值下存储。
3.2.8、虚拟传真设备
虚拟传真设备是对客户来说好象存在但实际并没有相应传真服务器的TAPI线路设备与之相联系的设备。因特网上的传真服务就是供应商用虚拟传真设备的一个例子。在这个例子中,物理传真设备并不存在,仅有到因特网的连接。
如果供应商输出 FaxDevVirtualDeviceCreation 函数,传真服务供应商能为传真服务提供多个虚拟传真设备。在初始化期间,传真服务检查FaxDevVirtualDeviceCreation的传真服务供应商DLL 。如果函数存在,传真服务允许用户使用虚拟的设备客户收发传真。
3.2.8.1、虚拟设备状态的信令变化
传真服务调用传真服务供应商的 FAX_LINECALLBACK函数通知服务供应商何时终端客户激活或屏蔽虚拟传真设备的传真收发。当传真服务调用 FaxDevInitialize 函数时,传真服务供应商由传递其地址注册回调函数。
传真服务使用下列值调用FaxDevInitialize 函数。
参数 值
FaxHandle NULL
hDevice 虚拟传真设备标示符
dwMessage LINE_DEVSPECIFIC
dwInstance 0
dwParam1 传真服务为此参数产生一个值。如果虚拟传真设备被激活接收传真,此参数有非零值 。如果传真接收被屏蔽,此参数为零。
dwParam2 传真服务为此参数产生一个值。如果虚拟传真设备被激活发送传真,该参数有非零值 。如果传真发送被屏蔽,参数等于零。
dwParam2 0
即使仅有一台虚拟设备改变状态,传真服务也会多次调用 FAX_LINECALLBACK,每次对应传真服务供应商支持的一台虚拟设备。
3.2.9、传真服务供应商编程指南
下面讨论开发集成传真设备为传真服务的传真服务供应商 DLL的编程问题。
3.2.9.1、内存分配
所有的传真服务供应商必须使用私有堆进行内存分配。当传真服务装载传真服务供应商DLL并在调用FaxDevInitialize 函数时传递堆句柄,传真服务为每个传真服务供应商创建私有堆。当卸载 DLL 时,传真服务释放堆。
传真服务供应商应该用私有函数在DLL 内封装所有内存分配和释放。私有函数应该用传递到FaxDevInitialize的堆句柄调用 HeapAlloc 和 HeapFree 函数。
该方法用服务供应商模型的扩展性获取一个具有鲁棒性的服务器,并可分离出特定传真服务供应商的内存问题。
3.2.9.2、多线程环境操作
 因为传真操作在分离的线程被执行,传真服务在一个新传真作业的开始时调用 FaxDevStartJob 并在每次传真操作均进行调用。传真服务供应商必须在多线程环境作业。传真服务供应商必须为每个传真线程操作的特定作业实例数据分配内存以保证传真服务供应商 DLL线程内安全。当传真操作完成时,传真服务供应商应为实例数据释放内存。
3.2.9.3、处理异常
Try-except异常处理块保护所有对传真服务供应商函数的调用。如果传真服务检测到传真服务供应商 DLL的一个异常,服务调用 FaxDevAbortOperation 函数来终止失败的传真操作。推荐传真服务供应商使用try-except块捕获错误并以适当方式处理错误。
3.2.9.4、变换字符串参数
传真服务供应商函数原型对字符串参数使用 LPWSTR 数据类型。传真服务供应商 DLLs 必须被编译为 Unicode码。如果传真服务供应商没有被编译为 Unicode,因为传真服务供应商 DLL 仅接收 Unicode ,则函数调用失败。
3.2.9.5、 设置最新错误代码
传真服务供应商函数返回指示函数成功或失败的布尔值。如果函数失败,传真服务调用 GetLastError 函数检索扩展错误信息。函数失败时,传真服务供应商必须立即调用 SetLastError 以设定最新错误代码。如果传真服务供应商在设定最新错误代码后调用另外的 Win32 函数,则此函数能覆盖传真服务供应商的最新错误代码。
3.2.10、传真图象格式
传真服务基于 TIFF 6.0 规范为传真文件创建标签图象文件格式类F文件( TIFF F类)。
除了TIFF 6.0 规范的要求,传真服务对 TIFF类F文件有下列要求:
a.TIFF 文件必须可以修订修改读( MMR )2维编码数据压缩格式。此格式由 CCITT(国际的电报电话咨询委员会)组 4 定义。
b.TIFF 文件的命令字节格式必须匹配CPU处理文件的命令字节格式。如little-endian  CPU接收一份 TIFF 文件,则文件必须为 little-endian 格式。
c.TIFF字段(标签) RowsPerStrip 必须包含值 1,这是因为传真服务不支持数据图象条的传送。 RowsPerStrip 在传真图象时描述每个图象条的扫描行数。
3.3、传真服务供应商 API应用
本节主要论述,传真服务供应商状态变化时创建并邮寄完备包到传真服务和使用虚拟传真设备传送传真。
3.3.1、创建完备包
下列例程说明了创建一个 I/O 完备包并且邮寄包到传真服务的过程。当传真供应商改变状态时,服务供应商必须以 FAX_DEV_STATUS 结构形式邮寄 I/O 完备包到传真服务。
例程首先计算FAX_DEV_STATUS 结构所要求的大小,并调用 HeapAlloc 函数按照 FaxDevInitialize 函数的 HeapHandle 参数指定的堆为该结构分配内存。然后例程把值赋到结构中的各个成员。最后,例程使用FaxDevStartJob 函数指定的 CompletionPortHandle 和CompletionKey 参数调用 PostQueuedCompletionStatus 函数邮寄完备包。
例程:
BOOL rVal;
DWORD StatusSize;
PFAX_DEV_STATUS FaxStatus;
 
 
//
// Compute the size of the status structure.
//
 
StatusSize = 0;
 
//
// Allocate memory for the status structure.
//
 
FaxStatus = (PFAX_DEV_STATUS) HeapAlloc( HeapHandle, HEAP_ZERO_MEMORY, StatusSize );
if (!FaxStatus) {
    //
    // Process some errors.
    //
}
 
//
// Assign values to the status structure.
//
 
FaxStatus->SizeOfStruct     = sizeof(FAX_DEV_STATUS);
FaxStatus->StatusId         = 0;
FaxStatus->StringId         = 0;
FaxStatus->PageCount        = 0;
FaxStatus->CSI              = NULL;
FaxStatus->CallerId         = NULL;
FaxStatus->RoutingInfo      = NULL;
FaxStatus->ErrorCode        = 0;
 
//
// Post the packet to the fax service.
//
 
rVal = PostQueuedCompletionStatus(
    CompletionPortHandle,             // from FaxDevStartJob
    sizeof(FAX_DEV_STATUS),
    CompletionKey,                    // from FaxDevStartJob
    (LPOVERLAPPED) FaxStatus
    );
if (!rVal) {
    //
    // Process some errors.
    //
}
 3.3.2、使用虚拟设备传送传真
支持虚拟的传真设备的传真服务供应商必须输出FaxDevVirtualDeviceCreation 函数。传真服务在初始化期间调用该函数。可以使用虚拟传真设备进行收发传真等多项工作。
(1)使用虚拟传真设备传送传真
 使用一台虚拟传真设备发送传真不需要任何特殊步骤。在传送传真时,物理传真设备和虚拟传真设备之间没有差别。当客户排列一个传真作业,传真服务会选择有最高传送优先权的设备来传送传真,此设备可以是物理设备或虚拟设备。
(2)使用虚拟传真设备接收传真
当传真服务调用 FaxDevVirtualDeviceCreation 时,服务指定CompletionPort参数I/O 完备端口的句柄和CompletionKey 参数值。
当供应商邮寄 I/O 完备端口包来信令传真服务,供应商将在供应商虚拟端口上接收一份传真时,传真服务供应商必须使用这些值。这些值信令传真服务调用 FaxDevStartJob 函数初始化传真作业的传真服务和 FaxDevReceive 函数。(此步是必要的,因为虚拟设备没有使关联的电话服务供应商为传真服务产生振铃事件。)
使用虚拟传真设备接收一份传真,传真服务供应商必须执行以下列步骤:
a.输出 FaxDevVirtualDeviceCreation 函数。
b.调用 PostQueuedCompletionStatus 函数,用信令传真服务供应商想要接收传真。由使用CompletionKey和CompletionPort参数值传真服务指定何时服务调用 FaxDevVirtualDeviceCreation 函数。完备端口包必须是 LINEMESSAGE 结构。
c.当传真服务调用FaxDevStartJob函数时,适当回应。
d.当传真服务调用FaxDevReceive函数时,适当回应。
e.继续调用 PostQueuedCompletionStatus 函数,接收消息并邮寄更新状态,直到传真服务调用 FaxDevEndJob。由指定CompletionPort和CompletionKey 参数值服务指定传真服务何时调用 FaxDevStartJob 函数。完备端口包必须是 FAX_DEV_STATUS 结构。
第四章 传真路由扩展应用程序接口
传真路由扩展应用程序接口(API)允许为微软®传真服务增加路由功能。 API为第三方软件卖主提供多种路由方法来与传真软件程序连接。
本章描述支持传真路由扩展API的组件及API提供的功能,同时也提供注册传真路由扩展DLL和管理传真设备的要求。
本章中的传真路由方法是指传真路由扩展DLL支持和定义的程序。
4.1、传真路由扩展API简介
传真路由扩展API允许第三方软件卖主在与微软®传真服务接口时使用多个传真路由方法接收传真。这些方法主要有:打印传真、存储传真、转换传真图象为文本文件。
下图提供了传真路由进程的概况:

 
必须在源文件中包含传真路由扩展头文件FaxRoute.h。
4.1.1、传真路由扩展软件要求
下列组件要求支持传真路由扩展API:
a.传真路由扩展动态链接库(DLL),该DLL是已定义的连接第三方卖主传真路由软件和传真服务的接口。
b.传真服务 (FaxSvc.exe)。此服务支持程序为传真路由扩展提供可执行上下文。传真服务管理传真设备和配置数据、提供打印设备、收发传真文件。传真服务也为传真路由扩展提供初始化和重发传真路由方法 。
此外,程序源代码文件必须包含传真路由扩展头文件FaxRoute.h。
4.1.2 、传真路由扩展
传真路由扩展是给传真服务增加路由功能的一个动态链接库(DLL)。多个传真路由器扩展可以处于同一个服务器上。当传真服务器接收一个传真时,把接收的文件按优先级顺序通过每个传真路由扩展发送。客户使用微软®管理控制台(MMC)插件传真服务管理应用程序设置发送的优先级。
每个传真路由扩展必须产生一系列注册健值及通知传真服务其扩展和传真路由方法的键值。如果注册表中存在正确入口,在服务初始化时装载传真路由扩展。
4.1.3、传真路由方法简介
传真路由方法是传真路由扩展定义的一个程序。传真路由方法主要包括打印传真、存储传真和操作接收的传真文件。当服务接收一个传真文件后,传真服务以优先级顺序调用传真路由方法。
传真路由扩展可支持多个传真路由方法,但是扩展必须为每一种路由方法输出名为FaxRourteMethod的特定函数。路由扩展必须为扩展输出的每一个传真路由方法创造一个注册表子键。
传真路由方法可以执行多个操作。例如:读取接收的传真文件,并把从图形文件转换为可编辑的文本文件。传真路由方法不能删除或修改原始的标志图象文件格式,TIFF类F文件。
4.1.4、传真文件列表
传真服务用其接收和处理的传真文档与传真文件列表进行联系。传真路由方法可以使用传真路由函数为文件列表增加文件、删除文件及枚举表中的文件。
在每个传真路由方法运行前,传真文件列表中唯一的文件是接收的传真文件,这是一种TIFF的F类文件。传真路由方法能够把接收的TIFF文件作为一个只读源文件来给传真文件列表创建和增加一个或多个文件。传真服务然后通过多路传真路由扩展和每个扩展中的多个路由方法发送所接收的文件。这个增加的功能事实上就是传统的文件过滤器。
例如,传真路由扩展的传真路由方法包含以下步骤:
a.使用光学字符识别技术(OCR)把接收的TIFF文件转换为文本。
b.从文本中创建一个微软Word文档。
c.把Word文本文件增加到与接收的传真有关的传真文件列表中。
在此实例执行后,任何传真路由方法都能访问传真文件列表中的Word文档。如果传真路由采用e-mail程序发送接收的传真,则可以在客户的电子邮件信息中包括Word文档和TIFF文件。
传真路由方法不能修改原始的TIFF文件或把它从传真文件列表中删除。
4.1.5、初始化传真路由扩展
传真服务每次开始时,会调用FaxRouteInitialize函数来初始化传真路由扩展。如果函数调用成功,则传真服务按优先级顺序通过这个扩展的传真路由方法路由接收的传真。当传真服务调用FaxRuoteInitialize时,传真路由扩展必须执行所有必要的初始化操作。
当传真服务调用FaxRouteInitialize时,传真服务把指针传递给FaxRouteAddFile、FaxRouteDeleteFile、FaxRouteGetFile、FaxRouteModifyRoutingData和FaxRouteEnumFiles回调函数。服务在FAX_ROUTE_CALLBACKROUTINES结构中传递指针。扩展的传真路由方法调用这些函数管理与接收传真文档关联的传真文件列表文件。传真路由扩展必须以全局变量存储这个回调函数的指针以备后用。传真路由扩展必须输出FaxRouteInitialize函数。
4.1.6、发送传真
传真路由扩展能输出多个FaxRouteMethod路由函数,每个路由方法对应一个函数,每个函数必须有唯一的名称。FaxRouteMethod是扩展定义的传真路由方法的占位符。
传真服务把FAXROUTE结构传送给传真路由方法。这个结构确定与接收的传真有关的传真作业,包括路由信息和调用及接收传真设备的数据。
传真路由方法可以调用FaxRouteModifyRoutingData函数来改变或添加以后路由方法会用到的FAX_ROUTE结构的路由信息。要修改的路由方法必须比调用的路由方法优先级低,也必须在调用的路由方法之后运行。(优先级定义了当服务接收传真文档时传真服务调用传真路由方法的相对顺序)
当传真服务调用FaxRouteInitialize函数时,传真服务给FaxRouteModifyRoutingData回调函数传递一个指针,并把这个指针放在FAXROUTECALLBACKROUTINES结构中。
FaxRouteGetRoutingInfo函数和FaxRouteSetRoutingInfo函数分别检索和修改指定传真设备的传真路由配置资料。传真路由扩展必须输出FaxRouteGetRoutingInfo和FaxRouteSetRoutingInfo函数。
4.1.7、管理传真文件列表
传真路由方法可以调用一个或多个函数来管理与接收传真文档有关的传真文件列表文件。
在第一个传真路由方法运行前,传真文件列表中唯一的文件是接收的标签图象文件格式,TIFF  F 类文件。传真路由方法可以用接收的TIFF文件作为只读源文件来给文档的传真文件列表创建、增加一个或多个文件。
例如,路由方法能把接收的TIFF文件转换为可编辑的文本文件。然后把文本文件添加到与接收的传真关联的传真文件列表中去。在给传真文件列表中添加文件时,传真路由方法必须调用FaxRouteAddFile函数提供文本文件的路径和名称的指针。
传真路由方法调用FaxRouteDeleteFile函数来删除传真路由扩展方法已增加到传真文件列表中的文件。传真路由方法不能修改原始TIFF文件或把它从传真文件中移走。
为了列举传真文件列表中的文件,传真路由可以方法调用FaxRouteEnumFiles回调函数。FaxRouteEnumFiles给FaxRouteEnumFile回调函数传送一个指针(路由扩展必须定义一个FasRouteEnumFile函数)。传真服务对传真文件列表中的每个文件都调用一次FaxRouteEnumFile,这个函数返回列表中每个文件的完全有效路径和名称。
传真路由方法也可以使用文件索引调用FaxRouteGetFile回调函数来从传真文件列表中检索一个特定的文件名。传真路由方法必须调用FaxRouteGetFile函数两次。第一次调用时,给FileNameBuffer参数中传递一个NULL(空)指针。传真服务把RequiredSize参数设置为FileNameBuffer所需要的大小。传真路由方法给FaxRouteInitialize函数指定的堆栈分配缓存所需的内存,然后再次调用FaxRouteGetFile,这次调用FaxRouteGetFile必须在FileNameBuffer参数中传递一根有效指针。
当传真服务调用FaxRouteInitialize函数时,传真服务把函数指针传递给FaxRouteAddFile,FaxRouteDeleteFile,FaxRouteGetFile,FaxRouting和FaxRoutEnumFile函数。服务在FAXROUTECALLBACKROUTINES结构中传递指针。
4.2、传真路由扩展注册
每个传真路由扩展必须在安装时注册传真服务,以提供有关扩展和传真路由方法的信息。
4.2.1、注册传真路由扩展
传真路由扩展可直接安装在传真服务器上(本地安装)或从网络上的计算机安装(远程安装)。推荐使用本地安装。
(1)本地安装
为了本地注册传真服务,推荐传真路由扩展DLL按以下步骤操作而不是直接访问注册表。
a.拷贝传真路由扩展DLL到FaxRegisterRoutingExtension函数的ImageName参数指定的位置。
b.调用FaxConnectFaxServer函数,在MachineName参数中定义一个NULL(空)指针,得到一个本地服务器的传真服务器的句柄。
c.调用FaxRegisterRoutingExtension函数,注册传真路由扩展DLL。
必须重启传真服务以使用由FaxRegisterRoutingExtension安装的传真路由扩展上输出的传真路由方法。
(2)远程安装
每个传真路由扩展DLL必须通过在远程计算机注册表下列主键下创建子键来给传真服务提供有关扩展的信息:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fax\Routing Extensions\<MyExtension Id>
这里的<MyExtensionID>是传真路由扩展创建的注册自身的注册表主键名。建议用主键名描述传真路由扩展,标示符可以是公司名称。为了注册扩展,需在注册表主键下设置以下两个值。
值 描述
FriendlyName 包含传真路由扩展的友好用户显示名REG_SZ字符串
ImageName 包含传真路由扩展的全部路径及名称 REG_EXPAND_SZ 字符串,也可包含合法环境变量。
4.2.2、注册传真路由方法
为向传真服务提供有关传真路由扩展的路由方法信息。扩展必须创建下列注册子键。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fax\
Routing Extensions\<MyExtensionID>\Routing Methods
这里〈MyExtensionID〉是传真路由扩展创建的注册自身的主键名。
传真路由扩展必须为每一个传真路由方法的扩展输出创建一个注册表子键。子键名描述的传真路由方法扩展应是已注册的。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fax\Routing Extensions\<MyExtensionID>\Routing Methods\<MyMethodDescription>
为注册传真路由方法,在注册表子键中设置下列要求值:
值 描述
FunctionName 包含传真路由方法函数的传真路由扩展输出的实际名称的REG_SZ字符串。
Guid 包含传真路由方法的合法全局唯一标示符(GUID) REG_SZ字符串。
FuncionName入口必须包括运行传真路由方法函数的确切名字。入口区分大小写,必须包括名字装饰,传真服务器在调用GetProcAdDRess函数时使用该入口去检索运行指定传真路由方法的函数地址。
为向路由方法产生一个GUID,可以运行VOIDGEN.EXE工具,为注册表格式化的GUID必须为包含在花括号中的无效终止串。如:
{12340001-4980-1920-6788-123456789012}
GUID由于以下原因,必须指定一个传真路由:
a.传真路由扩展DLL能支持多路由方法;
b.传真路由扩展DLL可为每个路由方法和每个传真设备设置唯一配置数据;
c.多路传真路由扩展DLL能输出有同样名字的路由方法。
4.3、管理传真设备
当传真设备被从传真服务器中添加或删除时,或安装一个新传真设备时,传真服务调用FaxRouteDeviceChangeNotification函数通知传真路由扩展。扩展此时执行所需的初始化程序或清除路由。
调用FaxRouteDeviceEnable函数可以激活或屏蔽特定传真设备指定的传真路由方法,此函数也允许传真路由扩展查询传真设备上路由方法的状态。
传真路由扩展必须输出FaxRouteDeviceChangeNotification和FaxRouteDeviceEnable函数。
4.4、枚举可获传真设备
为枚举可获传真设备, 传真路由扩展必须读取注册表。在初始化期间,推荐传真路由扩展打开和读取下列主键: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fax\Devices
此主键下的注册表子键即是使用传真路由扩展方法的可获传真设备。每个传真设备有多个注册表值,但是传真路由扩展要求的该值是包含传真设备标示符的双字PermanentLineId值。在调用传真路由扩展函数时,传真设备传递此标示符。传真路由扩展应在注册表相应Devices主键下创建子键来存储永久传真设备配置。一个传真路由扩展的数据样本应包含特定传真设备文件配置格式信息。传真路由扩展读取注册表后,必须在注册表中创建一张表格以复制每个可获传真设备的标示符。传真路由扩展须在表中对指向传真路由扩展的特定传真设备复制所有的配置数据。


 

本文地址:http://com.8s8s.com/it/it2218.htm