internal unsafe void ClearCache()
        {
            // Tell the driver to search for any new SSIDs
            // and return them on the next OID_802_11_BSSID_LIST
            // message.
            uint dwBytesReturned       = 0;
            NDISUIO_QUERY_OID queryOID = new NDISUIO_QUERY_OID(0);
            IntPtr            ndisAccess;
            bool retval;

            // Attach to NDISUIO.
            ndisAccess = FileEx.CreateFile(
                NDISUIOPInvokes.NDISUIO_DEVICE_NAME,
                FileAccess.All,
                FileShare.None,
                FileCreateDisposition.OpenExisting,
                NDISUIOPInvokes.FILE_ATTRIBUTE_NORMAL | NDISUIOPInvokes.FILE_FLAG_OVERLAPPED);
            if ((int)ndisAccess == FileEx.InvalidHandle)
            {
                // The operation failed.  Leave us empty.
                return;
            }

            // Send message to driver.
            byte[] namestr = System.Text.Encoding.Unicode.GetBytes(adapter.Name + '\0');
            fixed(byte *name = &namestr[0])
            {
                // Get Signal strength
                queryOID.ptcDeviceName = name;
                queryOID.Oid           = NDISUIOPInvokes.OID_802_11_BSSID_LIST_SCAN;       // 0x0D01011A

                retval = NDISUIOPInvokes.DeviceIoControl(ndisAccess,
                                                         NDISUIOPInvokes.IOCTL_NDISUIO_SET_OID_VALUE, // 0x120814
                                                         queryOID,
                                                         queryOID.Size,
                                                         queryOID,
                                                         queryOID.Size,
                                                         ref dwBytesReturned,
                                                         IntPtr.Zero);
            }

            if (retval)
            {
                // The call went fine.  There is no return
                // data.
            }
            else
            {
                // There was an error.
                int err = MarshalEx.GetLastWin32Error();

                // ToDo: Additional error processing.
            }

            queryOID = null;

            FileEx.CloseHandle(ndisAccess);
        }
        internal unsafe void RefreshList(Boolean clearCache)
        {
            // If we are to clear the driver's cache of SSID
            // values, call the appropriate method.
            //Console.WriteLine("Entering RefreshList");
            if (clearCache)
            {
                this.ClearCache();

                // This seems to be needed to avoid having
                // a list of zero elements returned.
                System.Threading.Thread.Sleep(1000);
            }

            this.List.Clear();

            // Retrieve a list of NDIS_802_11_BSSID_LIST
            // structures from the driver.  We'll parse that
            // list and populate ourselves based on the data
            // that we find there.
            uint dwBytesReturned       = 0;
            NDISUIO_QUERY_OID queryOID = new NDISUIO_QUERY_OID(6000 /* TESTING JFK was 2000 */);
            IntPtr            ndisAccess;
            bool retval;

            // Attach to NDISUIO.
            ndisAccess = FileEx.CreateFile(
                NDISUIOPInvokes.NDISUIO_DEVICE_NAME,
                FileAccess.All,
                FileShare.None,
                FileCreateDisposition.OpenExisting,
                NDISUIOPInvokes.FILE_ATTRIBUTE_NORMAL | NDISUIOPInvokes.FILE_FLAG_OVERLAPPED);
            if ((int)ndisAccess == FileEx.InvalidHandle)
            {
                Console.WriteLine("Attach to NDISUIO Failed");
                // The operation failed.  Leave us empty.
                return;
            }

            // Get Signal strength
            byte[] namestr = System.Text.Encoding.Unicode.GetBytes(adapter.Name + '\0');
            fixed(byte *name = &namestr[0])
            {
                // Get Signal strength
                queryOID.ptcDeviceName = name;
                queryOID.Oid           = NDISUIOPInvokes.OID_802_11_BSSID_LIST;       // 0x0D010217

                retval = NDISUIOPInvokes.DeviceIoControl(ndisAccess,
                                                         NDISUIOPInvokes.IOCTL_NDISUIO_QUERY_OID_VALUE, // 0x00120804
                                                         queryOID,
                                                         queryOID.Size,
                                                         queryOID,
                                                         queryOID.Size,
                                                         ref dwBytesReturned,
                                                         IntPtr.Zero);
            }

            if (retval)
            {
                // Now we need to parse the incoming data into
                // suitable representations of the SSIDs.

                // Figure out how many SSIDs there are.
                NDIS_802_11_BSSID_LIST rawlist = new NDIS_802_11_BSSID_LIST(queryOID.Data);

                for (int i = 0; i < rawlist.NumberOfItems; i++)
                {
                    // Get the next raw item from the list.
                    NDIS_WLAN_BSSID bssid = rawlist.Item(i);

                    // Using the raw item, create a cooked
                    // SSID item.
                    AccessPoint ssid = new AccessPoint(bssid);

                    // Add the new item to this.
                    this.List.Add(ssid);
                }
            }
            else
            {
                // We might just need more room.
                // For now, we just leave the list empty.
                // ToDo: Additional error processing.
                Console.WriteLine("ERROR Buffer Too Small");                //You'll notice here there should be some sort of error contol but there isn't.
                //We simply don't have enough room.
            }
        }
        internal void StatusThread()
        {
            // Ask NDISUIO to send us notification messages for our
            // adapter.
            IntPtr ndisAccess = FileEx.CreateFile(
                NDISUIOPInvokes.NDISUIO_DEVICE_NAME,
                FileAccess.All,
                FileShare.None,
                FileCreateDisposition.OpenExisting,
                NDISUIOPInvokes.FILE_ATTRIBUTE_NORMAL | NDISUIOPInvokes.FILE_FLAG_OVERLAPPED);

            if ((int)ndisAccess == FileEx.InvalidHandle)
            {
                return;
            }

            NDISUIO_REQUEST_NOTIFICATION ndisRequestNotification =
                new NDISUIO_REQUEST_NOTIFICATION();

            ndisRequestNotification.hMsgQueue           = mq.Handle;
            ndisRequestNotification.dwNotificationTypes =
                NDISUIOPInvokes.NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION |
                NDISUIOPInvokes.NDISUIO_NOTIFICATION_MEDIA_CONNECT |
                NDISUIOPInvokes.NDISUIO_NOTIFICATION_MEDIA_DISCONNECT |
                NDISUIOPInvokes.NDISUIO_NOTIFICATION_BIND |
                NDISUIOPInvokes.NDISUIO_NOTIFICATION_UNBIND;

            UInt32 xcount = 0;

            if (!NDISUIOPInvokes.DeviceIoControl(ndisAccess,
                                                 NDISUIOPInvokes.IOCTL_NDISUIO_REQUEST_NOTIFICATION,
                                                 ndisRequestNotification.getBytes(),
                                                 NDISUIO_REQUEST_NOTIFICATION.Size,
                                                 null, 0, ref xcount, IntPtr.Zero))
            {
                System.Diagnostics.Debug.WriteLine(this, "Error in DeviceIoControl to request notifications!");
            }

            // Each notification will be of this type.
            NDISUIO_DEVICE_NOTIFICATION ndisDeviceNotification =
                new NDISUIO_DEVICE_NOTIFICATION();

            // Wait for the queue to be signaled.  When it is, decode
            // the message and call any listeners for it.  If the
            // queue closes suddenly, that's our cue to exit, shutting
            // down NDISUIO notifications before we leave.
            PointToPointMsgQueue q = mq;

            while (mq != null)                  // Check the global object here.
            {
                // Wait.  On return, true indicates that the queue is
                // signaled; false is a chance to check whether we should
                // exit.
                if (q.Wait(-1))
                {
                    // Read the event data.
                    int bytes = 0;
                    PointToPointMsgQueueFlags readFlags = 0;
                    if (q.ReadMsgQueue(ndisDeviceNotification.getBytes(),
                                       NDISUIO_DEVICE_NOTIFICATION.Size,
                                       ref bytes, -1, ref readFlags))
                    {
                        // Handle the event.
                        OnAdapterNotification(new AdapterNotificationArgs(
                                                  ndisDeviceNotification.ptcDeviceName,
                                                  (NdisNotificationType)ndisDeviceNotification.dwNotificationType));
                    }
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine(this, "mq is null in monitoring thread.  Exiting...");
                }
            }

            System.Diagnostics.Debug.WriteLine(this, "exiting AdapterStatusMonitor thread.");

            if (!NDISUIOPInvokes.DeviceIoControl(ndisAccess,
                                                 NDISUIOPInvokes.IOCTL_NDISUIO_CANCEL_NOTIFICATION,
                                                 null, 0,
                                                 null, 0, ref xcount, IntPtr.Zero))
            {
                System.Diagnostics.Debug.WriteLine(this, "Error in DeviceIoControl to stop notifications!");
                // ????
            }

            // Don't forget to close our handle to NDISUIO.
            FileEx.CloseHandle(ndisAccess);
        }