我在Windows7x32下使用RASAPI。以下函数返回错误632(错误无效的大小):
int32_t set_username_passwd(wchar_t *entry_title)
{
RASDIALPARAMS ras_param;
ZeroMemory(&ras_param, sizeof(RASDIALPARAMS));
ras_param.dwSize = sizeof(RASDIALPARAMS);
memcpy(ras_param.szEntryName, entry_title, wcslen(entry_title));
memcpy(ras_param.szUserName, L"username", wcslen(L"username"));
memcpy(ras_param.szPassword, L"password", wcslen(L"password"));
return RasSetEntryDialParams(0, &ras_param, 0);
}
sizeof(RASDIALPARAMS)
返回错误的大小?怎么可能?或者我错过了什么?
最佳答案
RASDIALPARAMS
这些年来增加了新的字段:
#define RASDIALPARAMSW struct tagRASDIALPARAMSW
RASDIALPARAMSW
{
DWORD dwSize;
WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
WCHAR szPhoneNumber[ RAS_MaxPhoneNumber + 1 ];
WCHAR szCallbackNumber[ RAS_MaxCallbackNumber + 1 ];
WCHAR szUserName[ UNLEN + 1 ];
WCHAR szPassword[ PWLEN + 1 ];
WCHAR szDomain[ DNLEN + 1 ];
#if (WINVER >= 0x401) // 95/NT4 and later
DWORD dwSubEntry;
ULONG_PTR dwCallbackId;
#endif
#if (WINVER >= 0x601) // Windows 7 and later
DWORD dwIfIndex;
#endif
};
因此,
RASDIALPARAMS
期望的RasSetEntryDialParams()
的大小取决于特定的Windows版本。但应用程序内部RASDIALPARAMS
的实际大小取决于编译期间的WINVER
定义,如上图所示。因此,当以Windows7为目标时,
WINVER
必须设置为至少0x601
的值(Windows7是v6.1)。如果使用较低的WINVER
值编译,RASDIALPARAMS
的大小将太小,Windows 7无法接受。如果将
WINVER
设置为比目标Windows版本高的值,则可以在运行时检测操作系统版本并将ras_param.dwSize
设置为适当的大小,因为sizeof(RASDIALPARAMS)
将大于RasSetEntryDialParams()
所期望的大小。例如:int32_t set_username_passwd(wchar_t *entry_title)
{
RASDIALPARAMSW ras_param;
ZeroMemory(&ras_param, sizeof(ras_param));
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(osvi));
GetVersionEx(&osvi);
#if (WINVER >= 0x401)
if ((osvi.dwMajorVersion < 4) ||
((osvi.dwMajorVersion == 4) && (osvi.dwMinVersion < 1)) )
{
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwSubEntry);
}
else
#endif
#if (WINVER >= 0x601)
if ((osvi.dwMajorVersion < 6) ||
((osvi.dwMajorVersion == 6) && (osvi.dwMinVersion < 1)) )
{
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwIfIndex);
}
else
#endif
{
ras_param.dwSize = sizeof(ras_param);
}
wcsncpy(ras_param.szEntryName, entry_title, RAS_MaxEntryName);
wcsncpy(ras_param.szUserName, L"username", UNLEN);
wcsncpy(ras_param.szPassword, L"password", PWLEN);
return RasSetEntryDialParamsW(0, &ras_param, 0);
}
或者,您可以跳过操作系统检查,只处理
ERROR_INVALID_SIZE
错误:int32_t set_username_passwd(wchar_t *entry_title)
{
RASDIALPARAMSW ras_param;
ZeroMemory(&ras_param, sizeof(ras_param));
ras_param.dwSize = sizeof(ras_param);
wcsncpy(ras_param.szEntryName, entry_title, RAS_MaxEntryName);
wcsncpy(ras_param.szUserName, L"username", UNLEN);
wcsncpy(ras_param.szPassword, L"password", PWLEN);
DWORD dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
#if (WINVER >= 0x601)
if (dwRet == ERROR_INVALID_SIZE)
{
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwIfIndex);
dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
}
#elif (WINVER >= 0x401)
if (dwRet == ERROR_INVALID_SIZE)
{
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwSubEntry);
dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
}
#endif
return dwRet;
}