| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Installer *
- * *
- * $Archive:: /Commando/Code/Installer/SerialDialog.cpp $*
- * *
- * $Author:: Ian_l $*
- * *
- * $Modtime:: 1/15/02 11:09a $*
- * *
- * $Revision:: 10 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- // Includes.
- #include "SerialDialog.h"
- #include "CodeControl.h"
- #include "EditCtrl.h"
- #include "Installer.h"
- #include "Resource.h"
- #include "Translator.h"
- // Defines.
- #define EDIT_CONTROL_COUNT 4
- // Forward declarations.
- unsigned int Check_Sum (char *str);
- // Static data.
- static const int _EditControlIds [EDIT_CONTROL_COUNT] = {IDC_SERIAL_EDIT1,
- IDC_SERIAL_EDIT2,
- IDC_SERIAL_EDIT3,
- IDC_SERIAL_EDIT4};
- static const int _EditControlLengths [EDIT_CONTROL_COUNT] = {6, 6, 6, 4};
- static char *_SerialNumberLowRange;
- static char *_SerialNumberHighRange;
- /***********************************************************************************************
- * SerialDialogClass::On_Init_Dialog -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- void SerialDialogClass::On_Init_Dialog (void)
- {
- if (!_Installer.Beta_Test()) {
- #if USE_QA_SERIAL_NOS
- _SerialNumberLowRange = "0661";
- _SerialNumberHighRange = "0661";
- #else
- _SerialNumberLowRange = "0559";
- _SerialNumberHighRange = "0660";
- #endif
- } else {
- _SerialNumberLowRange = "0663";
- _SerialNumberHighRange = "0663";
- }
- #if NDEBUG
- #if USE_QA_SERIAL_NOS
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT1, WideStringClass (_SerialNumberLowRange));
- #endif
- #else
- // Initialize with a valid serial number.
- if (!_Installer.Beta_Test()) {
- #if USE_QA_SERIAL_NOS
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT1, WideStringClass ("066146"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT2, WideStringClass ("321463"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT3, WideStringClass ("028258"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT4, WideStringClass ("8591"));
- #else
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT1, WideStringClass ("065906"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT2, WideStringClass ("044792"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT3, WideStringClass ("767144"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT4, WideStringClass ("4915"));
- #endif
- } else {
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT1, WideStringClass ("066390"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT2, WideStringClass ("274825"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT3, WideStringClass ("508134"));
- Set_Dlg_Item_Text (IDC_SERIAL_EDIT4, WideStringClass ("6328"));
- }
- #endif
- InstallMenuDialogClass::On_Init_Dialog();
- }
- /***********************************************************************************************
- * SerialDialogClass::On_Unicode_Char -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- void SerialDialogClass::On_Unicode_Char (uint16 unicode)
- {
- // Scan the edit controls for input focus...
- for (unsigned i = 0; i < EDIT_CONTROL_COUNT; i++) {
- EditCtrlClass *editcontrol = Get_Dlg_Item (_EditControlIds [i])->As_EditCtrlClass();
- // Does this control have focus?
- if (editcontrol->Has_Focus()) {
- int textlength = wcslen (editcontrol->Get_Text());
- // Is this key one of the edit keys?
- switch (unicode) {
- case VK_BACK:
- if (textlength == 0) {
- if (i > 0) {
-
- EditCtrlClass *preveditcontrol = Get_Dlg_Item (_EditControlIds [i - 1])->As_EditCtrlClass();
- preveditcontrol->Set_Focus();
- preveditcontrol->Set_Sel (-1, -1);
- }
-
- } else {
- InstallMenuDialogClass::On_Unicode_Char (unicode);
- }
- break;
- case VK_DELETE:
- case VK_HOME:
- case VK_END:
- case VK_LEFT:
- case VK_RIGHT:
- case VK_RETURN:
- case VK_UP:
- case VK_DOWN:
- case VK_TAB:
- // Process the key.
- InstallMenuDialogClass::On_Unicode_Char (unicode);
- break;
- default:
-
- // Is it a numeric key?
- if ((unicode >= L'0') && (unicode <= L'9')) {
- if (textlength < _EditControlLengths [i]) {
-
- // Process the key.
- InstallMenuDialogClass::On_Unicode_Char (unicode);
- textlength = wcslen (editcontrol->Get_Text());
- // If the edit control is now full and the caret is at the end...
- if ((textlength == _EditControlLengths [i]) && (textlength == editcontrol->Get_Caret_Pos())) {
- // If the next edit control is empty switch focus to it.
- if (i < EDIT_CONTROL_COUNT - 1) {
- EditCtrlClass *nexteditcontrol = Get_Dlg_Item (_EditControlIds [i + 1])->As_EditCtrlClass();
- if (wcslen (nexteditcontrol->Get_Text()) == 0) {
- nexteditcontrol->Set_Focus();
- }
- }
- }
- } else {
- if ((textlength == _EditControlLengths [i]) && (textlength == editcontrol->Get_Caret_Pos())) {
-
- // If the next edit control is empty switch focus to it and process the key.
- if (i < EDIT_CONTROL_COUNT - 1) {
- EditCtrlClass *nexteditcontrol = Get_Dlg_Item (_EditControlIds [i + 1])->As_EditCtrlClass();
- if (wcslen (nexteditcontrol->Get_Text()) == 0) {
- nexteditcontrol->Set_Focus();
- InstallMenuDialogClass::On_Unicode_Char (unicode);
- }
- }
- }
- }
- }
- }
- break;
- }
- }
- }
- /***********************************************************************************************
- * SerialDialogClass::On_Command -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- void SerialDialogClass::On_Command (int ctrl_id, int message_id, DWORD param)
- {
- bool valid = true;
- switch (ctrl_id) {
- case IDOK:
- {
- StringClass serialnumber;
- valid = Get_Serial_Number (serialnumber);
- if (valid) {
- #if NDEBUG
- StringClass lowrange (_SerialNumberLowRange);
- StringClass highrange (_SerialNumberHighRange);
-
- // Limit range of serial number.
- valid = !(((_strnicmp (serialnumber, lowrange, 4) < 0) || (_strnicmp (serialnumber, highrange, 4) > 0)));
- #endif
- if (valid) {
- unsigned i, v;
-
- // Scan the string for all zeros.
- v = 0;
- for (i = 0; i < (unsigned) serialnumber.Get_Length(); i++) {
- v += *(serialnumber.Peek_Buffer() + i) - '0';
- }
- valid = (v > 0);
- if (valid) {
-
- const unsigned offset = 18;
- StringClass checksumstring (serialnumber);
- unsigned checksum;
- // Apply checksum test.
- *(checksumstring.Peek_Buffer() + offset) = '\0';
- checksum = Check_Sum (checksumstring.Peek_Buffer());
- valid = (checksum == (uint32) atol (serialnumber.Peek_Buffer() + offset));
- }
- }
- }
- break;
- }
- default:
- // Do nothing.
- break;
- }
-
- if (valid) {
- InstallMenuDialogClass::On_Command (ctrl_id, message_id, param);
- } else {
- MessageBoxClass::Do_Dialog (TxWideStringClass (IDS_WARNING), TxWideStringClass (IDS_INCORRECT_SERIAL), MessageBoxClass::MESSAGE_BOX_TYPE_OK, this);
- }
- }
- /***********************************************************************************************
- * SerialDialogClass::Get_Serial_Number -- *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/01 IML : Created. *
- *=============================================================================================*/
- bool SerialDialogClass::Get_Serial_Number (StringClass &serialnumber)
- {
- bool valid = false;
- for (unsigned i = 0; i < EDIT_CONTROL_COUNT; i++) {
- EditCtrlClass *editcontrol = Get_Dlg_Item (_EditControlIds [i])->As_EditCtrlClass();
- // Extract the serial number.
- WideStringClass widedigits (editcontrol->Get_Text());
- StringClass digits;
- // Ensure that the text contains correct no. of characters.
- // NOTE: Non-numeric characters have already been filtered out, so no need to check for this.
- valid = (widedigits.Get_Length() == _EditControlLengths [i]);
- if (!valid) {
- break;
- }
- widedigits.Convert_To (digits);
- serialnumber += digits;
- }
- return (valid);
- }
- /***********************************************************************************************
- * SerialDialogClass::CheckSum -- Generate a checksum number between 0...9999 from a null *
- * terminated string of numbers. *
- * *
- * INPUT: none. *
- * *
- * OUTPUT: none. *
- * *
- * WARNINGS: *
- * *
- * The checksum is divided into 2 parts. The first is computed by grabbing 7 digits at a *
- * grabbing 7 digits at a time and summing them mod 97. The second part is computed by *
- * grabbing 5 digits at a time and The second part is computed by grabbing 5 digits at a *
- * time and summing them mod 93. *
- * *
- * Note that it's important that 97 & 93 are prime (or at least relatively prime...) and *
- * less than 100. 7 & 5 were chosen because they can stay out of phase for the length of *
- * the input string. *
- * *
- * The two components together make the checksum. This will catch all errors of 1 & 2 *
- * digits and many other errors, but the proof is left as an exercise to the reader. *
- * *
- * Note, if you try and checksum ammounts over 30 chars the above guarantees will fail. *
- * (That's the number of chars that the skip & offset values will stay out of phase). * *
- * *
- * Note: The checksum of all zeros will be 0 so you need to special case the check to not *
- * allow this (since it's a pretty obvious thing for a user to type all 0's to try and *
- * cheat the system). *
- * *
- * HISTORY: *
- * 10/30/1995 MML : Created. *
- *=============================================================================================*/
- unsigned int Check_Sum (char *str)
- {
- unsigned int counter = 0;
- unsigned int retval = 0;
- unsigned int group = 0;
- int len = strlen( str );
- int mult = 0;
- int i;
- int j;
-
- const int skipa = 7; // part A's skip value
- const int skipb = 5; // ... part B
- const int offsa = -5; // Everywhere the skips are in phase is a place where an 2nd error can occur and not be detected.
- //---------------------------------------------------------------------------
- // Part1
- //---------------------------------------------------------------------------
- counter = 0;
- for ( i = offsa; i < len; i += skipa ) {
- mult = 1;
- for ( j = 1; j < skipa; j++ ) {
- mult *= 10;
- }
-
- group = 0;
- for ( j = i; j < MIN( len, i+skipa ); j++ ) {
- if ( j >= 0 ) {
- group += ((int)( str[j] - '0' )) * mult;
- }
- mult /= 10;
- }
- counter += group;
- counter %= 97;
- }
- retval = counter * 100;
-
- //---------------------------------------------------------------------------
- // Part2
- //---------------------------------------------------------------------------
- counter = 0;
- for ( i = 0; i < len; i += skipb ) {
- mult = 1;
- for ( j = 1; j < skipb; j++ ) {
- mult *= 10;
- }
-
- group = 0;
- for ( j = i; j < MIN( len, i+skipb ); j++ ) {
- if ( j >= 0 ) {
- group += ((int)( str[j] - '0' )) * mult;
- }
- mult /= 10;
- }
- counter += group;
- counter %= 93;
- }
- retval += counter;
-
- return (retval);
- }
|