Я работаю с RAS API под Windows 7 x32. Следующая функция возвращает ошибку 632 (ERROR_INVALID_SIZE):
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
во время компиляции, как показано выше.
Таким образом, при настройке на Windows 7 значение WINVER
должно быть установлено на значение не менее 0x601
(Windows 7 - 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;
}