| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- /*
- ** 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/>.
- */
- /******************************************************************************
- *
- * FILE
- * $Archive: /Commando/Code/launcher/Protect.cpp $
- *
- * DESCRIPTION
- *
- * PROGRAMMER
- * Denzil E. Long, Jr.
- * $Author: Tom_s $
- *
- * VERSION INFO
- * $Modtime: 3/04/02 5:55p $
- * $Revision: 3 $
- *
- ******************************************************************************/
- #include "Protect.h"
- #ifdef COPY_PROTECT
- #include "BFish.h"
- #include <Support\UString.h>
- #include <Support\RefPtr.h>
- #include <Storage\File.h>
- #include <windows.h>
- #include <memory>
- #include <assert.h>
- #include <Debug\DebugPrint.h>
- #include "SafeDisk\CdaPfn.h"
- #include "..\combat\specialbuilds.h"
- // This GUID should be unique for each product. (CHANGE IT WHEN DOING THE
- // NEXT PRODUCT) Note that the game will need to agree on this GUID also, so
- // the game will have to be modified also.
- const char* const LAUNCHER_GUID = "48BC11BD-C4D7-466b-8A31-C6ABBAD47B3E";
- #ifdef OLDWAY
- /******************************************************************************
- *
- * NAME
- *
- * DESCRIPTION
- *
- * INPUTS
- *
- * RESULT
- *
- ******************************************************************************/
- Protect::Protect()
- : mLauncherMutex(NULL),
- mMappedFile(NULL)
- {
- // Secure launcher mutex
- mLauncherMutex = CreateMutex(NULL, FALSE, LAUNCHER_GUID);
- if ((mLauncherMutex == NULL) ||
- ((mLauncherMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- return;
- }
- // Create memory mapped file to mirror protected file
- File file("Conquer.dat", Rights_ReadOnly);
- if (!file.IsAvailable())
- {
- return;
- }
- UInt32 fileSize = file.GetLength();
- SECURITY_ATTRIBUTES security;
- security.nLength = sizeof(security);
- security.lpSecurityDescriptor = NULL;
- security.bInheritHandle = TRUE;
- mMappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, &security,
- PAGE_READWRITE, 0, fileSize, NULL);
- if ((mMappedFile == NULL) ||
- ((mMappedFile != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- PrintWin32Error("***** CreateFileMapping() Failed!");
- CloseHandle(mMappedFile);
- mMappedFile = NULL;
- return;
- }
- // Map file to programs address space
- LPVOID mapAddress = MapViewOfFileEx(mMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
- if (mapAddress == NULL)
- {
- PrintWin32Error("***** MapViewOfFileEx() Failed!");
- return;
- }
- // Decrypt protected file contents to mapping file
- void* buffer = NULL;
- UInt32 bufferSize = 0;
- file.Load(buffer, bufferSize);
- if ((buffer != NULL) && (bufferSize > 0))
- {
- // Retrieve protection key
- RefPtr<UString> passKey = GetPassKey();
- Char key[64];
- passKey->ConvertToANSI(key, sizeof(key));
- DebugPrint("Retrieved PassKey: %s\n", key);
- // Decrypt data
- BlowfishEngine blowfish;
- blowfish.Submit_Key(key, strlen(key));
- blowfish.Decrypt(buffer, bufferSize, mapAddress);
- DebugPrint("Decrypted data: %s\n", mapAddress);
- free(buffer);
- }
- UnmapViewOfFile(mapAddress);
- }
- /******************************************************************************
- *
- * NAME
- *
- * DESCRIPTION
- *
- * INPUTS
- *
- * RESULT
- *
- ******************************************************************************/
- Protect::~Protect()
- {
- if (mMappedFile != NULL)
- {
- CloseHandle(mMappedFile);
- mMappedFile = NULL;
- }
- if (mLauncherMutex != NULL)
- {
- CloseHandle(mLauncherMutex);
- mLauncherMutex = NULL;
- }
- }
- /******************************************************************************
- *
- * NAME
- * Protect::SendMappedFileHandle()
- *
- * DESCRIPTION
- * Send the handle to the memory mapped file to the application.
- *
- * INPUTS
- * Process - Process of the application to send handle to.
- * ThreadID - Thread of the applicatin to send handle to.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void Protect::SendMappedFileHandle(HANDLE process, DWORD threadID) const
- {
- DebugPrint("SendMappedFileHandle()\n");
- DebugPrint("Creating running notification event.\n");
- const char* const protectGUID = "D6E7FC97-64F9-4d28-B52C-754EDF721C6F";
- HANDLE event = CreateEvent(NULL, FALSE, FALSE, protectGUID);
- if ((event == NULL) || ((event != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- PrintWin32Error("CreateEvent() Failed!");
- return;
- }
- DebugPrint("Waiting for game (timeout in %.02f seconds)...\n", ((float)((5 * 60) * 1000) * 0.001));
- #ifdef _DEBUG
- unsigned long start = timeGetTime();
- #endif
- HANDLE handles[2];
- handles[0] = event;
- handles[1] = process;
- DWORD waitResult = WaitForMultipleObjects(2, &handles[0], FALSE, ((5 * 60) * 1000));
- #ifdef _DEBUG
- unsigned long stop = timeGetTime();
- #endif
- DebugPrint("WaitResult = %ld (WAIT_OBJECT_0 = %ld)\n", waitResult, WAIT_OBJECT_0);
- if (waitResult == WAIT_OBJECT_0)
- {
- if (mMappedFile != NULL)
- {
- DebugPrint("Sending game the beef. (%lx)\n", mMappedFile);
- BOOL sent = PostThreadMessage(threadID, 0xBEEF, 0, (LPARAM)mMappedFile);
- assert(sent == TRUE);
- }
- }
- else
- {
- DebugPrint("***** Timeout!\n");
- }
- #ifdef _DEBUG
- DebugPrint("Waited %.02f seconds\n", ((float)(stop - start) * 0.001));
- #endif
- CloseHandle(event);
- }
- /******************************************************************************
- *
- * NAME
- *
- * DESCRIPTION
- *
- * INPUTS
- *
- * RESULT
- *
- ******************************************************************************/
- RefPtr<UString> Protect::GetPassKey(void) const
- {
- RefPtr<UString> passKey = new UString;
- if (passKey.IsValid())
- {
- unsigned char installPath[MAX_PATH];
- installPath[0] = '\0';
- // Get game information
- HKEY hKey;
-
- /*
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Westwood\\Red Alert 2", 0, KEY_READ, &hKey);
- */
- #if defined(FREEDEDICATEDSERVER)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeFDS", 0, KEY_READ, &hKey);
- #elif defined(MULTIPLAYERDEMO)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeMPDemo", 0, KEY_READ, &hKey);
- #elif defined(BETACLIENT)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeBeta", 0, KEY_READ, &hKey);
- #else
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\Renegade", 0, KEY_READ, &hKey);
- #endif
- if (result != ERROR_SUCCESS)
- {
- DebugPrint("***** Failed to open game registry key\n");
- assert(result == ERROR_SUCCESS);
- }
- if (result == ERROR_SUCCESS)
- {
- // Retrieve install path
- DWORD type;
- DWORD sizeOfBuffer = sizeof(installPath);
- result = RegQueryValueEx(hKey, "InstallPath", NULL, &type, installPath, &sizeOfBuffer);
- if (result != ERROR_SUCCESS)
- {
- DebugPrint("***** Failed to obtain game install path!\n");
- assert(result == ERROR_SUCCESS);
- }
- DebugPrint("Game install path: %s\n", installPath);
- if (strlen((const char*)installPath) == 0)
- {
- DebugPrint("***** Game install path invalid!\n");
- }
- // Retrieve Hard drive S/N
- char drive[8];
- _splitpath((const char*)installPath, drive, NULL, NULL, NULL);
- strcat(drive, "\\");
- DWORD volumeSerialNumber = 0;
- DWORD maxComponentLength;
- DWORD fileSystemFlags;
- BOOL volInfoSuccess = GetVolumeInformation((const char*)drive, NULL, 0,
- &volumeSerialNumber, &maxComponentLength, &fileSystemFlags, NULL, 0);
- if (volInfoSuccess == FALSE)
- {
- PrintWin32Error("GetVolumeInformation() Failed!");
- }
- DebugPrint("Drive Serial Number: %lx\n", volumeSerialNumber);
- // Add hard drive serial number portion
- char volumeSN[16];
- sprintf(volumeSN, "%lx-", volumeSerialNumber);
- *passKey += volumeSN;
- // Retrieve game serial #
- unsigned char gameSerialNumber[64];
- gameSerialNumber[0] = '\0';
- sizeOfBuffer = sizeof(gameSerialNumber);
- result = RegQueryValueEx(hKey, "Serial", NULL, &type, gameSerialNumber, &sizeOfBuffer);
- if (result != ERROR_SUCCESS)
- {
- DebugPrint("***** Failed to obtain windows serial number!\n");
- assert(result == ERROR_SUCCESS);
- }
- DebugPrint("Game serial number: %s\n", gameSerialNumber);
- if (strlen((const char*)gameSerialNumber) == 0)
- {
- DebugPrint("***** Game serial number invalid!\n");
- }
- RegCloseKey(hKey);
- // Add game serial number portion
- *passKey += (char*)gameSerialNumber;
- }
- // Obtain windows product ID
- result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hKey);
- if (result != ERROR_SUCCESS)
- {
- DebugPrint("***** Failed to open windows registry key!\n");
- assert(result == ERROR_SUCCESS);
- }
- if (result == ERROR_SUCCESS)
- {
- // Retrieve Windows Product ID
- unsigned char winProductID[64];
- winProductID[0] = '\0';
- DWORD type;
- DWORD sizeOfBuffer = sizeof(winProductID);
- result = RegQueryValueEx(hKey, "ProductID", NULL, &type, winProductID, &sizeOfBuffer);
- if (result != ERROR_SUCCESS)
- {
- DebugPrint("***** Failed to obtain windows product ID!\n");
- assert(result == ERROR_SUCCESS);
- }
- DebugPrint("Windows Product ID: %s\n", winProductID);
- if (strlen((const char*)winProductID) == 0)
- {
- DebugPrint("***** Invalid windows product ID\n");
- }
- RegCloseKey(hKey);
- // Add windows product ID portion
- *passKey += "-";
- *passKey += (char*)winProductID;
- }
- }
- return passKey;
- }
- #else
- HANDLE mLauncherMutex = NULL;
- HANDLE mMappedFile = NULL;
- void InitializeProtect(void)
- {
- ShutdownProtect();
- DebugPrint("Initializing protection\n");
- mLauncherMutex = NULL;
- mMappedFile = NULL;
- // Secure launcher mutex
- mLauncherMutex = CreateMutex(NULL, FALSE, LAUNCHER_GUID);
- if ((mLauncherMutex == NULL) || (mLauncherMutex && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- DebugPrint("***** Failed to create launcher mutex\n");
- return;
- }
- // Create memory mapped file to mirror protected file
- File file("Conquer.dat", Rights_ReadOnly);
- if (!file.IsAvailable())
- {
- DebugPrint("***** Unable to find Conquer.dat\n");
- return;
- }
- UInt32 fileSize = file.GetLength();
- SECURITY_ATTRIBUTES security;
- security.nLength = sizeof(security);
- security.lpSecurityDescriptor = NULL;
- security.bInheritHandle = TRUE;
- mMappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, &security, PAGE_READWRITE, 0, fileSize, NULL);
- if ((mMappedFile == NULL) || (mMappedFile && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- PrintWin32Error("***** CreateFileMapping() Failed!");
- CloseHandle(mMappedFile);
- mMappedFile = NULL;
- return;
- }
- }
- CDAPFN_DECLARE_GLOBAL(SendProtectMessage, CDAPFN_OVERHEAD_L5, CDAPFN_CONSTRAINT_NONE);
- void SendProtectMessage(HANDLE process, DWORD threadID)
- {
- // Decrypt protected file contents to mapping file
- File file("Conquer.dat", Rights_ReadOnly);
- if (!file.IsAvailable())
- {
- DebugPrint("***** Unable to find Conquer.dat\n");
- return;
- }
- // Map file to programs address space
- LPVOID mapAddress = MapViewOfFileEx(mMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
- if (mapAddress == NULL)
- {
- PrintWin32Error("***** MapViewOfFileEx() Failed!");
- return;
- }
- void* buffer = NULL;
- UInt32 bufferSize = 0;
- file.Load(buffer, bufferSize);
- if (buffer && (bufferSize > 0))
- {
- DebugPrint("Generating PassKey\n");
- // Generate passkey
- char passKey[64];
- passKey[0] = '\0';
- // Get game information
- HKEY hKey;
- /*
- #ifdef FREEDEDICATEDSERVER
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeFDS", 0, KEY_READ, &hKey);
- #else //FREEDEDICATEDSERVER
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\Renegade", 0, KEY_READ, &hKey);
- #endif //FREEDEDICATEDSERVER
- */
- #if defined(FREEDEDICATEDSERVER)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeFDS", 0, KEY_READ, &hKey);
- #elif defined(MULTIPLAYERDEMO)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeMPDemo", 0, KEY_READ, &hKey);
- #elif defined(BETACLIENT)
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\RenegadeBeta", 0, KEY_READ, &hKey);
- #else
- LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Westwood\\Renegade", 0, KEY_READ, &hKey);
- #endif
- assert((result == ERROR_SUCCESS) && "Failed to open game registry key");
- if (result == ERROR_SUCCESS)
- {
- // Retrieve install path
- unsigned char installPath[MAX_PATH];
- DWORD type;
- DWORD sizeOfBuffer = sizeof(installPath);
- result = RegQueryValueEx(hKey, "InstallPath", NULL, &type, installPath, &sizeOfBuffer);
- assert((result == ERROR_SUCCESS) && "Failed to obtain game install path!");
- assert((strlen((const char*)installPath) > 0) && "Game install path invalid!");
- DebugPrint("Game install path: %s\n", installPath);
- // Retrieve Hard drive S/N
- char drive[8];
- _splitpath((const char*)installPath, drive, NULL, NULL, NULL);
- strcat(drive, "\\");
- DWORD volumeSerialNumber = 0;
- DWORD maxComponentLength;
- DWORD fileSystemFlags;
- BOOL volInfoSuccess = GetVolumeInformation((const char*)drive, NULL, 0,
- &volumeSerialNumber, &maxComponentLength, &fileSystemFlags, NULL, 0);
- if (volInfoSuccess == FALSE)
- {
- PrintWin32Error("***** GetVolumeInformation() Failed!");
- }
- DebugPrint("Drive Serial Number: %lx\n", volumeSerialNumber);
- // Add hard drive serial number portion
- char volumeSN[16];
- sprintf(volumeSN, "%lx-", volumeSerialNumber);
- strcat(passKey, volumeSN);
- // Retrieve game serial #
- unsigned char gameSerialNumber[64];
- gameSerialNumber[0] = '\0';
- sizeOfBuffer = sizeof(gameSerialNumber);
- result = RegQueryValueEx(hKey, "Serial", NULL, &type, gameSerialNumber, &sizeOfBuffer);
- assert((result == ERROR_SUCCESS) && "Failed to obtain windows serial number!");
- assert((strlen((const char*)gameSerialNumber) > 0) && "Game serial number invalid!");
- DebugPrint("Game serial number: %s\n", gameSerialNumber);
- RegCloseKey(hKey);
- // Add game serial number portion
- strcat(passKey, (char*)gameSerialNumber);
- }
- // Obtain windows product ID
- result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &hKey);
- assert((result == ERROR_SUCCESS) && "Failed to open windows registry key!");
- if (result == ERROR_SUCCESS)
- {
- // Retrieve Windows Product ID
- unsigned char winProductID[64];
- winProductID[0] = '\0';
- DWORD type;
- DWORD sizeOfBuffer = sizeof(winProductID);
- result = RegQueryValueEx(hKey, "ProductID", NULL, &type, winProductID, &sizeOfBuffer);
- assert((result == ERROR_SUCCESS) && "Failed to obtain windows product ID!");
- assert((strlen((const char*)winProductID) > 0) && "Invalid windows product ID");
- DebugPrint("Windows Product ID: %s\n", winProductID);
- RegCloseKey(hKey);
- // Add windows product ID portion
- strcat(passKey, "-");
- strcat(passKey, (char*)winProductID);
- }
- DebugPrint("Retrieved PassKey: %s\n", passKey);
- // Decrypt protected data into the memory mapped file
- BlowfishEngine blowfish;
- blowfish.Submit_Key(passKey, strlen(passKey));
- blowfish.Decrypt(buffer, bufferSize, mapAddress);
- DebugPrint("Decrypted data: %s\n", mapAddress);
- free(buffer);
- }
- UnmapViewOfFile(mapAddress);
- //---------------------------------------------------------------------------
- // Send protection message
- //---------------------------------------------------------------------------
- DebugPrint("Sending protect message\n");
- DebugPrint("Creating running notification event.\n");
- const char* const protectGUID = "D6E7FC97-64F9-4d28-B52C-754EDF721C6F";
- HANDLE event = CreateEvent(NULL, FALSE, FALSE, protectGUID);
- if ((event == NULL) || (event && (GetLastError() == ERROR_ALREADY_EXISTS)))
- {
- PrintWin32Error("***** CreateEvent() Failed!");
- return;
- }
- DebugPrint("Waiting for game (timeout in %.02f seconds)...\n", ((float)((5 * 60) * 1000) * 0.001));
- #ifdef _DEBUG
- unsigned long start = timeGetTime();
- #endif
- HANDLE handles[2];
- handles[0] = event;
- handles[1] = process;
- DWORD waitResult = WaitForMultipleObjects(2, &handles[0], FALSE, ((5 * 60) * 1000));
- #ifdef _DEBUG
- unsigned long stop = timeGetTime();
- #endif
- DebugPrint("WaitResult = %ld (WAIT_OBJECT_0 = %ld)\n", waitResult, WAIT_OBJECT_0);
- if (waitResult == WAIT_OBJECT_0)
- {
- if (mMappedFile != NULL)
- {
- DebugPrint("Sending game the beef. (%lx)\n", mMappedFile);
- BOOL sent = PostThreadMessage(threadID, 0xBEEF, 0, (LPARAM)mMappedFile);
- assert(sent == TRUE);
- }
- }
- else
- {
- DebugPrint("***** Timeout!\n");
- }
- #ifdef _DEBUG
- DebugPrint("Waited %.02f seconds\n", ((float)(stop - start) * 0.001));
- #endif
- CloseHandle(event);
- CDAPFN_ENDMARK(SendProtectMessage);
- }
- void ShutdownProtect(void)
- {
- if (mMappedFile)
- {
- CloseHandle(mMappedFile);
- mMappedFile = NULL;
- }
- if (mLauncherMutex)
- {
- CloseHandle(mLauncherMutex);
- mLauncherMutex = NULL;
- }
- }
- #endif
- #endif // COPY_PROTECT
|