版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1 1第9章 链接库技术9.1 链接库概述链接库概述9.2 静态链接库静态链接库9.3 动态链接库动态链接库9.4 传输效力提供者传输效力提供者小结小结2 2在程序设计过程中,往往需求反复运用一段或假设干代码(函数或过程),这种需求叫做程序复用。程序复用采用的方法往往是将复用的代码集成为一个个方便调用的包,这种包可以是链接库、类库、COM包、插件、控件,等等。从本章开场,将先后引见两种代码复用的集成技术,即链接库技术和MFC类库(见第10章)。本章引见的链接库技术是一种非常有用的代码集成技术,对于代码的复用、软件的晋级、调用的规范化、不同编程器的协同编程等都至关重要。3 3本章首先引见链接库的
2、概念,然后依次引见静态和动态两种链接库的概念、调用以及编写方法,继而针对网络中不同类型的动态链接库的调用,引见了基于链接库技术的Winsock传输效力提供者(Service Provider Interface,SPI)编程。SPI编程为用户设计本人的通讯协议、防火墙和木马程序提供了有效手段。4 4链接库是从C言语函数库和Pascal库单元的概念开展而来的。一切的C言语规范库函数都存放在某一函数库中,同时用户也可以用公用的程序创建本人的函数库。在库函数链接运用程序的过程中,链接器从库文件中拷贝程序调用的函数代码,并把这些函数代码添加到可执行文件中。9.1 链链接接库库概概述述5 5目前链接库有
3、静态和动态之分,二者的链接方法有所不同。假设采用静态链接库,那么lib中的指令全部都被直接包含在最终生成的EXE文件中了;假设运用dll,那么该dll不用被包含在最终的exe文件中,exe文件执行时可以“动态地援用和卸载这个与exe独立的dll文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态链接库,而在动态链接库中还可以再包含其他的动态或静态链接库。6 6需求留意的是,头文件与库文件都包含函数,但二者存在以下区别:(1) 头文件由编译器运用,库文件由衔接器运用;(2) 头文件中的函数为对应的库文件中的函数提供接口(ASCII码),普通包括函数声明、宏
4、定义、类型定义等,库文件中放着函数实现代码编译后的结果(二进制的机器码)。7 79.2.1 静态链接库概念静态链接库不同于动态链接库(*.dll),在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.lib),Visual C+的编译器在链接过程中将从静态库中恢复这些函数和数据并把它们和运用程序中的其他模块组合在一同生成可执行文件。这个过程称为“静态链接,此时由于运用程序所需的全部内容都是从库中复制出来的,所以静态库本身并不需求与可执行文件一同发行。9.2 静静态态链链接接库库8 8可以说,每一个lib文件就是假设干函数(假设只需函数)的定义。完好的可调用的静态链接库最少提供两个
5、文件,即静态库的头文件和静态库的lib文件。9 99.2.2 静态链接库设计静态链接库设计创建一个静态链接库可以利用编译器的导游。创建一个静态链接库可以利用编译器的导游。以以VC6.0为例,首先选择为例,首先选择“FileNew菜单,弹出菜单,弹出“New对话框;选择对话框;选择“Projects标签,在工程类标签,在工程类型列表框中选择型列表框中选择“Win32 Static Library项,在项,在“Name中输入中输入“MyLib,阐明要创建一个,阐明要创建一个MyLib.lib的静态库文件,最后选择的静态库文件,最后选择“完成。其他完成。其他版本的版本的VC编译器与这个过程区别不大。
6、编译器与这个过程区别不大。在工程中最少需求新建在工程中最少需求新建.h和和.cpp两个文件,两个文件,一个用于对要封装的函数进展声明,一个是函数一个用于对要封装的函数进展声明,一个是函数的实现。下面两段程序就是的实现。下面两段程序就是MyLib.h和和MyLibp,封装了函数封装了函数MyFunc()。10 10文件MyLib.h如下:#ifndef _MYMATH_H #define _MYMATH_H extern C int MyFunc(int n); /进展函数的声明/其他函数的声明 #endif11 11文件MyLibp如下:#includeMyLib.h int MyFunc(i
7、nt n) return n+=1003; 编译这个工程就得到了一个MyLib.lib文件,这个文件就是一个函数库,它提供了MyFunc功能。将头文件和.lib文件提交给用户后,用户就可以直接运用其中的函数了。12 129.2.3 静态链接库调用静态链接库调用调用静态链接库的方法有两种:一种是经过调用静态链接库的方法有两种:一种是经过编译器中的工程设置实现调用,另一种是在程序编译器中的工程设置实现调用,另一种是在程序代码中参与调用语句。两种调用方式都需求将要代码中参与调用语句。两种调用方式都需求将要调用的静态链接库的头文件采用调用的静态链接库的头文件采用“#include方法方法参与文件。参与
8、文件。1工程设置调用工程设置调用在在Win32环境下的环境下的VC+6.0编译器,以调用编译器,以调用netapi32.lib静态链接库为例,在菜单中的静态链接库为例,在菜单中的“工程工程下拉菜单的下拉菜单的“设置项的设置项的“Link选项卡中参与选项卡中参与netapi32.lib,如图,如图9-1所示。所示。13 13图9-1 netapi32.lib设置14 14在VS2019中,工程调用设置分两步: 右键点击工程名testlib,选择“属性,弹出“工程属性框,然后选择“配置属性链接器常规附加库目录选项,该选项就是用于设置lib所在目录的,添加的目录如图9-2所示; 选择“属性项,弹出“
9、工程属性框,然后是“配置属性链接器常规附加依赖项,该选项就用于指定工程中需求用到的库文件(由于前面曾经指定了库文件所在目录),如图9-3所示。15 15 图9-2 VS2019的lib途径设置 16 16 图9-3 VS2019的文件设置17 17对于系统规范库(如包含函数printf的库文件),在程序中调用的时候只需把它的头文件“stdio.h用“#include加到程序里就可以了,不用再手工指定,衔接器会在编译时自动衔接它们,因此调用方法会与后面提及的方法稍有不同。18 182程序代码调用程序代码调用除了上述在编译器中设置除了上述在编译器中设置lib之外,还可以在之外,还可以在运用程序代码
10、中直接调用。运用如下语句进展静运用程序代码中直接调用。运用如下语句进展静态链接库的调用时,该当留意该链接库该当放在态链接库的调用时,该当留意该链接库该当放在编译器可以找到的位置,否那么就该当在文件名编译器可以找到的位置,否那么就该当在文件名处把文件的途径写全处把文件的途径写全(假设假设netapi32.lib放在根目录放在根目录下下)。#include stdafx.h#includeMyLib.h #pragma comment(lib,MyLib.lib) /#pragma comment(lib,C: MyLib.lib)19 19int main(int argc, char* arg
11、v)int a=MyFunc(2); printf (jiguo is %d,a); return 0; 这种调用方法比较适宜其他程序员对程序源代码的阅读,同样也不适用于系统规范库20209.3.1 动态链接库概念动态链接库在Windows操作系统中,对于程序执行是非常重要的,由于程序在执行的时候必需链接到dll文件,才可以正确地运转,而有些dll文件可以被许多程序共用。因此,程序设计人员可以利用dll文件,使程序不至于太过宏大。但是当安装的程序越来越多时,dll文件也就会越来越多,当用户删除程序的时候,假设没有用的dll文件没有被删除的话,久而久之就会呵斥系统的负担。9.3 动动态态链链接接
12、库库21 21运用动态链接库的一些益处是:(1) 多个运用程序共享代码和数据。比如Office软件的各个组成部分有类似的外观和功能,这就是经过共享动态链接库实现的。(2) 在钩子(挂钩)程序过滤系统音讯时必需运用动态链接库。(3) 动态链接库以一种自然的方式将一个大的运用程序划分为几个小的模块,这有利于小组内部成员的分工与协作,并且各个模块还可以独立晋级。假设小组中的一个成员开发了一组适用例程,他就可以把这些例程放在一个动态链接库中,让小组的其他成员运用。2222(4) 为了实现运用程序的国际化,往往需求运用动态链接库。运用动态链接库可以将针对某一国家、言语的信息存放在其中。对于不同的版本,应
13、运用不同的动态链接库。在运用AppWizard生成运用程序时,我们可以指定资源文件运用的言语,这就是经过提供不同的动态链接库实现的。(5) 拓展研发工具的功能。由于dll是和言语无关的,因此创建一个dll,可以被C+、VB或一切支持动态链接库的言语调用。假设一种言语存在缺乏,就能经过访问另一种言语创建的dll来弥补。2323VC+、C+ Builder、Delphi都可以编写dll文件。dll不是独立运转的程序,它是某个程序的一个部分,它只能由所属的程序调用,用户不能翻开它。生成一个动态链接库时应包含两个文件:*.dll和*.lib。lib是编译时需求的,dll是运转时需求的。假设要完成源代码
14、的编译,有lib就够了。假设要使动态链接的程序运转起来,有dll就够了。lib文件是必需在编译期就链接到运用程序中的,而dll文件是运转期才会被调用的。dll文件包含函数的实现,是可执行的代码。lib文件是dll的一个映像文件,普通包含一些索引信息,如dll导出的函数的称号和位置等。动态链接库有两种调用方式:隐式调用和显示调用。24249.3.2 动态链接库调用动态链接库调用动态链接库调用的方法分隐式和显式两种。动态链接库调用的方法分隐式和显式两种。1隐式调用隐式调用运用程序运用运用程序运用lib文件链接到所需求运用的文件链接到所需求运用的dll文件,库中的函数和数据并不复制到文件,库中的函数
15、和数据并不复制到exe文件中,文件中,因此在运用程序的可执行文件中,存放的不是被因此在运用程序的可执行文件中,存放的不是被调用的函数代码,而是调用的函数代码,而是dll中所要调用的函数的内中所要调用的函数的内存地址存地址(lib文件是必需的文件是必需的),下面以动态链接库,下面以动态链接库a为为例阐明其隐式调用步骤,可分为以下三步:例阐明其隐式调用步骤,可分为以下三步:(1) 确保确保a.dll和和a.lib两个文件都存放到了指定两个文件都存放到了指定目录目录(这里假设两个文件放在调用该库的运用程序这里假设两个文件放在调用该库的运用程序所在目录所在目录);2525(2) 将要调用函数(假设为t
16、est()函数)的文件定位信息(包含在lib文件中)和声明写到调用该库及函数的代码头文件中。#pragma comment(lib,a.lib) /指定该动态链接库相应静态库的文件定位信息extern C_declspec(dllimport) test1); /对需调用的函数进展声明 (3) 进展(2)中的声明后,就可以在文件中调用该函数了。26262显式调用显式调用假设假设dll没有对应的没有对应的.lib文件,那么就只能运用文件,那么就只能运用显示调用显示调用(动态加载动态加载)的方式了,显式调用步骤如下:的方式了,显式调用步骤如下:(1) 创建一个函数指针,其指针数据类型要与创建一个函
17、数指针,其指针数据类型要与调用的调用的dll引出函数相吻合;引出函数相吻合;(2) 经过经过Win32 API函数函数LoadLibrary()显式地显式地调用调用dll,此函数前往,此函数前往dll的实例句柄;的实例句柄;(3) 经过经过Win32 API函数函数GetProcAddress()获取获取要调用的要调用的dll的函数地址,把结果赋给自定义函数的函数地址,把结果赋给自定义函数的指针类型;的指针类型;(4) 运用函数指针来调用运用函数指针来调用dll函数;函数;2727(5) 调用完成后,经过Win32 API函数FreeLibrary()释放dll函数。同样,以动态链接库a的te
18、st函数为例,下面代码描画了显式调用过程。typedef int(*test)();/宏定义声明欲调用函数指针类型,/简要起见这里该函数没有方式参数2828HINSTANCE hDll;/Dll句柄test myFun;/函数指针hDll=LoadLibrary(a.dll);/显式调用dll,a.dll文件放置在运用程序所在目录if (hDll!=NULL) myFun=(test)GetProcAddress(hDll, test);/获取函数地址2929 if (addFun!=NULL)test();/函数调用FreeLibrary(hDll);/释放dll如前所述,dll正确调用的前
19、提是,需将dll(隐式的还包括lib文件)放入系统可以找到的目录下(系统寻觅dll文件的顺序依次为:运用程序所在目录当前目录Windows系统目录PATH环境中设置的其他目录),假设不能找到该dll库文件,那么调用势必失败。30309.3.3 动态链接库编程动态链接库编程dll可以简单分为两种类型,即用可以简单分为两种类型,即用C/C+(不用不用对象对象)编写的基于编写的基于API的传统的传统dll和基于和基于MFC对象的对象的dll。在。在VC中可以利用导游,以前者为例:在中可以利用导游,以前者为例:在“FileNewProjects中选择中选择“Win32 Dynamic-Link Lib
20、rary项,并在项,并在“Project Name中输入中输入“demo之后,按之后,按“OK按钮就可以生成一个按钮就可以生成一个dll工程。工程中的工程。工程中的demop文件如下:文件如下:#include stdafx.h#include demo.hBOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)31 31 switch (ul_reason_for_call)case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL
21、_THREAD_DETACH:case DLL_PROCESS_DETACH:break; return TRUE;3232/ This is an example of an exported variableDEMO_API int nDemo=0;/ This is an example of an exported function.DEMO_API int fnDemo(void) return 42;void _declspec(dllexport) test()3333 MessageBox(NULL,Its so easy!,test,MB_OK);/ This is the
22、constructor of a class that has been exported. see demo.h for the class definitionCDemo:CDemo() return; 3434这就像C言语编写的运用程序一样,每一个dll必需有一个入口点,DllMain()是一个缺省的入口函数,用这个缺省的入口函数就能使动态链接库被调用时得到正确的初始化。参数中,hMoudle是动态库被调用时所传送来的一个指向本人的句柄(实践上,它是指向_DGROUP段的一个选择符);ul_reason_for_call是一个阐明动态库被调缘由的标志(当进程或线程装入或卸载动态链接库时,
23、操作系统调用入口函数,并阐明动态链接库被调用的缘由);lpReserved为保管参数。3535dll中定义了两种函数:导出函数(exportfunction(),可以被其他模块调用)和内部函数(internalfunction(),只能在dll内部运用)。该文件设计了一个名为nDemo()的导出变量,名为fnDemo()和text()的导出函数、一个名为Cdemo()的导出类,详细定义在demo.h中。_declspec(dllexport)是VC提供的一个关键字,用它可在动态链接库中输出一个数据、一个函数或一个类,与_declspec(dllimport)配合运用(参见9.3.2节)。363
24、6WinSock是Windows平台下的网络编程接口,支持多种通讯协议,这一点置信大家在本书的前些章节中曾经深有领会。然而读者也许会产生疑问,WinSock是如何对不同通讯协议进展选择呢?这主要是得益于基于链接库技术实现的SPI这种效力。经过SPI的运用,用户可以监控WinSock来调用、插入本人期望的操作,这对于网络通讯、QoS(Quality of Service,质量效力)、数据包过滤、木马程序都是必要的。本节将对SPI效力编程进展引见。9.4 传输效力提供者传输效力提供者37379.4.1 SPI引见引见SPI是由是由WinSock2提供的建立在提供的建立在Windows开开放系统架构
25、放系统架构WOSA(Windows Open System Architecture)之上的一种运用程序效力。这种架构之上的一种运用程序效力。这种架构允许第三方效力提供者插入进去,从而使得允许第三方效力提供者插入进去,从而使得WinSock更加开放,也可以得到第三方的支持与扩更加开放,也可以得到第三方的支持与扩展。展。1根本构成根本构成WinSock2 SPI由传输效力提供者和名字空间由传输效力提供者和名字空间效力提供者组成。效力提供者组成。3838传输提供者(Transport Providers,TP)普通称做协议堆栈,例如TCP/IP,可以提供建立通讯、传输数据、日常数据流控制和错误控制
26、等传输功能方面的效力。名字空间提供者(Name Space Providers,NSP)(如DNS名字解析效力)把一个网络协议的地址属性和一个或多个用户友好称号关联到一同,以便启用与运用无关的名字解析方案。传输效力提供者是本书程序设计所关怀的SPI效力,它可以分为两类:根底效力提供者(Base Service Provider,BSP)和分层效力提供者(Layered Service Provider,LSP)。3939BSP执行网络传输根底协议(如TCP/IP)的详细细节,其中包括在网络上收发数据之类的中心网络协议功能,普通由开发商提供。LSP只担任执行高级的自定义通讯功能,并依托下面的根底
27、效力提供者,在网络上进展真正的数据交换。LSP将本人安装到LSP链(参见9.4.2节)的根底效力提供者上面,截取来自运用程序WinSock API的调用,安排适宜的BSP来实现根底协议。假设把根底效力提供者比作“座位,那么LSP就相当于“引座员。只需程序环境支持WinSock2 SPI,程序员就可以经过定制、修正LSP,在根底协议上实现一些自定义的功能,如平安管理或带宽管理。40402SPI函数函数各种各种SPI都是都是Windows支持的支持的dll,挂靠在,挂靠在WinSock2的的WS2_32.dll模块下。模块下。SPI的实现基于的实现基于SPI函数和函数和SPI协议。协议。SPI函数
28、的类型可以经过其前缀加以区分,详函数的类型可以经过其前缀加以区分,详细见表细见表9-1。41 41表9-1 SPI函数前缀及含义4242实践上,SPI函数就是WinSock详细动作的真正实现者,也就是说,用户运用程序调用的WinSock2 API函数,根本都是由SPI提供应它们对应的运作方式而实现功能的,例如:API函数WSAConnect有相应的SPI函数WSPConnect,调用WSAConnect,WSAConnect又调用WSPConnect来实现详细的动作。被运用程序调用的WS2_32.dll里的WinSock API函数,大部分都最终映射成了SPI里的30个函数,这30个函数都是用
29、WSP开头的。4343不被映射到SPI的WinSock API操作主要有以下几种情况:(1) 地址转换函数,如hton()、lhtons()、ntohl()、ntohs()、inet_addr()、inet_ntoa()。(2) WinSock错误码查询函数,如WSAGetlastErro()、WSASetlastError()。(3) 事件对象操作和等待函数,如WSACreateEvent()、WSASetEvent()、WSARetEvent()、WSACloseEvent()、WSAWaitforMutipleEvents()。(4) WinSock效力提供者枚举函数,如WSAEnumP
30、rotocals()。4444(5) 名字转换和地址解析函数,如gethostname()等。SPI里的函数是不能被运用程序直接调用的,而是应该由WS2_32.dll来调用。45453协议分类Windows Socket SPI提供了三种协议:分层协议、根底协议和协议链。分层协议是在根底协议的上层,依托底层根底协议实现更高级的通讯效力。根底协议是可以独立、平安地和远程端点实现数据通讯的协议,它是相对于分层协议而言的。协议链是将一系列的根底协议和分层协议按特点的顺序衔接在一同的链状构造。46464任务位置SPI处于WS_32.dll和底层的通讯协议之间,文件位置如图9-4所示,协议位置如图9-5
31、所示。SPI向上为用户运用程序提供一个规范的API接口,向下为WinSock组件和WinSock效力提供者(比如TCP/IP协议栈)之间提供一个规范的SPI接口。4747 图9-4 SPI文件位置 4848 图9-5 SPI协议位置49495动态加载动态加载调用调用WSAStartup期间,期间,WinSock根据根据WSASocket调用的地址家族、套接字类型和协议调用的地址家族、套接字类型和协议参数,以决议需求加载哪个效力提供者。以参数,以决议需求加载哪个效力提供者。以TCP/IP协议为例,只需在一个运用程序经过协议为例,只需在一个运用程序经过Socket或或WSASocket API调用
32、建立一个地址家族为调用建立一个地址家族为AF_INET、套接字类型为、套接字类型为SOCK_STREAM的套接的套接字时,字时,WinSock才会搜索并加载与之相应的、可以才会搜索并加载与之相应的、可以提供提供TCP/IP才干的传输效力提供者。才干的传输效力提供者。WSPStartup的参数的参数UpcallTable获得获得WS2_32.dll的的SPI函数派遣函数派遣表,表,LSP利用这些函数来管理本身和利用这些函数来管理本身和WinSock2之之间的间的I/O操作。操作。50509.4.2 LSP编程编程本节重点引见本节重点引见LSP编程的主要思想。编程的主要思想。1开发原那么开发原那么
33、TSP的的BSP实现了网络协议传输的实践细节,实现了网络协议传输的实践细节,包括建立衔接、传送数据、流控制和过失控制。包括建立衔接、传送数据、流控制和过失控制。各种协议就是在各种协议就是在BSP中实现的。普通的中实现的。普通的BSP是由操是由操作系统厂商和传输协议栈厂商提供的。即使用户作系统厂商和传输协议栈厂商提供的。即使用户开发了本人的开发了本人的BSP,也会由于无法推行而变得毫无,也会由于无法推行而变得毫无意义。另外,意义。另外,NSP与与TSP类似,实际上也可以分为类似,实际上也可以分为根底的和分层的根底的和分层的SP,但是目前分层的效力系统还,但是目前分层的效力系统还不支持,而根底的也
34、由开发商提供,由此可见留不支持,而根底的也由开发商提供,由此可见留给程序员的传输者效力编程主要就是给程序员的传输者效力编程主要就是LSP的开发。的开发。51 51LSP是BSP之上的,用于实现高层的用户自定义的通讯功能,详细包括:监控和过滤网络数据、修正网络数据(包括加密)、数据重定向、URL重定向(代理效力器)、防火墙、WOSA实现等功能。由于LSP依赖于下层的BSP,因此这种自定义的通讯功能设计要遭到BSP功能的限制,比如开发者可以在此根底上开发许多有用的运用。52522程序构造程序构造WinSock2 LSP都是规范的都是规范的Windows dll,这些,这些dll只需一个导入的入口函
35、数,即只需一个导入的入口函数,即WSPStartup。该。该SPI函数的原型如下:函数的原型如下:int WSPStartup ( WORD wVersionRequested, /调用者支持的最高版本号调用者支持的最高版本号 LPWSPDATAW lpWSPData, /用于接纳用于接纳WinSock的的SP的信息指针的信息指针5353 LPWSAPROTOCOL_INFOW lpProtocolInfo,/用于定义期望协议特征的/WSAPROTOCOL_INFO指针 WSPUPCALLTABLE UpcallTable, /WS2_32.dll的呼叫派遣表 LPWSPPROC_TABLE
36、lpProcTable /指向SPI函数指针表的指针);5454参数lpProcTable是一个LPWSPPROC_TABLE构造体,这个构造体定义了一个LSP必需实现的函数,以及这些函数的入口点。LPWSPPROC_TABLE的构造如下:typedef struct _WSPPROC_TABLE LPWSPACCEPT lpWSPAccept; LPWSPADDRESSTOSTRING lpWSPAddressToString; LPWSPASYNCSELECT lpWSPAsyncSelect;5555 LPWSPBIND lpWSPBind; LPWSPCANCELBLOCKINGCAL
37、L lpWSPCancelBlockingCall; LPWSPCLEANUP lpWSPCleanup; LPWSPCLOSESOCKET lpWSPCloseSocket; LPWSPCONNECT lpWSPConnect;5656 LPWSPDUPLICATESOCKET lpWSPDuplicateSocket; LPWSPENUMNETWORKEVENTS lpWSPEnumNetworkEvents; LPWSPEVENTSELECT lpWSPEventSelect; LPWSPGETOVERLAPPEDRESULT lpWSPGetOverlappedResult;5757
38、LPWSPGETPEERNAME lpWSPGetPeerName; LPWSPGETSOCKNAME lpWSPGetSockName; LPWSPGETSOCKOPT lpWSPGetSockOpt; LPWSPGETQOSBYNAME lpWSPGetQOSByName;5858 LPWSPIOCTL lpWSPIoctl; LPWSPJOINLEAF lpWSPJoinLeaf; LPWSPLISTEN lpWSPListen; LPWSPRECV lpWSPRecv; LPWSPRECVDISCONNECT lpWSPRecvDisconnect;5959 LPWSPRECVFROM
39、 lpWSPRecvFrom; LPWSPSELECT lpWSPSelect; LPWSPSEND lpWSPSend; LPWSPSENDDISCONNECT lpWSPSendDisconnect; LPWSPSENDTO lpWSPSendTo;6060 LPWSPSETSOCKOPT lpWSPSetSockOpt; LPWSPSHUTDOWN lpWSPShutdown; LPWSPSOCKET lpWSPSocket; LPWSPSTRINGTOADDRESS lpWSPStringToAddress; WSPPROC_TABLE, FAR * LPWSPPROC_TABLE;6
40、1 61可以看出这个构造非常复杂。通常,我们只需求设计所关怀的少量函数,对于没有涉及的函数,可以让其直接调用下一个LSP相应的函数(当然,用户在插入一个本人设计的LSP之前,系统就曾经有其他的LSP存在了)。62623LSP链链LSP和和BSP被串了起来,构成一个协议链。被串了起来,构成一个协议链。WSAPROTOCOL_INFOW构造体构造体(与构造体与构造体WSAPROTOCOL_INFO一致,见一致,见5.2.1节节)就是整就是整个的协议链,它描画了个的协议链,它描画了LSP、SPI的衔接顺序的衔接顺序(如图如图9-5所示所示),可以运用,可以运用PSDK提供的工具对计算机上提供的工具对
41、计算机上的的LSP链进展查询链进展查询(参见参见9.4.3节节)。在在WS2_32.dll调用调用LSP时就是按照时就是按照LSP链来顺链来顺序加载的。首先序加载的。首先LSP链最顶端的链最顶端的LSP由由WS2_32.dll加载,其他的加载,其他的LSP由上一层由上一层LSP加载。加载。6363无论由谁加载一个LSP,加载LSP后,会调用它的SPI函数WSPStartup(),并经过函数的UpcallTable参数(WSPUPCALLTABLE构造体)把上层的LSP信息传给下层。假设一个LSP的下一层是LSP而不是BSP,那么代表协议链信息的lpProtocolInfo (LPWSPPROC
42、_TABLE)也会被SPI函数WSPStartup传送给下层的LSP。程序中,WSPStartup能够被调用多次,每调用一次都必需调用一次SPI函数WSPCleanup(),以保证内存不被浪费。64644LSP安装安装1) 安装原理安装原理LSP安装程序经过配置安装程序经过配置WinSock2系统配置数系统配置数据库据库(WinSock2 system configuration database)实实现现LSP的安装。这个数据库实践上就是一切已安装的安装。这个数据库实践上就是一切已安装的的service providers的目录。的目录。WinSock2可以经过这可以经过这个数据库知道个数据
43、库知道service provider的存在及其定义所的存在及其定义所提供效力的类型。当提供效力的类型。当WinSock运用程序创建运用程序创建socket时,时,WinSock2就会用这个数据库来确定所需加载就会用这个数据库来确定所需加载的的TSP。6565详细是由WS2_32.dll 搜索数据库以找到与该Socket或WSASocket API调用的输入参数(如地址族、socket 类型和协议)相匹配的第一个provider(当存在多个相匹配时,运用第一个)。进而WS2_32.dll就加载目录中指定的相应的service provider dll。这就解释了同样的WinSock函数可以运用
44、不同的通讯协议的问题(参见5.2.1节)。66662) 安装方法要胜利安装并管理WinSock2系统配置数据库中的效力提供者实体(service provider entry)需求四个函数。这四个函数均都是以WSC为前缀开头,它们分别是WSCEnumProtocols()、WSCInstallProvider()、WSCWriteProviderOrder()、WSCDeinstallProvider()。归纳起来,在安装过程中,这几个函数主要关怀的是ProviderId、dwCatalogEntryId和ProtocolChain这三个域。ProviderId域是一个全局独一的标识符,该标识
45、符可用来在任何系统上定义和安装provider。6767dwCatalogEntryId域只是标识了数据库中的每一个WSAPROTOCOL_INFOW目录项构造体。ProtocolChain决议了每个WSAPROTOCOL_INFOW 构造体的类型,构造原型如下:typedef struct int ChainLen; /链值DWORD ChainEntriesMAX_PROTOCOL_CHAIN; /目录ID数组 WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;6868参数ChainLen 决议了目录项表示BSP、LSP或是定义一个协议链(length的
46、值为0时代表LSP,为1代表BSP,大于1时表示这是一个协议链)。对于LSP和BSP,在数据库中每个开发商(provider)只需一个目录项。最后的ChainEntries域表示的目录IDs是用来描画协议链目录项中SP的加载顺序的。安装LSP时,需求创建两个WSAPROTOCOL_INFOW目录项构造体,一个表示LSP,另一个表示将LSP链接到BSP的协议链。运用前要进展初始化,在初始化之后调用WSCInstallProvider()函数来安装LSP的目录项,继而再获得初始化后赋给此构造体的目录 ID。这样目录项就可以建立将LSP链接到另一个provider(可以是LSP,也可以是BSP)的协
47、议链目录项。6969安装链接的provider还要调用WSCInstallProvider()函数,其中LSP的WSAPROTOCOL_INFOW构造体中指定了PFL_HIDDEN 标志,保证了WSAEnumProtocols (参见5.2.1节)不会在前往的缓冲区中包含LSP的目录。70703) 位置排序完成上面步骤之后,LSP就安装到系统上了。但是任务并没有全部完成,想要这个新安装的LSP被正确调用,还需对其位置进展正确排序。这是由于WinSock2在数据库中查找SP时,要经过socket或WSASocket的调用参数来确定计划运用的协议,会首先运用在目录最上头的匹配项。例如,假设创建运用
48、AF_INET地址族和SOCK_STREAM类型的socket,WinSock2会首先在提供此功能的数据库中查找目录最上面的可用的TCP/IP协议链目录项或是BSP目录项。71 71而上面用WSCInstallProvider为LSP安装协议链时,目录项会自动变为数据库的最后一项。为了让新的链成为默许的TCP/IP提供者,还必需将数据库重新排序并调用,即调用WSCWriteProviderOrder将协议链目录项放在其他同类的TCP/IP SP的前面。位置排序完成后,LSP的安装才算全部完成。72729.4.3 LSP程序设计程序设计由由9.4.2节知节知LSP编程需求完成两个部分,即安编程需
49、求完成两个部分,即安装和实现装和实现.dll文件。安装文件将实现文件安装到文件。安装文件将实现文件安装到WinSock2系统配置数据库中,用户就可以调用实系统配置数据库中,用户就可以调用实现文件进展详细的操作了。现文件进展详细的操作了。1安装程序安装程序下面对下面对LSP的安装程序进展引见。在微软提供的安装程序进展引见。在微软提供的的PSDK中中(以以Microsoft Platform SDK for Windows Server 2019 R2为例为例)就有包含就有包含LSP的安的安装文件装文件(在途径在途径.Microsoft Platform SDK for Windows Serve
50、r 2019 R2SamplesNetDS7373WinSockLSPinstall文件夹下),其主要实如今instlsp.cpp文件里,下面对该文件的主要功能函数及其代码功能进展分析引见。/主要功能函数:BOOLgetfilter(); /获得一切曾经安装的传输效力 void freefilter(); /释放存储空间 void installfilter(); /安装分层协议、协议链及排序void removefilter(); /卸载分层协议和协议链/函数代码分析:7474 protoinfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc (GPTR,protoinf
51、osize); /分配WSAPROTOCOL_INFOW构造的存储空间 totalprotos=WSCEnumProtocols(NULL,protoinfo, &protoinfosize,&errorcode); /获得系统中已安装的一切效力提供者 GetCurrentDirectory(MAX_PATH,filter_path); /得到当前的途径 _tcscpy(filter_name,_T(ipfilter.dll); 7575 /构造效力提供者文件ipfilter.dll的途径全名 WSCInstallProvider(&filterguid,filter_
52、path, &iplayerinfo,1,&errorcode); /安装自定义的IP分层协议 iplayercataid=protoinfoi.dwCatalogEntryId; /获得已安装的自定义IP分层协议的由WS2_32.dll分配的独一标志udpchaininfo.ProtocolChain.ChainEntries0=iplayercataid; /将自定义的IP分层协议作为自定义UDP协议链的根分层效力提供者,安装在协议链的顶端7676 WSCInstallProvider(&filterchainguid,filter_path, chainarray
53、,provcnt,&errorcode); /安装协议链 WSCWriteProviderOrder(cataentries,totalprotos); /更新一切效力提供者的安装顺序,把自定义的效力提供者排在一切协议的最前列 WSCDeinstallProvider(&filterguid,&errorcode); /卸载IP分层协议 WSCDeinstallProvider(&filterchainguid,&errorcode); /卸载协议链7777为了加快开发进度,用户可以直接运用PSDK提供的instlsp.exe文件对LSP进展安装。获得i
54、nstlsp.exe的方法很简单,也是利用VC编译器(建议采用VS2019及以上版本)的nmake编译命令,编译目录下的makefile文件。nmake是编译器自带的命令行编译器,其命令协助信息如图9-6所示。编译本节程序时,首先启动命令行工具“cmd,进入编译器的bin目录下(在.MicrosoftVisual StudioVC98Bin),执行vcvars32批处置命令配置环境,再进入LSP的安装文件所在目录执行以下命令(如图9-7所示):nmake /f makefile7878 图9-6 nmake命令协助信息 7979图9-7 nmake编译PSDK例程8080图9-8 LSP链安装
55、情况81 81编译完成后可以得到instlsp.exe 和lsp.dll两个文件,instlsp.exe就是LSP的安装文件。首先把lsp.dll拷贝到系统目录下,然后执行instlsp.exe就可以安装LSP了。LSP安装之后,只需参数相匹配就会加载相应的SPI程序。在Windows下有很多系统网络效力都是在系统启动时自动加载的,这就为隐藏木马进程提供了有利的条件。也就是说,在LSP程序里嵌入木马程序,这样嵌入的木马程序就会在系统启动时自动加载,在系统封锁时才会卸载,隐藏效果很强,需格外引起留意。8282为了了解LSP的安装情况,可以经过 Platform SDK 中的sporder.exe 工具来查看providers的安装和排序情况(如图9-8所示)。留意:运转sporder.exe时,一定要将sporder.dll放在同一目录下,否那么sporder.exe会失败。图中,MSAFD TcpipTCP/IP表示将LSP链接到BSP MSAFD Tcpip TCP/IP上的协议链。由图中的“up、“down功能键可以看出,sp
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年电源适配器项目资金需求报告代可行性研究报告
- 强化品德修养方面存在的问题-原因-措施
- 校园招聘宣讲会演讲稿【汇编五篇】
- 北京高考语文三年模拟真题(21-23年)知识点汇编-写作
- 互联网平台运营合作协议示范文本
- 企业兼职保密协议书格式
- 2024年医疗器械临床试验研究者手册
- 家庭旅馆出租合同格式
- 技术引进合同撰写指南
- 天津改制企业股份制合同样本
- 论《史记_陈涉世家》中陈胜的英雄形象
- xx大学成人高等教育校外教学点检查自查报告
- 《在政府教育工作督导评估反馈会上的表态发言》
- 六年级上册数学比的计算题
- 装饰工程公司架构与职责
- 第三方破坏事故分析与对策
- 投标保证金退付申请书四篇
- 创伤的救治流程PPT课件
- 无机分析化学化学热力学练习题
- 上公司财务风险分析与防范——以苏宁云商为例
- 小学毕业班教学质量目标管理责任书
评论
0/150
提交评论