#include <pharlap.h>
#include <windows.h>
#include "tntapi.h"

typedef void (*FUNCPTR)();

BOOL WINAPI my_GetComputerName (LPSTR lpBuffer, LPDWORD nSize);
BOOL (WINAPI *gcn_ptr)(LPSTR lpBuffer, LPDWORD nSize);

BOOL WINAPI my_SetComputerName (LPSTR lpBuffer);
BOOL (WINAPI *scn_ptr)(LPSTR lpBuffer);

VOID WINAPI my_GetSystemInfo(LPSYSTEM_INFO lpSystemInfo);
VOID (WINAPI *gsi_ptr)(LPSYSTEM_INFO lpSystemInfo);

DWORD WINAPI my_GetVersion(VOID);
DWORD (WINAPI *gv_ptr)(VOID);

UINT WINAPI my_GetWindowsDirectory(LPTSTR lpszWinPath, UINT cchWinPath);
UINT (WINAPI *wd_ptr)(LPTSTR lpszWinPath, UINT cchWinPath);

UINT WINAPI my_GetSystemDirectory(LPTSTR lpszWinPath, UINT cchWinPath);
UINT (WINAPI *sd_ptr)(LPTSTR lpszWinPath, UINT cchWinPath);

void __STKCALL WriteStr(char *pStr);

BOOL WINAPI my_GetComputerName (LPSTR lpBuffer, LPDWORD nSize)
{
/*
	replacement API function

	use the TNT DOS-Extender "Get Machine Name" (5e00h) system
        call to get the machine name under Microsoft Networks
	This will work only if Microsoft Networks is installed.  If
	a different network is installed, see if it provides a
	comparable function.

	return TRUE and name in lpBuffer if name is defined
	return FALSE and null in lpBUffer if name is not defined

*/

	int retcode = 0;
	char name_defined =0;


	_asm
	{
		mov	ax, 0x5e00
		mov	edx, lpBuffer
                int	0x21
                jnc	all_ok
                mov	word ptr retcode,ax
		jmp	all_done
	all_ok:
		mov	name_defined,ch
	all_done:
	}

	if (retcode || !name_defined )
	{
		lpBuffer[0] = (char) NULL;
		*nSize = 0;
	}
	else
		*nSize = sizeof(lpBuffer);

	if (!retcode)
		return TRUE;
	else
		return FALSE;
}

BOOL WINAPI my_SetComputerName (LPSTR lpBuffer)
{
/*
	replacement API function

	use the TNT DOS-Extender "Set Machine Name" (5e01h) system
        call to set the machine name under Microsoft Networks
	This will work only if Microsoft Networks is installed.  If
	a different network is installed, see if it provides a
	comparable function.

	return TRUE if successful
	return FALSE if not successful

*/

	int retcode = 0;
	char name_defined =0;

	if (sizeof(lpBuffer) > MAX_COMPUTERNAME_LENGTH)
		return FALSE;

	_asm
	{
		mov	ax, 0x5e01
		mov	esi, lpBuffer
		mov 	ch, 1
		mov	cl, 1 
                int	0x21
                jnc	all_ok
                mov	word ptr retcode,ax
	all_ok:
	}

	if (retcode == 0)
		return TRUE;
	else
		return FALSE;
}

VOID WINAPI my_GetSystemInfo(lpSystemInfo)

LPSYSTEM_INFO lpSystemInfo;	/* address of system info. structure */

/*   Call the TNT DOS-Extender function _dx_config_inf in DOSX32.LIB to
     get the available system information.  Where there is no comparable
     function, return 0
*/

{
	CONFIG_INF config_inf;

	_dx_config_inf(&config_inf, (UCHAR *)&config_inf);

	lpSystemInfo->dwOemId = 0;   // no equivalent TNT call
	lpSystemInfo->dwPageSize = 4*1024; // TNT page size is 4K
	lpSystemInfo->lpMinimumApplicationAddress = (void *)config_inf.c_minext;
	lpSystemInfo->lpMaximumApplicationAddress = (void *)config_inf.c_maxext;
	lpSystemInfo->dwActiveProcessorMask = 1; // TNT supports 1 processor
	lpSystemInfo->dwNumberOfProcessors = 1;  // TNT supports 1 processor
	switch (config_inf.c_processor)
 	{
	   case 3 : lpSystemInfo->dwProcessorType = PROCESSOR_INTEL_386;
		    break;
	   case 4 : lpSystemInfo->dwProcessorType = PROCESSOR_INTEL_486;
		    break;
 	  default : break;
	}
}
DWORD WINAPI my_GetVersion(VOID)

/*  This is only partially equivalent to the Win32 GetVersion().  
    TNT DOS-Extender does not distinguish between Windows 3.x and
    Windows NT.  The spec for GetVersion() is that the high word
    contains information about the operating system platform.  The
    high bit is 0 for Windows NT and 1 for Windows 3.1.  There is no
    way to specify a non-Windows environment.  We set the low word
    to 0 for Windows not-present.
*/

{
	
	CONFIG_INF config_inf;
	DWORD retval;

	_dx_config_inf(&config_inf, (UCHAR *)&config_inf);
	switch (config_inf.c_windowsf)
	{
	  case 0 : // Windows not present
		   retval=0;
		   break;
	case 1 :   // Windows present;
                  //  TNT doesn't differentiate between 3.x and NT
		   retval = MAKELONG(
                               MAKEWORD(config_inf.c_winmaj,
                                        config_inf.c_winmin),
                               0x8000);
		   break;
	 default : break;
	}
}

UINT WINAPI my_GetWindowsDirectory(lpszWinPath, cchWinPath)

LPTSTR lpszWinPath;	/* address of buffer for Windows directory */
UINT cchWinPath;	/* size of directory buffer	*/

{

/*  Call GetEnvironmentVariable to find the value of "windir" -- this
    will be the correct directory for the Windows directory.
    GetEnvironmentVariable is implemented by TNT DOS-Extender.
*/

	return(GetEnvironmentVariable("windir",lpszWinPath, cchWinPath));
}

UINT WINAPI my_GetSystemDirectory(lpszWinPath, cchWinPath)

LPTSTR lpszWinPath;     /* address of buffer for Windows directory */
UINT cchWinPath;        /* size of directory buffer     */

{

/*  Call GetEnvironmentVariable to find the value of "windir" -- this
    will be the correct directory for the Windows directory.
    GetEnvironmentVariable is implemented by TNT DOS-Extender.  We
    assume the system directory is the \SYSTEM subdirectory in the
    Windows directory.  This may not always be true.
*/
	UINT charcount;

        charcount = GetEnvironmentVariable("windir",lpszWinPath, cchWinPath);

	if (charcount != 0)
	{
		strcat(lpszWinPath, "\\SYSTEM");
		return strlen(lpszWinPath);
	}
	else
		return charcount;
}

BOOL WINAPI DllEntryPoint(HINSTANCE DllHandle, DWORD Reason, LPVOID reserved)
{
HMODULE dll_handle;

    switch (Reason)
    {
        case DLL_PROCESS_ATTACH :
             // get function pointer to existing Virtual Alloc()
             dll_handle = GetModuleHandle("kernel32.dll");
             if (dll_handle == NULL)
                {
                    WriteStr("could not get handle of dll\n$");
                    return FALSE;
                }
             gcn_ptr = (LPVOID) GetProcAddress(dll_handle,"GetComputerNameA");
             if (gcn_ptr == NULL)
                {
                    WriteStr("could not get address of GetComputerName\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "GetComputerNameA", (FUNCPTR) my_GetComputerName))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             scn_ptr = (LPVOID) GetProcAddress(dll_handle,"SetComputerNameA");
             if (scn_ptr == NULL)
                {
                    WriteStr("could not get address of SetComputerName\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "SetComputerNameA", (FUNCPTR) my_SetComputerName))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             gsi_ptr = (LPVOID) GetProcAddress(dll_handle,"GetSystemInfo");
             if (gsi_ptr == NULL)
                {
                    WriteStr("could not get address of GetSystemInfo\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "GetSystemInfo", (FUNCPTR) my_GetSystemInfo))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             gv_ptr = (LPVOID) GetProcAddress(dll_handle,"GetVersion");
             if (gv_ptr == NULL)
                {
                    WriteStr("could not get address of GetVersion\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "GetVersion", (FUNCPTR) my_GetVersion))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             wd_ptr = (LPVOID) GetProcAddress(dll_handle,"GetWindowsDirectoryA");
             if (wd_ptr == NULL)
                {
                    WriteStr("could not get address of GetWindowsDirectory\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "GetWindowsDirectoryA", (FUNCPTR) my_GetWindowsDirectory))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             sd_ptr = (LPVOID) GetProcAddress(dll_handle,"GetSystemDirectoryA");
             if (sd_ptr == NULL)
                {
                    WriteStr("could not get address of GetSystemDirectory\n$");
                    return FALSE;
                }
             // install the new (trace) function
             if (!SetProcAddress(dll_handle, "GetSystemDirectoryA", (FUNCPTR) my_GetSystemDirectory))
                {
                    WriteStr("error from SetProcAddress\n$");
                    return FALSE;
                }
             break;
        case DLL_PROCESS_DETACH :
             break;
        case DLL_THREAD_ATTACH :  
             break;
        case DLL_THREAD_DETACH :  
             break;
        default :
             break;
    }
    return TRUE;
}

void WriteStr(char *pStr)
{
        _asm {
                push    edx
                mov     edx,pStr
                mov     ah,9
                int     21h
                pop     edx
        }
        return;
}
