RAS API. sizeof (RASDIALPARAMS) неверно. Ошибка 632

0

Я работаю с 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) возвращает неправильный размер? Как это могло произойти?

Или что мне не хватает?

  • 0
    Цитата: «Windows XP или более поздняя версия: не используйте функцию RasSetEntryDialParams»
Теги:
winapi
size
ras

1 ответ

4
Лучший ответ

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;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню