//---------------------------------------------------------------------------

#pragma hdrstop

#include "win.h"
#include <stdio.h>
// #include <mem.h>
#include "..\..\api.h"
//#include "NTSTATUS.H"

char OS_String[0x100];

char SysDriverFileName[]    =   "ktapi.sys";
char DriverName[]           =   "ktapi";

#define STATUS_INVALID_PAGE_PROTECTION   (0xC0000045)
#define STATUS_CONFLICTING_ADDRESSES     (0xC0000018)
#define STATUS_SECTION_PROTECTION        (0xC000004E)
#define STATUS_SUCCESS                          (0x00000000) // ntsubauth

//---------------------------------------------------------------------------
//#pragma package(smart_init)

BOOL InstalledDriver=FALSE;

BOOL CopyDriver(PCHAR DRV_NAME);

/*
DWORDLONG AvailVirtualMemDump(char * String)
{
  MEMORYSTATUSEX statex;

  statex.dwLength = sizeof (statex);

  GlobalMemoryStatusEx (&statex);

  printf ("%s AvailVirtual %ld\n",String,statex.ullAvailVirtual);
  return statex.ullAvailVirtual;
}
*/

VOID UnMapMem(void * PartyMem)
{
void * pPartyMem;

	pPartyMem=PartyMem;

	TalkToDriver(IOCTL_KTAPI_DRV_UNMEMMAP,&pPartyMem,sizeof(PVOID));
}

PUCHAR MapMem(DWORD offset,DWORD nbytes)
{
    unsigned long DriverStatus;

    //char str[1024] = {0};
    //char line[4];
    PHYSICAL_MEMORY_INFO pmi;
    DWORD                cbReturned;
    ULONG                length;
    PVOID                IOBUF;

    pmi.InterfaceType       = (ULONG) 1;
    pmi.BusNumber           = (ULONG) 0;
    pmi.BusAddress.HighPart = (LONG)  0x00000000;
    pmi.AddressSpace        = (ULONG) 0;

    pmi.BusAddress.LowPart = offset;
    pmi.Length = nbytes-1;

    IOBUF = &pmi;
    DriverStatus = TalkToDriver(IOCTL_KTAPI_DRV_MEMMAP,IOBUF,sizeof(PHYSICAL_MEMORY_INFO));

    //pPartyMem = ((PUCHAR) (*(PULONG)IOBUF));
	return  ((PUCHAR) (*(PULONG)IOBUF));

    //return  pPartyMem;
}


DWORD InitializeDriver(VOID)
{
	CHAR DRV_PATH[MAX_PATH] = {0};
	ULONG STATUS = 0;
	ULONG RESULT = 1;
	SC_HANDLE   schSCManager;

	schSCManager = OpenSCManager (NULL,NULL,SC_MANAGER_ALL_ACCESS);
	
	if (schSCManager!=INVALID_HANDLE_VALUE)
	{
		InstalledDriver=TRUE;
		
		GetSystemDirectory(DRV_PATH,sizeof(DRV_PATH));
		strcat(DRV_PATH,"\\drivers\\");
		strcat(DRV_PATH,SysDriverFileName);
		
		//    printf("\nSTART1 %s\n",DRV_PATH);
		
		if (!IsDriverOnDisk(DRV_PATH))
		CopyDriver(DRV_PATH);
		
		//CreateDriver(DRV_PATH);
		
		
		
		//    printf("\nSTART2 %s ",DRV_PATH);
		
		RESULT = InstallDriver(schSCManager,DriverName,DRV_PATH);
		//      printf("\nINST %d",RESULT);
		
		
		RESULT = StartDriver(schSCManager,DriverName);
		//      printf("\nSTART %d",RESULT);
		
		//EnableRealTime(TRUE);
		
		CloseServiceHandle (schSCManager);
    }
    else
    {
//    	printf("\nOpenSCManager Fail");
    	InstalledDriver=FALSE;
    }

   return RESULT;
}

DWORD UninitializeDriver(VOID)
{
   SC_HANDLE   schSCManager;
   ULONG RESULT = 1;

	if (InstalledDriver)      
	{
		
		schSCManager = OpenSCManager (NULL,NULL,SC_MANAGER_ALL_ACCESS);
		if (schSCManager!=INVALID_HANDLE_VALUE)
		{
		
			RESULT = StopDriver   (schSCManager,DriverName);
			//      printf("\nSTOP %d",RESULT);
			
			RESULT = RemoveDriver (schSCManager,DriverName);
			//      printf("\nREMOVE %d",RESULT);
			
			CloseServiceHandle (schSCManager);
		}
		else
		{
			printf("\nOpenSCManager Fail");
		}
		
	}
	
	return RESULT;
}

HANDLE   hKTAPI=((HANDLE)-1);

UCHAR TalkToDriver(DWORD IOCTL_CODE,PVOID IOBUF,DWORD DATA_SIZE)
{
    char     completeDeviceName[80] = {0};
    BOOL     ret;
    DWORD    ReturnedLength;     // Number of bytes returned
    BOOL     IoctlResult;
    char str[40];

	/*
    strcat (completeDeviceName,"\\\\.\\");

    strcat (completeDeviceName,DriverName);

    hKTAPI = CreateFile (completeDeviceName,
                           GENERIC_READ,
                           FILE_SHARE_READ,
                           NULL,
                           OPEN_EXISTING,
                           0,
                           NULL);

    if (hKTAPI == ((HANDLE)-1))
    {
        ret = FALSE;
        printf("\nDRIVER ERROR!");
        //printf("Unable to create %s",completeDeviceName);
        //getch();
    }

    else
    {
	  */
         IoctlResult = DeviceIoControl(
                            hKTAPI,            // Handle to device
                            IOCTL_CODE,         // IO Control code for Read
                            IOBUF,              // Buffer to driver.
                            DATA_SIZE,          // Length of buffer in bytes.
                            IOBUF,              // Buffer from driver.
                            DATA_SIZE,          // Length of buffer in bytes.
                            &ReturnedLength,    // Bytes placed in DataBuffer.
                            NULL );             // NULL means wait till op. completes.

		/*

        CloseHandle (hKTAPI);

        ret = TRUE;
    }
		  */
    return TRUE;

}


BOOL InstallDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName, LPCTSTR ServiceExe)
{
    SC_HANDLE  schService;
    DWORD      err;

    //
    // NOTE: This creates an entry for a standalone driver. If this
    //       is modified for use with a driver that requires a Tag,
    //       Group, and/or Dependencies, it may be necessary to
    //       query the registry for existing driver information
    //       (in order to determine a unique Tag, etc.).
    //

//    printf("name=%s",DriverName);

    schService = CreateService (SchSCManager,          // SCManager database
                                DriverName,            // name of service
                                DriverName,            // name to display
                                SERVICE_ALL_ACCESS,    // desired access
                                SERVICE_KERNEL_DRIVER, // service type
                                SERVICE_DEMAND_START,  // start type
                                SERVICE_ERROR_NORMAL,  // error control type
                                ServiceExe,            // service's binary
                                NULL,                  // no load ordering group
                                NULL,                  // no tag identifier
                                NULL,                  // no dependencies
                                NULL,                  // LocalSystem account
                                NULL                   // no password
                                );

    if (schService == NULL)
    {
	    //printf("\nCreateService FAILD!");
        //Return false for failure
        return FALSE;
    }

    CloseServiceHandle (schService);

    //Return true for SUCCESS
    return TRUE;
}

BOOL RemoveDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName)
{
    SC_HANDLE  schService;
    BOOL       ret;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                              );

    if (schService == NULL)
    {
        return FALSE;
    }

    ret = DeleteService (schService);

    CloseServiceHandle (schService);

    return ret;
}

BOOL StartDriver(IN SC_HANDLE SchSCManager, LPCTSTR DriverName)
{
    SC_HANDLE  schService;
    BOOL       ret;
    DWORD      err;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                              );

    if (schService == NULL)
    {
        return FALSE;
    }

    ret = StartService (schService,    // service identifier
                        0,             // number of arguments
                        NULL           // pointer to arguments
                        );

    CloseServiceHandle (schService);

    return ret;
}

BOOL StopDriver(SC_HANDLE SchSCManager, LPCTSTR DriverName)
{
    SC_HANDLE       schService;
    BOOL            ret;
    SERVICE_STATUS  serviceStatus;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                              );

    if (schService == NULL)
    {
        return FALSE;
    }

    ret = ControlService (schService,
                          SERVICE_CONTROL_STOP,
                          &serviceStatus
                          );

    CloseServiceHandle (schService);

    return ret;
}

BOOL IsDriverOnDisk(PCHAR DRV_NAME)
{
   FILE *Handle;

   if ((Handle = fopen(DRV_NAME,"rb")) == NULL)
      return FALSE;
   else
   {
      fclose(Handle);
      return TRUE;
   }
}

BOOL CopyDriver(PCHAR DRV_NAME)
{

	 CopyFile("ktapi.sys",DRV_NAME,FALSE);
  	 return TRUE;
}

DWORDLONG MemStart;
DWORDLONG MemEnd;


int OS_Init(void)
{
    DWORD dwVersion = 0; 
	DWORD dwMajorVersion = 0;
	DWORD dwMinorVersion = 0; 
	DWORD dwBuild = 0;

	char     completeDeviceName[80] = {0};
    BOOL     ret;
    DWORD    ReturnedLength;     // Number of bytes returned
    BOOL     IoctlResult;
    char str[40];

	//MemStart=AvailVirtualMemDump(__FUNCTION__);
	
    dwVersion = GetVersion();
 
    // Get the Windows version.

    dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
    dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));

    // Get the build number.

    if (dwVersion < 0x80000000)              
        dwBuild = (DWORD)(HIWORD(dwVersion));
	
	sprintf(OS_String,"Windows %d.%d.%d",dwMajorVersion,dwMinorVersion,dwBuild);
	
    strcat (completeDeviceName,"\\\\.\\");

    strcat (completeDeviceName,DriverName);
	//OutputDebugString("OS_Init");

    hKTAPI = CreateFile (completeDeviceName,
                           GENERIC_READ,
                           FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           0,
                           NULL);
                           
	if (hKTAPI==INVALID_HANDLE_VALUE)
	{
		// try to start/install the driver
		//OutputDebugString("try to start/install the driver");
		
		InitializeDriver();    
		
	    hKTAPI = CreateFile (completeDeviceName,
	                           GENERIC_READ,
	                           FILE_SHARE_READ,
	                           NULL,
	                           OPEN_EXISTING,
	                           0,
	                           NULL);
	
	}
	

	return hKTAPI!=INVALID_HANDLE_VALUE;
}

void OS_Deinit(void)
{
	if (hKTAPI!= INVALID_HANDLE_VALUE)
	{
        CloseHandle (hKTAPI);
	}

	UninitializeDriver();

	//MemEnd=AvailVirtualMemDump(__FUNCTION__);
	
	//printf("Memused %d\n",MemStart-MemEnd);
	
	
}


void *OS_Alloc_Execute_Read_Write(unsigned int Size)
{
void * Temp;
	//AvailVirtualMemDump(__FUNCTION__);

	//Size+=0x1000;
	
	Temp=VirtualAlloc(NULL,Size,MEM_COMMIT|MEM_TOP_DOWN ,PAGE_EXECUTE_READWRITE);
	
	//printf("OS_Alloc_Execute_Read_Write %08x @ %08x\n",Size,Temp);

	return Temp;
}
void   OS_Free_Execute_Read_Write(void * Adr,unsigned int Size)
{
BOOL bSuccess;   

	
	//printf("OS_Free_Execute_Read_Write %08x @ %08x\n",Size,Adr);

	Size;
//	VirtualFree(Adr,0,MEM_RELEASE);
	bSuccess=VirtualFree(Adr,0,MEM_RELEASE);
	//printf("%s\n",bSuccess ? "OK" : "Failed");	
	
	//AvailVirtualMemDump(__FUNCTION__);
	
}

void * OS_Memory_Allocate(unsigned long Size)
{
void * Temp;
/*
unsigned long SizePage;
SYSTEM_INFO sSysInfo;    
   
	AvailVirtualMemDump(__FUNCTION__);
   
	GetSystemInfo(&sSysInfo); 
	
	SizePage=Size + (sSysInfo.dwPageSize-1);
	SizePage&=~(sSysInfo.dwPageSize-1);
	
	
	SizePage+=sSysInfo.dwPageSize;
	
	
	printf("Size %08x - %08x\n",Size,SizePage);
	
   */
	Temp=(void *) VirtualAlloc(NULL,Size,MEM_COMMIT,PAGE_READWRITE);

	//printf("OS_Memory_Allocate %08x @ %08x\n",Size,Temp);
	
	return Temp;
}

void   OS_Memory_Free(void * Adr,unsigned long Size)
{
BOOL bSuccess;   

	Size;
	//printf("OS_Memory_Free %08x @ %08x\n",Size,Adr);
	

	//VirtualFree((void *)Adr,(unsigned long)0,MEM_RELEASE);
	bSuccess=VirtualFree(Adr,0,MEM_RELEASE);
	//printf("%s\n",bSuccess ? "OK" : "Failed");
	
	//AvailVirtualMemDump(__FUNCTION__);

	
}

void * OS_Physical_Memory_Map(void * Adr,unsigned long Size)
{
    unsigned long DriverStatus;

    PHYSICAL_MEMORY_INFO pmi;
    DWORD                cbReturned;
    ULONG                length;
    PVOID                IOBUF;

    pmi.InterfaceType       = (ULONG) 1;
    pmi.BusNumber           = (ULONG) 0;
    pmi.BusAddress.HighPart = (LONG)  0x00000000;
    pmi.AddressSpace        = (ULONG) 0;

    pmi.BusAddress.LowPart =(unsigned long) Adr;
    pmi.Length = Size-1;

    IOBUF = &pmi;
    DriverStatus = TalkToDriver(IOCTL_KTAPI_DRV_MEMMAP,IOBUF,sizeof(PHYSICAL_MEMORY_INFO));

	return  ((PUCHAR) (*(PULONG)IOBUF));

}

void  OS_Physical_Memory_Unmap(void * Adr,unsigned long Size)
{
//void * pPartyMem;

unsigned __int64 pPartyMem;

	Size;
	pPartyMem=(unsigned __int64)Adr;

	TalkToDriver(IOCTL_KTAPI_DRV_UNMEMMAP,&pPartyMem,sizeof(unsigned __int64));

}




unsigned int OS_Execute_IO_Block(_API_IO_Struct * IO_Block,unsigned int Size)
{

    DWORD    ReturnedLength;     // Number of bytes returned
    BOOL     IoctlResult;
	unsigned int Val;
	
	ReturnedLength=0;
	Val=0;


         IoctlResult = DeviceIoControl(
                            hKTAPI,            // Handle to device
                            IOCTL_KTAPI_DRV_IO_BLOCK,         // IO Control code for Read
                            IO_Block,              // Buffer to driver.
                            Size,          // Length of buffer in bytes.
                            &Val,              // Buffer from driver.
                            4,          // Length of buffer in bytes.
                            &ReturnedLength,    // Bytes placed in DataBuffer.
                            NULL );             // NULL means wait till op. completes.

	return (unsigned int)Val;

}


int OS_Microsecond_Delay(unsigned int DelayCount)
{
	return _API_se_Error;
}

int OS_CPUID(_API_ASM_REGS_Struct * _API_ASM_REGS)
{
	_API_ASM_REGS->_EAX=0;
	_API_ASM_REGS->_EBX=0;
	_API_ASM_REGS->_ECX=0;
	_API_ASM_REGS->_EDX=0;
	return _API_se_Error;
}
int OS_Read_MSR(_API_ASM_REGS_Struct * _API_ASM_REGS)
{
	_API_ASM_REGS->_EAX=0;
	_API_ASM_REGS->_EBX=0;
	_API_ASM_REGS->_ECX=0;
	_API_ASM_REGS->_EDX=0;
	return _API_se_Error;
}

int OS_Write_MSR(_API_ASM_REGS_Struct * _API_ASM_REGS)
{
	_API_ASM_REGS->_EAX=0;
	_API_ASM_REGS->_EBX=0;
	_API_ASM_REGS->_ECX=0;
	_API_ASM_REGS->_EDX=0;
	return _API_se_Error;
}
