⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 微过滤器驱动开发指南 之四.txt

📁 文件系统驱动开发的文档资料(IFS DDK)
💻 TXT
📖 第 1 页 / 共 2 页
字号:
微过滤器驱动开发指南 之四

10.与用户态的通信

10.1 过滤器通信端口对象
为了实现安全的和支持多种不同类型通信方法,一个新的对象被引入:微过滤器通信端口(以下简称通信端口或者端口)。专门设计用来给核心态-用户态通信或者反过来。核心-核心通信现在不在支持。一个端口是一个有名字的NT对象。而且有一个安全的描述符号。

过滤管理器生成了一个新的对象类型,FilterConnectionPort来实现这个。过滤管理器在它的DriverEntry中生成这个新的对象类型,赶在了任何微过滤器加载之前。

只有核心模式的驱动才能生成一个通信端口,使用以下的调用:
NTSTATUS
FltCreateCommunicationPort(
  IN PFLT_FILTER Filter,
  OUT PHANDLE PortHandle,
  IN POBJECT_ATTRIBUTES ObjectAttributes,
  IN PVOID ServerPortCookie OPTIONAL,
  IN PFLT_CONNECT_NOTIFY ConnectNotifyCallback,
  IN PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,
  IN PFLT_MESSAGE_NOTIFY MessageNotifyCallback,
  IN ULONG MaxConnections
);
Filter是微过滤器的过滤器句柄。成功生成之后,端口的句柄在PortHandle参数中返回。
和其他的NT对象一样,ObjectAttributes参数定义了OBJECT_ATTRIBUTES结构来初始化要生成的端口对象的名字,对象属性和安全描述符等。

请注意属性中OBJ_KERNEL_HANDLE标记必须设置。因为通信端口只能是核心对象。

ServerPortCookie是一个上下文。微过滤器可以通过这个和端口联系在一起。这个上下文对过滤管理器是不透明的。所有的连接,中断通知,都会同过这个上下文才能传递给微过滤器。有些过滤器可能要生成一组通信端口,又想功用一个同志例程。那么可以通过这个上下文中保存的数据进行区分。

调用者还可以注册一些回调函数:

ConnectNotifyCallback():     当一个用户态进程尝试打开一个端口的时候,这个例程被调用。过滤器可以选择把这个请求失败掉。通知例程回手到一个关于此连接的句柄。每一个连接有唯一的一个句柄。ServerPortCookie 也会传入。微过可以填写ConnectionCookie为一个上下文。这个上下文会传到所有的用户态传来的消息以及连接中断例程中。

DisconnectNotifyCallback():     当一个端口被用户态关闭的时候会调用这个回调。(也就是打开计数到0的时候)。

MessageNotifyCallback():     任何时候手到一个消息都会调用这个。

MaxConnections指出了这个通信端口上允许的最大向外连接数。这没有默认值,必须设置得大于0。

并不能保证所有的对象名会生成在根名字空间。有可能过滤管理器把它们映射在\FileSystem\Filters目录下。不过即使如此,对微过滤器和用户态应用程序来说,这是透明的。当引用了一个通信断口的名字,那么所有的足见都应该使用同样的名字。例子Sacnner Minifiter中展示了这是怎么做的。

对应于新的对象类型,新的访问方式也被引入了。有新的访问方式如下:
FLT_PORT_CONNECT
FLT_PORT_ALL_ACCESS
这是一些访问类型。调用者可以设置这些来给使用者权限。用于构造安全描述符的时候,使用InitializeObjectAttributes()。

设置了FLT_PORT_CONNECT,那么我们的应用程序足可以连接这个端口并发送和接受消息。

微过滤器生成一个端口之后,端口就会开始侦听可能的连接。直到你使用ZwClose()将它关闭为止。

10.2 从用户态连接到通信端口

微过滤器的通信端口模型和旧模型的过滤器一样,是不对称的。核心态端生成,用户态端连接。有一个接口用来给用户态应用打开一个端口。当端口建立,ConnectNotify()例程被调用来通知微过滤器。

用户态下连接一个端口的编程接口原型如下:
HRESULT
FilterConnectCommunicationPort(
  IN LPWSTR lpPortName,
  IN DWORD dwOptions,
  IN LPVOID lpContext,
  IN WORD wSizeOfContext,
  IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  OUT HANDLE *hPort
);

lpPortName是一个宽字符格式的字符串,指出要连接的端口的名字。这个名字应该和微过滤器生成这个端口的时候一样。名字可以以”\”开头表示在根路径中。过滤管理器会在合适的路径下打开他们并管理很多微过滤器通信端口。

dwOptions现在没有使用。
LpContext是一个指针。指向一个不透明的参数块。这个参数会被传入到ConnectNotify()中。比如可以用来鉴别请求生成端口的应用程序的版本。wSizeOfContext指出这个上下文的字节数。

LpSecurtityAttributes指出给用户端的安全权限。如果这个句柄是继承得到的。

如果这个调用不成功,合适的HRESULT会返回。

返回得到的句柄可以被管理或者被复制。这要通过一些编程接口。它也可以和一个I/O完成端口绑定。

当这个接口被调用,一个新的核心态的无名端口对象就生成了(类型是FilterCommunicationPort).这个对象用来表示这个连接。微过滤器的ConnectNotify()例程被调用,从而得到通知。而且也得到连接端口的句柄,用来从核心态发送消息。

如果调用者没有访问这个服务端口的权限,或者已经达到了最大连接数,那么调用会失败。

10.3 中断与通信端口的连接

当用户态程序调用CloseHandle()或者核心态调用ZwClose()来关闭连接句柄的时候,连接会中断。

只有用户态调用CloseHandle()的时候,微端口的DisconnectNotify()例程才会调用。

理想情况下,微过滤器应该总是在连接结束的时候,在DisconnectNotify()中关闭连接。如果一个微过滤器在其他地方关闭句柄,那么它必须用一些同步方法确保不会在DisconnectNotify()中关闭再次关闭它。

当一个连接在核心态或者用户态被中断了,以下情况发生:

1.     所有用户态的等待(通过FilterGetMessage)被清理掉,而且以STATUS_FLT_PORT_DISCONNECTED结束掉(被解释为win32错误码ERROR_DISCONNECTED)。
2. 所有核心的被阻塞的发送例程会以STATUS_FLT_PORT_DISCONNECTED结束阻塞。
3. 因为端口变无效了,所以不可能有其他的等待或者阻塞的情况出现。

微过滤器总是可以对服务端口的句柄调用ZwClose()来关闭服务端口。这并不会使已经建立的连接中断,但是会阻止新连接的建立。

10.4 卸载

微过滤器总是必须在FltUnregisterFilter()调用之前,在FilterUnload例程或者更早关闭服务端口。否则系统可能在卸载例程中被挂起。

即使在有一些连接打开的情况下(比如用户态一放已经打开了一些连接句柄),微过滤器也应该允许被卸载。这种情况下,过滤管理器会尝试强行终止这些连接。过滤管理器会调用DisconnectNotify()例程。微过滤器应该在这里关闭这些连接句柄以避免句柄的泄漏。

11.文件名处理

通过查找操作的参数或者询问文件系统,过滤管理器能得到对象的名字。因而过滤管理器提供一组调用来方便获取对象名。为了更高的效率,过滤管理器也暂存一些对象名。当很多过滤器经常查一个名字的时候,暂存这个名字所付出的代价是很值得的。

查询对象名的时候,过滤管理器返回一个FLT_FILE_NAME_INFORAMTION结构来避免数据拷贝。这些结构被根据过滤器的请求次数计数。只有通过过滤管理器的编程接口才能改变这些结构中的数据。下面有这些结构的详细信息。

11.1 从操作获得一个文件名

可以在当前操作的CallbackData->Iopb->TargetFileObject中得到文件名。这需要调用下面的例程:
NTSTATUS
FLTAPI
FltGetFileNameInformation (
  IN PFLT_CALLBACK_DATA CallbackData,
  IN FLT_FILE_NAME_FORMAT NameFormat,
  IN FLT_FILE_NAME_QUERY_METHOD QueryMethod,
  OUT PFLT_FILE_NAME_INFORMATION *FileNameInformation
);

CallbackData是这个操作的FLT_CALLBACK_DATA结构。现在假设过滤器想从这个操作中得到文件名。

名字的格式是以下三种:
FLT_FILE_NAME_NORMALIZED_FORMAT:请求全路径名字,包括卷名。所有的短名被扩展成长名。任何流名足见回去掉后边的“:$DATA”.如果这是一个目录名,且不是根目录,最后的“\”会被去掉。
FLT_FILE_NAME_OPENED_FORMAT:     包含全路径,包括卷名。但是这个名字和打开这个对象所用的名字相同。因此可能在路径中包含一些短名。
FLT_FILE_NAME_SHORT_FORMAT:     仅仅含有路径中最后一个元素的短名(Dos名),不会返回全路径。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -