Tools.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3. #include <vcl.h>
  4. #pragma hdrstop
  5. #include <Consts.hpp>
  6. #include <shlobj.h>
  7. #include <stdio.h>
  8. #include <Common.h>
  9. #include <TextsWin.h>
  10. #include "GUITools.h"
  11. #include "VCLCommon.h"
  12. #include "Tools.h"
  13. //---------------------------------------------------------------------------
  14. #pragma package(smart_init)
  15. //---------------------------------------------------------------------------
  16. TFontStyles __fastcall IntToFontStyles(int value)
  17. {
  18. TFontStyles Result;
  19. for (int i = fsBold; i <= fsStrikeOut; i++)
  20. {
  21. if (value & 1)
  22. {
  23. Result << (TFontStyle)i;
  24. }
  25. value >>= 1;
  26. }
  27. return Result;
  28. }
  29. //---------------------------------------------------------------------------
  30. int __fastcall FontStylesToInt(const TFontStyles value)
  31. {
  32. int Result = 0;
  33. for (int i = fsStrikeOut; i >= fsBold; i--)
  34. {
  35. Result <<= 1;
  36. if (value.Contains((TFontStyle)i))
  37. {
  38. Result |= 1;
  39. }
  40. }
  41. return Result;
  42. }
  43. //---------------------------------------------------------------------------
  44. void __fastcall CenterFormOn(TForm * Form, TControl * CenterOn)
  45. {
  46. TPoint ScreenPoint = CenterOn->ClientToScreen(TPoint(0, 0));
  47. Form->Left = ScreenPoint.x + (CenterOn->Width / 2) - (Form->Width / 2);
  48. Form->Top = ScreenPoint.y + (CenterOn->Height / 2) - (Form->Height / 2);
  49. }
  50. //---------------------------------------------------------------------------
  51. AnsiString __fastcall GetListViewStr(TListView * ListView)
  52. {
  53. AnsiString Result;
  54. for (int Index = 0; Index < ListView->Columns->Count; Index++)
  55. {
  56. if (!Result.IsEmpty())
  57. {
  58. Result += ",";
  59. }
  60. Result += IntToStr(ListView->Column[Index]->Width);
  61. }
  62. return Result;
  63. }
  64. //---------------------------------------------------------------------------
  65. void __fastcall LoadListViewStr(TListView * ListView, AnsiString LayoutStr)
  66. {
  67. int Index = 0;
  68. while (!LayoutStr.IsEmpty() && (Index < ListView->Columns->Count))
  69. {
  70. ListView->Column[Index]->Width = StrToIntDef(
  71. CutToChar(LayoutStr, ',', true), ListView->Column[Index]->Width);
  72. Index++;
  73. }
  74. }
  75. //---------------------------------------------------------------------------
  76. void __fastcall RestoreForm(AnsiString Data, TForm * Form)
  77. {
  78. assert(Form);
  79. if (!Data.IsEmpty())
  80. {
  81. TMonitor * Monitor = FormMonitor(Form);
  82. TRect Bounds = Form->BoundsRect;
  83. int Left = StrToIntDef(::CutToChar(Data, ';', true), Bounds.Left);
  84. int Top = StrToIntDef(::CutToChar(Data, ';', true), Bounds.Top);
  85. bool DefaultPos = (Left == -1) && (Top == -1);
  86. if (!DefaultPos)
  87. {
  88. Bounds.Left = Left;
  89. Bounds.Top = Top;
  90. }
  91. else
  92. {
  93. Bounds.Left = 0;
  94. Bounds.Top = 0;
  95. }
  96. Bounds.Right = StrToIntDef(::CutToChar(Data, ';', true), Bounds.Right);
  97. Bounds.Bottom = StrToIntDef(::CutToChar(Data, ';', true), Bounds.Bottom);
  98. TWindowState State = (TWindowState)StrToIntDef(::CutToChar(Data, ';', true), (int)wsNormal);
  99. Form->WindowState = State;
  100. if (State == wsNormal)
  101. {
  102. // move to the target monitor
  103. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  104. // reduce window size to that of monitor size
  105. // (this does not cut window into monitor!)
  106. if (Bounds.Width() > Monitor->WorkareaRect.Width())
  107. {
  108. Bounds.Right -= (Bounds.Width() - Monitor->WorkareaRect.Width());
  109. }
  110. if (Bounds.Height() > Monitor->WorkareaRect.Height())
  111. {
  112. Bounds.Bottom -= (Bounds.Height() - Monitor->WorkareaRect.Height());
  113. }
  114. if (DefaultPos ||
  115. ((Bounds.Left < Monitor->Left) ||
  116. (Bounds.Left > Monitor->Left + Monitor->WorkareaRect.Width() - 20) ||
  117. (Bounds.Top < Monitor->Top) ||
  118. (Bounds.Top > Monitor->Top + Monitor->WorkareaRect.Height() - 20)))
  119. {
  120. if (Monitor->Primary)
  121. {
  122. if ((Application->MainForm == NULL) || (Application->MainForm == Form))
  123. {
  124. Form->Position = poDefaultPosOnly;
  125. }
  126. else
  127. {
  128. Form->Position = poMainFormCenter;
  129. }
  130. Form->Width = Bounds.Width();
  131. Form->Height = Bounds.Height();
  132. }
  133. else
  134. {
  135. // when positioning on non-primary monitor, we need
  136. // to handle that ourselves, so place window to center
  137. Form->SetBounds(Monitor->Left + ((Monitor->Width - Bounds.Width()) / 2),
  138. Monitor->Top + ((Monitor->Height - Bounds.Height()) / 2),
  139. Bounds.Width(), Bounds.Height());
  140. Form->Position = poDesigned;
  141. }
  142. }
  143. else
  144. {
  145. Form->Position = poDesigned;
  146. Form->BoundsRect = Bounds;
  147. }
  148. }
  149. else if (State == wsMaximized)
  150. {
  151. Form->Position = poDesigned;
  152. Bounds = Form->BoundsRect;
  153. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  154. Form->BoundsRect = Bounds;
  155. }
  156. }
  157. else if (Form->Position == poDesigned)
  158. {
  159. Form->Position = poDefaultPosOnly;
  160. }
  161. }
  162. //---------------------------------------------------------------------------
  163. AnsiString __fastcall StoreForm(TCustomForm * Form)
  164. {
  165. assert(Form);
  166. TRect Bounds = Form->BoundsRect;
  167. OffsetRect(Bounds, -Form->Monitor->Left, -Form->Monitor->Top);
  168. return FORMAT("%d;%d;%d;%d;%d", ((int)Bounds.Left, (int)Bounds.Top,
  169. (int)Bounds.Right, (int)Bounds.Bottom,
  170. // we do not want WinSCP to start minimized next time (we cannot handle that anyway).
  171. // note that WindowState is wsNormal when window in minimized for some reason.
  172. // actually it is wsMinimized only when minimized by MSVDM
  173. (int)(Form->WindowState == wsMinimized ? wsNormal : Form->WindowState)));
  174. }
  175. //---------------------------------------------------------------------------
  176. bool __fastcall ExecuteShellAndWait(const AnsiString Path, const AnsiString Params)
  177. {
  178. return ExecuteShellAndWait(Application->Handle, Path, Params,
  179. &Application->ProcessMessages);
  180. }
  181. //---------------------------------------------------------------------------
  182. bool __fastcall ExecuteShellAndWait(const AnsiString Command)
  183. {
  184. return ExecuteShellAndWait(Application->Handle, Command,
  185. &Application->ProcessMessages);
  186. }
  187. //---------------------------------------------------------------------------
  188. void __fastcall CreateDesktopShortCut(const AnsiString &Name,
  189. const AnsiString &File, const AnsiString & Params, const AnsiString & Description,
  190. int SpecialFolder)
  191. {
  192. IShellLink* pLink;
  193. IPersistFile* pPersistFile;
  194. LPMALLOC ShellMalloc;
  195. LPITEMIDLIST DesktopPidl;
  196. char DesktopDir[MAX_PATH];
  197. if (SpecialFolder < 0)
  198. {
  199. SpecialFolder = CSIDL_DESKTOPDIRECTORY;
  200. }
  201. try
  202. {
  203. if (FAILED(SHGetMalloc(&ShellMalloc))) throw Exception("");
  204. if (FAILED(SHGetSpecialFolderLocation(NULL, SpecialFolder, &DesktopPidl)))
  205. {
  206. throw Exception("");
  207. }
  208. if (!SHGetPathFromIDList(DesktopPidl, DesktopDir))
  209. {
  210. ShellMalloc->Free(DesktopPidl);
  211. ShellMalloc->Release();
  212. throw Exception("");
  213. }
  214. ShellMalloc->Free(DesktopPidl);
  215. ShellMalloc->Release();
  216. if (SUCCEEDED(CoInitialize(NULL)))
  217. {
  218. if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  219. IID_IShellLink, (void **) &pLink)))
  220. {
  221. try
  222. {
  223. pLink->SetPath(File.c_str());
  224. pLink->SetDescription(Description.c_str());
  225. pLink->SetArguments(Params.c_str());
  226. pLink->SetShowCmd(SW_SHOW);
  227. if (SUCCEEDED(pLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile)))
  228. {
  229. try
  230. {
  231. WideString strShortCutLocation(DesktopDir);
  232. // Name can contain even path (e.g. to create quick launch icon)
  233. strShortCutLocation += AnsiString("\\") + Name + ".lnk";
  234. if (!SUCCEEDED(pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE)))
  235. {
  236. throw Exception("");
  237. }
  238. }
  239. __finally
  240. {
  241. pPersistFile->Release();
  242. }
  243. }
  244. }
  245. __finally
  246. {
  247. pLink->Release();
  248. }
  249. }
  250. CoUninitialize();
  251. }
  252. }
  253. catch(...)
  254. {
  255. throw Exception(CREATE_SHORTCUT_ERROR);
  256. }
  257. }
  258. //---------------------------------------------------------------------------
  259. void __fastcall ValidateMaskEdit(TComboBox * Edit)
  260. {
  261. assert(Edit != NULL);
  262. TFileMasks Masks = Edit->Text;
  263. int Start, Length;
  264. if (!Masks.IsValid(Start, Length))
  265. {
  266. SimpleErrorDialog(FMTLOAD(MASK_ERROR, (Masks.Masks.SubString(Start + 1, Length))));
  267. Edit->SetFocus();
  268. Edit->SelStart = Start;
  269. Edit->SelLength = Length;
  270. Abort();
  271. }
  272. }
  273. //---------------------------------------------------------------------------
  274. void __fastcall ValidateMaskEdit(TEdit * Edit)
  275. {
  276. assert(Edit != NULL);
  277. TFileMasks Masks = Edit->Text;
  278. int Start, Length;
  279. if (!Masks.IsValid(Start, Length))
  280. {
  281. SimpleErrorDialog(FMTLOAD(MASK_ERROR, (Masks.Masks.SubString(Start + 1, Length))));
  282. Edit->SetFocus();
  283. Edit->SelStart = Start;
  284. Edit->SelLength = Length;
  285. Abort();
  286. }
  287. }
  288. //---------------------------------------------------------------------------
  289. void __fastcall ExitActiveControl(TForm * Form)
  290. {
  291. if (Form->ActiveControl != NULL)
  292. {
  293. TNotifyEvent OnExit = ((TEdit*)Form->ActiveControl)->OnExit;
  294. if (OnExit != NULL)
  295. {
  296. OnExit(Form->ActiveControl);
  297. }
  298. }
  299. }
  300. //---------------------------------------------------------------------------
  301. void __fastcall OpenBrowser(AnsiString URL)
  302. {
  303. ShellExecute(Application->Handle, "open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
  304. }
  305. //---------------------------------------------------------------------------
  306. bool __fastcall IsFormatInClipboard(unsigned int Format)
  307. {
  308. bool Result = OpenClipboard(0);
  309. if (Result)
  310. {
  311. Result = IsClipboardFormatAvailable(Format);
  312. CloseClipboard();
  313. }
  314. return Result;
  315. }
  316. //---------------------------------------------------------------------------
  317. bool __fastcall TextFromClipboard(AnsiString & Text)
  318. {
  319. bool Result = OpenClipboard(0);
  320. if (Result)
  321. {
  322. HANDLE Handle = NULL;
  323. try
  324. {
  325. Handle = GetClipboardData(CF_TEXT);
  326. Result = (Handle != NULL);
  327. if (Result)
  328. {
  329. Text = static_cast<const char*>(GlobalLock(Handle));
  330. }
  331. }
  332. __finally
  333. {
  334. if (Handle != NULL)
  335. {
  336. GlobalUnlock(Handle);
  337. }
  338. CloseClipboard();
  339. }
  340. }
  341. return Result;
  342. }
  343. //---------------------------------------------------------------------------
  344. static bool __fastcall GetResource(
  345. const AnsiString ResName, void *& Content, unsigned long & Size)
  346. {
  347. HRSRC Resource = FindResourceEx(HInstance, RT_RCDATA, ResName.c_str(),
  348. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
  349. bool Result = (Resource != NULL);
  350. if (Result)
  351. {
  352. Size = SizeofResource(HInstance, Resource);
  353. if (!Size)
  354. {
  355. throw Exception(FORMAT("Cannot get size of resource %s", (ResName)));
  356. }
  357. Content = LoadResource(HInstance, Resource);
  358. if (!Content)
  359. {
  360. throw Exception(FORMAT("Cannot read resource %s", (ResName)));
  361. }
  362. Content = LockResource(Content);
  363. if (!Content)
  364. {
  365. throw Exception(FORMAT("Cannot lock resource %s", (ResName)));
  366. }
  367. }
  368. return Result;
  369. }
  370. //---------------------------------------------------------------------------
  371. bool __fastcall DumpResourceToFile(const AnsiString ResName,
  372. const AnsiString FileName)
  373. {
  374. void * Content;
  375. unsigned long Size;
  376. bool Result = GetResource(ResName, Content, Size);
  377. if (Result)
  378. {
  379. FILE * f = fopen(FileName.c_str(), "wb");
  380. if (!f)
  381. {
  382. throw Exception(FORMAT("Cannot create file %s", (FileName)));
  383. }
  384. if (fwrite(Content, 1, Size, f) != Size)
  385. {
  386. throw Exception(FORMAT("Cannot write to file %s", (FileName)));
  387. }
  388. fclose(f);
  389. }
  390. return Result;
  391. }
  392. //---------------------------------------------------------------------------
  393. AnsiString __fastcall ReadResource(const AnsiString ResName)
  394. {
  395. void * Content;
  396. unsigned long Size;
  397. AnsiString Result;
  398. if (GetResource(ResName, Content, Size))
  399. {
  400. Result = AnsiString(static_cast<char*>(Content), Size);
  401. }
  402. return Result;
  403. }
  404. //---------------------------------------------------------------------------
  405. template <class T>
  406. void __fastcall BrowseForExecutableT(T * Control, AnsiString Title,
  407. AnsiString Filter, bool FileNameCommand, bool Escape)
  408. {
  409. AnsiString Executable, Program, Params, Dir;
  410. Executable = Control->Text;
  411. if (FileNameCommand)
  412. {
  413. ReformatFileNameCommand(Executable);
  414. }
  415. SplitCommand(Executable, Program, Params, Dir);
  416. TOpenDialog * FileDialog = new TOpenDialog(Application);
  417. try
  418. {
  419. if (Escape)
  420. {
  421. Program = StringReplace(Program, "\\\\", "\\", TReplaceFlags() << rfReplaceAll);
  422. }
  423. AnsiString ExpandedProgram = ExpandEnvironmentVariables(Program);
  424. FileDialog->FileName = ExpandedProgram;
  425. FileDialog->Filter = Filter;
  426. FileDialog->Title = Title;
  427. if (FileDialog->Execute())
  428. {
  429. TNotifyEvent PrevOnChange = Control->OnChange;
  430. Control->OnChange = NULL;
  431. try
  432. {
  433. // preserve unexpanded file, if the destination has not changed actually
  434. if (!CompareFileName(ExpandedProgram, FileDialog->FileName))
  435. {
  436. Program = FileDialog->FileName;
  437. if (Escape)
  438. {
  439. Program = StringReplace(Program, "\\", "\\\\", TReplaceFlags() << rfReplaceAll);
  440. }
  441. }
  442. Control->Text = FormatCommand(Program, Params);
  443. }
  444. __finally
  445. {
  446. Control->OnChange = PrevOnChange;
  447. }
  448. if (Control->OnExit != NULL)
  449. {
  450. Control->OnExit(Control);
  451. }
  452. }
  453. }
  454. __finally
  455. {
  456. delete FileDialog;
  457. }
  458. }
  459. //---------------------------------------------------------------------------
  460. void __fastcall BrowseForExecutable(TEdit * Control, AnsiString Title,
  461. AnsiString Filter, bool FileNameCommand, bool Escape)
  462. {
  463. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  464. }
  465. //---------------------------------------------------------------------------
  466. void __fastcall BrowseForExecutable(TComboBox * Control, AnsiString Title,
  467. AnsiString Filter, bool FileNameCommand, bool Escape)
  468. {
  469. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  470. }
  471. //---------------------------------------------------------------------------
  472. void __fastcall CopyToClipboard(AnsiString Text)
  473. {
  474. HANDLE Data;
  475. void * DataPtr;
  476. if (OpenClipboard(0))
  477. {
  478. try
  479. {
  480. Data = GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, Text.Length() + 1);
  481. try
  482. {
  483. DataPtr = GlobalLock(Data);
  484. try
  485. {
  486. memcpy(DataPtr, Text.c_str(), Text.Length() + 1);
  487. EmptyClipboard();
  488. SetClipboardData(CF_TEXT, Data);
  489. }
  490. __finally
  491. {
  492. GlobalUnlock(Data);
  493. }
  494. }
  495. catch(...)
  496. {
  497. GlobalFree(Data);
  498. throw;
  499. }
  500. }
  501. __finally
  502. {
  503. CloseClipboard();
  504. }
  505. }
  506. else
  507. {
  508. throw Exception(Consts_SCannotOpenClipboard);
  509. }
  510. }
  511. //---------------------------------------------------------------------------
  512. void __fastcall CopyToClipboard(TStrings * Strings)
  513. {
  514. if (Strings->Count > 0)
  515. {
  516. if (Strings->Count == 1)
  517. {
  518. CopyToClipboard(Strings->Strings[0]);
  519. }
  520. else
  521. {
  522. CopyToClipboard(Strings->Text);
  523. }
  524. }
  525. }
  526. //---------------------------------------------------------------------------
  527. bool __fastcall IsWin64()
  528. {
  529. static int Result = -1;
  530. if (Result < 0)
  531. {
  532. typedef BOOL WINAPI (*IsWow64ProcessType)(HANDLE Process, PBOOL Wow64Process);
  533. Result = 0;
  534. HMODULE Kernel = GetModuleHandle(kernel32);
  535. if (Kernel != NULL)
  536. {
  537. IsWow64ProcessType IsWow64Process =
  538. (IsWow64ProcessType)GetProcAddress(Kernel, "IsWow64Process");
  539. if (IsWow64Process != NULL)
  540. {
  541. BOOL Wow64Process = FALSE;
  542. if (IsWow64Process(GetCurrentProcess(), &Wow64Process))
  543. {
  544. if (Wow64Process)
  545. {
  546. Result = 1;
  547. }
  548. }
  549. }
  550. }
  551. }
  552. return (Result > 0);
  553. }
  554. //---------------------------------------------------------------------------
  555. // Code from http://gentoo.osuosl.org/distfiles/cl331.zip/io/
  556. // The autoproxy functions were only documented in WinHTTP 5.1, so we have to
  557. // provide the necessary defines and structures ourselves
  558. #ifndef WINHTTP_ACCESS_TYPE_DEFAULT_PROXY
  559. #define HINTERNET HANDLE
  560. typedef struct
  561. {
  562. WORD dwAccessType;
  563. LPWSTR lpszProxy;
  564. LPWSTR lpszProxyBypass;
  565. } WINHTTP_PROXY_INFO;
  566. typedef struct {
  567. BOOL fAutoDetect;
  568. LPWSTR lpszAutoConfigUrl;
  569. LPWSTR lpszProxy;
  570. LPWSTR lpszProxyBypass;
  571. } WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
  572. #endif /* WinHTTP 5.1 defines and structures */
  573. typedef BOOL (*WINHTTPGETDEFAULTPROXYCONFIGURATION)(WINHTTP_PROXY_INFO * pProxyInfo);
  574. typedef BOOL (*WINHTTPGETIEPROXYCONFIGFORCURRENTUSER)(
  575. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig);
  576. //---------------------------------------------------------------------------
  577. bool __fastcall AutodetectProxyUrl(AnsiString & Proxy)
  578. {
  579. static HMODULE WinHTTP = NULL;
  580. static WINHTTPGETDEFAULTPROXYCONFIGURATION WinHttpGetDefaultProxyConfiguration = NULL;
  581. static WINHTTPGETIEPROXYCONFIGFORCURRENTUSER WinHttpGetIEProxyConfigForCurrentUser = NULL;
  582. bool Result = true;
  583. /* Under Win2K SP3, XP and 2003 (or at least Windows versions with
  584. WinHTTP 5.1 installed in some way, it officially shipped with the
  585. versions mentioned earlier) we can use WinHTTP AutoProxy support,
  586. which implements the Web Proxy Auto-Discovery (WPAD) protocol from
  587. an internet draft that expired in May 2001. Under older versions of
  588. Windows we have to use the WinINet InternetGetProxyInfo, however this
  589. consists of a ghastly set of kludges that were never meant to be
  590. exposed to the outside world (they were only crowbarred out of MS
  591. as part of the DoJ consent decree), and user experience with them is
  592. that they don't really work except in the one special way in which
  593. MS-internal code calls them. Since we don't know what this is, we
  594. use the WinHTTP functions instead */
  595. if (WinHTTP == NULL)
  596. {
  597. if ((WinHTTP = LoadLibrary("WinHTTP.dll")) == NULL)
  598. {
  599. Result = false;
  600. }
  601. else
  602. {
  603. WinHttpGetDefaultProxyConfiguration = (WINHTTPGETDEFAULTPROXYCONFIGURATION)
  604. GetProcAddress(WinHTTP, "WinHttpGetDefaultProxyConfiguration");
  605. WinHttpGetIEProxyConfigForCurrentUser = (WINHTTPGETIEPROXYCONFIGFORCURRENTUSER)
  606. GetProcAddress(WinHTTP, "WinHttpGetIEProxyConfigForCurrentUser");
  607. if ((WinHttpGetDefaultProxyConfiguration == NULL) ||
  608. (WinHttpGetIEProxyConfigForCurrentUser == NULL))
  609. {
  610. FreeLibrary(WinHTTP);
  611. Result = false;
  612. }
  613. }
  614. }
  615. if (Result)
  616. {
  617. Result = false;
  618. /* Forst we try for proxy info direct from the registry if
  619. it's available. */
  620. if (!Result)
  621. {
  622. WINHTTP_PROXY_INFO ProxyInfo;
  623. memset(&ProxyInfo, 0, sizeof(ProxyInfo));
  624. if ((WinHttpGetDefaultProxyConfiguration != NULL) &&
  625. WinHttpGetDefaultProxyConfiguration(&ProxyInfo))
  626. {
  627. if (ProxyInfo.lpszProxy != NULL)
  628. {
  629. Proxy = ProxyInfo.lpszProxy;
  630. GlobalFree(ProxyInfo.lpszProxy);
  631. Result = true;
  632. }
  633. if (ProxyInfo.lpszProxyBypass != NULL)
  634. {
  635. GlobalFree(ProxyInfo.lpszProxyBypass);
  636. }
  637. }
  638. }
  639. /* The next fallback is to get the proxy info from MSIE. This is also
  640. usually much quicker than WinHttpGetProxyForUrl(), although sometimes
  641. it seems to fall back to that, based on the longish delay involved.
  642. Another issue with this is that it won't work in a service process
  643. that isn't impersonating an interactive user (since there isn't a
  644. current user), but in that case we just fall back to
  645. WinHttpGetProxyForUrl() */
  646. if (!Result)
  647. {
  648. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyInfo;
  649. memset(&IEProxyInfo, 0, sizeof(IEProxyInfo));
  650. if ((WinHttpGetIEProxyConfigForCurrentUser != NULL) &&
  651. WinHttpGetIEProxyConfigForCurrentUser(&IEProxyInfo))
  652. {
  653. if (IEProxyInfo.lpszProxy != NULL)
  654. {
  655. Proxy = IEProxyInfo.lpszProxy;
  656. GlobalFree(IEProxyInfo.lpszProxy);
  657. Result = true;
  658. }
  659. if (IEProxyInfo.lpszAutoConfigUrl != NULL)
  660. {
  661. GlobalFree(IEProxyInfo.lpszAutoConfigUrl);
  662. }
  663. if (IEProxyInfo.lpszProxyBypass != NULL)
  664. {
  665. GlobalFree(IEProxyInfo.lpszProxyBypass);
  666. }
  667. }
  668. }
  669. // We can also use WinHttpGetProxyForUrl, but it is lengthy
  670. // See the source address of the code for example
  671. }
  672. return Result;
  673. }