	             _         __ _               _                        _ 
	            | |       / _(_)             | |                      | |
	  __ _ _   _| |_ ___ | |_ _ _ __ ___     | | _____ _ __ _ __   ___| |
	 / _` | | | | __/ _ \|  _| | '__/ _ \    | |/ / _ \ '__| '_ \ / _ \ |
	| (_| | |_| | || (_) | | | | | |  __/    |   <  __/ |  | | | |  __/ |
	 \__,_|\__,_|\__\___/|_| |_|_|  \___|    |_|\_\___|_|  |_| |_|\___|_|
                                                                  


    -- [ programmation kernel pour un autofire !
 


	a/ readme
	b/ codes sources 
	c/ annexes pour la suite des codes


Place a l'article!

	a/ readme

I - c'est quoi cette bete là ?
------------------------------

Cette bestiole, c'est une petite démo de programmation noyau
pour windows. Le driver s'accroche à la gestion de la souris,
et simule un autofire comme sur nos bons vieux joysticks. Quand
vous cliquez gauche et laissez appuyé, le driver envoie des
signaux (pas clic) / (clic) en rafale.

Utilité ? Rendre impossible les parties de solitaire, déja.
Forcément, le cliquer-glisser ne marche plus car le clic long
se transforme en rafale de clic courts. Rendre galère la
navigation sous windows, vous lancez des applis au lieu de
sélectionner l'icone et des choses du genre.

Plus sérieusement, un ami m'avait demandé un truc de ce genre
il y a un moment, pour... tricher aux FPS ! pour les armes qui
gèrent mal le rate of fire maximal, c'est pas mal du tout.
Essayez dans un hélico à Battlefield 2, c'est marrant.



II - limitations et bugs
------------------------

Je ne suis pas une brute de programmation noyau.

Voila, c'est dit :)

Donc c'est plus histoire de faire profiter de mes petits délires
persos. Le programme est tributaire des messages souris existants.
Ca veut dire que quand la souris ne bouge pas, pas de message, donc
l'autofire n'agit pas. C'est comme orangina, il faut secouer pour
que ca pete. En jeu, ca ne gene pas car la souris reste rarement
immobile, pour viser ou piloter ca bouge tout le temps.

Autre limitation : je n'ai pas encore trouvé comment ne pas faire
planter le driver lorsqu'on veut le décharger. Donc quand vous voudrez
cliquer sur "arreter" pour reprendre une utilisation normale de votre pc...
attendez vous à un plantage. Et quand un driver plante, c'est pas une
belle boite de dialogue sympa, c'est un ecran bleu. Désolé :p


III - utilisation
-----------------

Appli est mon centre de test de drivers. C'est pas fait pour etre
super convivial, désolé. Pour vous éviter des tracas, vla la marche
à suivre pour aller au plus simple :

1) copiez les 2 fichiers du répertoire Toys vers c:\
2) lancez appli.exe
3) cliquez sur enregistrement
4) cliquez sur lancement

5) et quand vous en aurez marre, cliquez sur arrêt
6) ensuite, ou apres un reboot, revenez cliquer sur suppression

voila. Si, ô lecteur, tu as des infos sur comment gérer ces !#@!!%$ IRP
de maniere à ce que ca ne plante plus à la fin, sache que je suivrais
tes conseils avec gratitude !





	b/ codes sources 



				- driver_management.cpp - 

#include "stdafx.h"
#include "appli.h"
#include "appliDlg.h"

#include "Winsvc.h"
#include "driver_management.h"
#include "Windows.h"

//Vérifie le status du driver ==========================================================
int verifie_status (char* nom_court)
{
	//Ouvre le service manager
	HANDLE hSCManager = OpenSCManager(
		NULL,										//lpMachineName
		NULL,										//lpDatabaseName
		SC_MANAGER_ENUMERATE_SERVICE				//dwDesiredAccess
		);

	//Ouvre le service
	HANDLE hFile = OpenService(
		 hSCManager,
		 nom_court,
		 SC_MANAGER_ENUMERATE_SERVICE
		 );
         
	//Si on y a pas accédé, alors cassos !
	if(hFile == NULL)
	{
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_STATUS_ABSENT;
	}

	//Chope les informations sur le driver
	SERVICE_STATUS les_infos;
	QueryServiceStatus(
		hFile,								//hService
		&les_infos							//lpServiceStatus
		);

	//Nettoyage
	CloseServiceHandle(hSCManager);
	CloseServiceHandle(hFile);

	//Et selon les infos, cassos
	switch (les_infos.dwCurrentState)
	{
		case SERVICE_STOPPED:
			return DRIVER_MANAGER_STATUS_INACTIF;
		default:
			return DRIVER_MANAGER_STATUS_ACTIF;
	}
}


// Teste l'existance d'un fichier ======================================================
BOOL IsFileExist(LPSTR lpszFilename)
{
	DWORD dwAttr = GetFileAttributes(lpszFilename);
	if (dwAttr == 0xffffffff)
		return FALSE;
	else 
		return TRUE;
}


// Appel à IO Ctrl =====================================================================
bool ioctrl_driver (char* nom_dos, char*message, DWORD io_type, char*buffer, unsigned long *taille )
{
	char buffer1[1024];
	DWORD taille1;
	
	//Calcule la taille à envoyer
	taille1 = strlen(message);
	if (taille1 > 1023)
		taille1 = 1023;
		
	//Et recopie le message venant de ioctrl dans le buffer
	memset(buffer1,0, 1024);
	memcpy(buffer1,message,taille1);


	//Accède au driver
	HANDLE hFile = CreateFile(
		 nom_dos, 
         GENERIC_READ | GENERIC_WRITE,
		 0, 
		 NULL, 
         OPEN_EXISTING, 
		 0, 
		 NULL
		 );

	//Si on y a pas accédé, alors cassos !
	if(hFile == INVALID_HANDLE_VALUE)
		return false;

	//Sinon initialise le buffer et Action !
	memset(buffer,0, *taille);
	DeviceIoControl(hFile,
                       io_type, 
                       buffer1, 
                       1024, 
                       buffer, 
                       1024, 
                       taille, 
                       NULL);

	//Ferme l'accès au driver
	CloseHandle(hFile);
	return true;
}


// Appel à Write =======================================================================
bool ecris_driver (char* nom_dos, char*message )
{
	//Prépare le buffer d'envoi
	char buffer[1024];
	int taille;
	memset(buffer,0,1024);
	
	//Calcule la taille du message
	taille = strlen(message);
	if (taille > 1023)
		taille = 1023;
		
	//Et recopie le message dans le buffer
	memcpy(buffer,message,taille);

	//Accède au driver
	HANDLE hFile = CreateFile(
		 nom_dos, 
         GENERIC_READ | GENERIC_WRITE,
		 0, 
		 NULL, 
         OPEN_EXISTING, 
		 0, 
		 NULL
		 );

	if (hFile == INVALID_HANDLE_VALUE)
		return false;
 
	//Si on a l'accès, envoie le buffer
	DWORD taille_ecrite;
    WriteFile(hFile, buffer, taille+1, &taille_ecrite, NULL);
	
	//Ferme l'accès au driver
 	CloseHandle(hFile);
	return true;
}

// Appel à Read ========================================================================
bool lis_driver (char* nom_dos, char*buffer, unsigned long *taille )
{
	//Prépare le buffer de lecture
	memset(buffer,0,*taille);
	
	//Accède au driver
	HANDLE hFile = CreateFile(
		 nom_dos, 
         GENERIC_READ | GENERIC_WRITE,
		 0, 
		 NULL, 
         OPEN_EXISTING, 
		 0, 
		 NULL
		 );
 
	if(hFile == INVALID_HANDLE_VALUE)
		return false;
	//Si on y a accédé, alors lecture ! taille contiendra alors la taille lue
	ReadFile(hFile, buffer, *taille, taille, NULL);
	
	//Ferme l'accès au driver
	CloseHandle(hFile);
	return true;
}

// Mise en place du pilote dans la base de registre ====================================
int enregistre_driver (char* emplacement, char* nom_court, char* nom_complet, int type)
{

    //Vérifie si le fichier existe
	if (!IsFileExist(emplacement))
		return DRIVER_MANAGER_NO_FILE;
	
	//Ouvre le Service Manager
	HANDLE hSCManager = OpenSCManager(
		NULL,										//lpMachineName
		NULL,										//lpDatabaseName
		SC_MANAGER_CREATE_SERVICE					//dwDesiredAccess
		);
    
	if(!hSCManager)
		return DRIVER_MANAGER_ERROR_SCM;

	int type_value;
	switch (type)
	{
	case 0://A la demande
		type_value = SERVICE_DEMAND_START;
		break;
	case 1://Automatique
		type_value = SERVICE_AUTO_START;
		break;
	case 2://Boot
		type_value = SERVICE_BOOT_START;
		break;
	case 3://Désactivé
		type_value = SERVICE_DISABLED;
		break;
	case 4://Système
		type_value = SERVICE_SYSTEM_START;
		break;
	default:
		return DRIVER_MANAGER_ERROR_CREATE;
	}


	
	//Si tout va bien, créé le driver
    HANDLE hService = CreateService(
		hSCManager,									//hSCManager
		nom_court,									//lpServiceName
		nom_complet,								//lpDisplayName
		SERVICE_START | DELETE | SERVICE_STOP,		//dwDesiredAccess
		SERVICE_KERNEL_DRIVER,						//dwServiceType
		SERVICE_DEMAND_START,						//dwStartType
		SERVICE_ERROR_IGNORE,						//dwErrorControl
		emplacement,								//lpBinaryPathName
		NULL,										//lpLoadOrderGroup
		NULL,										//lpdwTagId
		NULL,										//lpDependencies
		NULL,										//lpServiceStartName
		NULL										//lpPassword
		);

	if (!hService)
	{
		CloseServiceHandle(hSCManager);

		if (GetLastError() == ERROR_SERVICE_EXISTS)
			return DRIVER_MANAGER_ERROR_ALREADY;
		else
			return DRIVER_MANAGER_ERROR_CREATE;
	}

	//Nettoie tout ca
    CloseServiceHandle(hService); 
	CloseServiceHandle(hSCManager);
        
    return DRIVER_MANAGER_OK;
}

// Efface le driver du registre ========================================================
int supprime_driver (char* nom_driver)
{

	//Ouvre le Service Manager
	HANDLE hSCManager = OpenSCManager(
		NULL,										//lpMachineName
		NULL,										//lpDatabaseName
		SC_MANAGER_CREATE_SERVICE					//dwDesiredAccess
		);
    
	if(!hSCManager)
		return DRIVER_MANAGER_ERROR_SCM;

	//Si tout va bien, ouvre le driver
	HANDLE hService = OpenService(
		hSCManager,									//hSCManager
		nom_driver,									//lpServiceName
		SERVICE_START | DELETE | SERVICE_STOP		//dwDesiredAccess
		);

	if (!hService)
	{
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_ACCESS;
	}


    //L'efface
	if (!DeleteService(hService))
	{
		CloseServiceHandle(hService); 
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_DELETE;

	}


	//Nettoie tout ca
    CloseServiceHandle(hService); 
	CloseServiceHandle(hSCManager);
        
    return DRIVER_MANAGER_OK;
}

// Lance le driver =====================================================================
int load_driver (char* nom_driver)
{

	//Ouvre le Service Manager
	HANDLE hSCManager = OpenSCManager(
		NULL,										//lpMachineName
		NULL,										//lpDatabaseName
		SC_MANAGER_CREATE_SERVICE					//dwDesiredAccess
		);
    
	if(!hSCManager)
		return DRIVER_MANAGER_ERROR_SCM;

	//Si tout va bien, ouvre le driver
	HANDLE hService = OpenService(
		hSCManager,									//hSCManager
		nom_driver,									//lpServiceName
		SERVICE_START | DELETE | SERVICE_STOP		//dwDesiredAccess
		);

	if (!hService)
	{
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_ACCESS;
	}


    //Le démarre
	if (!StartService(
			hService,								//hService
			0,										//dwNumServiceArgs
			NULL									//lpServiceArgVectors
			)
		)
	{
		CloseServiceHandle(hService); 
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_RUN;

	}


	//Nettoie tout ca
    CloseServiceHandle(hService); 
	CloseServiceHandle(hSCManager);
        
    return DRIVER_MANAGER_OK;
}

//Arrete le driver =====================================================================
int unload_driver (char* nom_driver)
{
	//Ouvre le Service Manager
	HANDLE hSCManager = OpenSCManager(
		NULL,										//lpMachineName
		NULL,										//lpDatabaseName
		SC_MANAGER_CREATE_SERVICE					//dwDesiredAccess
		);
    
	if(!hSCManager)
		return DRIVER_MANAGER_ERROR_SCM;

	//Si tout va bien, ouvre le driver
	HANDLE hService = OpenService(
		hSCManager,									//hSCManager
		nom_driver,									//lpServiceName
		SERVICE_START | DELETE | SERVICE_STOP		//dwDesiredAccess
		);

	if (!hService)
	{
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_ACCESS;
	}


    //L'éteint
	SERVICE_STATUS ss;
	if (!ControlService(
			hService,								//hService
			SERVICE_CONTROL_STOP,					//dwControl
			&ss										//lpServiceStatus
			)
		)
	{
		CloseServiceHandle(hService); 
		CloseServiceHandle(hSCManager);
		return DRIVER_MANAGER_ERROR_SHUTDOWN;

	}


	//Nettoie tout ca
    CloseServiceHandle(hService); 
	CloseServiceHandle(hSCManager);
        
    return DRIVER_MANAGER_OK;
}















				- appliDlg.cpp -


// appliDlg.cpp : implementation file
//

#include "stdafx.h"
#include "appli.h"
#include "appliDlg.h"

#include "driver_management.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAppliDlg dialog

CAppliDlg::CAppliDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAppliDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CAppliDlg)
	m_emplacement = _T("");
	m_fullname = _T("");
	m_shortname = _T("");
	m_write = _T("");
	m_read = _T("");
	m_dos = _T("");
	m_ioctrl = _T("");
	m_iotype = -1;
	m_startupmode = -1;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_shortname =	(LPCSTR)"Exemple";
	m_fullname =	(LPCSTR)"Driver d'exemple";
	m_dos =			(LPCSTR)"\\\\.\\test_driver";
	m_emplacement =	(LPCSTR)"c:\\test_driver.sys";
	m_iotype = 0;
	m_startupmode = 0;
}

void CAppliDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAppliDlg)
	DDX_Text(pDX, IDC_EMPLACEMENT, m_emplacement);
	DDX_Text(pDX, IDC_FULLNAME, m_fullname);
	DDX_Text(pDX, IDC_SHORTNAME, m_shortname);
	DDX_Text(pDX, IDC_WRITE, m_write);
	DDX_Text(pDX, IDC_READ, m_read);
	DDX_Text(pDX, IDC_DOS, m_dos);
	DDX_Text(pDX, IDC_IOCTRL, m_ioctrl);
	DDX_CBIndex(pDX, IDC_COMBO1, m_iotype);
	DDX_CBIndex(pDX, IDC_COMBO2, m_startupmode);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAppliDlg, CDialog)
	//{{AFX_MSG_MAP(CAppliDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnEnregistrement)
	ON_WM_CREATE()
	ON_WM_CANCELMODE()
	ON_BN_CLICKED(IDC_BUTTON2, OnSuppression)
	ON_BN_CLICKED(IDC_BUTTON3, OnLancement)
	ON_BN_CLICKED(IDC_BUTTON4, OnArret)
	ON_BN_CLICKED(IDC_BUTTON5, OnWrite)
	ON_BN_CLICKED(IDC_BUTTON6, OnRead)
	ON_BN_CLICKED(IDC_BUTTON7, OnEnvoi)
	ON_BN_CLICKED(IDC_BUTTON8, OnStatus)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CAppliDlg message handlers

BOOL CAppliDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	//Initialise les champs

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CAppliDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

void CAppliDlg::OnDestroy()
{
	WinHelp(0L, HELP_QUIT);
	CDialog::OnDestroy();
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CAppliDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CAppliDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

int CAppliDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	return 0;
}

void CAppliDlg::OnCancelMode() 
{
	CDialog::OnCancelMode();
	
	// TODO: Add your message handler code here
	
}





void CAppliDlg::OnEnregistrement() 
{
	//Récupère les variables et les rend plus faciles à manipuler
	UpdateData(); 
	char* emplacement =(char*)LPCTSTR(m_emplacement); 
	char* nom_court =(char*)LPCTSTR(m_shortname); 
	char* nom_complet =(char*)LPCTSTR(m_fullname); 

	//Si il manque des infos, message et cassos
	if (!(strlen(emplacement) && strlen (nom_court) && strlen (nom_complet)))
	{
		MessageBox("Veuillez renseigner les champs ci dessus");
		return;
	}

	//Appel à la fonction et messages à afficher à l'utilisateur	
	switch (enregistre_driver(emplacement, nom_court, nom_complet, m_startupmode))
	{
		case DRIVER_MANAGER_OK:
			MessageBox("Driver enregistré avec succes");
			break;
		case DRIVER_MANAGER_ERROR_CREATE:
			MessageBox("Impossible d'enregistrer le driver, peut-être est il lancé");
			break;
		case DRIVER_MANAGER_ERROR_SCM:
			MessageBox("Accès au Service Control Manager interdit");
			break;
		case DRIVER_MANAGER_NO_FILE:
			MessageBox("Le fichier n'existe pas");
			break;
		case DRIVER_MANAGER_ERROR_ALREADY:
			MessageBox("Le driver existe déja");
			break;
	}
}


void CAppliDlg::OnSuppression() 
{
	//Récupère les variables et les rend plus faciles à manipuler
	UpdateData(); 
	char* emplacement =(char*)LPCTSTR(m_emplacement); 
	char* nom_court =(char*)LPCTSTR(m_shortname); 
	char* nom_complet =(char*)LPCTSTR(m_fullname); 

	//Si il manque des infos, message d'erreur et cassos
	if (!(strlen(emplacement) && strlen (nom_court) && strlen (nom_complet)))
	{
		MessageBox("Veuillez renseigner les champs ci dessus");
		return;
	}

	//Appel à la fonction et messages pour l'utilisateur
	switch (supprime_driver(nom_court))
	{
		case DRIVER_MANAGER_OK:
			MessageBox("Driver supprimé avec succes");
			break;
		case DRIVER_MANAGER_ERROR_ACCESS:
			MessageBox("Impossible d'accéder au driver, il n'est peut-être pas enregistré");
			break;
		case DRIVER_MANAGER_ERROR_SCM:
			MessageBox("Accès au Service Control Manager interdit");
			break;
		case DRIVER_MANAGER_ERROR_DELETE:
			MessageBox("Impossible de supprimer le driver");
			break;
	}
}


void CAppliDlg::OnLancement() 
{
	//Récupère les variables et les rend plus faciles à utiliser
	UpdateData(); 
	char* emplacement =(char*)LPCTSTR(m_emplacement); 
	char* nom_court =(char*)LPCTSTR(m_shortname); 
	char* nom_complet =(char*)LPCTSTR(m_fullname); 

	//Si il manque des infos, message et cassos
	if (!(strlen(emplacement) && strlen (nom_court) && strlen (nom_complet)))
	{
		MessageBox("Veuillez renseigner les champs ci dessus");
		return;
	}

	//Appel à la fonction et messages utilisateur
	switch (load_driver(nom_court))
	{
		case DRIVER_MANAGER_OK:
			MessageBox("Driver démarré avec succes");
			break;

		case DRIVER_MANAGER_ERROR_ACCESS:
			MessageBox("Impossible d'accéder au driver, il n'est peut-être pas enregistré");
			break;

		case DRIVER_MANAGER_ERROR_SCM:
			MessageBox("Accès au Service Control Manager interdit");
			break;

		case DRIVER_MANAGER_ERROR_RUN:
			MessageBox("Impossible de démarrer le driver, il est peut-être déja lancé");
			break;
	}	
}


void CAppliDlg::OnArret() 
{
	//Récupération des variables et les rend plus faciles à manipuler
	UpdateData(); 
	char* emplacement =(char*)LPCTSTR(m_emplacement); 
	char* nom_court =(char*)LPCTSTR(m_shortname); 
	char* nom_complet =(char*)LPCTSTR(m_fullname); 

	//Si il manque des informations, message et cassos
	if (!(strlen(emplacement) && strlen (nom_court) && strlen (nom_complet)))
	{
		MessageBox("Veuillez renseigner les champs ci dessus");
		return;
	}

	//Appel à la fonction et message utilisateur	
	switch (unload_driver(nom_court))
	{
		case DRIVER_MANAGER_OK:
			MessageBox("Driver arrêté avec succes");
			break;
		case DRIVER_MANAGER_ERROR_ACCESS:
			MessageBox("Impossible d'accéder au driver, il n'est peut-être pas enregistré");
			break;
		case DRIVER_MANAGER_ERROR_SCM:
			MessageBox("Accès au Service Control Manager interdit");
			break;
		case DRIVER_MANAGER_ERROR_SHUTDOWN:
			MessageBox("Impossible d'éteindre le driver, il n'est peut-être pas lancé");
			break;
	}	
}


void CAppliDlg::OnWrite() 
{
	// Récupère les champs
	UpdateData(); 
	if (!ecris_driver ((char*)LPCTSTR(m_dos), (char*)LPCTSTR(m_write) ))
		MessageBox("Ecriture impossible, le driver ne semble pas chargé");
}


void CAppliDlg::OnRead() 
{
	//Le buffer local pour stoquer les infos lues
	char buffer_lecture[1024];
	unsigned long taille_buffer_lecture = 1024;
	
	//Récupère les variables
	UpdateData(); 
	
	//Appelle la fonction de lecture
	if (!lis_driver ((char*)LPCTSTR(m_dos), buffer_lecture, &taille_buffer_lecture))
		MessageBox("Lecture impossible, le driver ne semble pas chargé");
	else
	{
		//Et renvoie la valeur dans le champ
		m_read = (LPCTSTR)buffer_lecture;
 		UpdateData(FALSE);
	}
}


void CAppliDlg::OnEnvoi() 
{
	//Buffer local pour la partie MDL de la communication avec le driver	
	char buffer_ioctrl[1024];
	unsigned long taille_buffer_ioctrl = 1024;

	//Les deux types de communication possibles
	DWORD IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO = 2285569;
	DWORD IOCTL_EXAMPLE_SAMPLE_DIRECT_OUT_IO = 2285574;

	//Récupération des variables
	UpdateData(); 

	//Un mode de communication doit etre sélectionné, sinon cassos
	CString string_controle;
	int nIndex = GetDlgItemText(IDC_COMBO1, string_controle); 

	//Action
	bool verdict;
	if (m_iotype == 0)
		verdict = ioctrl_driver ((char*)LPCTSTR(m_dos), (char*)LPCTSTR(m_ioctrl), IOCTL_EXAMPLE_SAMPLE_DIRECT_IN_IO, buffer_ioctrl, &taille_buffer_ioctrl );
	else
		verdict = ioctrl_driver ((char*)LPCTSTR(m_dos), (char*)LPCTSTR(m_ioctrl), IOCTL_EXAMPLE_SAMPLE_DIRECT_OUT_IO, buffer_ioctrl, &taille_buffer_ioctrl);

	if (verdict)
	{
		m_ioctrl = (LPCTSTR)buffer_ioctrl;
		UpdateData(FALSE); 
	}
	else
		MessageBox("IO-Control impossible, le driver ne semble pas chargé");
}


void CAppliDlg::OnStatus() 
{
	// Récupère les variables
	UpdateData(); 

	switch (verifie_status((char*)LPCTSTR(m_shortname)))
	{
	case DRIVER_MANAGER_STATUS_ABSENT:
		MessageBox("Le driver n'est pas enregistré");
		break;
	case DRIVER_MANAGER_STATUS_ACTIF:
		MessageBox("Le driver est enregistré et actif");
		break;
	case DRIVER_MANAGER_STATUS_INACTIF:
		MessageBox("Le driver est enregistré mais inactif");
		break;
	}
	
}














				- appli.cpp -




// appli.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "appli.h"
#include "appliDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAppliApp

BEGIN_MESSAGE_MAP(CAppliApp, CWinApp)
	//{{AFX_MSG_MAP(CAppliApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAppliApp construction

CAppliApp::CAppliApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CAppliApp object

CAppliApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CAppliApp initialization

BOOL CAppliApp::InitInstance()
{
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	CAppliDlg dlg;
	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}

	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}









			- test_driver.c -


//tolwin_kernel.h
#define	DWORD	unsigned long
#define	BOOL	unsigned long
#define	WORD	unsigned int
#define	UINT	unsigned int
#define	BYTE	unsigned char


#include "ntddk.h"
#include "ntstrsafe.h"



// TYPES UTILISES ===============================================================================
	// Le device extension
	typedef struct {
		PDEVICE_OBJECT pMouseOldTopOfStack;
		BOOL autofire;
		int pending;
		PCHAR buffer;
		PIRP MouseIrp;
		BOOL latch;
		BOOL terminate_thread;
		HANDLE thread_handle;
		
	}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

	// Les données d'un IRP souris
	typedef struct {
		USHORT UnitId;
		USHORT flags;
		union {
			ULONG Buttons;
			struct {
				USHORT ButtonFlags;
				USHORT ButtonData;
			};
		};
		ULONG RawButtons;
		long LastX;
		long LastY;
		ULONG ExtraInformation;
	} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA;



// PROTOTYPES DES FONCTIONS ====================================================================
	// Utilitaires
	UINT IsStringTerminatedAndSize	(PCHAR pString, UINT uiLength);
	
	//Driver
	VOID	 Unload					(IN PDRIVER_OBJECT  pDriverObject);
	
	//Device
	NTSTATUS PasTouche 				( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp );
	NTSTATUS FiltreLecture 				( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp );
	NTSTATUS ConfigurationDriver 		( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp );
	NTSTATUS CompletionRoutine		( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp, IN PVOID Context);


	void the_thread (IN PVOID pcontext);




//KeGetCurrentIrql()
/*#define PASSIVE_LEVEL            0      // Passive release level
#define LOW_LEVEL                0      // Lowest interrupt level
#define APC_LEVEL                1      // APC interrupt level
#define DISPATCH_LEVEL           2      // Dispatcher level
#define CMC_LEVEL                3      // Correctable machine check level
#define DEVICE_LEVEL_BASE        4      // 4 - 11 - Device IRQLs
#define PC_LEVEL                12      // Performance Counter IRQL
#define IPI_LEVEL               14      // IPI IRQL
#define CLOCK_LEVEL             13      // Clock Timer IRQL
#define POWER_LEVEL             15      // Power failure level
#define PROFILE_LEVEL           15      // Profiling level
#define HIGH_LEVEL              15      // Highest interrupt level
*/

// DRIVER ENTRY POINT ===========================================================================
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  pRegistryPath)
{
	//Variables regroupées sinon bug de compilation à cause des DbgPrint
		//Divers
		NTSTATUS status = STATUS_UNSUCCESSFUL;
		int mj_function;
		//Création du device
		PDEVICE_OBJECT pMouseDeviceObject;
		PDEVICE_EXTENSION pDeviceExtension; 
		//Attache du device au stack souris
		CCHAR NomDriverStack[] = "\\Device\\PointerClass0";
		STRING NomDriverStackString;
		UNICODE_STRING uNomDriverStack;

		LARGE_INTEGER offset;



	//Le code de DriverEntry
		//Petit texte de debut d'exécution
		DbgPrint("\r\n\r\ntest_driver> Execution de DriverEntry\r\n");
		DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());


		//Initialise les irp majeures sur la fonction de dispatch de base
		DbgPrint("test_driver> Initialisation des fonctions majeures du driver filtrant\r\n");
		for (mj_function = 0; mj_function < IRP_MJ_MAXIMUM_FUNCTION; mj_function++)
			pDriverObject->MajorFunction[mj_function] = PasTouche;

		//Règle les irps qui auront un traitement spécifiques, les veinardes
		pDriverObject->MajorFunction[IRP_MJ_READ] = FiltreLecture;
		pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ConfigurationDriver;
		pDriverObject->DriverUnload = Unload;

		//Création du device
		DbgPrint("test_driver> Creation du device de filtrage\r\n");
		status = IoCreateDevice (pDriverObject,sizeof(DEVICE_EXTENSION),NULL,FILE_DEVICE_MOUSE,0,TRUE,&pMouseDeviceObject);
		if (status != STATUS_SUCCESS)
		{
			//Si erreur alors cassos
			DbgPrint("test_driver> Erreur lors de la creation du device\r\n");
			return status;
		}
		else
			DbgPrint("test_driver> Device cree avec succes\r\n");

		//Initialisation du device extension : mise à zéro et utilisation d'un pointeur plus pratique à manipuler
		DbgPrint("test_driver> Initialisation du device de filtrage : mise a zero de la ram device extension\r\n");
		RtlZeroMemory(pMouseDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
		pDeviceExtension = (DEVICE_EXTENSION*)pMouseDeviceObject->DeviceExtension;

		//Attache le device a la premiere device stack de classe souris
		DbgPrint("test_driver> Attache le device de filtrage sur %s\r\n",NomDriverStack);
		RtlInitAnsiString(&NomDriverStackString,NomDriverStack);
		RtlAnsiStringToUnicodeString(&uNomDriverStack,&NomDriverStackString,TRUE);
		status = IoAttachDevice(pMouseDeviceObject, &uNomDriverStack,&pDeviceExtension->pMouseOldTopOfStack);
		RtlFreeUnicodeString(&uNomDriverStack);
		if (status != STATUS_SUCCESS)
		{
			//Si erreur alors efface le device et cassos
			DbgPrint("test_driver> Erreur lors de l'insertion du device sur %s\r\n",NomDriverStack);
			IoDeleteDevice (pMouseDeviceObject);
			return status;
		}
		else
			DbgPrint("test_driver> Device insere avec succes sur %s\r\n",NomDriverStack);

		//Paramétrage de notre device filtrant notamment au moyen de valeurs provenant du driver souris original
		DbgPrint("test_driver> Parametrage du device\r\n");
		pMouseDeviceObject->Flags |= DO_BUFFERED_IO; //(pDeviceExtension->pMouseOldTopOfStack->Flags & DO_BUFFERED_IO)
		pMouseDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
		pMouseDeviceObject->DeviceType = pDeviceExtension->pMouseOldTopOfStack->DeviceType;
		pMouseDeviceObject->Characteristics = pDeviceExtension->pMouseOldTopOfStack->Characteristics;


/*
		//Lance le thread systeme
		pDeviceExtension->terminate_thread = FALSE;
		status = PsCreateSystemThread (
			&pDeviceExtension->thread_handle,
			(ACCESS_MASK)0,
			NULL,
			(HANDLE)0,
			NULL,
			the_thread,			//Adresse du thread
			pDeviceExtension		//Pagametre
			);
		if (status != STATUS_SUCCESS)
		{
			//Si erreur alors efface le device et cassos
			DbgPrint("Erreur lors de ca creation du thread\r\n");
			IoDetachDevice(pDeviceExtension->pMouseOldTopOfStack);
			IoDeleteDevice (pMouseDeviceObject);
			return status;
		}
		else
			DbgPrint("Thread cree avec succes\r\n");


		//Alloue le buffer pour l'IRP
		pDeviceExtension->buffer = ExAllocatePoolWithTag (NonPagedPool, sizeof(MOUSE_INPUT_DATA), 'Mous');
		if (pDeviceExtension->buffer == NULL)
		{
			//Si erreur alors detache et efface le device et cassos
			DbgPrint("Erreur lors de l'allocation du buffer\r\n");
			IoDetachDevice(pDeviceExtension->pMouseOldTopOfStack);
			IoDeleteDevice (pMouseDeviceObject);
			return status;
		}
		else
			DbgPrint("Buffer alloue avec succes\r\n");

		//Créé l'irp
		offset.QuadPart = 0;
		pDeviceExtension->MouseIrp = IoBuildAsynchronousFsdRequest( IRP_MJ_READ, pDeviceExtension->pMouseOldTopOfStack, pDeviceExtension->buffer, sizeof(MOUSE_INPUT_DATA), &offset, NULL);
		if (pDeviceExtension->MouseIrp == NULL)
		{
			//Si erreur alors detache et efface le device et cassos
			DbgPrint("Erreur lors de la creation de l'irp souris\r\n");
			IoDetachDevice(pDeviceExtension->pMouseOldTopOfStack);
			IoDeleteDevice (pMouseDeviceObject);
			return status;
		}
		else
			DbgPrint("Irp souris creee avec succes\r\n");
*/

		//Fin du driver entry
		return status;
}





// FONCTION DE DECHARGEMENT =====================================================================
VOID Unload(IN PDRIVER_OBJECT  pDriverObject)
{    
	PDEVICE_EXTENSION pDeviceExtension; 

	DbgPrint("test_driver> Execution de FilterUnload\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());
//	__asm int 3
	
	pDeviceExtension = pDriverObject->DeviceObject->DeviceExtension;
	DbgPrint("test_driver> pending : %i\r\n",pDeviceExtension->pending );

	do 	DbgPrint("test_driver> Wait pending\r\n");
		while (pDeviceExtension->pending > 0);

	//Séparation
//	__asm int 3
//	IoDetachDevice(pDeviceExtension->pMouseOldTopOfStack);

	//Efface le device
//	__asm int 3
//	IoDeleteDevice(pDriverObject->DeviceObject);

}


// QUELQUES FONCTIONS QUI APPELLENT L'ANCIEN DRIVER ====================================================
NTSTATUS ConfigurationDriver ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp )
{
	PDEVICE_EXTENSION pDeviceExtension; 

	DbgPrint("test_driver> Execution de ConfigurationDriver\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());

	pDeviceExtension = pDeviceObject->DeviceExtension;

    	IoSkipCurrentIrpStackLocation(Irp);
	return IoCallDriver(pDeviceExtension->pMouseOldTopOfStack, Irp);
}


NTSTATUS PasTouche ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp )
{
	PDEVICE_EXTENSION pDeviceExtension; 

	DbgPrint("test_driver> Execution de PasTouche\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());

	
	pDeviceExtension = pDeviceObject->DeviceExtension;

    	IoSkipCurrentIrpStackLocation(Irp);
	return IoCallDriver(pDeviceExtension->pMouseOldTopOfStack, Irp);
}




// LA FONCTION DE LECTURE ET SON CALLBACK ============================================================

NTSTATUS FiltreLecture ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp )
{
	PDEVICE_EXTENSION pDeviceExtension; 
	PIO_STACK_LOCATION pIoStackIrp = NULL;
	NTSTATUS status = STATUS_UNSUCCESSFUL;


	DbgPrint("test_driver> Execution de FiltreLecture\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());


	pDeviceExtension = pDeviceObject->DeviceExtension;

	//Chope les positions dans l'irp stack
   	pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
   	IoCopyCurrentIrpStackLocationToNext(Irp);

	//Mise en place de la completion routine
	DbgPrint("test_driver> Regle CompletionRoutine et down the stack\r\n");
	IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) CompletionRoutine, NULL, TRUE, TRUE, TRUE);

	//Appel au driver d'origine
	pDeviceExtension->pending++;
	status = IoCallDriver(pDeviceExtension->pMouseOldTopOfStack, Irp);
	pDeviceExtension->pending--;

	return status;
}





NTSTATUS CompletionRoutine(PDEVICE_OBJECT pDeviceObject, PIRP Irp, PVOID Context)
{
    	PMOUSE_INPUT_DATA pMouseData;
	PDEVICE_EXTENSION pDeviceExtension; 

	DbgPrint("test_driver> Execution de CompletionRoutine\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());

	pMouseData = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
	pDeviceExtension = pDeviceObject->DeviceExtension;


	//Teste pour l'autofire : si appel d'origine et que le bouton 1 est en jeu alors... ...
	if (pMouseData->UnitId == 0)
	{
		if (pMouseData->Buttons & 1)
			{
				pDeviceExtension->autofire = TRUE;
				pDeviceExtension->latch=TRUE;
			 	DbgPrint("test_driver> Autofire on\r\n");
			}
			else if (pMouseData->Buttons & 2)
			{
				pDeviceExtension->autofire = FALSE;
			    	DbgPrint("test_driver> Autofire off\r\n");
			}
	}

	if (pDeviceExtension->autofire == TRUE)
	{
		if (pDeviceExtension->latch == TRUE)
		{
			//Ici je passe le bouton à 1
			pMouseData->Buttons &= 0xFFFD;
			pMouseData->Buttons |= 0x0001;
			pDeviceExtension->latch = FALSE;
		}
		else
		{
			//Ici je passe le bouton à 2
			pMouseData->Buttons &= 0xFFFE;
			pMouseData->Buttons |= 0x0002;
			pDeviceExtension->latch = TRUE;
		}
	}

	if (Irp->PendingReturned)
		IoMarkIrpPending(Irp);
	
	return Irp->IoStatus.Status;
}



void the_thread (IN PVOID pcontext)
{
	PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION) pcontext;
	PMOUSE_INPUT_DATA pMouseData;
	PIO_STACK_LOCATION nextstack;

	DbgPrint("test_driver> Execution de void the_thread\r\n");
	DbgPrint("test_driver> Irql : %i\r\n",KeGetCurrentIrql());

	pMouseData = pDeviceExtension->MouseIrp->AssociatedIrp.SystemBuffer;
	nextstack = IoGetNextIrpStackLocation(pDeviceExtension->MouseIrp);
	nextstack->MajorFunction = IRP_MJ_READ;
	nextstack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);


while (1)
{
	if (pDeviceExtension->autofire == TRUE)
	{
		if (pDeviceExtension->latch == TRUE)
		{
			RtlZeroMemory(pMouseData, sizeof(MOUSE_INPUT_DATA));
			pMouseData->UnitId = 1;
			pMouseData->flags = 1;
			pMouseData->Buttons = 1;
			pMouseData->RawButtons = 0;
			pMouseData->LastX = 0;
			pMouseData->LastY = 0;
			pMouseData->ExtraInformation = 0;
		//	pDeviceExtension->MouseIrp->IoStatus.Status = STATUS_SUCCESS;
			//pDeviceExtension->MouseIrp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
			if (pDeviceExtension->pending == 0) IoCallDriver(pDeviceExtension->pMouseOldTopOfStack, pDeviceExtension->MouseIrp);
		
			pDeviceExtension->latch = FALSE;
		 	DbgPrint("test_driver> Fire !!!\r\n");
		}
		else
		{
			RtlZeroMemory(pMouseData, sizeof(MOUSE_INPUT_DATA));
			pMouseData->UnitId = 1;
			pMouseData->flags = 1;
			pMouseData->Buttons = 2;
			pMouseData->RawButtons = 0;
			pMouseData->LastX = 0;
			pMouseData->LastY = 0;
			pMouseData->ExtraInformation = 0;
			//pDeviceExtension->MouseIrp->IoStatus.Status = STATUS_SUCCESS;
			//pDeviceExtension->MouseIrp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
			if (pDeviceExtension->pending == 0) IoCallDriver(pDeviceExtension->pMouseOldTopOfStack, pDeviceExtension->MouseIrp);
		
			pDeviceExtension->latch = TRUE;
		}
	}
}

}


// QUELQUES FONCTIONS UTILES ====================================================================
UINT IsStringTerminatedAndSize(PCHAR pString, UINT uiLength)
{
    UINT uiIndex = 0;

    while(uiIndex < uiLength)
    {
        if(pString[uiIndex] == '\0')
        {
            return uiIndex+1;
        }
        else
        {
           uiIndex++;
        }
    }

    return 0;
}






		c/ annexes

direction l'index ou l'annexe pour la suite du programme, executable et autres
fichiers compris.


    -- [ Tolwin