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

/*!
 * \file $RCSfile$
 * \version $Revision: 206532 $
 * \date $Date:: 2020-02-12 14:10:57 +0300#$
 * \author $Author: sagafyin $
 * \brief Функция регистрации считывателя.
 */

#include "fat12prj.h"


static const TCHAR BASE_NAME_CFG[] = _TEXT("hdimage");

/*!
 * \ingroup hdimage_fun_reader
 * \brief Функция регистрации считывателя.
 * \param context [in] контекст считывателя.
 * \param info [in/out] структура #TSupSysInfoRegister
 * \sa #TSupSysInfoRegister, #SUPSYS_FUN_REGISTER, 
 *  #TSupSysFunction, #hdimage_info_unregister, 
 *  #rdr_unregister
 * \return Код ошибки
 * \retval #ERROR_SUCCESS считыватель зарегистрирован
 * \retval #(DWORD)ERROR_INVALID_PARAMETER при неправильно переданных параметрах
 * \retval #(DWORD)NTE_NO_MEMORY при нехватке оперативной памяти
 * \retval #(DWORD)NTE_PROVIDER_DLL_FAIL при сбоях или неправильной установке
 */
static DWORD hdimage_register_ex(TSupSysContext *context, TSupSysInfo *info, BOOL is_hsm)
{
    TSupSysInfoRegister *inf = (TSupSysInfoRegister*)info;
    TFat12Context *ctx;
    DWORD code;
    TCHAR * reg_path = NULL;
    size_t reg_length;


    SUPSYS_PRE(context == NULL);
    SUPSYS_PRE_INFO(info, TSupSysInfoRegister);

    support_set_library(inf->support_module);

#ifndef UNIX
    if (support_path2dir(NULL, NULL, NULL))
	return (DWORD)NTE_PROVIDER_DLL_FAIL;
#endif
    inf->context = NULL;
    ctx = malloc(sizeof(TFat12Context));
    if (ctx == NULL) {
	return (DWORD)NTE_NO_MEMORY;
    }
    reg_length = _tcslen(BASE_PATH_CFG) + 1 + _tcslen(BASE_NAME_CFG) + 1 + _tcslen(DEFAULT_CONNECT) + 1 + _tcslen(LONG_NAMES_KEY) + 1;
    reg_path = malloc(reg_length*sizeof(TCHAR));
    if (!reg_path) {
	free(ctx); 
	return (DWORD)NTE_NO_MEMORY;
    }
    _sntprintf(reg_path, reg_length, _TEXT("%s\\%s\\%s\\%s"), BASE_PATH_CFG, BASE_NAME_CFG, DEFAULT_CONNECT, LONG_NAMES_KEY);
    ctx->long_names = get_registry_long_names_flag(reg_path);
    free(reg_path);

    ctx->path = NULL;
    ctx->path_to_item = NULL;
    code = hdimage_path_default(&(ctx->path), 0, is_hsm);
    if (code) {
	free(ctx->path);
	free(ctx);
	return code;
    }
    ctx->folder = NULL;
    ctx->flags = FAT12_FLAG_HDIMAGE;
    ctx->nickname[0] = 0;
    ctx->connect[0] = 0;
    ctx->is_encrypted = is_hsm;
#ifdef UNIX
    ctx->handle = NULL;
    ctx->locked = FALSE;
    _tcscpy(ctx->lock_name, TEXT("hdimage_lock"));
#else /* UNIX */
    ctx->handle = INVALID_HANDLE_VALUE;
#endif /* UNIX */

    inf->context = ctx;
    return ERROR_SUCCESS;
}

DWORD hdimage_register(TSupSysContext *context, TSupSysInfo *info)
{
    return hdimage_register_ex(context, info, FALSE);
}

DWORD ehdimage_register(TSupSysContext *context, TSupSysInfo *info)
{
    return hdimage_register_ex(context, info, TRUE);
}

DWORD hdimage_unregister(TSupSysContext *context, TSupSysInfo *info)
{
    TFat12Context *ctx = (TFat12Context*)context;
    UNUSED(info);

    /* Проверка входных параметров. */
    if (ctx == NULL)
	return ERROR_SUCCESS;
    free(ctx->path);
    free(ctx->path_to_item);
    free(ctx);
    return ERROR_SUCCESS;
}

DWORD hdimage_local_machine(void *context, TSupSysInfo *info)
{
    int *inf = (int*)info;
    TFat12Context *ctx = (TFat12Context*)context;
    DWORD code;
    TCHAR *path;
    int machine;

    SUPSYS_PRE_CONTEXT(context, TFat12Context);
    SUPSYS_PRE_INFO(info, int);

    /*
    sagafyin: hdimage_path_default при частых независимых обращениях к носителям (например, при постоянном перечислении)
    кушает прилично ресурсов. Напрашивается оптимизация if (machine == ctx->machine) return 0, но так делать нельзя - 
    ломается работа под пользователями в службе, т.к. для разных пользователей будут разные path'и, а мы на данном уровне
    вроде (?) не можем определить, тот ли это пользователь, что был в прошлый раз. 
    Так что пусть кушает ресурсы - может, как-нибудь на досуге придумаем нормальную оптимизацию
    */
    machine = (*inf & 1);
    code = hdimage_path_default(&path, machine, ctx->is_encrypted);
    if (code)
	return code;
    ctx->machine = machine;
    free(ctx->path);
    ctx->path = path;
    return ERROR_SUCCESS;
}
