private static (IntPtr, int) PrepareOptionList(List <InternetPerConnectionOption> options, string connName)
        {
            int len = options.Sum(o => Marshal.SizeOf(o));

            IntPtr buf = Marshal.AllocCoTaskMem(len);
            IntPtr cur = buf;

            foreach (InternetPerConnectionOption o in options)
            {
                Marshal.StructureToPtr(o, cur, false);
                cur += Marshal.SizeOf(o);
            }
            InternetPerConnectionOptionList optionList = new InternetPerConnectionOptionList
            {
                pOptions    = buf,
                OptionCount = options.Count,
                Connection  = string.IsNullOrEmpty(connName)
                    ? IntPtr.Zero
                    : Marshal.StringToHGlobalAuto(connName),
                OptionError = 0,
            };
            int listSize = Marshal.SizeOf(optionList);

            optionList.Size = listSize;

            IntPtr unmanagedList = Marshal.AllocCoTaskMem(listSize);

            Marshal.StructureToPtr(optionList, unmanagedList, true);
            return(unmanagedList, listSize);
        }
        private static void ClearOptionList(IntPtr list)
        {
            InternetPerConnectionOptionList l = Marshal.PtrToStructure <InternetPerConnectionOptionList>(list);

            Marshal.FreeCoTaskMem(l.pOptions);
            Marshal.FreeCoTaskMem(list);
        }
        public static WinINetSetting Query()
        {
            if (!operational)
            {
                return(new WinINetSetting());
            }

            List <InternetPerConnectionOption> options = new List <InternetPerConnectionOption>
            {
                new InternetPerConnectionOption {
                    dwOption = (int)InternetPerConnectionOptionEnum.FlagsUI
                },
                new InternetPerConnectionOption {
                    dwOption = (int)InternetPerConnectionOptionEnum.ProxyServer
                },
                new InternetPerConnectionOption {
                    dwOption = (int)InternetPerConnectionOptionEnum.ProxyBypass
                },
                new InternetPerConnectionOption {
                    dwOption = (int)InternetPerConnectionOptionEnum.AutoConfigUrl
                },
            };

            (IntPtr unmanagedList, int listSize) = PrepareOptionList(options, null);
            bool ok = InternetQueryOption(IntPtr.Zero, (int)InternetOptions.PerConnectionOption, unmanagedList, ref listSize);

            if (!ok)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            WinINetSetting proxy = new WinINetSetting();

            InternetPerConnectionOptionList ret = Marshal.PtrToStructure <InternetPerConnectionOptionList>(unmanagedList);
            IntPtr p       = ret.pOptions;
            int    nOption = ret.OptionCount;
            List <InternetPerConnectionOption> outOptions = new List <InternetPerConnectionOption>();

            for (int i = 0; i < nOption; i++)
            {
                InternetPerConnectionOption o = Marshal.PtrToStructure <InternetPerConnectionOption>(p);
                outOptions.Add(o);
                p += Marshal.SizeOf(o);
            }

            foreach (InternetPerConnectionOption o in outOptions)
            {
                switch ((InternetPerConnectionOptionEnum)o.dwOption)
                {
                case InternetPerConnectionOptionEnum.FlagsUI:
                case InternetPerConnectionOptionEnum.Flags:
                    proxy.Flags = (InternetPerConnectionFlags)o.Value.dwValue;
                    break;

                case InternetPerConnectionOptionEnum.AutoConfigUrl:
                    proxy.AutoConfigUrl = Marshal.PtrToStringAuto(o.Value.pszValue);
                    break;

                case InternetPerConnectionOptionEnum.ProxyBypass:
                    proxy.ProxyBypass = Marshal.PtrToStringAuto(o.Value.pszValue);
                    break;

                case InternetPerConnectionOptionEnum.ProxyServer:
                    proxy.ProxyServer = Marshal.PtrToStringAuto(o.Value.pszValue);
                    break;

                default:
                    break;
                }
            }
            return(proxy);
        }