protected void InitializeDriver()
        {
            FILTER_INFO filterInfo;

            driver = NtTdiApi.OpenFilterDriverW(NtTdiApi.NTTDIDR_DRIVER_NAMEW);
            if (driver == 0)
            {
                throw new Exception("Cannot open driver");
            }

            uint driverVersion = NtTdiApi.GetDriverVersion(driver);

            if (driverVersion != NtTdiApi.NTTDIDR_DRIVER_VERSION)
            {
                throw new Exception("Unsupported driver version");
            }

            buffer = Marshal.AllocHGlobal(new IntPtr(bufferSize));
            if (buffer == IntPtr.Zero)
            {
                throw new Exception(string.Format("Cannot allocate {0} bytes", bufferSize));
            }

            NtTdiApi.SetLoggingState(driver, 1);

            filterInfo = new FILTER_INFO(1,
                                         NtTdiApi.EVENT_MASK_FULL,
                                         NtTdiApi.FLT_ACTION_LOG,
                                         0,
                                         0x00000000,
                                         0x00000000,
                                         0,
                                         0xFFFF,
                                         PROTOCOL.PROTOCOL_ANY,
                                         0,
                                         0xFFF);

            NtTdiApi.RemoveAllFilters(driver);

            if (!NtTdiApi.AddStaticFilter(driver, filterInfo))
            {
                throw new Exception("Cannot set filter");
            }
        }
        /// <summary>
        /// Stops the traffic monitoring
        /// </summary>
        public void PauseListening()
        {
            listening = false;
            ThreadPool.QueueUserWorkItem((a) =>
            {
                lock (serializer)
                {
                    foreach (var packet in packetBuffer)
                    {
                        serializer.SerializePacket(packet);
                    }
                }
            });

            Marshal.FreeHGlobal(buffer);

            NtTdiApi.SetLoggingState(driver, 0);
            NtTdiApi.PurgeLog(driver);
            NtTdiApi.RemoveAllFilters(driver);

            this.DownloadSpeed = 0;
            this.UploadSpeed   = 0;
        }
        /// <summary>
        /// Starts capturing the packets
        /// </summary>
        public void StartListening()
        {
            InitializeDriver();

            double downloaded = 0;
            double uploaded   = 0;

            //get speed information every second
            Timer t = new Timer(1000);

            t.Elapsed += new ElapsedEventHandler((e, o) =>
            {
                if (downloaded != 0)
                {
                    this.DownloadSpeed = downloaded / 1000;
                    NotifyPropertyChanged("DownloadSpeed");
                    downloaded = 0;
                }

                if (uploaded != 0)
                {
                    this.UploadSpeed = uploaded / 1000;
                    NotifyPropertyChanged("UploadSpeed");
                    uploaded = 0;
                }
            });
            t.Start();

            int      i = 0, j = 0, error = 0;
            uint     bytesProcessed = 0;
            LOG_INFO logInfo;
            string   protocol;



            while (listening)
            {
                uint bytesRead = bufferSize;

                if (NtTdiApi.ReadLogEx(driver, buffer, ref bytesRead))
                {
                    i++;
                    bytesProcessed = 0;

                    for (j = 0; bytesProcessed < bytesRead; j++)
                    {
                        IntPtr currentPtr = new IntPtr(buffer.ToInt32() + bytesProcessed);
                        logInfo = (LOG_INFO)Marshal.PtrToStructure(currentPtr, typeof(LOG_INFO));

                        if (logInfo.m_LocalAddress.m_Ip != 0 && logInfo.m_RemoteAddress.m_Ip != 0)
                        {
                            Packet p = new Packet(logInfo);
                            OnPacketReceived(p);

                            packetBuffer.Add(p);
                            if (packetBuffer.Count == PACKET_BUFFER_SIZE)
                            {
                                var packetsToSave = new Packet[PACKET_BUFFER_SIZE];
                                packetBuffer.CopyTo(packetsToSave);
                                packetBuffer.Clear();

                                ThreadPool.QueueUserWorkItem((a) =>
                                {
                                    lock (serializer)
                                    {
                                        foreach (var packet in packetsToSave)
                                        {
                                            serializer.SerializePacket(packet);
                                        }
                                    }
                                });
                            }

                            totalPackets++;
                            NotifyPropertyChanged("TotalPackets");

                            if (p.PacketDirection == PacketDirection.Downloading)
                            {
                                totalDownloaded += p.Size;
                                downloaded      += (ulong)p.Size;
                                NotifyPropertyChanged("TotalDownloaded");
                            }
                            else if (p.PacketDirection ==
                                     PacketDirection.Uploading)
                            {
                                totalUploaded += p.Size;
                                uploaded      += (ulong)p.Size;
                                NotifyPropertyChanged("TotalUploaded");
                            }
                        }

                        bytesProcessed += Convert.ToUInt32(Marshal.SizeOf(typeof(LOG_INFO))) + logInfo.m_DataLength;
                    }
                }
                else
                {
                    error = Marshal.GetLastWin32Error();

                    if (error == 122 /*ERROR_INSUFFICIENT_BUFFER*/)
                    {
                        bufferSize += 0x1000;
                        buffer      = Marshal.ReAllocHGlobal(buffer, new IntPtr(bufferSize));

                        if (buffer == IntPtr.Zero)
                        {
                            throw new Exception(string.Format("Cannot allocate {0} bytes! abort", bufferSize));
                        }
                    }

                    if (NtTdiApi.GetWaitEvent(driver))
                    {
                        NtTdiApi.WaitForData(driver, 0xFFFFFFFF); //INFINITE
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
        }