/*************************************************************************
* Rutoken                                                                *
* Copyright (c) 2003-2017, CJSC Aktiv-Soft. All rights reserved.         *
* Подробная информация:  http://www.rutoken.ru                           *
*------------------------------------------------------------------------*
* Импорт сертификата в контейнер:                                        *
*  - анализ параметров командной строки;                                 *
*  - выбор криптопровайдера для работы;                                  *
*  - выбор подходящего контейнера;                                       *
*  - импорт сертификата в выбранный контейнер.                           *
*************************************************************************/

/*************************************************************************
* Включение файла stdafx.h.                                              *
* Файл stdafx.h используется *только* в Cert2Cont для доступа к          *
* заголовочным файлам стандартного ввода/вывода и функциям Win32 API.    *
*------------------------------------------------------------------------*
* Включение файла Cert2Cont.h.                                           *
* Файл Cert2Cont.h используется *только* в Cert2Cont для доступа к:      *
*  - константам;                                                         *
*  - именам ключей командной строки.                                     *
*------------------------------------------------------------------------*
* Включение файла CSPs.h.                                                *
* Файл CSPs.h используется *только* в Cert2Cont для доступа к            *
* вспомогательным функциям для перебора криптопровайдеров.               *
*------------------------------------------------------------------------*
* Включение файла Containers.h.                                          *
* Файл Containers.h используется *только* в Cert2Cont для доступа к      *
* следующим вспомогательным функциям:                                    *
*  - перебора контейнеров;                                               *
*  - проверки наличия сертификата в контейнере.                          *
*------------------------------------------------------------------------*
* Включение файла Util_Funcs.h.                                          *
* Файл Util_Funcs.h используется *только* в Cert2Cont для доступа к      *
* следующим вспомогательным функциям:                                    *
*  - печати сообщений в командной строке;                                *
*  - анализа параметров переданных в командной строке;                   *
*  - освобождения использованных ресурсов.                               *
*------------------------------------------------------------------------*
* Включение файла Import.h.                                              *
* Файл Import.h используется *только* в Cert2Cont для доступа к          *
* вспомогательным функциям для импорта сертификата в контейнер.          *
*************************************************************************/


#include "stdafx.h"
#include "Cert2Cont.h"
#include "CSPs.h"
#include "Containers.h"
#include "Util_Funcs.h"
#include "Import.h"

int wmain(int argc, WCHAR* argv[])
{
	BOOL bResult = TRUE;                                        // Вспомогательная переменная для хранения результата выполнения функции

	LPWSTR lpszCSPName = NULL;                                  // Указатель на строку с именем криптопровайдера
	LPWSTR lpszContainerName = NULL;                            // Указатель на строку с именем контейнера
	DWORD dwKeySpec = 0;                                        // Тип ключевой пары

	LPWSTR lpszCertFileName = NULL;                             // Указатель на строку с именем сертификата
	BOOL bPrintHelpAndExit = FALSE;                             // Если TRUE, то распечатать справку и завершить программу

	LPWSTR lpszCSPs[C2C_MAX_ENUM_COUNT] = { 0 };                // Массив указателей на строки с именами криптопровайдеров
	DWORD pdwCSPsTypes[C2C_MAX_ENUM_COUNT] = { 0 };             // Массив из типов криптопровайдеров
	DWORD dwCSPsCount = 0;                                      // Количество элементов в массивах имен криптопровайдеров и их типов
	DWORD dwSelectedCSP = 0;                                    // Порядковый номер элемента в массивах имен криптопровайдеров и их типов

	LPWSTR lpszContainers[C2C_MAX_ENUM_COUNT] = { 0 };          // Массив указателей на строки с именами контейнеров
	DWORD dwContainersCount = 0;                                // Количество элементов в массиве имен контейнеров
	DWORD dwSelectedContainer = 0;                              // Порядковый номер элемента в массиве имен контейнеров

	LPVOID lpvCertBuffer = NULL;                                // Указатель на буфер с сертификатом
	DWORD dwCertBufferSize = 0;                                 // Размер буфера с сертификатом в байтах

	for (;; ) {
		/**********************************************************************
		* Шаг 1: Распечатать приветствие.                                     *
		**********************************************************************/
		PrintWelcomeInformation();

		/**********************************************************************
		* Шаг 2: Проанализировать параметры, переданные в командной строке.   *
		**********************************************************************/
		bResult = ParseCommandLine(argc,
		                           argv,
		                           &lpszCSPName,
		                           &lpszContainerName,
		                           &dwKeySpec,
		                           &lpszCertFileName,
		                           &bPrintHelpAndExit);
		if (!bResult || bPrintHelpAndExit) {
			break;
		}

		/**********************************************************************
		* Шаг 3: Получить массив имен криптопровайдеров.                      *
		**********************************************************************/
		bResult = EnumCSPs(lpszCSPs,
		                   pdwCSPsTypes,
		                   &dwCSPsCount);
		if (!bResult) {
			break;
		}

		/************************************************************************
		* Шаг 4: Получить порядковый номер элемента в массиве имен              *
		*        криптопровайдеров.                                             *
		************************************************************************/
		dwSelectedCSP = SelectCSP(lpszCSPName,
		                          lpszCSPs,
		                          pdwCSPsTypes,
		                          dwCSPsCount);
		bResult = dwSelectedCSP != C2C_BAD_SELECT;
		if (!bResult) {
			break;
		}

		/**********************************************************************
		* Шаг 5: Получить массив имен контейнеров.                            *
		**********************************************************************/
		bResult = EnumContainers(lpszCSPs,
		                         pdwCSPsTypes,
		                         dwSelectedCSP,
		                         lpszContainers,
		                         &dwContainersCount);
		if (!bResult) {
			break;
		}

		/************************************************************************
		* Шаг 6: Получить порядковый номер элемента в массиве имен              *
		*        контейнеров.                                                   *
		************************************************************************/
		dwSelectedContainer = SelectContainer(lpszContainerName,
		                                      lpszContainers,
		                                      dwContainersCount);
		bResult = dwSelectedContainer != C2C_BAD_SELECT;
		if (!bResult) {
			break;
		}

		/************************************************************************
		* Шаг 7: Считать сертификат из файла.                                   *
		************************************************************************/
		bResult = ReadCertificateFromFile(lpszCertFileName,
		                                  &lpvCertBuffer,
		                                  &dwCertBufferSize);
		if (!bResult) {
			break;
		}

		/************************************************************************
		* Шаг 8: Импортировать сертификат в выбранный контейнер.                *
		************************************************************************/
		bResult = ImportCertificateToContainer(lpszCSPs,
		                                       pdwCSPsTypes,
		                                       dwSelectedCSP,
		                                       lpszContainers,
		                                       dwSelectedContainer,
		                                       dwKeySpec,
		                                       lpvCertBuffer,
		                                       dwCertBufferSize);
		break;
	}


	/************************************************************************
	* Освободить ресурсы, использованные для хранения параметров,           *
	* переданных в командной строке                                         *
	************************************************************************/
	LocalFree(lpvCertBuffer);

	FreePointersList(lpszContainers,
	                 dwContainersCount);

	FreePointersList(lpszCSPs,
	                 dwCSPsCount);

	LocalFree(lpszContainerName);

	LocalFree(lpszCertFileName);

	LocalFree(lpszCSPName);

	if (bResult) {
		wprintf(L"Success.");
	} else {
		wprintf(L"Error occurred.");
	}

	return 0;
}
