wlanapi.h) (WlanGetProfile 函数

WlanGetProfile 函数检索有关指定无线配置文件的所有信息。

语法

DWORD WlanGetProfile(
  [in]                HANDLE     hClientHandle,
  [in]                const GUID *pInterfaceGuid,
  [in]                LPCWSTR    strProfileName,
  [in]                PVOID      pReserved,
  [out]               LPWSTR     *pstrProfileXml,
  [in, out, optional] DWORD      *pdwFlags,
  [out, optional]     DWORD      *pdwGrantedAccess
);

参数

[in] hClientHandle

客户端的会话句柄,由先前对 WlanOpenHandle 函数的调用获取。

[in] pInterfaceGuid

无线接口的 GUID。

可以使用 WlanEnumInterfaces 函数检索本地计算机上无线接口的 GUID 列表。

[in] strProfileName

配置文件的名称。 配置文件名称区分大小写。 此字符串必须以 NULL 结尾。 配置文件名称的最大长度为 255 个字符。 这意味着此字符串(包括 NULL 终止符)的最大长度为 256 个字符。

带 SP3 的 Windows XP 和适用于 SP2 的 Windows XP 无线 LAN API: 配置文件的名称自动派生自网络的 SSID。 对于基础结构网络配置文件,配置文件的名称是网络的 SSID。 对于即席网络配置文件,配置文件的名称是即席网络的 SSID,后跟 -adhoc

[in] pReserved

保留供将来使用。 必须设置为 NULL

[out] pstrProfileXml

一个字符串,表示查询的配置文件的 XML 表示形式。 没有预定义的最大字符串长度。

[in, out, optional] pdwFlags

输入时,指向地址位置的指针,用于提供有关请求的其他信息。 如果此参数在输入时为 NULL ,则不会返回有关配置文件标志的信息。 输出时,指向用于接收配置文件标志的地址位置的指针。

带 SP3 的 Windows XP 和适用于 SP2 的 Windows XP 无线 LAN API: 不支持每用户配置文件。 将此参数设置为 NULL

pdwFlags 参数可以指向包含以下值的地址位置:

含义
WLAN_PROFILE_GET_PLAINTEXT_KEY
输入时,此标志指示调用方希望从无线配置文件中检索纯文本键。 如果调用线程具有所需的权限,则 WlanGetProfile 函数在 pstrProfileXml 参数指向的缓冲区中返回的配置文件的 keyMaterial 元素中返回纯文本键。

要使 WlanGetProfile 调用返回纯文本键,必须在调用线程上设置WLAN_SECURABLE_OBJECT枚举类型的wlan_secure_get_plaintext_key权限。 DACL 还必须包含向调用线程的访问令牌授予 WLAN_READ_ACCESS 权限的 ACE。 默认情况下,仅允许本地计算机上的 Administrators 组的成员具有检索纯文本密钥的权限。

如果调用线程缺少所需的权限,WlanGetProfile 函数将在 pstrProfileXml 参数指向的缓冲区中返回的配置文件的 keyMaterial 元素中返回加密密钥。 如果调用线程缺少所需的权限,则不会返回任何错误。

Windows 7: 输入时传递的此标志是 Windows 7 及更高版本上添加的本机无线 API 的扩展。 pdwFlags 参数是 Windows 7 及更高版本上的__inout_opt参数。

WLAN_PROFILE_GROUP_POLICY
WlanGetProfile 调用成功时输出时,此标志指示此配置文件是由组策略创建的。 组策略配置文件是只读的。 不能更改配置文件的内容和首选项顺序。
WLAN_PROFILE_USER
WlanGetProfile 调用成功时输出时,此标志指示配置文件是调用线程所在的上下文中的特定用户的用户配置文件。 如果未设置,则此配置文件为所有用户配置文件。

[out, optional] pdwGrantedAccess

所有用户配置文件的访问掩码。

含义
WLAN_READ_ACCESS
用户可以查看配置文件的内容。
WLAN_EXECUTE_ACCESS
用户具有读取访问权限,用户还可以使用配置文件连接到网络或从网络断开连接。 如果用户具有WLAN_EXECUTE_ACCESS,则该用户也具有WLAN_READ_ACCESS。
WLAN_WRITE_ACCESS
用户具有执行访问权限,用户还可以修改配置文件的内容或删除配置文件。 如果用户具有WLAN_WRITE_ACCESS,则该用户还具有WLAN_EXECUTE_ACCESS和WLAN_READ_ACCESS。

返回值

如果函数成功,则返回值为 ERROR_SUCCESS。

如果函数失败,则返回值可能是以下返回代码之一。

返回代码 说明
ERROR_ACCESS_DENIED
调用方没有足够的权限。 如果 pstrProfileXml 参数指定了一个全用户配置文件,但调用方对该配置文件没有读取访问权限,则返回此错误。
ERROR_INVALID_HANDLE
句柄无效。 如果在句柄表中找不到 hClientHandle 参数中指定的句柄,则返回此错误。
ERROR_INVALID_PARAMETER
参数不正确。 如果出现以下任一情况,则返回此错误:
  • hClientHandleNULL
  • pInterfaceGuidNULL
  • pstrProfileXmlNULL
  • pReserved 不为 NULL
ERROR_NOT_ENOUGH_MEMORY
没有足够的存储空间可用于处理此命令。 如果系统无法为配置文件分配内存,则返回此错误。
ERROR_NOT_FOUND
找不到 strProfileName 指定的配置文件。
其他
各种 RPC 和其他错误代码。 使用 FormatMessage 获取返回错误的消息字符串。

注解

如果 WlanGetProfile 函数成功,则会在 pstrProfileXml 参数指向的缓冲区中返回无线配置文件。 缓冲区包含一个字符串,该字符串是查询的配置文件的 XML 表示形式。 有关无线配置文件的 XML 表示形式的说明,请参阅 WLAN_profile 架构

调用方负责调用 WlanFreeMemory 函数,以便在不再需要缓冲区时释放 pstrProfileXml 参数为缓冲区指针分配的内存。

如果 pstrProfileXml 指定了一个全用户配置文件, 则 WlanGetProfile 调用方必须对该配置文件具有读取访问权限。 否则, WlanGetProfile 调用将失败,返回值为 ERROR_ACCESS_DENIED。 使用 WlanSetProfileWlanSaveTemporaryProfile 创建或保存配置文件时,将建立对所有用户配置文件的权限。

Windows 7:

如果在输入时 pdwFlags 参数指向的值中设置WLAN_PROFILE_GET_PLAINTEXT_KEY标志来调用 WlanGetProfile 函数,则以纯文本形式请求 pstrProfileXml 指向的配置文件架构中返回的 keyMaterial 元素。

对于 WEP 密钥,创建或更新配置文件时,可以使用 5 个 ASCII 字符或 10 个十六进制字符来设置纯文本键。 但是,无论原始输入用于创建配置文件,WEP 配置文件都将在密钥中保存 10 个十六进制字符。 因此,在 WlanGetProfile 函数返回的配置文件中,纯文本 WEP 键始终以 10 个十六进制字符的形式返回。

要使 WlanGetProfile 调用返回纯文本键,必须在调用线程上设置WLAN_SECURABLE_OBJECT枚举类型的wlan_secure_get_plaintext_key权限。 DACL 还必须包含向调用线程的访问令牌授予 WLAN_READ_ACCESS 权限的 ACE。 默认情况下,仅允许本地计算机上的 Administrators 组的成员具有检索纯文本密钥的权限。

如果调用线程缺少所需的权限,WlanGetProfile 函数将在 pstrProfileXml 参数指向的缓冲区中返回的配置文件的 keyMaterial 元素中返回加密密钥。 如果调用线程缺少所需的权限,则不会返回错误。

默认情况下,pstrProfileXml 指向的配置文件中返回的 keyMaterial 元素是加密的。 如果进程在同一计算机上的 LocalSystem 帐户上下文中运行,则可以通过调用 CryptUnprotectData 函数来取消加密密钥材料。

Windows Server 2008 和 Windows Vista: 始终加密 pstrProfileXml 指向的配置文件架构中返回的 keyMaterial 元素。 如果进程在 LocalSystem 帐户的上下文中运行,则可以通过调用 CryptUnprotectData 函数来取消加密密钥材料。

具有 SP3 的 Windows XP 和适用于 SP2 的 Windows XP 的无线 LAN API: 密钥材料永远不会加密。

示例

以下示例枚举本地计算机上的无线 LAN 接口,检索每个无线 LAN 接口上特定无线配置文件的信息,并打印检索到的值。 还会打印查询配置文件的 XML 表示形式的字符串。

注意 如果未安装并启动无线 LAN 服务,本示例将无法在 Windows Server 2008 和 Windows Server 2008 R2 上加载。
 
#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>

#include <stdio.h>
#include <stdlib.h>

// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")


int _cdecl wmain(int argc, WCHAR **argv)
{

    // Declare and initialize variables.

    HANDLE hClient = NULL;
    DWORD dwMaxClient = 2;      //    
    DWORD dwCurVersion = 0;
    DWORD dwResult = 0;
    DWORD dwRetVal = 0;
    int iRet = 0;
    
    WCHAR GuidString[39] = {0};

    unsigned int i;

    /* variables used for WlanEnumInterfaces  */

    PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
    PWLAN_INTERFACE_INFO pIfInfo = NULL;

    LPCWSTR pProfileName = NULL;
    LPWSTR pProfileXml = NULL;
    DWORD dwFlags = 0;
    DWORD dwGrantedAccess = 0;
   
        // Validate the parameters
    if (argc < 2) {
        wprintf(L"usage: %s <profile>\n", argv[0]);
        wprintf(L"   Gets a wireless profile\n");
        wprintf(L"   Example\n");
        wprintf(L"       %s \"Default Wireless\"\n", argv[0]);
        exit(1);
    }
    
    pProfileName = argv[1];
     
    wprintf(L"Information for profile: %ws\n\n", pProfileName);
    
    dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
    if (dwResult != ERROR_SUCCESS) {
        wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
        return 1;
        // You can use FormatMessage here to find out why the function failed
    }

    dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
    if (dwResult != ERROR_SUCCESS) {
        wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
        return 1;
        // You can use FormatMessage here to find out why the function failed
    } else {
        wprintf(L"WLAN_INTERFACE_INFO_LIST for this system\n");

        wprintf(L"Num Entries: %lu\n", pIfList->dwNumberOfItems);
        wprintf(L"Current Index: %lu\n\n", pIfList->dwIndex);
        for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) {
            pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i];
            wprintf(L"  Interface Index[%u]:\t %lu\n", i, i);
            iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, 
                sizeof(GuidString)/sizeof(*GuidString)); 
            // For c rather than C++ source code, the above line needs to be
            // iRet = StringFromGUID2(&pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, 
            //     sizeof(GuidString)/sizeof(*GuidString)); 
            if (iRet == 0)
                wprintf(L"StringFromGUID2 failed\n");
            else {
                wprintf(L"  InterfaceGUID[%d]: %ws\n",i, GuidString);
            }    
            wprintf(L"  Interface Description[%d]: %ws", i, 
                pIfInfo->strInterfaceDescription);
            wprintf(L"\n");
            wprintf(L"  Interface State[%d]:\t ", i);
            switch (pIfInfo->isState) {
            case wlan_interface_state_not_ready:
                wprintf(L"Not ready\n");
                break;
            case wlan_interface_state_connected:
                wprintf(L"Connected\n");
                break;
            case wlan_interface_state_ad_hoc_network_formed:
                wprintf(L"First node in a ad hoc network\n");
                break;
            case wlan_interface_state_disconnecting:
                wprintf(L"Disconnecting\n");
                break;
            case wlan_interface_state_disconnected:
                wprintf(L"Not connected\n");
                break;
            case wlan_interface_state_associating:
                wprintf(L"Attempting to associate with a network\n");
                break;
            case wlan_interface_state_discovering:
                wprintf(L"Auto configuration is discovering settings for the network\n");
                break;
            case wlan_interface_state_authenticating:
                wprintf(L"In process of authenticating\n");
                break;
            default:
                wprintf(L"Unknown state %ld\n", pIfInfo->isState);
                break;
            }
            wprintf(L"\n\n");

            dwResult = WlanGetProfile(hClient,
                                             &pIfInfo->InterfaceGuid,
                                             pProfileName,
                                             NULL, 
                                             &pProfileXml,
                                             &dwFlags,
                                             &dwGrantedAccess);

            if (dwResult != ERROR_SUCCESS) {
                wprintf(L"WlanGetProfile failed with error: %u\n",
                        dwResult);
                // You can use FormatMessage to find out why the function failed
            } else {
                wprintf(L"  Profile Name:  %ws\n", pProfileName);

                wprintf(L"  Profile XML string:\n");
                wprintf(L"%ws\n\n", pProfileXml);

                wprintf(L"  dwFlags:\t    0x%x", dwFlags);
//                    if (dwFlags & WLAN_PROFILE_GET_PLAINTEXT_KEY)
//                        wprintf(L"   Get Plain Text Key");
                    if (dwFlags & WLAN_PROFILE_GROUP_POLICY)
                        wprintf(L"  Group Policy");
                    if (dwFlags & WLAN_PROFILE_USER)
                        wprintf(L"  Per User Profile");
                    wprintf(L"\n");    

                wprintf(L"  dwGrantedAccess:  0x%x", dwGrantedAccess);
                if (dwGrantedAccess & WLAN_READ_ACCESS)
                    wprintf(L"  Read access");
                if (dwGrantedAccess & WLAN_EXECUTE_ACCESS)
                    wprintf(L"  Execute access");
                if (dwGrantedAccess & WLAN_WRITE_ACCESS)
                    wprintf(L"  Write access");
                wprintf(L"\n");    

                wprintf(L"\n");
            }
        }

    }
    if (pProfileXml != NULL) {
        WlanFreeMemory(pProfileXml);
        pProfileXml = NULL;
    }

    if (pIfList != NULL) {
        WlanFreeMemory(pIfList);
        pIfList = NULL;
    }

    return dwRetVal;
}

要求

   
最低受支持的客户端 Windows Vista、Windows XP 和 SP3 [仅限桌面应用]
最低受支持的服务器 Windows Server 2008 [仅限桌面应用]
目标平台 Windows
标头 wlanapi.h (包括 Wlanapi.h)
Library Wlanapi.lib
DLL Wlanapi.dll
可再发行组件 适用于 Windows XP 的无线 LAN API SP2

另请参阅

WLAN_PROFILE_INFO

WLAN_PROFILE_INFO_LIST

WLAN_SECURABLE_OBJECT

WLAN_profile架构

WlanDeleteProfile

WlanEnumInterfaces

WlanFreeMemory

WlanGetProfileCustomUserData

WlanGetProfileList

WlanOpenHandle

WlanRenameProfile

WlanSaveTemporaryProfile

WlanSetProfile

WlanSetProfileCustomUserData

WlanSetProfileEapUserData

WlanSetProfileEapXmlUserData

WlanSetProfileList

WlanSetProfilePosition