浏览代码

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 年之前
父节点
当前提交
28646f95d1
共有 3 个文件被更改,包括 114 次插入2 次删除
  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;
 		Trace.String("publish registered modules"); Trace.Ln;
 	END;
 	END;
 	PublishRegisteredModules;
 	PublishRegisteredModules;
+#IF ~SHAREDLIB THEN
 	(* a standard A2 kernel does not reach this point, but for standalone executables this is required *)
 	(* a standard A2 kernel does not reach this point, but for standalone executables this is required *)
 	Machine.Shutdown(FALSE);
 	Machine.Shutdown(FALSE);
+#END;
 END Main;
 END Main;
 
 
 #END
 #END

+ 102 - 1
source/Windows.Kernel32.Mod

@@ -929,7 +929,9 @@ VAR
 	VAR i: LONGINT;
 	VAR i: LONGINT;
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 		OutputString("Kernel32.Shutdown");
 		OutputString("Kernel32.Shutdown");
+	#IF ~SHAREDLIB THEN
 		ExitProcess(l);
 		ExitProcess(l);
+	#END;
 	END ShutdownP;
 	END ShutdownP;
 	
 	
 	PROCEDURE Init*;
 	PROCEDURE Init*;
@@ -1115,6 +1117,104 @@ VAR hout: HANDLE;
 
 
 
 
 #IF I386 THEN
 #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 
 		(* 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
 			It contains the import table for the two procedures Kernel32.GetProcAddress and Kernel32.LoadLibrary that
 			are patched by the PE linker. 
 			are patched by the PE linker. 
@@ -1160,6 +1260,7 @@ VAR hout: HANDLE;
 			MOV getProcAddress, EAX
 			MOV getProcAddress, EAX
 			
 			
 		END EntryPoint;
 		END EntryPoint;
+	#END;
 		
 		
 #ELSIF AMD64 THEN
 #ELSIF AMD64 THEN
 		(* The following procedure is linked as the first block in the code section of a PE32 executable file 
 		(* 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;
 	END EntryPoint;
 #ELSE
 #ELSE
 	UNIMPLEMENTED
 	UNIMPLEMENTED
-#END	
+#END
 
 
 END Kernel32.
 END Kernel32.

+ 10 - 1
source/Windows.WinTrace.Mod

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