mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 23:31:49 +02:00
871 lines
22 KiB
ObjectPascal
871 lines
22 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1999-2004 by the Free Pascal development team.
|
|
|
|
Dos unit for BP7 compatible RTL
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
{$IFNDEF FPC_DOTTEDUNITS}
|
|
unit dos;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
interface
|
|
|
|
Const
|
|
Max_Path = 260;
|
|
|
|
Type
|
|
PWinFileTime = ^TWinFileTime;
|
|
TWinFileTime = record
|
|
dwLowDateTime,
|
|
dwHighDateTime : DWORD;
|
|
end;
|
|
|
|
PWinFindData = ^TWinFindData;
|
|
TWinFindData = record
|
|
dwFileAttributes: DWORD;
|
|
ftCreationTime: TWinFileTime;
|
|
ftLastAccessTime: TWinFileTime;
|
|
ftLastWriteTime: TWinFileTime;
|
|
nFileSizeHigh: DWORD;
|
|
nFileSizeLow: DWORD;
|
|
dwReserved0: DWORD;
|
|
dwReserved1: DWORD;
|
|
cFileName: array[0..MAX_PATH-1] of AnsiChar;
|
|
cAlternateFileName: array[0..15] of AnsiChar;
|
|
// The structure should be 320 bytes long...
|
|
pad : system.integer;
|
|
end;
|
|
|
|
Searchrec = Record
|
|
FindHandle : THandle;
|
|
WinFindData : TWinFindData;
|
|
ExcludeAttr : longint;
|
|
time : longint;
|
|
size : longint;
|
|
attr : longint;
|
|
name : string;
|
|
end;
|
|
|
|
{$i dosh.inc}
|
|
|
|
Const
|
|
{ allow EXEC to inherited handles from calling process,
|
|
needed for FPREDIR in ide/text
|
|
now set to true by default because
|
|
other OS also pass open handles to childs
|
|
finally reset to false after Florian's response PM }
|
|
ExecInheritsHandles : Longbool = false;
|
|
|
|
|
|
implementation
|
|
|
|
{$IFDEF FPC_DOTTEDUNITS}
|
|
uses
|
|
System.Strings;
|
|
{$ELSE FPC_DOTTEDUNITS}
|
|
uses
|
|
strings;
|
|
{$ENDIF FPC_DOTTEDUNITS}
|
|
|
|
{$DEFINE HAS_GETMSCOUNT}
|
|
{$DEFINE HAS_GETSHORTNAME}
|
|
{$DEFINE HAS_GETLONGNAME}
|
|
|
|
{$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
|
|
{$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
|
|
|
|
{$I dos.inc}
|
|
|
|
const
|
|
INVALID_HANDLE_VALUE = THandle(-1);
|
|
|
|
VER_PLATFORM_WIN32s = 0;
|
|
VER_PLATFORM_WIN32_WINDOWS = 1;
|
|
VER_PLATFORM_WIN32_NT = 2;
|
|
|
|
type
|
|
OSVERSIONINFO = record
|
|
dwOSVersionInfoSize : DWORD;
|
|
dwMajorVersion : DWORD;
|
|
dwMinorVersion : DWORD;
|
|
dwBuildNumber : DWORD;
|
|
dwPlatformId : DWORD;
|
|
szCSDVersion : array[0..127] of AnsiChar;
|
|
end;
|
|
|
|
var
|
|
kernel32dll : THandle;
|
|
|
|
{******************************************************************************
|
|
--- Conversion ---
|
|
******************************************************************************}
|
|
|
|
function GetLastError : DWORD;
|
|
stdcall; external 'kernel32' name 'GetLastError';
|
|
function FileTimeToDosDateTime(const ft :TWinFileTime;var data,time : word) : longbool;
|
|
stdcall; external 'kernel32' name 'FileTimeToDosDateTime';
|
|
function DosDateTimeToFileTime(date,time : word;var ft :TWinFileTime) : longbool;
|
|
stdcall; external 'kernel32' name 'DosDateTimeToFileTime';
|
|
function FileTimeToLocalFileTime(const ft : TWinFileTime;var lft : TWinFileTime) : longbool;
|
|
stdcall; external 'kernel32' name 'FileTimeToLocalFileTime';
|
|
function LocalFileTimeToFileTime(const lft : TWinFileTime;var ft : TWinFileTime) : longbool;
|
|
stdcall; external 'kernel32' name 'LocalFileTimeToFileTime';
|
|
function GetTickCount : longint;
|
|
stdcall;external 'kernel32' name 'GetTickCount';
|
|
|
|
function GetMsCount: int64;
|
|
begin
|
|
GetMsCount := cardinal (GetTickCount);
|
|
end;
|
|
|
|
type
|
|
Longrec=packed record
|
|
lo,hi : word;
|
|
end;
|
|
|
|
function Last2DosError(d:dword):integer;
|
|
begin
|
|
case d of
|
|
87 : { Parameter invalid -> Data invalid }
|
|
Last2DosError:=13;
|
|
else
|
|
Last2DosError:=d;
|
|
end;
|
|
end;
|
|
|
|
|
|
Function DosToWinAttr (Const Attr : Longint) : longint;
|
|
begin
|
|
DosToWinAttr:=Attr;
|
|
end;
|
|
|
|
|
|
Function WinToDosAttr (Const Attr : Longint) : longint;
|
|
begin
|
|
WinToDosAttr:=Attr;
|
|
end;
|
|
|
|
|
|
Function DosToWinTime (DTime:longint;Var Wtime : TWinFileTime):longbool;
|
|
var
|
|
lft : TWinFileTime;
|
|
begin
|
|
DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,lft) and
|
|
LocalFileTimeToFileTime(lft,Wtime);
|
|
end;
|
|
|
|
|
|
Function WinToDosTime (Const Wtime : TWinFileTime;var DTime:longint):longbool;
|
|
var
|
|
lft : TWinFileTime;
|
|
begin
|
|
WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
|
|
FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Info / Date / Time ---
|
|
******************************************************************************}
|
|
|
|
type
|
|
TSystemTime = record
|
|
wYear,
|
|
wMonth,
|
|
wDayOfWeek,
|
|
wDay,
|
|
wHour,
|
|
wMinute,
|
|
wSecond,
|
|
wMilliseconds: Word;
|
|
end;
|
|
|
|
function GetVersion : longint;
|
|
stdcall; external 'kernel32' name 'GetVersion';
|
|
procedure GetLocalTime(var t : TSystemTime);
|
|
stdcall; external 'kernel32' name 'GetLocalTime';
|
|
function SetLocalTime(const t : TSystemTime) : longbool;
|
|
stdcall; external 'kernel32' name 'SetLocalTime';
|
|
|
|
function dosversion : word;
|
|
begin
|
|
dosversion:=GetVersion and $ffff;
|
|
end;
|
|
|
|
|
|
procedure getdate(var year,month,mday,wday : word);
|
|
var
|
|
t : TSystemTime;
|
|
begin
|
|
GetLocalTime(t);
|
|
year:=t.wYear;
|
|
month:=t.wMonth;
|
|
mday:=t.wDay;
|
|
wday:=t.wDayOfWeek;
|
|
end;
|
|
|
|
|
|
procedure setdate(year,month,day : word);
|
|
var
|
|
t : TSystemTime;
|
|
begin
|
|
{ we need the time set privilege }
|
|
{ so this function crash currently }
|
|
{!!!!!}
|
|
GetLocalTime(t);
|
|
t.wYear:=year;
|
|
t.wMonth:=month;
|
|
t.wDay:=day;
|
|
{ only a quite good solution, we can loose some ms }
|
|
SetLocalTime(t);
|
|
end;
|
|
|
|
|
|
procedure gettime(var hour,minute,second,sec100 : word);
|
|
var
|
|
t : TSystemTime;
|
|
begin
|
|
GetLocalTime(t);
|
|
hour:=t.wHour;
|
|
minute:=t.wMinute;
|
|
second:=t.wSecond;
|
|
sec100:=t.wMilliSeconds div 10;
|
|
end;
|
|
|
|
|
|
procedure settime(hour,minute,second,sec100 : word);
|
|
var
|
|
t : TSystemTime;
|
|
begin
|
|
{ we need the time set privilege }
|
|
{ so this function crash currently }
|
|
{!!!!!}
|
|
GetLocalTime(t);
|
|
t.wHour:=hour;
|
|
t.wMinute:=minute;
|
|
t.wSecond:=second;
|
|
t.wMilliSeconds:=sec100*10;
|
|
SetLocalTime(t);
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Exec ---
|
|
******************************************************************************}
|
|
|
|
type
|
|
PProcessInformation = ^TProcessInformation;
|
|
TProcessInformation = record
|
|
hProcess: THandle;
|
|
hThread: THandle;
|
|
dwProcessId: DWORD;
|
|
dwThreadId: DWORD;
|
|
end;
|
|
|
|
function CreateProcess(lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar;
|
|
lpProcessAttributes, lpThreadAttributes: Pointer;
|
|
bInheritHandles: Longbool; dwCreationFlags: DWORD; lpEnvironment: Pointer;
|
|
lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfo;
|
|
var lpProcessInformation: TProcessInformation): longbool;
|
|
stdcall; external 'kernel32' name 'CreateProcessA';
|
|
function getExitCodeProcess(h:THandle;var code:longint):longbool;
|
|
stdcall; external 'kernel32' name 'GetExitCodeProcess';
|
|
function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
|
|
stdcall; external 'kernel32' name 'WaitForSingleObject';
|
|
function CloseHandle(h : THandle) : longint;
|
|
stdcall; external 'kernel32' name 'CloseHandle';
|
|
|
|
procedure exec(const path : pathstr;const comline : comstr);
|
|
var
|
|
SI: TStartupInfo;
|
|
PI: TProcessInformation;
|
|
l : Longint;
|
|
{ Maximum length of both short string is
|
|
2x255 = 510, plus possibly two double-quotes,
|
|
two spaces and the final #0, makes 515 chars }
|
|
CommandLine : array[0..515] of AnsiChar;
|
|
has_no_double_quote : boolean;
|
|
begin
|
|
DosError:=0;
|
|
FillChar(SI, SizeOf(SI), 0);
|
|
SI.cb:=SizeOf(SI);
|
|
SI.wShowWindow:=1;
|
|
{ always surround the name of the application by quotes
|
|
so that long filenames will always be accepted. But don't
|
|
do it if there are already double quotes, since Win32 does not
|
|
like double quotes which are duplicated!
|
|
}
|
|
has_no_double_quote:=pos('"',path)=0;
|
|
if has_no_double_quote then
|
|
begin
|
|
CommandLine[0]:='"';
|
|
l:=1;
|
|
end
|
|
else
|
|
l:=0;
|
|
Move(Path[1],CommandLine[l],length(Path));
|
|
l:=l+length(Path);
|
|
if has_no_double_quote then
|
|
begin
|
|
CommandLine[l]:='"';
|
|
inc(l);
|
|
end;
|
|
{ Add two spaces }
|
|
CommandLine[l]:=' ';
|
|
inc(l);
|
|
CommandLine[l]:=' ';
|
|
inc(l);
|
|
{ Add comline string }
|
|
Move(ComLine[1],CommandLine[l],length(Comline));
|
|
l:=l+length(ComLine);
|
|
{ Terminate string }
|
|
CommandLine[l]:=#0;
|
|
if not CreateProcess(nil, PAnsiChar(@CommandLine),
|
|
Nil, Nil, ExecInheritsHandles,$20, Nil, Nil, SI, PI) then
|
|
begin
|
|
DosError:=Last2DosError(GetLastError);
|
|
exit;
|
|
end;
|
|
if WaitForSingleObject(PI.hProcess,dword($ffffffff))<>$ffffffff then
|
|
GetExitCodeProcess(PI.hProcess,l)
|
|
else
|
|
l:=-1;
|
|
CloseHandle(PI.hProcess);
|
|
CloseHandle(PI.hThread);
|
|
LastDosExitCode:=l;
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Disk ---
|
|
******************************************************************************}
|
|
|
|
function GetDiskFreeSpace(drive:PAnsiChar;var sector_cluster,bytes_sector,
|
|
freeclusters,totalclusters:DWORD):longbool;
|
|
stdcall; external 'kernel32' name 'GetDiskFreeSpaceA';
|
|
type
|
|
TGetDiskFreeSpaceEx = function(drive:PAnsiChar;var availableforcaller,
|
|
total,free):longbool;stdcall;
|
|
|
|
var
|
|
GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
|
|
|
|
function diskfree(drive : byte) : int64;
|
|
var
|
|
disk : array[1..4] of AnsiChar;
|
|
secs,bytes,
|
|
free,total : DWORD;
|
|
qwtotal,qwfree,qwcaller : int64;
|
|
|
|
|
|
begin
|
|
if drive=0 then
|
|
begin
|
|
disk[1]:='\';
|
|
disk[2]:=#0;
|
|
end
|
|
else
|
|
begin
|
|
disk[1]:=chr(drive+64);
|
|
disk[2]:=':';
|
|
disk[3]:='\';
|
|
disk[4]:=#0;
|
|
end;
|
|
if assigned(GetDiskFreeSpaceEx) then
|
|
begin
|
|
if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
|
|
diskfree:=qwfree
|
|
else
|
|
diskfree:=-1;
|
|
end
|
|
else
|
|
begin
|
|
if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
|
|
diskfree:=int64(free)*secs*bytes
|
|
else
|
|
diskfree:=-1;
|
|
end;
|
|
end;
|
|
|
|
|
|
function disksize(drive : byte) : int64;
|
|
var
|
|
disk : array[1..4] of AnsiChar;
|
|
secs,bytes,
|
|
free,total : DWORD;
|
|
qwtotal,qwfree,qwcaller : int64;
|
|
|
|
begin
|
|
if drive=0 then
|
|
begin
|
|
disk[1]:='\';
|
|
disk[2]:=#0;
|
|
end
|
|
else
|
|
begin
|
|
disk[1]:=chr(drive+64);
|
|
disk[2]:=':';
|
|
disk[3]:='\';
|
|
disk[4]:=#0;
|
|
end;
|
|
if assigned(GetDiskFreeSpaceEx) then
|
|
begin
|
|
if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
|
|
disksize:=qwtotal
|
|
else
|
|
disksize:=-1;
|
|
end
|
|
else
|
|
begin
|
|
if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
|
|
disksize:=int64(total)*secs*bytes
|
|
else
|
|
disksize:=-1;
|
|
end;
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- Findfirst FindNext ---
|
|
******************************************************************************}
|
|
|
|
{ Needed kernel calls }
|
|
|
|
function FindFirstFile (lpFileName: PAnsiChar; var lpFindFileData: TWinFindData): THandle;
|
|
stdcall; external 'kernel32' name 'FindFirstFileA';
|
|
function FindNextFile (hFindFile: THandle; var lpFindFileData: TWinFindData): LongBool;
|
|
stdcall; external 'kernel32' name 'FindNextFileA';
|
|
function FindCloseFile (hFindFile: THandle): LongBool;
|
|
stdcall; external 'kernel32' name 'FindClose';
|
|
|
|
Procedure StringToPchar (Var S : ShortString);
|
|
Var L : Longint;
|
|
begin
|
|
L:=ord(S[0]);
|
|
Move (S[1],S[0],L);
|
|
S[L]:=#0;
|
|
end;
|
|
|
|
Procedure PCharToString (Var S : ShortString);
|
|
Var L : Longint;
|
|
begin
|
|
L:=strlen(PAnsiChar(@S[0]));
|
|
Move (S[0],S[1],L);
|
|
S[0]:=AnsiChar(l);
|
|
end;
|
|
|
|
|
|
procedure FindMatch(var f:searchrec);
|
|
begin
|
|
{ Find file with correct attribute }
|
|
While (F.WinFindData.dwFileAttributes and DWORD(F.ExcludeAttr))<>0 do
|
|
begin
|
|
if not FindNextFile (F.FindHandle,F.WinFindData) then
|
|
begin
|
|
DosError:=Last2DosError(GetLastError);
|
|
if DosError=2 then
|
|
DosError:=18;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
{ Convert some attributes back }
|
|
f.size:=F.WinFindData.NFileSizeLow;
|
|
f.attr:=WinToDosAttr(F.WinFindData.dwFileAttributes);
|
|
WinToDosTime(F.WinFindData.ftLastWriteTime,f.Time);
|
|
f.Name:=StrPas(@F.WinFindData.cFileName);
|
|
end;
|
|
|
|
|
|
procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
|
|
|
|
var
|
|
S : ShortString;
|
|
|
|
begin
|
|
fillchar(f,sizeof(f),0);
|
|
{ no error }
|
|
doserror:=0;
|
|
F.Name:=Path;
|
|
F.Attr:=attr;
|
|
F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
|
|
S:=f.name;
|
|
StringToPchar(S);
|
|
|
|
{ FindFirstFile is a Win32 Call }
|
|
F.WinFindData.dwFileAttributes:=DosToWinAttr(f.attr);
|
|
F.FindHandle:=FindFirstFile (PAnsiChar(@S),F.WinFindData);
|
|
|
|
If F.FindHandle=Invalid_Handle_value then
|
|
begin
|
|
DosError:=Last2DosError(GetLastError);
|
|
if DosError=2 then
|
|
DosError:=18;
|
|
exit;
|
|
end;
|
|
{ Find file with correct attribute }
|
|
FindMatch(f);
|
|
end;
|
|
|
|
|
|
procedure findnext(var f : searchRec);
|
|
begin
|
|
{ no error }
|
|
doserror:=0;
|
|
if not FindNextFile (F.FindHandle,F.WinFindData) then
|
|
begin
|
|
DosError:=Last2DosError(GetLastError);
|
|
if DosError=2 then
|
|
DosError:=18;
|
|
exit;
|
|
end;
|
|
{ Find file with correct attribute }
|
|
FindMatch(f);
|
|
end;
|
|
|
|
|
|
Procedure FindClose(Var f: SearchRec);
|
|
begin
|
|
If F.FindHandle<>Invalid_Handle_value then
|
|
FindCloseFile(F.FindHandle);
|
|
end;
|
|
|
|
|
|
{******************************************************************************
|
|
--- File ---
|
|
******************************************************************************}
|
|
|
|
function GetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
|
|
stdcall; external 'kernel32' name 'GetFileTime';
|
|
function SetWinFileTime(h : longint;creation,lastaccess,lastwrite : PWinFileTime) : longbool;
|
|
stdcall; external 'kernel32' name 'SetFileTime';
|
|
function SetFileAttributes(lpFileName : PAnsiChar;dwFileAttributes : longint) : longbool;
|
|
stdcall; external 'kernel32' name 'SetFileAttributesA';
|
|
function GetFileAttributes(lpFileName : PAnsiChar) : longint;
|
|
stdcall; external 'kernel32' name 'GetFileAttributesA';
|
|
|
|
|
|
{ <immobilizer> }
|
|
|
|
function GetFullPathName(lpFileName: PAnsiChar; nBufferLength: Longint; lpBuffer: PAnsiChar; var lpFilePart : PAnsiChar):DWORD;
|
|
stdcall; external 'kernel32' name 'GetFullPathNameA';
|
|
function GetShortPathName(lpszLongPath:PAnsiChar; lpszShortPath:PAnsiChar; cchBuffer:DWORD):DWORD;
|
|
stdcall; external 'kernel32' name 'GetShortPathNameA';
|
|
|
|
|
|
Function FSearch(path: pathstr; dirlist: shortstring): pathstr;
|
|
var
|
|
p1 : longint;
|
|
s : searchrec;
|
|
newdir : pathstr;
|
|
begin
|
|
{ No wildcards allowed in these things }
|
|
if (pos('?',path)<>0) or (pos('*',path)<>0) then
|
|
begin
|
|
fsearch:='';
|
|
exit;
|
|
end;
|
|
{ check if the file specified exists }
|
|
findfirst(path,anyfile and not(directory),s);
|
|
if doserror=0 then
|
|
begin
|
|
findclose(s);
|
|
fsearch:=path;
|
|
exit;
|
|
end;
|
|
findclose(s);
|
|
{ allow slash as backslash }
|
|
DoDirSeparators(dirlist);
|
|
repeat
|
|
p1:=pos(';',dirlist);
|
|
if p1<>0 then
|
|
begin
|
|
newdir:=copy(dirlist,1,p1-1);
|
|
delete(dirlist,1,p1);
|
|
end
|
|
else
|
|
begin
|
|
newdir:=dirlist;
|
|
dirlist:='';
|
|
end;
|
|
if (newdir<>'') and (not (newdir[length(newdir)] in [DirectorySeparator,DriveSeparator])) then
|
|
newdir:=newdir+DirectorySeparator;
|
|
findfirst(newdir+path,anyfile and not(directory),s);
|
|
if doserror=0 then
|
|
newdir:=newdir+path
|
|
else
|
|
newdir:='';
|
|
findclose(s);
|
|
until (dirlist='') or (newdir<>'');
|
|
fsearch:=newdir;
|
|
end;
|
|
|
|
|
|
procedure getftime(var f;var time : longint);
|
|
var
|
|
ft : TWinFileTime;
|
|
begin
|
|
doserror:=0;
|
|
if GetWinFileTime(filerec(f).Handle,nil,nil,@ft) and
|
|
WinToDosTime(ft,time) then
|
|
exit
|
|
else
|
|
begin
|
|
DosError:=Last2DosError(GetLastError);
|
|
time:=0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure setftime(var f;time : longint);
|
|
var
|
|
ft : TWinFileTime;
|
|
begin
|
|
doserror:=0;
|
|
if DosToWinTime(time,ft) and
|
|
SetWinFileTime(filerec(f).Handle,nil,nil,@ft) then
|
|
exit
|
|
else
|
|
DosError:=Last2DosError(GetLastError);
|
|
end;
|
|
|
|
|
|
procedure getfattr(var f;var attr : word);
|
|
var
|
|
l : longint;
|
|
s : RawByteString;
|
|
begin
|
|
doserror:=0;
|
|
s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
|
|
l:=GetFileAttributes(PAnsiChar(s));
|
|
if l=longint($ffffffff) then
|
|
begin
|
|
doserror:=getlasterror;
|
|
attr:=0;
|
|
end
|
|
else
|
|
attr:=l and $ffff;
|
|
end;
|
|
|
|
|
|
procedure setfattr(var f;attr : word);
|
|
var s : RawByteString;
|
|
begin
|
|
{ Fail for setting VolumeId }
|
|
if (attr and VolumeID)<>0 then
|
|
doserror:=5
|
|
else
|
|
begin
|
|
s:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
|
|
if SetFileAttributes(PAnsiChar(s),attr) then
|
|
doserror:=0
|
|
else
|
|
doserror:=getlasterror;
|
|
end;
|
|
end;
|
|
|
|
{ change to short filename if successful win32 call PM }
|
|
function GetShortName(var p : shortString) : boolean;
|
|
var
|
|
buffer : array[0..255] of AnsiChar;
|
|
ret : longint;
|
|
begin
|
|
{we can't mess with p, because we have to return it if call is
|
|
unsuccesfully.}
|
|
|
|
if Length(p)>0 then {copy p to array of AnsiChar}
|
|
move(p[1],buffer[0],length(p));
|
|
buffer[length(p)]:=chr(0);
|
|
|
|
{Should return value load loaddoserror?}
|
|
|
|
ret:=GetShortPathName(@buffer,@buffer,255);
|
|
if (Ret > 0) and (Ret <= 255) then
|
|
begin
|
|
Move (Buffer, P [1], Ret);
|
|
byte (P [0]) := Ret;
|
|
GetShortName := true;
|
|
end
|
|
else
|
|
GetShortName := false;
|
|
end;
|
|
|
|
{ change to long filename if successful DOS call PM }
|
|
function GetLongName(var p : shortString) : boolean;
|
|
|
|
var
|
|
SR: SearchRec;
|
|
FullFN, FinalFN, TestFN: shortstring;
|
|
Found: boolean;
|
|
SPos: byte;
|
|
begin
|
|
if Length (P) = 0 then
|
|
GetLongName := false
|
|
else
|
|
begin
|
|
FullFN := FExpand (P); (* Needed to be done at the beginning to get proper case for all parts *)
|
|
SPos := 1;
|
|
if (Length (FullFN) > 2) then
|
|
if (FullFN [2] = DriveSeparator) then
|
|
SPos := 4
|
|
else
|
|
if (FullFN [1] = DirectorySeparator) and (FullFN [2] = DirectorySeparator) then
|
|
begin
|
|
SPos := 3;
|
|
while (Length (FullFN) > SPos) and (FullFN [SPos] <> DirectorySeparator) do
|
|
Inc (SPos);
|
|
if SPos >= Length (FullFN) then
|
|
SPos := 1
|
|
else
|
|
begin
|
|
Inc (SPos);
|
|
while (Length (FullFN) >= SPos) and (FullFN [SPos] <> DirectorySeparator) do
|
|
Inc (SPos);
|
|
if SPos <= Length (FullFN) then
|
|
Inc (SPos);
|
|
end;
|
|
end;
|
|
FinalFN := Copy (FullFN, 1, Pred (SPos));
|
|
Delete (FullFN, 1, Pred (SPos));
|
|
Found := true;
|
|
while (FullFN <> '') and Found do
|
|
begin
|
|
SPos := Pos (DirectorySeparator, FullFN);
|
|
TestFN := Copy (FullFN, 1, Pred (SPos));
|
|
Delete (FullFN, 1, Pred (SPos));
|
|
FindFirst (FinalFN + TestFN, AnyFile, SR);
|
|
if DosError <> 0 then
|
|
Found := false
|
|
else
|
|
begin
|
|
FinalFN := FinalFN + SR.Name;
|
|
if (FullFN <> '') and (FullFN [1] = DirectorySeparator) then
|
|
begin
|
|
FinalFN := FinalFN + DirectorySeparator;
|
|
Delete (FullFN, 1, 1);
|
|
end;
|
|
end;
|
|
FindClose (SR);
|
|
end;
|
|
if Found then
|
|
begin
|
|
GetLongName := true;
|
|
P := FinalFN;
|
|
end
|
|
else
|
|
GetLongName := false
|
|
end;
|
|
end;
|
|
|
|
{******************************************************************************
|
|
--- Environment ---
|
|
******************************************************************************}
|
|
|
|
{
|
|
The environment is a block of zero terminated strings
|
|
terminated by a #0
|
|
}
|
|
|
|
function GetEnvironmentStrings : PAnsiChar;
|
|
stdcall; external 'kernel32' name 'GetEnvironmentStringsA';
|
|
function FreeEnvironmentStrings(p : PAnsiChar) : longbool;
|
|
stdcall; external 'kernel32' name 'FreeEnvironmentStringsA';
|
|
|
|
{$push}
|
|
{ GetEnvironmentStrings cannot be checked by CheckPointer function }
|
|
{$checkpointer off}
|
|
|
|
function envcount : longint;
|
|
var
|
|
hp,p : PAnsiChar;
|
|
count : longint;
|
|
begin
|
|
p:=GetEnvironmentStrings;
|
|
hp:=p;
|
|
count:=0;
|
|
while hp^<>#0 do
|
|
begin
|
|
{ next string entry}
|
|
hp:=hp+strlen(hp)+1;
|
|
inc(count);
|
|
end;
|
|
FreeEnvironmentStrings(p);
|
|
envcount:=count;
|
|
end;
|
|
|
|
|
|
Function EnvStr (Index: longint): shortstring;
|
|
var
|
|
hp,p : PAnsiChar;
|
|
count,i : longint;
|
|
begin
|
|
{ envcount takes some time in win32 }
|
|
count:=envcount;
|
|
|
|
{ range checking }
|
|
if (index<=0) or (index>count) then
|
|
begin
|
|
envstr:='';
|
|
exit;
|
|
end;
|
|
p:=GetEnvironmentStrings;
|
|
hp:=p;
|
|
|
|
{ retrive the string with the given index }
|
|
for i:=2 to index do
|
|
hp:=hp+strlen(hp)+1;
|
|
|
|
envstr:=strpas(hp);
|
|
FreeEnvironmentStrings(p);
|
|
end;
|
|
|
|
|
|
Function GetEnv(envvar: shortstring): shortstring;
|
|
var
|
|
s : shortstring;
|
|
i : longint;
|
|
hp,p : PAnsiChar;
|
|
begin
|
|
getenv:='';
|
|
p:=GetEnvironmentStrings;
|
|
hp:=p;
|
|
while hp^<>#0 do
|
|
begin
|
|
s:=strpas(hp);
|
|
i:=pos('=',s);
|
|
if upcase(copy(s,1,i-1))=upcase(envvar) then
|
|
begin
|
|
{ getenv:=copy(s,i+1,length(s)-i);
|
|
this limits the size to 255-(i+1) }
|
|
getenv:=strpas(hp+i);
|
|
break;
|
|
end;
|
|
{ next string entry}
|
|
hp:=hp+strlen(hp)+1;
|
|
end;
|
|
FreeEnvironmentStrings(p);
|
|
end;
|
|
{$pop}
|
|
|
|
function GetModuleHandle(p : PAnsiChar) : PtrUInt;
|
|
stdcall; external 'kernel32' name 'GetModuleHandleA';
|
|
function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
|
|
stdcall; external 'kernel32' name 'GetVersionExA';
|
|
function GetProcAddress(hModule : THandle;lpProcName : PAnsiChar) : pointer;
|
|
stdcall; external 'kernel32' name 'GetProcAddress';
|
|
|
|
|
|
begin
|
|
GetDiskFreeSpaceEx:=nil;
|
|
kernel32dll:=GetModuleHandle('kernel32');
|
|
if kernel32dll<>0 then
|
|
GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
|
|
end.
|