Tools.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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. #define INITGUID
  9. #include <propkey.h>
  10. #include <Common.h>
  11. #include <TextsWin.h>
  12. #include <Exceptions.h>
  13. #include <CoreMain.h>
  14. #include <RemoteFiles.h>
  15. #include "GUITools.h"
  16. #include "VCLCommon.h"
  17. #include "Setup.h"
  18. #include "Tools.h"
  19. #include <WinHelpViewer.hpp>
  20. #include <PasTools.hpp>
  21. #include <System.Win.ComObj.hpp>
  22. //---------------------------------------------------------------------------
  23. #pragma package(smart_init)
  24. //---------------------------------------------------------------------------
  25. TFontStyles __fastcall IntToFontStyles(int value)
  26. {
  27. TFontStyles Result;
  28. for (int i = fsBold; i <= fsStrikeOut; i++)
  29. {
  30. if (value & 1)
  31. {
  32. Result << (TFontStyle)i;
  33. }
  34. value >>= 1;
  35. }
  36. return Result;
  37. }
  38. //---------------------------------------------------------------------------
  39. int __fastcall FontStylesToInt(const TFontStyles value)
  40. {
  41. int Result = 0;
  42. for (int i = fsStrikeOut; i >= fsBold; i--)
  43. {
  44. Result <<= 1;
  45. if (value.Contains((TFontStyle)i))
  46. {
  47. Result |= 1;
  48. }
  49. }
  50. return Result;
  51. }
  52. //---------------------------------------------------------------------------
  53. void __fastcall CenterFormOn(TForm * Form, TControl * CenterOn)
  54. {
  55. TPoint ScreenPoint = CenterOn->ClientToScreen(TPoint(0, 0));
  56. Form->Left = ScreenPoint.x + (CenterOn->Width / 2) - (Form->Width / 2);
  57. Form->Top = ScreenPoint.y + (CenterOn->Height / 2) - (Form->Height / 2);
  58. }
  59. //---------------------------------------------------------------------------
  60. UnicodeString __fastcall GetListViewStr(TListView * ListView)
  61. {
  62. UnicodeString Result;
  63. for (int Index = 0; Index < ListView->Columns->Count; Index++)
  64. {
  65. if (!Result.IsEmpty())
  66. {
  67. Result += L",";
  68. }
  69. Result += IntToStr(ListView->Column[Index]->Width);
  70. }
  71. return Result;
  72. }
  73. //---------------------------------------------------------------------------
  74. void __fastcall LoadListViewStr(TListView * ListView, UnicodeString LayoutStr)
  75. {
  76. int Index = 0;
  77. while (!LayoutStr.IsEmpty() && (Index < ListView->Columns->Count))
  78. {
  79. ListView->Column[Index]->Width = StrToIntDef(
  80. ::CutToChar(LayoutStr, L',', true), ListView->Column[Index]->Width);
  81. Index++;
  82. }
  83. }
  84. //---------------------------------------------------------------------------
  85. void __fastcall RestoreForm(UnicodeString Data, TForm * Form)
  86. {
  87. assert(Form);
  88. if (!Data.IsEmpty())
  89. {
  90. Forms::TMonitor * Monitor = FormMonitor(Form);
  91. TRect Bounds = Form->BoundsRect;
  92. int Left = StrToIntDef(::CutToChar(Data, L';', true), Bounds.Left);
  93. int Top = StrToIntDef(::CutToChar(Data, L';', true), Bounds.Top);
  94. bool DefaultPos = (Left == -1) && (Top == -1);
  95. if (!DefaultPos)
  96. {
  97. Bounds.Left = Left;
  98. Bounds.Top = Top;
  99. }
  100. else
  101. {
  102. Bounds.Left = 0;
  103. Bounds.Top = 0;
  104. }
  105. Bounds.Right = StrToIntDef(::CutToChar(Data, L';', true), Bounds.Right);
  106. Bounds.Bottom = StrToIntDef(::CutToChar(Data, L';', true), Bounds.Bottom);
  107. TWindowState State = (TWindowState)StrToIntDef(::CutToChar(Data, L';', true), (int)wsNormal);
  108. Form->WindowState = State;
  109. if (State == wsNormal)
  110. {
  111. // move to the target monitor
  112. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  113. // reduce window size to that of monitor size
  114. // (this does not cut window into monitor!)
  115. if (Bounds.Width() > Monitor->WorkareaRect.Width())
  116. {
  117. Bounds.Right -= (Bounds.Width() - Monitor->WorkareaRect.Width());
  118. }
  119. if (Bounds.Height() > Monitor->WorkareaRect.Height())
  120. {
  121. Bounds.Bottom -= (Bounds.Height() - Monitor->WorkareaRect.Height());
  122. }
  123. if (DefaultPos ||
  124. ((Bounds.Left < Monitor->Left) ||
  125. (Bounds.Left > Monitor->Left + Monitor->WorkareaRect.Width() - 20) ||
  126. (Bounds.Top < Monitor->Top) ||
  127. (Bounds.Top > Monitor->Top + Monitor->WorkareaRect.Height() - 20)))
  128. {
  129. if (Monitor->Primary)
  130. {
  131. if ((Application->MainForm == NULL) || (Application->MainForm == Form))
  132. {
  133. Form->Position = poDefaultPosOnly;
  134. }
  135. else
  136. {
  137. Form->Position = poOwnerFormCenter;
  138. }
  139. Form->Width = Bounds.Width();
  140. Form->Height = Bounds.Height();
  141. }
  142. else
  143. {
  144. // when positioning on non-primary monitor, we need
  145. // to handle that ourselves, so place window to center
  146. Form->SetBounds(Monitor->Left + ((Monitor->Width - Bounds.Width()) / 2),
  147. Monitor->Top + ((Monitor->Height - Bounds.Height()) / 2),
  148. Bounds.Width(), Bounds.Height());
  149. Form->Position = poDesigned;
  150. }
  151. }
  152. else
  153. {
  154. Form->Position = poDesigned;
  155. Form->BoundsRect = Bounds;
  156. }
  157. }
  158. else if (State == wsMaximized)
  159. {
  160. Form->Position = poDesigned;
  161. Bounds = Form->BoundsRect;
  162. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  163. Form->BoundsRect = Bounds;
  164. }
  165. }
  166. else if (Form->Position == poDesigned)
  167. {
  168. Form->Position = poDefaultPosOnly;
  169. }
  170. }
  171. //---------------------------------------------------------------------------
  172. UnicodeString __fastcall StoreForm(TCustomForm * Form)
  173. {
  174. assert(Form);
  175. TRect Bounds = Form->BoundsRect;
  176. OffsetRect(Bounds, -Form->Monitor->Left, -Form->Monitor->Top);
  177. return FORMAT(L"%d;%d;%d;%d;%d", ((int)Bounds.Left, (int)Bounds.Top,
  178. (int)Bounds.Right, (int)Bounds.Bottom,
  179. // we do not want WinSCP to start minimized next time (we cannot handle that anyway).
  180. // note that WindowState is wsNormal when window in minimized for some reason.
  181. // actually it is wsMinimized only when minimized by MSVDM
  182. (int)(Form->WindowState == wsMinimized ? wsNormal : Form->WindowState)));
  183. }
  184. //---------------------------------------------------------------------------
  185. void __fastcall RestoreFormSize(UnicodeString Data, TForm * Form)
  186. {
  187. int Width = StrToIntDef(::CutToChar(Data, L',', true), Form->Width);
  188. int Height = StrToIntDef(::CutToChar(Data, L',', true), Form->Height);
  189. ResizeForm(Form, Width, Height);
  190. }
  191. //---------------------------------------------------------------------------
  192. UnicodeString __fastcall StoreFormSize(TForm * Form)
  193. {
  194. return FORMAT(L"%d,%d", (Form->Width, Form->Height));
  195. }
  196. //---------------------------------------------------------------------------
  197. bool __fastcall ExecuteShellAndWait(const UnicodeString Path, const UnicodeString Params)
  198. {
  199. return ExecuteShellAndWait(Application->Handle, Path, Params,
  200. &Application->ProcessMessages);
  201. }
  202. //---------------------------------------------------------------------------
  203. bool __fastcall ExecuteShellAndWait(const UnicodeString Command)
  204. {
  205. return ExecuteShellAndWait(Application->Handle, Command,
  206. &Application->ProcessMessages);
  207. }
  208. //---------------------------------------------------------------------------
  209. IShellLink * __fastcall CreateDesktopShortCut(const UnicodeString & Name,
  210. const UnicodeString &File, const UnicodeString & Params, const UnicodeString & Description,
  211. int SpecialFolder, bool Return)
  212. {
  213. IShellLink* pLink = NULL;
  214. if (SpecialFolder < 0)
  215. {
  216. SpecialFolder = CSIDL_DESKTOPDIRECTORY;
  217. }
  218. try
  219. {
  220. if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  221. IID_IShellLink, (void **) &pLink)))
  222. {
  223. try
  224. {
  225. pLink->SetPath(File.c_str());
  226. pLink->SetDescription(Description.c_str());
  227. pLink->SetArguments(Params.c_str());
  228. pLink->SetShowCmd(SW_SHOW);
  229. // Explicitly setting icon file,
  230. // without this icons are not shown at least in Windows 7 jumplist
  231. pLink->SetIconLocation(File.c_str(), 0);
  232. IPersistFile* pPersistFile;
  233. if (!Return &&
  234. SUCCEEDED(pLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile)))
  235. {
  236. try
  237. {
  238. LPMALLOC ShellMalloc;
  239. LPITEMIDLIST DesktopPidl;
  240. wchar_t DesktopDir[MAX_PATH];
  241. OleCheck(SHGetMalloc(&ShellMalloc));
  242. try
  243. {
  244. OleCheck(SHGetSpecialFolderLocation(NULL, SpecialFolder, &DesktopPidl));
  245. OleCheck(SHGetPathFromIDList(DesktopPidl, DesktopDir));
  246. }
  247. __finally
  248. {
  249. ShellMalloc->Free(DesktopPidl);
  250. ShellMalloc->Release();
  251. }
  252. WideString strShortCutLocation(DesktopDir);
  253. // Name can contain even path (e.g. to create quick launch icon)
  254. strShortCutLocation += UnicodeString(L"\\") + Name + L".lnk";
  255. OleCheck(pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE));
  256. }
  257. __finally
  258. {
  259. pPersistFile->Release();
  260. }
  261. }
  262. // this is necessary for Windows 7 taskbar jump list links
  263. IPropertyStore * PropertyStore;
  264. if (SUCCEEDED(pLink->QueryInterface(IID_IPropertyStore, (void**)&PropertyStore)))
  265. {
  266. PROPVARIANT Prop;
  267. Prop.vt = VT_LPWSTR;
  268. Prop.pwszVal = Name.c_str();
  269. PropertyStore->SetValue(PKEY_Title, Prop);
  270. PropertyStore->Commit();
  271. PropertyStore->Release();
  272. }
  273. }
  274. catch(...)
  275. {
  276. pLink->Release();
  277. throw;
  278. }
  279. if (!Return)
  280. {
  281. pLink->Release();
  282. pLink = NULL;
  283. }
  284. }
  285. }
  286. catch(Exception & E)
  287. {
  288. throw ExtException(&E, LoadStr(CREATE_SHORTCUT_ERROR));
  289. }
  290. return pLink;
  291. }
  292. //---------------------------------------------------------------------------
  293. IShellLink * __fastcall CreateDesktopSessionShortCut(
  294. const UnicodeString & SessionName, UnicodeString Name,
  295. const UnicodeString & AdditionalParams, int SpecialFolder, bool Return)
  296. {
  297. bool DefaultsOnly;
  298. UnicodeString InfoTip;
  299. bool IsFolder = StoredSessions->IsFolder(SessionName);
  300. bool IsWorkspace = StoredSessions->IsWorkspace(SessionName);
  301. if (IsFolder || IsWorkspace)
  302. {
  303. InfoTip = FMTLOAD(
  304. (IsFolder ? SHORTCUT_INFO_TIP_FOLDER : SHORTCUT_INFO_TIP_WORKSPACE),
  305. (SessionName));
  306. if (Name.IsEmpty())
  307. {
  308. // no slashes in filename
  309. Name = UnixExtractFileName(SessionName);
  310. }
  311. }
  312. else
  313. {
  314. TSessionData * SessionData =
  315. StoredSessions->ParseUrl(SessionName, NULL, DefaultsOnly);
  316. InfoTip =
  317. FMTLOAD(SHORTCUT_INFO_TIP, (SessionName, SessionData->InfoTip));
  318. if (Name.IsEmpty())
  319. {
  320. // no slashes in filename
  321. Name = SessionData->LocalName;
  322. }
  323. delete SessionData;
  324. }
  325. return
  326. CreateDesktopShortCut(ValidLocalFileName(Name), Application->ExeName,
  327. FORMAT(L"\"%s\"%s%s", (SessionName, (AdditionalParams.IsEmpty() ? L"" : L" "), AdditionalParams)),
  328. InfoTip, SpecialFolder, Return);
  329. }
  330. //---------------------------------------------------------------------------
  331. template<class TEditControl>
  332. void __fastcall ValidateMaskEditT(const UnicodeString & Mask, TEditControl * Edit, int ForceDirectoryMasks)
  333. {
  334. assert(Edit != NULL);
  335. TFileMasks Masks(ForceDirectoryMasks);
  336. try
  337. {
  338. Masks = Mask;
  339. }
  340. catch(EFileMasksException & E)
  341. {
  342. ShowExtendedException(&E);
  343. Edit->SetFocus();
  344. // This does not work for TEdit and TMemo (descendants of TCustomEdit) anymore,
  345. // as it re-selects whole text on exception in TCustomEdit.CMExit
  346. Edit->SelStart = E.ErrorStart - 1;
  347. Edit->SelLength = E.ErrorLen;
  348. Abort();
  349. }
  350. }
  351. //---------------------------------------------------------------------------
  352. void __fastcall ValidateMaskEdit(TComboBox * Edit)
  353. {
  354. ValidateMaskEditT(Edit->Text, Edit, -1);
  355. }
  356. //---------------------------------------------------------------------------
  357. void __fastcall ValidateMaskEdit(TEdit * Edit)
  358. {
  359. ValidateMaskEditT(Edit->Text, Edit, -1);
  360. }
  361. //---------------------------------------------------------------------------
  362. void __fastcall ValidateMaskEdit(TMemo * Edit, bool Directory)
  363. {
  364. UnicodeString Mask = TFileMasks::ComposeMaskStr(GetUnwrappedMemoLines(Edit), Directory);
  365. ValidateMaskEditT(Mask, Edit, Directory ? 1 : 0);
  366. }
  367. //---------------------------------------------------------------------------
  368. TStrings * __fastcall GetUnwrappedMemoLines(TMemo * Memo)
  369. {
  370. TStrings * Result = new TStringList();
  371. // This removes soft linebreakes when text in memo wraps
  372. // (Memo->Lines includes soft linebreaks, while Memo->Text does not)
  373. Result->Text = Memo->Text;
  374. return Result;
  375. }
  376. //---------------------------------------------------------------------------
  377. void __fastcall ExitActiveControl(TForm * Form)
  378. {
  379. if (Form->ActiveControl != NULL)
  380. {
  381. TNotifyEvent OnExit = ((TEdit*)Form->ActiveControl)->OnExit;
  382. if (OnExit != NULL)
  383. {
  384. OnExit(Form->ActiveControl);
  385. }
  386. }
  387. }
  388. //---------------------------------------------------------------------------
  389. void __fastcall OpenBrowser(UnicodeString URL)
  390. {
  391. UnicodeString HomePageUrl = LoadStr(HOMEPAGE_URL);
  392. if (SameText(URL.SubString(1, HomePageUrl.Length()), HomePageUrl))
  393. {
  394. URL = CampaignUrl(URL);
  395. }
  396. ShellExecute(Application->Handle, L"open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
  397. }
  398. //---------------------------------------------------------------------------
  399. bool __fastcall IsFormatInClipboard(unsigned int Format)
  400. {
  401. bool Result = OpenClipboard(0);
  402. if (Result)
  403. {
  404. Result = IsClipboardFormatAvailable(Format);
  405. CloseClipboard();
  406. }
  407. return Result;
  408. }
  409. //---------------------------------------------------------------------------
  410. HANDLE __fastcall OpenTextFromClipboard(const wchar_t *& Text)
  411. {
  412. HANDLE Result = NULL;
  413. if (OpenClipboard(0))
  414. {
  415. // Check also for CF_TEXT?
  416. Result = GetClipboardData(CF_UNICODETEXT);
  417. if (Result != NULL)
  418. {
  419. Text = static_cast<const wchar_t*>(GlobalLock(Result));
  420. }
  421. else
  422. {
  423. CloseClipboard();
  424. }
  425. }
  426. return Result;
  427. }
  428. //---------------------------------------------------------------------------
  429. void __fastcall CloseTextFromClipboard(HANDLE Handle)
  430. {
  431. if (Handle != NULL)
  432. {
  433. GlobalUnlock(Handle);
  434. }
  435. CloseClipboard();
  436. }
  437. //---------------------------------------------------------------------------
  438. bool __fastcall TextFromClipboard(UnicodeString & Text)
  439. {
  440. const wchar_t * AText = NULL;
  441. HANDLE Handle = OpenTextFromClipboard(AText);
  442. bool Result = (Handle != NULL);
  443. if (Result)
  444. {
  445. Text = AText;
  446. CloseTextFromClipboard(Handle);
  447. }
  448. return Result;
  449. }
  450. //---------------------------------------------------------------------------
  451. static bool __fastcall GetResource(
  452. const UnicodeString ResName, void *& Content, unsigned long & Size)
  453. {
  454. HRSRC Resource = FindResourceEx(HInstance, RT_RCDATA, ResName.c_str(),
  455. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
  456. bool Result = (Resource != NULL);
  457. if (Result)
  458. {
  459. Size = SizeofResource(HInstance, Resource);
  460. if (!Size)
  461. {
  462. throw Exception(FORMAT(L"Cannot get size of resource %s", (ResName)));
  463. }
  464. Content = LoadResource(HInstance, Resource);
  465. if (!Content)
  466. {
  467. throw Exception(FORMAT(L"Cannot read resource %s", (ResName)));
  468. }
  469. Content = LockResource(Content);
  470. if (!Content)
  471. {
  472. throw Exception(FORMAT(L"Cannot lock resource %s", (ResName)));
  473. }
  474. }
  475. return Result;
  476. }
  477. //---------------------------------------------------------------------------
  478. bool __fastcall DumpResourceToFile(const UnicodeString ResName,
  479. const UnicodeString FileName)
  480. {
  481. void * Content;
  482. unsigned long Size;
  483. bool Result = GetResource(ResName, Content, Size);
  484. if (Result)
  485. {
  486. FILE * f = _wfopen(FileName.c_str(), L"wb");
  487. if (!f)
  488. {
  489. throw Exception(FORMAT(L"Cannot create file %s", (FileName)));
  490. }
  491. if (fwrite(Content, 1, Size, f) != Size)
  492. {
  493. throw Exception(FORMAT(L"Cannot write to file %s", (FileName)));
  494. }
  495. fclose(f);
  496. }
  497. return Result;
  498. }
  499. //---------------------------------------------------------------------------
  500. UnicodeString __fastcall ReadResource(const UnicodeString ResName)
  501. {
  502. void * Content;
  503. unsigned long Size;
  504. UnicodeString Result;
  505. if (GetResource(ResName, Content, Size))
  506. {
  507. Result = UnicodeString(UTF8String(static_cast<char*>(Content), Size));
  508. }
  509. return Result;
  510. }
  511. //---------------------------------------------------------------------------
  512. template <class T>
  513. void __fastcall BrowseForExecutableT(T * Control, UnicodeString Title,
  514. UnicodeString Filter, bool FileNameCommand, bool Escape)
  515. {
  516. UnicodeString Executable, Program, Params, Dir;
  517. Executable = Control->Text;
  518. if (FileNameCommand)
  519. {
  520. ReformatFileNameCommand(Executable);
  521. }
  522. SplitCommand(Executable, Program, Params, Dir);
  523. TOpenDialog * FileDialog = new TOpenDialog(Application);
  524. try
  525. {
  526. if (Escape)
  527. {
  528. Program = StringReplace(Program, L"\\\\", L"\\", TReplaceFlags() << rfReplaceAll);
  529. }
  530. UnicodeString ExpandedProgram = ExpandEnvironmentVariables(Program);
  531. FileDialog->FileName = ExpandedProgram;
  532. UnicodeString InitialDir = ExtractFilePath(ExpandedProgram);
  533. if (!InitialDir.IsEmpty())
  534. {
  535. FileDialog->InitialDir = InitialDir;
  536. }
  537. FileDialog->Filter = Filter;
  538. FileDialog->Title = Title;
  539. if (FileDialog->Execute())
  540. {
  541. TNotifyEvent PrevOnChange = Control->OnChange;
  542. Control->OnChange = NULL;
  543. try
  544. {
  545. // preserve unexpanded file, if the destination has not changed actually
  546. if (!CompareFileName(ExpandedProgram, FileDialog->FileName))
  547. {
  548. Program = FileDialog->FileName;
  549. if (Escape)
  550. {
  551. Program = StringReplace(Program, L"\\", L"\\\\", TReplaceFlags() << rfReplaceAll);
  552. }
  553. }
  554. Control->Text = FormatCommand(Program, Params);
  555. }
  556. __finally
  557. {
  558. Control->OnChange = PrevOnChange;
  559. }
  560. if (Control->OnExit != NULL)
  561. {
  562. Control->OnExit(Control);
  563. }
  564. }
  565. }
  566. __finally
  567. {
  568. delete FileDialog;
  569. }
  570. }
  571. //---------------------------------------------------------------------------
  572. void __fastcall BrowseForExecutable(TEdit * Control, UnicodeString Title,
  573. UnicodeString Filter, bool FileNameCommand, bool Escape)
  574. {
  575. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  576. }
  577. //---------------------------------------------------------------------------
  578. void __fastcall BrowseForExecutable(TComboBox * Control, UnicodeString Title,
  579. UnicodeString Filter, bool FileNameCommand, bool Escape)
  580. {
  581. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  582. }
  583. //---------------------------------------------------------------------------
  584. bool __fastcall FontDialog(TFont * Font)
  585. {
  586. bool Result;
  587. TFontDialog * Dialog = new TFontDialog(Application);
  588. try
  589. {
  590. Dialog->Device = fdScreen;
  591. Dialog->Options = TFontDialogOptions() << fdForceFontExist;
  592. Dialog->Font = Font;
  593. Result = Dialog->Execute();
  594. if (Result)
  595. {
  596. Font->Assign(Dialog->Font);
  597. }
  598. }
  599. __finally
  600. {
  601. delete Dialog;
  602. }
  603. return Result;
  604. }
  605. //---------------------------------------------------------------------------
  606. bool __fastcall SaveDialog(UnicodeString Title, UnicodeString Filter,
  607. UnicodeString DefaultExt, UnicodeString & FileName)
  608. {
  609. bool Result;
  610. #if 0
  611. TFileSaveDialog * Dialog = new TFileSaveDialog(Application);
  612. try
  613. {
  614. Dialog->Title = Title;
  615. FilterToFileTypes(Filter, Dialog->FileTypes);
  616. Dialog->DefaultExtension = DefaultExt;
  617. Dialog->FileName = FileName;
  618. UnicodeString DefaultFolder = ExtractFilePath(FileName);
  619. if (!DefaultFolder.IsEmpty())
  620. {
  621. Dialog->DefaultFolder = DefaultFolder;
  622. }
  623. Dialog->Options = Dialog->Options << fdoOverWritePrompt << fdoForceFileSystem <<
  624. fdoPathMustExist << fdoNoReadOnlyReturn;
  625. Result = Dialog->Execute();
  626. if (Result)
  627. {
  628. FileName = Dialog->FileName;
  629. }
  630. }
  631. __finally
  632. {
  633. delete Dialog;
  634. }
  635. #else
  636. TSaveDialog * Dialog = new TSaveDialog(Application);
  637. try
  638. {
  639. Dialog->Title = Title;
  640. Dialog->Filter = Filter;
  641. Dialog->DefaultExt = DefaultExt;
  642. Dialog->FileName = FileName;
  643. UnicodeString InitialDir = ExtractFilePath(FileName);
  644. if (!InitialDir.IsEmpty())
  645. {
  646. Dialog->InitialDir = InitialDir;
  647. }
  648. Dialog->Options = Dialog->Options << ofOverwritePrompt << ofPathMustExist <<
  649. ofNoReadOnlyReturn;
  650. Result = Dialog->Execute();
  651. if (Result)
  652. {
  653. FileName = Dialog->FileName;
  654. }
  655. }
  656. __finally
  657. {
  658. delete Dialog;
  659. }
  660. #endif
  661. return Result;
  662. }
  663. //---------------------------------------------------------------------------
  664. void __fastcall CopyToClipboard(UnicodeString Text)
  665. {
  666. HANDLE Data;
  667. void * DataPtr;
  668. if (OpenClipboard(0))
  669. {
  670. try
  671. {
  672. size_t Size = (Text.Length() + 1) * sizeof(wchar_t);
  673. Data = GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, Size);
  674. try
  675. {
  676. DataPtr = GlobalLock(Data);
  677. try
  678. {
  679. memcpy(DataPtr, Text.c_str(), Size);
  680. EmptyClipboard();
  681. SetClipboardData(CF_UNICODETEXT, Data);
  682. }
  683. __finally
  684. {
  685. GlobalUnlock(Data);
  686. }
  687. }
  688. catch(...)
  689. {
  690. GlobalFree(Data);
  691. throw;
  692. }
  693. }
  694. __finally
  695. {
  696. CloseClipboard();
  697. }
  698. }
  699. else
  700. {
  701. throw Exception(Vcl_Consts_SCannotOpenClipboard);
  702. }
  703. }
  704. //---------------------------------------------------------------------------
  705. void __fastcall CopyToClipboard(TStrings * Strings)
  706. {
  707. if (Strings->Count > 0)
  708. {
  709. if (Strings->Count == 1)
  710. {
  711. CopyToClipboard(Strings->Strings[0]);
  712. }
  713. else
  714. {
  715. CopyToClipboard(Strings->Text);
  716. }
  717. }
  718. }
  719. //---------------------------------------------------------------------------
  720. bool __fastcall IsWin64()
  721. {
  722. static int Result = -1;
  723. if (Result < 0)
  724. {
  725. typedef BOOL WINAPI (*IsWow64ProcessType)(HANDLE Process, PBOOL Wow64Process);
  726. Result = 0;
  727. HMODULE Kernel = GetModuleHandle(kernel32);
  728. if (Kernel != NULL)
  729. {
  730. IsWow64ProcessType IsWow64Process =
  731. (IsWow64ProcessType)GetProcAddress(Kernel, "IsWow64Process");
  732. if (IsWow64Process != NULL)
  733. {
  734. BOOL Wow64Process = FALSE;
  735. if (IsWow64Process(GetCurrentProcess(), &Wow64Process))
  736. {
  737. if (Wow64Process)
  738. {
  739. Result = 1;
  740. }
  741. }
  742. }
  743. }
  744. }
  745. return (Result > 0);
  746. }
  747. //---------------------------------------------------------------------------
  748. void __fastcall ShutDownWindows()
  749. {
  750. HANDLE Token;
  751. TOKEN_PRIVILEGES Priv;
  752. // Get a token for this process.
  753. Win32Check(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token));
  754. // Get the LUID for the shutdown privilege.
  755. Win32Check(LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &Priv.Privileges[0].Luid));
  756. Priv.PrivilegeCount = 1; // one privilege to set
  757. Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  758. // Get the shutdown privilege for this process.
  759. Win32Check(AdjustTokenPrivileges(Token, FALSE, &Priv, 0, (PTOKEN_PRIVILEGES)NULL, 0));
  760. // Shut down the system and force all applications to close.
  761. Win32Check(ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF,
  762. SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED));
  763. }
  764. //---------------------------------------------------------------------------
  765. void __fastcall EditSelectBaseName(HWND Edit)
  766. {
  767. UnicodeString Text;
  768. Text.SetLength(GetWindowTextLength(Edit) + 1);
  769. GetWindowText(Edit, Text.c_str(), Text.Length());
  770. int P = Text.LastDelimiter(L".");
  771. if (P > 0)
  772. {
  773. // SendMessage does not work, if edit control is not fully
  774. // initialized yet
  775. PostMessage(Edit, EM_SETSEL, 0, P - 1);
  776. }
  777. }
  778. //---------------------------------------------------------------------------
  779. // Code from http://gentoo.osuosl.org/distfiles/cl331.zip/io/
  780. // The autoproxy functions were only documented in WinHTTP 5.1, so we have to
  781. // provide the necessary defines and structures ourselves
  782. #ifndef WINHTTP_ACCESS_TYPE_DEFAULT_PROXY
  783. #define HINTERNET HANDLE
  784. typedef struct
  785. {
  786. WORD dwAccessType;
  787. LPWSTR lpszProxy;
  788. LPWSTR lpszProxyBypass;
  789. } WINHTTP_PROXY_INFO;
  790. typedef struct {
  791. BOOL fAutoDetect;
  792. LPWSTR lpszAutoConfigUrl;
  793. LPWSTR lpszProxy;
  794. LPWSTR lpszProxyBypass;
  795. } WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
  796. #endif /* WinHTTP 5.1 defines and structures */
  797. typedef BOOL (*WINHTTPGETDEFAULTPROXYCONFIGURATION)(WINHTTP_PROXY_INFO * pProxyInfo);
  798. typedef BOOL (*WINHTTPGETIEPROXYCONFIGFORCURRENTUSER)(
  799. IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig);
  800. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyInfo;
  801. static HMODULE WinHTTP = NULL;
  802. static WINHTTPGETDEFAULTPROXYCONFIGURATION WinHttpGetDefaultProxyConfiguration = NULL;
  803. static WINHTTPGETIEPROXYCONFIGFORCURRENTUSER WinHttpGetIEProxyConfigForCurrentUser = NULL;
  804. //---------------------------------------------------------------------------
  805. static bool __fastcall GetProxyUrlFromIE(UnicodeString & Proxy)
  806. {
  807. bool Result = false;
  808. memset(&IEProxyInfo, 0, sizeof(IEProxyInfo));
  809. if ((WinHttpGetIEProxyConfigForCurrentUser != NULL) &&
  810. WinHttpGetIEProxyConfigForCurrentUser(&IEProxyInfo))
  811. {
  812. if (IEProxyInfo.lpszProxy != NULL)
  813. {
  814. Proxy = IEProxyInfo.lpszProxy;
  815. GlobalFree(IEProxyInfo.lpszProxy);
  816. Result = true;
  817. }
  818. if (IEProxyInfo.lpszAutoConfigUrl != NULL)
  819. {
  820. GlobalFree(IEProxyInfo.lpszAutoConfigUrl);
  821. }
  822. if (IEProxyInfo.lpszProxyBypass != NULL)
  823. {
  824. GlobalFree(IEProxyInfo.lpszProxyBypass);
  825. }
  826. }
  827. return Result;
  828. }
  829. //---------------------------------------------------------------------------
  830. bool __fastcall AutodetectProxyUrl(UnicodeString & Proxy)
  831. {
  832. bool Result = true;
  833. /* Under Win2K SP3, XP and 2003 (or at least Windows versions with
  834. WinHTTP 5.1 installed in some way, it officially shipped with the
  835. versions mentioned earlier) we can use WinHTTP AutoProxy support,
  836. which implements the Web Proxy Auto-Discovery (WPAD) protocol from
  837. an internet draft that expired in May 2001. Under older versions of
  838. Windows we have to use the WinINet InternetGetProxyInfo, however this
  839. consists of a ghastly set of kludges that were never meant to be
  840. exposed to the outside world (they were only crowbarred out of MS
  841. as part of the DoJ consent decree), and user experience with them is
  842. that they don't really work except in the one special way in which
  843. MS-internal code calls them. Since we don't know what this is, we
  844. use the WinHTTP functions instead */
  845. if (WinHTTP == NULL)
  846. {
  847. if ((WinHTTP = LoadLibrary(L"WinHTTP.dll")) == NULL)
  848. {
  849. Result = false;
  850. }
  851. else
  852. {
  853. WinHttpGetDefaultProxyConfiguration = (WINHTTPGETDEFAULTPROXYCONFIGURATION)
  854. GetProcAddress(WinHTTP, "WinHttpGetDefaultProxyConfiguration");
  855. WinHttpGetIEProxyConfigForCurrentUser = (WINHTTPGETIEPROXYCONFIGFORCURRENTUSER)
  856. GetProcAddress(WinHTTP, "WinHttpGetIEProxyConfigForCurrentUser");
  857. if ((WinHttpGetDefaultProxyConfiguration == NULL) ||
  858. (WinHttpGetIEProxyConfigForCurrentUser == NULL))
  859. {
  860. FreeLibrary(WinHTTP);
  861. Result = false;
  862. }
  863. }
  864. }
  865. if (Result)
  866. {
  867. Result = false;
  868. /* Forst we try for proxy info direct from the registry if
  869. it's available. */
  870. if (!Result)
  871. {
  872. WINHTTP_PROXY_INFO ProxyInfo;
  873. memset(&ProxyInfo, 0, sizeof(ProxyInfo));
  874. if ((WinHttpGetDefaultProxyConfiguration != NULL) &&
  875. WinHttpGetDefaultProxyConfiguration(&ProxyInfo))
  876. {
  877. if (ProxyInfo.lpszProxy != NULL)
  878. {
  879. Proxy = ProxyInfo.lpszProxy;
  880. GlobalFree(ProxyInfo.lpszProxy);
  881. Result = true;
  882. }
  883. if (ProxyInfo.lpszProxyBypass != NULL)
  884. {
  885. GlobalFree(ProxyInfo.lpszProxyBypass);
  886. }
  887. }
  888. }
  889. /* The next fallback is to get the proxy info from MSIE. This is also
  890. usually much quicker than WinHttpGetProxyForUrl(), although sometimes
  891. it seems to fall back to that, based on the longish delay involved.
  892. Another issue with this is that it won't work in a service process
  893. that isn't impersonating an interactive user (since there isn't a
  894. current user), but in that case we just fall back to
  895. WinHttpGetProxyForUrl() */
  896. if (!Result)
  897. {
  898. Result = GetProxyUrlFromIE(Proxy);
  899. }
  900. // We can also use WinHttpGetProxyForUrl, but it is lengthy
  901. // See the source address of the code for example
  902. }
  903. return Result;
  904. }
  905. //---------------------------------------------------------------------------
  906. //---------------------------------------------------------------------------
  907. class TWinHelpTester : public TInterfacedObject, public IWinHelpTester
  908. {
  909. public:
  910. virtual bool __fastcall CanShowALink(const UnicodeString ALink, const UnicodeString FileName);
  911. virtual bool __fastcall CanShowTopic(const UnicodeString Topic, const UnicodeString FileName);
  912. virtual bool __fastcall CanShowContext(const int Context, const UnicodeString FileName);
  913. virtual TStringList * __fastcall GetHelpStrings(const UnicodeString ALink);
  914. virtual UnicodeString __fastcall GetHelpPath();
  915. virtual UnicodeString __fastcall GetDefaultHelpFile();
  916. IUNKNOWN
  917. };
  918. //---------------------------------------------------------------------------
  919. class TCustomHelpSelector : public TInterfacedObject, public IHelpSelector
  920. {
  921. public:
  922. __fastcall TCustomHelpSelector(const UnicodeString & Name);
  923. virtual int __fastcall SelectKeyword(TStrings * Keywords);
  924. virtual int __fastcall TableOfContents(TStrings * Contents);
  925. IUNKNOWN
  926. private:
  927. UnicodeString FName;
  928. };
  929. //---------------------------------------------------------------------------
  930. void __fastcall AssignHelpSelector(IHelpSelector * HelpSelector)
  931. {
  932. _di_IHelpSystem HelpSystem;
  933. if (GetHelpSystem(HelpSystem))
  934. {
  935. HelpSystem->AssignHelpSelector(HelpSelector);
  936. }
  937. }
  938. //---------------------------------------------------------------------------
  939. void __fastcall InitializeCustomHelp(ICustomHelpViewer * HelpViewer)
  940. {
  941. _di_IHelpManager HelpManager;
  942. RegisterViewer(HelpViewer, HelpManager);
  943. // Register dummy tester that disables win help
  944. WinHelpTester = new TWinHelpTester();
  945. AssignHelpSelector(new TCustomHelpSelector(HelpViewer->GetViewerName()));
  946. }
  947. //---------------------------------------------------------------------------
  948. void __fastcall FinalizeCustomHelp()
  949. {
  950. AssignHelpSelector(NULL);
  951. }
  952. //---------------------------------------------------------------------------
  953. //---------------------------------------------------------------------------
  954. bool __fastcall TWinHelpTester::CanShowALink(const UnicodeString ALink,
  955. const UnicodeString FileName)
  956. {
  957. return !Application->HelpFile.IsEmpty();
  958. }
  959. //---------------------------------------------------------------------------
  960. bool __fastcall TWinHelpTester::CanShowTopic(const UnicodeString Topic,
  961. const UnicodeString FileName)
  962. {
  963. assert(false);
  964. return !Application->HelpFile.IsEmpty();
  965. }
  966. //---------------------------------------------------------------------------
  967. bool __fastcall TWinHelpTester::CanShowContext(const int /*Context*/,
  968. const UnicodeString FileName)
  969. {
  970. assert(false);
  971. return !Application->HelpFile.IsEmpty();
  972. }
  973. //---------------------------------------------------------------------------
  974. TStringList * __fastcall TWinHelpTester::GetHelpStrings(const UnicodeString ALink)
  975. {
  976. assert(false);
  977. TStringList * Result = new TStringList();
  978. Result->Add(ViewerName + L": " + ALink);
  979. return Result;
  980. }
  981. //---------------------------------------------------------------------------
  982. UnicodeString __fastcall TWinHelpTester::GetHelpPath()
  983. {
  984. // never called on windows anyway
  985. return ExtractFilePath(Application->HelpFile);
  986. }
  987. //---------------------------------------------------------------------------
  988. UnicodeString __fastcall TWinHelpTester::GetDefaultHelpFile()
  989. {
  990. return Application->HelpFile;
  991. }
  992. //---------------------------------------------------------------------------
  993. //---------------------------------------------------------------------------
  994. __fastcall TCustomHelpSelector::TCustomHelpSelector(const UnicodeString & Name) :
  995. FName(Name)
  996. {
  997. }
  998. //---------------------------------------------------------------------------
  999. int __fastcall TCustomHelpSelector::SelectKeyword(TStrings * /*Keywords*/)
  1000. {
  1001. FAIL;
  1002. return 0;
  1003. }
  1004. //---------------------------------------------------------------------------
  1005. int __fastcall TCustomHelpSelector::TableOfContents(TStrings * Contents)
  1006. {
  1007. return Contents->IndexOf(FName);
  1008. }