Windows 95 is not supported by Free Pascal 2.4.4 compiler

The Free Pascal Compiler development team has discovered after 2.4.2 release that the Free Pascal Compiler does not support Windows 95 Operating System anymore. The fix is also not included in 2.4.4 source.

The following patch allows to fix the 2.4.4 RTL sources in such a way as to be able to run applications compiled with that patched RTL on Windows 95 operating system.

Win95 version 2.4.4 RTL patch support

--- systhrd.inc.orig	2011-05-05 14:16:51.719492700 +0200
+++ systhrd.inc	2011-05-05 14:14:47.903086200 +0200
@@ -13,6 +13,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  **********************************************************************}
+{$define SUPPORT_WIN95}


 {*****************************************************************************
@@ -66,9 +67,6 @@ procedure WinDoneCriticalSection(var cs
 procedure WinEnterCriticalSection(var cs : TRTLCriticalSection);
   {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'EnterCriticalSection';

-function  WinTryEnterCriticalSection(var cs : TRTLCriticalSection):longint;
-  {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TryEnterCriticalSection';
-
 procedure WinLeaveCriticalSection(var cs : TRTLCriticalSection);
   {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'LeaveCriticalSection';

@@ -80,6 +78,15 @@ CONST
    WAIT_ABANDONED = $80;
    WAIT_FAILED = $ffffffff;

+{$ifndef SUPPORT_WIN95}
+function WinTryEnterCriticalSection(var cs : TRTLCriticalSection):longint;
+  {$ifdef wince}cdecl{$else}stdcall{$endif};external KernelDLL name 'TryEnterCriticalSection';
+{$else SUPPORT_WIN95}
+type
+  TTryEnterCriticalSection = function(var cs : TRTLCriticalSection):longint; stdcall;
+var
+  WinTryEnterCriticalSection : TTryEnterCriticalSection;
+{$endif SUPPORT_WIN95}

 {*****************************************************************************
                              Threadvar support
@@ -148,10 +155,10 @@ CONST
       var
         dataindex : pointer;
         errorsave : dword;
-      begin
+      begin	
 {$ifdef dummy}
         { it least in the on windows 7 x64, this still doesn't not work, fs:(0x2c) is
-          self referencing on this system (FK)
+          self referencing on this system (FK)
           MVC: It also does not work on Windows Vista 32-bit, Home Premium, SP 1. Results in a crash}
         asm
           movl TLSKey,%edx
@@ -351,6 +358,35 @@ begin
   WinEnterCriticalSection(PRTLCriticalSection(@cs)^);
 end;

+{$ifdef SUPPORT_WIN95}
+function Win95TryEnterCriticalSection(var cs : TRTLCriticalSection):longint;stdcall;
+var
+  MyThreadID : DWORD;
+begin
+  MyThreadId:=GetCurrentThreadId();
+  if InterlockedIncrement(cs.LockCount)=0 then
+    begin
+      cs.OwningThread:=MyThreadId;
+      cs.RecursionCount:=1;
+      result:=1;
+    end
+  else
+    begin
+      if cs.OwningThread=MyThreadId then
+        begin
+          InterlockedDecrement(cs.LockCount);
+          InterlockedIncrement(cs.RecursionCount);
+          result:=1;
+        end
+      else
+        begin
+          InterlockedDecrement(cs.LockCount);
+          result:=0;
+        end;
+    end;
+end;
+{$endif SUPPORT_WIN95}
+
 function SysTryEnterCriticalSection(var cs):longint;
 begin
   result:=WinTryEnterCriticalSection(PRTLCriticalSection(@cs)^);
@@ -455,6 +491,10 @@ Var
   WinThreadManager : TThreadManager;

 Procedure InitSystemThreads;
+{$IFDEF SUPPORT_WIN95}
+var
+  KernelHandle : THandle;
+{$ENDIF SUPPORT_WIN95}
 begin
   With WinThreadManager do
     begin
@@ -496,5 +536,16 @@ begin
   ThreadID := GetCurrentThreadID;
   if IsLibrary then
     SysInitMultithreading;
+ {$IFDEF SUPPORT_WIN95}
+   { Try to find TryEnterCriticalSection function }
+   KernelHandle:=LoadLibrary(KernelDLL);
+   if KernelHandle<>0 then
+     begin
+       WinTryEnterCriticalSection:=TTryEnterCriticalSection(GetProcAddress(KernelHandle,'TryEnterCriticalSection'));
+       FreeLibrary(KernelHandle);
+     end;
+   if not assigned(WinTryEnterCriticalSection) then
+     WinTryEnterCriticalSection:=@Win95TryEnterCriticalSection;
+ {$ENDIF SUPPORT_WIN95}
 end;


How to apply this patch?

You first need to install the sources of 2.4.4 RTL. After, just copy the content of the patch above to a file, named systhread.patch. Copy that file into the directory rtl/win, and apply the patch using:

patch -p 0 -i systhread.patch
Move back to rtl directory level, and recompile the RTL, using make:
make clean all
If you want to be able to compile applications that should run on Windows 95 operating system, you should probably install the new rtl over the existing one.

If you try to recompile all the packages, you might also run into the cdrom directory problem: cdrom is a device name (like aux, con, lpt1, com1 ...) under standard Win95 installation, and thus no directory have this name is allowed. This means that on extraction of cdrom directory from fpcbuild-2.4.4.zip will fail, leading later to an error if you try to recompile the packages. To overcome this limitation, remove the occurences of cdrom inside makefile.fpc in packages directory and run:

fpcmake -Tall
in the same directory. After this change, the compilation of packages directory should succeed.

Pierre Muller, 2011-05-05