// Uninstall.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <setupapi.h>

#include <iostream>
#include <string>

using namespace std;


const char* souscle = "SOFTWARE\\Microsoft\\Windows"
					  "\\CurrentVersion\\Uninstall\\Programmez";
const char* installdir_cle = "InstallDir";

TCHAR* binsdir = "bins";
TCHAR* docsdir = "docs";
TCHAR* curdir = ""; 

TCHAR* fichiers[] = 
{
	"HelloProg.exe",
	"HelloDll.dll",
	"ProgIcon.ico",

	"Doc1.txt",
	"Doc2.txt",
	"Doc3.txt",

	"Readme.txt",
	"Uninstall.exe",
};

TCHAR* addpaths[] = 
{
	binsdir,
	binsdir,
	binsdir,

	docsdir,
	docsdir,
	docsdir,

	curdir,
	curdir,
};

UINT CALLBACK MyCallback(PVOID Context, UINT Notification,
		UINT_PTR Param1,
		UINT_PTR Param2)
{

	switch(Notification)
	{
	case SPFILENOTIFY_STARTQUEUE:
		cout << "Debut de l'effacement des fichiers" << endl;
		break;

	case SPFILENOTIFY_STARTDELETE:
		FILEPATHS* filepaths;
		filepaths = reinterpret_cast<FILEPATHS*>(Param1);
		cout << endl << "Effacement de ";
		cout << filepaths->Target;
		cout  << " ...";
		break;

	case SPFILENOTIFY_ENDDELETE:
		cout << "termine" << endl;
		break;

	case SPFILENOTIFY_ENDQUEUE:
		cout << "Fin de l'effacement des fichiers" << endl;
		break;

	default:
		break;

	}
	return SetupDefaultQueueCallback(
		Context,
		Notification,
		Param1,
		Param2);
}


int main(int argc, char* argv[])
{
	HKEY hKey;
	DWORD dwType;
	DWORD dwSizeValue;
	HSPFILEQ MyQueue = NULL;
	PVOID Context;
	LONG  result;
	char* buffer;
	string repertoire;

	cout << endl << "Desinstalaltion de HelloProg" << endl;

	// Ouverture de la clé de registre
	result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
		souscle,
		NULL,
		KEY_ALL_ACCESS,
		&hKey);
	if(result != ERROR_SUCCESS)
	{
		cout << "cle introuvable" << endl;
		cout << "L'application HelloProg est probalement"
				" deja desinstallee" << endl;
		cout << "Appuyez sur une touche" << endl;
		cin.get();
		return 1;
	}
	
	// première lecture de la clé pour connaître
	// la longueur des données à lire et le type
	result = ::RegQueryValueEx(hKey,
				installdir_cle,
				NULL,
				&dwType,
				NULL,
				&dwSizeValue);
	if(result != ERROR_SUCCESS)
	{
		cout << "Lecture du repertoire d'installation impossible" << endl;
		cout << "L'application HelloProg est probalement"
				" deja desinstallee" << endl;
		cout << "Appuyez sur une touche" << endl;
		cin.get();
		return 1;
	}


	// Deuxième lecture de la clé pour
	// obtenir les données
	buffer = new char[dwSizeValue];
	::RegQueryValueEx(hKey,
		installdir_cle,
		NULL,
		&dwType,
		(BYTE*)buffer,
		&dwSizeValue);
	repertoire = buffer;
	delete[] buffer;

	// Fermeture de la clé
	::RegCloseKey(hKey);
	// Suppression de la cle et de ses valeurs
	cout << "Mise a jour du registre" << endl;
	::RegDeleteKey(HKEY_LOCAL_MACHINE, souscle);

	// Suppression de fichiers
	// Création de la queue
	MyQueue = SetupOpenFileQueue();
	// Mise en place de la fonction de rappel
	Context = ::SetupInitDefaultQueueCallback(NULL);
	
	// Mise en queue des fichiers à copier	
	for(int i=0; i<sizeof(fichiers)/sizeof(TCHAR*); ++i)
	{
		string filepath = repertoire;
		if(strlen(addpaths[i]))
		{
			filepath += "\\";
			filepath += addpaths[i];
		}
		filepath += "\\";
		filepath += fichiers[i];

	::SetupQueueDelete(
		MyQueue,
		filepath.c_str(),
		NULL);
	}

	// Lancement de l'effacement
	::SetupCommitFileQueue (
		NULL,
		MyQueue,
		MyCallback,
		Context);

	::SetupTermDefaultQueueCallback(Context);
	::SetupCloseFileQueue(MyQueue);
	
	::RemoveDirectory((repertoire + "\\" + binsdir).c_str());
	::RemoveDirectory((repertoire + "\\" + docsdir).c_str());
	::RemoveDirectory(repertoire.c_str());

	cout << "Desinstallation terminee" << endl;
	cout << "Appuyez sur une touche" << endl;
	cin.get();
	return 0;
}
