none
Struct WLAN_RAW_DATA_LIST erzeugen RRS feed

Antworten

  • Ok jetzt verstehe ich wie dumm meine frage ist und wie wenig ich von C++ verstehe.

    Man reserviert Arbeitsspeicher und schreibt den struct der die Größe und die Positionen den Daten angibt am Anfang des Datensatzes gefolgt von den Daten selbst. In C# wäre das ein einfaches byte[] wobei der type DWORD 4 bytes einnimmt. In C++ macht das sicherlich sinn da man dann nur einen reservierten Bereich hat den man wieder freigeben muss. Ist eigentlich nicht anderes als ein protokolierten Stream zu lesen. Hätte ich auch früher drauf kommen können 


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Donnerstag, 1. August 2019 21:56
  • Hallo Thomas,

    da hier im Forum Antworten vom Wochenende verlorengingen, poste ich nochmal den Code. Den Text habe ich nicht mehr, den hattest du ja schon zur Kenntnis genommen.

    DWORD SetIe(HANDLE hClient)
    {
    	DWORD dwResult = 0;
    	PWLAN_RAW_DATA_LIST rawDataList = new WLAN_RAW_DATA_LIST();
    	LPCWSTR formatData = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    
    	char ieData[] = { '\x00', '\x01', '\x02', '\x03' };
    
    	rawDataList->dwTotalSize = 16 + sizeof(ieData);
    	rawDataList->dwNumberOfItems = 1;
    	rawDataList->DataList[0].dwDataOffset = 8;
    	rawDataList->DataList[0].dwDataSize = sizeof(ieData);
    
    	char* buffer = new char[rawDataList->dwTotalSize];
    
    	// sizeof(&rawDataList) oder sizeof(rawDataList) würden nur 4 (bzw. 8 auf 64-Bit-OS) ergeben, da dies Zeiger sind.
    //	memcpy(&buffer, &rawDataList, sizeof(&rawDataList));
    	memcpy(buffer, rawDataList, sizeof(WLAN_RAW_DATA_LIST));
    
    	for (size_t i = 0, j = 16; i < sizeof(ieData); i++, j++)
    	{
    		buffer[j] = ieData[i];
    	}
    
    	// 'rawDataList' und 'buffer' sollten keine weitere Zuweisung erhalten, da ihr
    	// speicher wieder freigegeben werden muß.
    //	rawDataList = (PWLAN_RAW_DATA_LIST)buffer;
    
    	DWORD	ret = WlanSetPsdIEDataList(hClient, formatData, (PWLAN_RAW_DATA_LIST)buffer, NULL);
    
    	delete []buffer;
    	delete rawDataList;
    
    //	return WlanSetPsdIEDataList(hClient, formatData, rawDataList, NULL);
    	return ret;
    }
    // WifiDirect.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <wlanapi.h>
    
    struct BLOB_HEADER
    {
    	DWORD	dwOffset,
    			dwSize;
    };
    
    struct PSD
    {
    	BYTE	  Id;
    	BYTE	  Length;
    	BYTE	  OUI[3];
    	BYTE	  OUIType;
    	BYTE	  FormatIdentifierHash[4];
    	BYTE	  Data[230];	// Maximale Länge; Data kann kürzer sein.
    };
    
    int _tmain(int argc, _TCHAR* argv[]);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int size, BYTE * data);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5);
    void PrintResult(DWORD error);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	DWORD	ret,
    			usedVersion;
    	HANDLE	hWlan;
    
    	ret = WlanOpenHandle(2, NULL, &usedVersion, &hWlan);
    	if (ret != ERROR_SUCCESS)
    	{
    		PrintResult(ret);
    		return -1;
    	}
    	// Siehe https://docs.microsoft.com/de-de/windows/win32/api/wlanapi/nf-wlanapi-wlansetpsdiedatalist
    
    	int		size = sizeof(PSD);
    	wchar_t	* format = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    	PSD		* pPsd = new PSD;
    
    	memset(pPsd, 0, sizeof(PSD));
    	pPsd->Id = 221;
    	pPsd->Length = 10;	// 8; Die Länge soll PSD.Data + 8 sein. Die Felder in PSD vor PSD.Data sind jedoch 10 Bytes. ???
    	pPsd->OUI[0] = (BYTE)0x00;
    	pPsd->OUI[1] = (BYTE)0x50;
    	pPsd->OUI[2] = (BYTE)0xF2;
    	pPsd->OUIType = 6;
    	pPsd->FormatIdentifierHash[0] = 0xF8;
    	pPsd->FormatIdentifierHash[1] = 0xCB;
    	pPsd->FormatIdentifierHash[2] = 0x35;
    	pPsd->FormatIdentifierHash[3] = 0x15;
    
    	//BYTE	data[] = { (BYTE)0x00, (BYTE)0x01, (BYTE)0x02, (BYTE)0x03 };
    
    	//size = sizeof(data);
    	//ret = SetBlobs(hWlan, format, size, data);
    	ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd);
    	if (ret == ERROR_SUCCESS)
    	{
    		// Test mit mehreren Blobs (bis zu 5; DOT11_PSD_IE_MAX_ENTRY_NUMBER)
    		PSD	psd2,
    			psd3,
    			psd4;
    
    		memcpy(&psd2, pPsd, size);
    		memcpy(&psd3, pPsd, size);
    		memcpy(&psd4, pPsd, size);
    
    		// ERROR_SUCCESS
    	//	ret = SetBlobs(hWlan, format, size, data, size, data, 0, NULL, 0, NULL, 0, NULL);
    	//	ret = SetBlobs(hWlan, format, size, (BYTE *)&psd2, 0, NULL, 0, NULL, 0, NULL, 0, NULL);
    		ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd, size, (BYTE *)&psd2, size, (BYTE *)&psd3, size, (BYTE *)&psd4, 0, NULL);
    	}
    	delete pPsd;
    	WlanCloseHandle(hWlan, NULL);
    	PrintResult(ret);
    	return 0;
    }
    
    // Für genau einen Blob.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize, BYTE * data)
    {
    	// Ohne Blobs liefert WlanSetPsdIEDataList() auch ERROR_SUCCESS.
    /*	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[8];
    
    	pList->dwTotalSize = 8;
    	pList->dwNumberOfItems = 0;
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	PrintResult(ret);
    
    	delete[](BYTE *)pList;
    	return ret;
    */
    
    	if (!hWlan || dataSize <= 0 || dataSize > DOT11_PSD_IE_MAX_DATA_SIZE || !data)
    		return ERROR_INVALID_PARAMETER;
    
    	int	size = sizeof(WLAN_RAW_DATA_LIST) + dataSize;
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;	// Die Angabe im Beispiel der MSDN ist widersprüchlich, statt 84 sollte dort 68 (nach meiner Meinung) stehen.
    	pList->dwNumberOfItems = 1;
    	pList->DataList[0].dwDataSize = dataSize;
    	pList->DataList[0].dwDataOffset = 8;
    
    	memcpy((BYTE *)pList + sizeof(WLAN_RAW_DATA_LIST), data, dataSize);
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	delete [](BYTE *)pList;
    	return ret;
    }
    
    // Für 0 bis 5 Blobs.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5)
    {
    	if (!hWlan)
    		return ERROR_INVALID_PARAMETER;
    
    	DWORD	size = sizeof(BLOB_HEADER),
    			dataOffset = 0,
    			count = 0;
    
    	if (dataSize1 < 0 || dataSize1 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize1 > 0 && !data1)
    		return ERROR_INVALID_PARAMETER;
    	else if (dataSize1 > 0)
    	{
    		size += sizeof(BLOB_HEADER) + dataSize1;
    		dataOffset += sizeof(BLOB_HEADER);
    		count++;
    		if (dataSize2 < 0 || dataSize2 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize2 > 0 && !data2)
    			return ERROR_INVALID_PARAMETER;
    		else if (dataSize2 > 0)
    		{
    			size += sizeof(BLOB_HEADER) + dataSize2;
    			dataOffset += sizeof(BLOB_HEADER);
    			count++;
    			if (dataSize3 < 0 || dataSize3 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize3 > 0 && !data3)
    				return ERROR_INVALID_PARAMETER;
    			else if (dataSize3 > 0)
    			{
    				size += sizeof(BLOB_HEADER) + dataSize3;
    				dataOffset += sizeof(BLOB_HEADER);
    				count++;
    				if (dataSize4 < 0 || dataSize4 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize4 > 0 && !data4)
    					return ERROR_INVALID_PARAMETER;
    				else if (dataSize4 > 0)
    				{
    					size += sizeof(BLOB_HEADER) + dataSize4;
    					dataOffset += sizeof(BLOB_HEADER);
    					count++;
    					if (dataSize5 < 0 || dataSize5 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize5 > 0 && !data5)
    						return ERROR_INVALID_PARAMETER;
    					else if (dataSize5 > 0)
    					{
    						size += sizeof(BLOB_HEADER) + dataSize5;
    						dataOffset += sizeof(BLOB_HEADER);
    						count++;
    					}
    				}
    			}
    		}
    	}
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;
    	pList->dwNumberOfItems = count;
    
    	BLOB_HEADER	* pBlobHeader = (BLOB_HEADER *)&pList->DataList;
    	BYTE		* pData = (BYTE *)&pList->DataList + dataOffset;
    
    	if (count >= 1)
    	{
    		pBlobHeader->dwSize = dataSize1;
    		pBlobHeader->dwOffset = dataOffset;
    		memcpy(pData, data1, dataSize1);
    		if (count >= 2)
    		{
    			pBlobHeader++;
    			pData += dataSize1;
    			dataOffset -= sizeof(BLOB_HEADER);
    			dataOffset += dataSize1;
    			pBlobHeader->dwSize = dataSize2;
    			pBlobHeader->dwOffset = dataOffset;
    			memcpy(pData, data2, dataSize2);
    			if (count >= 3)
    			{
    				pBlobHeader++;
    				pData += dataSize2;
    				dataOffset -= sizeof(BLOB_HEADER);
    				dataOffset += dataSize2;
    				pBlobHeader->dwSize = dataSize3;
    				pBlobHeader->dwOffset = dataOffset;
    				memcpy(pData, data3, dataSize3);
    				if (count >= 4)
    				{
    					pBlobHeader++;
    					pData += dataSize3;
    					dataOffset -= sizeof(BLOB_HEADER);
    					dataOffset += dataSize3;
    					pBlobHeader->dwSize = dataSize4;
    					pBlobHeader->dwOffset = dataOffset;
    					memcpy(pData, data4, dataSize4);
    					if (count >= 5)
    					{
    						pBlobHeader++;
    						pData += dataSize4;
    						dataOffset -= sizeof(BLOB_HEADER);
    						dataOffset += dataSize4;
    						pBlobHeader->dwSize = dataSize5;
    						pBlobHeader->dwOffset = dataOffset;
    						memcpy(pData, data5, dataSize5);
    					}
    				}
    			}
    		}
    	}
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	// Da der Speicher für 'pList' als Array (von BYTEs) angefordert wurde, muß er auch als Array freigegeben werden.
    	delete[](BYTE *)pList;
    	return ret;
    }
    
    void PrintResult(DWORD error)
    {
    	switch (error)
    	{
    	case ERROR_SUCCESS:
    		puts("ERROR_SUCCESS");
    		break;
    	case ERROR_INVALID_PARAMETER:
    		puts("ERROR_INVALID_PARAMETER");
    		break;
    	case ERROR_NOT_ENOUGH_MEMORY:
    		puts("ERROR_NOT_ENOUGH_MEMORY");
    		break;
    	case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
    		puts("ERROR_REMOTE_SESSION_LIMIT_EXCEEDED");
    		break;
    	default:
    		printf("0x%08X\r\n", error);
    		break;
    	}
    	getchar();
    }


    Gruß,
    Heiko

    Dienstag, 20. August 2019 15:27
  • Hallo Thomas,

    dumme Fragen gibt es nicht. Man wird doch wohl untereinander laut denken dürfen ;-)

    Im C++ Code bringst du einiges durcheinander. Ein memcpy() mit den Adressen von Zeigervariablen (also Zeiger auf Zeiger) ist wie eine normale Zuweisung einer Zeigervariablen mit =, die hier mit memcpy() sicher nicht gewollt ist. Dass das Beispiel nicht abstürzt, ist wohl eher Zufall ;-)

    Im C++ sollte man immer an das delete denken. Dabei kommt es darauf an, ob ein Array oder ein einzelner Typ beim new angegeben wurde. Je nachdem ist 'delete' oder 'delete []' zu verwenden.

    Die Struktur WLAN_RAW_DATA_LIST enthält keine Zeiger. Deshalb sollte man auch nicht beim Versuch, die Struktur im C# nachzubilden, einen Zeiger einbauen. Die Struktur enthält Daten, die im Speicher zusammenhängend sind. Da die Struktur eine dynamische Länge haben kann, muß man vorher die Größe des zu benötigten Speichers berechnen.

    Sollte eine Struktur nicht nur aus DWORDs bestehen, sondern auch BYTEs und größere Typen gemischt beinhalten, muß man das Alignment beachten. Dadurch kann theoretisch sizeof(MY_STRUCT) größer sein, als die Summe ihrer Member. Das Alignment sollte man jedoch nicht ändern, besonders, wenn Strukturen Modul-übergreifend verwendet werden. (Siehe Projekt-Einstellungen/C++/Codegenerierung/Strukturmemberausrichtung) Bei WLAN_RAW_DATA_LIST spielt das Alignment keine Rolle, da hier nur DWORDs verwendet werden und durch das Alignment keine Lücken in der Struktur entstehen können.

    Das Beispiel in der MSDN zu WLAN_RAW_DATA_LIST enthält in dwTotalSize 84. Das ist verwirrend, da meiner Meinung nach die resultierende Größe 68 ergibt.

    Bei der Beschreibung der PSD-Struktur wird gesagt, dass die Length = (Länge der Daten + 8) sein soll. Die PSD-Header-Angaben nehmen jedoch 10 Bytes ein. => ebenfalls komisch.

    Ich habe mal versucht, das Ganze nachzustellen. Auch mit mehreren PSD-Strukturen, also mit mehreren Blobs, funktioniert es, ERROR_SUCCESS.

    In C# müßte man wohl alle Felder nach und nach in eine List<byte> einfügen. Dabei könnte man für die DWORDs folgendes verwenden:

    uint totalSize = x;
    
    byteList.AddRange(BitConverter.GetBytes(totalSize));

    Den Zeiger auf ein Array von byteList.ToArray() würde man dann an WlanSetPsdIEDataList() übergeben.

    Ich hoffe, ich kann dir mit dem C++ etwas hilfreich sein und du bekommst wieder Lust am Projekt.

    // WifiDirect.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <wlanapi.h>
    
    struct BLOB_HEADER
    {
    	DWORD	dwOffset,
    			dwSize;
    };
    
    struct PSD
    {
    	BYTE	  Id;
    	BYTE	  Length;
    	BYTE	  OUI[3];
    	BYTE	  OUIType;
    	BYTE	  FormatIdentifierHash[4];
    	BYTE	  Data[230];	// Maximale Länge; Data kann kürzer sein.
    };
    
    int _tmain(int argc, _TCHAR* argv[]);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int size, BYTE * data);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5);
    void PrintResult(DWORD error);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	DWORD	ret,
    			usedVersion;
    	HANDLE	hWlan;
    
    	ret = WlanOpenHandle(2, NULL, &usedVersion, &hWlan);
    	if (ret != ERROR_SUCCESS)
    	{
    		PrintResult(ret);
    		return -1;
    	}
    
    	// Siehe https://docs.microsoft.com/de-de/windows/win32/api/wlanapi/nf-wlanapi-wlansetpsdiedatalist
    
    	int		size = sizeof(PSD);
    	wchar_t	* format = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    	PSD		* pPsd = new PSD;
    
    	memset(pPsd, 0, sizeof(PSD));
    	pPsd->Id = 221;
    	pPsd->Length = 10;	// 8; Die Länge soll PSD.Data + 8 sein. Die Felder in PSD vor PSD.Data sind jedoch 10 Bytes. ???
    	pPsd->OUI[0] = (BYTE)0x00;
    	pPsd->OUI[1] = (BYTE)0x50;
    	pPsd->OUI[2] = (BYTE)0xF2;
    	pPsd->OUIType = 6;
    	pPsd->FormatIdentifierHash[0] = 0xF8;
    	pPsd->FormatIdentifierHash[1] = 0xCB;
    	pPsd->FormatIdentifierHash[2] = 0x35;
    	pPsd->FormatIdentifierHash[3] = 0x15;
    
    	//BYTE	data[] = { (BYTE)0x00, (BYTE)0x01, (BYTE)0x02, (BYTE)0x03 };
    
    	//size = sizeof(data);
    	//ret = SetBlobs(hWlan, format, size, data);
    	ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd);
    	if (ret == ERROR_SUCCESS)
    	{
    		// Test mit mehreren Blobs (bis zu 5; DOT11_PSD_IE_MAX_ENTRY_NUMBER)
    		PSD	psd2,
    			psd3,
    			psd4;
    
    		memcpy(&psd2, pPsd, size);
    		memcpy(&psd3, pPsd, size);
    		memcpy(&psd4, pPsd, size);
    
    		// ERROR_SUCCESS
    	//	ret = SetBlobs(hWlan, format, size, data, size, data, 0, NULL, 0, NULL, 0, NULL);
    	//	ret = SetBlobs(hWlan, format, size, (BYTE *)&psd2, 0, NULL, 0, NULL, 0, NULL, 0, NULL);
    		ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd, size, (BYTE *)&psd2, size, (BYTE *)&psd3, size, (BYTE *)&psd4, 0, NULL);
    	}
    	delete pPsd;
    	WlanCloseHandle(hWlan, NULL);
    	PrintResult(ret);
    	return 0;
    }
    
    // Für genau einen Blob.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize, BYTE * data)
    {
    	// Ohne Blobs liefert WlanSetPsdIEDataList() auch ERROR_SUCCESS.
    /*	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[8];
    
    	pList->dwTotalSize = 8;
    	pList->dwNumberOfItems = 0;
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	PrintResult(ret);
    
    	delete[](BYTE *)pList;
    	return ret;
    */
    
    	if (!hWlan || dataSize <= 0 || dataSize > DOT11_PSD_IE_MAX_DATA_SIZE || !data)
    		return ERROR_INVALID_PARAMETER;
    
    	int	size = sizeof(WLAN_RAW_DATA_LIST) + dataSize;
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;	// Die Angabe im Beispiel der MSDN ist widersprüchlich, statt 84 sollte dort 68 (nach meiner Meinung) stehen.
    	pList->dwNumberOfItems = 1;
    	pList->DataList[0].dwDataSize = dataSize;
    	pList->DataList[0].dwDataOffset = 8;
    
    	memcpy((BYTE *)pList + sizeof(WLAN_RAW_DATA_LIST), data, dataSize);
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	delete [](BYTE *)pList;
    	return ret;
    }
    
    // Für 0 bis 5 Blobs.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5)
    {
    	if (!hWlan)
    		return ERROR_INVALID_PARAMETER;
    
    	DWORD	size = sizeof(BLOB_HEADER),
    			dataOffset = 0,
    			count = 0;
    
    	if (dataSize1 < 0 || dataSize1 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize1 > 0 && !data1)
    		return ERROR_INVALID_PARAMETER;
    	else if (dataSize1 > 0)
    	{
    		size += sizeof(BLOB_HEADER) + dataSize1;
    		dataOffset += sizeof(BLOB_HEADER);
    		count++;
    		if (dataSize2 < 0 || dataSize2 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize2 > 0 && !data2)
    			return ERROR_INVALID_PARAMETER;
    		else if (dataSize2 > 0)
    		{
    			size += sizeof(BLOB_HEADER) + dataSize2;
    			dataOffset += sizeof(BLOB_HEADER);
    			count++;
    			if (dataSize3 < 0 || dataSize3 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize3 > 0 && !data3)
    				return ERROR_INVALID_PARAMETER;
    			else if (dataSize3 > 0)
    			{
    				size += sizeof(BLOB_HEADER) + dataSize3;
    				dataOffset += sizeof(BLOB_HEADER);
    				count++;
    				if (dataSize4 < 0 || dataSize4 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize4 > 0 && !data4)
    					return ERROR_INVALID_PARAMETER;
    				else if (dataSize4 > 0)
    				{
    					size += sizeof(BLOB_HEADER) + dataSize4;
    					dataOffset += sizeof(BLOB_HEADER);
    					count++;
    					if (dataSize5 < 0 || dataSize5 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize5 > 0 && !data5)
    						return ERROR_INVALID_PARAMETER;
    					else if (dataSize5 > 0)
    					{
    						size += sizeof(BLOB_HEADER) + dataSize5;
    						dataOffset += sizeof(BLOB_HEADER);
    						count++;
    					}
    				}
    			}
    		}
    	}
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;
    	pList->dwNumberOfItems = count;
    
    	BLOB_HEADER	* pBlobHeader = (BLOB_HEADER *)&pList->DataList;
    	BYTE		* pData = (BYTE *)&pList->DataList + dataOffset;
    
    	if (count >= 1)
    	{
    		pBlobHeader->dwSize = dataSize1;
    		pBlobHeader->dwOffset = dataOffset;
    		memcpy(pData, data1, dataSize1);
    		if (count >= 2)
    		{
    			pBlobHeader++;
    			pData += dataSize1;
    			dataOffset -= sizeof(BLOB_HEADER);
    			dataOffset += dataSize1;
    			pBlobHeader->dwSize = dataSize2;
    			pBlobHeader->dwOffset = dataOffset;
    			memcpy(pData, data2, dataSize2);
    			if (count >= 3)
    			{
    				pBlobHeader++;
    				pData += dataSize2;
    				dataOffset -= sizeof(BLOB_HEADER);
    				dataOffset += dataSize2;
    				pBlobHeader->dwSize = dataSize3;
    				pBlobHeader->dwOffset = dataOffset;
    				memcpy(pData, data3, dataSize3);
    				if (count >= 4)
    				{
    					pBlobHeader++;
    					pData += dataSize3;
    					dataOffset -= sizeof(BLOB_HEADER);
    					dataOffset += dataSize3;
    					pBlobHeader->dwSize = dataSize4;
    					pBlobHeader->dwOffset = dataOffset;
    					memcpy(pData, data4, dataSize4);
    					if (count >= 5)
    					{
    						pBlobHeader++;
    						pData += dataSize4;
    						dataOffset -= sizeof(BLOB_HEADER);
    						dataOffset += dataSize4;
    						pBlobHeader->dwSize = dataSize5;
    						pBlobHeader->dwOffset = dataOffset;
    						memcpy(pData, data5, dataSize5);
    					}
    				}
    			}
    		}
    	}
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	// Da der Speicher für 'pList' als Array (von BYTEs) angefordert wurde, muß er auch als Array freigegeben werden.
    	delete[](BYTE *)pList;
    	return ret;
    }
    
    void PrintResult(DWORD error)
    {
    	switch (error)
    	{
    	case ERROR_SUCCESS:
    		puts("ERROR_SUCCESS");
    		break;
    	case ERROR_INVALID_PARAMETER:
    		puts("ERROR_INVALID_PARAMETER");
    		break;
    	case ERROR_NOT_ENOUGH_MEMORY:
    		puts("ERROR_NOT_ENOUGH_MEMORY");
    		break;
    	case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
    		puts("ERROR_REMOTE_SESSION_LIMIT_EXCEEDED");
    		break;
    	default:
    		printf("0x%08X\r\n", error);
    		break;
    	}
    	getchar();
    }

    Gruß,
    Heiko

    Samstag, 17. August 2019 13:07
  • Hallo Thomas,

    in deinem Beispiel schreibst du Speicher kaputt, ohne dass es auffällt. Besser wäre es so:

    DWORD SetIe(HANDLE hClient)
    {
    	DWORD dwResult = 0;
    	PWLAN_RAW_DATA_LIST rawDataList = new WLAN_RAW_DATA_LIST();
    	LPCWSTR formatData = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    
    	char ieData[] = { '\x00', '\x01', '\x02', '\x03' };
    
    	rawDataList->dwTotalSize = 16 + sizeof(ieData);
    	rawDataList->dwNumberOfItems = 1;
    	rawDataList->DataList[0].dwDataOffset = 8;
    	rawDataList->DataList[0].dwDataSize = sizeof(ieData);
    
    	char* buffer = new char[rawDataList->dwTotalSize];
    
    	// sizeof(&rawDataList) oder sizeof(rawDataList) würden nur 4 (bzw. 8 auf 64-Bit-OS) ergeben, da dies Zeiger sind.
    //	memcpy(&buffer, &rawDataList, sizeof(&rawDataList));
    	memcpy(buffer, rawDataList, sizeof(WLAN_RAW_DATA_LIST));
    
    	for (size_t i = 0, j = 16; i < sizeof(ieData); i++, j++)
    	{
    		buffer[j] = ieData[i];
    	}
    
    	// 'rawDataList' und 'buffer' sollten keine weitere Zuweisung erhalten, da ihr
    	// Speicher wieder freigegeben werden muß.
    //	rawDataList = (PWLAN_RAW_DATA_LIST)buffer;
    
    	DWORD	ret = WlanSetPsdIEDataList(hClient, formatData, (PWLAN_RAW_DATA_LIST)buffer, NULL);
    
    	delete []buffer;
    	delete rawDataList;
    
    //	return WlanSetPsdIEDataList(hClient, formatData, rawDataList, NULL);
    	return ret;
    }

    Es ist jedoch nicht nötig, zwei mal Speicher anzufordern und zu kopieren, siehe dazu meine andere Antwort.

    Gruß,
    Heiko

    Samstag, 17. August 2019 13:46

Alle Antworten

  • Ok jetzt verstehe ich wie dumm meine frage ist und wie wenig ich von C++ verstehe.

    Man reserviert Arbeitsspeicher und schreibt den struct der die Größe und die Positionen den Daten angibt am Anfang des Datensatzes gefolgt von den Daten selbst. In C# wäre das ein einfaches byte[] wobei der type DWORD 4 bytes einnimmt. In C++ macht das sicherlich sinn da man dann nur einen reservierten Bereich hat den man wieder freigeben muss. Ist eigentlich nicht anderes als ein protokolierten Stream zu lesen. Hätte ich auch früher drauf kommen können 


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Donnerstag, 1. August 2019 21:56
  • Hier auch noch der Code. Sicherlich könnte man das besser machen. Für meinen ersten versuch in C++ reicht mir das

    int SetIe(HANDLE hClient)
    {
    	DWORD dwResult = 0;
    	PWLAN_RAW_DATA_LIST rawDataList = new WLAN_RAW_DATA_LIST();
    	LPCWSTR formatData = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    
    	char ieData[] = { '\x00', '\x01', '\x02', '\x03' };
    
    	rawDataList->dwTotalSize = 16 + sizeof(ieData);
    	rawDataList->dwNumberOfItems = 1;
    	rawDataList->DataList[0].dwDataOffset = 8;
    	rawDataList->DataList[0].dwDataSize = sizeof(ieData);
    
    	char* buffer = new char[rawDataList->dwTotalSize];
    	memcpy(&buffer, &rawDataList, sizeof(&rawDataList));
    
    	for (size_t i = 0, j = 16; i < sizeof(ieData); i++, j++)
    	{
    		buffer[j] = ieData[i];
    	}
    
    	rawDataList = (PWLAN_RAW_DATA_LIST)buffer;
    	
    	return WlanSetPsdIEDataList(hClient, formatData, rawDataList, NULL);
    }


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Donnerstag, 15. August 2019 22:53
  • Hallo Thomas,

    dumme Fragen gibt es nicht. Man wird doch wohl untereinander laut denken dürfen ;-)

    Im C++ Code bringst du einiges durcheinander. Ein memcpy() mit den Adressen von Zeigervariablen (also Zeiger auf Zeiger) ist wie eine normale Zuweisung einer Zeigervariablen mit =, die hier mit memcpy() sicher nicht gewollt ist. Dass das Beispiel nicht abstürzt, ist wohl eher Zufall ;-)

    Im C++ sollte man immer an das delete denken. Dabei kommt es darauf an, ob ein Array oder ein einzelner Typ beim new angegeben wurde. Je nachdem ist 'delete' oder 'delete []' zu verwenden.

    Die Struktur WLAN_RAW_DATA_LIST enthält keine Zeiger. Deshalb sollte man auch nicht beim Versuch, die Struktur im C# nachzubilden, einen Zeiger einbauen. Die Struktur enthält Daten, die im Speicher zusammenhängend sind. Da die Struktur eine dynamische Länge haben kann, muß man vorher die Größe des zu benötigten Speichers berechnen.

    Sollte eine Struktur nicht nur aus DWORDs bestehen, sondern auch BYTEs und größere Typen gemischt beinhalten, muß man das Alignment beachten. Dadurch kann theoretisch sizeof(MY_STRUCT) größer sein, als die Summe ihrer Member. Das Alignment sollte man jedoch nicht ändern, besonders, wenn Strukturen Modul-übergreifend verwendet werden. (Siehe Projekt-Einstellungen/C++/Codegenerierung/Strukturmemberausrichtung) Bei WLAN_RAW_DATA_LIST spielt das Alignment keine Rolle, da hier nur DWORDs verwendet werden und durch das Alignment keine Lücken in der Struktur entstehen können.

    Das Beispiel in der MSDN zu WLAN_RAW_DATA_LIST enthält in dwTotalSize 84. Das ist verwirrend, da meiner Meinung nach die resultierende Größe 68 ergibt.

    Bei der Beschreibung der PSD-Struktur wird gesagt, dass die Length = (Länge der Daten + 8) sein soll. Die PSD-Header-Angaben nehmen jedoch 10 Bytes ein. => ebenfalls komisch.

    Ich habe mal versucht, das Ganze nachzustellen. Auch mit mehreren PSD-Strukturen, also mit mehreren Blobs, funktioniert es, ERROR_SUCCESS.

    In C# müßte man wohl alle Felder nach und nach in eine List<byte> einfügen. Dabei könnte man für die DWORDs folgendes verwenden:

    uint totalSize = x;
    
    byteList.AddRange(BitConverter.GetBytes(totalSize));

    Den Zeiger auf ein Array von byteList.ToArray() würde man dann an WlanSetPsdIEDataList() übergeben.

    Ich hoffe, ich kann dir mit dem C++ etwas hilfreich sein und du bekommst wieder Lust am Projekt.

    // WifiDirect.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <wlanapi.h>
    
    struct BLOB_HEADER
    {
    	DWORD	dwOffset,
    			dwSize;
    };
    
    struct PSD
    {
    	BYTE	  Id;
    	BYTE	  Length;
    	BYTE	  OUI[3];
    	BYTE	  OUIType;
    	BYTE	  FormatIdentifierHash[4];
    	BYTE	  Data[230];	// Maximale Länge; Data kann kürzer sein.
    };
    
    int _tmain(int argc, _TCHAR* argv[]);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int size, BYTE * data);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5);
    void PrintResult(DWORD error);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	DWORD	ret,
    			usedVersion;
    	HANDLE	hWlan;
    
    	ret = WlanOpenHandle(2, NULL, &usedVersion, &hWlan);
    	if (ret != ERROR_SUCCESS)
    	{
    		PrintResult(ret);
    		return -1;
    	}
    
    	// Siehe https://docs.microsoft.com/de-de/windows/win32/api/wlanapi/nf-wlanapi-wlansetpsdiedatalist
    
    	int		size = sizeof(PSD);
    	wchar_t	* format = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    	PSD		* pPsd = new PSD;
    
    	memset(pPsd, 0, sizeof(PSD));
    	pPsd->Id = 221;
    	pPsd->Length = 10;	// 8; Die Länge soll PSD.Data + 8 sein. Die Felder in PSD vor PSD.Data sind jedoch 10 Bytes. ???
    	pPsd->OUI[0] = (BYTE)0x00;
    	pPsd->OUI[1] = (BYTE)0x50;
    	pPsd->OUI[2] = (BYTE)0xF2;
    	pPsd->OUIType = 6;
    	pPsd->FormatIdentifierHash[0] = 0xF8;
    	pPsd->FormatIdentifierHash[1] = 0xCB;
    	pPsd->FormatIdentifierHash[2] = 0x35;
    	pPsd->FormatIdentifierHash[3] = 0x15;
    
    	//BYTE	data[] = { (BYTE)0x00, (BYTE)0x01, (BYTE)0x02, (BYTE)0x03 };
    
    	//size = sizeof(data);
    	//ret = SetBlobs(hWlan, format, size, data);
    	ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd);
    	if (ret == ERROR_SUCCESS)
    	{
    		// Test mit mehreren Blobs (bis zu 5; DOT11_PSD_IE_MAX_ENTRY_NUMBER)
    		PSD	psd2,
    			psd3,
    			psd4;
    
    		memcpy(&psd2, pPsd, size);
    		memcpy(&psd3, pPsd, size);
    		memcpy(&psd4, pPsd, size);
    
    		// ERROR_SUCCESS
    	//	ret = SetBlobs(hWlan, format, size, data, size, data, 0, NULL, 0, NULL, 0, NULL);
    	//	ret = SetBlobs(hWlan, format, size, (BYTE *)&psd2, 0, NULL, 0, NULL, 0, NULL, 0, NULL);
    		ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd, size, (BYTE *)&psd2, size, (BYTE *)&psd3, size, (BYTE *)&psd4, 0, NULL);
    	}
    	delete pPsd;
    	WlanCloseHandle(hWlan, NULL);
    	PrintResult(ret);
    	return 0;
    }
    
    // Für genau einen Blob.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize, BYTE * data)
    {
    	// Ohne Blobs liefert WlanSetPsdIEDataList() auch ERROR_SUCCESS.
    /*	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[8];
    
    	pList->dwTotalSize = 8;
    	pList->dwNumberOfItems = 0;
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	PrintResult(ret);
    
    	delete[](BYTE *)pList;
    	return ret;
    */
    
    	if (!hWlan || dataSize <= 0 || dataSize > DOT11_PSD_IE_MAX_DATA_SIZE || !data)
    		return ERROR_INVALID_PARAMETER;
    
    	int	size = sizeof(WLAN_RAW_DATA_LIST) + dataSize;
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;	// Die Angabe im Beispiel der MSDN ist widersprüchlich, statt 84 sollte dort 68 (nach meiner Meinung) stehen.
    	pList->dwNumberOfItems = 1;
    	pList->DataList[0].dwDataSize = dataSize;
    	pList->DataList[0].dwDataOffset = 8;
    
    	memcpy((BYTE *)pList + sizeof(WLAN_RAW_DATA_LIST), data, dataSize);
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	delete [](BYTE *)pList;
    	return ret;
    }
    
    // Für 0 bis 5 Blobs.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5)
    {
    	if (!hWlan)
    		return ERROR_INVALID_PARAMETER;
    
    	DWORD	size = sizeof(BLOB_HEADER),
    			dataOffset = 0,
    			count = 0;
    
    	if (dataSize1 < 0 || dataSize1 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize1 > 0 && !data1)
    		return ERROR_INVALID_PARAMETER;
    	else if (dataSize1 > 0)
    	{
    		size += sizeof(BLOB_HEADER) + dataSize1;
    		dataOffset += sizeof(BLOB_HEADER);
    		count++;
    		if (dataSize2 < 0 || dataSize2 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize2 > 0 && !data2)
    			return ERROR_INVALID_PARAMETER;
    		else if (dataSize2 > 0)
    		{
    			size += sizeof(BLOB_HEADER) + dataSize2;
    			dataOffset += sizeof(BLOB_HEADER);
    			count++;
    			if (dataSize3 < 0 || dataSize3 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize3 > 0 && !data3)
    				return ERROR_INVALID_PARAMETER;
    			else if (dataSize3 > 0)
    			{
    				size += sizeof(BLOB_HEADER) + dataSize3;
    				dataOffset += sizeof(BLOB_HEADER);
    				count++;
    				if (dataSize4 < 0 || dataSize4 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize4 > 0 && !data4)
    					return ERROR_INVALID_PARAMETER;
    				else if (dataSize4 > 0)
    				{
    					size += sizeof(BLOB_HEADER) + dataSize4;
    					dataOffset += sizeof(BLOB_HEADER);
    					count++;
    					if (dataSize5 < 0 || dataSize5 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize5 > 0 && !data5)
    						return ERROR_INVALID_PARAMETER;
    					else if (dataSize5 > 0)
    					{
    						size += sizeof(BLOB_HEADER) + dataSize5;
    						dataOffset += sizeof(BLOB_HEADER);
    						count++;
    					}
    				}
    			}
    		}
    	}
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;
    	pList->dwNumberOfItems = count;
    
    	BLOB_HEADER	* pBlobHeader = (BLOB_HEADER *)&pList->DataList;
    	BYTE		* pData = (BYTE *)&pList->DataList + dataOffset;
    
    	if (count >= 1)
    	{
    		pBlobHeader->dwSize = dataSize1;
    		pBlobHeader->dwOffset = dataOffset;
    		memcpy(pData, data1, dataSize1);
    		if (count >= 2)
    		{
    			pBlobHeader++;
    			pData += dataSize1;
    			dataOffset -= sizeof(BLOB_HEADER);
    			dataOffset += dataSize1;
    			pBlobHeader->dwSize = dataSize2;
    			pBlobHeader->dwOffset = dataOffset;
    			memcpy(pData, data2, dataSize2);
    			if (count >= 3)
    			{
    				pBlobHeader++;
    				pData += dataSize2;
    				dataOffset -= sizeof(BLOB_HEADER);
    				dataOffset += dataSize2;
    				pBlobHeader->dwSize = dataSize3;
    				pBlobHeader->dwOffset = dataOffset;
    				memcpy(pData, data3, dataSize3);
    				if (count >= 4)
    				{
    					pBlobHeader++;
    					pData += dataSize3;
    					dataOffset -= sizeof(BLOB_HEADER);
    					dataOffset += dataSize3;
    					pBlobHeader->dwSize = dataSize4;
    					pBlobHeader->dwOffset = dataOffset;
    					memcpy(pData, data4, dataSize4);
    					if (count >= 5)
    					{
    						pBlobHeader++;
    						pData += dataSize4;
    						dataOffset -= sizeof(BLOB_HEADER);
    						dataOffset += dataSize4;
    						pBlobHeader->dwSize = dataSize5;
    						pBlobHeader->dwOffset = dataOffset;
    						memcpy(pData, data5, dataSize5);
    					}
    				}
    			}
    		}
    	}
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	// Da der Speicher für 'pList' als Array (von BYTEs) angefordert wurde, muß er auch als Array freigegeben werden.
    	delete[](BYTE *)pList;
    	return ret;
    }
    
    void PrintResult(DWORD error)
    {
    	switch (error)
    	{
    	case ERROR_SUCCESS:
    		puts("ERROR_SUCCESS");
    		break;
    	case ERROR_INVALID_PARAMETER:
    		puts("ERROR_INVALID_PARAMETER");
    		break;
    	case ERROR_NOT_ENOUGH_MEMORY:
    		puts("ERROR_NOT_ENOUGH_MEMORY");
    		break;
    	case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
    		puts("ERROR_REMOTE_SESSION_LIMIT_EXCEEDED");
    		break;
    	default:
    		printf("0x%08X\r\n", error);
    		break;
    	}
    	getchar();
    }

    Gruß,
    Heiko

    Samstag, 17. August 2019 13:07
  • Hallo Thomas,

    in deinem Beispiel schreibst du Speicher kaputt, ohne dass es auffällt. Besser wäre es so:

    DWORD SetIe(HANDLE hClient)
    {
    	DWORD dwResult = 0;
    	PWLAN_RAW_DATA_LIST rawDataList = new WLAN_RAW_DATA_LIST();
    	LPCWSTR formatData = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    
    	char ieData[] = { '\x00', '\x01', '\x02', '\x03' };
    
    	rawDataList->dwTotalSize = 16 + sizeof(ieData);
    	rawDataList->dwNumberOfItems = 1;
    	rawDataList->DataList[0].dwDataOffset = 8;
    	rawDataList->DataList[0].dwDataSize = sizeof(ieData);
    
    	char* buffer = new char[rawDataList->dwTotalSize];
    
    	// sizeof(&rawDataList) oder sizeof(rawDataList) würden nur 4 (bzw. 8 auf 64-Bit-OS) ergeben, da dies Zeiger sind.
    //	memcpy(&buffer, &rawDataList, sizeof(&rawDataList));
    	memcpy(buffer, rawDataList, sizeof(WLAN_RAW_DATA_LIST));
    
    	for (size_t i = 0, j = 16; i < sizeof(ieData); i++, j++)
    	{
    		buffer[j] = ieData[i];
    	}
    
    	// 'rawDataList' und 'buffer' sollten keine weitere Zuweisung erhalten, da ihr
    	// Speicher wieder freigegeben werden muß.
    //	rawDataList = (PWLAN_RAW_DATA_LIST)buffer;
    
    	DWORD	ret = WlanSetPsdIEDataList(hClient, formatData, (PWLAN_RAW_DATA_LIST)buffer, NULL);
    
    	delete []buffer;
    	delete rawDataList;
    
    //	return WlanSetPsdIEDataList(hClient, formatData, rawDataList, NULL);
    	return ret;
    }

    Es ist jedoch nicht nötig, zwei mal Speicher anzufordern und zu kopieren, siehe dazu meine andere Antwort.

    Gruß,
    Heiko

    Samstag, 17. August 2019 13:46
  • Hab' noch was korrigiert. Funktioniert nun auch mit mehreren Blobs.

    Gruß,
    Heiko

    Samstag, 17. August 2019 14:38
  • Hallo Heiko,

    danke für deine ausführliche Antwort und die Korrektur meiner Funktion, ich werde mir das genauer ansehen.

    Soweit hat mein Code oben funktioniert. Ich konnte das Ergebnis auch mit Wireshark sehen. Leider ist mir erst dann aufgefallen das der OUI Typ 06 verwendet wird (wie in der Doku auch beschrieben wird). Ich brauchen aber den OUI Typ 04. Mit dieser Funktion lässt sich das nicht erreichen. Ich habe auch keine andere Funktion gefunden mit der man das erreichen könnte.

    Jetzt habe ich mir den ESP32 von Espressif gekauft und mein erstes Ziel erreicht. Nun arbeite mich mit dem open Book von Rheinwerk C von A-Z in C ein. In ein paar Tagen verstehe ich das ganze sicherlich besser.


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Samstag, 17. August 2019 18:46
  • Hallo Thomas,

    da hier im Forum Antworten vom Wochenende verlorengingen, poste ich nochmal den Code. Den Text habe ich nicht mehr, den hattest du ja schon zur Kenntnis genommen.

    DWORD SetIe(HANDLE hClient)
    {
    	DWORD dwResult = 0;
    	PWLAN_RAW_DATA_LIST rawDataList = new WLAN_RAW_DATA_LIST();
    	LPCWSTR formatData = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    
    	char ieData[] = { '\x00', '\x01', '\x02', '\x03' };
    
    	rawDataList->dwTotalSize = 16 + sizeof(ieData);
    	rawDataList->dwNumberOfItems = 1;
    	rawDataList->DataList[0].dwDataOffset = 8;
    	rawDataList->DataList[0].dwDataSize = sizeof(ieData);
    
    	char* buffer = new char[rawDataList->dwTotalSize];
    
    	// sizeof(&rawDataList) oder sizeof(rawDataList) würden nur 4 (bzw. 8 auf 64-Bit-OS) ergeben, da dies Zeiger sind.
    //	memcpy(&buffer, &rawDataList, sizeof(&rawDataList));
    	memcpy(buffer, rawDataList, sizeof(WLAN_RAW_DATA_LIST));
    
    	for (size_t i = 0, j = 16; i < sizeof(ieData); i++, j++)
    	{
    		buffer[j] = ieData[i];
    	}
    
    	// 'rawDataList' und 'buffer' sollten keine weitere Zuweisung erhalten, da ihr
    	// speicher wieder freigegeben werden muß.
    //	rawDataList = (PWLAN_RAW_DATA_LIST)buffer;
    
    	DWORD	ret = WlanSetPsdIEDataList(hClient, formatData, (PWLAN_RAW_DATA_LIST)buffer, NULL);
    
    	delete []buffer;
    	delete rawDataList;
    
    //	return WlanSetPsdIEDataList(hClient, formatData, rawDataList, NULL);
    	return ret;
    }
    // WifiDirect.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <wlanapi.h>
    
    struct BLOB_HEADER
    {
    	DWORD	dwOffset,
    			dwSize;
    };
    
    struct PSD
    {
    	BYTE	  Id;
    	BYTE	  Length;
    	BYTE	  OUI[3];
    	BYTE	  OUIType;
    	BYTE	  FormatIdentifierHash[4];
    	BYTE	  Data[230];	// Maximale Länge; Data kann kürzer sein.
    };
    
    int _tmain(int argc, _TCHAR* argv[]);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int size, BYTE * data);
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5);
    void PrintResult(DWORD error);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	DWORD	ret,
    			usedVersion;
    	HANDLE	hWlan;
    
    	ret = WlanOpenHandle(2, NULL, &usedVersion, &hWlan);
    	if (ret != ERROR_SUCCESS)
    	{
    		PrintResult(ret);
    		return -1;
    	}
    	// Siehe https://docs.microsoft.com/de-de/windows/win32/api/wlanapi/nf-wlanapi-wlansetpsdiedatalist
    
    	int		size = sizeof(PSD);
    	wchar_t	* format = L"http://schemas.xmlsoaps.org/ws/2004/10/discovery";
    	PSD		* pPsd = new PSD;
    
    	memset(pPsd, 0, sizeof(PSD));
    	pPsd->Id = 221;
    	pPsd->Length = 10;	// 8; Die Länge soll PSD.Data + 8 sein. Die Felder in PSD vor PSD.Data sind jedoch 10 Bytes. ???
    	pPsd->OUI[0] = (BYTE)0x00;
    	pPsd->OUI[1] = (BYTE)0x50;
    	pPsd->OUI[2] = (BYTE)0xF2;
    	pPsd->OUIType = 6;
    	pPsd->FormatIdentifierHash[0] = 0xF8;
    	pPsd->FormatIdentifierHash[1] = 0xCB;
    	pPsd->FormatIdentifierHash[2] = 0x35;
    	pPsd->FormatIdentifierHash[3] = 0x15;
    
    	//BYTE	data[] = { (BYTE)0x00, (BYTE)0x01, (BYTE)0x02, (BYTE)0x03 };
    
    	//size = sizeof(data);
    	//ret = SetBlobs(hWlan, format, size, data);
    	ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd);
    	if (ret == ERROR_SUCCESS)
    	{
    		// Test mit mehreren Blobs (bis zu 5; DOT11_PSD_IE_MAX_ENTRY_NUMBER)
    		PSD	psd2,
    			psd3,
    			psd4;
    
    		memcpy(&psd2, pPsd, size);
    		memcpy(&psd3, pPsd, size);
    		memcpy(&psd4, pPsd, size);
    
    		// ERROR_SUCCESS
    	//	ret = SetBlobs(hWlan, format, size, data, size, data, 0, NULL, 0, NULL, 0, NULL);
    	//	ret = SetBlobs(hWlan, format, size, (BYTE *)&psd2, 0, NULL, 0, NULL, 0, NULL, 0, NULL);
    		ret = SetBlobs(hWlan, format, size, (BYTE *)pPsd, size, (BYTE *)&psd2, size, (BYTE *)&psd3, size, (BYTE *)&psd4, 0, NULL);
    	}
    	delete pPsd;
    	WlanCloseHandle(hWlan, NULL);
    	PrintResult(ret);
    	return 0;
    }
    
    // Für genau einen Blob.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize, BYTE * data)
    {
    	// Ohne Blobs liefert WlanSetPsdIEDataList() auch ERROR_SUCCESS.
    /*	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[8];
    
    	pList->dwTotalSize = 8;
    	pList->dwNumberOfItems = 0;
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	PrintResult(ret);
    
    	delete[](BYTE *)pList;
    	return ret;
    */
    
    	if (!hWlan || dataSize <= 0 || dataSize > DOT11_PSD_IE_MAX_DATA_SIZE || !data)
    		return ERROR_INVALID_PARAMETER;
    
    	int	size = sizeof(WLAN_RAW_DATA_LIST) + dataSize;
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;	// Die Angabe im Beispiel der MSDN ist widersprüchlich, statt 84 sollte dort 68 (nach meiner Meinung) stehen.
    	pList->dwNumberOfItems = 1;
    	pList->DataList[0].dwDataSize = dataSize;
    	pList->DataList[0].dwDataOffset = 8;
    
    	memcpy((BYTE *)pList + sizeof(WLAN_RAW_DATA_LIST), data, dataSize);
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	delete [](BYTE *)pList;
    	return ret;
    }
    
    // Für 0 bis 5 Blobs.
    DWORD SetBlobs(HANDLE hWlan, wchar_t * format, int dataSize1, BYTE * data1, int dataSize2, BYTE * data2, int dataSize3, BYTE * data3, int dataSize4, BYTE * data4, int dataSize5, BYTE * data5)
    {
    	if (!hWlan)
    		return ERROR_INVALID_PARAMETER;
    
    	DWORD	size = sizeof(BLOB_HEADER),
    			dataOffset = 0,
    			count = 0;
    
    	if (dataSize1 < 0 || dataSize1 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize1 > 0 && !data1)
    		return ERROR_INVALID_PARAMETER;
    	else if (dataSize1 > 0)
    	{
    		size += sizeof(BLOB_HEADER) + dataSize1;
    		dataOffset += sizeof(BLOB_HEADER);
    		count++;
    		if (dataSize2 < 0 || dataSize2 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize2 > 0 && !data2)
    			return ERROR_INVALID_PARAMETER;
    		else if (dataSize2 > 0)
    		{
    			size += sizeof(BLOB_HEADER) + dataSize2;
    			dataOffset += sizeof(BLOB_HEADER);
    			count++;
    			if (dataSize3 < 0 || dataSize3 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize3 > 0 && !data3)
    				return ERROR_INVALID_PARAMETER;
    			else if (dataSize3 > 0)
    			{
    				size += sizeof(BLOB_HEADER) + dataSize3;
    				dataOffset += sizeof(BLOB_HEADER);
    				count++;
    				if (dataSize4 < 0 || dataSize4 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize4 > 0 && !data4)
    					return ERROR_INVALID_PARAMETER;
    				else if (dataSize4 > 0)
    				{
    					size += sizeof(BLOB_HEADER) + dataSize4;
    					dataOffset += sizeof(BLOB_HEADER);
    					count++;
    					if (dataSize5 < 0 || dataSize5 > DOT11_PSD_IE_MAX_DATA_SIZE || dataSize5 > 0 && !data5)
    						return ERROR_INVALID_PARAMETER;
    					else if (dataSize5 > 0)
    					{
    						size += sizeof(BLOB_HEADER) + dataSize5;
    						dataOffset += sizeof(BLOB_HEADER);
    						count++;
    					}
    				}
    			}
    		}
    	}
    
    	WLAN_RAW_DATA_LIST	* pList = (WLAN_RAW_DATA_LIST *)new BYTE[size];
    
    	pList->dwTotalSize = size;
    	pList->dwNumberOfItems = count;
    
    	BLOB_HEADER	* pBlobHeader = (BLOB_HEADER *)&pList->DataList;
    	BYTE		* pData = (BYTE *)&pList->DataList + dataOffset;
    
    	if (count >= 1)
    	{
    		pBlobHeader->dwSize = dataSize1;
    		pBlobHeader->dwOffset = dataOffset;
    		memcpy(pData, data1, dataSize1);
    		if (count >= 2)
    		{
    			pBlobHeader++;
    			pData += dataSize1;
    			dataOffset -= sizeof(BLOB_HEADER);
    			dataOffset += dataSize1;
    			pBlobHeader->dwSize = dataSize2;
    			pBlobHeader->dwOffset = dataOffset;
    			memcpy(pData, data2, dataSize2);
    			if (count >= 3)
    			{
    				pBlobHeader++;
    				pData += dataSize2;
    				dataOffset -= sizeof(BLOB_HEADER);
    				dataOffset += dataSize2;
    				pBlobHeader->dwSize = dataSize3;
    				pBlobHeader->dwOffset = dataOffset;
    				memcpy(pData, data3, dataSize3);
    				if (count >= 4)
    				{
    					pBlobHeader++;
    					pData += dataSize3;
    					dataOffset -= sizeof(BLOB_HEADER);
    					dataOffset += dataSize3;
    					pBlobHeader->dwSize = dataSize4;
    					pBlobHeader->dwOffset = dataOffset;
    					memcpy(pData, data4, dataSize4);
    					if (count >= 5)
    					{
    						pBlobHeader++;
    						pData += dataSize4;
    						dataOffset -= sizeof(BLOB_HEADER);
    						dataOffset += dataSize4;
    						pBlobHeader->dwSize = dataSize5;
    						pBlobHeader->dwOffset = dataOffset;
    						memcpy(pData, data5, dataSize5);
    					}
    				}
    			}
    		}
    	}
    
    	DWORD	ret = WlanSetPsdIEDataList(hWlan, format, pList, NULL);
    
    	// Da der Speicher für 'pList' als Array (von BYTEs) angefordert wurde, muß er auch als Array freigegeben werden.
    	delete[](BYTE *)pList;
    	return ret;
    }
    
    void PrintResult(DWORD error)
    {
    	switch (error)
    	{
    	case ERROR_SUCCESS:
    		puts("ERROR_SUCCESS");
    		break;
    	case ERROR_INVALID_PARAMETER:
    		puts("ERROR_INVALID_PARAMETER");
    		break;
    	case ERROR_NOT_ENOUGH_MEMORY:
    		puts("ERROR_NOT_ENOUGH_MEMORY");
    		break;
    	case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED:
    		puts("ERROR_REMOTE_SESSION_LIMIT_EXCEEDED");
    		break;
    	default:
    		printf("0x%08X\r\n", error);
    		break;
    	}
    	getchar();
    }


    Gruß,
    Heiko

    Dienstag, 20. August 2019 15:27
  • Hallo Heiko,

    ganz richtig ist dein Beispiel nicht. Man kann keine OUI setzen, sie die wird von MS festgelegt und sie ist immer 0x0050F206. Die Msg wir nur an das IE angehängt


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings


    Dienstag, 20. August 2019 20:25
  • Hallo Thomas,

    eigentlich ging es mir nur darum, zu zeigen, wie man die WLAN_RAW_DATA_LIST-Struktur im C++ dynamisch aufbauen und füllen kann. Da bei mir anfangs WlanSetPsdIEDataList() nicht ERROR_SUCCESS zurück gab, dachte ich, man müsste auch die PSD-Struktur benutzen und tippte einfach ab, was auf der MSDN-Seite steht. Letzten Endes war es dann aber egal, was man als Blob übergibt, oder ob die PSD-Struktur richtig gefüllt ist, es hätte auch mit 0123 funktioniert.

    Gruß,

    Heiko

    Dienstag, 20. August 2019 21:15
  • Dein Beispiel ist auch sehr gut. Wollte das nur klar stellen.


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Dienstag, 20. August 2019 21:25