summaryrefslogtreecommitdiff
path: root/gameui/CDKeyEntryDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gameui/CDKeyEntryDialog.cpp')
-rw-r--r--gameui/CDKeyEntryDialog.cpp323
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();
+}