sysutils.pp 30 KB

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