macro_file IDEXE;

//#define _DEBUG_

#ifdef _DEBUG_
	#include DBUG.SH
	#include SPRINTF.SH
#endif

#include IDEXE.SH
#include METOOLS.SH
#include WINDOWS.SH


int IdExe( str Program = Parse_Str( "/P=", MParm_Str ) ) Trans2 {
/******************************************************************************
															 Multi-Edit Macro
															 06-Jun-95  13:34

	Function: Determines the Executable type of Program.  Can detect DOS,
						Windows, OS/2, NT and Bound Windows and Bound OS/2 programs.

							 Copyright (C) 1995 by American Cybernectic, Inc.
********************************************************************( ldh )***/


	int Result = _Exe_Id_Unknown;

	int Hn = 0;
	int Bound = _Exe_Id_Unknown;
	int Lo;
	int Hi;

	str Ts[4];
	str Ext[ 3 ];

	program = GetShortName(program);

	Ext = Caps( Get_Extension( Program ) );
	if ( Ext == "BAT" ) {
		Result = _Exe_Id_Dos;
		goto Exit;
	}
	if ( Ext == "CMD" ) {
		Result = _Exe_Id_Os2;
		goto Exit;
	}
	if ( Ext == "PIF" ) {
		Result = _Exe_Id_Windows;
		goto Exit;
	}
	if ( S_Open_File( Program, 0, Hn ) != 0 ) {  // Open file
		goto Exit;
	}
	S_Move_File_Ptr( Hn, 0, 0x18 );
	if ( S_Read_Bytes( Ts, Hn, 2 ) != 0 ) {  // Read the relocation table offset
		goto Exit;
	}
	if( Svl( Ts ) != 2 ) {
		goto Exit;
	}
	Lo = Ascii( Str_Char( Ts, 1 ) ) + ( Ascii( Str_Char( Ts, 2 ) ) << 8 );
	if ( Lo != 0x40 ) {                   // No new header
		Result = _Exe_Id_Dos;
	}
	else {
		S_Move_File_Ptr( Hn, 0, 0x06 );
		if ( S_Read_Bytes( Ts, Hn, 2 ) != 0 ) {  // Read the number of relocations
			goto Exit;
		}
		if( Svl( Ts ) != 2 ) {
			goto Exit;
		}
		Lo = Ascii( Str_Char( Ts, 1 ) ) + ( Ascii( Str_Char( Ts, 2 ) ) << 8 );
		if ( Lo != 0 ) {                    // Bound executable when relocations > 0
			Bound = _Exe_Id_Bound;
		}

		S_Move_File_Ptr( Hn, 0, 0x3C );
		if ( S_Read_Bytes( Ts, Hn, 4 ) != 0 ) {  // Read file address of new header
			goto Exit;
		}
		if( Svl( Ts ) != 4 ) {
			goto Exit;
		}
		Lo = Ascii( Str_Char( Ts, 1 ) ) + ( Ascii( Str_Char( Ts, 2 ) ) << 8 );
		Hi = Ascii( Str_Char( Ts, 3 ) ) + ( Ascii( Str_Char( Ts, 4 ) ) << 8 );
		Lo += Hi << 16;
		if ( Lo == 0 ) {
			goto Exit;
		}
		S_Move_File_Ptr( Hn, 0, Lo );
		if ( S_Read_Bytes( Ts, Hn, 2 ) != 0 ) {  // Read new header magic number
			goto Exit;
		}
		if( Svl( Ts ) != 2 ) {
			goto Exit;
		}
		switch ( Ts ) {

			case "NE" :                       // 16bit segmented header
				S_Move_File_Ptr( Hn, 1, 0x0A );
				if ( S_Read_Bytes( Ts, Hn, 2 ) != 0 ) {  // Read new flags
					goto Exit;
				}
				if( Svl( Ts ) != 2 ) {
					goto Exit;
				}
				Hi = Ascii( Str_Char( Ts, 1 ) ) + ( Ascii( Str_Char( Ts, 2 ) ) << 8 );
				S_Move_File_Ptr( Hn, 1, 0x28 );
				if ( S_Read_Bytes( Ts, Hn, 2 ) != 0 ) {  // Read os type
					goto Exit;
				}
				if( Svl( Ts ) != 2 ) {
					goto Exit;
				}
				Lo = Ascii( Str_Char( Ts, 1 ) );
				switch ( Lo ) {

					case 1 :                      // 16bit OS/2 (PMode DOS)
						if ( Bound && ( ( Hi & 0x0808 ) == 0x08 ) ) {  // Borland PMode
							if ( !( Ascii( Str_Char( Ts, 2 ) ) & 0x01 ) ) { // Longnames?
								Bound = _Exe_Id_Unknown;
								Result = _Exe_Id_Dos;
								break;
							}
						}
						Result = _Exe_Id_Os2;
						break;

					 case 2 :                     // 16bit Windows
						Result = _Exe_Id_Windows;
						break;

					 case 5 :                     // Borland PMode
					 case 0x81 :                  // Blinker DOS Extender
						Bound = _Exe_Id_Unknown;
						Result = _Exe_Id_Dos;
						break;
				}
				break;

			case "LX" :                       // 32bit header (OS/2)
				S_Move_File_Ptr( Hn, 1, 0x08 );
				if ( S_Read_Bytes( Ts, Hn, 1 ) != 0 ) {  // Read os type
					goto Exit;
				}
				if ( Svl( Ts ) != 1 ) {
					goto Exit;
				}
				Lo = Ascii( Str_Char( Ts, 1 ) );
				switch ( Lo ) {

					case 1 :                      // 32bit OS/2
						Result = _Exe_Id_Os2;
						S_Move_File_Ptr( Hn, 1, 0x6 );
						if ( S_Read_Bytes( Ts, Hn, 1 ) != 0 ) {
							goto Exit;
						}
						if ( Svl( Ts ) != 1 ) {
							goto Exit;
						}
						Lo = Ascii( Str_Char( Ts, 1 ) ) & 0x3;
						switch ( Lo ) {
							case 3 :
								Result |= _Exe_Id_GUI;
								break;

							case 2 :
								Result |= _Exe_Id_CUI;
								break;
						}
						break;
				}
				break;

			case "PE" :                       // NT header, Win32
				Result = _Exe_Id_Nt;
				S_Move_File_Ptr( Hn, 1, 0x5A );
				if ( S_Read_Bytes( Ts, Hn, 1 ) != 0 ) {
					goto Exit;
				}
				if ( Svl( Ts ) != 1 ) {
					goto Exit;
				}
				Lo = Ascii( Str_Char( Ts, 1 ) );
				switch ( Lo ) {
					case 2 :
						Result |= _Exe_Id_GUI;
						break;

					case 3 :
					case 5 :
						Result |= _Exe_Id_CUI;
						break;
				}
				break;
		}
		Result |= Bound;
	}
#ifdef _DEBUG_
   MessageF( "AppType=%x Program=%s", Result, Program );
#endif

Exit:
	if ( Hn != 0 ) {
		S_Close_File( Hn );
	}
	ExeType = Result;
	return ( Result );

}  // IdExe

int GetDosVersion( ) {
/******************************************************************************
															 Multi-Edit Macro
															 24-Aug-94  14:08

	Function: Returns the version number of the running OS. (Major, Minor).

	Entry   : None


	Exit    : int     - Version of running OS.
												(Major in High byte, Minor in Low byte)

	Globals : None.

	Macros  : None.

							 Copyright (C) 1995 by American Cybernectic, Inc.
**********************************************************************(ldh)***/


	int Result;

	Result = GetVersion( ) >> 16;

#ifdef _DEBUG_
	MessageF( "%x DOS %d.%d", Result, Result >> 8, Result & 0xFF );
#endif

	return ( Result );

}  // GetDosVersion

int IsOs2( ) {
/******************************************************************************
															 Multi-Edit Macro
															 24-Aug-94  14:08

	Function: Returns True if OS/2 is running.

							 Copyright (C) 1995 by American Cybernectic, Inc.
**********************************************************************(ldh)***/

	int Result = GetDosVersion( );
	if ( Result > 0x140A ) {
		Result = True;

#ifdef _DEBUG_
		MessageF( "OS/2 %d.%d is running.", ( R_AX & 0xFF ) / 10, R_AX >> 8 );
#endif
	}
	else {
		Result = False;

#ifdef _DEBUG_
	  Make_Message( "OS/2 is not running." );
#endif
	}
	return ( Result );

}  // IsOs2

void IdExeGetHdr( str Program = Parse_Str( "/P=", MParm_Str ) ) {
/******************************************************************************
															 Multi-Edit Macro
															 02-Feb-95  15:55

	Function: Read the header information from Program and write it to the
						IDEXE.BIN file.  This is used to help us identify programs that fail
						the IdExe classification tests and allow us to fix the macro to
						correctly identify Program.

							 Copyright (C) 1995 by American Cybernectics, Inc.
********************************************************************( ldh )***/

	int OrgWin = Window_Id;
	int TRefresh = Refresh;
	int HdrFileWin = 0;
	int Hn = 0;
	int Jx;
	int NewHdrAddr = 0;
	int FirstLine;

	str HdrFileName = TempFileName( "IDEXE.BIN" );
	str Buffer = "";

	program = GetShortName(program);
	Refresh = False;
	if ( !Switch_File( HdrFileName ) ) {
		Create_Window;
	}
	Fixed_Line_Length = 16;
	if ( File_Exists( HdrFileName ) ) {
		Error_Level = 0;
		Load_File( HdrFileName );
		if ( Error_Level != 0 ) {
			Error_Level = 0;
			Goto Exit;
		}
	}
	HdrFileWin = Window_Id;
	File_Name = HdrFileName;
	Eof;
	if ( C_Col != 1 ) {
		Cr;
	}
	FirstLine = C_Line;
	if ( S_Open_File( Program, 0, Hn ) == 0 ) {  // Open file
		Buffer = '--' + Caps( Truncate_Path( Program ) );
		Pad_Str( Buffer, 0x10, '-' );
		Put_Line( Buffer );
		Down;
		if ( S_Read_Bytes( Buffer, Hn, 0x40 ) != 0 ) {
			goto Exit;
		}
		if( Svl( Buffer ) != 0x40 ) {
			goto Exit;
		}
		Put_Line( Buffer );
		Down;
		Buffer = '';
		Pad_Str( Buffer, 0x10, '-' );
		Put_Line( Buffer );
		Down;
		Mark_Pos;
		Goto_Line( FirstLine + 1 );
		Goto_Col( 0x18 + 1 );
		if ( Cur_Char == "\x40" ) {
			Goto_Col( 0x3C + 1 );
			for ( Jx = 0; Jx < 4; ++Jx ) {
				NewHdrAddr += Ascii( Cur_Char ) << ( Jx * 8 );
				Right;
			}
		}
		Goto_Mark;
		if ( NewHdrAddr != 0 ) {
//       MessageF( "Addr=%x", NewHdrAddr );
			if ( S_Move_File_Ptr( Hn, 0, NewHdrAddr ) == 0 ) {
				if ( S_Read_Bytes( Buffer, Hn, 0x80 ) == 0 ) {
					if( Svl( Buffer ) == 0x80 ) {
						Put_Line( Buffer );
						Down;
						Buffer = '';
						Pad_Str( Buffer, 0x10, '-' );
						Put_Line( Buffer );
						Down;
					}
				}
			}
		}
	}

Exit:
	if ( File_Changed ) {
		Save_File;
	}
	if ( Hn != 0 ) {
		S_Close_File( Hn );
	}
	if ( Window_Id != OrgWin ) {
		Delete_Window;
	}
	Switch_Win_Id( OrgWin );
	Refresh = TRefresh;

}  // IdExeGetHdr

int IdBaseOs( ) {
/******************************************************************************
															 Multi-Edit Macro
															 25-May-95  12:33

  Function: Determine the Operating sytem that is running.

  Exit    : int
							_BaseOs_Unknown
							_BaseOs_Dos
							_BaseOs_Os2
							_BaseOs_Nt
							_BaseOs_Windows 	- Windows 95

							 Copyright (C) 1995 by American Cybernectic, Inc.
********************************************************************( ldh )***/

	int OsType = _BaseOs_Dos;
	int Flags;
	int Win;

	Flags = GetWinFlags( ) & 0x6000 ;
	if ( Flags == 0x4000 ) {
		OsType = _BaseOs_Nt;
	}
	else {
		Flags = GetVersion( );
		Win = ( ( Flags >> 8 ) & 0xFF ) | ( ( Flags & 0xFF ) << 8 );
		if ( Win >= 0x035F ) {
			OsType = _BaseOs_Windows;
		}
		else {
			if ( Flags >= 0x140A ) {
				OsType = _BaseOs_Os2;
			}
		}
	}

#ifdef _DEBUG_
	MessageF( "OsType=%x", OsType );
#endif

	return ( OsType );

}  // IdBaseOs