diff options
Diffstat (limited to 'rtl/os2/sysutils.pp')
-rw-r--r-- | rtl/os2/sysutils.pp | 400 |
1 files changed, 277 insertions, 123 deletions
diff --git a/rtl/os2/sysutils.pp b/rtl/os2/sysutils.pp index 20bb39b516..80a94a4119 100644 --- a/rtl/os2/sysutils.pp +++ b/rtl/os2/sysutils.pp @@ -23,6 +23,7 @@ interface {$H+} {$DEFINE HAS_SLEEP} +{$DEFINE HAS_OSERROR} { used OS file system APIs use ansistring } {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL} @@ -43,6 +44,9 @@ type (* Necessary here due to a different definition of TDateTime in DosCalls. *) TDateTime = System.TDateTime; +threadvar + LastOSError: cardinal; + {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *) {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *) {$DEFINE FPC_FEXPAND_GETENV_PCHAR} @@ -83,8 +87,11 @@ begin If Rc=0 then FileOpen:=Handle else + begin FileOpen:=feInvalidHandle; //FileOpen:=-RC; //should return feInvalidHandle(=-1) if fail, other negative returned value are no more errors + OSErrorWatch (RC); + end; end; function FileCreate (const FileName: RawByteString): THandle; @@ -115,56 +122,84 @@ begin if RC = 0 then FileCreate := Handle else - FileCreate := feInvalidHandle; + begin + FileCreate := feInvalidHandle; + OSErrorWatch (RC); + end; End; function FileRead (Handle: THandle; Out Buffer; Count: longint): longint; Var T: cardinal; + RC: cardinal; begin - DosRead(Handle, Buffer, Count, T); + RC := DosRead (Handle, Buffer, Count, T); FileRead := longint (T); + if RC <> 0 then + OSErrorWatch (RC); end; function FileWrite (Handle: THandle; const Buffer; Count: longint): longint; Var T: cardinal; + RC: cardinal; begin - DosWrite (Handle, Buffer, Count, T); + RC := DosWrite (Handle, Buffer, Count, T); FileWrite := longint (T); + if RC <> 0 then + OSErrorWatch (RC); end; function FileSeek (Handle: THandle; FOffset, Origin: longint): longint; var NPos: int64; + RC: cardinal; begin - if (Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0) - and (NPos < high (longint)) then + RC := Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos); + if (RC = 0) and (NPos < high (longint)) then FileSeek:= longint (NPos) else + begin FileSeek:=-1; + OSErrorWatch (RC); + end; end; function FileSeek (Handle: THandle; FOffset: Int64; Origin: Longint): Int64; var NPos: int64; + RC: cardinal; begin - if Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos) = 0 then + RC := Sys_DosSetFilePtrL (Handle, FOffset, Origin, NPos); + if RC = 0 then FileSeek:= NPos else + begin FileSeek:=-1; + OSErrorWatch (RC); + end; end; procedure FileClose (Handle: THandle); +var + RC: cardinal; begin - DosClose(Handle); + RC := DosClose (Handle); + if RC <> 0 then + OSErrorWatch (RC); end; function FileTruncate (Handle: THandle; Size: Int64): boolean; +var + RC: cardinal; begin - FileTruncate:=Sys_DosSetFileSizeL(Handle, Size)=0; - FileSeek(Handle, 0, 2); + RC := Sys_DosSetFileSizeL(Handle, Size); + FileTruncate := RC = 0; + if RC = 0 then + FileSeek(Handle, 0, 2) + else + OSErrorWatch (RC); end; function FileAge (const FileName: RawByteString): longint; @@ -222,7 +257,9 @@ begin else Err := DosFindFirst (PChar (SystemEncodedPath), Rslt.FindHandle, Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard); - if (Err = 0) and (Count = 0) then + if Err <> 0 then + OSErrorWatch (Err) + else if Count = 0 then Err := 18; InternalFindFirst := -Err; if Err = 0 then @@ -261,7 +298,9 @@ begin New (FStat); Count := 1; Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count); - if (Err = 0) and (Count = 0) then + if Err <> 0 then + OSErrorWatch (Err) + else if Count = 0 then Err := 18; InternalFindNext := -Err; if Err = 0 then @@ -290,9 +329,12 @@ end; Procedure InternalFindClose(var Handle: THandle); var SR: PSearchRec; + RC: cardinal; begin - DosFindClose (Handle); + RC := DosFindClose (Handle); Handle := 0; + if RC <> 0 then + OSErrorWatch (RC); end; function FileGetDate (Handle: THandle): longint; @@ -308,7 +350,10 @@ begin if Time = 0 then Time := FStat.TimeCreation + longint (FStat.DateCreation) shl 16; end else + begin Time:=0; + OSErrorWatch (RC); + end; FileGetDate:=Time; end; @@ -320,19 +365,25 @@ begin New (FStat); RC := DosQueryFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^)); if RC <> 0 then - FileSetDate := -1 + begin + FileSetDate := -1; + OSErrorWatch (RC); + end else - begin + begin FStat^.DateLastAccess := Hi (Age); FStat^.DateLastWrite := Hi (Age); FStat^.TimeLastAccess := Lo (Age); FStat^.TimeLastWrite := Lo (Age); RC := DosSetFileInfo (Handle, ilStandard, FStat, SizeOf (FStat^)); if RC <> 0 then - FileSetDate := -1 + begin + FileSetDate := -1; + OSErrorWatch (RC); + end else - FileSetDate := 0; - end; + FileSetDate := 0; + end; Dispose (FStat); end; @@ -340,11 +391,18 @@ function FileGetAttr (const FileName: RawByteString): longint; var FS: PFileStatus3; SystemFileName: RawByteString; + RC: cardinal; begin SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename); New(FS); - Result:=-DosQueryPathInfo(PChar (SystemFileName), ilStandard, FS, SizeOf(FS^)); - If Result=0 Then Result:=FS^.attrFile; + RC := DosQueryPathInfo(PChar (SystemFileName), ilStandard, FS, SizeOf(FS^)); + if RC = 0 then + Result := FS^.AttrFile + else + begin + Result := - longint (RC); + OSErrorWatch (RC); + end; Dispose(FS); end; @@ -352,12 +410,16 @@ function FileSetAttr (const Filename: RawByteString; Attr: longint): longint; Var FS: PFileStatus3; SystemFileName: RawByteString; + RC: cardinal; Begin SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename); New(FS); FillChar(FS, SizeOf(FS^), 0); FS^.AttrFile:=Attr; - Result:=-DosSetPathInfo(PChar (SystemFileName), ilStandard, FS, SizeOf(FS^), 0); + RC := DosSetPathInfo(PChar (SystemFileName), ilStandard, FS, SizeOf(FS^), 0); + if RC <> 0 then + OSErrorWatch (RC); + Result := - longint (RC); Dispose(FS); end; @@ -365,18 +427,34 @@ end; function DeleteFile (const FileName: RawByteString): boolean; var SystemFileName: RawByteString; + RC: cardinal; Begin SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename); - Result:=(DosDelete(PChar (SystemFileName))=0); + RC := DosDelete (PChar (SystemFileName)); + if RC <> 0 then + begin + Result := false; + OSErrorWatch (RC); + end + else + Result := true; End; function RenameFile (const OldName, NewName: RawByteString): boolean; var OldSystemFileName, NewSystemFileName: RawByteString; + RC: cardinal; Begin OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName); NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName); - Result:=(DosMove(PChar (OldSystemFileName), PChar (NewSystemFileName))=0); + RC := DosMove (PChar (OldSystemFileName), PChar (NewSystemFileName)); + if RC <> 0 then + begin + Result := false; + OSErrorWatch (RC); + end + else + Result := true; End; {**************************************************************************** @@ -389,13 +467,16 @@ var FI: TFSinfo; RC: cardinal; begin - {In OS/2, we use the filesystem information.} - RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI)); - if RC = 0 then - DiskFree := int64 (FI.Free_Clusters) * + {In OS/2, we use the filesystem information.} + RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI)); + if RC = 0 then + DiskFree := int64 (FI.Free_Clusters) * int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector) - else - DiskFree := -1; + else + begin + DiskFree := -1; + OSErrorWatch (RC); + end; end; function DiskSize (Drive: byte): int64; @@ -404,13 +485,16 @@ var FI: TFSinfo; RC: cardinal; begin - {In OS/2, we use the filesystem information.} - RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI)); - if RC = 0 then - DiskSize := int64 (FI.Total_Clusters) * + {In OS/2, we use the filesystem information.} + RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI)); + if RC = 0 then + DiskSize := int64 (FI.Total_Clusters) * int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector) - else - DiskSize := -1; + else + begin + DiskSize := -1; + OSErrorWatch (RC); + end; end; @@ -469,17 +553,21 @@ end; procedure sysbeep; begin - // Maybe implement later on ? - + DosBeep (800, 250); end; {**************************************************************************** Locale Functions ****************************************************************************} +var + Country: TCountryCode; + CtryInfo: TCountryInfo; + procedure InitAnsi; -var I: byte; - Country: TCountryCode; +var + I: byte; + RC: cardinal; begin for I := 0 to 255 do UpperCaseTable [I] := Chr (I); @@ -493,46 +581,63 @@ end; procedure InitInternational; -var Country: TCountryCode; - CtryInfo: TCountryInfo; - Size: cardinal; - RC: cardinal; +var + Size: cardinal; + RC: cardinal; begin - Size := 0; - FillChar (Country, SizeOf (Country), 0); - FillChar (CtryInfo, SizeOf (CtryInfo), 0); - RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size); - if RC = 0 then - begin - DateSeparator := CtryInfo.DateSeparator; - case CtryInfo.DateFormat of - 1: begin - ShortDateFormat := 'd/m/y'; - LongDateFormat := 'dd" "mmmm" "yyyy'; - end; - 2: begin - ShortDateFormat := 'y/m/d'; - LongDateFormat := 'yyyy" "mmmm" "dd'; - end; - 3: begin - ShortDateFormat := 'm/d/y'; - LongDateFormat := 'mmmm" "dd" "yyyy'; - end; - end; - TimeSeparator := CtryInfo.TimeSeparator; - DecimalSeparator := CtryInfo.DecimalSeparator; - ThousandSeparator := CtryInfo.ThousandSeparator; - CurrencyFormat := CtryInfo.CurrencyFormat; - CurrencyString := PChar (CtryInfo.CurrencyUnit); + Size := 0; + FillChar (Country, SizeOf (Country), 0); + FillChar (CtryInfo, SizeOf (CtryInfo), 0); + RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size); + if RC = 0 then + begin + DateSeparator := CtryInfo.DateSeparator; + case CtryInfo.DateFormat of + 1: begin + ShortDateFormat := 'd/m/y'; + LongDateFormat := 'dd" "mmmm" "yyyy'; + end; + 2: begin + ShortDateFormat := 'y/m/d'; + LongDateFormat := 'yyyy" "mmmm" "dd'; end; - InitAnsi; - InitInternationalGeneric; + 3: begin + ShortDateFormat := 'm/d/y'; + LongDateFormat := 'mmmm" "dd" "yyyy'; + end; + end; + TimeSeparator := CtryInfo.TimeSeparator; + DecimalSeparator := CtryInfo.DecimalSeparator; + ThousandSeparator := CtryInfo.ThousandSeparator; + CurrencyFormat := CtryInfo.CurrencyFormat; + CurrencyString := PChar (CtryInfo.CurrencyUnit); + end + else + OSErrorWatch (RC); + InitAnsi; + InitInternationalGeneric; end; function SysErrorMessage(ErrorCode: Integer): String; - +const + SysMsgFile: array [0..10] of char = 'OSO001.MSG'#0; +var + OutBuf: array [0..999] of char; + RetMsgSize: cardinal; + RC: cardinal; begin - Result:=Format(SUnknownErrorCode,[ErrorCode]); + RC := DosGetMessage (nil, 0, @OutBuf [0], SizeOf (OutBuf), + ErrorCode, @SysMsgFile [0], RetMsgSize); + if RC = 0 then + begin + SetLength (Result, RetMsgSize); + Move (OutBuf [0], Result [1], RetMsgSize); + end + else + begin + Result:=Format(SUnknownErrorCode,[ErrorCode]); + OSErrorWatch (RC); + end; end; @@ -648,9 +753,10 @@ var ObjName: shortstring; RC: cardinal; ExecAppType: cardinal; + MaxArgsSize: PtrUInt; (* Amount of memory reserved for arguments in bytes. *) + MaxArgsSizeInc: word; const - MaxArgsSize = 3072; (* Amount of memory reserved for arguments in bytes. *) ObjBufSize = 512; function StartSession: cardinal; @@ -687,7 +793,10 @@ begin SD.ObjectBuffLen := ObjBufSize; RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]); if RC <> 0 then - Move (QName [1], ObjNameBuf^, Length (QName)) + begin + Move (QName [1], ObjNameBuf^, Length (QName)); + OSErrorWatch (RC); + end else begin RC := DosStartSession (SD, SID, PID); @@ -697,15 +806,28 @@ begin if RC = 0 then begin Result := PCI^.Return; - DosCloseQueue (HQ); - DosFreeMem (PCI); + RC := DosCloseQueue (HQ); + if RC <> 0 then + OSErrorWatch (RC); + RC := DosFreeMem (PCI); + if RC <> 0 then + OSErrorWatch (RC); FreeMem (ObjNameBuf, ObjBufSize); end else - DosCloseQueue (HQ); + begin + OSErrorWatch (RC); + RC := DosCloseQueue (HQ); + OSErrorWatch (RC); + end; end else - DosCloseQueue (HQ); + begin + OSErrorWatch (RC); + RC := DosCloseQueue (HQ); + if RC <> 0 then + OSErrorWatch (RC); + end; end; end; @@ -715,52 +837,68 @@ begin GetMem (ObjNameBuf, ObjBufSize); FillChar (ObjNameBuf^, ObjBufSize, 0); - if (DosQueryAppType (PChar (Path), ExecAppType) = 0) and - (ApplicationType and 3 = ExecAppType and 3) then -(* DosExecPgm should work... *) + RC := DosQueryAppType (PChar (Path), ExecAppType); + if RC <> 0 then begin - if ComLine = '' then - begin - Args0 := nil; - Args := nil; - end - else + OSErrorWatch (RC); + if (RC = 190) or (RC = 191) then + Result := StartSession; + end + else + begin + if (ApplicationType and 3 = ExecAppType and 3) then +(* DosExecPgm should work... *) begin - GetMem (Args0, MaxArgsSize); - Args := Args0; + MaxArgsSize := Length (ComLine) + Length (Path) + 256; (* More than enough *) + if MaxArgsSize > high (word) then + Exit; + if ComLine = '' then + begin + Args0 := nil; + Args := nil; + end + else + begin + GetMem (Args0, MaxArgsSize); + Args := Args0; (* Work around a bug in OS/2 - argument to DosExecPgm *) (* should not cross 64K boundary. *) - if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then - Inc (pointer (Args), 1024); - ArgSize := 0; - Move (Path [1], Args^ [ArgSize], Length (Path)); - Inc (ArgSize, Length (Path)); - Args^ [ArgSize] := 0; - Inc (ArgSize); - {Now do the real arguments.} - Move (ComLine [1], Args^ [ArgSize], Length (ComLine)); - Inc (ArgSize, Length (ComLine)); - Args^ [ArgSize] := 0; - Inc (ArgSize); - Args^ [ArgSize] := 0; - end; - Res.ExitCode := $FFFFFFFF; - RC := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res, PChar (Path)); - if Args0 <> nil then - FreeMem (Args0, MaxArgsSize); - if RC = 0 then - begin - Result := Res.ExitCode; - FreeMem (ObjNameBuf, ObjBufSize); + while ((PtrUInt (Args) + MaxArgsSize) and $FFFF) < MaxArgsSize do + begin + MaxArgsSizeInc := MaxArgsSize - + ((PtrUInt (Args) + MaxArgsSize) and $FFFF); + Inc (MaxArgsSize, MaxArgsSizeInc); + if MaxArgsSize > high (word) then + Exit; + ReallocMem (Args0, MaxArgsSize); + Inc (pointer (Args), MaxArgsSizeInc); + end; + ArgSize := 0; + Move (Path [1], Args^ [ArgSize], Length (Path)); + Inc (ArgSize, Length (Path)); + Args^ [ArgSize] := 0; + Inc (ArgSize); + {Now do the real arguments.} + Move (ComLine [1], Args^ [ArgSize], Length (ComLine)); + Inc (ArgSize, Length (ComLine)); + Args^ [ArgSize] := 0; + Inc (ArgSize); + Args^ [ArgSize] := 0; + end; + Res.ExitCode := $FFFFFFFF; + RC := DosExecPgm (ObjNameBuf, ObjBufSize, 0, Args, nil, Res, + PChar (Path)); + if RC <> 0 then + OSErrorWatch (RC); + if Args0 <> nil then + FreeMem (Args0, MaxArgsSize); + if RC = 0 then + begin + Result := Res.ExitCode; + FreeMem (ObjNameBuf, ObjBufSize); + end end - else - begin - if (RC = 190) or (RC = 191) then - Result := StartSession; - end; - end - else - Result := StartSession; + end; if RC <> 0 then begin ObjName := StrPas (ObjNameBuf); @@ -805,16 +943,30 @@ begin GetTickCount := L; end; - function GetTickCount64: QWord; var - L: cardinal; + Freq2: cardinal; + T: QWord; begin - DosQuerySysInfo (svMsCount, svMsCount, L, 4); - GetTickCount64 := L; + DosTmrQueryFreq (Freq2); + DosTmrQueryTime (T); + GetTickCount64 := T div (QWord (Freq2) div 1000); +{$NOTE GetTickCount64 takes 20 microseconds on 1GHz CPU, GetTickCount not measurable} end; +const + OrigOSErrorWatch: TOSErrorWatch = nil; + +procedure TrackLastOSError (Error: cardinal); +begin + LastOSError := Error; + OrigOSErrorWatch (Error); +end; +function GetLastOSError: Integer; +begin + GetLastOSError := Integer (LastOSError); +end; {**************************************************************************** Initialization code @@ -824,6 +976,8 @@ Initialization InitExceptions; { Initialize exceptions. OS independent } InitInternational; { Initialize internationalization settings } OnBeep:=@SysBeep; + LastOSError := 0; + OrigOSErrorWatch := TOSErrorWatch (SetOSErrorTracking (@TrackLastOSError)); Finalization DoneExceptions; end. |