Partage
  • Partager sur Facebook
  • Partager sur Twitter

lister les wifis disponibles et s'y connecter

via l'api wlan en c++

    7 mars 2018 à 12:15:26

    Il est souvent intéressant de faire des pauses dans une conception, ça permet de sortir la tête du guidon, et de revenir avec des idées plus claires. ;)

    Remarque de casse-couille, DTO, ça veut dire "Data Transfert Objet", donc des objets qui doivent facilement migrer entre les couches d'une application. Le seul moyen simple d'assurer cela est dans faire de simple structure, composer de champs publics dont les types sont des types de "bases".

    Donc y ajouter une méthode statique, c'est commencer à faire une entorse au Design Pattern de base.

    Il n'est pas interdit d'y faire des entorses, mais il faut évaluer le pour et le contre, et c'est assez souvent un mauvais choix.

    Comme vous le suggérez dans votre EDIT, je pense que mettre cette méthode dans la classe Wlan permettrait de ne pas faire d'entorses, et, pour moi, serait plus "naturel" (c'est aussi un avantage des Design Pattern, c'est qu'en les respectant, on n'est plus confortable car les détails de conception sont déjà connus, d'où le "naturel").

    2ème remarques à la con, évitez le franglais avec "Wlan" qui est un acronyme anglais et "Reseau" qui est français dans le même code. Ici "Reseau" c'est le "n" de Wlan (network) ou c'est "Wlan" en entier ?

    Vous devriez "marquer" le caractère DTO de la classe "Reseau" avec un nom l'indiquant, comme un suffixe, comme "ReseauDTO" (mais je préfèrerais WlanInfos ou WlanParams).

    Si vous suivez le DP DTO, il n'est pas forcement pertinent d'utiliser "tout" les champs du DTO pour les appels suivants mais juste un champ "id" ou une "sous-structure" identifiantes. Si l'utilisateur fait le con avec les autres champs du DTO, c'est ces oignons.

    Vous suivez l'approche qui est de faire une API qui correspond à vos besoins présents (et avenir si possible) et pas de "mimiquer" celle induite par les composants que vous utiliserez dans les couches basses. Cela permet d'avoir une API plus simple d'utilisation, plus spécialisée à vos besoins et plus facilement portable MAIS plus complexe à implémenter.

    Si vous suivez l'approche de "mimiquer" celle induite par les composants que vous utiliserez dans les couches basses, c'est faire un wrapper C++ à l'API C qui vous cherchez à utiliser, vous avez les avantages et inconvénients inverses de l'approche API "originale", mais aussi vous avez une conception offerte sur un plateau. Un avantage bien pratique quand on débute.

    >Wlan qui n'a qu'une fonction, son constructeur

    C'est un peu limiter comme service rendu pour une classe, mais je pense qu'on pourra facilement y ajouter des services sympas.

    >auquel on passe en argument un Reseau

    Je serais plus chaud pour un identifiant (champs du DTO) plutôt que tout le DTO.

    >Ainsi on à des objets fonctionnels à la sortie du constructeur,

    Nickel.

    > moins de risque d'erreur dans les arguments car Reseau ne peut être construit "à la main",

    C'est encore plus vrai avec un "Identifiant".

    Que l'utilisateur de la classe DTO fasse des conneries avec, c'est ses oignons, tant qu'il respect le contrat de ne pas toucher au champ "Identifiant".

    >De plus on pourra mettre certaines infos de Reseau en private

    Je ne mettrais pas cela dans le DTO mais dans une classe interne à votre librairie, que l'identifiant permet de récupérer dans une map, par exemple.

    >Ou Reseau amie de Wlan, dans quel sens le faire ?

    Avec des classes internes, vous pouvez être moins regardant sur l'isolation. Si c'est Wlan qui a besoin de regarder le contenu de la classe "Reseau interne", c'est Wlan qui doit être l'ami de "Reseau interne" et pas l'inverse.

    >Si ca appartient à Reseau, c'est une classe, sinon c'est une bête structure.

    DTO => bête structure

    • Partager sur Facebook
    • Partager sur Twitter
    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
      8 mars 2018 à 9:24:12

      > Comme vous le suggérez dans votre EDIT, je pense que mettre cette méthode dans la classe Wlan permettrait de ne pas faire d'entorses, et, pour moi, serait plus "naturel" (c'est aussi un avantage des Design Pattern, c'est qu'en les respectant, on n'est plus confortable car les détails de conception sont déjà connus, d'où le "naturel").

      ca me parait bien.

      > C'est un peu limiter comme service rendu pour une classe, mais je pense qu'on pourra facilement y ajouter des services sympas.

      Enfin une fonction "principale", nécessaire à l'API pour rendre un objet utilisable et faire d'autres actions.

      Ensuite je n'ai pas tout compris les trucs de l'identifiant, qu'est-ce que vous appelez un identifiant ? Une clé d'un map ?

      Et on passerait cet identifiant en paramètre à Wlan qui en interne utiliserait la fonction getAvilablesNetworks ? (j'ai changé le nom)

      Dans ce cas la autant passer directement le nom en paramètre du constructeur de Wlan non ?

      • Partager sur Facebook
      • Partager sur Twitter
      "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
        8 mars 2018 à 11:18:22

        >qu'est-ce que vous appelez un identifiant ? Une clé d'un map ?

        Par exemple, ou simplement un indice dans un tableau, comme l'est la majorité des "handle" des API C.

        Un truc qui identifie de manière unique le réseau. Attention à ne pas forcement prendre des trucs qui ont un sens dans l'API C.

        L'utilisateur n'a pas à connaitre l'API C que vous wrappez/cachez.

        >Dans ce cas la autant passer directement le nom en paramètre

        Si cela identifie de manière unique le "Wlan" et que ce n'est pas un détail d'implémentation de votre librairie ou de l'API C sous-jacente, oui c'est un bon identifiant.

        Un SSID n'est pas obligatoire pour un Wifi, je crois, donc SSID est différent du "nom".

        Si "nom" a du sens pour l'utilisateur sans avoir à connaitre comment fonctionne précisément le Wifi, oui "nom" est un bon identifiant.

        • Partager sur Facebook
        • Partager sur Twitter
        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
          8 mars 2018 à 19:45:22

          Un SSID est obligatoire il me semble mais pas toujours visible (réseau masqué).

          J'y pense mais il faut aussi un moyen d'identifier sur quel carte réseau on veut se connecter !

          Pourquoi ne pas créer une autre structure, sous-jacente à Reseau qui contient le SSID, le GUID et éventuellement un nom ou un numéro pour l'identifier sans doutes possibles.

          Un code d'exemple serait alors

          std::vector<Reseau> reseaux;
          reseaux = Wlan::getNetworkInfos();
          //affichage des infos
          std::cout << "Quel réseau voulez vous choisir ?" << std::endl;
          int numéro;
          std::cin >> numéro;
          std::cout << "Saisissez le mot de passe" << std::endl;
          std::string password;
          std::cin >> password;
          Wlan wlan(reseaux[numéro].connectionInfos, password);

          On commence à etre pas mal non ?

          • Partager sur Facebook
          • Partager sur Twitter
          "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
            9 mars 2018 à 10:51:49

            >On commence à etre pas mal non ?

            Rien à redire, reste à l'implémenter.

            (Et peut-être à ajouter des services à la classe Wlan ;) ).

            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              9 mars 2018 à 18:37:02

              Alors c'est parti !
              • Partager sur Facebook
              • Partager sur Twitter
              "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                13 mars 2018 à 19:18:04

                Bonjour !

                J'ai fini d'implémenter mon API mais ça ne fonctionne pas encore (INVALID_PARAMETER, vous l'aurez reconnu ;)).

                Il reste deux trois trucs à faire mais le principal pour fonctionner est la.

                Il y a encore surement des erreurs mais j'en suis pas si mécontent :-°

                Bon allez, le code :

                Wifi.cpp

                #include <iostream>
                #include "wlan.h"
                #include "exceptionWlan.h"
                
                int main()
                {
                	try
                	{
                		std::vector<NetworkInfos> infos;
                		infos = Wlan::getNetworkInfos();
                		for (int i(0); i < (int)infos.size(); i++)
                		{
                			std::cout << infos[i].SSID << std::endl;
                		}
                		int nb;
                		std::cin >> nb;
                		Wlan wlan(infos[nb].connexionInfos, "test");
                	}
                	catch (const NetworkNotFound & e)
                	{
                		std::cout << e.what() << std::endl;
                	}
                	catch (const InvalidHandle & e)
                	{
                		std::cout << e.what() << std::endl;
                	}
                	catch (const InvalidParameter & e)
                	{
                		std::cout << e.what() << std::endl;
                	}
                	catch (const OtherError & e)
                	{
                		std::cout << e.what() << std::endl;
                	}
                	catch (const std::exception & e)
                	{
                		std::cout << e.what() << std::endl;
                	}
                //il doit me manquer quelques exceptions mais de toute facon la on fait toujours la même chose si ya une exception.
                	system("pause"); //oui oui je saiiiiiiiiis
                	return 0;
                }

                profil.h

                #pragma comment(lib, "wlanapi.lib")
                #pragma comment(lib, "ole32.lib")
                
                class Profile
                {
                	Profile(ProfileInfos *profileInfos);
                public:
                	static std::unique_ptr<Profile> createProfile(ProfileInfos *profileInfos);
                };

                profil.cpp

                #include <string>
                #include <iostream>
                #include "profil.h"
                
                
                std::unique_ptr<Profile> Profile::createProfile(ProfileInfos *profileInfos)
                {
                	return std::unique_ptr<Profile>(new Profile(profileInfos));
                }
                
                Profile::Profile(ProfileInfos *profileInfos)
                {
                	std::wstring sTemp(profileInfos->SSID.begin(), profileInfos->SSID.end());
                	LPCWSTR SSID = sTemp.c_str();
                	LPWSTR xmlWstr;
                	DWORD dwResult;
                	dwResult = WlanGetProfile(profileInfos->handle, &profileInfos->GUID, SSID, NULL, &xmlWstr, NULL, NULL);
                	if (dwResult != ERROR_SUCCESS && dwResult != ERROR_NOT_FOUND)
                	{
                		switch (dwResult)
                		{
                		case ERROR_ACCESS_DENIED:
                			throw AccessDenied("WlanGetProfile");
                			break;
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanGetProfile");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanGetProfile");
                			break;
                		case ERROR_INVALID_HANDLE:
                			throw InvalidHandle("WlanGetProfile");
                			break;
                		default:
                			throw OtherError("WlanGetProfile", dwResult);
                			break;
                		}
                	}
                	else if (dwResult == ERROR_NOT_FOUND)
                	{
                		//Bon la j'ai pas encore fait la création des 9326 profils possible differents (Vous verrez que dans la structure ProfileInfos, ya des champs pour ce genre d'infos)
                		DWORD dwResaonCode;
                		LPCWSTR xmlProfile;
                		std::string authAlgo;
                		dwResult = WlanSetProfile(profileInfos->handle, &profileInfos->GUID, 0, xmlProfile, 0, false, NULL, &dwResaonCode);
                	}
                	profileInfos->xmlProfile = xmlWstr;
                	WlanCloseHandle(profileInfos->handle, NULL);
                }


                reseau.h (faudra peut etre changer le nom)

                #pragma once
                #include <Windows.h>
                #include <Wlanapi.h>
                #include <memory>
                #include <string>
                #include <vector>
                #include "exceptionWlan.h"
                #pragma comment(lib, "wlanapi.lib")
                #pragma comment(lib, "ole32.lib")
                
                
                struct NetworkConnectionInfos
                {
                	GUID interfaceGUID;
                	int identificationNumber;
                	std::string SSID;
                };
                
                struct NetworkInfos
                {
                	std::wstring profileName;
                	std::string SSID;
                	int nbBSSIDs;
                	int nbPhyTypes;
                	int signalQuality;
                	int interfaceNumber;
                	bool securityEnabled;
                	bool haveProfile;
                	GUID interfaceGUID;
                	_DOT11_PHY_TYPE phyTypes;
                	_DOT11_BSS_TYPE bssTypes;
                	_DOT11_AUTH_ALGORITHM authAlgo;
                	_DOT11_CIPHER_ALGORITHM cipherAlgo;
                	NetworkConnectionInfos connexionInfos;
                };
                
                struct ProfileInfos
                {
                	std::string SSID;
                	std::string password;
                	const GUID GUID;
                	HANDLE handle;
                	LPWSTR xmlProfile;
                	_DOT11_AUTH_ALGORITHM authAlgo; //ici 
                	_DOT11_CIPHER_ALGORITHM cipherAlgo; //et ici pour la contruction des profils
                };



                Wlan.h

                #pragma once
                #include "profil.h"
                #include "Reseau.h"
                
                class Wlan
                {
                	friend Profile;
                
                	HANDLE m_handle;
                	const GUID m_GUID;
                	const std::string m_SSID;
                	const std::string m_password;
                	std::unique_ptr<Profile> m_profile;
                public:
                	Wlan(NetworkConnectionInfos connectionInfos, std::string password);
                	static std::vector<NetworkInfos> Wlan::getNetworkInfos();
                };
                

                Wlan.cpp

                #include <Windows.h>
                #include <Wlanapi.h>
                #include "wlan.h"
                #include "reseau.h"
                
                Wlan::Wlan(NetworkConnectionInfos connectionInfos, std::string password) : m_GUID(connectionInfos.interfaceGUID), m_SSID(connectionInfos.SSID), m_password(password)
                {
                	DWORD dwMaxClient(2);
                	DWORD dwCurVersion(0);
                	DWORD dwResult;
                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &m_handle);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanOpenHandle");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanOpenHandle");
                			break;
                		default:
                			throw OtherError("WlanOpenHandle", dwResult);
                			break;
                		}
                	}
                
                
                	PWLAN_AVAILABLE_NETWORK_LIST networkList = NULL;
                	dwResult = WlanGetAvailableNetworkList(m_handle, &m_GUID, 0, NULL, &networkList);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanGetAvailableNetworkList");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanGetAvailableNetworkList");
                			break;
                		case ERROR_INVALID_HANDLE:
                			throw InvalidHandle("WlanGetAvailableNetworkList");
                			break;
                		default:
                			throw OtherError("WlanGetAvailableNetworkList", dwResult);
                			break;
                		}
                	}
                
                
                	WLAN_AVAILABLE_NETWORK network;
                	ProfileInfos profileInfos{ m_SSID, m_password, m_GUID, m_handle, 0, (DOT11_AUTH_ALGORITHM)NULL, (DOT11_CIPHER_ALGORITHM)NULL };
                	for (int i(0); i < (int)networkList->dwNumberOfItems; i++)
                	{
                		if (reinterpret_cast<char*>(networkList->Network[i].dot11Ssid.ucSSID) == m_SSID && i == connectionInfos.identificationNumber)//si le nom du réseau saisi est trouvé dans la liste on créé un profile
                		{
                			
                			m_profile = Profile::createProfile(&profileInfos);
                			network = networkList->Network[i];
                			break;
                		}
                	}
                	if (m_profile == NULL)//si le profil n'est pas créé car le reseau passé en paramètre n'est pas trouvé dans la liste
                	{
                		throw NetworkNotFound(m_SSID);
                	}
                
                
                	WlanCloseHandle(m_handle, NULL);
                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &m_handle);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanOpenHandle");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanOpenHandle");
                			break;
                		default:
                			throw OtherError("WlanOpenHandle", dwResult);
                			break;
                		}
                	}
                
                
                	PWLAN_BSS_LIST bssList;
                	dwResult = WlanGetNetworkBssList(m_handle, &m_GUID, &network.dot11Ssid, network.dot11BssType, network.bSecurityEnabled, NULL, &bssList); //Ici je tente un truc pour avoir l'adresse MAC du wifi
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanGetNetworkBssList");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanGetNetworkBssList");
                			break;
                		case ERROR_INVALID_HANDLE:
                			throw InvalidHandle("WlanGetNetworkBssList");
                			break;
                		case ERROR_NOT_FOUND:
                			throw NetworkNotFound("WlanGetNetworkBssList");
                			break;
                		case ERROR_NOT_SUPPORTED:
                			throw ErrorNotSupported("WlanGetNetworkBssList");
                			break;
                		case ERROR_NDIS_DOT11_POWER_STATE_INVALID:
                			throw RadioTurnedOff("WlanGetNetworkBssList");
                			break;
                		default:
                			throw OtherError("WlanGetNetworkBssList", dwResult);
                			break;
                		}
                	}
                
                
                	NDIS_OBJECT_HEADER ndisHeader;
                	ZeroMemory(&ndisHeader, sizeof(NDIS_OBJECT_HEADER));
                	ndisHeader.Revision = DOT11_BSSID_LIST_REVISION_1;
                	ndisHeader.Type = NDIS_OBJECT_TYPE_DEFAULT;
                	ndisHeader.Size = sizeof(DOT11_BSSID_LIST);
                	
                
                	DOT11_BSSID_LIST dot11BssidList{ndisHeader, 1, 1, *bssList->wlanBssEntries[0].dot11Bssid };
                        //alors ici je suis obligé d'initialiser ici 
                	/*ZeroMemory(&dot11BssidList, sizeof(DOT11_BSSID_LIST));
                	dot11BssidList.Header = ndisHeader;
                	dot11BssidList.BSSIDs = bssList->wlanBssEntries[0].dot11Bssid; //sinon ici il me dit que dot11BssidList.BSSIDs n'est pas une valeur modifiable, j'ai aussi éssayé avec dot11BssidList.BSSIDs[0] mais le compilo ne veut rien entendre.
                	dot11BssidList.uNumOfEntries = 1;
                	dot11BssidList.uTotalNumOfEntries = 1;*/
                
                
                	WLAN_CONNECTION_PARAMETERS connectionParams;
                	ZeroMemory(&connectionParams, sizeof(connectionParams));
                
                	connectionParams.dot11BssType = network.dot11BssType;
                	connectionParams.pDot11Ssid = &network.dot11Ssid;
                	connectionParams.strProfile = profileInfos.xmlProfile;
                	connectionParams.wlanConnectionMode = wlan_connection_mode_profile;
                	//connectionParams.pDesiredBssidList = &dot11BssidList;
                	connectionParams.dwFlags = WLAN_CONNECTION_IGNORE_PRIVACY_BIT;
                	
                
                	WlanCloseHandle(m_handle, NULL);
                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &m_handle);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanOpenHandle");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanOpenHandle");
                			break;
                		default:
                			throw OtherError("WlanOpenHandle", dwResult);
                			break;
                		}
                	}
                
                
                	dwResult = WlanConnect(m_handle, &m_GUID, &connectionParams, NULL);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanConnect");
                			break;
                		case ERROR_INVALID_HANDLE:
                			throw InvalidHandle("WlanConnect");
                			break;
                		case ERROR_ACCESS_DENIED:
                			throw AccessDenied("WlanConnect");
                		default:
                			throw OtherError("WlanConnect", dwResult);
                			break;
                		}
                	}
                	WlanCloseHandle(m_handle, NULL);
                }
                
                std::vector<NetworkInfos> Wlan::getNetworkInfos()
                {
                	DWORD dwMaxClient(2);
                	DWORD dwCurVersion(0);
                	DWORD dwResult;
                	HANDLE handle;
                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &handle);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanOpenHandle");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanOpenHandle");
                			break;
                		default:
                			throw OtherError("WlanOpenHandle", dwResult);
                			break;
                		}
                	}
                	PWLAN_INTERFACE_INFO_LIST pIfList;
                	dwResult = WlanEnumInterfaces(handle, NULL, &pIfList);
                	if (dwResult != ERROR_SUCCESS)
                	{
                		switch (dwResult)
                		{
                		case ERROR_INVALID_PARAMETER:
                			throw InvalidParameter("WlanEnumInterfaces");
                			break;
                		case ERROR_NOT_ENOUGH_MEMORY:
                			throw NotEnoughMemory("WlanEnumInterfaces");
                			break;
                		case ERROR_INVALID_HANDLE:
                			throw InvalidHandle("WlanEnumInterfaces");
                			break;
                		default:
                			throw OtherError("WlanEnumInterfaces", dwResult);
                			break;
                		}
                	}
                	PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
                	std::vector<NetworkInfos> listInfos;
                	for (int i(0); i < (int)pIfList->dwNumberOfItems; i++)
                	{
                		dwResult = WlanGetAvailableNetworkList(handle, &pIfList->InterfaceInfo->InterfaceGuid, 0, NULL, &pBssList);
                		if (dwResult != ERROR_SUCCESS)
                		{
                			switch (dwResult)
                			{
                			case ERROR_INVALID_PARAMETER:
                				throw InvalidParameter("WlanGetAvailableNetworkList");
                				break;
                			case ERROR_NOT_ENOUGH_MEMORY:
                				throw NotEnoughMemory("WlanGetAvailableNetworkList");
                				break;
                			case ERROR_INVALID_HANDLE:
                				throw InvalidHandle("WlanGetAvailableNetworkList");
                				break;
                			default:
                				throw OtherError("WlanGetAvailableNetworkList", dwResult);
                				break;
                			}
                		}
                		for (int j(0); j < (int)pBssList->dwNumberOfItems; j++)
                		{
                			NetworkInfos infos;
                			infos.authAlgo = pBssList->Network[j].dot11DefaultAuthAlgorithm;
                			infos.bssTypes = pBssList->Network[j].dot11BssType;
                			infos.cipherAlgo = pBssList->Network[j].dot11DefaultCipherAlgorithm;
                			infos.haveProfile = (pBssList->Network[j].strProfileName == NULL) ? false : true;
                			infos.interfaceGUID = pIfList->InterfaceInfo->InterfaceGuid;
                			infos.interfaceNumber = i;
                			infos.nbBSSIDs = (int)pBssList->Network[j].uNumberOfBssids;
                			infos.nbPhyTypes = (int)pBssList->Network[j].uNumberOfPhyTypes;
                			infos.phyTypes = *pBssList->Network[j].dot11PhyTypes;
                			if (pBssList->Network[j].strProfileName == NULL)
                			{
                				infos.profileName = L"";
                			}
                			else
                			{
                				infos.profileName = pBssList->Network[j].strProfileName;
                			}
                			infos.securityEnabled = pBssList->Network[j].bSecurityEnabled;
                			infos.signalQuality = pBssList->Network[j].wlanSignalQuality;
                			infos.SSID = std::string(reinterpret_cast<const char*>(pBssList->Network[j].dot11Ssid.ucSSID), pBssList->Network[j].dot11Ssid.uSSIDLength);
                			infos.connexionInfos = { infos.interfaceGUID, j, infos.SSID };
                			listInfos.push_back(infos);
                		}
                	}
                	WlanCloseHandle(handle, NULL);
                	return listInfos;
                }
                


                exceptionWlan.h (pas forcemement la peine de lire)

                #pragma once
                #include <Windows.h>
                #include <exception> 
                #include <string>
                
                class ExceptionWlan : public std::runtime_error
                {
                public:
                	ExceptionWlan(const char *msg) : std::runtime_error(msg) {};
                };
                
                class NetworkNotFound : public ExceptionWlan
                {
                public:
                	NetworkNotFound(std::string nomReseau) : ExceptionWlan((std::string("ERREUR : Il n'existe aucun réseau nommé ") + nomReseau + " à proximités.").c_str()) {};
                };
                
                class ErrorNotSupported : public ExceptionWlan
                {
                public:
                	ErrorNotSupported(std::string function) : ExceptionWlan(std::string("ERREUR : Votre requete dans la fonction " + function + " n'est pas supportée par votre système.").c_str()) {};
                };
                
                class ServiceNotActive : public ExceptionWlan
                {
                public:
                	ServiceNotActive(std::string function) : ExceptionWlan(std::string("ERREUR : L'AutoConfig Wlan n'est pas activé sur votre système? L'erreur est survenue dans la fonction " + function).c_str()) {};
                };
                
                class AccessDenied : public ExceptionWlan
                {
                public:
                	AccessDenied(std::string fonction) : ExceptionWlan((std::string("ERREUR : Acces refusé dans la fonction ") + fonction).c_str()) {};
                };
                
                class InvalidParameter : public ExceptionWlan
                {
                public:
                	InvalidParameter(std::string function) : ExceptionWlan((std::string("ERREUR : Un des arguments passé en paramètre est invalide dans la fonction ") + function).c_str()) {};
                };
                
                class RadioTurnedOff : public ExceptionWlan
                {
                public:
                	RadioTurnedOff(std::string function) : ExceptionWlan((std::string("ERREUR : La radio est désactivée sur l'interface passée en argument à la fonction ") + function).c_str()) {};
                };
                
                class InvalidHandle : public ExceptionWlan
                {
                public:
                	InvalidHandle(std::string function) : ExceptionWlan((std::string("ERREUR : Le handle passé en paramètre est invalide dans la fonction ") + function).c_str()) {};
                };
                
                class NotEnoughMemory : public ExceptionWlan
                {
                public:
                	NotEnoughMemory(std::string function) : ExceptionWlan((std::string("ERREUR : Pas assez de memoire pour appeller la fonction ") + function).c_str()) {};
                };
                
                class OtherError : public ExceptionWlan
                {
                public:
                	OtherError(std::string function, DWORD error) : ExceptionWlan((std::string("ERREUR : Une erreur inconnue s'est produite dans la fonction ") + function + ". Voici le code d'erreur : " + std::to_string(error)).c_str()) {};
                };
                



                Ca fait pas mal de code mais c'en est déjà moins qu'avant et c'est plus lisible et organisé.

                Pour l'instant je pointe du doigt le dwFlags j'ai mit le meme qu'avant mais il ne me parait pas bien mais je vois pas lequel mettre.

                aussi le pBssList que je contruis à la main avec une autre fonction, bref pour moi c'est un des deux.

                Vous aurez noté que j'ouvre plusieurs handle par ils sont parfois "périmés", je ne sais pas pourquoi...

                • Partager sur Facebook
                • Partager sur Twitter
                "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                  14 mars 2018 à 19:31:28

                  Les ligne 19 à 34 de "wifi.cpp" sont totalement inutiles.

                  Les lignes 9 et 10 de "wifi.cpp" peuvent être fusionnées.

                  Les "#pragma comment (lib,...)" bofbof, c'est mieux d'utiliser les propriétés du projet ou les mettre uniquement dans l'en-tête chapeau de votre module (cloisonnement des dépendances).

                  Il y a beaucoup trop d'include inutiles dans les fichiers d'en-tête. Ils doivent contenir le strict minimum pour qu'ils soient utilisables pour des déclarations, par pour des implémentations. Les en-tête nécessaire à l'implémentation doivent être inclus dans le fichier ".cpp" dans l'implémentation, pas dans le ".h".

                  Chacune de tes structures doit avoir son propre fichier d'en-tête. Si tu veux les regrouper, utilise un header "chapeau" qui inclus ces fichiers d'en-tête "spécifique" à la classe/structure.

                  Les types commençant par "_DOT11" sont des types de la bibliothèque que vous utilisez en interne, il serait préférable que l'utilisateur n'y est pas connaissance, ou tout du moins pas accès. Pour qu'il n'en ait pas connaissance, supprimez ces champs des structures "publiques". Pour qu'il n'y en ait pas l'accès, mettrez ces champs en "private" et uniquement "settable" via un constructeur "private" qu'une fonction statique de la structure/classe pourra utiliser (implémentation du Design Pattern "Factory", comme pour la classe "Profile").

                  "profil.h/cpp" => très rapidement renommer les fichiers pour qu'ils correspondent à la classe qu'ils contiennent (ou mieux, configurer votre IDE pour qu'il le fasse pour vous).

                  N'utiliser jamais de pointeurs nus dans du code C++ (jusqu'à ce que vous aillez le niveau pour contredire intelligemment ce dogme). Donc pas de paramètre "pointeur nus" pour le constructeur de "Profile".

                  La seule utilisation de pointeurs nus comme celui dans le constructeur de "Profile" peut largement expliquer les "INVALID_PARAMETER" à répétition que vous vous prenez dans les dents.

                  Vous ne gérez pas correctement la durée de vie (l'ownership) des variables, et l'utilisation de pointeurs nus dans ce cas est rédhibitoire.

                  Je vous conseille très chaudement de changer la signature de votre constructeur de la classe "Profile" par :

                  class Profile
                  {
                      Profile(ProfileInfos&& profileInfos);
                  public:
                      static std::unique_ptr<Profile> createProfile(ProfileInfos&& profileInfos);
                  };


                  C'est l'utilisation du concept de "move sémantique" car le "ProfileInfos" que vous passez à ce constructeur n'est plus opérationnel après la constructeur. (ligne 48 de "profil.cpp" invalide l'handle stocké dans le ProfileInfos)

                  Des classes/structures avec des handle dedans ne devraient pas être "clonable", on parle de classe à sémantique d'"Entité".

                  Cela implique des contraintes sur la conception de ce type de classes comme pas de constructeur par copie, etc..., je te laisse voir avec notre ami Google les contraintes que tu devrais ajouter à cette classe ProfileInfos.

                  L'utilisation du "move sémantique" renforce l'usage correct de ce type de classe à sémantique d'"Entité".

                  Telle que ton implémentation est faites, le constructeur de "Profile" vampirise le ProfileInfos en paramètre, et c'est à cela que sert de "move sémantique" : officialiser cette vampirisation.

                  Je ne suis pas sûr que votre usage des handles de la librairie sous-jacente soit correct. Souvent, quand on récupère un handle (handle_récupéré) via une API qui demande un handle en entrée (handle_source), le fait de fermer l'handle_source rend inopérant le "handle_récupéré".

                  Un ajout de C++14 : make_unique ( http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique ):

                  std::unique_ptr<Profile> Profile::createProfile(ProfileInfos&& profileInfos)
                  {
                      return std::make_unique<Profile>(profileInfos);
                  }

                  Comme les pointeurs nus, jamais de "new" dans du C++.

                  Votre code de gestion des erreurs / du résultat dans "dwResult" est extrêmement lourde.

                  Ce code est primordial pour le bon fonctionnement du système, mais il n'apporte rien en terme de "sémantique" de la fonction.

                  C'est du "bruit" dans le code.
                  On cherche toujours à minimiser ce bruit "visuellement", pour rendre le code bien plus lisible.

                  Votre manière de faire est très lourde mais aussi très sujette à erreur, car un oubli de copier-coller (pour les cases, les noms de la méthode, etc...) et c'est le drame.

                  Vous pouvez très facilement factoriser tout ce code.

                  Moi, je fais généralement cela via une MACRO, type SUCCESS ( https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms687197%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 ) mais vous pouvez aussi faire une fonction de traitement des erreurs "centralisée" ( comme une fonction "inverse" d'une fonction Lippincott http://cppsecrets.blogspot.fr/2013/12/using-lippincott-function-for.html). On peut coupler les 2 , MACRO + fonction de traitement des erreurs.

                  Lignes 15, 16, 42 à 44 de "Profil.cpp", toujours correctement initialiser les variables et encore plus quand on les passent à une API C système. (ZeroMempry, etc...., je crois qu'on a déjà largement évoqué le problème dans cette même file de message)

                  La classe Wlan contient un HANDLE, elle a donc une sémantique de classe "Entité", donc même remarque que pour la classe "Profile", la rendre non-clonable, etc...

                  Ligne 6 de "Wlan.cpp", vous êtes sûr que le passage de paramètres par copie à la place de références constantes se justifie ?

                  Ligne 8 et 9 de "Wlan.cpp", utilisez plutôt de "{}" que des "()" pour l'initialisation des variables, ça évite des fautes bêtes :

                      DWORD dwMaxClient{2};
                      DWORD dwCurVersion{0};


                  Attention à la génération d'exception dans un constructeur, généralement, il faut utiliser des idiosyncrasies particulières :

                  https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom

                  Dans tout le fichier "Wlan.cpp", l'initialisation des variables est très mal faites, à revoir complètement.

                  Dans du code C++, il n'y aucune justification pour faire des casts à la C. Donc supprimez tous ces casts ( ligne 52 "(DOT11_AUTH_ALGORITHM)" etc..., aucun cast de la forme "(T)").

                  Il y a plusieurs types de cast en C++, utilisez les à bon escient et les "reinterpret_cast" à éviter le plus possible.

                  Pas de "NULL" en C++, c'est "nullptr".

                  Ligne 55 de "Wlan.cpp", attention à vérifier la sémantique de l'opérateur "==" entre ces types. Est-ce une égalité sur les pointeurs mémoire ou sur le contenu des "chaines" ? (en attendant l'introduction de l'opérateur "spaceship" '<=>' à la JavaScript, en C++20 normalement).

                  Ligne 69 de "Wlan.cpp", pourquoi elle n'a pas de gestion d'erreur ??? En utilisant une MACRO et/ou une fonction Lippincott "inverse", ça serait plus visible, ce genre d'oubli.

                  >//alors ici je suis obligé d'initialiser ici

                  On n'est toujours obligé d'initialiser, et encore plus quand on interface une API C.

                  Attention à votre membre "m_handle" de la classe Wlan qui n'est pas toujours valide et même souvent invalide, tout au long du constructeur. Un membre, c'est pas une variable locale++. ;)

                  C'est le genre de truc qui rend le code imbittable et super-buggué.

                  Ligne 19 de " la suite de Wlan.cpp", idem à ligne 69 de "Wlan.cpp", soyez rigoureux avec le traitement des erreurs.(Il n'y a pas que ces 2 lignes, revoyez tout le code)

                  Dans la suite du code, de nombreuses choses qui correspondent à des remarques que j'ai déjà faites.

                  La MACRO "L" à la ligne 138 de " la suite de Wlan.cpp" me fait remarquer que vous mélangez un peu les types de chaines de caractères, ce qui peut rendre le code difficile à comprendre et à maintenir.

                  Vous utilisez des primitives qui ne sont pas "marquées" avec un suffixe "A" (pour ASCII) ou "W" (WIDE => UNICODE).

                  Si ces primitives prennent des chaines de caractères en paramètre, vous deviez utiliser de TCHAR et pas de char ou des std::string.

                  Donc, quand le type de chaine de caractère n'est pas explicitement indiqué, pensez à utiliser systématiquement des TCHAR/PTSTR/la MACRO TEXT etc...

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                    19 mars 2018 à 23:53:24

                    > Les ligne 19 à 34 de "wifi.cpp" sont totalement inutiles.
                    Les lignes 9 et 10 de "wifi.cpp" peuvent être fusionnées.
                    Corrigé.
                    >Les "#pragma comment (lib,...)" bofbof, c'est mieux d'utiliser les propriétés du projet ou les mettre uniquement dans l'en-tête chapeau de votre module (cloisonnement des dépendances).
                    Je ne comprend pas pourquoi, le chemin vers les libs est dans les propriétés mais sans ca marche pas, l'en tête chapeau j'ai toujours du mal à savoir quoi mettre dedans, toutes nos classes "publiques" c'est ca ?
                    >Il y a beaucoup trop d'include inutiles dans les fichiers d'en-tête. Ils doivent contenir le strict minimum pour qu'ils soient utilisables pour des déclarations, par pour des implémentations. Les en-tête nécessaire à l'implémentation doivent être inclus dans le fichier ".cpp" dans l'implémentation, pas dans le ".h".
                    Chacune de tes structures doit avoir son propre fichier d'en-tête. Si tu veux les regrouper, utilise un header "chapeau" qui inclus ces fichiers d'en-tête "spécifique" à la classe/structure.
                    Ok j'ai corrigé, j'ai mis les #pragma comment(lib,..) dedans en plus.
                    >Les types commençant par "_DOT11" sont des types de la bibliothèque que vous utilisez en interne, il serait préférable que l'utilisateur n'y est pas connaissance, ou tout du moins pas accès. Pour qu'il n'en ait pas connaissance, supprimez ces champs des structures "publiques". Pour qu'il n'y en ait pas l'accès, mettrez ces champs en "private" et uniquement "settable" via un constructeur "private" qu'une fonction statique de la structure/classe pourra utiliser (implémentation du Design Pattern "Factory", comme pour la classe "Profile").
                    Vu que l'utilisateur doit y avoir acces je peux aussi faire un
                    typedef _DOT11_CIPHER_ALGORITHM CipherAlgo;
                    et changer dans la definition de mes structures, qu'en pensez vous ?
                    >"profil.h/cpp" => très rapidement renommer les fichiers pour qu'ils correspondent à la classe qu'ils contiennent (ou mieux, configurer votre IDE pour qu'il le fasse pour vous).
                    Rajouter le "e" ? fait !
                    Pour les pointeurs nus je fais comment du coup ?
                    Je dois passer une valeur null à certains arguments vu que je les recupère après.
                    > Vous ne gérez pas correctement la durée de vie (l'ownership) des variables, et l'utilisation de pointeurs nus dans ce cas est rédhibitoire.
                    Ah bon ? Que dois-je faire en plus ?
                    Je change la signature de profile.
                    Je me suis renseigné sur les classes à sémantique d'Entité et je me suis posé une question, doit elle etre swappable ?
                    Je n'y vois pas inconvénient, je dois juste mettre un constructeur privé avec notre méthode avec unique_ptr, un constructeur de copie privé et un opérateur = privé.
                    >Telle que ton implémentation est faites, le constructeur de "Profile" vampirise le ProfileInfos en paramètre, et c'est à cela que sert de "move sémantique" : officialiser cette vampirisation.
                    Vampirise ? C'est à dire ?
                    > Je ne suis pas sûr que votre usage des handles de la librairie sous-jacente soit correct. Souvent, quand on récupère un handle (handle_récupéré) via une API qui demande un handle en entrée (handle_source), le fait de fermer l'handle_source rend inopérant le "handle_récupéré".
                    Là j'ai pas compris, en théorie je suis censé avoir un seul handle, mais quand vous dites "handle", on parle bien d'une variable de type handle ?
                    J'aime bien la technique du Lippincott, couplé avec la macro SUCCESS, c'est vrai que c'est bien mieux et léger.
                    >Ligne 6 de "Wlan.cpp", vous êtes sûr que le passage de paramètres par copie à la place de références constantes se justifie ?
                    Absolument pas !
                    >Ligne 8 et 9 de "Wlan.cpp", utilisez plutôt de "{}" que des "()" pour l'initialisation des variables, ça évite des fautes bêtes 
                    Ok, je le fais partout ?
                    > Attention à la génération d'exception dans un constructeur, généralement, il faut utiliser des idiosyncrasies particulières :
                    https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
                    J'a lu le lien et me suis renseigné mais ca s'applique au constructeur par copie ça non ?
                    > Dans tout le fichier "Wlan.cpp", l'initialisation des variables est très mal faites, à revoir complètement.
                    Je rajoute des ZeroMemory et essaye de faire des aggrgate initializations, c'est bien ce qu'il faut faire ?
                    >Dans du code C++, il n'y aucune justification pour faire des casts à la C. Donc supprimez tous ces casts ( ligne 52 "(DOT11_AUTH_ALGORITHM)" etc..., aucun cast de la forme "(T)").
                    Il y a plusieurs types de cast en C++, utilisez les à bon escient et les "reinterpret_cast" à éviter le plus possible.
                    Oui mais que faire pour faire passer nullptr en DOT11_AUTH_ALGORITHM ? Je suppose que je dois pas le faire
                    >Ligne 55 de "Wlan.cpp", attention à vérifier la sémantique de l'opérateur "==" entre ces types. Est-ce une égalité sur les pointeurs mémoire ou sur le contenu des "chaines" ? (en attendant l'introduction de l'opérateur "spaceship" '<=>' à la JavaScript, en C++20 normalement).
                    C'est censé comparer les valeurs mais ca m'tonnerais pas que il y ai une merde sur cette ligne
                    > Ligne 69 de "Wlan.cpp", pourquoi elle n'a pas de gestion d'erreur ??? En utilisant une MACRO et/ou une fonction Lippincott "inverse", ça serait plus visible, ce genre d'oubli.
                    Ah oui, en effet, je vais ajouter ma fonction de suite.
                    > Attention à votre membre "m_handle" de la classe Wlan qui n'est pas toujours valide et même souvent invalide, tout au long du constructeur. Un membre, c'est pas une variable locale++. ;)
                    justement je ne comprend pas pourquoi c'est pas valide, j'ai cru voir une réponse plus haut mais je n'ai pas compris (c'est écrit)
                    > Ligne 19 de " la suite de Wlan.cpp", idem à ligne 69 de "Wlan.cpp", soyez rigoureux avec le traitement des erreurs.(Il n'y a pas que ces 2 lignes, revoyez tout le code)
                    En effet, je vais y ajouter ma petite gestion des erreurs.
                    Pour la suite :
                    Je dois donc utiliser uniquement des TCHAR par exemple ? Des fois je n'ai pas le choix, il est imposé par l'API.
                    J'enverrais mon code un peu plus tard (dès que j'aurais fini de le retoucher, d'ou l'abscence de réponse à certains de vos commentaires, je le fais).
                    • Partager sur Facebook
                    • Partager sur Twitter
                    "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                      20 mars 2018 à 19:09:14

                      >Je ne comprend pas pourquoi, le chemin vers les libs est dans les propriétés mais sans ca marche pas,

                      Vraisemblablement dans la mauvaise "propriété" alors. ;)

                      C'est toujours mieux que l'utilisateur puisse indiquer où sont les lib plutôt que de l'obliger à les copier à un endroit qu'il ne lui convient pas forcement.

                      > l'en tête chapeau j'ai toujours du mal à savoir quoi mettre dedans, toutes nos classes "publiques" c'est ca ?

                      Si par "mettre dedans", tu veux dire un "#include" des .h associés à ces classes, oui alors.

                      Avec un en-tête chapeau, l'utilisateur l'inclus et il n'a pas à se prendre la tête comment sont organisés les fichiers d'en-tête de la librairie qu'il veut utiliser. Les "#pragma comment (lib,...)" dans ce type d'en-tête, ça permet d'indiquer clairement à celui qui veut recompiler qu'il doit faire le nécessaire pour que l'éditeur de lien les choppent.

                      >Ok j'ai corrigé, j'ai mis les #pragma comment(lib,..) dedans en plus.

                      Pour en faire un vrai chapeau, il reste à inclure les .h des classes publiques (et aussi supprimer les "#pragma comment(lib,..)" en corrigeant les paramètres du projet).

                      >Vu que l'utilisateur doit y avoir acces je peux aussi faire un

                      Pourquoi l'utilisateur doit-il y avoir accès ?

                      Vous devez encapsuler la couche C car l'utilisateur ne devrait pas la connaitre. En plus, c'est une structure C bien pérave. S'il à besoin des informations contenues dans cette structure, wrappez la dans un "vrai" objet C++, pratique et facile d'utilisation (rendre facile la bonne utilisation et difficile la mauvaise utilisation).

                      >et changer dans la definition de mes structures, qu'en pensez vous ?

                      Changez la définition de vos structures pour qu'elles contiennent des objets faciles d'utilisation.(ou pas d'objet si ça sert à rien).

                      >Pour les pointeurs nus je fais comment du coup ?

                      C'est fonction de ce que l'on veut faire. C'est pour ça que les pointeurs nus c'est pourri, ça fait tout, très très mal.

                      >Je dois passer une valeur null à certains arguments vu que je les recupère après.

                      Pourquoi ?

                      Il suffit que cela soit la valeur de retour ou un composant de la valeur de retour.

                      Avec ce type de pointeur en paramètre, c'est qui qui est en charge de libérer le machin de pointeur nus ?

                      etc...

                      Analysez l'usage et vous tomberez quasi systématiquement sur un truc mieux que le pointeur nu.

                      >Ah bon ? Que dois-je faire en plus ?

                      Pourquoi en plus ? Il faut juste prendre le bon outil en fonction de votre intention.

                      > doit elle etre swappable ?

                      Qu'entendez-vous par "swappable" ???

                      >Vampirise ? C'est à dire ?

                      Quand vous utilisez le "move sémantique", l'objet en paramètre est considéré par l'appelant comme "perdu" et vous ne devez pas vous en servir dans le code après l'appel. Quand on implémente une méthode qui prend en paramètre un "T&&", mais qu'on veut garder les données qu'il contient, on ne copie par ses champs, on transfère la propriété (l'ownership) de ses champs vers un autre objet. Comme l'objet appelant a perdu la propriété de ses champs, c'est comme si le code de la méthode l'avait vampirisé car il ne possède plus la propriété des champs qu'il avait en entré de la méthode.

                      >Là j'ai pas compris, en théorie je suis censé avoir un seul handle

                      Alors qu'en théorie, parce que des handles, vous en créez un peu partout dans votre code. Il faut être consciencieux avec ce type d'objet.

                      >mais quand vous dites "handle", on parle bien d'une variable de type handle ?

                      "variable", ça veut rien dire ou tout dire. J'espère que je n'utilise pas ce terme.

                      Si je parle de "handle" (donc en minuscule), c'est que je parle de l'identifiant, qui lui est mis à toutes les sauces dans votre code : variable locale, champ d'une classe, etc... . Si je parle du type c'est HANDLE, le C++ est case sensitive. ;)

                      >Absolument pas !

                      Alors utilisez le type de passage de paramètre qu'il convient, il ne faut pas en prendre un au pif.

                      >Ok, je le fais partout ?

                      Vaut mieux, oui.

                      >J'a lu le lien et me suis renseigné mais ca s'applique au constructeur par copie ça non ?

                      Non, à tout type de constructeur.

                      >Je rajoute des ZeroMemory et essaye de faire des aggrgate initializations, c'est bien ce qu'il faut faire ?

                      Oui, mais attention aux "aggrgate initializations" qui peuvent ne pas remplir correctement les structures C.

                      >Oui mais que faire pour faire passer nullptr en DOT11_AUTH_ALGORITHM ?

                      Bin non, "DOT11_AUTH_ALGORITHM" est un enum, pas un pointeur, et votre cast ne fait que mettre un "NULL" donc un "0" dans cet enum. Vous avez donc forcé une valeur interdite, 0, dans un champ de type "DOT11_AUTH_ALGORITHM" qui ne devrait pas accepter. Vous avez donc bien défoncé toute la structure avec des données complètement au zef, c'est tout le pouvoir des cast à la C, foutre le bordel sans s'en rendre compte. Comme je ne vois pas l'utilité de mettre le champ "authAlgo" dans cette structure, je ne peux vous conseiller une méthode, mais clairement, foutre de force un 0/NULL dedans, ça sent mauvais.

                      >C'est censé comparer les valeurs mais ca m'tonnerais pas que il y ai une merde sur cette ligne

                      Vous devez savoir ce que doit faire les méthodes/opérateurs que vous utilisez, sinon c'est la fin des haricots.

                      >justement je ne comprend pas pourquoi c'est pas valide

                      Ligne 56 de 'la suite de Wlan.cpp", vous pensez qu'il est dans quel état m_handle après un appel à "WlanCloseHandle" ? ;)

                      >Je dois donc utiliser uniquement des TCHAR par exemple ?

                      TCHAR quand le type de chaine de caractère n'est pas spécifié.

                      >Des fois je n'ai pas le choix, il est imposé par l'API.

                      Alors utilisez le type de chaine de caractère imposé, mais uniquement dans le cadre de l'API et de manière explicite et systématique.

                      Mais assez rare qu'une API impose un type de chaine de caractère.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        26 mars 2018 à 9:35:18

                        J'avais préparé une belle réponse mais je me débat actuellement avec mon compilateur car j'ai du changer la méthode Profile::createProfile comme ça:

                        std::unique_ptr<Profile> Profile::createProfile(ProfileInfos&& profileInfos)
                        {
                        	return std::make_unique<Profile>(std::move(profileInfos));
                        }

                        Mais du coup il me signale que std::make_unique essaye d’accéder à un membre privé (ici mon constructeur) donc il faudrait que std::make_unique soit amie avec Profile mais je n'arrive pas à le faire.

                        Voici ce que je fais :

                        	template<class _Types>
                        	friend std::make_unique(_Types&&...);

                        Mais il me dit que std::make_unique n'est pas une fonction.

                        Comment le mettre en amie ?

                        • Partager sur Facebook
                        • Partager sur Twitter
                        "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                          27 mars 2018 à 16:36:20

                          Désolé pour le délai de réponse.

                          Vous êtes tombé sur un "os" par ma faute.

                          Je vous conseille de créer un nouveau sujet sur ce problème précis, car vous êtes tombé dans un "trou" de Visual C++.

                          Avec un nouveau sujet, vous aurez des personnes successibles de vous répondre sur ce problème précis d'implémentation du DP Factory en C++. Moi, je n'ai que des solutions que j'estime être du bricolage. Personne ne continue à lire un thread de message de plusieurs centaines de message autre que ceux qui "dialoguent".

                          Avec des personnes plus au fait des template C++ comme @jo_link_noir, sur ce forum, vous êtes sûr d'avoir une réponse "state of the art".

                          Sur le papier, vous n'êtes pas obligé de "friendliser" le template mais juste sa spécialisation :

                          friend std::unique_ptr<Profile> std::make_unique<Profile>(ProfileInfos&&);

                          Mais VS semble toujours avoir un problème avec l'instantiation des templates dans ce cas d'usage.

                          Il n'y a toujours des solutions à base new ou l'usage d'un namespace pour contourner ces problèmes d'instanciation mais je vous invite chaudement à poser la question sur le forum pour avoir l'avis des "spécialistes".

                          Courage.

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                            27 mars 2018 à 19:45:03

                            Bonjour,

                            Pas de problème pour les délais ça n'a pas d'importance.

                            J'ai donc créé un topic ici : https://openclassrooms.com/forum/sujet/mettre-la-fonction-std-make-unique-en-amie (et j'ai tag jo_link_noir sur le discord, il m'avait déjà aidé un peu pour ce type de problème.

                            Merci, on y arrivera.

                            Raphael.

                            -
                            Edité par raphaeldesaintalbin 28 mars 2018 à 9:51:21

                            • Partager sur Facebook
                            • Partager sur Twitter
                            "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte

                            lister les wifis disponibles et s'y connecter

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown