Browse Source

Changes in order to support shared libraries (DLLs in Windows)
- do not shutdown when returning from "main"
- do not free windows console (unclear exception)
- changed entry and exit points for the DLL

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8348 8c9fc860-2736-0410-a75d-ab315db34111

eth.morozova 6 years ago
parent
commit
28646f95d1
3 changed files with 114 additions and 2 deletions
  1. 2 0
      source/Modules.Mod
  2. 102 1
      source/Windows.Kernel32.Mod
  3. 10 1
      source/Windows.WinTrace.Mod

+ 2 - 0
source/Modules.Mod

@@ -887,8 +887,10 @@ BEGIN
 		Trace.String("publish registered modules"); Trace.Ln;
 	END;
 	PublishRegisteredModules;
+#IF ~SHAREDLIB THEN
 	(* a standard A2 kernel does not reach this point, but for standalone executables this is required *)
 	Machine.Shutdown(FALSE);
+#END;
 END Main;
 
 #END

+ 102 - 1
source/Windows.Kernel32.Mod

@@ -929,7 +929,9 @@ VAR
 	VAR i: LONGINT;
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 		OutputString("Kernel32.Shutdown");
+	#IF ~SHAREDLIB THEN
 		ExitProcess(l);
+	#END;
 	END ShutdownP;
 	
 	PROCEDURE Init*;
@@ -1115,6 +1117,104 @@ VAR hout: HANDLE;
 
 
 #IF I386 THEN
+	
+	#IF SHAREDLIB THEN
+	
+		PROCEDURE CallSdw();
+		PROCEDURE SDW EXTERN "Modules.Shutdown"(code: LONGINT);
+		BEGIN
+			SDW(-1);
+		END CallSdw;
+		
+		(**
+			DLL entry point that corresponds to 
+			
+			BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+		*)
+		PROCEDURE {INITIAL, NOPAF} EntryPoint*;
+		CODE{SYSTEM.i386}
+			JMP  DWORD end;
+				DB 0
+				DB 0
+				DB 0
+
+			ImportTable:
+				DD Kernel32Import + 1000H
+				DD 0
+				DD -1
+				DD Kernel32Name + 1000H
+				DD Kernel32Import + 1000H
+				DD 0, 0, 0, 0, 0
+
+			Kernel32Import:
+			adrLoadLibrary:
+				DD LoadLibraryA + 1000H
+			adrGetProcAddress:
+				DD GetProcAddress + 1000H
+				DD 0
+
+			Kernel32Name:
+				DB 'KERNEL32.DLL' , 0
+
+			LoadLibraryA:
+				DW 0
+				DB 'LoadLibraryA',0,0
+
+			GetProcAddress:
+				DW 0
+				DB 'GetProcAddress',0
+
+			end:
+				PUSH EBP
+				MOV EBP, ESP
+				MOV EAX, [EBP+12]
+				CMP EAX, 1
+				JZ ProcessAttach ; call all modules bodies only when fdwReason = DLL_PROCESS_ATTACH (1)
+				CMP EAX, 0
+				JZ ProcessDetach ; call all modules bodies only when fdwReason = DLL_PROCESS_DETACH (0)
+				
+				POP EBP
+				RET 12
+
+			ProcessAttach:
+				PUSH EBX
+				PUSH ESI
+				PUSH EDI
+
+				MOV EDX, EntryPoint;
+				MOV EAX,[EDX+adrLoadLibrary]
+				MOV LoadLibrary, EAX
+				MOV EAX,[EDX+adrGetProcAddress]
+				MOV getProcAddress, EAX
+				JMP exit
+				
+			ProcessDetach:
+				PUSH EBX
+				PUSH ESI
+				PUSH EDI
+				CALL CallSdw
+				POP EDI
+				POP ESI
+				POP EBX
+		
+				POP EBP
+				RET 12
+				
+			exit:
+		END EntryPoint;
+		
+		PROCEDURE {FINAL, NOPAF} Exit*;
+		CODE{SYSTEM.i386}
+			POP EDI
+			POP ESI
+			POP EBX
+			POP EBP
+
+			MOV EAX, 1
+			RET 12
+		END Exit;
+
+	#ELSE
 		(* The following procedure is linked as the first block in the code section of a PE32 executable file 
 			It contains the import table for the two procedures Kernel32.GetProcAddress and Kernel32.LoadLibrary that
 			are patched by the PE linker. 
@@ -1160,6 +1260,7 @@ VAR hout: HANDLE;
 			MOV getProcAddress, EAX
 			
 		END EntryPoint;
+	#END;
 		
 #ELSIF AMD64 THEN
 		(* The following procedure is linked as the first block in the code section of a PE32 executable file 
@@ -1211,6 +1312,6 @@ VAR hout: HANDLE;
 	END EntryPoint;
 #ELSE
 	UNIMPLEMENTED
-#END	
+#END
 
 END Kernel32.

+ 10 - 1
source/Windows.WinTrace.Mod

@@ -7,6 +7,8 @@ CONST
 VAR
 	hin-, hout-, herr-: Kernel32.HANDLE;
 	mode: LONGINT; (* none, console or file *)
+	
+	traceChar0: PROCEDURE(ch: CHAR);
 
 (* Sender to be used with Stream.Writer *)
 PROCEDURE Send* (CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
@@ -52,9 +54,14 @@ END Init;
 PROCEDURE Close*;
 VAR res: WORD;
 BEGIN
+	IF traceChar0 # NIL THEN
+		Trace.Char := traceChar0; 
+	END;
 	IF mode = console THEN
 		Kernel32.CloseHandle(hout);
+	#IF ~SHAREDLIB THEN
 		res := Kernel32.FreeConsole ();
+	#END;
 	ELSIF mode = file THEN
 		Kernel32.CloseHandle(hout);
 	END;
@@ -80,7 +87,8 @@ BEGIN
 
 	herr := Kernel32.GetStdHandle (Kernel32.STDError);
 	ASSERT ((herr) # (Kernel32.InvalidHandleValue));
-
+	
+	traceChar0 := Trace.Char;
 	Trace.Char := Char;
 	mode := console;
 END OpenConsole;
@@ -93,6 +101,7 @@ BEGIN
 	hout := Kernel32.CreateFile(filename, {Kernel32.GenericWrite}, {Kernel32.FileShareRead}, NIL, Kernel32.CreateAlways, {Kernel32.FileAttributeNormal}, Kernel32.NULL);
 	ASSERT ((hout) # (Kernel32.InvalidHandleValue));
 	herr := hout;
+	traceChar0 := Trace.Char;
 	Trace.Char := Char;
 	mode := file;
 END OpenFile;