Почему старый помощник прокси WinINet ломается в 64-битной сборке
Распознавайте усечение указателей в примерах interop прокси на C# и проверяйте расположение структур и владение памятью, прежде чем использовать их повторно.
Одно приведение типа может превратить внешне обычный помощник настроек прокси в сбой, зависящий от архитектуры:
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 влияет только на один элемент управления, один процесс или настройки текущего пользователя. Проверьте такое поведение API, прежде чем принимать остальную часть старого примера. Если он также отправляет уведомления об обновлении, выберите их для нужной области.