-
-
[原创]提前拜年:浅谈内核LPC开发多向通讯+简单框架结构+私人送个简单的通讯协议
-
发表于:
2013-2-8 13:03
12763
-
[原创]提前拜年:浅谈内核LPC开发多向通讯+简单框架结构+私人送个简单的通讯协议
kd> dt e1320030 _LPCP_PORT_OBJECT
nt!_LPCP_PORT_OBJECT
+0x000 ConnectionPort : 0xe12ca458 _LPCP_PORT_OBJECT ------> 由服务器调用NtCreatePort所创建的连接端口
+0x004 ConnectedPort : 0xe10f3388 _LPCP_PORT_OBJECT ------> 已经建立连接后,对方通讯端口的对象
+0x008 MsgQueue : _LPCP_PORT_QUEUE ------> 消息队列
+0x018 Creator : _CLIENT_ID
+0x020 ClientSectionBase : (null)
+0x024 ServerSectionBase : (null)
+0x028 PortContext : (null)
+0x02c ClientThread : (null)
+0x030 SecurityQos : _SECURITY_QUALITY_OF_SERVICE
+0x03c StaticSecurity : _SECURITY_CLIENT_CONTEXT
+0x078 LpcReplyChainHead : _LIST_ENTRY [ 0xe13200a8 - 0xe13200a8 ]
+0x080 LpcDataInfoChainHead : _LIST_ENTRY [ 0xe13200b0 - 0xe13200b0 ]
+0x088 ServerProcess : (null)
+0x088 MappingProcess : (null)
+0x08c MaxMessageLength : 0x148
+0x08e MaxConnectionInfoLength : 0
+0x090 Flags : 0x80000004
+0x094 WaitEvent : _KEVENT
//
// 对于创建得到的连接端口和客户端连接后得到的数据通讯端口,服务器调用
// NtReplyWaitReceivePortEx始终在监听NtCreatePort得到的连接端口
//
if ((PortObject->Flags & PORT_TYPE) != CLIENT_COMMUNICATION_PORT) {
if (PortObject->ConnectionPort == PortObject) {
ConnectionPort = ReceivePort = PortObject;
ObReferenceObject (ConnectionPort);
} else {
LpcpAcquireLpcpLockByThread(CurrentThread);
ConnectionPort = ReceivePort = PortObject->ConnectionPort;
if (ConnectionPort == NULL) {
LpcpReleaseLpcpLock();
ObDereferenceObject( PortObject );
return STATUS_PORT_DISCONNECTED;
}
ObReferenceObject( ConnectionPort );
LpcpReleaseLpcpLock();
}
//
// 对于客户端来说,调用NtReplyWaitReceivePortEx监听的总是自己连接上服务器
// 得到的通讯端口。所以在设计中,监听自身通讯端口,可以将发起权交给服务器
//
} else {
ReceivePort = PortObject;
}
// ...............
Status = KeWaitForSingleObject( ReceivePort->MsgQueue.Semaphore,
WrLpcReceive,
WaitMode,
FALSE,
Timeout );
//
// 对于客户端来说,调用NtRequestWaitReplyPort总是把请求消息插入到
// NtCreatePort所创建的连接端口对象的消息队列中。。。
//
LpcpAcquireLpcpLockByThread(CurrentThread);
Msg->PortContext = NULL;
if ((PortObject->Flags & PORT_TYPE) != SERVER_CONNECTION_PORT) {
QueuePort = PortObject->ConnectedPort;
if (QueuePort == NULL) {
LpcpFreeToPortZone( Msg, LPCP_MUTEX_OWNED | LPCP_MUTEX_RELEASE_ON_RETURN );
ObDereferenceObject( PortObject );
return STATUS_PORT_DISCONNECTED;
}
RundownPort = QueuePort;
if ((PortObject->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {
Msg->PortContext = QueuePort->PortContext;
ConnectionPort = QueuePort = PortObject->ConnectionPort;
if (ConnectionPort == NULL) {
LpcpFreeToPortZone( Msg, LPCP_MUTEX_OWNED | LPCP_MUTEX_RELEASE_ON_RETURN );
ObDereferenceObject( PortObject );
return STATUS_PORT_DISCONNECTED;
}
} else if ((PortObject->Flags & PORT_TYPE) != SERVER_COMMUNICATION_PORT) {
ConnectionPort = QueuePort = PortObject->ConnectionPort;
if (ConnectionPort == NULL) {
LpcpFreeToPortZone( Msg, LPCP_MUTEX_OWNED | LPCP_MUTEX_RELEASE_ON_RETURN );
ObDereferenceObject( PortObject );
return STATUS_PORT_DISCONNECTED;
}
}
if (ConnectionPort) {
ObReferenceObject( ConnectionPort );
}
//
// 对于服务器来说,调用NtRequestWaitReplyPort就是将消息插入调用者指定的端口对象的
// 消息队列。所以在设计中可以利用这个特点,自己给自己发请求来退出监控线程的。
//
} else {
QueuePort = PortObject;
RundownPort = PortObject;
}
// ............
InsertTailList( &QueuePort->MsgQueue.ReceiveHead, &Msg->Entry );
InsertTailList( &RundownPort->LpcReplyChainHead, &CurrentThread->LpcReplyChain );
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!