Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

535 lines
14 KiB

  1. // ===========================================================================
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. // PARTICULAR PURPOSE.
  6. //
  7. // Copyright 2000 Microsoft Corporation. All Rights Reserved.
  8. // ===========================================================================
  9. #include <windows.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include <stdlib.h>
  14. #include <io.h>
  15. #include <winhttp.h>
  16. #include <ntverp.h>
  17. #include <common.ver>
  18. #include "proxymsg.h"
  19. // Global module handles for error message lookup
  20. HMODULE g_hModWinHttp = NULL;
  21. //
  22. // MessageCleanup
  23. //
  24. // Free DLL loaded for message lookup
  25. //
  26. void
  27. MessageCleanup(void)
  28. {
  29. if (g_hModWinHttp)
  30. FreeLibrary(g_hModWinHttp);
  31. }
  32. //
  33. // GetMessage
  34. //
  35. // Get localized message text from WinHTTP or System.
  36. // Caller responsible for LocalFree'ing the returned string.
  37. //
  38. PWSTR
  39. GetMessage(
  40. IN DWORD dwError
  41. )
  42. {
  43. PWSTR pwszMessage = NULL;
  44. DWORD dwCount = 0;
  45. if (dwError > WINHTTP_ERROR_BASE && dwError <= WINHTTP_ERROR_LAST)
  46. {
  47. if (g_hModWinHttp == NULL)
  48. {
  49. g_hModWinHttp = LoadLibraryEx(
  50. "winhttp.dll",
  51. NULL,
  52. LOAD_LIBRARY_AS_DATAFILE
  53. );
  54. }
  55. dwCount = FormatMessageW(
  56. FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message
  57. FORMAT_MESSAGE_IGNORE_INSERTS | // don't expand printf tokens
  58. FORMAT_MESSAGE_FROM_HMODULE, // get message from module
  59. g_hModWinHttp,
  60. dwError,
  61. 0, // default language
  62. (PWSTR)&pwszMessage,
  63. 0, // allocate as much as necessary
  64. NULL // no args
  65. );
  66. }
  67. else
  68. {
  69. dwCount = FormatMessageW(
  70. FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message
  71. FORMAT_MESSAGE_IGNORE_INSERTS | // don't expand printf tokens
  72. FORMAT_MESSAGE_FROM_SYSTEM, // get system message
  73. NULL,
  74. dwError,
  75. 0, // default language
  76. (PWSTR)&pwszMessage,
  77. 0, // allocate as much as necessary
  78. NULL // no args
  79. );
  80. }
  81. if (dwCount > 0 && pwszMessage != NULL)
  82. return pwszMessage;
  83. return L"\n";
  84. }
  85. //
  86. // PrintMessage
  87. //
  88. // Prints messages using localized strings from the resources
  89. // of this application.
  90. //
  91. void
  92. PrintMessage(
  93. IN DWORD dwMsg,
  94. ...
  95. )
  96. {
  97. va_list pArg;
  98. PWSTR pwszUnicode = NULL;
  99. PSTR pszStr = NULL;
  100. DWORD dwLen = 0;
  101. HANDLE hOut;
  102. DWORD dwBytesWritten;
  103. DWORD fdwMode;
  104. va_start(pArg, dwMsg);
  105. dwLen = FormatMessageW(
  106. FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message and
  107. FORMAT_MESSAGE_FROM_HMODULE, // get message from module and
  108. NULL, // NULL means this application
  109. dwMsg,
  110. 0, // default language
  111. (PWSTR)&pwszUnicode,
  112. 0, // allocate as much as necessary
  113. &pArg // args for printf inserts
  114. );
  115. va_end(pArg);
  116. if (dwLen == 0 || pwszUnicode == NULL)
  117. return;
  118. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  119. if ((GetFileType(hOut) & FILE_TYPE_CHAR) && GetConsoleMode(hOut, &fdwMode))
  120. {
  121. // output not redirected - output UNICODE to console directly
  122. WriteConsoleW(hOut, pwszUnicode, wcslen(pwszUnicode), &dwBytesWritten, 0);
  123. }
  124. else
  125. {
  126. // output redirected - convert to multi-byte and output to file
  127. dwLen = WideCharToMultiByte(
  128. GetConsoleOutputCP(),
  129. 0,
  130. pwszUnicode,
  131. -1,
  132. NULL,
  133. 0,
  134. NULL,
  135. NULL);
  136. pszStr = new CHAR[dwLen];
  137. if (pszStr == NULL)
  138. return;
  139. dwLen = WideCharToMultiByte(
  140. GetConsoleOutputCP(),
  141. 0,
  142. pwszUnicode,
  143. -1,
  144. pszStr,
  145. dwLen,
  146. NULL,
  147. NULL);
  148. WriteFile(hOut, pszStr, dwLen-1, &dwBytesWritten, 0);
  149. if (pszStr) delete [] pszStr;
  150. }
  151. return;
  152. }
  153. //
  154. // AnsiToWideChar
  155. //
  156. // Used to convert command line input to UNICODE
  157. //
  158. DWORD
  159. AnsiToWideChar(const char * pszA, LPWSTR * ppszW)
  160. {
  161. DWORD cchW;
  162. *ppszW = NULL;
  163. if (!pszA)
  164. return ERROR_SUCCESS;
  165. // Determine how big the widechar string will be
  166. cchW = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
  167. *ppszW = new WCHAR[cchW];
  168. if (!*ppszW)
  169. return ERROR_NOT_ENOUGH_MEMORY;
  170. // now convert it
  171. cchW = MultiByteToWideChar(CP_ACP, 0, pszA, -1, *ppszW, cchW);
  172. return ERROR_SUCCESS;
  173. }
  174. typedef struct
  175. {
  176. DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
  177. LPSTR lpszProxy; // proxy server list
  178. LPSTR lpszProxyBypass; // proxy bypass list
  179. }
  180. WINHTTP_PROXY_INFOA;
  181. // MigrateProxySettings is defined in ProxyMigrate.cxx
  182. DWORD MigrateProxySettings (void);
  183. /*
  184. usage:
  185. proxycfg -? : to view help information
  186. proxycfg : to view current WinHTTP proxy settings
  187. proxycfg [-d] [-p <server-name> [<bypass-list>]]
  188. -d : set direct access
  189. -p : set proxy server(s), and optional bypass list
  190. proxycfg -u : import proxy settings from current user's
  191. Microsoft Internet Explorer manual settings (in HKCU)
  192. */
  193. enum ARGTYPE
  194. {
  195. ARGS_HELP,
  196. ARGS_SET_PROXY_SETTINGS,
  197. ARGS_VIEW_PROXY_SETTINGS,
  198. ARGS_INITIALIZE_PROXY_SETTINGS, // updates from HKCU only if never init
  199. ARGS_MIGRATE_PROXY_SETTINGS // forces update from HKCU
  200. };
  201. struct ARGS
  202. {
  203. ARGTYPE Command;
  204. DWORD Flags;
  205. char * ProxyServer;
  206. char * BypassList;
  207. };
  208. #define INTERNET_SETTINGS_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  209. static const WCHAR szRegPathConnections[] = INTERNET_SETTINGS_KEY L"\\Connections";
  210. void ParseArguments(int argc, char ** argv, ARGS * Args)
  211. {
  212. Args->Command = ARGS_VIEW_PROXY_SETTINGS;
  213. Args->Flags = WINHTTP_ACCESS_TYPE_NO_PROXY;
  214. Args->ProxyServer = NULL;
  215. Args->BypassList = NULL;
  216. if (argc == 0)
  217. return;
  218. for (;;)
  219. {
  220. if ((argv[0][0] != '-') || (lstrlen(argv[0]) != 2))
  221. {
  222. Args->Command = ARGS_HELP;
  223. goto Exit;
  224. }
  225. switch (tolower(argv[0][1]))
  226. {
  227. default:
  228. Args->Command = ARGS_HELP;
  229. goto Exit;
  230. case 'd':
  231. Args->Command = ARGS_SET_PROXY_SETTINGS;
  232. Args->Flags = WINHTTP_ACCESS_TYPE_NO_PROXY;
  233. argc--;
  234. argv++;
  235. if (argc == 0)
  236. goto Exit;
  237. continue;
  238. case 'i':
  239. Args->Command = ARGS_INITIALIZE_PROXY_SETTINGS;
  240. goto Exit;
  241. case 'p':
  242. argc--;
  243. argv++;
  244. if (argc == 0)
  245. {
  246. // error: no proxy specified
  247. Args->Command = ARGS_HELP;
  248. }
  249. else
  250. {
  251. Args->Command = ARGS_SET_PROXY_SETTINGS;
  252. Args->Flags |= WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  253. Args->ProxyServer = argv[0];
  254. argc--;
  255. argv++;
  256. if (argc >= 1)
  257. {
  258. Args->BypassList = argv[0];
  259. }
  260. }
  261. goto Exit;
  262. case 'u':
  263. Args->Command = ARGS_MIGRATE_PROXY_SETTINGS;
  264. goto Exit;
  265. }
  266. }
  267. Exit:
  268. return;
  269. }
  270. DWORD WriteProxySettings( WINHTTP_PROXY_INFOA * pInfo)
  271. {
  272. DWORD error = ERROR_SUCCESS;
  273. WINHTTP_PROXY_INFO proxyInfo;
  274. memset( &proxyInfo, 0, sizeof( proxyInfo));
  275. switch( pInfo->dwAccessType)
  276. {
  277. case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
  278. case WINHTTP_ACCESS_TYPE_NO_PROXY:
  279. proxyInfo.dwAccessType = pInfo->dwAccessType;
  280. break;
  281. default:
  282. // When migrating, we get some weird flags in dwAccessType.
  283. // Be smart about guessing if there is a proxy or not.
  284. proxyInfo.dwAccessType = pInfo->lpszProxy != NULL
  285. ? WINHTTP_ACCESS_TYPE_NAMED_PROXY
  286. : WINHTTP_ACCESS_TYPE_NO_PROXY;
  287. }
  288. // we only support ANSI hostnames so only try to convert from ANSI to UNICODE
  289. if( NULL != pInfo->lpszProxy)
  290. {
  291. error = AnsiToWideChar( pInfo->lpszProxy, &proxyInfo.lpszProxy);
  292. if( error != ERROR_SUCCESS)
  293. goto quit;
  294. }
  295. if( NULL != pInfo->lpszProxyBypass)
  296. {
  297. error = AnsiToWideChar( pInfo->lpszProxyBypass, &proxyInfo.lpszProxyBypass);
  298. if( error != ERROR_SUCCESS)
  299. goto quit;
  300. }
  301. error = ERROR_SUCCESS;
  302. if( TRUE != WinHttpSetDefaultProxyConfiguration( &proxyInfo))
  303. {
  304. error = GetLastError();
  305. }
  306. quit:
  307. if( proxyInfo.lpszProxy != NULL)
  308. delete[] proxyInfo.lpszProxy;
  309. if( proxyInfo.lpszProxyBypass != NULL)
  310. delete[] proxyInfo.lpszProxyBypass;
  311. return error;
  312. }
  313. DWORD SetProxySettings(DWORD Flags, char * ProxyServer, char * BypassList)
  314. {
  315. WINHTTP_PROXY_INFOA proxyInfo;
  316. DWORD error;
  317. LPWSTR pwszString = NULL;
  318. // initialize structure
  319. memset(&proxyInfo, 0, sizeof(proxyInfo));
  320. proxyInfo.dwAccessType = Flags;
  321. proxyInfo.lpszProxy = ProxyServer;
  322. proxyInfo.lpszProxyBypass = BypassList;
  323. error = WriteProxySettings(&proxyInfo);
  324. if (error != ERROR_SUCCESS)
  325. {
  326. pwszString = GetMessage(error);
  327. PrintMessage(MSG_ERROR_WRITING_PROXY_SETTINGS, error,
  328. pwszString ? pwszString : L"");
  329. if (pwszString) LocalFree(pwszString);
  330. }
  331. else
  332. {
  333. PrintMessage(MSG_UPDATE_SUCCESS);
  334. }
  335. return error;
  336. }
  337. void ViewProxySettings()
  338. {
  339. WINHTTP_PROXY_INFO proxyInfo;
  340. DWORD error;
  341. PWSTR pwszString = NULL;
  342. if( TRUE != WinHttpGetDefaultProxyConfiguration( &proxyInfo))
  343. {
  344. error = GetLastError();
  345. pwszString = GetMessage(error);
  346. PrintMessage(MSG_ERROR_READING_PROXY_SETTINGS, error,
  347. pwszString ? pwszString : L"");
  348. if (pwszString ) LocalFree(pwszString );
  349. return;
  350. }
  351. PrintMessage(MSG_CURRENT_SETTINGS_HEADER, szRegPathConnections);
  352. switch( proxyInfo.dwAccessType)
  353. {
  354. case WINHTTP_ACCESS_TYPE_NO_PROXY:
  355. PrintMessage(MSG_DIRECT_ACCESS);
  356. break;
  357. case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
  358. if( proxyInfo.lpszProxy != NULL)
  359. PrintMessage(MSG_PROXY_SERVERS, proxyInfo.lpszProxy);
  360. else
  361. PrintMessage(MSG_ERROR_PROXY_SERVER_MISSING);
  362. if( proxyInfo.lpszProxyBypass != NULL)
  363. PrintMessage(MSG_BYPASS_LIST, proxyInfo.lpszProxyBypass);
  364. else
  365. PrintMessage(MSG_BYPASS_LIST_NONE);
  366. break;
  367. default:
  368. PrintMessage(MSG_UNKNOWN_PROXY_ACCESS_TYPE);
  369. break;
  370. }
  371. if( NULL != proxyInfo.lpszProxy)
  372. GlobalFree( proxyInfo.lpszProxy);
  373. if( NULL != proxyInfo.lpszProxyBypass)
  374. GlobalFree( proxyInfo.lpszProxyBypass);
  375. }
  376. int __cdecl main (int argc, char **argv)
  377. {
  378. ARGS Args;
  379. DWORD dwErr;
  380. PWSTR pwszString = NULL;
  381. PrintMessage(MSG_STARTUP_BANNER);
  382. PrintMessage(MSG_COPYRIGHT);
  383. // Discard program arg.
  384. argv++;
  385. argc--;
  386. ParseArguments(argc, argv, &Args);
  387. switch (Args.Command)
  388. {
  389. case ARGS_HELP:
  390. default:
  391. PrintMessage(MSG_USAGE);
  392. break;
  393. case ARGS_SET_PROXY_SETTINGS:
  394. SetProxySettings(Args.Flags, Args.ProxyServer, Args.BypassList);
  395. ViewProxySettings();
  396. break;
  397. case ARGS_INITIALIZE_PROXY_SETTINGS:
  398. // intentional fall through
  399. case ARGS_MIGRATE_PROXY_SETTINGS:
  400. dwErr = MigrateProxySettings();
  401. if (dwErr != ERROR_SUCCESS)
  402. {
  403. pwszString = GetMessage(dwErr);
  404. PrintMessage(MSG_MIGRATION_FAILED_WITH_ERROR, dwErr,
  405. pwszString ? pwszString : L"");
  406. if (pwszString) LocalFree(pwszString);
  407. exit (dwErr);
  408. }
  409. ViewProxySettings();
  410. break;
  411. case ARGS_VIEW_PROXY_SETTINGS:
  412. ViewProxySettings();
  413. break;
  414. }
  415. MessageCleanup();
  416. return 0;
  417. }