// Complet.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* installpath = "C:\\Program Files\\Programmez";
const char* souscle = "SOFTWARE\\Microsoft\\Windows"
					  "\\CurrentVersion\\Uninstall\\Programmez";
const char* installdir_cle = "InstallDir";
const char* installdir_cle_value = "C:\\Program Files\\Programmez";
const char* DisplayName = "Programmez!";

const char* texte =
	"\nIci une application d'installation\n"
	"bien elevee ouvrirait une boite de dialogue\n"
	"pour demander a l'utilisateur de saisir\n"
	"un repertoire d'installation\n"
	"Dans cet exemple l'installation aura lieu dans\n"
	"C:\\Program Files\\Programmez\n"
	"des que vous aurez appuye sur [return]\n";


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,
};

string GetCurDir()
{
	TCHAR buffer[MAX_PATH+1];
	::GetCurrentDirectory(sizeof(buffer), buffer);
	return buffer;
}

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

	switch(Notification)
	{
	case SPFILENOTIFY_STARTQUEUE:
		cout << "Lancement du processus "
			    "de copie des fichiers" << endl;
		break;

	case SPFILENOTIFY_STARTCOPY:
		FILEPATHS* filepaths;
		filepaths = reinterpret_cast<FILEPATHS*>(Param1);
		cout << endl << "Copie de ";
		cout << filepaths->Source << endl;
		cout << "vers:" << endl;
		cout << filepaths->Target << " ...";
		break;

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

	case SPFILENOTIFY_ENDQUEUE:
		cout << "Fin de la copie des fichiers" << endl;
		break;

	default:
		break;

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

int main(int argc, char* argv[])
{
	HSPFILEQ MyQueue = NULL;
	PVOID Context;
	
	string sourcepath = GetCurDir();
 
	cout << endl << "installation de HelloProg" << endl;


	cout << texte;
	cin.get();

	// 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 newinstallpath = installpath;
		if(strlen(addpaths[i]))
		{
			newinstallpath += "\\";
			newinstallpath += addpaths[i];
		}

	::SetupQueueCopy(
		MyQueue,
		sourcepath.c_str(),
		addpaths[i],
		fichiers[i],
		NULL,
		NULL,
		newinstallpath.c_str(),
		NULL,
		SP_COPY_NOSKIP|SP_COPY_NOBROWSE
		); 
	}

	// Copie des fichiers
	::SetupCommitFileQueue (
		NULL,
		MyQueue,
		MyCallback,
		Context);
	
	// Menu démarrer
	cout << endl<< "ATTENTION" << endl;
	cout << "Cet exemple ne cree pas d'entree" << endl;
	cout << "dans le menu demarrer, ce n'est pas un bug ;)" << endl << endl;
	
	// Mise à jour du registre.
	HKEY macle;
	DWORD Disposition;

	//  créer la clé
	::RegCreateKeyEx(
		HKEY_LOCAL_MACHINE,
		souscle,
		NULL,
		NULL,
		REG_OPTION_NON_VOLATILE,
		KEY_WRITE,
		NULL,
		&macle,
		&Disposition);
	
	// Répertoire d'installation
	::RegSetValueEx(
		macle,
		installdir_cle,
		NULL,
		REG_SZ,
		(BYTE*)installdir_cle_value,
		strlen(installdir_cle_value)+1);

	// Chaîne de désinstallation
	string uninstall_cle_value = installdir_cle_value;
	uninstall_cle_value += "\\";
	uninstall_cle_value += "Uninstall.exe";
	
	 ::RegSetValueEx(
		macle,
		"UninstallString",
		NULL,
		REG_SZ,
		(BYTE*)uninstall_cle_value.c_str(),
		uninstall_cle_value.length()+1);

	 // valeur d'affichage pour le panneau de configuration
	 ::RegSetValueEx(
		macle,
		"DisplayName",
		NULL,
		REG_SZ,
		(BYTE*)DisplayName,
		strlen(DisplayName)+1);

	::RegCloseKey(macle);
	cout << "Registre mis a jour" << endl;

	::SetupTermDefaultQueueCallback(Context);
	::SetupCloseFileQueue(MyQueue);
	cout << "Installation terminee" << endl;
	cout << "appuyez sur une touche" << endl;
	cin.get();
	return 0;
}
