[c++] Loop through struct

Pagina: 1
Acties:

  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
Hallo

Ik ben bezig met het opvraggen van signaalsterktes met behulp van ndis5.1

Dat werkte prima totdat ik het met een andere netwerkkaart ging proberen. Nu heb ik eindelijk uitgevonden dat de vraag die ik met DeviceIoControl aan de driver stel niet altijd het zelfde resultaat opleverd

de ene keer levert het een NDIS_802_11_BSSID_LIST sructuur op en de andere keer een NDIS_802_11_BSSID_LIST_EX structuur

de structuur heeft dit formaat.

C++:
1
2
3
4
5
typedef_struct _NDIS_802_11_BSSID_LIST
{
 ULONG  NumberOfItems;
 NDIS_WLAN_BSSID  Bssid[1];
} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;


het verschil komt doordat de ene keer de lijst gevuld is met NDIS_WLAN_BSSID structuren en de andere keer met NDIS_WLAN_BSSID_EX structuren

NDIS_WLAN_BSSID
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct _NDIS_WLAN_BSSID
{
 ULONG  Length;
 NDIS_802_11_MAC_ADDRESS  MacAddress;
 Uchar  Reserved[2];
 NDIS_802_11_SSID  Ssid;
 ULONG  Privacy;
 NDIS_802_11_RSSI  Rssi;
 NDIS_802_11_NETWORK_TYPE  NetworkTypeInUse;
 NDIS_802_11_CONFIGURATION  Configuration;
 NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
 NDIS_802_11_RATES  SupportedRates;
} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID;


NDIS_WLAN_BSSID_EX

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct _NDIS_WLAN_BSSID_EX
{
  ULONG  Length;
  NDIS_802_11_MAC_ADDRESS  MacAddress;
  Uchar  Reserved[2];
  NDIS_802_11_SSID  Ssid;
  ULONG  Privacy;
  NDIS_802_11_RSSI  Rssi;
  NDIS_802_11_NETWORK_TYPE  NetworkTypeInUse;
  NDIS_802_11_CONFIGURATION  Configuration;
  NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
  NDIS_802_11_RATES_EX  SupportedRates;
  ULONG IELength;
  UCHAR IEs[1];
} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX;


Toen alles werkte gebruikte ik de eerste structuur.
Daar liep ik met onderstaande code doorheen
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bssidList = (NDIS_802_11_BSSID_LIST *)( &queryOID->Data );
            for ( unsigned int i = 0; i < bssidList->NumberOfItems; i++ )
            {
                TCHAR   s[ 512 ];
            
                // Adjust RSSI value so that it's negative, as it should be.
                if ( bssidList->Bssid[ i ].Rssi > 0 )
                    bssidList->Bssid[ i ].Rssi = -1 * bssidList->Bssid[ i ].Rssi;

                //if ((bssidList->Bssid[ i ].Rssi < 0) && (bssidList->Bssid[ i ].Rssi > -99)){
                  _stprintf( s, _T( "%02x%02x%02x%02x%02x%02x:%d," ),
bssidList->Bssid[ i ].MacAddress[0],bssidList->Bssid[ i ].MacAddress[1]...., bssidList->Bssid[ i ].Rssi );
 
                  _tcscat(str,s);
            //  }
            }


Dit werkt alleen niet voor de NDIS_802_11_BSSID_LIST_EX structuur omdat de NDIS_WLAN_BSSID_EX structuren een variabele lengte hebben.


Nu denk ik dat ik er met een pointer doorheen moet lopen en dan deze aan het begin van elke structuur zetten. om zo op de goeie plek inn het geheugen te komen.

Mijn probleem is echter dat ik dat het wel in pseudo code kan bedenken maar niet zo goed in c++ ben dat ik het ook kan coderen(heb ik vaker last van :-))

Is er hier iemand die mij kan uitleggen hoe ik op een goeie manier door de lijst heen kan lopen

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Uh ik heb er wat moeite mee om door het hele verhaal van BSSID structs e.d. heen te lezen... kun je het probleem even kort samenvatten in een paar regels wat je wil? ;)

Professionele website nodig?


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Je kunt de waarde Length in _NDIS_WLAN_BSSID_EX gebruiken om de lengte van de structure te bepalen.
Zet aan het begin een pointer naar Bssid[0] en verschuif de pointer steeds met de waarde in Length om de volgende structure te bepalen.

Developer Accused Of Unreadable Code Refuses To Comment


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Het probleem :

- Window API calls kunnen verschillende resultaten geven (als in : Verschillende structs) adv de data waar
naar gevraagd wordt.

Men wil :

- Gewoon door de resultset heen lopen :)

De oplossing :

Welk type je terug krijgt kun je zien aan het length veld. Ik maak gewoon een algemene struct aan, en typecast die adv de waarde van het length veld naar de juiste struct.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
union ndis_wlan_bssid_types {
NDIS_WLAN_BSSID normal;
NDIS_WLAN_BSSID_EX extended;
};

/* call naar functie */
switch (var.length) {
   case sizeof(NDIS_WLAN_BSSID):
      /* cast result naar een NDIS_WLAN_BSSID */
   case sizeof(NDIS_WLAN_BSSID_EX):
      /* cast result naar een NDIS_WLAN_BSSID_EX */
}
}


De casts is uitvogelen, in Length staat de sizeof van de struct die je terug krijgt.

  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
de size van de 2e struct is variabel.

Op zich maakt dat niks uit want dan test je gewoon op de lengte van de eerste structure.

Kan ik op deze manier een Pointer aanmaken?

C++:
1
2
3
4
5
PNDIS_WLAN_BSSID *mijnPointer ;

mijnPointer = &bssidList->Bssid[0];

PNDIS_WLAN_BSSID  mijnBSSID = *mijnPointer;



en naar de volgende laten wijzen op deze manier?
C++:
1
mijnPointer = &mijnBSSID + mijnBSSID.Length; 


Ik weet niet of dit goed is want mijn c++ kenis is nog niet zo uitgebreid

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

igmar schreef op 08 juni 2004 @ 12:29:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
union ndis_wlan_bssid_types {
NDIS_WLAN_BSSID normal;
NDIS_WLAN_BSSID_EX extended;
};

/* call naar functie */
switch (var.length) {
   case sizeof(NDIS_WLAN_BSSID):
      /* cast result naar een NDIS_WLAN_BSSID */
   case sizeof(NDIS_WLAN_BSSID_EX):
      /* cast result naar een NDIS_WLAN_BSSID_EX */
}
}


De casts is uitvogelen, in Length staat de sizeof van de struct die je terug krijgt.
Ik neem aan dat ie een array van structs terug krijgt, dus dan heb je hier weinig aan.
mr_taipan schreef op 08 juni 2004 @ 12:53:
de size van de 2e struct is variabel.

Op zich maakt dat niks uit want dan test je gewoon op de lengte van de eerste structure.

Kan ik op deze manier een Pointer aanmaken?

C++:
1
2
3
4
5
PNDIS_WLAN_BSSID *mijnPointer ;

mijnPointer = &bssidList->Bssid[0];

PNDIS_WLAN_BSSID  mijnBSSID = *mijnPointer;



en naar de volgende laten wijzen op deze manier?
C++:
1
mijnPointer = &mijnBSSID + mijnBSSID.Length; 


Ik weet niet of dit goed is want mijn c++ kenis is nog niet zo uitgebreid
Het had wellicht handiger geweest als je je probleem had uitgelegd met een simpel codevoorbeeld ipv je daadwerkelijke probleem ;)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct S1
{
    int length;
    int var1;
};

struct S2
{
    int length;
    int var1, var2, var3;
    char buf[1];
};

void func (void ** buffer, int * numElements);


Als ik het goed begrijp, heb je dus te maken met een functie (hier "func"), die een array van 2 verschillende soorten structs terug kan geven (hier "S1" en "S2"), waarvan de 2e soort van een variabele lengte is, en nu wil je gewoon door al die structs heen lopen?

In principe is het vrij simpel; het is alleen handig om te werken met char pointers, omdat je dan gewoon echt kunt tellen met bytes. Als je namelijk een pointer naar S1 hebt, en je telt daar 1 bij op, dan wijst die pointer dus sizeof (S1) verder, en niet slechts 1 byte. Bij char is dat echter wel zo, dus dat rekent makkelijker.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char * buffer;
int numElements;

func ((void**)&buffer, &numElements);

// doorloop alle elementen
for (int i = 0; i < numElements; i++)
{
    // kijk of het een S1 of een S2 is
    S1 * s1 = (S1 *) buffer;
    if (s1->length == sizeof (S1))
    {
        // handel een S1 af
    }

    else
    {
        S2 * s2 = (S2 *) buffer;
        // handel een S2 af
    }

    buffer += s1->length;  // de volgende struct bevindt zich length bytes verder
}

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

.oisyn schreef op 08 juni 2004 @ 13:44:
Ik neem aan dat ie een array van structs terug krijgt, dus dan heb je hier weinig aan.
Lijkt me onlogisch, maar dan nog is het oplosbaar, alleen zal de oplossing wat minder fris zijn.

  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
Het resultaat wat de functie terug geeft is een structure met een array van structures en een ulong waar het aantal structures in de array in staat.

de structures in de array kunnen variable zijn dat hoeft niet.

-edit-

Ik heb de oplossing gevonden thx

C++:
1
2
3
4
5
6
7
8
9
char *bssIdBase = (char *) &bssidList->Bssid;

for(){

  BssId = (PNDIS_WLAN_BSSID) bssIdBase;
  ....

  bssIdBase += BssId->Length;
}


Door naar een PNDIS_WLAN_BSSID te kasten word automatisch het extra stukje van PNDIS_WLAN_BSSID_EX overgeslagen en hoeft er dus niet gekozen te worden :Y)

[ Voor 47% gewijzigd door mr_taipan op 08-06-2004 15:55 . Reden: Oplossing gevonden ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Voor alle duidelijkheid, het woord "array" wordt hier gebruikt op een ongebruikelijke manier. In een normale array staat het N-de element op relatieve positie N*sizeof(element), maar hier niet.

Ik zou de zaak als volgt oplossen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class bssid {
  union {
    _NDIS_WLAN_BSSID* base;
    _NDIS_WLAN_BSSID_EX derived;
  } ptr;
  int trailing;
public:
  bssid( _NDIS_802_11_BSSID_LIST& list ) : trailing(list.NumberOfItems )
  {
     ptr.base = list.Bssid;
  }
  bool isValid() const { return trailing>=0; }
  bool isEx() const { return ptr.base->Length == sizeof(  _NDIS_WLAN_BSSID )
  operator _NDIS_WLAN_BSSID*() { return ptr.base; }
  operator _NDIS_WLAN_BSSID_EX*() { return ptr.derived; }
  operator _NDIS_WLAN_BSSID const*() const { return ptr.base; }
  operator _NDIS_WLAN_BSSID_EX const* () const { return ptr.derived; }
private:
  bssid(); // geen default-ctor
public:
  // Hier zit de "array-logica"

  bssid next()
  {
    assert( this->isValid() );
    bssid next = *this;
    --next.trailing;
    next.ptr.base += this->ptr.base.Length;
    return next;
  }
};

Gebruik:
C++:
1
2
3
4
5
6
7
8
9
bssid iterator( beginwaarde );
while( iterator.isValid() )
{
  if( iterator.isEx() )
    // use iterator as _NDIS_WLAN_BSSID_EX*
  else
    // use iterator as _NDIS_WLAN_BSSID*
  iterator = iterator.next();
}

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1