您的位置:首页 > 其它

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

2014-09-21 10:33 639 查看
应用层与内核通讯是通过通讯端口来进行的,下面的这个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);


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐