Visual Studio 2013开发 mini-filter driver step by step 应用层与内核通讯(8)

应用层与内核通讯是通过通讯端口来进行的,下面的这个API就是内核用来创建一个内核端口的。

NTSTATUS FltCreateCommunicationPort(
  _In_      PFLT_FILTER Filter,
  _Out_     PFLT_PORT *ServerPort,
  _In_      POBJECT_ATTRIBUTES ObjectAttributes,
  _In_opt_  PVOID ServerPortCookie,
  _In_      PFLT_CONNECT_NOTIFY ConnectNotifyCallback,
  _In_      PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,
  _In_opt_  PFLT_MESSAGE_NOTIFY MessageNotifyCallback,
  _In_      LONG MaxConnections
);


这里面有重要的三个回调函数,ConnectNotifyCallback,DisconnectNotifyCallback,MessageNotifyCallback。

ConnectNotifyCallback

当应用层调用FilterConnectCommunicationPort 来与minifilter driver建立连接的时候,Filter Manager 会调用这个回调函数。

DisconnectNotifyCallback:

Pointer to a caller-supplied callback routine to be called whenever the user-mode handle count for the client port reaches zero or when the minifilter driver is about to be unloaded。

MessageNotifyCallback [in, optional]

The Filter Manager calls this routine, at IRQL = PASSIVE_LEVEL, whenever a user-mode application callsFilterSendMessage to send a message to the minifilter driver through the client port.

学习最有效,最快的方式不是看书和看文档,而是实战,来看看示例代码:

NTSTATUS
SSMFInitializeCommPort()
{
 NTSTATUS status = STATUS_SUCCESS;
 PSECURITY_DESCRIPTOR sd;
 OBJECT_ATTRIBUTES oa;
 UNICODE_STRING uniString;

 status = FltBuildDefaultSecurityDescriptor(&sd,
  FLT_PORT_ALL_ACCESS);

 if (!NT_SUCCESS(status))
 {
  return status;
 }

 RtlInitUnicodeString(&uniString, SSMF_PORT_NAME);

 InitializeObjectAttributes(&oa,
  &uniString,
  OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
  NULL,
  sd);

 status = FltCreateCommunicationPort(gFilterHandle,
  &gServerPort,
  &oa,
  NULL,
  SSMFConnect,
  SSMFDisconnect,
  SSMFMessage,
  1);

 FltFreeSecurityDescriptor(sd);

 return status;
}

这个SSMFInitializeCommPort函数就是创建了一个内核端口供应用层连接,当然还有那三个重要的函数要实现,在这里我们只是简单的输出一下log信息和返回一些简单的数据。

NTSTATUS
SSMFConnect(
_In_ PFLT_PORT ClientPort,
_In_ PVOID ServerPortCookie,
_In_reads_bytes_(SizeOfContext) PVOID ConnectionContext,
_In_ ULONG SizeOfContext,
_Flt_ConnectionCookie_Outptr_ PVOID *ConnectionCookie
)

{

 PAGED_CODE();

 UNREFERENCED_PARAMETER(ServerPortCookie);
 UNREFERENCED_PARAMETER(ConnectionContext);
 UNREFERENCED_PARAMETER(SizeOfContext);
 UNREFERENCED_PARAMETER(ConnectionCookie);
 PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("SSMF!SSMFConnect entered"));

 gClientPort = ClientPort;
 return STATUS_SUCCESS;
}

VOID
SSMFDisconnect(
_In_opt_ PVOID ConnectionCookie
)
{

 PAGED_CODE();

 UNREFERENCED_PARAMETER(ConnectionCookie);

 //
 //  Close our handle
 //
 PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("SSMF!SSMFDisconnect entered"));

 FltCloseClientPort(gFilterHandle, &gClientPort);
}

NTSTATUS
SSMFMessage(
_In_ PVOID ConnectionCookie,
_In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer,
_In_ ULONG InputBufferSize,
_Out_writes_bytes_to_opt_(OutputBufferSize, *ReturnOutputBufferLength) PVOID OutputBuffer,
_In_ ULONG OutputBufferSize,
_Out_ PULONG ReturnOutputBufferLength
)
{
 
 NTSTATUS status = STATUS_SUCCESS;

 PAGED_CODE();

 UNREFERENCED_PARAMETER(ConnectionCookie);
 UNREFERENCED_PARAMETER(InputBuffer);
 UNREFERENCED_PARAMETER(OutputBuffer);
 UNREFERENCED_PARAMETER(OutputBufferSize);
 UNREFERENCED_PARAMETER(ReturnOutputBufferLength);
 UNREFERENCED_PARAMETER(InputBufferSize);
 if (InputBuffer)
 {
  char* data = (char*)InputBuffer;
  PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("The message data is %s",data));
 }
 if (OutputBuffer != NULL && OutputBufferSize > 4)
 {
  RtlCopyMemory(OutputBuffer, "1234", 4);
  *ReturnOutputBufferLength = 4;
 }

 PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("SSMF!SSMFMessage entered"));

 return status;
}

下面我们来看看应用层怎么来与内核通讯并且传递数据:


HANDLE port = INVALID_HANDLE_VALUE;
 printf("Connecting to filter's port...\n");

 HRESULT hResult = FilterConnectCommunicationPort(SSMF_PORT_NAME,
  0,
  NULL,
  0,
  NULL,
  &port);
 if (hResult != S_OK)
 {
  return false;
 }
 printf("connected to the filter's port\n");
 //send message
 char buffer[100] = { 0 };
 strcpy_s(buffer, "abcdefg");
 char out_buf[100] = { 0 };
 DWORD ret_size = 0;
 hResult = FilterSendMessage(port, buffer, strlen(buffer), out_buf, 100, &ret_size);
 if (hResult == S_OK)
 {
  printf("The data is %s,len is %d\n", out_buf,ret_size);
 }
 CloseHandle(port);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simple-Soft

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值