2
0

sysutils.pp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  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. { force ansistrings }
  16. {$H+}
  17. uses
  18. dos,
  19. windows;
  20. {$DEFINE HAS_SLEEP}
  21. {$DEFINE HAS_OSERROR}
  22. {$DEFINE HAS_OSCONFIG}
  23. {$DEFINE HAS_CREATEGUID}
  24. { Include platform independent interface part }
  25. {$i sysutilh.inc}
  26. type
  27. TSystemTime = Windows.TSystemTime;
  28. EWin32Error = class(Exception)
  29. public
  30. ErrorCode : DWORD;
  31. end;
  32. Var
  33. Win32Platform : Longint;
  34. Win32MajorVersion,
  35. Win32MinorVersion,
  36. Win32BuildNumber : dword;
  37. Win32CSDVersion : ShortString; // CSD record is 128 bytes only?
  38. implementation
  39. uses
  40. sysconst;
  41. {$define HASCREATEGUID}
  42. {$define HASEXPANDUNCFILENAME}
  43. { Include platform independent implementation part }
  44. {$i sysutils.inc}
  45. Function SysGetTempFileName(lpPathName:LPCSTR; lpPrefixString:LPCSTR; uUnique:UINT; lpTempFileName:LPSTR):UINT; external 'kernel32' name 'GetTempFileNameA';
  46. function GetTempFileName(Dir,Prefix: PChar; uUnique: DWORD; TempFileName: PChar):DWORD;
  47. begin
  48. Result:=SysGetTempFileName(Dir,Prefix,uUnique,TempFileName);
  49. end;
  50. { UUID generation. }
  51. function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';
  52. function SysCreateGUID(out Guid: TGUID): Integer;
  53. begin
  54. Result := Integer(CoCreateGuid(Guid));
  55. end;
  56. function ExpandUNCFileName (const filename:string) : string;
  57. { returns empty string on errors }
  58. var
  59. s : ansistring;
  60. size : dword;
  61. rc : dword;
  62. p,buf : pchar;
  63. begin
  64. s := ExpandFileName (filename);
  65. s := s + #0;
  66. size := max_path;
  67. getmem(buf,size);
  68. try
  69. rc := WNetGetUniversalName (pchar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  70. if rc=ERROR_MORE_DATA then
  71. begin
  72. buf:=reallocmem(buf,size);
  73. rc := WNetGetUniversalName (pchar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  74. end;
  75. if rc = NO_ERROR then
  76. Result := PRemoteNameInfo(buf)^.lpUniversalName
  77. else if rc = ERROR_NOT_CONNECTED then
  78. Result := filename
  79. else
  80. Result := '';
  81. finally
  82. freemem(buf);
  83. end;
  84. end;
  85. {****************************************************************************
  86. File Functions
  87. ****************************************************************************}
  88. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  89. const
  90. AccessMode: array[0..2] of Cardinal = (
  91. GENERIC_READ,
  92. GENERIC_WRITE,
  93. GENERIC_READ or GENERIC_WRITE);
  94. ShareMode: array[0..4] of Integer = (
  95. 0,
  96. 0,
  97. FILE_SHARE_READ,
  98. FILE_SHARE_WRITE,
  99. FILE_SHARE_READ or FILE_SHARE_WRITE);
  100. Var
  101. FN : string;
  102. begin
  103. FN:=FileName+#0;
  104. result := CreateFile(@FN[1], dword(AccessMode[Mode and 3]),
  105. dword(ShareMode[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
  106. FILE_ATTRIBUTE_NORMAL, 0);
  107. end;
  108. Function FileCreate (Const FileName : String) : Longint;
  109. Var
  110. FN : string;
  111. begin
  112. FN:=FileName+#0;
  113. Result := CreateFile(@FN[1], GENERIC_READ or GENERIC_WRITE,
  114. 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  115. end;
  116. Function FileCreate (Const FileName : String; Mode:longint) : SizeInt;
  117. begin
  118. FileCreate:=FileCreate(FileName);
  119. end;
  120. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  121. Var
  122. res : dword;
  123. begin
  124. if ReadFile(Handle, Buffer, Count, res, nil) then
  125. FileRead:=Res
  126. else
  127. FileRead:=-1;
  128. end;
  129. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  130. Var
  131. Res : dword;
  132. begin
  133. if WriteFile(Handle, Buffer, Count, Res, nil) then
  134. FileWrite:=Res
  135. else
  136. FileWrite:=-1;
  137. end;
  138. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  139. begin
  140. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  141. end;
  142. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  143. begin
  144. {$warning need to add 64bit call }
  145. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  146. end;
  147. Procedure FileClose (Handle : Longint);
  148. begin
  149. if Handle<=4 then
  150. exit;
  151. CloseHandle(Handle);
  152. end;
  153. Function FileTruncate (Handle,Size: Longint) : boolean;
  154. begin
  155. Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
  156. If Result then
  157. Result:=SetEndOfFile(handle);
  158. end;
  159. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  160. var
  161. lft : TFileTime;
  162. begin
  163. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
  164. LocalFileTimeToFileTime(lft,Wtime);
  165. end;
  166. Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
  167. var
  168. lft : TFileTime;
  169. begin
  170. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  171. FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
  172. end;
  173. Function FileAge (Const FileName : String): Longint;
  174. var
  175. Handle: THandle;
  176. FindData: TWin32FindData;
  177. begin
  178. Handle := FindFirstFile(Pchar(FileName), FindData);
  179. if Handle <> INVALID_HANDLE_VALUE then
  180. begin
  181. Windows.FindClose(Handle);
  182. if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  183. If WinToDosTime(FindData.ftLastWriteTime,Result) then
  184. exit;
  185. end;
  186. Result := -1;
  187. end;
  188. Function FileExists (Const FileName : String) : Boolean;
  189. var
  190. Handle: THandle;
  191. FindData: TWin32FindData;
  192. begin
  193. Handle := FindFirstFile(Pchar(FileName), FindData);
  194. Result:=Handle <> INVALID_HANDLE_VALUE;
  195. If Result then
  196. Windows.FindClose(Handle);
  197. end;
  198. Function DirectoryExists (Const Directory : String) : Boolean;
  199. var
  200. Handle: THandle;
  201. FindData: TWin32FindData;
  202. begin
  203. Result:=False;
  204. Handle := FindFirstFile(Pchar(Directory), FindData);
  205. If (Handle <> INVALID_HANDLE_VALUE) then
  206. begin
  207. Result:=((FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY);
  208. Windows.FindClose(Handle);
  209. end;
  210. end;
  211. Function FindMatch(var f: TSearchRec) : Longint;
  212. begin
  213. { Find file with correct attribute }
  214. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  215. begin
  216. if not FindNextFile (F.FindHandle,F.FindData) then
  217. begin
  218. Result:=GetLastError;
  219. exit;
  220. end;
  221. end;
  222. { Convert some attributes back }
  223. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  224. f.size:=F.FindData.NFileSizeLow;
  225. f.attr:=F.FindData.dwFileAttributes;
  226. f.Name:=StrPas(@F.FindData.cFileName);
  227. Result:=0;
  228. end;
  229. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  230. begin
  231. Rslt.Name:=Path;
  232. Rslt.Attr:=attr;
  233. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  234. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  235. { FindFirstFile is a Win32 Call }
  236. Rslt.FindHandle:=FindFirstFile (PChar(Path),Rslt.FindData);
  237. If Rslt.FindHandle=Invalid_Handle_value then
  238. begin
  239. Result:=GetLastError;
  240. exit;
  241. end;
  242. { Find file with correct attribute }
  243. Result:=FindMatch(Rslt);
  244. end;
  245. Function FindNext (Var Rslt : TSearchRec) : Longint;
  246. begin
  247. if FindNextFile(Rslt.FindHandle, Rslt.FindData) then
  248. Result := FindMatch(Rslt)
  249. else
  250. Result := GetLastError;
  251. end;
  252. Procedure FindClose (Var F : TSearchrec);
  253. begin
  254. if F.FindHandle <> INVALID_HANDLE_VALUE then
  255. Windows.FindClose(F.FindHandle);
  256. end;
  257. Function FileGetDate (Handle : Longint) : Longint;
  258. Var
  259. FT : TFileTime;
  260. begin
  261. If GetFileTime(Handle,nil,nil,@ft) and
  262. WinToDosTime(FT,Result) then
  263. exit;
  264. Result:=-1;
  265. end;
  266. Function FileSetDate (Handle,Age : Longint) : Longint;
  267. Var
  268. FT: TFileTime;
  269. begin
  270. Result := 0;
  271. if DosToWinTime(Age,FT) and
  272. SetFileTime(Handle, ft, ft, FT) then
  273. Exit;
  274. Result := GetLastError;
  275. end;
  276. Function FileGetAttr (Const FileName : String) : Longint;
  277. begin
  278. Result:=GetFileAttributes(PChar(FileName));
  279. end;
  280. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  281. begin
  282. if not SetFileAttributes(PChar(FileName), Attr) then
  283. Result := GetLastError
  284. else
  285. Result:=0;
  286. end;
  287. Function DeleteFile (Const FileName : String) : Boolean;
  288. begin
  289. DeleteFile:=Windows.DeleteFile(Pchar(FileName));
  290. end;
  291. Function RenameFile (Const OldName, NewName : String) : Boolean;
  292. begin
  293. Result := MoveFile(PChar(OldName), PChar(NewName));
  294. end;
  295. {****************************************************************************
  296. Disk Functions
  297. ****************************************************************************}
  298. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  299. freeclusters,totalclusters:longint):longbool;
  300. stdcall;external 'kernel32' name 'GetDiskFreeSpaceA';
  301. type
  302. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
  303. var
  304. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  305. function diskfree(drive : byte) : int64;
  306. var
  307. disk : array[1..4] of char;
  308. secs,bytes,
  309. free,total : longint;
  310. qwtotal,qwfree,qwcaller : int64;
  311. begin
  312. if drive=0 then
  313. begin
  314. disk[1]:='\';
  315. disk[2]:=#0;
  316. end
  317. else
  318. begin
  319. disk[1]:=chr(drive+64);
  320. disk[2]:=':';
  321. disk[3]:='\';
  322. disk[4]:=#0;
  323. end;
  324. if assigned(GetDiskFreeSpaceEx) then
  325. begin
  326. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  327. diskfree:=qwfree
  328. else
  329. diskfree:=-1;
  330. end
  331. else
  332. begin
  333. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  334. diskfree:=int64(free)*secs*bytes
  335. else
  336. diskfree:=-1;
  337. end;
  338. end;
  339. function disksize(drive : byte) : int64;
  340. var
  341. disk : array[1..4] of char;
  342. secs,bytes,
  343. free,total : longint;
  344. qwtotal,qwfree,qwcaller : int64;
  345. begin
  346. if drive=0 then
  347. begin
  348. disk[1]:='\';
  349. disk[2]:=#0;
  350. end
  351. else
  352. begin
  353. disk[1]:=chr(drive+64);
  354. disk[2]:=':';
  355. disk[3]:='\';
  356. disk[4]:=#0;
  357. end;
  358. if assigned(GetDiskFreeSpaceEx) then
  359. begin
  360. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  361. disksize:=qwtotal
  362. else
  363. disksize:=-1;
  364. end
  365. else
  366. begin
  367. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  368. disksize:=int64(total)*secs*bytes
  369. else
  370. disksize:=-1;
  371. end;
  372. end;
  373. Function GetCurrentDir : String;
  374. begin
  375. GetDir(0, result);
  376. end;
  377. Function SetCurrentDir (Const NewDir : String) : Boolean;
  378. begin
  379. {$I-}
  380. ChDir(NewDir);
  381. {$I+}
  382. result := (IOResult = 0);
  383. end;
  384. Function CreateDir (Const NewDir : String) : Boolean;
  385. begin
  386. {$I-}
  387. MkDir(NewDir);
  388. {$I+}
  389. result := (IOResult = 0);
  390. end;
  391. Function RemoveDir (Const Dir : String) : Boolean;
  392. begin
  393. {$I-}
  394. RmDir(Dir);
  395. {$I+}
  396. result := (IOResult = 0);
  397. end;
  398. {****************************************************************************
  399. Time Functions
  400. ****************************************************************************}
  401. Procedure GetLocalTime(var SystemTime: TSystemTime);
  402. Var
  403. Syst : Windows.TSystemtime;
  404. begin
  405. windows.Getlocaltime(@syst);
  406. SystemTime.year:=syst.wYear;
  407. SystemTime.month:=syst.wMonth;
  408. SystemTime.day:=syst.wDay;
  409. SystemTime.hour:=syst.wHour;
  410. SystemTime.minute:=syst.wMinute;
  411. SystemTime.second:=syst.wSecond;
  412. SystemTime.millisecond:=syst.wMilliSeconds;
  413. end;
  414. {****************************************************************************
  415. Misc Functions
  416. ****************************************************************************}
  417. procedure Beep;
  418. begin
  419. MessageBeep(0);
  420. end;
  421. {****************************************************************************
  422. Locale Functions
  423. ****************************************************************************}
  424. Procedure InitAnsi;
  425. Var
  426. i : longint;
  427. begin
  428. { Fill table entries 0 to 127 }
  429. for i := 0 to 96 do
  430. UpperCaseTable[i] := chr(i);
  431. for i := 97 to 122 do
  432. UpperCaseTable[i] := chr(i - 32);
  433. for i := 123 to 191 do
  434. UpperCaseTable[i] := chr(i);
  435. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  436. for i := 0 to 64 do
  437. LowerCaseTable[i] := chr(i);
  438. for i := 65 to 90 do
  439. LowerCaseTable[i] := chr(i + 32);
  440. for i := 91 to 191 do
  441. LowerCaseTable[i] := chr(i);
  442. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  443. end;
  444. function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
  445. var
  446. L: Integer;
  447. Buf: array[0..255] of Char;
  448. begin
  449. L := GetLocaleInfo(LID, LT, Buf, SizeOf(Buf));
  450. if L > 0 then
  451. SetString(Result, @Buf[0], L - 1)
  452. else
  453. Result := Def;
  454. end;
  455. function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
  456. var
  457. Buf: array[0..1] of Char;
  458. begin
  459. if GetLocaleInfo(LID, LT, Buf, 2) > 0 then
  460. Result := Buf[0]
  461. else
  462. Result := Def;
  463. end;
  464. Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
  465. Var
  466. S: String;
  467. C: Integer;
  468. Begin
  469. S:=GetLocaleStr(LID,TP,'0');
  470. Val(S,Result,C);
  471. If C<>0 Then
  472. Result:=Def;
  473. End;
  474. procedure GetFormatSettings;
  475. var
  476. HF : Shortstring;
  477. LID : LCID;
  478. I,Day,DateOrder : longint;
  479. begin
  480. LID := GetThreadLocale;
  481. { Date stuff }
  482. for I := 1 to 12 do
  483. begin
  484. ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
  485. LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
  486. end;
  487. for I := 1 to 7 do
  488. begin
  489. Day := (I + 5) mod 7;
  490. ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
  491. LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
  492. end;
  493. DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
  494. DateOrder := GetLocaleInt(LID, LOCALE_IDate, 0);
  495. Case DateOrder Of
  496. 1: Begin
  497. ShortDateFormat := 'dd/mm/yyyy';
  498. LongDateFormat := 'dddd, d. mmmm yyyy';
  499. End;
  500. 2: Begin
  501. ShortDateFormat := 'yyyy/mm/dd';
  502. LongDateFormat := 'dddd, yyyy mmmm d.';
  503. End;
  504. else
  505. // Default american settings...
  506. ShortDateFormat := 'mm/dd/yyyy';
  507. LongDateFormat := 'dddd, mmmm d. yyyy';
  508. End;
  509. { Time stuff }
  510. TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
  511. TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
  512. TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
  513. if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
  514. HF:='h'
  515. else
  516. HF:='hh';
  517. // No support for 12 hour stuff at the moment...
  518. ShortTimeFormat := HF+':nn';
  519. LongTimeFormat := HF + ':nn:ss';
  520. { Currency stuff }
  521. CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
  522. CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
  523. NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
  524. { Number stuff }
  525. ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
  526. DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
  527. CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
  528. end;
  529. Procedure InitInternational;
  530. var
  531. { A call to GetSystemMetrics changes the value of the 8087 Control Word on
  532. Pentium4 with WinXP SP2 }
  533. old8087CW: word;
  534. begin
  535. InitInternationalGeneric;
  536. old8087CW:=Get8087CW;
  537. SysLocale.MBCS:=GetSystemMetrics(SM_DBCSENABLED)<>0;
  538. SysLocale.RightToLeft:=GetSystemMetrics(SM_MIDEASTENABLED)<>0;
  539. SysLocale.DefaultLCID := $0409;
  540. SysLocale.PriLangID := LANG_ENGLISH;
  541. SysLocale.SubLangID := SUBLANG_ENGLISH_US;
  542. // probably needs update with getthreadlocale. post 2.0.2
  543. Set8087CW(old8087CW);
  544. InitAnsi;
  545. GetFormatSettings;
  546. end;
  547. {****************************************************************************
  548. Target Dependent
  549. ****************************************************************************}
  550. function FormatMessageA(dwFlags : DWORD;
  551. lpSource : Pointer;
  552. dwMessageId : DWORD;
  553. dwLanguageId: DWORD;
  554. lpBuffer : PCHAR;
  555. nSize : DWORD;
  556. Arguments : Pointer): DWORD; stdcall;external 'kernel32' name 'FormatMessageA';
  557. function SysErrorMessage(ErrorCode: Integer): String;
  558. const
  559. MaxMsgSize = Format_Message_Max_Width_Mask;
  560. var
  561. MsgBuffer: pChar;
  562. begin
  563. GetMem(MsgBuffer, MaxMsgSize);
  564. FillChar(MsgBuffer^, MaxMsgSize, #0);
  565. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
  566. nil,
  567. ErrorCode,
  568. MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
  569. MsgBuffer, { This function allocs the memory }
  570. MaxMsgSize, { Maximum message size }
  571. nil);
  572. SysErrorMessage := StrPas(MsgBuffer);
  573. FreeMem(MsgBuffer, MaxMsgSize);
  574. end;
  575. {****************************************************************************
  576. Initialization code
  577. ****************************************************************************}
  578. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  579. var
  580. s : string;
  581. i : longint;
  582. hp,p : pchar;
  583. begin
  584. Result:='';
  585. p:=GetEnvironmentStrings;
  586. hp:=p;
  587. while hp^<>#0 do
  588. begin
  589. s:=strpas(hp);
  590. i:=pos('=',s);
  591. if uppercase(copy(s,1,i-1))=upcase(envvar) then
  592. begin
  593. Result:=copy(s,i+1,length(s)-i);
  594. break;
  595. end;
  596. { next string entry}
  597. hp:=hp+strlen(hp)+1;
  598. end;
  599. FreeEnvironmentStrings(p);
  600. end;
  601. Function GetEnvironmentVariableCount : Integer;
  602. var
  603. hp,p : pchar;
  604. begin
  605. Result:=0;
  606. p:=GetEnvironmentStrings;
  607. hp:=p;
  608. If (Hp<>Nil) then
  609. while hp^<>#0 do
  610. begin
  611. Inc(Result);
  612. hp:=hp+strlen(hp)+1;
  613. end;
  614. FreeEnvironmentStrings(p);
  615. end;
  616. Function GetEnvironmentString(Index : Integer) : String;
  617. var
  618. hp,p : pchar;
  619. begin
  620. Result:='';
  621. p:=GetEnvironmentStrings;
  622. hp:=p;
  623. If (Hp<>Nil) then
  624. begin
  625. while (hp^<>#0) and (Index>1) do
  626. begin
  627. Dec(Index);
  628. hp:=hp+strlen(hp)+1;
  629. end;
  630. If (hp^<>#0) then
  631. Result:=StrPas(HP);
  632. end;
  633. FreeEnvironmentStrings(p);
  634. end;
  635. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  636. var
  637. SI: TStartupInfo;
  638. PI: TProcessInformation;
  639. Proc : TWin32Handle;
  640. l : DWord;
  641. CommandLine : ansistring;
  642. e : EOSError;
  643. begin
  644. DosError := 0;
  645. FillChar(SI, SizeOf(SI), 0);
  646. SI.cb:=SizeOf(SI);
  647. SI.wShowWindow:=1;
  648. { always surround the name of the application by quotes
  649. so that long filenames will always be accepted. But don't
  650. do it if there are already double quotes, since Win32 does not
  651. like double quotes which are duplicated!
  652. }
  653. if pos('"',path)=0 then
  654. CommandLine:='"'+path+'"'
  655. else
  656. CommandLine:=path;
  657. if ComLine <> '' then
  658. CommandLine:=Commandline+' '+ComLine+#0
  659. else
  660. CommandLine := CommandLine + #0;
  661. if not CreateProcess(nil, pchar(CommandLine),
  662. Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
  663. begin
  664. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  665. e.ErrorCode:=GetLastError;
  666. raise e;
  667. end;
  668. Proc:=PI.hProcess;
  669. CloseHandle(PI.hThread);
  670. if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
  671. begin
  672. GetExitCodeProcess(Proc,l);
  673. CloseHandle(Proc);
  674. result:=l;
  675. end
  676. else
  677. begin
  678. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  679. e.ErrorCode:=GetLastError;
  680. CloseHandle(Proc);
  681. raise e;
  682. end;
  683. end;
  684. function ExecuteProcess(Const Path: AnsiString; Const ComLine: Array of AnsiString):integer;
  685. Var
  686. CommandLine : AnsiString;
  687. i : Integer;
  688. Begin
  689. Commandline:='';
  690. For i:=0 to high(ComLine) Do
  691. Commandline:=CommandLine+' '+Comline[i];
  692. ExecuteProcess:=ExecuteProcess(Path,CommandLine);
  693. End;
  694. Procedure Sleep(Milliseconds : Cardinal);
  695. begin
  696. Windows.Sleep(MilliSeconds)
  697. end;
  698. Function GetLastOSError : Integer;
  699. begin
  700. Result:=GetLastError;
  701. end;
  702. {****************************************************************************
  703. Initialization code
  704. ****************************************************************************}
  705. var
  706. kernel32dll : THandle;
  707. Procedure LoadVersionInfo;
  708. // and getfreespaceex
  709. Var
  710. versioninfo : TOSVERSIONINFO;
  711. i : Integer;
  712. begin
  713. kernel32dll:=0;
  714. GetDiskFreeSpaceEx:=nil;
  715. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  716. GetVersionEx(versioninfo);
  717. Win32Platform:=versionInfo.dwPlatformId;
  718. Win32MajorVersion:=versionInfo.dwMajorVersion;
  719. Win32MinorVersion:=versionInfo.dwMinorVersion;
  720. Win32BuildNumber:=versionInfo.dwBuildNumber;
  721. Move (versioninfo.szCSDVersion ,Win32CSDVersion[1],128);
  722. win32CSDVersion[0]:=chr(strlen(pchar(@versioninfo.szCSDVersion)));
  723. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  724. (versioninfo.dwBuildNUmber>=1000)) or
  725. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  726. begin
  727. kernel32dll:=LoadLibrary('kernel32');
  728. if kernel32dll<>0 then
  729. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  730. end;
  731. end;
  732. function FreeLibrary(hLibModule : THANDLE) : longbool;
  733. stdcall;external 'kernel32' name 'FreeLibrary';
  734. function GetVersionEx(var VersionInformation:TOSVERSIONINFO) : longbool;
  735. stdcall;external 'kernel32' name 'GetVersionExA';
  736. function LoadLibrary(lpLibFileName : pchar):THandle;
  737. stdcall;external 'kernel32' name 'LoadLibraryA';
  738. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  739. stdcall;external 'kernel32' name 'GetProcAddress';
  740. Const
  741. CSIDL_PROGRAMS = $0002; { %SYSTEMDRIVE%\Program Files }
  742. CSIDL_PERSONAL = $0005; { %USERPROFILE%\My Documents }
  743. CSIDL_FAVORITES = $0006; { %USERPROFILE%\Favorites }
  744. CSIDL_STARTUP = $0007; { %USERPROFILE%\Start menu\Programs\Startup }
  745. CSIDL_RECENT = $0008; { %USERPROFILE%\Recent }
  746. CSIDL_SENDTO = $0009; { %USERPROFILE%\Sendto }
  747. CSIDL_STARTMENU = $000B; { %USERPROFILE%\Start menu }
  748. CSIDL_MYMUSIC = $000D; { %USERPROFILE%\Documents\My Music }
  749. CSIDL_MYVIDEO = $000E; { %USERPROFILE%\Documents\My Videos }
  750. CSIDL_DESKTOPDIRECTORY = $0010; { %USERPROFILE%\Desktop }
  751. CSIDL_NETHOOD = $0013; { %USERPROFILE%\NetHood }
  752. CSIDL_TEMPLATES = $0015; { %USERPROFILE%\Templates }
  753. CSIDL_COMMON_STARTMENU = $0016; { %PROFILEPATH%\All users\Start menu }
  754. CSIDL_COMMON_PROGRAMS = $0017; { %PROFILEPATH%\All users\Start menu\Programs }
  755. CSIDL_COMMON_STARTUP = $0018; { %PROFILEPATH%\All users\Start menu\Programs\Startup }
  756. CSIDL_COMMON_DESKTOPDIRECTORY = $0019; { %PROFILEPATH%\All users\Desktop }
  757. CSIDL_APPDATA = $001A; { %USERPROFILE%\Application Data (roaming) }
  758. CSIDL_PRINTHOOD = $001B; { %USERPROFILE%\Printhood }
  759. CSIDL_LOCAL_APPDATA = $001C; { %USERPROFILE%\Local Settings\Application Data (non roaming) }
  760. CSIDL_COMMON_FAVORITES = $001F; { %PROFILEPATH%\All users\Favorites }
  761. CSIDL_INTERNET_CACHE = $0020; { %USERPROFILE%\Local Settings\Temporary Internet Files }
  762. CSIDL_COOKIES = $0021; { %USERPROFILE%\Cookies }
  763. CSIDL_HISTORY = $0022; { %USERPROFILE%\Local settings\History }
  764. CSIDL_COMMON_APPDATA = $0023; { %PROFILESPATH%\All Users\Application Data }
  765. CSIDL_WINDOWS = $0024; { %SYSTEMROOT% }
  766. CSIDL_SYSTEM = $0025; { %SYSTEMROOT%\SYSTEM32 (may be system on 95/98/ME) }
  767. CSIDL_PROGRAM_FILES = $0026; { %SYSTEMDRIVE%\Program Files }
  768. CSIDL_MYPICTURES = $0027; { %USERPROFILE%\My Documents\My Pictures }
  769. CSIDL_PROFILE = $0028; { %USERPROFILE% }
  770. CSIDL_PROGRAM_FILES_COMMON = $002B; { %SYSTEMDRIVE%\Program Files\Common }
  771. CSIDL_COMMON_TEMPLATES = $002D; { %PROFILEPATH%\All Users\Templates }
  772. CSIDL_COMMON_DOCUMENTS = $002E; { %PROFILEPATH%\All Users\Documents }
  773. CSIDL_COMMON_ADMINTOOLS = $002F; { %PROFILEPATH%\All Users\Start Menu\Programs\Administrative Tools }
  774. CSIDL_ADMINTOOLS = $0030; { %USERPROFILE%\Start Menu\Programs\Administrative Tools }
  775. CSIDL_COMMON_MUSIC = $0035; { %PROFILEPATH%\All Users\Documents\my music }
  776. CSIDL_COMMON_PICTURES = $0036; { %PROFILEPATH%\All Users\Documents\my pictures }
  777. CSIDL_COMMON_VIDEO = $0037; { %PROFILEPATH%\All Users\Documents\my videos }
  778. CSIDL_CDBURN_AREA = $003B; { %USERPROFILE%\Local Settings\Application Data\Microsoft\CD Burning }
  779. CSIDL_PROFILES = $003E; { %PROFILEPATH% }
  780. CSIDL_FLAG_CREATE = $8000; { (force creation of requested folder if it doesn't exist yet) }
  781. Type
  782. PFNSHGetFolderPath = Function(Ahwnd: HWND; Csidl: Integer; Token: THandle; Flags: DWord; Path: PChar): HRESULT; stdcall;
  783. var
  784. SHGetFolderPath : PFNSHGetFolderPath = Nil;
  785. CFGDLLHandle : THandle = 0;
  786. Procedure InitDLL;
  787. Var
  788. P : Pointer;
  789. begin
  790. CFGDLLHandle:=LoadLibrary('shell32.dll');
  791. if (CFGDLLHandle<>0) then
  792. begin
  793. P:=GetProcAddress(CFGDLLHandle,'SHGetFolderPathA');
  794. If (P=Nil) then
  795. begin
  796. FreeLibrary(CFGDLLHandle);
  797. CFGDllHandle:=0;
  798. end
  799. else
  800. SHGetFolderPath:=PFNSHGetFolderPath(P);
  801. end;
  802. If (P=Nil) then
  803. begin
  804. CFGDLLHandle:=LoadLibrary('shfolder.dll');
  805. if (CFGDLLHandle<>0) then
  806. begin
  807. P:=GetProcAddress(CFGDLLHandle,'SHGetFolderPathA');
  808. If (P=Nil) then
  809. begin
  810. FreeLibrary(CFGDLLHandle);
  811. CFGDllHandle:=0;
  812. end
  813. else
  814. ShGetFolderPath:=PFNSHGetFolderPath(P);
  815. end;
  816. end;
  817. If (@ShGetFolderPath=Nil) then
  818. Raise Exception.Create('Could not determine SHGetFolderPath Function');
  819. end;
  820. Function GetSpecialDir(ID : Integer) : String;
  821. Var
  822. APath : Array[0..MAX_PATH] of char;
  823. begin
  824. Result:='';
  825. if (CFGDLLHandle=0) then
  826. InitDLL;
  827. If (SHGetFolderPath<>Nil) then
  828. begin
  829. if SHGetFolderPath(0,ID or CSIDL_FLAG_CREATE,0,0,@APATH[0])=S_OK then
  830. Result:=IncludeTrailingPathDelimiter(StrPas(@APath[0]));
  831. end;
  832. end;
  833. Function GetAppConfigDir(Global : Boolean) : String;
  834. begin
  835. If Global then
  836. Result:=DGetAppConfigDir(Global) // or use windows dir ??
  837. else
  838. begin
  839. Result:=GetSpecialDir(CSIDL_LOCAL_APPDATA)+ApplicationName;
  840. If (Result='') then
  841. Result:=DGetAppConfigDir(Global);
  842. end;
  843. end;
  844. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  845. begin
  846. if Global then
  847. begin
  848. Result:=IncludeTrailingPathDelimiter(DGetAppConfigDir(Global));
  849. if SubDir then
  850. Result:=IncludeTrailingPathDelimiter(Result+'Config');
  851. Result:=Result+ApplicationName+ConfigExtension;
  852. end
  853. else
  854. begin
  855. Result:=IncludeTrailingPathDelimiter(GetAppConfigDir(False));
  856. if SubDir then
  857. Result:=Result+'Config\';
  858. Result:=Result+ApplicationName+ConfigExtension;
  859. end;
  860. end;
  861. Procedure InitSysConfigDir;
  862. begin
  863. SetLength(SysConfigDir, MAX_PATH);
  864. SetLength(SysConfigDir, GetWindowsDirectory(PChar(SysConfigDir), MAX_PATH));
  865. end;
  866. {****************************************************************************
  867. Target Dependent WideString stuff
  868. ****************************************************************************}
  869. function Win32CompareWideString(const s1, s2 : WideString) : PtrInt;
  870. begin
  871. SetLastError(0);
  872. Result:=CompareStringW(LOCALE_USER_DEFAULT,0,pwidechar(s1),
  873. length(s1),pwidechar(s2),length(s2))-2;
  874. if GetLastError<>0 then
  875. RaiseLastOSError;
  876. end;
  877. function Win32CompareTextWideString(const s1, s2 : WideString) : PtrInt;
  878. begin
  879. SetLastError(0);
  880. Result:=CompareStringW(LOCALE_USER_DEFAULT,NORM_IGNORECASE,pwidechar(s1),
  881. length(s1),pwidechar(s2),length(s2))-2;
  882. if GetLastError<>0 then
  883. RaiseLastOSError;
  884. end;
  885. function Win32AnsiUpperCase(const s: string): string;
  886. begin
  887. if length(s)>0 then
  888. begin
  889. result:=s;
  890. UniqueString(result);
  891. CharUpperBuff(pchar(result),length(result));
  892. end
  893. else
  894. result:='';
  895. end;
  896. function Win32AnsiLowerCase(const s: string): string;
  897. begin
  898. if length(s)>0 then
  899. begin
  900. result:=s;
  901. UniqueString(result);
  902. CharLowerBuff(pchar(result),length(result));
  903. end
  904. else
  905. result:='';
  906. end;
  907. function Win32AnsiCompareStr(const S1, S2: string): PtrInt;
  908. begin
  909. result:=CompareString(LOCALE_USER_DEFAULT,0,pchar(s1),length(s1),
  910. pchar(s2),length(s2))-2;
  911. end;
  912. function Win32AnsiCompareText(const S1, S2: string): PtrInt;
  913. begin
  914. result:=CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE,pchar(s1),length(s1),
  915. pchar(s2),length(s2))-2;
  916. end;
  917. function Win32AnsiStrComp(S1, S2: PChar): PtrInt;
  918. begin
  919. result:=CompareString(LOCALE_USER_DEFAULT,0,s1,-1,s2,-1)-2;
  920. end;
  921. function Win32AnsiStrIComp(S1, S2: PChar): PtrInt;
  922. begin
  923. result:=CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,-1,s2,-1)-2;
  924. end;
  925. function Win32AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  926. begin
  927. result:=CompareString(LOCALE_USER_DEFAULT,0,s1,maxlen,s2,maxlen)-2;
  928. end;
  929. function Win32AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  930. begin
  931. result:=CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,maxlen,s2,maxlen)-2;
  932. end;
  933. function Win32AnsiStrLower(Str: PChar): PChar;
  934. begin
  935. CharLower(str);
  936. result:=str;
  937. end;
  938. function Win32AnsiStrUpper(Str: PChar): PChar;
  939. begin
  940. CharUpper(str);
  941. result:=str;
  942. end;
  943. { there is a similiar procedure in the system unit which inits the fields which
  944. are relevant already for the system unit }
  945. procedure InitWin32Widestrings;
  946. begin
  947. widestringmanager.CompareWideStringProc:=@Win32CompareWideString;
  948. widestringmanager.CompareTextWideStringProc:=@Win32CompareTextWideString;
  949. widestringmanager.UpperAnsiStringProc:=@Win32AnsiUpperCase;
  950. widestringmanager.LowerAnsiStringProc:=@Win32AnsiLowerCase;
  951. widestringmanager.CompareStrAnsiStringProc:=@Win32AnsiCompareStr;
  952. widestringmanager.CompareTextAnsiStringProc:=@Win32AnsiCompareText;
  953. widestringmanager.StrCompAnsiStringProc:=@Win32AnsiStrComp;
  954. widestringmanager.StrICompAnsiStringProc:=@Win32AnsiStrIComp;
  955. widestringmanager.StrLCompAnsiStringProc:=@Win32AnsiStrLComp;
  956. widestringmanager.StrLICompAnsiStringProc:=@Win32AnsiStrLIComp;
  957. widestringmanager.StrLowerAnsiStringProc:=@Win32AnsiStrLower;
  958. widestringmanager.StrUpperAnsiStringProc:=@Win32AnsiStrUpper;
  959. end;
  960. Initialization
  961. InitWin32Widestrings;
  962. InitExceptions; { Initialize exceptions. OS independent }
  963. InitInternational; { Initialize internationalization settings }
  964. LoadVersionInfo;
  965. InitSysConfigDir;
  966. Finalization
  967. DoneExceptions;
  968. if kernel32dll<>0 then
  969. FreeLibrary(kernel32dll);
  970. if CFGDLLHandle<>0 then
  971. FreeLibrary(CFGDllHandle);
  972. end.