Files correlati : Ricompilazione Demo : [ ] Commento : colors.* Aggiunta funzione per calcolo distanza tra colori per gestione trasparenze in menu principale dongle.cpp Corretta gestione chiave Eutron normale (non SV) image.cpp Migliorata gestion etrasparenze progind.cpp Corretta gestione messaggi su piu' righe relapp.cpp Corretta traduzione messaggi di richiesta salvataggio validate.cpp Sostituita TFixed_string errata con la corretta const TString& git-svn-id: svn://10.65.10.50/trunk@11123 c028cbd2-c16b-5b4b-a496-9718f37d4682
851 lines
20 KiB
C++
Executable File
851 lines
20 KiB
C++
Executable File
#include <xvt.h>
|
||
|
||
#include <applicat.h>
|
||
#include <config.h>
|
||
#include <dongle.h>
|
||
#include <isamrpc.h>
|
||
#include <utility.h>
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Dongle stuff
|
||
///////////////////////////////////////////////////////////
|
||
|
||
#ifndef _DEMO_
|
||
|
||
#define USERADR 26952
|
||
#define AGAADR 26953
|
||
#define PRASSIADR 26954
|
||
#define REFKEY (unsigned char*)"CAMPOKEY"
|
||
#define VERKEY (unsigned char*)"ìpÙˆ¬cê<"
|
||
|
||
#pragma pack(push, 1)
|
||
|
||
struct TEutronHeader
|
||
{
|
||
char _serno[8]; // 8
|
||
unsigned short _year_assist; // 10
|
||
unsigned short _max_users; // 12
|
||
unsigned long _last_date; // 16
|
||
unsigned long _scad_date; // 20
|
||
unsigned long _checksum; // 24
|
||
unsigned short _version; // 26
|
||
unsigned short _patch; // 28
|
||
unsigned short _offset_to_bits; // 30
|
||
unsigned short _size_of_bits; // 32
|
||
};
|
||
|
||
struct TEutronFooter
|
||
{
|
||
unsigned long _size; // Should be sizeof(TEutronFooter)
|
||
unsigned long _checksum; // Much smarter position than header
|
||
unsigned long _filler1;
|
||
unsigned long _filler2;
|
||
unsigned long _filler3;
|
||
unsigned long _filler4;
|
||
unsigned long _filler5;
|
||
unsigned long _last_assist; // Last date of assistance query
|
||
unsigned long _assistance[MAX_DONGLE_ASSIST]; // Pre-payed assistance
|
||
|
||
unsigned long checksum(bool set);
|
||
bool valid();
|
||
TEutronFooter();
|
||
};
|
||
|
||
#pragma pack(pop)
|
||
|
||
TEutronFooter::TEutronFooter()
|
||
{
|
||
const int s = sizeof(TEutronFooter);
|
||
memset(&_size, 0, s);
|
||
_size = s;
|
||
}
|
||
|
||
unsigned long TEutronFooter::checksum(bool set)
|
||
{
|
||
if (set) _size = sizeof(TEutronFooter);
|
||
|
||
const word offset = sizeof(_size) + sizeof(_checksum);
|
||
byte* ptr = (byte*)(&_size) + offset;
|
||
const word len = word(_size - offset);
|
||
|
||
unsigned long cs = 0;
|
||
for (word i = 0; i < len; i++, ptr++)
|
||
cs += *ptr | ~(*ptr << 8);
|
||
if (set) _checksum = cs;
|
||
return cs;
|
||
}
|
||
|
||
bool TEutronFooter::valid()
|
||
{
|
||
if (_size == 0 || _checksum == 0)
|
||
return FALSE;
|
||
return _checksum == checksum(FALSE);
|
||
}
|
||
|
||
#endif // _DEMO_
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Current dongle
|
||
///////////////////////////////////////////////////////////
|
||
|
||
static TDongle* _dongle = NULL;
|
||
|
||
TDongle& dongle()
|
||
{
|
||
if (_dongle == NULL)
|
||
_dongle = new TDongle;
|
||
return *_dongle;
|
||
}
|
||
|
||
bool destroy_dongle()
|
||
{
|
||
bool ok = _dongle != NULL;
|
||
if (ok)
|
||
{
|
||
delete _dongle;
|
||
_dongle = NULL;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Bit helper functions
|
||
///////////////////////////////////////////////////////////
|
||
|
||
inline bool test_bit(word w, int b)
|
||
{
|
||
bool on = (w & (1 << b)) != 0;
|
||
return on;
|
||
}
|
||
|
||
inline void set_bit(word& w, int b, bool on = TRUE)
|
||
{
|
||
if (on)
|
||
w |= 1 << b;
|
||
else
|
||
w &= ~(1 << b);
|
||
}
|
||
|
||
inline void reset_bit(word& w, byte b)
|
||
{
|
||
w &= ~(1 << b);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TDongle
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TDongle::TDongle()
|
||
: _hardware(_dongle_unknown), _type(_no_dongle), _serno(0xFFFF),
|
||
_dirty(FALSE), _max_users(1), _year_assist(1997)
|
||
{
|
||
memset(_eprom, 0, sizeof(_eprom));
|
||
memset(_assist, 0, sizeof(_assist));
|
||
}
|
||
|
||
TDongle::~TDongle()
|
||
{
|
||
if (_serno != 0xFFFF)
|
||
logout();
|
||
}
|
||
|
||
const TString& TDongle::administrator(TString* pwd)
|
||
{
|
||
if (_admin.empty())
|
||
{
|
||
TConfig ini("install.ini", "Main");
|
||
_admin = ini.get("Administrator");
|
||
if (_admin.empty())
|
||
_admin = "ADMIN";
|
||
else
|
||
_admin = ::decode(_admin);
|
||
_admpwd = ini.get("Password");
|
||
if (_admpwd.empty())
|
||
{
|
||
_admpwd = _admin;
|
||
_admpwd.lower();
|
||
_admpwd.insert(".", 2);
|
||
}
|
||
else
|
||
_admpwd = ::decode(_admpwd);
|
||
}
|
||
if (pwd)
|
||
*pwd = _admpwd;
|
||
return _admin;
|
||
}
|
||
|
||
|
||
// Data punta ad un array di 4 words
|
||
// Deve essere cosi' per problemi del C,
|
||
// non trasformare in array: pena di morte!
|
||
void TDongle::garble(word* data) const
|
||
{
|
||
#ifndef _DEMO_
|
||
switch (_hardware)
|
||
{
|
||
case _dongle_hardlock:
|
||
xvt_dongle_hl_crypt(data);
|
||
break;
|
||
case _dongle_eutron:
|
||
xvt_dongle_sl_crypt(data);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
bool TDongle::already_programmed() const
|
||
{
|
||
#ifndef _DEMO_
|
||
if (_hardware == _dongle_hardlock)
|
||
{
|
||
word data[4];
|
||
memcpy(data, &_eprom[60], sizeof(data));
|
||
garble(data);
|
||
|
||
if (data[0] < 1997 || data[0] > 2997)
|
||
return FALSE;
|
||
|
||
if (data[1] == 0 || data[1] >= 10000)
|
||
return FALSE;
|
||
|
||
const TDate today(TODAY);
|
||
const long& giulio = (const long&)data[2];
|
||
const long yyyymmdd = today.julian2date(giulio);
|
||
const TDate d(yyyymmdd);
|
||
if (d.year() < 1997 || d > today)
|
||
return FALSE;
|
||
} else
|
||
if (_hardware == _dongle_eutron)
|
||
{
|
||
const TEutronHeader* eh = (const TEutronHeader*)_eprom;
|
||
if (eh->_serno[0] == 0 || eh->_checksum == 0)
|
||
return FALSE; // Really virgin.
|
||
|
||
unsigned long cs = 0;
|
||
for (byte* ptr = (byte*)_eprom; ptr < (byte*)&eh->_checksum; ptr++)
|
||
cs += *ptr | ~(*ptr << 8);
|
||
if (eh->_checksum != cs)
|
||
return FALSE; // Malicious programming!
|
||
}
|
||
#endif // _DEMO_
|
||
return TRUE;
|
||
}
|
||
|
||
#ifndef _DEMO_
|
||
|
||
bool TDongle::hardlock_login(bool test_all_keys)
|
||
{
|
||
bool ok = TRUE;
|
||
_type = _user_dongle;
|
||
if (test_all_keys)
|
||
{
|
||
xvt_dongle_hl_logout();
|
||
if (xvt_dongle_hl_login(AGAADR, REFKEY, VERKEY))
|
||
_type = _aga_dongle;
|
||
else
|
||
{
|
||
xvt_dongle_hl_logout();
|
||
if (xvt_dongle_hl_login(PRASSIADR, REFKEY, VERKEY))
|
||
_type = _prassi_dongle;
|
||
}
|
||
}
|
||
xvt_dongle_hl_logout();
|
||
ok = xvt_dongle_hl_login(USERADR, REFKEY, VERKEY) != 0;
|
||
|
||
if (ok)
|
||
{
|
||
_hardware = _dongle_hardlock;
|
||
|
||
xvt_dongle_hl_read_block((unsigned char*)_eprom);
|
||
|
||
word data[4];
|
||
memcpy(data, _eprom, sizeof(data));
|
||
garble(data);
|
||
|
||
if (data[0] == 0xFAE8)
|
||
_serno = data[1];
|
||
else
|
||
{
|
||
if (data[0] == 0x3283 || data[0] == 0xA3AA) // chiave programmatori !!
|
||
{
|
||
if (_type == _user_dongle)
|
||
_type = _developer_dongle;
|
||
_serno = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ok)
|
||
{
|
||
_max_users = 1;
|
||
_last_update = TDate(TODAY);
|
||
_year_assist = _last_update.year();
|
||
|
||
if (_type == _user_dongle)
|
||
{
|
||
const bool already = already_programmed();
|
||
|
||
_module.reset(); // Disattiva tutti i moduli
|
||
const int last_word = already ? 12 : 4;
|
||
word data[4];
|
||
|
||
// Legge flag di attivazione dei moduli
|
||
for (int i = 0; i < last_word; i += 4)
|
||
{
|
||
memcpy(data, &_eprom[48+i], sizeof(data));
|
||
garble(data);
|
||
if (data[3] == _serno) // Validate block
|
||
{
|
||
for (int j = 0; j < 3; j++)
|
||
{
|
||
word parola = data[j] ^ _serno;
|
||
if (parola)
|
||
{
|
||
for (int b = 15; b >= 0; b--)
|
||
{
|
||
if (test_bit(parola, b))
|
||
{
|
||
const word bit = i * 12 + j * 16 + b;
|
||
_module.set(bit+1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
_module.set(0, TRUE); // Forza l'attivazione della base
|
||
|
||
// Legge anno di assitenza e numero massimo di utenti
|
||
memcpy(data, &_eprom[60], sizeof(data));
|
||
garble(data);
|
||
|
||
if (already)
|
||
{
|
||
_year_assist = data[0];
|
||
_max_users = data[1];
|
||
const long& giulio = (const long&)data[2];
|
||
const long yyyymmdd = _last_update.julian2date(giulio);
|
||
_last_update = yyyymmdd;
|
||
}
|
||
else
|
||
{
|
||
_year_assist = 0;
|
||
_dirty = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_module.set(255); // Last module on key
|
||
_module.set(); // Activate all modules
|
||
|
||
_max_users = 1;
|
||
_last_update = TDate(TODAY);
|
||
_year_assist = _last_update.year();
|
||
}
|
||
}
|
||
else
|
||
_type = _no_dongle;
|
||
|
||
return ok;
|
||
}
|
||
|
||
bool TDongle::eutron_login(bool test_all_keys)
|
||
{
|
||
bool ok = FALSE;
|
||
|
||
const char* labels[4] = { "AGA.INFORMATICA", "AGA.PRASSI",
|
||
"AGA.CAMPO", "25EBAI" };
|
||
TDongleType types[4] = { _aga_dongle, _prassi_dongle,
|
||
_user_dongle, _developer_dongle };
|
||
for (int k = test_all_keys ? 0 : 2; k < 4; k++)
|
||
{
|
||
const unsigned char* pwd = (const unsigned char*)::encode(labels[k]);
|
||
ok = xvt_dongle_sl_login((const unsigned char*)labels[k], pwd) != 0;
|
||
if (ok)
|
||
{
|
||
_hardware = _dongle_eutron;
|
||
_type = types[k];
|
||
break;
|
||
}
|
||
}
|
||
if (ok)
|
||
{
|
||
_serno = 0;
|
||
_max_users = 1;
|
||
_last_update = TDate(TODAY);
|
||
_year_assist = _last_update.year();
|
||
|
||
if (_type == _user_dongle)
|
||
{
|
||
_module.reset(); // Disattiva tutti i moduli
|
||
if (read_words(0, sizeof(TEutronHeader) / 2, _eprom))
|
||
{
|
||
const TEutronHeader* eh = (const TEutronHeader*)_eprom;
|
||
TString16 serno; serno.strncpy(eh->_serno, 8);
|
||
_serno = unsigned(atol(serno));
|
||
if (already_programmed())
|
||
{
|
||
_max_users = eh->_max_users;
|
||
_last_update = eh->_last_date;
|
||
_year_assist = eh->_year_assist;
|
||
|
||
// Calcola il numero della word dove cominciano i bit di attivazione
|
||
unsigned short otb = eh->_offset_to_bits;
|
||
if (otb == 0) otb = 16; // Compatibile Hardlock
|
||
|
||
unsigned short sob = eh->_size_of_bits;
|
||
if (sob == 0) sob = 16; // Compatibile Hardlock
|
||
|
||
word data[64];
|
||
if (read_words(otb, sob, data))
|
||
{
|
||
int module = 1;
|
||
for (word w = 0; w < sob; w++)
|
||
{
|
||
for (int b = 0; b < 16; b++)
|
||
{
|
||
if (test_bit(data[w], b))
|
||
_module.set(module);
|
||
module++;
|
||
}
|
||
}
|
||
}
|
||
|
||
memset(_assist, 0, sizeof(_assist)); // Azzera pre-pagato
|
||
TEutronFooter ef;
|
||
if (read_words(otb+sob, sizeof(ef)/2, (word*)&ef))
|
||
{
|
||
if (ef.valid())
|
||
{
|
||
_last_assist = ef._last_assist;
|
||
memcpy(_assist, ef._assistance, sizeof(_assist));
|
||
}
|
||
}
|
||
}
|
||
else
|
||
_dirty = TRUE;
|
||
}
|
||
_module.set(0, TRUE); // Forza l'attivazione della base
|
||
}
|
||
else
|
||
{
|
||
_module.set(255); // Last module on key
|
||
_module.set(); // Activate all modules
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDongle::network_login(bool test_all_keys)
|
||
{
|
||
if (network())
|
||
rpc_UserLogout();
|
||
|
||
TConfig ini(CONFIG_INSTALL, "Server");
|
||
const char* server = ini.get("Dongle");
|
||
const char* guest = "******";
|
||
const TString16 appname = main_app().name();
|
||
const char* utente = (!xvt_running() && appname == "ba0100") ? guest : user();
|
||
|
||
const bool ok = rpc_UserLogin(server, utente, "******", appname);
|
||
if (ok)
|
||
{
|
||
_hardware = _dongle_network;
|
||
_type = _user_dongle;
|
||
_serno = rpc_DongleNumber();
|
||
_max_users = 1;
|
||
_last_update = TDate(TODAY);
|
||
_year_assist = rpc_DongleYear();
|
||
rpc_DongleModules(_module);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
#endif // _DEMO_
|
||
|
||
int TDongle::can_try_server() const
|
||
{
|
||
if (xvt_sys_dongle_server_is_running())
|
||
return 3;
|
||
|
||
TConfig ini(CONFIG_INSTALL, "Server");
|
||
const TString& dongle = ini.get("Dongle");
|
||
return dongle.not_empty();
|
||
}
|
||
|
||
bool TDongle::login(bool test_all_keys)
|
||
{
|
||
bool ok = TRUE;
|
||
|
||
#ifdef _DEMO_
|
||
_hardware = _dongle_hardlock;
|
||
_type = _user_dongle;
|
||
_serno = 0;
|
||
_max_users = 1;
|
||
_last_update = TDate(TODAY);
|
||
_year_assist = _last_update.year();
|
||
_module.set(255); // Last module on key
|
||
_module.set(); // Activate all modules
|
||
#else
|
||
if (_type != _no_dongle) // Already logged in
|
||
logout();
|
||
|
||
TDongleHardware hw = _hardware;
|
||
if (hw == _dongle_unknown)
|
||
{
|
||
if (can_try_server())
|
||
{
|
||
hw = _dongle_network;
|
||
}
|
||
else
|
||
{
|
||
TConfig ini(CONFIG_INSTALL, "Main");
|
||
hw = (TDongleHardware)ini.get_int("Donglehw");
|
||
}
|
||
}
|
||
switch(hw)
|
||
{
|
||
case _dongle_hardlock:
|
||
ok = hardlock_login(test_all_keys);
|
||
break;
|
||
case _dongle_eutron:
|
||
ok = eutron_login(test_all_keys);
|
||
break;
|
||
case _dongle_network:
|
||
ok = network_login(test_all_keys);
|
||
break;
|
||
default:
|
||
ok = FALSE;
|
||
break;
|
||
}
|
||
if (!ok)
|
||
{
|
||
// retry login for various dongles ...
|
||
const int use_server = can_try_server();
|
||
if (use_server != 3) // Non sono obbligato ad usare il Dongle Server
|
||
{
|
||
if (!ok && hw != _dongle_eutron)
|
||
ok = eutron_login(test_all_keys);
|
||
if (!ok && hw != _dongle_hardlock)
|
||
ok = hardlock_login(test_all_keys);
|
||
}
|
||
|
||
if (ok)
|
||
{
|
||
TConfig ini(CONFIG_INSTALL, "Main");
|
||
ini.set("Donglehw",(int)_hardware);
|
||
}
|
||
}
|
||
#endif
|
||
return ok;
|
||
}
|
||
|
||
bool TDongle::logout()
|
||
{
|
||
#ifndef _DEMO_
|
||
if (_type != _no_dongle)
|
||
{
|
||
switch (_hardware)
|
||
{
|
||
case _dongle_hardlock:
|
||
xvt_dongle_hl_logout();
|
||
break;
|
||
case _dongle_eutron:
|
||
xvt_dongle_sl_logout();
|
||
break;
|
||
case _dongle_network:
|
||
rpc_UserLogout();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
_type = _no_dongle;
|
||
_serno = 0xFFFF;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// Data punta ad un array di 4 words
|
||
// Deve essere cosi' per problemi del C,
|
||
// non trasformare in array: pena di morte!
|
||
bool TDongle::read_words(word reg, word len, word* ud) const
|
||
{
|
||
bool ok = FALSE;
|
||
#ifndef _DEMO_
|
||
switch (_hardware)
|
||
{
|
||
case _dongle_hardlock:
|
||
{
|
||
for (word i = 0; i < len; i++)
|
||
xvt_dongle_hl_read(reg+i, &ud[i]);
|
||
ok = TRUE;
|
||
}
|
||
break;
|
||
case _dongle_eutron:
|
||
while (len > 0)
|
||
{
|
||
const unsigned short size = (len <= 16) ? len : 16;
|
||
ok = xvt_dongle_sl_read_block(reg, size, ud) != 0;
|
||
if (!ok)
|
||
{
|
||
yesnofatal_box("EUTRON read error");
|
||
break;
|
||
}
|
||
len -= size;
|
||
reg += size;
|
||
ud += size;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
#endif // _DEMO_
|
||
return ok;
|
||
}
|
||
|
||
// Data punta ad un array di 4 words
|
||
// Deve essere cosi' per problemi del C,
|
||
// non trasformare in array: pena di morte!
|
||
bool TDongle::write_words(word reg, word len, word* data) const
|
||
{
|
||
bool ok = FALSE;
|
||
#ifndef _DEMO_
|
||
switch(_hardware)
|
||
{
|
||
case _dongle_hardlock:
|
||
{
|
||
for (word r = 0; r < len; r++)
|
||
{
|
||
const word address = reg+r;
|
||
ok = xvt_dongle_hl_write(address, data[r]) != 0;
|
||
}
|
||
}
|
||
break;
|
||
case _dongle_eutron:
|
||
while (len > 0)
|
||
{
|
||
const unsigned short size = (len <= 16) ? len : 16;
|
||
ok = xvt_dongle_sl_write_block(reg, size, data) != 0;
|
||
if (!ok)
|
||
break;
|
||
len -= size;
|
||
reg += size;
|
||
data += size;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
#endif // _DEMO_
|
||
return ok;
|
||
}
|
||
|
||
#ifndef _DEMO_
|
||
|
||
bool TDongle::burn_hardlock()
|
||
{
|
||
word data[4];
|
||
|
||
const TDate today(TODAY);
|
||
const bool already = already_programmed();
|
||
if (already)
|
||
{
|
||
memcpy(data, &_eprom[60], sizeof(data));
|
||
garble(data);
|
||
if (data[0] < 1997 || data[0] > 2997)
|
||
return error_box("On Line Assistance error.");
|
||
if (data[1] == 0 || data[1] >= 10000)
|
||
return error_box("Bad users number.");
|
||
const long& val = (const long&)data[2];
|
||
const long yyyymmdd = today.julian2date(val);
|
||
const TDate date(yyyymmdd);
|
||
if (date > today)
|
||
return error_box("Too late sir: key has already expired!");
|
||
}
|
||
|
||
data[0] = _year_assist;
|
||
data[1] = _max_users;
|
||
long& val = (long&)data[2];
|
||
val = today.date2julian();
|
||
garble(data);
|
||
write_words(60, 4, data);
|
||
_last_update = today;
|
||
|
||
// Il primo bit della memoria della chiave corrisponde al modulo uno
|
||
// non allo zero (che e' la base ed e' sempre attivo)
|
||
word module = 1;
|
||
for (int octect = 0; octect < 3; octect++)
|
||
{
|
||
for(int parola = 0; parola < 3; parola++)
|
||
{
|
||
word& p = data[parola];
|
||
p = 0;
|
||
for (int bit = 0; bit < 16; bit++)
|
||
{
|
||
if (active(module))
|
||
set_bit(p, bit);
|
||
module++;
|
||
}
|
||
p ^= _serno;
|
||
}
|
||
data[3] = _serno;
|
||
garble(data);
|
||
write_words(48 + 4*octect, 4, data);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
bool TDongle::burn_eutron()
|
||
{
|
||
TEutronHeader* eh = (TEutronHeader*)_eprom;
|
||
memset(eh, 0, sizeof(TEutronHeader));
|
||
|
||
_last_update = TDate(TODAY);
|
||
sprintf(eh->_serno, "%lu", (unsigned long)_serno);
|
||
eh->_year_assist = _year_assist;
|
||
eh->_max_users = _max_users;
|
||
eh->_last_date = atol(_last_update.string(ANSI));
|
||
eh->_scad_date = 0;
|
||
|
||
unsigned long cs = 0;
|
||
for (byte* ptr = (byte*)_eprom; ptr < (byte*)&eh->_checksum; ptr++)
|
||
cs += *ptr | ~(*ptr << 8);
|
||
eh->_checksum = cs;
|
||
|
||
const word otb = sizeof(TEutronHeader) / 2;
|
||
const word sob = 16;
|
||
eh->_offset_to_bits = otb;
|
||
eh->_size_of_bits = sob;
|
||
|
||
bool ok = write_words(0, otb, _eprom);
|
||
|
||
if (ok)
|
||
{
|
||
word data[sob]; memset(data, 0, sizeof(data));
|
||
for (int module = 1; module < 256; module++)
|
||
{
|
||
if (active(module))
|
||
{
|
||
word& w = data[(module-1) / 16];
|
||
set_bit(w, (module-1) % 16, TRUE);
|
||
}
|
||
}
|
||
ok = write_words(otb, sob, data);
|
||
}
|
||
|
||
if (ok)
|
||
{
|
||
TEutronFooter ef;
|
||
CHECK(sizeof(ef._assistance) == sizeof(_assist), "Assistance size mismatch");
|
||
ef._last_assist = _last_assist.year()*10000L + _last_assist.month()*100L + _last_assist.day();
|
||
memcpy(ef._assistance, _assist, sizeof(_assist));
|
||
ef.checksum(TRUE);
|
||
ok = write_words(otb+sob, word(ef._size/2), (word*)&ef);
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
#endif // _DEMO_
|
||
|
||
bool TDongle::burn()
|
||
{
|
||
bool ok = local() && _type == _user_dongle;
|
||
|
||
#ifndef _DEMO_
|
||
if (ok)
|
||
{
|
||
switch(_hardware)
|
||
{
|
||
case _dongle_hardlock: ok = burn_hardlock(); break;
|
||
case _dongle_eutron : ok = burn_eutron(); break;
|
||
default : break;
|
||
}
|
||
}
|
||
#endif
|
||
if (ok)
|
||
_dirty = FALSE;
|
||
|
||
return ok;
|
||
}
|
||
|
||
#define BIT31 (1L<<31)
|
||
#define MSK31 (~BIT31)
|
||
|
||
real TDongle::residual_assist(int index, bool lire) const
|
||
{
|
||
real imp;
|
||
if (index >= 0 && index < MAX_DONGLE_ASSIST)
|
||
{
|
||
imp = (_assist[index] & MSK31) / 100.0;
|
||
if (lire)
|
||
{ imp *= 1936.27; imp.round(-2); }
|
||
}
|
||
return imp;
|
||
}
|
||
|
||
bool TDongle::can_require_assist(int index) const
|
||
{
|
||
bool ok = FALSE;
|
||
if (index >= 0 && index < MAX_DONGLE_ASSIST)
|
||
{
|
||
const TDate oggi(TODAY);
|
||
if (oggi == _last_assist)
|
||
ok = (_assist[index] & BIT31) == 0;
|
||
else
|
||
ok = oggi > _last_assist;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDongle::require_assist(int index, real imp, bool lire)
|
||
{
|
||
imp *= 100;
|
||
if (lire) { imp /= 1936.27; imp.round(2); }
|
||
|
||
bool ok = FALSE;
|
||
if (imp > ZERO)
|
||
{
|
||
if (can_require_assist(index))
|
||
{
|
||
const TDate oggi(TODAY);
|
||
if (oggi > _last_assist)
|
||
{
|
||
for (int i = 0; i < MAX_DONGLE_ASSIST; i++)
|
||
_assist[index] &= MSK31;
|
||
_last_assist = oggi;
|
||
}
|
||
_assist[index] &= MSK31;
|
||
_assist[index] += imp.integer();
|
||
_assist[index] |= BIT31;
|
||
_dirty = TRUE;
|
||
ok = burn();
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDongle::pay_assist(int index, real imp, bool lire)
|
||
{
|
||
bool ok = imp > ZERO;
|
||
if (ok)
|
||
{
|
||
imp *= 100;
|
||
if (lire) { imp /= 1936.27; imp.round(2); }
|
||
|
||
unsigned long old_bit31 = _assist[index] & BIT31;
|
||
_assist[index] &= MSK31;
|
||
_assist[index] -= imp.integer();
|
||
_assist[index] |= old_bit31;
|
||
_dirty = TRUE;
|
||
ok = burn();
|
||
}
|
||
return ok;
|
||
} |