多分自分以外には全く役に立たないし、これから先の未来永劫参照されることはない情報だと思うが、せっかく調べたので投稿しておく。
古いWindowsアプリケーションをVisualStdio2015の環境でビルドしなおしていたところ、WindowsServer2008R2より前のOSで正常に動作しない現象に出会った。
しかしWindows8.1やWindowsServer2012であればキチンと動作する。
本来ならデバッガを動かしたいところだったが訳あって現象が出るOSにリモートデバッガをインストールすることができなかった。
ログをろくに出力していないアプリケーションだったので、どこで止まっているかを確認するために、とりあえずログを出力するようにした。
エラーになっていたところは以下の関数のところだった。この関数は平成も終わるこのご時世にいまだ使われている古の通信方法であるダイヤルアップ接続を行うための関数である。
エラーコードを見ていると632となっていたが、このメッセージの意味は「構造体のサイズが違う」ということらしい。
正直「なんだこのエラーわ??」という感じだったが、引数一つ一つ構造体を確認してみると、どうやらWindowsのバージョンによって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
};
msdnのホームページを確認したときにはifマクロの定義がなかったが、実際のコードを確認してみたらifマクロが記述されていた。
この関数を実行する際にコンパイルした環境が期待している構造体のサイズとWindows2008R2以前の環境で実行する時の構造体のサイズのチェック処理があり、そこで引っかかるようになってしまったということらしい。
検索してみたらまさかStackoverflowにも同様の記事があった!
RAS API. sizeof(RASDIALPARAMS) is wrong. Error 632
ifマクロ使って条件分岐なんてことはしたくはないので、以下のように修正している。なんてことはなく、ERROR_INVALID_SIZEが返ってくるたびに構造体のサイズを小さくして実行するだけである。
RASDIALPARAMSW ras_param;
ZeroMemory(&ras_param, sizeof(ras_param));
ras_param.dwSize = sizeof(RASDIALPARAMSW);
DWORD dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
if (dwRet == ERROR_INVALID_SIZE) {
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwIfIndex);
dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
}
if (dwRet == ERROR_INVALID_SIZE) {
ras_param.dwSize = offsetof(RASDIALPARAMSW, dwSubEntry);
dwRet = RasSetEntryDialParamsW(0, &ras_param, 0);
}
また、どうやらRasGetConnectStatus関数も同様にWindowsのバージョンで構造体が変わっているらしい。
こちらも同様に、ERROR_INVALID_SIZEが返ってきたら徐々にサイズを縮めていけば良さそう。
というかどちらもページにも構造体のサイズに関する注意書きがあるので、もう少しアンテナを貼って置くべきだった…
とりあえず、これでWindows7、WindowsServer2008、WindowsServer2008でも動作する。
あと4〜5年したらアナログ回線やISDN回線による通信は絶滅する(とは言い過ぎかもだけど)と思うので、こんな現象に出会うのもこれで最後かもしれない。