1 回のキャストで、一見ありふれたプロキシ設定ヘルパーがアーキテクチャ依存の障害に変わります。

current = (IntPtr)((int)current + optionSize);

このコードは、次の構造体のサイズを加える前にネイティブ アドレスを 32 ビット整数に狭めています。64 ビット プロセスは収まらないアドレスを保持できます。変換と値によっては、結果はオーバーフロー例外や無効なアドレスになります。ビルドを x86 に戻すと誤りは隠れますが、interop 実装はその回避策に依存したままになります。

アドレスはポインターサイズの形で保ちます。たとえば、すでに割り当て済みの配列を進むには次を使えます。

IntPtr item = IntPtr.Add(buffer, checked(index * optionSize));

オフセットは整数のままで、アドレス自体がそれを通して押し込まれることはありません。割り当てサイズとインデックスは引き続き有効でなければなりません。

次に周囲の宣言を確認する

WinINet の接続ごとのオプションには、DWORD、文字列ポインター、FILETIME をメンバーに含む共用体があります。ポインター フィールドには IntPtr が必要で、DWORD フィールドは 32 ビットのままです。ネイティブのアラインメントが重要なので、すべての整数を 64 ビット整数に置き換えたり、パックしたレイアウトを強制したりすることは健全な修正ではありません。

配列を進むときはマーシャリング後の構造体サイズを使い、ANSI または Unicode の宣言を一貫して合わせ、各割り当てを個別に追跡します。オプション構造体のブロックを解放しても、別の場所で割り当てられ、それらの構造体から参照されている文字列は自動的に解放されません。

最後に、設定のスコープという問いをメモリの正しさから切り離してください。キャストを直しても、ヘルパーが選んだ WinINet オプションが 1 つのコントロール、1 つのプロセス、または現在のユーザーの設定だけに影響するとは証明できません。古いサンプルの残りを取り入れる前に、その API の動作を確認してください。更新通知も送る場合は、意図したスコープに合わせて選択してください。

関連記事