sysutils.pp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for win32
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. {$modeswitch typehelpers}
  19. {$modeswitch advancedrecords}
  20. uses
  21. windows;
  22. {$DEFINE HAS_SLEEP}
  23. {$DEFINE HAS_OSERROR}
  24. {$DEFINE HAS_OSCONFIG}
  25. {$DEFINE HAS_OSUSERDIR}
  26. {$DEFINE HAS_CREATEGUID}
  27. {$DEFINE HAS_LOCALTIMEZONEOFFSET}
  28. {$DEFINE HAS_GETTICKCOUNT}
  29. {$DEFINE HAS_GETTICKCOUNT64}
  30. {$DEFINE OS_FILESETDATEBYNAME}
  31. { used OS file system APIs use unicodestring }
  32. {$define SYSUTILS_HAS_UNICODESTR_FILEUTIL_IMPL}
  33. { OS has an ansistring/single byte environment variable API }
  34. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  35. { OS has a unicodestring/two byte environment variable API }
  36. {$define SYSUTILS_HAS_UNICODESTR_ENVVAR_IMPL}
  37. { Include platform independent interface part }
  38. {$i sysutilh.inc}
  39. type
  40. TSystemTime = Windows.TSystemTime;
  41. EWin32Error = class(Exception)
  42. public
  43. ErrorCode : DWORD;
  44. end;
  45. Var
  46. Win32Platform : Longint;
  47. Win32MajorVersion,
  48. Win32MinorVersion,
  49. Win32BuildNumber : dword;
  50. Win32CSDVersion : ShortString; // CSD record is 128 bytes only?
  51. const
  52. MaxEraCount = 7;
  53. var
  54. EraNames: array [1..MaxEraCount] of String;
  55. EraYearOffsets: array [1..MaxEraCount] of Integer;
  56. { Compatibility with Delphi }
  57. function Win32Check(res:boolean):boolean;inline;
  58. function WinCheck(res:boolean):boolean;
  59. function CheckWin32Version(Major,Minor : Integer ): Boolean;
  60. function CheckWin32Version(Major : Integer): Boolean;
  61. Procedure RaiseLastWin32Error;
  62. function GetFileVersion(const AFileName: string): Cardinal;
  63. function GetFileVersion(const AFileName: UnicodeString): Cardinal;
  64. procedure GetFormatSettings;
  65. procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings); platform;
  66. implementation
  67. uses
  68. sysconst,
  69. windirs;
  70. function WinCheck(res:boolean):boolean;
  71. begin
  72. if not res then
  73. RaiseLastOSError;
  74. result:=res;
  75. end;
  76. function Win32Check(res:boolean):boolean;inline;
  77. begin
  78. result:=WinCheck(res);
  79. end;
  80. procedure RaiseLastWin32Error;
  81. begin
  82. RaiseLastOSError;
  83. end;
  84. function CheckWin32Version(Major : Integer): Boolean;
  85. begin
  86. Result:=CheckWin32Version(Major,0)
  87. end;
  88. function CheckWin32Version(Major,Minor: Integer): Boolean;
  89. begin
  90. Result:=(Win32MajorVersion>dword(Major)) or
  91. ((Win32MajorVersion=dword(Major)) and (Win32MinorVersion>=dword(Minor)));
  92. end;
  93. function GetFileVersion(const AFileName:string):Cardinal;
  94. var
  95. { useful only as long as we don't need to touch different stack pages }
  96. buf : array[0..3071] of byte;
  97. bufp : pointer;
  98. fn : string;
  99. valsize,
  100. size : DWORD;
  101. h : DWORD;
  102. valrec : PVSFixedFileInfo;
  103. begin
  104. result:=$fffffff;
  105. fn:=AFileName;
  106. UniqueString(fn);
  107. size:=GetFileVersionInfoSizeA(pchar(fn),@h);
  108. if size>sizeof(buf) then
  109. begin
  110. getmem(bufp,size);
  111. try
  112. if GetFileVersionInfoA(pchar(fn),h,size,bufp) then
  113. if VerQueryValue(bufp,'\',valrec,valsize) then
  114. result:=valrec^.dwFileVersionMS;
  115. finally
  116. freemem(bufp);
  117. end;
  118. end
  119. else
  120. begin
  121. if GetFileVersionInfoA(pchar(fn),h,size,@buf) then
  122. if VerQueryValue(@buf,'\',valrec,valsize) then
  123. result:=valrec^.dwFileVersionMS;
  124. end;
  125. end;
  126. function GetFileVersion(const AFileName:UnicodeString):Cardinal;
  127. var
  128. { useful only as long as we don't need to touch different stack pages }
  129. buf : array[0..3071] of byte;
  130. bufp : pointer;
  131. fn : unicodestring;
  132. valsize,
  133. size : DWORD;
  134. h : DWORD;
  135. valrec : PVSFixedFileInfo;
  136. begin
  137. result:=$fffffff;
  138. fn:=AFileName;
  139. UniqueString(fn);
  140. size:=GetFileVersionInfoSizeW(pwidechar(fn),@h);
  141. if size>sizeof(buf) then
  142. begin
  143. getmem(bufp,size);
  144. try
  145. if GetFileVersionInfoW(pwidechar(fn),h,size,bufp) then
  146. if VerQueryValue(bufp,'\',valrec,valsize) then
  147. result:=valrec^.dwFileVersionMS;
  148. finally
  149. freemem(bufp);
  150. end;
  151. end
  152. else
  153. begin
  154. if GetFileVersionInfoW(pwidechar(fn),h,size,@buf) then
  155. if VerQueryValueW(@buf,'\',valrec,valsize) then
  156. result:=valrec^.dwFileVersionMS;
  157. end;
  158. end;
  159. {$define HASCREATEGUID}
  160. {$define HASEXPANDUNCFILENAME}
  161. {$DEFINE FPC_NOGENERICANSIROUTINES}
  162. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  163. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  164. function ConvertEraYearString(Count ,Year,Month,Day : integer) : string; forward;
  165. function ConvertEraString(Count ,Year,Month,Day : integer) : string; forward;
  166. { Include platform independent implementation part }
  167. {$i sysutils.inc}
  168. function GetTempFileName(Dir,Prefix: PChar; uUnique: DWORD; TempFileName: PChar):DWORD;
  169. begin
  170. Result:= Windows.GetTempFileNameA(Dir,Prefix,uUnique,TempFileName);
  171. end;
  172. { UUID generation. }
  173. function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';
  174. function SysCreateGUID(out Guid: TGUID): Integer;
  175. begin
  176. Result := Integer(CoCreateGuid(Guid));
  177. end;
  178. function ExpandUNCFileName (const filename:rawbytestring) : rawbytestring;
  179. { returns empty string on errors }
  180. var
  181. u: unicodestring;
  182. begin
  183. { prevent data loss due to unsupported characters in ansi code page }
  184. u:=ExpandUNCFileName(unicodestring(filename));
  185. widestringmanager.Unicode2AnsiMoveProc(punicodechar(u),result,DefaultRTLFileSystemCodePage,length(u));
  186. end;
  187. function ExpandUNCFileName (const filename:unicodestring) : unicodestring;
  188. { returns empty string on errors }
  189. var
  190. s : unicodestring;
  191. size : dword;
  192. rc : dword;
  193. buf : pwidechar;
  194. begin
  195. s := ExpandFileName (filename);
  196. s := s + #0;
  197. size := max_path;
  198. getmem(buf,size);
  199. try
  200. rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  201. if rc=ERROR_MORE_DATA then
  202. begin
  203. buf:=reallocmem(buf,size);
  204. rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  205. end;
  206. if rc = NO_ERROR then
  207. Result := PRemoteNameInfoW(buf)^.lpUniversalName
  208. else if rc = ERROR_NOT_CONNECTED then
  209. Result := filename
  210. else
  211. Result := '';
  212. finally
  213. freemem(buf);
  214. end;
  215. end;
  216. {****************************************************************************
  217. File Functions
  218. ****************************************************************************}
  219. const
  220. AccessMode: array[0..2] of Cardinal = (
  221. GENERIC_READ,
  222. GENERIC_WRITE,
  223. GENERIC_READ or GENERIC_WRITE or FILE_WRITE_ATTRIBUTES);
  224. ShareModes: array[0..4] of Integer = (
  225. 0,
  226. 0,
  227. FILE_SHARE_READ,
  228. FILE_SHARE_WRITE,
  229. FILE_SHARE_READ or FILE_SHARE_WRITE);
  230. Function FileOpen (Const FileName : unicodestring; Mode : Integer) : THandle;
  231. begin
  232. result := CreateFileW(PWideChar(FileName), dword(AccessMode[Mode and 3]),
  233. dword(ShareModes[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
  234. FILE_ATTRIBUTE_NORMAL, 0);
  235. //if fail api return feInvalidHandle (INVALIDE_HANDLE=feInvalidHandle=-1)
  236. end;
  237. Function FileCreate (Const FileName : UnicodeString) : THandle;
  238. begin
  239. FileCreate:=FileCreate(FileName, fmShareExclusive, 0);
  240. end;
  241. Function FileCreate (Const FileName : UnicodeString; Rights:longint) : THandle;
  242. begin
  243. FileCreate:=FileCreate(FileName, fmShareExclusive, Rights);
  244. end;
  245. Function FileCreate (Const FileName : UnicodeString; ShareMode : Integer; Rights : Integer) : THandle;
  246. begin
  247. Result := CreateFileW(PwideChar(FileName), GENERIC_READ or GENERIC_WRITE,
  248. dword(ShareModes[(ShareMode and $F0) shr 4]), nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  249. end;
  250. Function FileRead (Handle : THandle; out Buffer; Count : longint) : Longint;
  251. Var
  252. res : dword;
  253. begin
  254. if ReadFile(Handle, Buffer, Count, res, nil) then
  255. FileRead:=Res
  256. else
  257. FileRead:=-1;
  258. end;
  259. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
  260. Var
  261. Res : dword;
  262. begin
  263. if WriteFile(Handle, Buffer, Count, Res, nil) then
  264. FileWrite:=Res
  265. else
  266. FileWrite:=-1;
  267. end;
  268. Function FileSeek (Handle : THandle;FOffset,Origin : Longint) : Longint;
  269. begin
  270. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  271. end;
  272. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  273. var
  274. rslt: Int64Rec;
  275. begin
  276. rslt := Int64Rec(FOffset);
  277. rslt.lo := SetFilePointer(Handle, rslt.lo, @rslt.hi, Origin);
  278. if (rslt.lo = $FFFFFFFF) and (GetLastError <> 0) then
  279. rslt.hi := $FFFFFFFF;
  280. Result := Int64(rslt);
  281. end;
  282. Procedure FileClose (Handle : THandle);
  283. begin
  284. if Handle<=4 then
  285. exit;
  286. CloseHandle(Handle);
  287. end;
  288. Function FileTruncate (Handle : THandle;Size: Int64) : boolean;
  289. begin
  290. {
  291. Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
  292. }
  293. if FileSeek (Handle, Size, FILE_BEGIN) = Size then
  294. Result:=SetEndOfFile(handle)
  295. else
  296. Result := false;
  297. end;
  298. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  299. var
  300. lft : TFileTime;
  301. begin
  302. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
  303. LocalFileTimeToFileTime(lft,Wtime);
  304. end;
  305. Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
  306. var
  307. lft : TFileTime;
  308. begin
  309. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  310. FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
  311. end;
  312. Function FileAge (Const FileName : UnicodeString): Longint;
  313. var
  314. Handle: THandle;
  315. FindData: TWin32FindDataW;
  316. begin
  317. Handle := FindFirstFileW(Pwidechar(FileName), FindData);
  318. if Handle <> INVALID_HANDLE_VALUE then
  319. begin
  320. Windows.FindClose(Handle);
  321. if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  322. If WinToDosTime(FindData.ftLastWriteTime,Result) then
  323. exit;
  324. end;
  325. Result := -1;
  326. end;
  327. Function FileExists (Const FileName : UnicodeString) : Boolean;
  328. var
  329. Attr:Dword;
  330. begin
  331. Attr:=GetFileAttributesW(PWideChar(FileName));
  332. if Attr <> $ffffffff then
  333. Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) = 0
  334. else
  335. Result:=False;
  336. end;
  337. Function DirectoryExists (Const Directory : UnicodeString) : Boolean;
  338. var
  339. Attr:Dword;
  340. begin
  341. Attr:=GetFileAttributesW(PWideChar(Directory));
  342. if Attr <> $ffffffff then
  343. Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) > 0
  344. else
  345. Result:=False;
  346. end;
  347. Function FindMatch(var f: TAbstractSearchRec; var Name: UnicodeString) : Longint;
  348. begin
  349. { Find file with correct attribute }
  350. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  351. begin
  352. if not FindNextFileW (F.FindHandle,F.FindData) then
  353. begin
  354. Result:=GetLastError;
  355. exit;
  356. end;
  357. end;
  358. { Convert some attributes back }
  359. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  360. f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
  361. f.attr:=F.FindData.dwFileAttributes;
  362. Name:=F.FindData.cFileName;
  363. Result:=0;
  364. end;
  365. Function InternalFindFirst (Const Path : UnicodeString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name : UnicodeString) : Longint;
  366. begin
  367. Name:=Path;
  368. Rslt.Attr:=attr;
  369. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  370. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  371. { FindFirstFile is a Win32 Call }
  372. Rslt.FindHandle:=FindFirstFileW (PWideChar(Path),Rslt.FindData);
  373. If Rslt.FindHandle=Invalid_Handle_value then
  374. begin
  375. Result:=GetLastError;
  376. exit;
  377. end;
  378. { Find file with correct attribute }
  379. Result:=FindMatch(Rslt,Name);
  380. end;
  381. Function InternalFindNext (Var Rslt : TAbstractSearchRec; var Name: UnicodeString) : Longint;
  382. begin
  383. if FindNextFileW(Rslt.FindHandle, Rslt.FindData) then
  384. Result := FindMatch(Rslt, Name)
  385. else
  386. Result := GetLastError;
  387. end;
  388. Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
  389. begin
  390. if Handle <> INVALID_HANDLE_VALUE then
  391. Windows.FindClose(Handle);
  392. end;
  393. Function FileGetDate (Handle : THandle) : Longint;
  394. Var
  395. FT : TFileTime;
  396. begin
  397. If GetFileTime(Handle,nil,nil,@ft) and
  398. WinToDosTime(FT,Result) then
  399. exit;
  400. Result:=-1;
  401. end;
  402. Function FileSetDate (Handle : THandle;Age : Longint) : Longint;
  403. Var
  404. FT: TFileTime;
  405. begin
  406. Result := 0;
  407. if DosToWinTime(Age,FT) and
  408. SetFileTime(Handle, nil, nil, @FT) then
  409. Exit;
  410. Result := GetLastError;
  411. end;
  412. {$IFDEF OS_FILESETDATEBYNAME}
  413. Function FileSetDate (Const FileName : UnicodeString;Age : Longint) : Longint;
  414. Var
  415. fd : THandle;
  416. begin
  417. FD := CreateFileW (PWideChar (FileName), GENERIC_READ or GENERIC_WRITE,
  418. FILE_SHARE_WRITE, nil, OPEN_EXISTING,
  419. FILE_FLAG_BACKUP_SEMANTICS, 0);
  420. If (Fd<>feInvalidHandle) then
  421. try
  422. Result:=FileSetDate(fd,Age);
  423. finally
  424. FileClose(fd);
  425. end
  426. else
  427. Result:=GetLastOSError;
  428. end;
  429. {$ENDIF}
  430. Function FileGetAttr (Const FileName : UnicodeString) : Longint;
  431. begin
  432. Result:=Longint(GetFileAttributesW(PWideChar(FileName)));
  433. end;
  434. Function FileSetAttr (Const Filename : UnicodeString; Attr: longint) : Longint;
  435. begin
  436. if SetFileAttributesW(PWideChar(FileName), Attr) then
  437. Result:=0
  438. else
  439. Result := GetLastError;
  440. end;
  441. Function DeleteFile (Const FileName : UnicodeString) : Boolean;
  442. begin
  443. Result:=Windows.DeleteFileW(PWidechar(FileName));
  444. end;
  445. Function RenameFile (Const OldName, NewName : UnicodeString) : Boolean;
  446. begin
  447. Result := MoveFileW(PWideChar(OldName), PWideChar(NewName));
  448. end;
  449. {****************************************************************************
  450. Disk Functions
  451. ****************************************************************************}
  452. type
  453. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
  454. var
  455. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  456. function diskfree(drive : byte) : int64;
  457. var
  458. disk : array[1..4] of char;
  459. secs,bytes,
  460. free,total : dword;
  461. qwtotal,qwfree,qwcaller : int64;
  462. begin
  463. if drive=0 then
  464. begin
  465. disk[1]:='\';
  466. disk[2]:=#0;
  467. end
  468. else
  469. begin
  470. disk[1]:=chr(drive+64);
  471. disk[2]:=':';
  472. disk[3]:='\';
  473. disk[4]:=#0;
  474. end;
  475. if assigned(GetDiskFreeSpaceEx) then
  476. begin
  477. if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
  478. diskfree:=qwfree
  479. else
  480. diskfree:=-1;
  481. end
  482. else
  483. begin
  484. if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
  485. diskfree:=int64(free)*secs*bytes
  486. else
  487. diskfree:=-1;
  488. end;
  489. end;
  490. function disksize(drive : byte) : int64;
  491. var
  492. disk : array[1..4] of char;
  493. secs,bytes,
  494. free,total : dword;
  495. qwtotal,qwfree,qwcaller : int64;
  496. begin
  497. if drive=0 then
  498. begin
  499. disk[1]:='\';
  500. disk[2]:=#0;
  501. end
  502. else
  503. begin
  504. disk[1]:=chr(drive+64);
  505. disk[2]:=':';
  506. disk[3]:='\';
  507. disk[4]:=#0;
  508. end;
  509. if assigned(GetDiskFreeSpaceEx) then
  510. begin
  511. if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
  512. disksize:=qwtotal
  513. else
  514. disksize:=-1;
  515. end
  516. else
  517. begin
  518. if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
  519. disksize:=int64(total)*secs*bytes
  520. else
  521. disksize:=-1;
  522. end;
  523. end;
  524. {****************************************************************************
  525. Time Functions
  526. ****************************************************************************}
  527. Procedure GetLocalTime(var SystemTime: TSystemTime);
  528. begin
  529. windows.Getlocaltime(SystemTime);
  530. end;
  531. function GetLocalTimeOffset: Integer;
  532. var
  533. TZInfo: TTimeZoneInformation;
  534. begin
  535. case GetTimeZoneInformation(TZInfo) of
  536. TIME_ZONE_ID_UNKNOWN:
  537. Result := TZInfo.Bias;
  538. TIME_ZONE_ID_STANDARD:
  539. Result := TZInfo.Bias + TZInfo.StandardBias;
  540. TIME_ZONE_ID_DAYLIGHT:
  541. Result := TZInfo.Bias + TZInfo.DaylightBias;
  542. else
  543. Result := 0;
  544. end;
  545. end;
  546. function GetTickCount: LongWord;
  547. begin
  548. Result := Windows.GetTickCount;
  549. end;
  550. {$IFNDEF WINCE}
  551. type
  552. TGetTickCount64 = function : QWord; stdcall;
  553. var
  554. WinGetTickCount64: TGetTickCount64 = Nil;
  555. {$ENDIF}
  556. function GetTickCount64: QWord;
  557. {$IFNDEF WINCE}
  558. var
  559. lib: THandle;
  560. {$ENDIF}
  561. begin
  562. {$IFNDEF WINCE}
  563. { on Vista and newer there is a GetTickCount64 implementation }
  564. if Win32MajorVersion >= 6 then begin
  565. if not Assigned(WinGetTickCount64) then begin
  566. lib := LoadLibrary('kernel32.dll');
  567. WinGetTickCount64 := TGetTickCount64(
  568. GetProcAddress(lib, 'GetTickCount64'));
  569. end;
  570. Result := WinGetTickCount64();
  571. end else
  572. {$ENDIF}
  573. Result := Windows.GetTickCount;
  574. end;
  575. {****************************************************************************
  576. Misc Functions
  577. ****************************************************************************}
  578. procedure sysbeep;
  579. begin
  580. MessageBeep(0);
  581. end;
  582. {****************************************************************************
  583. Locale Functions
  584. ****************************************************************************}
  585. function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
  586. var
  587. L: Integer;
  588. Buf: array[0..255] of Char;
  589. begin
  590. L := GetLocaleInfoA(LID, LT, Buf, SizeOf(Buf));
  591. if L > 0 then
  592. SetString(Result, @Buf[0], L - 1)
  593. else
  594. Result := Def;
  595. end;
  596. function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
  597. var
  598. Buf: array[0..3] of Char; // sdate allows 4 chars.
  599. begin
  600. if GetLocaleInfoA(LID, LT, Buf, sizeof(buf)) > 0 then
  601. Result := Buf[0]
  602. else
  603. Result := Def;
  604. end;
  605. function ConvertEraString(Count ,Year,Month,Day : integer) : string;
  606. var
  607. ASystemTime: TSystemTime;
  608. buf: array[0..100] of char;
  609. ALCID : LCID;
  610. PriLangID : Word;
  611. SubLangID : Word;
  612. begin
  613. Result := ''; if (Count<=0) then exit;
  614. DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
  615. ALCID := GetThreadLocale;
  616. // ALCID := SysLocale.DefaultLCID;
  617. if GetDateFormatA(ALCID , DATE_USE_ALT_CALENDAR
  618. , @ASystemTime, PChar('gg')
  619. , @buf, SizeOf(buf)) > 0 then
  620. begin
  621. Result := buf;
  622. if Count = 1 then
  623. begin
  624. PriLangID := ALCID and $3FF;
  625. SubLangID := (ALCID and $FFFF) shr 10;
  626. case PriLangID of
  627. LANG_JAPANESE:
  628. begin
  629. Result := Copy(WideString(Result),1,1);
  630. end;
  631. LANG_CHINESE:
  632. if (SubLangID = SUBLANG_CHINESE_TRADITIONAL) then
  633. begin
  634. Result := Copy(WideString(Result),1,1);
  635. end;
  636. end;
  637. end;
  638. end;
  639. // if Result = '' then Result := StringOfChar('G',Count);
  640. end;
  641. function ConvertEraYearString(Count ,Year,Month,Day : integer) : string;
  642. var
  643. ALCID : LCID;
  644. ASystemTime : TSystemTime;
  645. AFormatText : string;
  646. buf : array[0..100] of Char;
  647. begin
  648. Result := '';
  649. DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
  650. if Count <= 2 then
  651. AFormatText := 'yy'
  652. else
  653. AFormatText := 'yyyy';
  654. ALCID := GetThreadLocale;
  655. // ALCID := SysLocale.DefaultLCID;
  656. if GetDateFormatA(ALCID, DATE_USE_ALT_CALENDAR
  657. , @ASystemTime, PChar(AFormatText)
  658. , @buf, SizeOf(buf)) > 0 then
  659. begin
  660. Result := buf;
  661. if (Count = 1) and (Result[1] = '0') then
  662. Result := Copy(Result, 2, Length(Result)-1);
  663. end;
  664. end;
  665. Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
  666. Var
  667. S: String;
  668. C: Integer;
  669. Begin
  670. S:=GetLocaleStr(LID,TP,'0');
  671. Val(S,Result,C);
  672. If C<>0 Then
  673. Result:=Def;
  674. End;
  675. function EnumEraNames(Names: PChar): WINBOOL; stdcall;
  676. var
  677. i : integer;
  678. begin
  679. Result := False;
  680. for i := Low(EraNames) to High(EraNames) do
  681. if (EraNames[i] = '') then
  682. begin
  683. EraNames[i] := Names;
  684. Result := True;
  685. break;
  686. end;
  687. end;
  688. function EnumEraYearOffsets(YearOffsets: PChar): WINBOOL; stdcall;
  689. var
  690. i : integer;
  691. begin
  692. Result := False;
  693. for i := Low(EraYearOffsets) to High(EraYearOffsets) do
  694. if (EraYearOffsets[i] = -1) then
  695. begin
  696. EraYearOffsets[i] := StrToIntDef(YearOffsets, 0);
  697. Result := True;
  698. break;
  699. end;
  700. end;
  701. procedure GetEraNamesAndYearOffsets;
  702. var
  703. ACALID : CALID;
  704. ALCID : LCID;
  705. buf : array[0..10] of char;
  706. i : integer;
  707. begin
  708. for i:= 1 to MaxEraCount do
  709. begin
  710. EraNames[i] := ''; EraYearOffsets[i] := -1;
  711. end;
  712. ALCID := GetThreadLocale;
  713. if GetLocaleInfoA(ALCID , LOCALE_IOPTIONALCALENDAR, buf, sizeof(buf)) <= 0 then exit;
  714. ACALID := StrToIntDef(buf,1);
  715. if ACALID in [3..5] then
  716. begin
  717. EnumCalendarInfoA(@EnumEraNames, ALCID, ACALID , CAL_SERASTRING);
  718. EnumCalendarInfoA(@EnumEraYearOffsets, ALCID, ACALID, CAL_IYEAROFFSETRANGE);
  719. end;
  720. (*
  721. 1 CAL_GREGORIAN Gregorian (localized)
  722. 2 CAL_GREGORIAN_US Gregorian (English strings always)
  723. 3 CAL_JAPAN Japanese Emperor Era
  724. 4 CAL_TAIWAN Taiwan Calendar
  725. 5 CAL_KOREA Korean Tangun Era
  726. 6 CAL_HIJRI Hijri (Arabic Lunar)
  727. 7 CAL_THAI Thai
  728. 8 CAL_HEBREW Hebrew (Lunar)
  729. 9 CAL_GREGORIAN_ME_FRENCH Gregorian Middle East French
  730. 10 CAL_GREGORIAN_ARABIC Gregorian Arabic
  731. 11 CAL_GREGORIAN_XLIT_ENGLISH Gregorian transliterated English
  732. 12 CAL_GREGORIAN_XLIT_FRENCH Gregorian transliterated French
  733. 23 CAL_UMALQURA Windows Vista or later: Um Al Qura (Arabic lunar) calendar
  734. *)
  735. end;
  736. procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings);
  737. var
  738. HF : Shortstring;
  739. LID : Windows.LCID;
  740. I,Day : longint;
  741. begin
  742. LID := LCID;
  743. with FormatSettings do
  744. begin
  745. { Date stuff }
  746. for I := 1 to 12 do
  747. begin
  748. ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
  749. LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
  750. end;
  751. for I := 1 to 7 do
  752. begin
  753. Day := (I + 5) mod 7;
  754. ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
  755. LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
  756. end;
  757. DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
  758. ShortDateFormat := GetLocaleStr(LID, LOCALE_SSHORTDATE, 'm/d/yy');
  759. LongDateFormat := GetLocaleStr(LID, LOCALE_SLONGDATE, 'mmmm d, yyyy');
  760. { Time stuff }
  761. TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
  762. TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
  763. TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
  764. if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
  765. HF:='h'
  766. else
  767. HF:='hh';
  768. // No support for 12 hour stuff at the moment...
  769. ShortTimeFormat := HF+':nn';
  770. LongTimeFormat := HF + ':nn:ss';
  771. { Currency stuff }
  772. CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
  773. CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
  774. NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
  775. { Number stuff }
  776. ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
  777. DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
  778. CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
  779. ListSeparator := GetLocaleChar(LID, LOCALE_SLIST, ',');
  780. end;
  781. end;
  782. procedure GetFormatSettings;
  783. begin
  784. GetlocaleFormatSettings(GetThreadLocale, DefaultFormatSettings);
  785. end;
  786. Procedure InitInternational;
  787. var
  788. { A call to GetSystemMetrics changes the value of the 8087 Control Word on
  789. Pentium4 with WinXP SP2 }
  790. old8087CW: word;
  791. DefaultCustomLocaleID : LCID; // typedef DWORD LCID;
  792. DefaultCustomLanguageID : Word; // typedef WORD LANGID;
  793. begin
  794. /// workaround for Windows 7 bug, see bug report #18574
  795. SetThreadLocale(GetUserDefaultLCID);
  796. InitInternationalGeneric;
  797. old8087CW:=Get8087CW;
  798. SysLocale.MBCS:=GetSystemMetrics(SM_DBCSENABLED)<>0;
  799. SysLocale.RightToLeft:=GetSystemMetrics(SM_MIDEASTENABLED)<>0;
  800. SysLocale.DefaultLCID := $0409;
  801. SysLocale.PriLangID := LANG_ENGLISH;
  802. SysLocale.SubLangID := SUBLANG_ENGLISH_US;
  803. // probably needs update with getthreadlocale. post 2.0.2
  804. DefaultCustomLocaleID := GetThreadLocale;
  805. if DefaultCustomLocaleID <> 0 then
  806. begin
  807. { Locale Identifiers
  808. +-------------+---------+-------------------------+
  809. | Reserved | Sort ID | Language ID |
  810. +-------------+---------+-------------------------+
  811. 31 20 19 16 15 0 bit }
  812. DefaultCustomLanguageID := DefaultCustomLocaleID and $FFFF; // 2^16
  813. if DefaultCustomLanguageID <> 0 then
  814. begin
  815. SysLocale.DefaultLCID := DefaultCustomLocaleID;
  816. { Language Identifiers
  817. +-------------------------+-------------------------+
  818. | SubLanguage ID | Primary Language ID |
  819. +-------------------------+-------------------------+
  820. 15 10 9 0 bit }
  821. SysLocale.PriLangID := DefaultCustomLanguageID and $3ff; // 2^10
  822. SysLocale.SubLangID := DefaultCustomLanguageID shr 10;
  823. end;
  824. end;
  825. Set8087CW(old8087CW);
  826. GetFormatSettings;
  827. if SysLocale.FarEast then GetEraNamesAndYearOffsets;
  828. end;
  829. {****************************************************************************
  830. Target Dependent
  831. ****************************************************************************}
  832. function SysErrorMessage(ErrorCode: Integer): String;
  833. const
  834. MaxMsgSize = Format_Message_Max_Width_Mask;
  835. var
  836. MsgBuffer: PUnicodeChar;
  837. begin
  838. GetMem(MsgBuffer, MaxMsgSize*2);
  839. FillChar(MsgBuffer^, MaxMsgSize*2, #0);
  840. FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
  841. nil,
  842. ErrorCode,
  843. MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
  844. MsgBuffer,
  845. MaxMsgSize,
  846. nil);
  847. SysErrorMessage := MsgBuffer;
  848. FreeMem(MsgBuffer, MaxMsgSize);
  849. end;
  850. {****************************************************************************
  851. Initialization code
  852. ****************************************************************************}
  853. {$push}
  854. { GetEnvironmentStrings cannot be checked by CheckPointer function }
  855. {$checkpointer off}
  856. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  857. var
  858. oemenvvar, oemstr : RawByteString;
  859. i, hplen : longint;
  860. hp,p : pchar;
  861. begin
  862. oemenvvar:=uppercase(envvar);
  863. SetCodePage(oemenvvar,CP_OEMCP);
  864. Result:='';
  865. p:=GetEnvironmentStringsA;
  866. hp:=p;
  867. while hp^<>#0 do
  868. begin
  869. oemstr:=hp;
  870. { cache length, may change after uppercasing depending on code page }
  871. hplen:=length(oemstr);
  872. { all environment variables are encoded in the oem code page }
  873. SetCodePage(oemstr,CP_OEMCP,false);
  874. i:=pos('=',oemstr);
  875. if uppercase(copy(oemstr,1,i-1))=oemenvvar then
  876. begin
  877. Result:=copy(oemstr,i+1,length(oemstr)-i);
  878. break;
  879. end;
  880. { next string entry}
  881. hp:=hp+hplen+1;
  882. end;
  883. FreeEnvironmentStringsA(p);
  884. end;
  885. Function GetEnvironmentVariable(Const EnvVar : UnicodeString) : UnicodeString;
  886. var
  887. s, upperenv : Unicodestring;
  888. i : longint;
  889. hp,p : pwidechar;
  890. begin
  891. Result:='';
  892. p:=GetEnvironmentStringsW;
  893. hp:=p;
  894. upperenv:=uppercase(envvar);
  895. while hp^<>#0 do
  896. begin
  897. s:=hp;
  898. i:=pos('=',s);
  899. if uppercase(copy(s,1,i-1))=upperenv then
  900. begin
  901. Result:=copy(s,i+1,length(s)-i);
  902. break;
  903. end;
  904. { next string entry}
  905. hp:=hp+strlen(hp)+1;
  906. end;
  907. FreeEnvironmentStringsW(p);
  908. end;
  909. Function GetEnvironmentVariableCount : Integer;
  910. var
  911. hp,p : pchar;
  912. begin
  913. Result:=0;
  914. p:=GetEnvironmentStringsA;
  915. hp:=p;
  916. If (Hp<>Nil) then
  917. while hp^<>#0 do
  918. begin
  919. Inc(Result);
  920. hp:=hp+strlen(hp)+1;
  921. end;
  922. FreeEnvironmentStringsA(p);
  923. end;
  924. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  925. var
  926. hp,p : pchar;
  927. {$ifdef FPC_RTL_UNICODE}
  928. tmpstr : RawByteString;
  929. {$endif}
  930. begin
  931. Result:='';
  932. p:=GetEnvironmentStringsA;
  933. hp:=p;
  934. If (Hp<>Nil) then
  935. begin
  936. while (hp^<>#0) and (Index>1) do
  937. begin
  938. Dec(Index);
  939. hp:=hp+strlen(hp)+1;
  940. end;
  941. If (hp^<>#0) then
  942. begin
  943. {$ifdef FPC_RTL_UNICODE}
  944. tmpstr:=hp;
  945. SetCodePage(tmpstr,CP_OEMCP,false);
  946. Result:=tmpstr;
  947. {$else}
  948. Result:=hp;
  949. SetCodePage(RawByteString(Result),CP_OEMCP,false);
  950. {$endif}
  951. end;
  952. end;
  953. FreeEnvironmentStringsA(p);
  954. end;
  955. {$pop}
  956. function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
  957. begin
  958. result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags);
  959. end;
  960. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
  961. // win specific function
  962. var
  963. SI: TStartupInfoW;
  964. PI: TProcessInformation;
  965. Proc : THandle;
  966. l : DWord;
  967. CommandLine : unicodestring;
  968. e : EOSError;
  969. ExecInherits : longbool;
  970. begin
  971. FillChar(SI, SizeOf(SI), 0);
  972. SI.cb:=SizeOf(SI);
  973. SI.wShowWindow:=1;
  974. { always surround the name of the application by quotes
  975. so that long filenames will always be accepted. But don't
  976. do it if there are already double quotes, since Win32 does not
  977. like double quotes which are duplicated!
  978. }
  979. if pos('"',path)=0 then
  980. CommandLine:='"'+path+'"'
  981. else
  982. CommandLine:=path;
  983. if ComLine <> '' then
  984. CommandLine:=Commandline+' '+ComLine+#0
  985. else
  986. CommandLine := CommandLine + #0;
  987. ExecInherits:=ExecInheritsHandles in Flags;
  988. if not CreateProcessW(nil, pwidechar(CommandLine),
  989. Nil, Nil, ExecInherits,$20, Nil, Nil, SI, PI) then
  990. begin
  991. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  992. e.ErrorCode:=GetLastError;
  993. raise e;
  994. end;
  995. Proc:=PI.hProcess;
  996. if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
  997. begin
  998. GetExitCodeProcess(Proc,l);
  999. CloseHandle(Proc);
  1000. CloseHandle(PI.hThread);
  1001. result:=l;
  1002. end
  1003. else
  1004. begin
  1005. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  1006. e.ErrorCode:=GetLastError;
  1007. CloseHandle(Proc);
  1008. CloseHandle(PI.hThread);
  1009. raise e;
  1010. end;
  1011. end;
  1012. function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
  1013. var
  1014. CommandLine: UnicodeString;
  1015. I: integer;
  1016. begin
  1017. Commandline := '';
  1018. for I := 0 to High (ComLine) do
  1019. if Pos (' ', ComLine [I]) <> 0 then
  1020. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1021. else
  1022. CommandLine := CommandLine + ' ' + Comline [I];
  1023. ExecuteProcess := ExecuteProcess (UnicodeString(Path), CommandLine,Flags);
  1024. end;
  1025. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
  1026. var
  1027. CommandLine: UnicodeString;
  1028. I: integer;
  1029. begin
  1030. Commandline := '';
  1031. for I := 0 to High (ComLine) do
  1032. if Pos (' ', ComLine [I]) <> 0 then
  1033. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1034. else
  1035. CommandLine := CommandLine + ' ' + Comline [I];
  1036. ExecuteProcess := ExecuteProcess (Path,CommandLine,Flags);
  1037. end;
  1038. Procedure Sleep(Milliseconds : Cardinal);
  1039. begin
  1040. Windows.Sleep(MilliSeconds)
  1041. end;
  1042. Function GetLastOSError : Integer;
  1043. begin
  1044. Result:=GetLastError;
  1045. end;
  1046. {****************************************************************************
  1047. Initialization code
  1048. ****************************************************************************}
  1049. var
  1050. kernel32dll : THandle;
  1051. Procedure LoadVersionInfo;
  1052. // and getfreespaceex
  1053. Var
  1054. versioninfo : TOSVERSIONINFO;
  1055. begin
  1056. GetDiskFreeSpaceEx:=nil;
  1057. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  1058. GetVersionEx(versioninfo);
  1059. Win32Platform:=versionInfo.dwPlatformId;
  1060. Win32MajorVersion:=versionInfo.dwMajorVersion;
  1061. Win32MinorVersion:=versionInfo.dwMinorVersion;
  1062. Win32BuildNumber:=versionInfo.dwBuildNumber;
  1063. Move (versioninfo.szCSDVersion ,Win32CSDVersion[1],128);
  1064. win32CSDVersion[0]:=chr(strlen(pchar(@versioninfo.szCSDVersion)));
  1065. kernel32dll:=GetModuleHandle('kernel32');
  1066. if kernel32dll<>0 then
  1067. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  1068. end;
  1069. Function GetAppConfigDir(Global : Boolean) : String;
  1070. begin
  1071. If Global then
  1072. Result:=GetWindowsSpecialDir(CSIDL_COMMON_APPDATA)
  1073. else
  1074. Result:=GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA);
  1075. If (Result<>'') then
  1076. begin
  1077. if VendorName<>'' then
  1078. Result:=IncludeTrailingPathDelimiter(Result+VendorName);
  1079. Result:=IncludeTrailingPathDelimiter(Result+ApplicationName);
  1080. end
  1081. else
  1082. Result:=IncludeTrailingPathDelimiter(DGetAppConfigDir(Global));
  1083. end;
  1084. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  1085. begin
  1086. result:=DGetAppConfigFile(Global,SubDir);
  1087. end;
  1088. Function GetUserDir : String;
  1089. begin
  1090. Result:=GetWindowsSpecialDir(CSIDL_PROFILE);
  1091. end;
  1092. Procedure InitSysConfigDir;
  1093. begin
  1094. SetLength(SysConfigDir, MAX_PATH);
  1095. SetLength(SysConfigDir, GetWindowsDirectoryA(PChar(SysConfigDir), MAX_PATH));
  1096. end;
  1097. {****************************************************************************
  1098. Target Dependent WideString stuff
  1099. ****************************************************************************}
  1100. { This is the case of Win9x. Limited to current locale of course, but it's better
  1101. than not working at all. }
  1102. function DoCompareStringA(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
  1103. var
  1104. a1, a2: AnsiString;
  1105. begin
  1106. if L1>0 then
  1107. widestringmanager.Wide2AnsiMoveProc(P1,a1,DefaultSystemCodePage,L1);
  1108. if L2>0 then
  1109. widestringmanager.Wide2AnsiMoveProc(P2,a2,DefaultSystemCodePage,L2);
  1110. SetLastError(0);
  1111. Result:=CompareStringA(LOCALE_USER_DEFAULT,Flags,pchar(a1),
  1112. length(a1),pchar(a2),length(a2))-2;
  1113. end;
  1114. function DoCompareStringW(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
  1115. begin
  1116. SetLastError(0);
  1117. Result:=CompareStringW(LOCALE_USER_DEFAULT,Flags,P1,L1,P2,L2)-2;
  1118. if GetLastError=0 then
  1119. Exit;
  1120. if GetLastError=ERROR_CALL_NOT_IMPLEMENTED then // Win9x case
  1121. Result:=DoCompareStringA(P1, P2, L1, L2, Flags);
  1122. if GetLastError<>0 then
  1123. RaiseLastOSError;
  1124. end;
  1125. const
  1126. WinAPICompareFlags : array [TCompareOption] of LongWord
  1127. = ({LINGUISTIC_IGNORECASE, LINGUISTIC_IGNOREDIACRITIC, }NORM_IGNORECASE{,
  1128. NORM_IGNOREKANATYPE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS, NORM_IGNOREWIDTH,
  1129. NORM_LINGUISTIC_CASING, SORT_DIGITSASNUMBERS, SORT_STRINGSORT});
  1130. function Win32CompareWideString(const s1, s2 : WideString; Options : TCompareOptions) : PtrInt;
  1131. Var
  1132. O : LongWord;
  1133. CO : TCompareOption;
  1134. begin
  1135. O:=0;
  1136. for CO in TCompareOption do
  1137. if CO in Options then
  1138. O:=O or WinAPICompareFlags[CO];
  1139. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), O);
  1140. end;
  1141. function Win32CompareTextWideString(const s1, s2 : WideString) : PtrInt;
  1142. begin
  1143. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
  1144. end;
  1145. function Win32AnsiUpperCase(const s: string): string;
  1146. begin
  1147. if length(s)>0 then
  1148. begin
  1149. result:=s;
  1150. UniqueString(result);
  1151. CharUpperBuffA(pchar(result),length(result));
  1152. end
  1153. else
  1154. result:='';
  1155. end;
  1156. function Win32AnsiLowerCase(const s: string): string;
  1157. begin
  1158. if length(s)>0 then
  1159. begin
  1160. result:=s;
  1161. UniqueString(result);
  1162. CharLowerBuffA(pchar(result),length(result));
  1163. end
  1164. else
  1165. result:='';
  1166. end;
  1167. function Win32AnsiCompareStr(const S1, S2: string): PtrInt;
  1168. begin
  1169. result:=CompareStringA(LOCALE_USER_DEFAULT,0,pchar(s1),length(s1),
  1170. pchar(s2),length(s2))-2;
  1171. end;
  1172. function Win32AnsiCompareText(const S1, S2: string): PtrInt;
  1173. begin
  1174. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,pchar(s1),length(s1),
  1175. pchar(s2),length(s2))-2;
  1176. end;
  1177. function Win32AnsiStrComp(S1, S2: PChar): PtrInt;
  1178. begin
  1179. result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,-1,s2,-1)-2;
  1180. end;
  1181. function Win32AnsiStrIComp(S1, S2: PChar): PtrInt;
  1182. begin
  1183. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,-1,s2,-1)-2;
  1184. end;
  1185. function Win32AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1186. begin
  1187. result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,maxlen,s2,maxlen)-2;
  1188. end;
  1189. function Win32AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1190. begin
  1191. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,maxlen,s2,maxlen)-2;
  1192. end;
  1193. function Win32AnsiStrLower(Str: PChar): PChar;
  1194. begin
  1195. CharLowerA(str);
  1196. result:=str;
  1197. end;
  1198. function Win32AnsiStrUpper(Str: PChar): PChar;
  1199. begin
  1200. CharUpperA(str);
  1201. result:=str;
  1202. end;
  1203. function Win32CompareUnicodeString(const s1, s2 : UnicodeString; Options : TCompareOptions) : PtrInt;
  1204. Var
  1205. O : LongWord;
  1206. CO : TCompareOption;
  1207. begin
  1208. O:=0;
  1209. for CO in TCompareOption do
  1210. if CO in Options then
  1211. O:=O or WinAPICompareFlags[CO];
  1212. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), O);
  1213. end;
  1214. function Win32CompareTextUnicodeString(const s1, s2 : UnicodeString) : PtrInt;
  1215. begin
  1216. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
  1217. end;
  1218. { there is a similiar procedure in the system unit which inits the fields which
  1219. are relevant already for the system unit }
  1220. procedure InitWin32Widestrings;
  1221. begin
  1222. { return value: number of code points in the string. Whenever an invalid
  1223. code point is encountered, all characters part of this invalid code point
  1224. are considered to form one "character" and the next character is
  1225. considered to be the start of a new (possibly also invalid) code point }
  1226. //!!! CharLengthPCharProc : function(const Str: PChar): PtrInt;
  1227. { return value:
  1228. -1 if incomplete or invalid code point
  1229. 0 if NULL character,
  1230. > 0 if that's the length in bytes of the code point }
  1231. //!!!! CodePointLengthProc : function(const Str: PChar; MaxLookAead: PtrInt): Ptrint;
  1232. widestringmanager.CompareWideStringProc:=@Win32CompareWideString;
  1233. widestringmanager.UpperAnsiStringProc:=@Win32AnsiUpperCase;
  1234. widestringmanager.LowerAnsiStringProc:=@Win32AnsiLowerCase;
  1235. widestringmanager.CompareStrAnsiStringProc:=@Win32AnsiCompareStr;
  1236. widestringmanager.CompareTextAnsiStringProc:=@Win32AnsiCompareText;
  1237. widestringmanager.StrCompAnsiStringProc:=@Win32AnsiStrComp;
  1238. widestringmanager.StrICompAnsiStringProc:=@Win32AnsiStrIComp;
  1239. widestringmanager.StrLCompAnsiStringProc:=@Win32AnsiStrLComp;
  1240. widestringmanager.StrLICompAnsiStringProc:=@Win32AnsiStrLIComp;
  1241. widestringmanager.StrLowerAnsiStringProc:=@Win32AnsiStrLower;
  1242. widestringmanager.StrUpperAnsiStringProc:=@Win32AnsiStrUpper;
  1243. widestringmanager.CompareUnicodeStringProc:=@Win32CompareUnicodeString;
  1244. end;
  1245. { Platform-specific exception support }
  1246. function WinExceptionObject(code: Longint; const rec: TExceptionRecord): Exception;
  1247. var
  1248. entry: PExceptMapEntry;
  1249. begin
  1250. entry := FindExceptMapEntry(code);
  1251. if assigned(entry) then
  1252. result:=entry^.cls.CreateRes(entry^.msg)
  1253. else
  1254. result:=EExternalException.CreateResFmt(@SExternalException,[rec.ExceptionCode]);
  1255. if result is EExternal then
  1256. EExternal(result).FExceptionRecord:=rec;
  1257. end;
  1258. function WinExceptionClass(code: longint): ExceptClass;
  1259. var
  1260. entry: PExceptMapEntry;
  1261. begin
  1262. entry := FindExceptMapEntry(code);
  1263. if assigned(entry) then
  1264. result:=entry^.cls
  1265. else
  1266. result:=EExternalException;
  1267. end;
  1268. Initialization
  1269. InitWin32Widestrings;
  1270. InitExceptions; { Initialize exceptions. OS independent }
  1271. {$ifdef mswindows} { Keeps exe size down for systems that do not use SEH }
  1272. ExceptObjProc:=@WinExceptionObject;
  1273. ExceptClsProc:=@WinExceptionClass;
  1274. {$endif mswindows}
  1275. InitInternational; { Initialize internationalization settings }
  1276. LoadVersionInfo;
  1277. InitSysConfigDir;
  1278. OnBeep:=@SysBeep;
  1279. Finalization
  1280. DoneExceptions;
  1281. end.