/*
 * Copyright(C) 2000 Проект ИОК
 *
 * Этот файл содержит информацию, являющуюся
 * собственностью компании Крипто Про.
 *
 * Любая часть этого файла не может быть скопирована,
 * исправлена, переведена на другие языки,
 * локализована или модифицирована любым способом,
 * откомпилирована, передана по сети с или на
 * любую компьютерную систему без предварительного
 * заключения соглашения с компанией Крипто Про.
 */

/*!
 * \file $RCSfile$
 * \version $Revision: 143486 $
 * \date $Date:: 2016-08-19 13:11:47 +0300#$
 * \author $Author: sagafyin $
 *
 * \brief Функция регистрации визуализатора.
 * Проект: интерфейс к визуализаторам.
 * Функция регистрации визуализатора.
 */

#include "hvis_prj.h" 
#include "reader.kit/reader.h"

/* для борьбы с динамическим распределением памяти не выделяем память под THvisLevel,
 * а в указатель пишем THvisLevel (или читаем из указателя THvisLevel)
 * Это смущает статические анализаторы, но безопасно,
 * т.к. sizeof(THvisLevel) <= sizeof(void*)
 */

 /* Освобождение контекста считывателя. */
static DWORD hvis_free_item(TSupSysContext *list, TSupSysInfo *info);
/* Дублирование контекста считывателя. */
static DWORD hvis_dup_item(TSupSysContext *list, TSupSysInfo *info);
static DWORD hvis_alloc_item(TSupSysContext *list, TSupSysInfo *info);
static DWORD hvis_info_base_path(TSupSysContext *context, TSupSysInfo *info);
static DWORD hvis_info_version(TSupSysContext *context, TSupSysInfo *info);

static const TCHAR HASHVIS_LIST_PARAM_LEVEL[] = _TEXT("\\Level");

static const TCHAR TC_HVIS_MSI_TITLE[] = _TEXT("hvis");
static const TCHAR TC_HVIS_ENTRY_POINT[] = _TEXT("_hvis_get_table");
static const TCHAR TC_HVIS_GROUP_POINT[] = _TEXT("_hvis_get_group_table");

static const TCHAR HVIS_BASE_PATH[] = _TEXT("\\Config\\Display\\");

static const TSupSysInfoIDSBaseItem HVIS_IDS_BASE_ITEMS[] =
{
    {
	SUPSYS_IDS_BLOCK_WND,
	IDS_HVIS_WND_BASE,
	SUPSYS_IDS_WND_LAST
    },
    {
	READER_IDS_BLOCK,
	READER_IDS_BASE,
	READER_IDS_QUANT_V1
    }
};

/*!
* \ingroup hvis_internal
* \brief Таблица баз и границ строк в ресурсе по умолчанию.
*/
static const TSupSysInfoIDSBase HVIS_IDS_BASE =
{
    sizeof(HVIS_IDS_BASE_ITEMS) / sizeof(TSupSysInfoIDSBaseItem),
    HVIS_IDS_BASE_ITEMS
};


static DWORD hvis_info_ids(
    TSupSysContext *context,
    TSupSysInfo *info)
{
    UNUSED(context);

    SUPSYS_PRE_INFO(info, TSupSysInfoIDSBase);
    memcpy(info, &HVIS_IDS_BASE, sizeof(TSupSysInfoIDSBase));
    return ERROR_SUCCESS;
}

/*!
* \brief Функция заполнения параметров регистрации
* \param context [in] не используется
* \param info [in,out] информация для регистрации
* \return #ERROR_SUCCESS, #NTE_NO_MEMORY
*/
static DWORD hvis_alloc_item(TSupSysContext *context, TSupSysInfo *info)
{
    TSupSysListItemAlloc *inf = (TSupSysListItemAlloc*)info;

    UNUSED(context);
    SUPSYS_PRE_CCONTEXT(info, TSupSysListItemAlloc);
    /* см.комментарий в начале файла */
    memcpy(&inf->owner, &inf->add_info, sizeof(THvisLevel));
    return ERROR_SUCCESS;
}

static DWORD info_base_path(TSupSysEContext *context, TSupSysInfo *info,
    const TCHAR *path)
{
    TSupSysInfoText *inf = (TSupSysInfoText*)info;

    UNUSED(context);
    SUPSYS_PRE_INFO(info, TSupSysInfoText);
    if (inf->length && inf->text)
    {
	_tcsncpy(inf->text, path, inf->length);
	inf->text[inf->length] = 0;
    }
    inf->length = _tcslen(path);
    return ERROR_SUCCESS;
}


/*!
* \brief Функция сравнения регистрируемого элемента и проверяемого
* \param context [in] не используется
* \param info [in,out] информация для регистрации
* \return результат проверки
* \retval "< 0" регитсрируемый элемент меньше текущего
* \retval ">= 0" регистрируемый элемент больше текущего
*/
static DWORD hvis_info_base_path(TSupSysContext *context, TSupSysInfo *info)
{
    return info_base_path(context, info, HVIS_BASE_PATH);
}

static DWORD hvis_compare_item(TSupSysContext *context, TSupSysInfo *info)
{
    TSupSysListItemCompare *inf = (TSupSysListItemCompare*)info;
    void *item1, *item2;
    THvisLevel x1, x2;

    SUPSYS_PRE_INFO(info, TSupSysListItemCompare);
    UNUSED(context);

    /* см.комментарий в начале файла */
    item1 = supsys_owner_context(inf->item1);
    item2 = supsys_owner_context(inf->item2);

    memcpy(&x1, &item1, sizeof(THvisLevel));
    memcpy(&x2, &item2, sizeof(THvisLevel));
    inf->res = x1 - x2;

    return ERROR_SUCCESS;
}

static DWORD retTCHARConst(TSupSysContext *context, TSupSysInfo *info, SHORT reason)
{
    TSupSysInfoNickname *nick = (TSupSysInfoNickname *)info;

    UNUSED(context);

    if (info == NULL)
	return (DWORD)ERROR_INVALID_PARAMETER;

    switch (reason) {
    case 1:
	_tcscpy(nick->nickname, TC_HVIS_MSI_TITLE);
	break;
    case 2:
	_tcscpy(nick->nickname, TC_HVIS_ENTRY_POINT);
	break;
    case 3:
	_tcscpy(nick->nickname, TC_HVIS_GROUP_POINT);
	break;
    default:
	return (DWORD)ERROR_INVALID_PARAMETER;
    }
    return 0;
}


/*!
* \brief Функция дублирования HANDLE
* \param context [in] не используется
* \param info [in,out] информация для регистрации
* \return #ERROR_SUCCESS
*/
static DWORD hvis_dup_item(TSupSysContext *context, TSupSysInfo *info)
{
    TSupSysListItemDup *inf = (TSupSysListItemDup*)info;
    void *p;

    SUPSYS_PRE_INFO(info, TSupSysListItemDup);
    UNUSED(context);

    /* см.комментарий в начале файла */
    p = supsys_owner_context(inf->src);
    memcpy(&inf->dest_owner, &p, sizeof(THvisLevel));
    return ERROR_SUCCESS;
}

static DWORD hvis_free_item(TSupSysContext *context, TSupSysInfo *info)
{
    UNUSED(context);
    UNUSED(info);
    return ERROR_SUCCESS;
}

/*!
* \brief Функция получения информации для регистрации из реестра
* \param context [in] не используется
* \param info [in,out] информация для регистрации
* \return \link support_error Код ошибки\endlink
*/
static DWORD hvis_info_get_fun(TSupSysContext *context, TSupSysInfo *info)
{
    TCHAR *ptr;
    DWORD code;
    long l;
    THvisLevel x;
    TSupSysListItemInfoGet *inf = (TSupSysListItemInfoGet*)info;

    SUPSYS_PRE_INFO(info, TSupSysListItemInfoGet);
    SUPSYS_PRE_STRING_PTRS(inf->path.text, inf->path.length);
    UNUSED(context);

    ptr = malloc((inf->path.length + _tcslen(HASHVIS_LIST_PARAM_LEVEL) + 1)
	* sizeof(TCHAR));
    if (ptr == NULL)
	return (DWORD)NTE_NO_MEMORY;
    _tcscpy(ptr, inf->path.text);
    _tcscat(ptr, HASHVIS_LIST_PARAM_LEVEL);
    code = support_registry_get_long(ptr, &l);
    free(ptr);
    if (code == (DWORD)ERROR_FILE_NOT_FOUND)
    {
	l = -1;
	code = ERROR_SUCCESS;
    }
    if (code)
	return code;
    x = (THvisLevel)l;
    memcpy(&inf->info.info, &x, sizeof(THvisLevel));
    inf->info.length = sizeof(THvisLevel);
    return ERROR_SUCCESS;
}

/*!
* \brief Функция уничтожения информации для регистрации
* \param context [in] не используется
* \param info [in] не используется
*/
static DWORD hvis_info_free_fun(TSupSysContext *context, TSupSysInfo *info)
{
    UNUSED(context);
    UNUSED(info);
    return ERROR_SUCCESS;
}

static DWORD hvis_msi_title(TSupSysContext *context, TSupSysInfo *info)
{
    return retTCHARConst(context, info, 1);
}

static DWORD hvis_prefix_name(TSupSysContext *context, TSupSysInfo *info)
{
    return retTCHARConst(context, info, 2);
}

static DWORD hvis_group_name(TSupSysContext *context, TSupSysInfo *info)
{
    return retTCHARConst(context, info, 3);
}

static const TSupSysFunctionTableItem HVIS_FUNS[] =
{
    { SUPSYS_FUN_IDS_BLOCK, hvis_info_ids },
    { SUPSYSL_FUN_BASE_PATH, hvis_info_base_path },
    { SUPSYSL_FUN_MSI_TITLE, hvis_msi_title },
    { SUPSYSL_FUN_PREFIX_NAME, hvis_prefix_name },
    { SUPSYSL_FUN_PREFIX_GROUP, hvis_group_name },

    { SUPSYSL_FUN_ITEM_ALLOC, hvis_alloc_item },
    { SUPSYSL_FUN_ITEM_FREE, hvis_free_item },
    { SUPSYSL_FUN_ITEM_DUP, hvis_dup_item },
    { SUPSYSL_FUN_ITEM_COMPARE, hvis_compare_item },
    { SUPSYSL_FUN_ITEM_INFO_GET, hvis_info_get_fun },
    { SUPSYSL_FUN_ITEM_INFO_FREE, hvis_info_free_fun },
    { SUPSYSL_FUN_ITEM_INFO_VERSION, hvis_info_version },
};

static const TSupSysFunctionTable HVIS_TABLE =
{
    sizeof(HVIS_FUNS) / sizeof(TSupSysFunctionTableItem),
    HVIS_FUNS
};

THvisLevel hvis_level_get(const TSupSysEContext *context)
{
    /* см.комментарий в начале файла */
    THvisLevel level;
    void *h = supsys_owner_context(context);
    memcpy(&level, &h, sizeof(THvisLevel));
    return level;
}

DWORD hvis_level_set(const TSupSysEContext *context, THvisLevel level)
{
    DWORD code;
    TCHAR *path;
    TSupSysNickname nickname;
    size_t length;
    static const TCHAR DEFAULT_CONNECT[] = _TEXT("Default");
    TCHAR *ptr;
    int def = 0;

    code = supsys_nickname(context, nickname);
    if (code)
	return code;
    code = supsys_connect_current(context, &length, NULL);
    if (code)
	return code;
    if (length == 0)
    {
	length = _tcslen(DEFAULT_CONNECT);
	def = 1;
    }
    ptr = malloc((length + 1) * sizeof(TCHAR));
    if (!ptr)
	return (DWORD)NTE_NO_MEMORY;
    if (!def)
    {
	code = supsys_connect_current(context, &length, ptr);
	if (code)
	{
	    free(ptr);
	    return code;
	}
    }
    else
	_tcscpy(ptr, DEFAULT_CONNECT);
    path = malloc((_tcslen(HVIS_BASE_PATH) + _tcslen(nickname)
	+ 1 + length
	+ _tcslen(HASHVIS_LIST_PARAM_LEVEL) + 1) * sizeof(TCHAR));
    if (path == NULL)
    {
	free(ptr);
	return (DWORD)NTE_NO_MEMORY;
    }
    _tcscpy(path, HVIS_BASE_PATH);
    _tcscat(path, nickname);
    _tcscat(path, _TEXT("\\"));
    _tcscat(path, ptr);
    free(ptr);
    _tcscat(path, HASHVIS_LIST_PARAM_LEVEL);
    code = support_registry_put_long(path, level);
    free(path);
    if (code == (DWORD)NTE_NO_MEMORY)
	return code;
    if (code)
	return (DWORD)NTE_PROVIDER_DLL_FAIL;
    return ERROR_SUCCESS;
}

DWORD hvis_register_start(TSupSysEList **list)
{
    return supsys_register_start(list, &HVIS_TABLE);
}

static DWORD hvis_info_version(TSupSysContext *context, TSupSysInfo *info)
{
    static const TSupSysInfoVersion _VERSION = { 3,6,0,0 };
    UNUSED(context);

    if (info == NULL)
	return (DWORD)ERROR_INVALID_PARAMETER;

    memcpy(info, &_VERSION, sizeof(_VERSION));
    return ERROR_SUCCESS;
}

