-
Notifications
You must be signed in to change notification settings - Fork 2
/
config_win.c
110 lines (89 loc) · 4.38 KB
/
config_win.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <windows.h>
#include <wininet.h>
#include "config.h"
#include "config_i.h"
#include "config_win.h"
#include "util.h"
#include "util_win.h"
// Use WinInet to retrieve user's proxy configuration because WinHttpGetIEProxyConfigForCurrentUser
// has a network dependency that causes it to be slow https://stackoverflow.com/questions/2151462/.
bool proxy_config_win_get_auto_discover(void) {
INTERNET_PER_CONN_OPTIONW options[1] = {{INTERNET_PER_CONN_FLAGS_UI, {0}}};
INTERNET_PER_CONN_OPTION_LISTW option_list = {sizeof(INTERNET_PER_CONN_OPTION_LISTW), NULL, 1, 0, options};
DWORD option_list_size = sizeof(option_list);
bool auto_discover = false;
// INTERNET_PER_CONN_FLAGS hides auto-detection setting if it believes the network does not have WPAD. To get
// the actual value we need to query using INTERNET_PER_CONN_FLAGS_UI https://stackoverflow.com/questions/15565997
if (!InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &option_list, &option_list_size)) {
options[0].dwOption = INTERNET_PER_CONN_FLAGS;
if (!InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &option_list, &option_list_size))
return auto_discover;
}
auto_discover = options[0].Value.dwValue & PROXY_TYPE_AUTO_DETECT;
return auto_discover;
}
char *proxy_config_win_get_auto_config_url(void) {
INTERNET_PER_CONN_OPTIONW options[2] = {{INTERNET_PER_CONN_FLAGS, {0}}, {INTERNET_PER_CONN_AUTOCONFIG_URL, {0}}};
INTERNET_PER_CONN_OPTION_LISTW option_list = {sizeof(INTERNET_PER_CONN_OPTION_LISTW), NULL, 2, 0, options};
DWORD option_list_size = sizeof(option_list);
char *auto_config_url = NULL;
if (InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &option_list, &option_list_size)) {
if (options[1].Value.pszValue) {
if (options[0].Value.dwValue & PROXY_TYPE_AUTO_PROXY_URL && *options[1].Value.pszValue)
auto_config_url = wchar_dup_to_utf8(options[1].Value.pszValue);
GlobalFree(options[1].Value.pszValue);
}
}
return auto_config_url;
}
char *proxy_config_win_get_proxy(const char *scheme) {
INTERNET_PER_CONN_OPTIONW options[2] = {{INTERNET_PER_CONN_FLAGS, {0}}, {INTERNET_PER_CONN_PROXY_SERVER, {0}}};
INTERNET_PER_CONN_OPTION_LISTW option_list = {sizeof(INTERNET_PER_CONN_OPTION_LISTW), NULL, 2, 0, options};
DWORD option_list_size = sizeof(option_list);
char *proxy_list = NULL;
if (InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &option_list, &option_list_size)) {
if (options[1].Value.pszValue) {
if (options[0].Value.dwValue & PROXY_TYPE_PROXY && *options[1].Value.pszValue)
proxy_list = wchar_dup_to_utf8(options[1].Value.pszValue);
GlobalFree(options[1].Value.pszValue);
}
}
if (!proxy_list)
return NULL;
// Proxy may be returned as a list of proxies
char *proxy = get_winhttp_proxy_by_scheme(scheme, proxy_list);
free(proxy_list);
return proxy;
}
char *proxy_config_win_get_bypass_list(void) {
INTERNET_PER_CONN_OPTIONW options[2] = {{INTERNET_PER_CONN_FLAGS, {0}}, {INTERNET_PER_CONN_PROXY_BYPASS, {0}}};
INTERNET_PER_CONN_OPTION_LISTW option_list = {sizeof(INTERNET_PER_CONN_OPTION_LISTW), NULL, 2, 0, options};
DWORD option_list_size = sizeof(option_list);
char *list = NULL;
if (InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &option_list, &option_list_size)) {
if (options[1].Value.pszValue) {
if (options[0].Value.dwValue & PROXY_TYPE_PROXY && *options[1].Value.pszValue)
list = wchar_dup_to_utf8(options[1].Value.pszValue);
GlobalFree(options[1].Value.pszValue);
}
}
// Normalize separators for all platforms to comma
if (list)
str_change_chr(list, ';', ',');
return list;
}
bool proxy_config_win_global_init(void) {
return true;
}
bool proxy_config_win_global_cleanup(void) {
return true;
}
proxy_config_i_s *proxy_config_win_get_interface(void) {
static proxy_config_i_s proxy_config_win_i = {
proxy_config_win_get_auto_discover, proxy_config_win_get_auto_config_url, proxy_config_win_get_proxy,
proxy_config_win_get_bypass_list, proxy_config_win_global_init, proxy_config_win_global_cleanup};
return &proxy_config_win_i;
}