diff options
Diffstat (limited to 'gameui/CDKeyEntryDialog.cpp')
| -rw-r--r-- | gameui/CDKeyEntryDialog.cpp | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/gameui/CDKeyEntryDialog.cpp b/gameui/CDKeyEntryDialog.cpp new file mode 100644 index 0000000..2ee6791 --- /dev/null +++ b/gameui/CDKeyEntryDialog.cpp @@ -0,0 +1,323 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "CDKeyEntryDialog.h" +#include "EngineInterface.h" + +#include "steamcommon.h" // VALVE_AUTH cd key checking code +#include "ValidateNewValveCDKeyClient.h" +#include "ValveCDKeyGameAndTerritoryCodes.h" + +#include "vgui/IInput.h" +#include "vgui/IPanel.h" +#include "vgui/ISystem.h" +#include "vgui/ISurface.h" +#include "vgui_controls/Button.h" +#include "vgui_controls/MessageBox.h" +#include "vgui_controls/TextEntry.h" +#include "vstdlib/random.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#include <ctype.h> + +using namespace vgui; + +#define FAKE_CDKEY_LEN 49 +#define FAKE_CDKEY_REGKEY "HKEY_CURRENT_USER\\Software\\Valve\\Source\\Settings\\EncryptedCDKey" + +//----------------------------------------------------------------------------- +// Purpose: hacky class to make all input uppercase +//----------------------------------------------------------------------------- +class CUpperCaseTextEntry : public vgui::TextEntry +{ + DECLARE_CLASS_SIMPLE( CUpperCaseTextEntry, vgui::TextEntry ); +public: + CUpperCaseTextEntry(vgui::Panel *parent, const char *name) : TextEntry(parent, name) {} + + virtual void InsertChar(wchar_t unichar) + { + // only allow input of valid cdkey characters + if (unichar >= 'a' && unichar <= 'z') + { + // force to be uppercase + BaseClass::InsertChar(unichar - 'a' + 'A'); + } + else if ((unichar >= 'A' && unichar <= 'Z') + || (unichar >= '0' && unichar <= '9')) + { + BaseClass::InsertChar(unichar); + } + } +}; + + +class CloseMessageBox : public vgui::MessageBox +{ +public: + CloseMessageBox(const char *title, const char *text, Panel *parent = NULL): MessageBox( title, text, parent) {} + + virtual void OnClose() + { + engine->ClientCmd_Unrestricted("quit\n"); + } +}; + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CCDKeyEntryDialog::CCDKeyEntryDialog(vgui::Panel *parent, bool inConnect) : BaseClass(parent, "CDKeyEntryDialog") +{ + // see what type of cdkey we have + SetDeleteSelfOnClose(true); + m_bInConnect = inConnect; + m_iErrCount = 0; + m_bEnteredValidCDKey = false; + + m_pOK = new Button(this, "OKButton", "#GameUI_OK"); + m_pQuitGame = new Button(this, "CancelButton", "#GameUI_Quit"); + m_pEntry1 = new CUpperCaseTextEntry(this, "Entry1");; + m_pEntry2 = new CUpperCaseTextEntry(this, "Entry2"); + m_pEntry3 = new CUpperCaseTextEntry(this, "Entry3"); + m_pEntry4 = new CUpperCaseTextEntry(this, "Entry4"); + m_pEntry5 = new CUpperCaseTextEntry(this, "Entry5"); + + m_pEntry1->SetMaximumCharCount(5); + m_pEntry2->SetMaximumCharCount(5); + m_pEntry3->SetMaximumCharCount(5); + m_pEntry4->SetMaximumCharCount(5); + m_pEntry5->SetMaximumCharCount(5); + + m_pEntry1->SetAutoProgressOnHittingCharLimit(true); + m_pEntry2->SetAutoProgressOnHittingCharLimit(true); + m_pEntry3->SetAutoProgressOnHittingCharLimit(true); + m_pEntry4->SetAutoProgressOnHittingCharLimit(true); + m_pEntry5->SetAutoProgressOnHittingCharLimit(false); + + SetSizeable(false); + SetSize(360, 224); + SetTitle("#GameUI_CDKey", true); + + LoadControlSettings("Resource/ValveCDKeyEntryDialog.res"); +// MoveToCenterOfScreen(); + + SetMinimizeButtonVisible(false); + SetMaximizeButtonVisible(false); + + m_pOK->SetEnabled(false); +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CCDKeyEntryDialog::~CCDKeyEntryDialog() +{ + vgui::surface()->RestrictPaintToSinglePanel(NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if there is a valid weak check key in the registry +//----------------------------------------------------------------------------- +bool CCDKeyEntryDialog::IsValidWeakCDKeyInRegistry() +{ + char fakekey[FAKE_CDKEY_LEN]; + if (vgui::system()->GetRegistryString(FAKE_CDKEY_REGKEY, fakekey, sizeof(fakekey))) + { + if (strlen(fakekey) == (FAKE_CDKEY_LEN - 1) + && fakekey[17] == 'E' + && fakekey[31] == 'z' + && fakekey[43] == 'n') + { + return true; + } + } + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCDKeyEntryDialog::OnCommand(const char *command) +{ + if (!stricmp(command, "OK")) + { + if (IsEnteredKeyValid()) + { + m_bEnteredValidCDKey = true; + + // write out fake key and continue + char fakekey[FAKE_CDKEY_LEN]; + for (int i = 0; i < sizeof(fakekey) - 1; i++) + { + // pick some random fields for us to check later + if (i == 17) + { + fakekey[i] = 'E'; + } + else if (i == 31) + { + fakekey[i] = 'z'; + } + else if (i == 43) + { + fakekey[i] = 'n'; + } + else + { + fakekey[i] = RandomInt('0', 'z'); + } + } + fakekey[sizeof(fakekey) - 1] = 0; + vgui::system()->SetRegistryString(FAKE_CDKEY_REGKEY, fakekey); + + if ( m_bInConnect ) + { + engine->ClientCmd_Unrestricted( "retry\n" ); // retry the server connection with this new key... + } + Close(); + } + else + { + m_hErrorBox = new MessageBox("#GameUI_CDKey_Invalid_Title","#GameUI_CDKey_Invalid_Text", this); + m_hErrorBox->ShowWindow( this ); + } + } + else if (!stricmp(command, "Cancel") || !stricmp(command, "Close")) + { + Close(); + } + else + { + BaseClass::OnCommand(command); + } + + if (!m_bEnteredValidCDKey) // moved away from the dialog box to make it a little harder to crack... + { + m_iErrCount++; + if( m_iErrCount >= MAX_CDKEY_ERRORS ) + { + // too many bad entries, make em quit + CloseMessageBox *bx = new CloseMessageBox("#GameUI_CDKey_Invalid_Title","#GameUI_CDKey_TooManyTries", this); + bx->ShowWindow( this ); + } + } + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCDKeyEntryDialog::OnClose() +{ + if (!m_bEnteredValidCDKey) + { + // if we don't have a valid key we can't continue + engine->ClientCmd_Unrestricted("quit\n"); + } + + BaseClass::OnClose(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCDKeyEntryDialog::OnThink() +{ + if (!m_bEnteredValidCDKey) + { + // force us to be the only thing to draw + VPANEL vpanel = m_hErrorBox.Get() ? m_hErrorBox->GetVPanel() : GetVPanel(); + vgui::surface()->RestrictPaintToSinglePanel(vpanel); + + // make sure we're the focus + if (!(input()->GetFocus() && ipanel()->HasParent(input()->GetFocus(), GetVPanel()))) + { + BaseClass::Activate(); + } + } + BaseClass::OnThink(); +} + +//----------------------------------------------------------------------------- +// Purpose: returns whether or not the key entered by the user passes the simple check +//----------------------------------------------------------------------------- +bool CCDKeyEntryDialog::IsEnteredKeyValid() +{ + // get the entered text + char cdkey[32]; + m_pEntry1->GetText(cdkey, 6); + m_pEntry2->GetText(cdkey + 6, 6); + m_pEntry3->GetText(cdkey + 12, 6); + m_pEntry4->GetText(cdkey + 18, 6); + m_pEntry5->GetText(cdkey + 24, 6); + + // add in the hyphens + cdkey[5] = '-'; + cdkey[11] = '-'; + cdkey[17] = '-'; + cdkey[23] = '-'; + + // verify the entry + for (int i = 0; i < 29; i++) + { + if (cdkey[i] != '-' && !isalnum(cdkey[i])) + return false; + } +#if !defined( NO_STEAM ) + uint gameCode, salesTerritoryCode, uniqueSerialNumber; + + // test key - this key passes they weak check, but not the strong check + // "5J5Q3-QCME2-2SMMV-SBHN9-43S2S" + if ( SteamWeakVerifyNewValveCDKey(cdkey, &gameCode, &salesTerritoryCode, &uniqueSerialNumber) == eSteamErrorNone ) + { + // require hl2 retail cdkey (ATI Bundle keys are also in this category) + if (gameCode == eHalfLife2) + return true; + } +#endif + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: handles user entering data in fields +//----------------------------------------------------------------------------- +void CCDKeyEntryDialog::OnTextChanged(Panel *entry) +{ + char cdkey[32]; + m_pEntry1->GetText(cdkey, 6); + m_pEntry2->GetText(cdkey + 6, 6); + m_pEntry3->GetText(cdkey + 12, 6); + m_pEntry4->GetText(cdkey + 18, 6); + m_pEntry5->GetText(cdkey + 24, 6); + + // add in the hyphens + cdkey[5] = '-'; + cdkey[11] = '-'; + cdkey[17] = '-'; + cdkey[23] = '-'; + + if (strlen(cdkey) == 29) + { + m_pOK->SetEnabled(true); + } + else + { + m_pOK->SetEnabled(false); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCDKeyEntryDialog::Activate() +{ + BaseClass::Activate(); + m_pEntry1->RequestFocus(); +} |