One cast can turn a seemingly ordinary proxy-settings helper into an architecture-dependent failure:

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

That code narrows a native address to a 32-bit integer before adding the next structure's size. A 64-bit process can hold addresses that do not fit. Depending on the conversion and value, the result can be an overflow exception or an invalid address. Switching the build back to x86 may hide the mistake, but it leaves the interop implementation dependent on that workaround.

Keep addresses in pointer-sized form. For example, advancing through an already allocated array can use:

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

The offset remains an integer; the address itself is not squeezed through one. The allocation size and index still need to be valid.

Then inspect the surrounding declarations

WinINet's per-connection options contain a union whose members include a DWORD, a string pointer and a FILETIME. Pointer fields need IntPtr; DWORD fields remain 32-bit. Native alignment matters, so replacing every integer with a 64-bit integer or forcing a packed layout is not a sound repair.

Use the marshaled structure size when stepping through the array, match the ANSI or Unicode declaration consistently, and track each allocation separately. Freeing the block of option structures does not automatically release strings allocated elsewhere and referenced by those structures.

Finally, keep the question of setting scope separate from memory correctness. Repairing a cast does not prove that a helper's chosen WinINet option affects only one control, one process or the current user's settings. Check that API behavior before adopting the rest of an old sample. If it also sends refresh notifications, select them for the intended scope.

Artiglyn mynjee