日期:2014-05-18  浏览次数:20782 次

NDIS网络数据监控程序NDISMonitor(3)-----NdisMonitro应用程序(C#)

转载请标明是引用于 http://blog.csdn.net/chenyujing1234 

欢迎大家拍砖!

 

 

1、主窗口Load函数ctrlForm_Load

(1)先调用GetExtensions来获得运行目录下bin目录中的所有文件,通过载入为Assembly,然后获取属性及名字, 并把它们转化为自定义的ExtensionInfo类型的数组存放。

(2)创建ComboxBox,并根据第(1)步得到的bin文件夹下文件初始化Combox里的内容。

(3)更新状态栏为

2、选择下拉框后的处理过程

(1)根据从下拉框选择的项,创建控件并加到容器(ctrlContainter,即主界面中显示收到包的控件)中;

if ( curr._instance == null )
			{
				// create the control and add it to the container.

				curr._instance = (INmExtension) Activator.CreateInstance( curr._type );

				System.Windows.Forms.UserControl	c =
					(System.Windows.Forms.UserControl) curr._instance;

				ctrlContainer.Controls.Add( c );

				// set the dock properties of the control.

				c.Anchor =
					AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

				c.Left = 0;
				c.Top = 0;
				c.Width = ctrlContainer.Width;
				c.Height = ctrlContainer.Height;

				ctrlContainer.Visible = true;
			}


 

(2)载入NDIO Monitor的内核Hook驱动。
for( int z=0; z<3; z ++ )
				{
					_protocolList = NdisHookStubs.NT_PROTOCOL_LIST.Start( (uint) PacketBacklog,
						UseLt == false ? 0 : LtLoopbackIp,
						UseLt == false ? 0 : LtNatIp );

					if ( _protocolList != null )
						break;
					else
						Thread.Sleep( 1000 );
				}


 

 根据从驱动中获得的协议列表提取出来的协议和适配器来初始化NT_PROTOCOL_LIST类。

(3)设置当前ExtensionInfo的_instance,用来添加菜单。
curr._instance.Showing ( new LogFn( ExtensionLogFn ), _protocolList, popupMenu );
			( (System.Windows.Forms.UserControl) curr._instance ).Visible = true;

			if ( popupMenu.MenuItems.Count != 0 )
				ctrlMenu.MenuItems.Add( popupMenuIndex, popupMenu );

			ctrlMenu.MenuItems[ ctrlMenu.MenuItems.Count - 1 ].Index =
				ctrlMenu.MenuItems.Count - 1; // help popup menu.

(4)主窗口启动监听线程。这一个线程相当重要。
Thread		listenThread = new Thread( new ThreadStart( listenThreadProc ) );
					listenThread.Start ();

(4、1)它做的事情是调用NdisHook的API接口等待数据包的到来,如果数据包来了,就返回一个数据包

NdisHookStubs.NEXT_PACKET		np = NdisHookStubs.NEXT_PACKET.WaitFor ();


(4、2)判断bArePacketsRemaining将所有的数据包接收完成存放在ArrayList  al 中;

al.Add( np );

(4、3)如果数据接收完成,那么根据包的序列号(_dwPacketSerial)排序后把每个包发到主窗口显示出来。

for ( int i=0; i<al.Count; i ++ )
							{
								NdisHookStubs.NEXT_PACKET		npI = (NdisHookStubs.NEXT_PACKET) al[ i ];
								int								k = i;
								for ( int j=i+1; j<al.Count; j ++ )
									if ( ((NdisHookStubs.NEXT_PACKET)al[ j ])._dwPacketSerial < npI._dwPacketSerial )
										k = j;
								if ( k != i )
								{
									al[ i ] = al[ k ];
									al[ k ] = npI;
								}
							}

							// post the packets in the correct thread context.
							foreach( NdisHookStubs.NEXT_PACKET thisNp in al )
							{
								IntPtr			ptr = (IntPtr) thisNp;
								PostMessage( THIS.Handle, _nextPacketArrived, new IntPtr( 0 ), ptr ); // old tricks die hard... !
							}


捕捉到的数据显示为:


(5)显示适配器对话框(OpenAdapters窗口)。

if ( showAdapters && _protocolList != null )
				miAdapters_Click( null, null );


 

3、显示适配器对话框的函数miAdapters_Click

(1)SetProtList。

把之前获得的<