/*
 *	driver.c
 *
 *	Copyright (c) c't 2010 Andreas Stiller 
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 *
 * Installs 32 or 64 bit drivers, depending on OS or WoW64
 * In 64 Bit Mode: Signature Check must be switched off (during Boot per F8-Menue) 
 * or using testmode with testsignature
*/

#include "stdafx.h"
#include "driver.h"

BOOL FileExists(const char * filename)
{
return GetFileAttributes(filename) != 0xFFFFFFFF;
}



BOOL InstallandStartDriver(int apath, PCHAR driverfilename, PCHAR servicename)
{
	SC_HANDLE	hSc, hService;
	char		szPath[MAX_PATH];
	size_t		i;
	BOOL res=FALSE; 
	int retry=0;
	switch (apath) {
		case NoPath: strcpy (szPath,driverfilename); break; 
		case ExePath: 
			GetModuleFileName( NULL, szPath, MAX_PATH ); //szPATH=EXEpath\exename
			for( i = strlen( szPath ); i >= 0; i-- )
			{
				if( szPath[i] == '\\' )
				{
					szPath[i + 1] = 0;
					break;
				}
			}

			//szPATH=EXEpath\ 

			strcat(szPath, driverfilename);

			//szPATH="EXEpath\drivername"
			break; 
		case WinPath: 
			GetEnvironmentVariable("windir", szPath,MAX_PATH);
			strcat(szPath,"\\");
			strcat(szPath, driverfilename);
			break; 
		case SysPath: 
			GetEnvironmentVariable("windir", szPath,MAX_PATH);
			strcat(szPath,"\\system32\\");
			strcat(szPath, driverfilename);
			break;
	}
	printf (" %s \n",szPath);
	if (!FileExists (szPath)) return FALSE; 

	hSc = OpenSCManager( 
		NULL, 
		NULL, 
		SC_MANAGER_CREATE_SERVICE );

	if( !hSc )
	{
	
        printf (" Can't open SCManager\n");
		return FALSE;
	}
	do {
		retry++;
		hService = CreateService( 
			hSc, 
			servicename, 
			servicename, //displayname=servicename 
			SERVICE_ALL_ACCESS, 
			SERVICE_KERNEL_DRIVER, 
			SERVICE_DEMAND_START, 
			SERVICE_ERROR_NORMAL, 
			szPath, 
			NULL, 
			NULL, 
			NULL, 
			NULL, 
			NULL );
		if (hService) CloseServiceHandle ( hService ); 
		//else printf ("Can't create Service\n");

		if( hService  || (GetLastError() == ERROR_SERVICE_EXISTS)) {

			hService = OpenService( 
				hSc, 
				servicename, 
				SERVICE_START );

			if( hService ) {
				res = (StartService( hService, 0, NULL ) || (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING));
				CloseServiceHandle( hService );
			}
			else printf ("Can't start service");
                  
			
		}
		else if (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE) {
			UninstallDriver(servicename); 

		}
	} while (!hService && retry < 2); 

		CloseServiceHandle( hSc );	

	return res;
}

BOOL StartDriver(PCHAR servicename)
{
	SC_HANDLE	hSc, hService;
	BOOL res=FALSE;

	hSc = OpenSCManager( 
		NULL, 
		NULL, 
		SC_MANAGER_CREATE_SERVICE );

	if( hSc == NULL )
		return FALSE;

	hService = OpenService( 
		hSc, 
		servicename, 
		SERVICE_START );
    CloseServiceHandle( hSc );
	if( !hService ) return FALSE;
    res = (StartService( hService, 0, NULL )|| (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING));
    CloseServiceHandle ( hService ); 
	return res ;
}

BOOL UninstallDriver(PCHAR servicename)
{
	SC_HANDLE		hSc, hService;
	SERVICE_STATUS	ss;
	BOOL res=FALSE;
	hSc = OpenSCManager( 
		NULL, 
		NULL, 
		SC_MANAGER_CREATE_SERVICE );

	if( hSc == NULL )
		return FALSE;

	hService = OpenService( 
		hSc, 
		servicename, 
		SERVICE_ALL_ACCESS );

	if( !hService )
	{
		CloseServiceHandle( hSc );

		return FALSE;
	}

	ControlService( hService, SERVICE_CONTROL_STOP, &ss );
    res= DeleteService( hService );
    CloseServiceHandle ( hService );
	CloseServiceHandle ( hSc );
  	return res;
}
