Laden...

OpenNetCF WZC gibt immer Output/Fehler 87 zurück

Erstellt von FrankenDerStein vor 8 Jahren Letzter Beitrag vor 7 Jahren 2.707 Views
FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren
OpenNetCF WZC gibt immer Output/Fehler 87 zurück

Hallo Kollegen, da ich auf die Idee kam das OpenNetCF Fehler bei der WZC Implementierung haben könnte, habe ich begonnen mich selbst mit WZC zu beschäftigen.
Leider hänge ich gleich zu beginn fest, denn WZCQueryInterface gibt mir immer 87 als Resultat aus, und ich verstehe nicht warum zum Henker er das tut.
Ich hoffe jemand kann mir da weiterhelfen.

Schöne grüße FrankenDerStein.


        static void Main(string[] args)
        {

            INTF_ENTRY a = new INTF_ENTRY();
            uint aut=0;
            uint r = WZCQueryInterface(null, 0xffffffff, ref a, out aut);//<----- r = 87
            
        }

        

        [DllImport("Wzcsapi.dll")]
        static extern int WZCEapolGetInterfaceParams(string pSrvAddr, byte[] pwszGuid, int dwSizeOfSSID, byte[] pbSSID, ref _EAPOL_INTF_PARAMS pIntfParams);

        [DllImport("Wzcsapi.dll",SetLastError=true)]
        static extern uint WZCEnumInterfaces(string pSrvAddr, ref INTFS_KEY_TABLE pIntfs);

        [DllImport("Wzcsapi.dll")]
        static extern uint WZCQueryInterface(string pSrvAddr, uint dwInFlags, ref INTF_ENTRY pIntf, out uint pdwOutFlags);

        [DllImport("Wzcsapi.dll")]
        static extern int WZCRefreshInterface(string pSrvAddr, int dwInFlags, INTF_ENTRY pIntf, out int pdwOutFlags);

        struct _EAPOL_INTF_PARAMS
        {
            public int dwVersion;
            public int dwReserved2;
            public int dwEapFlags;
            public int dwEapType;
            public int dwSizeOfSSID;
            public byte bssid;
        }

        struct INTF_ENTRY
        {
           public IntPtr wszGuid;
           public IntPtr wszDescr;
           public int dwContext;
           public ulong ulMediaState;
           public ulong ulMediaType;
           public ulong ulPhysicalMediaType;
           public int nInfraMode;
           public int nAuthMode;
           public int nWepStatus;
           public uint dwCtlFlags;
           public uint dwDynFlags;
           public uint dwCapabilities;
           public RAW_DATA rdNicCapabilities;
           public RAW_DATA rdSSID;
           public RAW_DATA rdBSSID;
           public RAW_DATA rdBSSIDList;
           public RAW_DATA rdStSSIDList;
           public RAW_DATA rdCtrlData;
        }

        struct RAW_DATA
        {
            public uint dwDataLen;
            public uint pData;
        }

        struct INTF_KEY_ENTRY
        {
            public IntPtr wszGuid;
        }

       unsafe struct INTFS_KEY_TABLE
        {
            public uint dwNumIntfs;
            public IntPtr pIntfs;
        }

T
314 Beiträge seit 2013
vor 8 Jahren

Gibts dort nun nen Fehler oder nicht? Schau doch mal bei OpenNetCF wie es dort gemacht wird.

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Hallo t0ms3n und danke für deine Reaktion.

Ja sagen die Hersteller des WLAN Geräts, ich sehe auch die fehl verhalten, und hoffe das es ist OpenNetCF.

OpenNetCF Code:


            INTF_ENTRY entry = new INTF_ENTRY();
            entry.Guid = adapterName; //Guid gibt es in meiner Struktur nicht und ist nicht von Microsoft angegeben
            INTF_FLAGS flags = 0;

            int result = WZCQueryInterface(null, INTF_FLAGS.INTF_ALL, ref entry, out flags);//enum : INTF_FLAGS.INTF_ALL = 0xffffffff

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Ich habe das Problem gelöst, was für openNetCF Guid ist, ist für mich wszGuid.
Es ist bisschen verwirten :-\

Nun habe ich ein neues Problem, rdBSSIDList gibt mir nichts.

Ich hoffe jemand kennt sich aus. 🙁


static void Main(string[] args)
        {
            INTFS_KEY_TABLE erg = new INTFS_KEY_TABLE();
            erg.dwNumIntfs = 0;
            erg.pIntfs = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * (int)erg.dwNumIntfs);
            uint r = WZCEnumInterfaces(null, ref erg);
            INTF_KEY_ENTRY i = (INTF_KEY_ENTRY)Marshal.PtrToStructure(erg.pIntfs, typeof(INTF_KEY_ENTRY));
            string name = Marshal.PtrToStringUni(i.wszGuid);

            INTF_ENTRY a = new INTF_ENTRY();
            a.wszGuid = Marshal.StringToBSTR(name);
            uint aut = 0;
            r = WZCQueryInterface(null, 0xffffffff, ref a, out aut);
            if (a.rdBSSIDList.pData!=0)
            {
                int L = 4;
                byte[] bA = new byte[L];
                Marshal.Copy(a.rdBSSIDList.pData, bA, 0, L);
                //NDIS_802_11_BSSID_LIST O = new NDIS_802_11_BSSID_LIST(bA, true); 
            }
            if (r == 0)
            {
                switch ((MediaState)a.ulMediaState)
                {
                    case MediaState.MEDIA_STATE_CONNECTED:
                        
                        break;
                    case MediaState.MEDIA_STATE_DISCONNECTED:
                        break;
                    case MediaState.MEDIA_STATE_UNKNOWN:
                        break;
                    default:
                        break;
                }
            }
            else
            {
                Debug.WriteLine(Marshal.GetExceptionForHR(r).Message);
            }

        }

16.834 Beiträge seit 2008
vor 8 Jahren

Gewöhn Dir an Deinen sinnvoll Code zu dokumentieren, also was er tut. Bei sowas speziellem Zeile für Zeile.
So können Entwickler eher helfen und verstehen, auch wenn sie die Schnittstelle nicht auswendig kennen.

Es wäre Zufall jemanden zu finden, der anhand dieser Beschreibung genau weiß, was Dein rdBSSIDList sein soll.
99,9% müssten jetzt in die MSDN gehen (davor selbst googlen, weil Du nichts verlinkst) um zu schauen, was dazu in der Beschreibung von INTF_ENTRY steht.

Anhand der Beschreibung, dass RAW_DATA.pData ein Pointer auf ein Byte-Array ist, hätte ich hier wahrscheinlich eher IntPtr daraus verstanden, und kein uint.
Woher hast Du die structs? Einfach irgendwo raus kopiert oder anhand der Beschreibung selbst ermittelt?

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

hallo Abt, danke für deine Reaktion.

Ich beschreibe mal genauer was dort passiert.

Dieser Teil ermittelt den namen der WLAN Hardware


            INTFS_KEY_TABLE erg = new INTFS_KEY_TABLE();
            erg.dwNumIntfs = 0;

            erg.pIntfs = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * (int)erg.dwNumIntfs);// hier wird Speicherplatz reserviert(ob das notwendig ist weiß ich nicht, ich mach es aus Empfehlung)

            uint r = WZCEnumInterfaces(null, ref erg);// ihr werden die Informationen geholt und in die INTF_KEY_ENTRY Struktur gepackt.

            INTF_KEY_ENTRY i = (INTF_KEY_ENTRY)Marshal.PtrToStructure(erg.pIntfs, typeof(INTF_KEY_ENTRY));// Ihr werden die Informationen die über einen zeiger kommen, in die eigentliche Unterstruktur gepackt.

            string name = Marshal.PtrToStringUni(i.wszGuid);// Da der Name auch über einen Zeiger gegeben werden müssen die auch erst abgerufen werden.

Der Zweite Teil soll mir den Status über das WLAN gerät verschaffen, also ob er verbunden ist und wie gut die Verbindung ist.


            INTF_ENTRY a = new INTF_ENTRY();
            a.wszGuid = Marshal.StringToBSTR(name);//Hier wird der Name der Hardware übergeben in vorm eines Zeigers.
            uint aut = 0;
            r = WZCQueryInterface(null, 0xffffffff, ref a, out aut);//0xffffffff soll ihm vermitteln das er alle Felder der Struktur  füllen soll, die null sagt ihm das es auf dem Lokalen  Rechner läuft.
            if (a.rdBSSIDList.pData!=IntPtr.Zero)// um Fehler zu vermeiden wird geprüft ob der Zeiger der die Informationen hat, das leider nicht der Fall ist warum auch immer.
            {
                int L = 4;
                byte[] bA = new byte[L];
                Marshal.Copy(a.rdBSSIDList.pData, bA, 0, L);//Die Informationen werden hier aus eine byte Array ermittelt, die von einen Zeiger kommen.
                NDIS_802_11_BSSID_LIST O = new NDIS_802_11_BSSID_LIST(bA, true); // diese klasse ist aus openNetCF, die ist für das auswerten der byte array zu ständig, ich bin noch dabei raus zu finden was sie genau macht, den Microsoft war nicht sehr verständlich über das was dort rauskommt.
            }
            if (r == 0)
            {
                switch ((MediaState)a.ulMediaState)// werden die Informationen ausgewertet ob das gerät verbunden ist oder nicht.
                {
                    case MediaState.MEDIA_STATE_CONNECTED:
                        
                        break;
                    case MediaState.MEDIA_STATE_DISCONNECTED:
                        break;
                    case MediaState.MEDIA_STATE_UNKNOWN:
                        break;
                    default:
                        break;
                }
            }
            else
            {
                Debug.WriteLine(Marshal.GetExceptionForHR((int)r).Message);// Falls "r" nicht 0 sein sollte,bekomme ich hier mehr Infos raus
            }

Die Informationen zu der Schnittstelle habe ich von dieser Microsoft Webseite:Microsoft msdn
Außer der Parameter 0xff.. den habe ich aus OpenNetCF entnommen.

Nachtrag:
Das mit den Strukturen, die habe ich selbst interpretiert, durch ausprobieren, uint und intPtr gingen gleicher massen, ursprünglich war es intptr habe mich da von anderen mitreisen lassen (Google) und noch mal geändert.

Ich weiß das man sie Pointer nennt, ich bin da bisschen sehr deutsch und nenne sie Zeiger.

W
872 Beiträge seit 2005
vor 8 Jahren

Wenn Du C Strukturen nach C# umsetzt, dann würde ich mich immer an diese Tabelle ("Marshaling Arguments") orientieren.
Ausserdem würde ich nie herumkopieren mit Marshal.Copy, sondern immer einen quasi Cast mit Marshal.PtrToStructure machen. Der Code sieht dann im Regelfall so aus:


public static T FromBytes(byte[] bytes)
        {
            var handle = GCHandle.Alloc(bytes,
                                        GCHandleType.Pinned);
            var result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
                                                        typeof (T));
            handle.Free();
            return result;
        }

Und RawData wird immer so aussehen:


  struct RAW_DATA
        {
            public uint dwDataLen;
            public IntPtrpData;
        }

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Hallo weismat, danke für deine Anteilnahme.
ich werde dein verfahren so mal umsetzen.

Nachtrag:
Das Problem ist dar durch nicht gelöst, IntPtr rdBSSIDList.pData ist leider immer noch null.

W
872 Beiträge seit 2005
vor 8 Jahren

Einen Tip habe ich noch.
Schreibe Dir kleine C und C# Programme, um mittels sizeof die Länge der C und C# Strukturen zu bekommen. sizeof gibt es auch in C#.
Das gibt Dir eine erste Indikation, ob Du alles richtig gemacht haben könntest.

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Danke weismat für den Tipp.

Ich muss so langsam feststellen das hier keinen gibt der sich mit dieser Schnittstelle auskennt.

Ich habe meine arbeit und die von OpenNetCF verglichen aber leider keine Ungereimtheiten eindecken können, ebenso habe ich es mit 2 Geräten verglichen und bei beiden kommt das selbe Resultat.
Ich finde den Fehler einfach überhaupt nicht.

Leider fehlt mir die Möglichkeit OpenNetCF zu Debuggen, sonst könnte ich werte vergleichen.
🙁

T
314 Beiträge seit 2013
vor 8 Jahren

Leider fehlt mir die Möglichkeit OpenNetCF zu Debuggen, sonst könnte ich werte vergleichen.
😦

Warum nicht? Ist doch OpenSource.

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Gute Frage, die Antwort lautet: Wenn ich es versuche haut er über 111 Fehler raus. 😕

Keine Ahnung warum.

16.834 Beiträge seit 2008
vor 8 Jahren

Visual Studio ist ja so intelligent, dass er Dir nicht nur die Anzahl der Fehler sagt, sondern auch wo genau das Problem ist.
Wieso versuchst Du nicht die Fehler zu lösen, dass Du endlich strukturiert an die Sache gehen kannst?
Ich mein, Du kopierst irgendwo Code und structs her ohne sie zu verstehen und wunderst Dich dann, dass Du bei Win32 Calls auf Fehler stößt.
Wie willst Du denn voran kommen und so Low-Level arbeiten, wenn Du die Grundlagen dessen gar nicht beherrschst?
Es nur ein gut gemeinter Hinweis.

Vermutlich sind es sowieso Folgefehler.
Löst Du einen sind zig andere Fehler weg.

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

hallo Abt, ich habe das was du mir geraten hast getan.

Ich habe herausgefunden, das es mit den Datentypen meiner Struktur zutun hat, warum mir keine gescheiten werte zurückkommen.

Ich habe mich an Anfang, wen es um Datentypen ging, recht streng an die angaben von Microsoft gehalten, aber es scheint mir das einige Datentypen falsch sind.

Ein Beispiel ist ULONG ulMediaState(Microsoft Angabe) ,in c# existirt uLong ebenso, opennetcf benutz (was ich falsch fand, und doch funktioniert) uint, kann mir jemand sagen warum das so ist ?

3.003 Beiträge seit 2006
vor 8 Jahren

Weil das zwei Datentypen sind, die den gleichen Namen haben, sonst aber nicht gleich sind.

ULONG ist -> Windows Data Types 32 bit unsigned int. Der dazu passende Datentyp in C# iost UInt32 (oder kurz: uint).

ulong (C#) ist 64Bit unsigned int, der passende Windows-Datentyp heisst ULONGLONG (kein Scherz.)

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

16.834 Beiträge seit 2008
vor 8 Jahren

(Ich fände VERYLONG wäre ein besserer Name gewesen. =)){gray}

Das hab ich gemeint mit den Grundlagen.
Wenn Du mit der Win32 API arbeiten willst, dann musst Du genau wissen, wie das funktioniert - und dazu gehören auch die Data Types.

Wenn Du das nicht beherrschst, dann bekommst Du sehr Seiteneffekte, die Du zunächst gar nicht nachvollziehen kannst oder Du bekommst Fehlermeldungen, die wirr sind und evtl. was anderes ausdrücken.
Mit der Win32 API zu arbeiten ist viel aufwändiger als mit C# - und Du hast nicht unbedingt das perfekte Einstiegsthema, da nicht besonders gut dokumentiert und Du wirst dazu auch sehr wenig Material im Web finden.

Du solltest hier wirklich - echt als netter Hinweis gemeint - nicht nur Code kopieren oder abschauen, sondern wirklich verstehen, was Du da machst.
Ich hab das selbst leider so lernen müssen 😉

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 8 Jahren

Danke für die Hilfe, ich habe aber noch eine frage.

Wie lauft es eigentlich mit der speicher Freigabe, wie muss ich das machen und auf was muss ich da achten, schließlich gibt es kein Dispose() Funktion.

W
872 Beiträge seit 2005
vor 8 Jahren

Zeig uns, was Du konkret machst. Wenn Du nur Marshal.PtrToStructure machst, dann ist nix nötig.
Der Garbage Collector macht seine Arbeit für alles, was im Managed Bereich ist, automatisch.
Da der Garbage Collector nicht weiss, was im Unmanaged Bereich passiert, muss man bei Function Pointer/Delegates künstliche Referenzen halten, damit der Garbage Collector die nicht wegräumt, obwohl man sie noch braucht.

FrankenDerStein Themenstarter:in
72 Beiträge seit 2015
vor 7 Jahren

Hallo weismat, danke für die Hilfe ,im Anhang ist eine ZIP mit 2 cs-Dateien, die als meine erster Prototyp in Sachen WLAN API sind.

Manche Sachen musste ich von Opennetcf übernehmen weil ich nichts informatives, zu den Sachen gefunden habe.

Ich hoffe dir fehlt dazu was ein.

W
872 Beiträge seit 2005
vor 7 Jahren

Du musst natürlich das Free aufrufen - der klassische C# Weg ist, daß Du für die Strukturen IDisposable definierst und dann die Strukturen entsprechend freigibst, wenn das aufgerufen wird.
Structs sind Wertetypen - bei Dir benutzt Du die Properties wieder - das schafft Komplexität.

Wenn Du das machst, dann kannst Du schönen Code schreiben:


using (UnmanagedType t =new UnmanagedType()) 
{
    byte charset = t.GdiCharSet;
}

In dem Fall wird das Dispose dann mit dem Ende des Blocks automatisch aufgerufen und der Compiler hilft Dir, nicht nach dem Dispose etwas mit der Variable zu machen.