Common.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "TextsCore.h"
  7. #include "Interface.h"
  8. #include <math.h>
  9. #include <shellapi.h>
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. #ifdef _DEBUG
  14. #include <stdio.h>
  15. void __fastcall Trace(const AnsiString SourceFile, const AnsiString Func,
  16. int Line, const AnsiString Message)
  17. {
  18. const char * FileName = getenv(TRACEENV);
  19. // !!!
  20. if (FileName == NULL)
  21. {
  22. FileName = "c:\\winscptrace.log";
  23. }
  24. // !!!
  25. if (FileName != NULL)
  26. {
  27. FILE * File = fopen(FileName, "a");
  28. if (File != NULL)
  29. {
  30. fprintf(File, "[%s] %s:%d:%s\n %s\n",
  31. Now().TimeString().c_str(),
  32. ExtractFileName(SourceFile).c_str(), Line, Func.c_str(), Message.c_str());
  33. fclose(File);
  34. }
  35. }
  36. }
  37. #endif // ifdef _DEBUG
  38. //---------------------------------------------------------------------------
  39. // TCriticalSection
  40. //---------------------------------------------------------------------------
  41. __fastcall TCriticalSection::TCriticalSection()
  42. {
  43. InitializeCriticalSection(&FSection);
  44. }
  45. //---------------------------------------------------------------------------
  46. __fastcall TCriticalSection::~TCriticalSection()
  47. {
  48. DeleteCriticalSection(&FSection);
  49. }
  50. //---------------------------------------------------------------------------
  51. void __fastcall TCriticalSection::Enter()
  52. {
  53. EnterCriticalSection(&FSection);
  54. }
  55. //---------------------------------------------------------------------------
  56. void __fastcall TCriticalSection::Leave()
  57. {
  58. LeaveCriticalSection(&FSection);
  59. }
  60. //---------------------------------------------------------------------------
  61. // TGuard
  62. //---------------------------------------------------------------------------
  63. __fastcall TGuard::TGuard(TCriticalSection * ACriticalSection) :
  64. FCriticalSection(ACriticalSection)
  65. {
  66. assert(ACriticalSection != NULL);
  67. FCriticalSection->Enter();
  68. }
  69. //---------------------------------------------------------------------------
  70. __fastcall TGuard::~TGuard()
  71. {
  72. FCriticalSection->Leave();
  73. }
  74. //---------------------------------------------------------------------------
  75. //---------------------------------------------------------------------------
  76. const char EngShortMonthNames[12][4] =
  77. {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  78. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  79. //---------------------------------------------------------------------------
  80. AnsiString ReplaceChar(AnsiString Str, Char A, Char B)
  81. {
  82. for (Integer Index = 0; Index < Str.Length(); Index++)
  83. if (Str[Index+1] == A) Str[Index+1] = B;
  84. return Str;
  85. }
  86. //---------------------------------------------------------------------------
  87. AnsiString DeleteChar(AnsiString Str, Char C)
  88. {
  89. int P;
  90. while ((P = Str.Pos(C)) > 0)
  91. {
  92. Str.Delete(P, 1);
  93. }
  94. return Str;
  95. }
  96. //---------------------------------------------------------------------------
  97. void PackStr(AnsiString &Str)
  98. {
  99. // Following will free unnecessary bytes
  100. Str = Str.c_str();
  101. }
  102. //---------------------------------------------------------------------------
  103. AnsiString GetTemporaryPath()
  104. {
  105. AnsiString Path;
  106. Path.SetLength(255);
  107. GetTempPath(Path.Length(), Path.c_str());
  108. PackStr(Path);
  109. if (!Path.IsPathDelimiter(Path.Length()))
  110. {
  111. Path += '\\';
  112. }
  113. return Path;
  114. }
  115. //---------------------------------------------------------------------------
  116. AnsiString MakeValidFileName(AnsiString FileName)
  117. {
  118. AnsiString IllegalChars = ";,=+<>|\"[] \\/?*";
  119. for (int Index = 0; Index < IllegalChars.Length(); Index++)
  120. {
  121. ReplaceChar(FileName, IllegalChars[Index+1], '-');
  122. }
  123. return FileName;
  124. }
  125. //---------------------------------------------------------------------------
  126. AnsiString RootKeyToStr(HKEY RootKey)
  127. {
  128. if (RootKey == HKEY_USERS) return "HKEY_USERS";
  129. else
  130. if (RootKey == HKEY_LOCAL_MACHINE) return "HKEY_LOCAL_MACHINE";
  131. else
  132. if (RootKey == HKEY_CURRENT_USER) return "HKEY_CURRENT_USER";
  133. else
  134. if (RootKey == HKEY_CLASSES_ROOT) return "HKEY_CLASSES_ROOT";
  135. else
  136. if (RootKey == HKEY_CURRENT_CONFIG) return "HKEY_CURRENT_CONFIG";
  137. else
  138. if (RootKey == HKEY_DYN_DATA) return "HKEY_DYN_DATA";
  139. else
  140. { Abort(); return ""; };
  141. }
  142. //---------------------------------------------------------------------------
  143. AnsiString BooleanToEngStr(bool B)
  144. {
  145. return B ? "Yes" : "No";
  146. }
  147. //---------------------------------------------------------------------------
  148. AnsiString BooleanToStr(bool B)
  149. {
  150. return B ? LoadStr(YES_STR) : LoadStr(NO_STR);
  151. }
  152. //---------------------------------------------------------------------------
  153. AnsiString CutToChar(AnsiString &Str, Char Ch, bool Trim)
  154. {
  155. Integer P = Str.Pos(Ch);
  156. AnsiString Result;
  157. if (P)
  158. {
  159. Result = Str.SubString(1, P-1);
  160. Str.Delete(1, P);
  161. }
  162. else
  163. {
  164. Result = Str;
  165. Str = "";
  166. }
  167. if (Trim)
  168. {
  169. Result = Result.TrimRight();
  170. Str = Str.TrimLeft();
  171. }
  172. return Result;
  173. }
  174. //---------------------------------------------------------------------------
  175. AnsiString ExceptionLogString(Exception *E)
  176. {
  177. assert(E);
  178. if (E->InheritsFrom(__classid(Exception)))
  179. {
  180. AnsiString Msg;
  181. Msg = FORMAT("(%s) %s", (E->ClassName(), E->Message));
  182. if (E->InheritsFrom(__classid(ExtException)))
  183. {
  184. TStrings * MoreMessages = ((ExtException*)E)->MoreMessages;
  185. if (MoreMessages)
  186. {
  187. Msg += "\n" +
  188. StringReplace(MoreMessages->Text, "\r", "", TReplaceFlags() << rfReplaceAll);
  189. }
  190. }
  191. return Msg;
  192. }
  193. else
  194. {
  195. char Buffer[1024];
  196. ExceptionErrorMessage(ExceptObject(), ExceptAddr(), Buffer, sizeof(Buffer));
  197. return AnsiString(Buffer);
  198. }
  199. }
  200. //---------------------------------------------------------------------------
  201. bool IsDots(const AnsiString Str)
  202. {
  203. char * str = Str.c_str();
  204. return (str[strspn(str, ".")] == '\0');
  205. }
  206. //---------------------------------------------------------------------------
  207. AnsiString __fastcall SystemTemporaryDirectory()
  208. {
  209. AnsiString TempDir;
  210. TempDir.SetLength(MAX_PATH);
  211. TempDir.SetLength(GetTempPath(MAX_PATH, TempDir.c_str()));
  212. return TempDir;
  213. }
  214. //---------------------------------------------------------------------------
  215. AnsiString __fastcall StripPathQuotes(const AnsiString Path)
  216. {
  217. if ((Path.Length() >= 2) &&
  218. (Path[1] == '\"') && (Path[Path.Length()] == '\"'))
  219. {
  220. return Path.SubString(2, Path.Length() - 2);
  221. }
  222. else
  223. {
  224. return Path;
  225. }
  226. }
  227. //---------------------------------------------------------------------------
  228. AnsiString __fastcall AddPathQuotes(AnsiString Path)
  229. {
  230. Path = StripPathQuotes(Path);
  231. if (Path.Pos(" "))
  232. {
  233. Path = "\"" + Path + "\"";
  234. }
  235. return Path;
  236. }
  237. //---------------------------------------------------------------------------
  238. void __fastcall SplitCommand(AnsiString Command, AnsiString &Program,
  239. AnsiString & Params, AnsiString & Dir)
  240. {
  241. Command = Command.Trim();
  242. Params = "";
  243. Dir = "";
  244. if (!Command.IsEmpty() && (Command[1] == '\"'))
  245. {
  246. Command.Delete(1, 1);
  247. int P = Command.Pos('"');
  248. if (P)
  249. {
  250. Program = Command.SubString(1, P-1).Trim();
  251. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  252. }
  253. else
  254. {
  255. throw Exception(FMTLOAD(INVALID_SHELL_COMMAND, ("\"" + Command)));
  256. }
  257. }
  258. else
  259. {
  260. int P = Command.Pos(" ");
  261. if (P)
  262. {
  263. Program = Command.SubString(1, P).Trim();
  264. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  265. }
  266. else
  267. {
  268. Program = Command;
  269. }
  270. }
  271. int B = Program.LastDelimiter("\\/");
  272. if (B)
  273. {
  274. Dir = Program.SubString(1, B).Trim();
  275. }
  276. }
  277. //---------------------------------------------------------------------------
  278. AnsiString __fastcall FormatCommand(AnsiString Program, AnsiString Params)
  279. {
  280. Program = Program.Trim();
  281. Params = Params.Trim();
  282. if (!Params.IsEmpty()) Params = " " + Params;
  283. if (Program.Pos(" ")) Program = "\"" + Program + "\"";
  284. return Program + Params;
  285. }
  286. //---------------------------------------------------------------------------
  287. bool __fastcall IsDisplayableStr(const AnsiString Str)
  288. {
  289. bool Displayable = true;
  290. int Index = 1;
  291. while ((Index <= Str.Length()) && Displayable)
  292. {
  293. if (Str[Index] < '\32')
  294. {
  295. Displayable = false;
  296. }
  297. Index++;
  298. }
  299. return Displayable;
  300. }
  301. //---------------------------------------------------------------------------
  302. AnsiString __fastcall StrToHex(const AnsiString Str)
  303. {
  304. AnsiString Result;
  305. for (int i = 1; i <= Str.Length(); i++)
  306. {
  307. Result += IntToHex(Str[i], 2);
  308. }
  309. return Result;
  310. }
  311. //---------------------------------------------------------------------------
  312. AnsiString __fastcall HexToStr(const AnsiString Hex)
  313. {
  314. static AnsiString Digits = "0123456789ABCDEF";
  315. AnsiString Result;
  316. int L, P1, P2;
  317. L = Hex.Length();
  318. if (L % 2 == 0)
  319. {
  320. for (int i = 1; i <= Hex.Length(); i += 2)
  321. {
  322. P1 = Digits.Pos(Hex[i]);
  323. P2 = Digits.Pos(Hex[i + 1]);
  324. if (P1 <= 0 || P2 <= 0)
  325. {
  326. break;
  327. }
  328. else
  329. {
  330. Result += static_cast<char>((P1 - 1) * 16 + P2 - 1);
  331. }
  332. }
  333. }
  334. return Result;
  335. }
  336. //---------------------------------------------------------------------------
  337. bool __fastcall FileSearchRec(const AnsiString FileName, TSearchRec & Rec)
  338. {
  339. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  340. bool Result = (FindFirst(FileName, FindAttrs, Rec) == 0);
  341. if (Result)
  342. {
  343. FindClose(Rec);
  344. }
  345. return Result;
  346. }
  347. //---------------------------------------------------------------------------
  348. void __fastcall ProcessLocalDirectory(AnsiString DirName,
  349. TProcessLocalFileEvent CallBackFunc, void * Param,
  350. int FindAttrs)
  351. {
  352. assert(CallBackFunc);
  353. if (FindAttrs < 0)
  354. {
  355. FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  356. }
  357. TSearchRec SearchRec;
  358. DirName = IncludeTrailingBackslash(DirName);
  359. if (FindFirst(DirName + "*.*", FindAttrs, SearchRec) == 0)
  360. {
  361. try
  362. {
  363. do
  364. {
  365. if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
  366. {
  367. CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
  368. }
  369. } while (FindNext(SearchRec) == 0);
  370. }
  371. __finally
  372. {
  373. FindClose(SearchRec);
  374. }
  375. }
  376. }
  377. //---------------------------------------------------------------------------
  378. struct TDateTimeParams
  379. {
  380. TDateTime UnixEpoch;
  381. double BaseDifference;
  382. long BaseDifferenceSec;
  383. double CurrentDaylightDifference;
  384. long CurrentDaylightDifferenceSec;
  385. double CurrentDifference;
  386. long CurrentDifferenceSec;
  387. double StandardDifference;
  388. long StandardDifferenceSec;
  389. double DaylightDifference;
  390. long DaylightDifferenceSec;
  391. SYSTEMTIME StandardDate;
  392. SYSTEMTIME DaylightDate;
  393. };
  394. static bool DateTimeParamsInitialized = false;
  395. static TDateTimeParams DateTimeParams;
  396. static TCriticalSection DateTimeParamsSection;
  397. //---------------------------------------------------------------------------
  398. static TDateTimeParams * __fastcall GetDateTimeParams()
  399. {
  400. if (!DateTimeParamsInitialized)
  401. {
  402. TGuard Guard(&DateTimeParamsSection);
  403. if (!DateTimeParamsInitialized)
  404. {
  405. TIME_ZONE_INFORMATION TZI;
  406. unsigned long GTZI;
  407. GTZI = GetTimeZoneInformation(&TZI);
  408. switch (GTZI)
  409. {
  410. case TIME_ZONE_ID_UNKNOWN:
  411. DateTimeParams.CurrentDifferenceSec = 0;
  412. DateTimeParams.CurrentDaylightDifferenceSec = 0;
  413. break;
  414. case TIME_ZONE_ID_STANDARD:
  415. DateTimeParams.CurrentDaylightDifferenceSec = TZI.StandardBias;
  416. break;
  417. case TIME_ZONE_ID_DAYLIGHT:
  418. DateTimeParams.CurrentDaylightDifferenceSec = TZI.DaylightBias;
  419. break;
  420. case TIME_ZONE_ID_INVALID:
  421. default:
  422. throw Exception(TIMEZONE_ERROR);
  423. }
  424. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  425. DateTimeParams.UnixEpoch = EncodeDate(1970, 1, 1);
  426. DateTimeParams.BaseDifferenceSec = TZI.Bias;
  427. DateTimeParams.BaseDifference = double(TZI.Bias) / 1440;
  428. DateTimeParams.BaseDifferenceSec *= 60;
  429. DateTimeParams.CurrentDifferenceSec = TZI.Bias +
  430. DateTimeParams.CurrentDaylightDifferenceSec;
  431. DateTimeParams.CurrentDifference =
  432. double(DateTimeParams.CurrentDifferenceSec) / 1440;
  433. DateTimeParams.CurrentDifferenceSec *= 60;
  434. DateTimeParams.CurrentDaylightDifference =
  435. double(DateTimeParams.CurrentDaylightDifferenceSec) / 1440;
  436. DateTimeParams.CurrentDaylightDifferenceSec *= 60;
  437. DateTimeParams.DaylightDifferenceSec = TZI.DaylightBias * 60;
  438. DateTimeParams.DaylightDifference = double(TZI.DaylightBias) / 1440;
  439. DateTimeParams.StandardDifferenceSec = TZI.StandardBias * 60;
  440. DateTimeParams.StandardDifference = double(TZI.StandardBias) / 1440;
  441. DateTimeParams.StandardDate = TZI.StandardDate;
  442. DateTimeParams.DaylightDate = TZI.DaylightDate;
  443. DateTimeParamsInitialized = true;
  444. }
  445. }
  446. return &DateTimeParams;
  447. }
  448. //---------------------------------------------------------------------------
  449. static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Year,
  450. TDateTime & Result)
  451. {
  452. if (Date.wYear == 0)
  453. {
  454. TDateTime Temp = EncodeDate(Year, Date.wMonth, 1);
  455. Result = Temp + ((Date.wDayOfWeek - DayOfWeek(Temp) + 8) % 7) +
  456. (7 * (Date.wDay - 1));
  457. if (Date.wDay == 5)
  458. {
  459. unsigned short Month = static_cast<unsigned short>(Date.wMonth + 1);
  460. if (Month > 12)
  461. {
  462. Month = static_cast<unsigned short>(Month - 12);
  463. Year++;
  464. }
  465. if (Result > EncodeDate(Year, Month, 1))
  466. {
  467. Result -= 7;
  468. }
  469. }
  470. Result += EncodeTime(Date.wHour, Date.wMinute, Date.wSecond,
  471. Date.wMilliseconds);
  472. }
  473. else
  474. {
  475. Result = EncodeDate(Year, Date.wMonth, Date.wDay) +
  476. EncodeTime(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
  477. }
  478. }
  479. //---------------------------------------------------------------------------
  480. static bool __fastcall IsDateInDST(const TDateTime & DateTime)
  481. {
  482. struct TDSTCache
  483. {
  484. bool Filled;
  485. unsigned short Year;
  486. TDateTime StandardDate;
  487. TDateTime DaylightDate;
  488. };
  489. static TDSTCache DSTCache[10];
  490. static int DSTCacheCount = 0;
  491. static TCriticalSection Section;
  492. TDateTimeParams * Params = GetDateTimeParams();
  493. bool Result;
  494. if (Params->StandardDate.wMonth == 0)
  495. {
  496. Result = false;
  497. }
  498. else
  499. {
  500. unsigned short Year, Month, Day;
  501. DecodeDate(DateTime, Year, Month, Day);
  502. TDSTCache * CurrentCache = &DSTCache[0];
  503. int CacheIndex = 0;
  504. while ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  505. CurrentCache->Filled && (CurrentCache->Year != Year))
  506. {
  507. CacheIndex++;
  508. CurrentCache++;
  509. }
  510. if ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  511. CurrentCache->Filled)
  512. {
  513. assert(CurrentCache->Year == Year);
  514. Result = (DateTime >= CurrentCache->DaylightDate) &&
  515. (DateTime < CurrentCache->StandardDate);
  516. }
  517. else
  518. {
  519. TDSTCache NewCache;
  520. EncodeDSTMargin(Params->StandardDate, Year, NewCache.StandardDate);
  521. EncodeDSTMargin(Params->DaylightDate, Year, NewCache.DaylightDate);
  522. AnsiString SD = FormatDateTime("dddddd tt", NewCache.StandardDate);
  523. AnsiString DD = FormatDateTime("dddddd tt", NewCache.DaylightDate);
  524. if (DSTCacheCount < LENOF(DSTCache))
  525. {
  526. TGuard Guard(&Section);
  527. if (DSTCacheCount < LENOF(DSTCache))
  528. {
  529. NewCache.Year = Year;
  530. DSTCache[DSTCacheCount] = NewCache;
  531. DSTCache[DSTCacheCount].Filled = true;
  532. DSTCacheCount++;
  533. }
  534. }
  535. Result = (DateTime >= NewCache.DaylightDate) &&
  536. (DateTime < NewCache.StandardDate);
  537. }
  538. }
  539. return Result;
  540. }
  541. //---------------------------------------------------------------------------
  542. TDateTime __fastcall UnixToDateTime(unsigned long TimeStamp, bool ConsiderDST)
  543. {
  544. TDateTimeParams * Params = GetDateTimeParams();
  545. TDateTime Result;
  546. Result = Params->UnixEpoch + (double(TimeStamp) / 86400) - Params->CurrentDifference;
  547. if (ConsiderDST)
  548. {
  549. Result -= (IsDateInDST(Result) ?
  550. Params->DaylightDifference : Params->StandardDifference);
  551. }
  552. return Result;
  553. }
  554. //---------------------------------------------------------------------------
  555. inline __int64 __fastcall Round(double Number)
  556. {
  557. double Floor = floor(Number);
  558. double Ceil = ceil(Number);
  559. return ((Number - Floor) > (Ceil - Number)) ? Ceil : Floor;
  560. }
  561. //---------------------------------------------------------------------------
  562. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime,
  563. bool /*ConsiderDST*/)
  564. {
  565. TDateTimeParams * Params = GetDateTimeParams();
  566. __int64 UnixTimeStamp;
  567. FILETIME Result;
  568. UnixTimeStamp = Round(double(DateTime - Params->UnixEpoch) * 86400) +
  569. Params->CurrentDifferenceSec;
  570. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  571. return Result;
  572. }
  573. //---------------------------------------------------------------------------
  574. unsigned long __fastcall ConvertTimestampToUnix(const FILETIME & FileTime,
  575. bool ConsiderDST)
  576. {
  577. unsigned long Result;
  578. TIME_WIN_TO_POSIX(FileTime, Result);
  579. if (ConsiderDST)
  580. {
  581. FILETIME LocalFileTime;
  582. SYSTEMTIME SystemTime;
  583. TDateTime DateTime;
  584. FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
  585. FileTimeToSystemTime(&LocalFileTime, &SystemTime);
  586. DateTime = SystemTimeToDateTime(SystemTime);
  587. TDateTimeParams * Params = GetDateTimeParams();
  588. Result += (IsDateInDST(DateTime) ?
  589. Params->DaylightDifferenceSec : Params->StandardDifferenceSec);
  590. }
  591. return Result;
  592. }
  593. //---------------------------------------------------------------------------
  594. TDateTime __fastcall AdjustDateTimeFromUnix(TDateTime DateTime, bool ConsiderDST)
  595. {
  596. TDateTimeParams * Params = GetDateTimeParams();
  597. DateTime = DateTime - Params->CurrentDaylightDifference;
  598. bool IsInDST = IsDateInDST(DateTime);
  599. // shift always, even with ConsiderDST == false
  600. DateTime = DateTime - (!IsInDST ? Params->DaylightDifference :
  601. Params->StandardDifference);
  602. if (ConsiderDST)
  603. {
  604. if (IsInDST)
  605. {
  606. //DateTime = DateTime - Params->DaylightDifference;
  607. }
  608. else
  609. {
  610. DateTime = DateTime + Params->DaylightDifference;
  611. }
  612. }
  613. return DateTime;
  614. }
  615. //---------------------------------------------------------------------------
  616. __inline static bool __fastcall UnifySignificance(unsigned short & V1,
  617. unsigned short & V2)
  618. {
  619. bool Result = (V1 == 0) || (V2 == 0);
  620. if (Result)
  621. {
  622. V1 = 0;
  623. V2 = 0;
  624. }
  625. return Result;
  626. }
  627. //---------------------------------------------------------------------------
  628. void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTime2)
  629. {
  630. unsigned short Y1, M1, D1, H1, N1, S1, MS1;
  631. unsigned short Y2, M2, D2, H2, N2, S2, MS2;
  632. bool Changed;
  633. if (DateTime1 != DateTime2)
  634. {
  635. DateTime1.DecodeDate(&Y1, &M1, &D1);
  636. DateTime1.DecodeTime(&H1, &N1, &S1, &MS1);
  637. DateTime2.DecodeDate(&Y2, &M2, &D2);
  638. DateTime2.DecodeTime(&H2, &N2, &S2, &MS2);
  639. Changed = UnifySignificance(MS1, MS2);
  640. if (Changed && UnifySignificance(S1, S2) && UnifySignificance(N1, N2) &&
  641. UnifySignificance(H1, H2) && UnifySignificance(D1, D2) &&
  642. UnifySignificance(M1, M2))
  643. {
  644. UnifySignificance(Y1, Y2);
  645. }
  646. if (Changed)
  647. {
  648. DateTime1 = EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
  649. DateTime2 = EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
  650. }
  651. }
  652. }
  653. //---------------------------------------------------------------------------
  654. bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin)
  655. {
  656. SHFILEOPSTRUCT Data;
  657. memset(&Data, 0, sizeof(Data));
  658. Data.hwnd = NULL;
  659. Data.wFunc = FO_DELETE;
  660. AnsiString FileList(FileName);
  661. FileList.SetLength(FileList.Length() + 2);
  662. FileList[FileList.Length() - 1] = '\0';
  663. FileList[FileList.Length()] = '\0';
  664. Data.pFrom = FileList.c_str();
  665. Data.pTo = "";
  666. Data.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR |
  667. FOF_NOERRORUI | FOF_SILENT;
  668. if (ToRecycleBin)
  669. {
  670. Data.fFlags |= FOF_ALLOWUNDO;
  671. }
  672. int Result = SHFileOperation(&Data);
  673. return (Result == 0);
  674. }
  675. //---------------------------------------------------------------------------
  676. int __fastcall CancelAnswer(int Answers)
  677. {
  678. int Result;
  679. if ((Answers & qaCancel) != 0)
  680. {
  681. Result = qaCancel;
  682. }
  683. else if ((Answers & qaNo) != 0)
  684. {
  685. Result = qaNo;
  686. }
  687. else if ((Answers & qaAbort) != 0)
  688. {
  689. Result = qaAbort;
  690. }
  691. else if ((Answers & qaOK) != 0)
  692. {
  693. Result = qaOK;
  694. }
  695. else
  696. {
  697. assert(false);
  698. Result = qaCancel;
  699. }
  700. return Result;
  701. }