2
$Id: syswin32.pp,v 1.1.2.1 2000/10/02 22:15:39 pierre Exp $
3
This file is part of the Free Pascal run time library.
4
Copyright (c) 1999-2000 by Florian Klaempfl and Pavel Ozerski
5
member of the Free Pascal development team.
7
FPC Pascal system unit for the Win32 API.
9
See the file COPYING.FPC, included in this distribution,
10
for details about the copyright.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
**********************************************************************}
21
{$define SYSTEMEXCEPTIONDEBUG}
25
{$define Set_i386_Exception_handler}
28
{ include system-independent routine headers }
31
{ include heap support headers }
35
{ Default filehandles }
36
UnusedHandle : longint = -1;
37
StdInputHandle : longint = 0;
38
StdOutputHandle : longint = 0;
39
StdErrorHandle : longint = 0;
41
FileNameCaseSensitive : boolean = true;
44
TStartupInfo=packed record
53
dwXCountChars : longint;
54
dwYCountChars : longint;
55
dwFillAttribute : longint;
59
lpReserved2 : Pointer;
66
{ C compatible arguments }
70
startupinfo : tstartupinfo;
75
DLLreason,DLLparam:longint;
76
Win32StackTop : Dword;
77
{ Thread count for DLL }
79
Thread_count : longint = 0;
81
TDLL_Process_Entry_Hook = function (dllparam : longint) : longbool;
82
TDLL_Entry_Hook = procedure (dllparam : longint);
85
Dll_Process_Attach_Hook : TDLL_Process_Entry_Hook = nil;
86
Dll_Process_Detach_Hook : TDLL_Entry_Hook = nil;
87
Dll_Thread_Attach_Hook : TDLL_Entry_Hook = nil;
88
Dll_Thread_Detach_Hook : TDLL_Entry_Hook = nil;
92
{ include system independent routines }
95
{ some declarations for Win32 API calls }
100
{ These constants are used for conversion of error codes }
101
{ from win32 i/o errors to tp i/o errors }
102
{ errors 1 to 18 are the same as in Turbo Pascal }
103
{ DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING! }
105
{ The media is write protected. }
106
ERROR_WRITE_PROTECT = 19;
107
{ The system cannot find the device specified. }
109
{ The device is not ready. }
110
ERROR_NOT_READY = 21;
111
{ The device does not recognize the command. }
112
ERROR_BAD_COMMAND = 22;
113
{ Data error (cyclic redundancy check) }
115
{ The program issued a command but the }
116
{ command length is incorrect. }
117
ERROR_BAD_LENGTH = 24;
118
{ The drive cannot locate a specific }
119
{ area or track on the disk. }
121
{ The specified disk or diskette cannot be accessed. }
122
ERROR_NOT_DOS_DISK = 26;
123
{ The drive cannot find the sector requested. }
124
ERROR_SECTOR_NOT_FOUND = 27;
125
{ The printer is out of paper. }
126
ERROR_OUT_OF_PAPER = 28;
127
{ The system cannot write to the specified device. }
128
ERROR_WRITE_FAULT = 29;
129
{ The system cannot read from the specified device. }
130
ERROR_READ_FAULT = 30;
131
{ A device attached to the system is not functioning.}
132
ERROR_GEN_FAILURE = 31;
133
{ The process cannot access the file because }
134
{ it is being used by another process. }
135
ERROR_SHARING_VIOLATION = 32;
144
function GetLastError : DWORD;
145
external 'kernel32' name 'GetLastError';
147
{ time and date functions }
148
function GetTickCount : longint;
149
external 'kernel32' name 'GetTickCount';
151
{ process functions }
152
procedure ExitProcess(uExitCode : UINT);
153
external 'kernel32' name 'ExitProcess';
156
Procedure Errno2InOutRes;
158
{ DO NOT MODIFY UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING }
159
if (errno >= ERROR_WRITE_PROTECT) and (errno <= ERROR_GEN_FAILURE) THEN
161
{ This is the offset to the Win32 to add to directly map }
162
{ to the DOS/TP compatible error codes when in this range }
163
InOutRes := word(errno)+131;
166
{ This case is special }
167
if errno=ERROR_SHARING_VIOLATION THEN
172
{ other error codes can directly be mapped }
173
InOutRes := Word(errno);
179
procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
181
called when trying to get local stack if the compiler directive $S
182
is set this function must preserve esi !!!! because esi is set by
183
the calling proc for methods it must preserve all registers !!
185
With a 2048 byte safe area used to write to StdIo without crossing
199
jae .L__short_on_stack
205
{ can be usefull for error recovery !! }
214
function paramcount : longint;
216
paramcount := argc - 1;
220
function GetModuleFileName(l1:longint;p:pointer;l2:longint):longint;
221
external 'kernel32' name 'GetModuleFileNameA';
222
function GetModuleHandle(p : pointer) : longint;
223
external 'kernel32' name 'GetModuleHandleA';
224
function GetCommandFile:pchar;forward;
226
function paramstr(l : longint) : string;
228
if (l>=0) and (l<argc) then
229
paramstr:=strpas(argv[l])
237
randseed:=GetTickCount;
241
{*****************************************************************************
243
*****************************************************************************}
246
function GlobalAlloc(mode,size:longint):longint;
247
external 'kernel32' name 'GlobalAlloc';
248
function GlobalLock(handle:longint):pointer;
249
external 'kernel32' name 'GlobalLock';
251
function GlobalSize(h:longint):longint;
252
external 'kernel32' name 'GlobalSize';
256
heap : longint;external name 'HEAP';
257
intern_heapsize : longint;external name 'HEAPSIZE';
259
function getheapstart:pointer;assembler;
265
function getheapsize:longint;assembler;
267
movl intern_HEAPSIZE,%eax
271
function Sbrk(size : longint):longint;
275
h:=GlobalAlloc(258,size);
276
l:=longint(GlobalLock(h));
280
Writeln('new heap part at $',hexstr(l,8), ' size = ',GlobalSize(h));
285
{ include standard heap management }
289
{*****************************************************************************
290
Low Level File Routines
291
*****************************************************************************}
293
function WriteFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
294
overlap:pointer):longint;
295
external 'kernel32' name 'WriteFile';
296
function ReadFile(fh:longint;buf:pointer;len:longint;var loaded:longint;
297
overlap:pointer):longint;
298
external 'kernel32' name 'ReadFile';
299
function CloseHandle(h : longint) : longint;
300
external 'kernel32' name 'CloseHandle';
301
function DeleteFile(p : pchar) : longint;
302
external 'kernel32' name 'DeleteFileA';
303
function MoveFile(old,_new : pchar) : longint;
304
external 'kernel32' name 'MoveFileA';
305
function SetFilePointer(l1,l2 : longint;l3 : pointer;l4 : longint) : longint;
306
external 'kernel32' name 'SetFilePointer';
307
function GetFileSize(h:longint;p:pointer) : longint;
308
external 'kernel32' name 'GetFileSize';
309
function CreateFile(name : pointer;access,sharing : longint;
310
security : pointer;how,attr,template : longint) : longint;
311
external 'kernel32' name 'CreateFileA';
312
function SetEndOfFile(h : longint) : longbool;
313
external 'kernel32' name 'SetEndOfFile';
314
function GetFileType(Handle:DWORD):DWord;
315
external 'kernel32' name 'GetFileType';
318
procedure AllowSlash(p:pchar);
322
{ allow slash as backslash }
323
for i:=0 to strlen(p) do
324
if p[i]='/' then p[i]:='\';
327
function do_isdevice(handle:longint):boolean;
329
do_isdevice:=(getfiletype(handle)=2);
333
procedure do_close(h : longint);
335
if do_isdevice(h) then
341
procedure do_erase(p : pchar);
344
if DeleteFile(p)=0 then
352
procedure do_rename(p1,p2 : pchar);
356
if MoveFile(p1,p2)=0 then
364
function do_write(h,addr,len : longint) : longint;
368
if writefile(h,pointer(addr),len,size,nil)=0 then
377
function do_read(h,addr,len : longint) : longint;
381
if readfile(h,pointer(addr),len,_result,nil)=0 then
390
function do_filepos(handle : longint) : longint;
394
l:=SetFilePointer(handle,0,nil,FILE_CURRENT);
405
procedure do_seek(handle,pos : longint);
407
if SetFilePointer(handle,pos,nil,FILE_BEGIN)=-1 then
415
function do_seekend(handle:longint):longint;
417
do_seekend:=SetFilePointer(handle,0,nil,FILE_END);
418
if do_seekend=-1 then
426
function do_filesize(handle : longint) : longint;
428
aktfilepos : longint;
430
aktfilepos:=do_filepos(handle);
431
do_filesize:=do_seekend(handle);
432
do_seek(handle,aktfilepos);
436
procedure do_truncate (handle,pos:longint);
439
if not(SetEndOfFile(handle)) then
447
procedure do_open(var f;p : pchar;flags:longint);
449
filerec and textrec have both handle and mode as the first items so
450
they could use the same routine for opening/creating.
451
when (flags and $100) the file will be append
452
when (flags and $1000) the file will be truncate/rewritten
453
when (flags and $10000) there is no check for close (needed for textfiles)
456
file_Share_Read = $00000001;
457
file_Share_Write = $00000002;
463
{ close first if opened }
464
if ((flags and $10000)=0) then
466
case filerec(f).mode of
467
fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
477
{ reset file handle }
478
filerec(f).handle:=UnusedHandle;
479
{ convert filesharing }
481
if ((filemode and fmshareExclusive) = fmshareExclusive) then
484
if (filemode = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
485
shflags := file_Share_Read
487
if ((filemode and fmshareDenyRead) = fmshareDenyRead) then
488
shflags := file_Share_Write
490
if ((filemode and fmshareDenyNone) = fmshareDenyNone) then
491
shflags := file_Share_Read + file_Share_Write;
492
{ convert filemode to filerec modes }
493
case (flags and 3) of
495
filerec(f).mode:=fminput;
496
oflags:=GENERIC_READ;
499
filerec(f).mode:=fmoutput;
500
oflags:=GENERIC_WRITE;
503
filerec(f).mode:=fminout;
504
oflags:=GENERIC_WRITE or GENERIC_READ;
507
{ standard is opening and existing file }
510
if (flags and $1000)<>0 then
514
if (flags and $100)<>0 then
516
{ empty name is special }
519
case FileRec(f).mode of
521
FileRec(f).Handle:=StdInputHandle;
522
fminout, { this is set by rewrite }
524
FileRec(f).Handle:=StdOutputHandle;
527
FileRec(f).Handle:=StdOutputHandle;
528
FileRec(f).mode:=fmoutput; {fool fmappend}
533
filerec(f).handle:=CreateFile(p,oflags,shflags,nil,cd,FILE_ATTRIBUTE_NORMAL,0);
535
if (flags and $100)<>0 then
537
do_seekend(filerec(f).handle);
538
filerec(f).mode:=fmoutput; {fool fmappend}
541
{ handle -1 is returned sometimes !! (PM) }
542
if (filerec(f).handle=0) or (filerec(f).handle=-1) then
552
{*****************************************************************************
553
UnTyped File Handling
554
*****************************************************************************}
558
{*****************************************************************************
560
*****************************************************************************}
564
{*****************************************************************************
566
*****************************************************************************}
572
{*****************************************************************************
574
*****************************************************************************}
576
function CreateDirectory(name : pointer;sec : pointer) : longint;
577
external 'kernel32' name 'CreateDirectoryA';
578
function RemoveDirectory(name:pointer):longint;
579
external 'kernel32' name 'RemoveDirectoryA';
580
function SetCurrentDirectory(name : pointer) : longint;
581
external 'kernel32' name 'SetCurrentDirectoryA';
582
function GetCurrentDirectory(bufsize : longint;name : pchar) : longint;
583
external 'kernel32' name 'GetCurrentDirectoryA';
586
TDirFnType=function(name:pointer):word;
588
procedure dirfn(afunc : TDirFnType;const s:string);
590
buffer : array[0..255] of char;
592
move(s[1],buffer,length(s));
593
buffer[length(s)]:=#0;
594
AllowSlash(pchar(@buffer));
595
if aFunc(@buffer)=0 then
602
function CreateDirectoryTrunc(name:pointer):word;
604
CreateDirectoryTrunc:=CreateDirectory(name,nil);
607
procedure mkdir(const s:string);[IOCHECK];
609
If InOutRes <> 0 then exit;
610
dirfn(TDirFnType(@CreateDirectoryTrunc),s);
613
procedure rmdir(const s:string);[IOCHECK];
615
If InOutRes <> 0 then exit;
616
dirfn(TDirFnType(@RemoveDirectory),s);
619
procedure chdir(const s:string);[IOCHECK];
621
If InOutRes <> 0 then exit;
622
dirfn(TDirFnType(@SetCurrentDirectory),s);
625
procedure getdir(drivenr:byte;var dir:shortstring);
627
Drive:array[0..3]of char=(#0,':',#0,#0);
629
defaultdrive:boolean;
630
DirBuf,SaveBuf:array[0..259] of Char;
632
defaultdrive:=drivenr=0;
633
if not defaultdrive then
635
byte(Drive[0]):=Drivenr+64;
636
GetCurrentDirectory(SizeOf(SaveBuf),SaveBuf);
637
SetCurrentDirectory(@Drive);
639
GetCurrentDirectory(SizeOf(DirBuf),DirBuf);
640
if not defaultdrive then
641
SetCurrentDirectory(@SaveBuf);
643
if not FileNameCaseSensitive then
648
{*****************************************************************************
649
SystemUnit Initialization
650
*****************************************************************************}
653
procedure GetStartupInfo(p : pointer);
654
external 'kernel32' name 'GetStartupInfoA';
655
function GetStdHandle(nStdHandle:DWORD):THANDLE;
656
external 'kernel32' name 'GetStdHandle';
658
{ command line/enviroment functions }
659
function GetCommandLine : pchar;
660
external 'kernel32' name 'GetCommandLineA';
664
ModuleName : array[0..255] of char;
666
function GetCommandFile:pchar;
668
GetModuleFileName(0,@ModuleName,255);
669
GetCommandFile:=@ModuleName;
673
procedure setup_arguments;
680
argsbuf : array[0..127] of pchar;
682
{ create commandline, it starts with the executed filename which is argv[0] }
683
{ Win32 passes the command NOT via the args, but via getmodulefilename}
689
until (pc[Arglen]=#0);
690
getmem(argsbuf[count],arglen+1);
691
move(pc^,argsbuf[count]^,arglen);
692
{ Now skip the first one }
695
{ skip leading spaces }
696
while pc^ in [' ',#9,#13] do
711
{ scan until the end of the argument }
713
while (pc^<>#0) and not(pc^ in quote) do
715
{ Don't copy the first one, it is already there.}
718
{ reserve some memory }
720
getmem(argsbuf[count],arglen+1);
721
move(argstart^,argsbuf[count]^,arglen);
722
argsbuf[count][arglen]:=#0;
731
{ create an nil entry }
735
getmem(argv,count shl 2);
736
move(argsbuf,argv^,count shl 2);
737
{ Setup cmdline variable }
738
cmdline:=GetCommandLine;
742
{*****************************************************************************
743
System Dependent Exit code
744
*****************************************************************************}
746
procedure install_exception_handlers;forward;
747
procedure remove_exception_handlers;forward;
748
procedure PascalMain;external name 'PASCALMAIN';
749
procedure fpc_do_exit;external name 'FPC_DO_EXIT';
750
Procedure ExitDLL(Exitcode : longint); forward;
752
Procedure system_exit;
754
{ don't call ExitProcess inside
756
This crashes Win95 at least PM }
759
if not IsConsole then
763
{ what about Input and Output ?? PM }
765
remove_exception_handlers;
766
ExitProcess(ExitCode);
770
Function SetUpStack : longint;
771
{ This routine does the following : }
772
{ returns the value of the initial SP - __stklen }
789
{ value of the stack segment
790
to check if the call stack can be written on exceptions }
794
fpucw : word = $1332;
796
procedure Exe_entry;[public, alias : '_FPC_EXE_Entry'];
799
{ install the handlers for exe only ?
800
or should we install them for DLL also ? (PM) }
801
install_exception_handlers;
802
{ This strange construction is needed to solve the _SS problem
803
with a smartlinked syswin32 (PFV) }
808
movl %eax,Win32StackTop
817
{ if we pass here there was no error ! }
823
DLL_PROCESS_ATTACH = 1;
824
DLL_THREAD_ATTACH = 2;
825
DLL_PROCESS_DETACH = 0;
826
DLL_THREAD_DETACH = 3;
830
DLLExitOK : boolean = true;
832
function Dll_entry : longbool;[public, alias : '_FPC_DLL_Entry'];
842
If SetJmp(DLLBuf) = 0 then
844
if assigned(Dll_Process_Attach_Hook) then
846
res:=Dll_Process_Attach_Hook(DllParam);
854
Dll_entry:=DLLExitOK;
859
if assigned(Dll_Thread_Attach_Hook) then
860
Dll_Thread_Attach_Hook(DllParam);
861
Dll_entry:=true; { return value is ignored }
866
if assigned(Dll_Thread_Detach_Hook) then
867
Dll_Thread_Detach_Hook(DllParam);
868
Dll_entry:=true; { return value is ignored }
872
Dll_entry:=true; { return value is ignored }
873
If SetJmp(DLLBuf) = 0 then
877
if assigned(Dll_Process_Detach_Hook) then
878
Dll_Process_Detach_Hook(DllParam);
883
Procedure ExitDLL(Exitcode : longint);
885
DLLExitOK:=ExitCode=0;
889
{$ifdef Set_i386_Exception_handler}
892
EXCEPTION_MAXIMUM_PARAMETERS = 15;
893
EXCEPTION_ACCESS_VIOLATION = $c0000005;
894
EXCEPTION_BREAKPOINT = $80000003;
895
EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
896
EXCEPTION_SINGLE_STEP = $80000004;
897
EXCEPTION_ARRAY_BOUNDS_EXCEEDED = $c000008c;
898
EXCEPTION_FLT_DENORMAL_OPERAND = $c000008d;
899
EXCEPTION_FLT_DIVIDE_BY_ZERO = $c000008e;
900
EXCEPTION_FLT_INEXACT_RESULT = $c000008f;
901
EXCEPTION_FLT_INVALID_OPERATION = $c0000090;
902
EXCEPTION_FLT_OVERFLOW = $c0000091;
903
EXCEPTION_FLT_STACK_CHECK = $c0000092;
904
EXCEPTION_FLT_UNDERFLOW = $c0000093;
905
EXCEPTION_INT_DIVIDE_BY_ZERO = $c0000094;
906
EXCEPTION_INT_OVERFLOW = $c0000095;
907
EXCEPTION_INVALID_HANDLE = $c0000008;
908
EXCEPTION_PRIV_INSTRUCTION = $c0000096;
909
EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
910
EXCEPTION_NONCONTINUABLE = $1;
911
EXCEPTION_STACK_OVERFLOW = $c00000fd;
912
EXCEPTION_INVALID_DISPOSITION = $c0000026;
913
EXCEPTION_ILLEGAL_INSTRUCTION = $C000001D;
914
EXCEPTION_IN_PAGE_ERROR = $C0000006;
916
EXCEPTION_EXECUTE_HANDLER = 1;
917
EXCEPTION_CONTINUE_EXECUTION = -(1);
918
EXCEPTION_CONTINUE_SEARCH = 0;
921
FLOATING_SAVE_AREA = record
926
ErrorSelector : DWORD;
928
DataSelector : DWORD;
929
RegisterArea : array[0..79] of BYTE;
932
_FLOATING_SAVE_AREA = FLOATING_SAVE_AREA;
933
TFLOATINGSAVEAREA = FLOATING_SAVE_AREA;
934
PFLOATINGSAVEAREA = ^FLOATING_SAVE_AREA;
937
ContextFlags : DWORD;
944
FloatSave : FLOATING_SAVE_AREA;
962
LPCONTEXT = ^CONTEXT;
968
type pexception_record = ^exception_record;
969
EXCEPTION_RECORD = record
970
ExceptionCode : longint;
971
ExceptionFlags : longint;
972
ExceptionRecord : pexception_record;
973
ExceptionAddress : pointer;
974
NumberParameters : longint;
975
ExceptionInformation : array[0..EXCEPTION_MAXIMUM_PARAMETERS-1] of pointer;
978
PEXCEPTION_POINTERS = ^EXCEPTION_POINTERS;
979
EXCEPTION_POINTERS = record
980
ExceptionRecord : PEXCEPTION_RECORD ;
981
ContextRecord : PCONTEXT ;
984
{ type of functions that should be used for exception handling }
985
LPTOP_LEVEL_EXCEPTION_FILTER = function(excep :PEXCEPTION_POINTERS) : longint;stdcall;
987
function SetUnhandledExceptionFilter(lpTopLevelExceptionFilter : LPTOP_LEVEL_EXCEPTION_FILTER)
988
: LPTOP_LEVEL_EXCEPTION_FILTER;
989
external 'kernel32' name 'SetUnhandledExceptionFilter';
993
except_level : byte = 0;
995
except_eip : array[0..Max_level-1] of longint;
996
except_error : array[0..Max_level-1] of byte;
997
reset_fpu : array[0..max_level-1] of boolean;
999
{$ifdef SYSTEMEXCEPTIONDEBUG}
1000
procedure DebugHandleErrorAddrFrame(error, addr, frame : longint);
1004
write(stderr,'call to HandleErrorAddrFrame(error=',error);
1005
write(stderr,',addr=',hexstr(addr,8));
1006
writeln(stderr,',frame=',hexstr(frame,8),')');
1008
HandleErrorAddrFrame(error,addr,frame);
1010
{$endif SYSTEMEXCEPTIONDEBUG}
1012
procedure JumpToHandleErrorFrame;
1014
eip,ebp,error : longint;
1020
if except_level>0 then
1022
eip:=except_eip[except_level];
1023
error:=except_error[except_level];
1024
{$ifdef SYSTEMEXCEPTIONDEBUG}
1027
writeln(stderr,'In JumpToHandleErrorFrame error=',error);
1029
{$endif SYSTEMEXCEPTIONDEBUG}
1030
if reset_fpu[except_level] then
1035
{ build a fake stack }
1045
movl ebp,%ebp // Change frame pointer
1046
{$ifdef SYSTEMEXCEPTIONDEBUG}
1047
jmpl DebugHandleErrorAddrFrame
1048
{$else not SYSTEMEXCEPTIONDEBUG}
1049
jmpl HandleErrorAddrFrame
1050
{$endif SYSTEMEXCEPTIONDEBUG}
1055
function syswin32_i386_exception_handler(excep :PEXCEPTION_POINTERS) : longint;stdcall;
1056
var frame,res : longint;
1057
function SysHandleErrorFrame(error,frame : longint;must_reset_fpu : boolean) : longint;
1060
SysHandleErrorFrame:=Exception_Continue_Search
1063
if except_level >= Max_level then
1065
except_eip[except_level]:=excep^.ContextRecord^.Eip;
1066
except_error[except_level]:=error;
1067
reset_fpu[except_level]:=must_reset_fpu;
1069
excep^.ContextRecord^.Eip:=longint(@JumpToHandleErrorFrame);
1070
excep^.ExceptionRecord^.ExceptionCode:=0;
1071
SysHandleErrorFrame:=Exception_Continue_Execution;
1072
{$ifdef SYSTEMEXCEPTIONDEBUG}
1075
writeln(stderr,'Exception Continue Exception set at ',
1076
hexstr(except_eip[except_level],8));
1077
writeln(stderr,'Eip changed to ',
1078
hexstr(longint(@JumpToHandleErrorFrame),8), ' error=',error);
1080
{$endif SYSTEMEXCEPTIONDEBUG}
1085
if excep^.ContextRecord^.SegSs=_SS then
1086
frame:=excep^.ContextRecord^.Ebp
1089
{ default : unhandled !}
1090
res:=Exception_Continue_Search;
1091
{$ifdef SYSTEMEXCEPTIONDEBUG}
1093
writeln(stderr,'Exception ',
1094
hexstr(excep^.ExceptionRecord^.ExceptionCode,8));
1095
{$endif SYSTEMEXCEPTIONDEBUG}
1096
case excep^.ExceptionRecord^.ExceptionCode of
1097
EXCEPTION_ACCESS_VIOLATION :
1098
res:=SysHandleErrorFrame(216,frame,false);
1099
{ EXCEPTION_BREAKPOINT = $80000003;
1100
EXCEPTION_DATATYPE_MISALIGNMENT = $80000002;
1101
EXCEPTION_SINGLE_STEP = $80000004; }
1102
EXCEPTION_ARRAY_BOUNDS_EXCEEDED :
1103
res:=SysHandleErrorFrame(201,frame,false);
1104
EXCEPTION_FLT_DENORMAL_OPERAND :
1106
res:=SysHandleErrorFrame(216,frame,true);
1108
EXCEPTION_FLT_DIVIDE_BY_ZERO :
1110
res:=SysHandleErrorFrame(200,frame,true);
1111
{excep^.ContextRecord^.FloatSave.StatusWord:=excep^.ContextRecord^.FloatSave.StatusWord and $ffffff00;}
1113
{EXCEPTION_FLT_INEXACT_RESULT = $c000008f; }
1114
EXCEPTION_FLT_INVALID_OPERATION :
1116
res:=SysHandleErrorFrame(207,frame,true);
1118
EXCEPTION_FLT_OVERFLOW :
1120
res:=SysHandleErrorFrame(205,frame,true);
1122
EXCEPTION_FLT_STACK_CHECK :
1124
res:=SysHandleErrorFrame(207,frame,true);
1126
EXCEPTION_FLT_UNDERFLOW :
1128
res:=SysHandleErrorFrame(206,frame,true); { should be accepted as zero !! }
1130
EXCEPTION_INT_DIVIDE_BY_ZERO :
1131
res:=SysHandleErrorFrame(200,frame,false);
1132
EXCEPTION_INT_OVERFLOW :
1133
res:=SysHandleErrorFrame(215,frame,false);
1134
{EXCEPTION_INVALID_HANDLE = $c0000008;
1135
EXCEPTION_PRIV_INSTRUCTION = $c0000096;
1136
EXCEPTION_NONCONTINUABLE_EXCEPTION = $c0000025;
1137
EXCEPTION_NONCONTINUABLE = $1;}
1138
EXCEPTION_STACK_OVERFLOW :
1139
res:=SysHandleErrorFrame(202,frame,false);
1140
{EXCEPTION_INVALID_DISPOSITION = $c0000026;}
1141
EXCEPTION_ILLEGAL_INSTRUCTION,
1142
EXCEPTION_PRIV_INSTRUCTION,
1143
EXCEPTION_IN_PAGE_ERROR,
1144
EXCEPTION_SINGLE_STEP : res:=SysHandleErrorFrame(217,frame,false);
1146
syswin32_i386_exception_handler:=res;
1150
procedure install_exception_handlers;
1151
{$ifdef SYSTEMEXCEPTIONDEBUG}
1153
oldexceptaddr,newexceptaddr : longint;
1154
{$endif SYSTEMEXCEPTIONDEBUG}
1156
{$ifdef SYSTEMEXCEPTIONDEBUG}
1159
movl %fs:(%eax),%eax
1160
movl %eax,oldexceptaddr
1162
{$endif SYSTEMEXCEPTIONDEBUG}
1163
SetUnhandledExceptionFilter(@syswin32_i386_exception_handler);
1164
{$ifdef SYSTEMEXCEPTIONDEBUG}
1167
movl %fs:(%eax),%eax
1168
movl %eax,newexceptaddr
1171
writeln(stderr,'Old exception ',hexstr(oldexceptaddr,8),
1172
' new exception ',hexstr(newexceptaddr,8));
1173
{$endif SYSTEMEXCEPTIONDEBUG}
1176
procedure remove_exception_handlers;
1178
SetUnhandledExceptionFilter(nil);
1181
{$else not i386 (Processor specific !!)}
1182
procedure install_exception_handlers;
1186
procedure remove_exception_handlers;
1190
{$endif Set_i386_Exception_handler}
1193
{****************************************************************************
1194
Error Message writing using messageboxes
1195
****************************************************************************}
1197
function MessageBox(w1:longint;l1,l2:pointer;w2:longint):longint;
1198
external 'user32' name 'MessageBoxA';
1201
ErrorBufferLength = 1024;
1203
ErrorBuf : array[0..ErrorBufferLength] of char;
1206
Function ErrorWrite(Var F: TextRec): Integer;
1208
An error message should always end with #13#10#13#10
1216
if F.BufPos+ErrorLen>ErrorBufferLength then
1217
i:=ErrorBufferLength-ErrorLen
1220
Move(F.BufPtr^,ErrorBuf[ErrorLen],i);
1222
ErrorBuf[ErrorLen]:=#0;
1226
p:=@ErrorBuf[ErrorLen];
1230
if not(p^ in [#10,#13]) then
1234
if ErrorLen=ErrorBufferLength then
1238
MessageBox(0,@ErrorBuf,pchar('Error'),0);
1246
Function ErrorClose(Var F: TextRec): Integer;
1250
MessageBox(0,@ErrorBuf,pchar('Error'),0);
1258
Function ErrorOpen(Var F: TextRec): Integer;
1260
TextRec(F).InOutFunc:=@ErrorWrite;
1261
TextRec(F).FlushFunc:=@ErrorWrite;
1262
TextRec(F).CloseFunc:=@ErrorClose;
1267
procedure AssignError(Var T: Text);
1270
TextRec(T).OpenFunc:=@ErrorOpen;
1277
Exe_entry_code : pointer = @Exe_entry;
1278
Dll_entry_code : pointer = @Dll_entry;
1281
{ get some helpful informations }
1282
GetStartupInfo(@startupinfo);
1283
{ some misc Win32 stuff }
1285
if not IsLibrary then
1286
HInstance:=getmodulehandle(GetCommandFile);
1287
MainInstance:=HInstance;
1288
{ No idea how to know this issue !! }
1289
IsMultithreaded:=false;
1290
cmdshow:=startupinfo.wshowwindow;
1291
{ to test stack depth }
1292
loweststack:=maxlongint;
1293
{ real test stack depth }
1294
{ stacklimit := setupstack; }
1298
{ Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
1299
displayed in and messagebox }
1300
StdInputHandle:=longint(GetStdHandle(STD_INPUT_HANDLE));
1301
StdOutputHandle:=longint(GetStdHandle(STD_OUTPUT_HANDLE));
1302
StdErrorHandle:=longint(GetStdHandle(STD_ERROR_HANDLE));
1303
if not IsConsole then
1305
AssignError(stderr);
1306
AssignError(stdout);
1312
OpenStdIO(Input,fmInput,StdInputHandle);
1313
OpenStdIO(Output,fmOutput,StdOutputHandle);
1314
OpenStdIO(StdOut,fmOutput,StdOutputHandle);
1315
OpenStdIO(StdErr,fmOutput,StdErrorHandle);
1321
{ Reset internal error variable }
1326
$Log: syswin32.pp,v $
1327
Revision 1.1.2.1 2000/10/02 22:15:39 pierre
1328
* all callbacks are stdcall functions
1330
Revision 1.1 2000/07/13 06:31:22 michael
1333
Revision 1.65 2000/06/22 18:39:14 peter
1334
* moved islibrary,isconsole,ismulithread to systemh as they are
1337
Revision 1.64 2000/05/08 13:25:34 peter
1338
* defined filemode constants in windows unit
1340
Revision 1.63 2000/03/31 23:21:19 pierre
1341
* multiple exception handling works
1342
(for linux only if syslinux is compiled with -dnewsignal)
1344
Revision 1.62 2000/03/16 20:42:26 michael
1345
+ Added more system exception handling afte T. Schatzl remark
1347
Revision 1.61 2000/03/10 09:21:11 pierre
1348
* ExitDLL fixed : uses now SetJmp LongJmp
1349
* System_exit unloads the exception hanlder before leaving
1351
Revision 1.60 2000/02/09 16:59:34 peter
1354
Revision 1.59 2000/02/09 12:24:39 peter
1355
* halt moved to system.inc
1357
Revision 1.58 2000/01/20 23:38:02 peter
1358
* support fm_inout as stdoutput for assign(f,'');rewrite(f,1); becuase
1359
rewrite opens always with filemode 2
1361
Revision 1.57 2000/01/18 09:03:04 pierre
1362
* DLL crash fixed : ExitProcess can not be called in DLL system_exit
1363
Problem : Halt or RunError code inside DLL will return to caller !!
1364
* Changed the "if h<4 then" into "if do_isdevice(h) then " in do_close
1365
to avoid closing of standard files
1367
Revision 1.56 2000/01/16 23:05:03 peter
1370
Revision 1.55 2000/01/16 22:25:38 peter
1371
* check handle for file closing
1373
Revision 1.54 2000/01/07 16:41:52 daniel
1376
Revision 1.53 2000/01/07 16:32:34 daniel
1377
* copyright 2000 added
1379
Revision 1.52 2000/01/06 23:40:36 peter
1380
* fixed exitprocess call, it's now in system_exit and uses exitcode
1382
Revision 1.51 1999/12/01 22:57:31 peter
1385
Revision 1.50 1999/11/20 00:16:44 pierre
1386
+ DLL Hooks for the four callings added
1388
Revision 1.49 1999/11/18 22:19:57 pierre
1389
* bug fix for web bug703 and 704
1391
Revision 1.48 1999/11/09 22:34:00 pierre
1392
* Check ErrorBuf at exit
1395
Revision 1.47 1999/10/26 12:25:51 peter
1396
* report stderr,stdout to message box for errors
1397
* close input,output when GUI app is made
1399
Revision 1.46 1999/10/22 14:47:19 peter
1400
* allocate an extra byte for argv[0]
1402
Revision 1.45 1999/10/03 19:39:05 peter
1403
* fixed argv[0] length
1405
Revision 1.44 1999/09/10 15:40:35 peter
1406
* fixed do_open flags to be > $100, becuase filemode can be upto 255
b'\\ No newline at end of file'