diff options
Diffstat (limited to 'dep/CascLib/src/CascBuildCfg.cpp')
-rw-r--r-- | dep/CascLib/src/CascBuildCfg.cpp | 1032 |
1 files changed, 0 insertions, 1032 deletions
diff --git a/dep/CascLib/src/CascBuildCfg.cpp b/dep/CascLib/src/CascBuildCfg.cpp deleted file mode 100644 index f39f09d886a..00000000000 --- a/dep/CascLib/src/CascBuildCfg.cpp +++ /dev/null @@ -1,1032 +0,0 @@ -/*****************************************************************************/ -/* CascBuildCfg.cpp Copyright (c) Ladislav Zezula 2014 */ -/*---------------------------------------------------------------------------*/ -/* Build configuration for CascLib */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 29.04.14 1.00 Lad The first version of CascBuildCfg.cpp */ -/*****************************************************************************/ - -#define __CASCLIB_SELF__ -#include "CascLib.h" -#include "CascCommon.h" - -//----------------------------------------------------------------------------- -// Local functions - -static bool inline IsValueSeparator(LPBYTE pbVarValue) -{ - return ((0 <= pbVarValue[0] && pbVarValue[0] <= 0x20) || (pbVarValue[0] == '|')); -} - -static bool IsCharDigit(BYTE OneByte) -{ - return ('0' <= OneByte && OneByte <= '9'); -} - -static void FreeCascBlob(PQUERY_KEY pBlob) -{ - if(pBlob != NULL) - { - if(pBlob->pbData != NULL) - CASC_FREE(pBlob->pbData); - - pBlob->pbData = NULL; - pBlob->cbData = 0; - } -} - -static DWORD GetLocaleMask(const char * szTag) -{ - if(!strcmp(szTag, "enUS")) - return CASC_LOCALE_ENUS; - - if(!strcmp(szTag, "koKR")) - return CASC_LOCALE_KOKR; - - if(!strcmp(szTag, "frFR")) - return CASC_LOCALE_FRFR; - - if(!strcmp(szTag, "deDE")) - return CASC_LOCALE_DEDE; - - if(!strcmp(szTag, "zhCN")) - return CASC_LOCALE_ZHCN; - - if(!strcmp(szTag, "esES")) - return CASC_LOCALE_ESES; - - if(!strcmp(szTag, "zhTW")) - return CASC_LOCALE_ZHTW; - - if(!strcmp(szTag, "enGB")) - return CASC_LOCALE_ENGB; - - if(!strcmp(szTag, "enCN")) - return CASC_LOCALE_ENCN; - - if(!strcmp(szTag, "enTW")) - return CASC_LOCALE_ENTW; - - if(!strcmp(szTag, "esMX")) - return CASC_LOCALE_ESMX; - - if(!strcmp(szTag, "ruRU")) - return CASC_LOCALE_RURU; - - if(!strcmp(szTag, "ptBR")) - return CASC_LOCALE_PTBR; - - if(!strcmp(szTag, "itIT")) - return CASC_LOCALE_ITIT; - - if(!strcmp(szTag, "ptPT")) - return CASC_LOCALE_PTPT; - - return 0; -} - -static bool IsInfoVariable(const char * szLineBegin, const char * szLineEnd, const char * szVarName, const char * szVarType) -{ - size_t nLength; - - // Check the variable name - nLength = strlen(szVarName); - if((size_t)(szLineEnd - szLineBegin) > nLength) - { - // Check the variable name - if(!_strnicmp(szLineBegin, szVarName, nLength)) - { - // Skip variable name and the exclamation mark - szLineBegin += nLength; - if(szLineBegin < szLineEnd && szLineBegin[0] == '!') - { - // Skip the exclamation mark - szLineBegin++; - - // Check the variable type - nLength = strlen(szVarType); - if((size_t)(szLineEnd - szLineBegin) > nLength) - { - // Check the variable name - if(!_strnicmp(szLineBegin, szVarType, nLength)) - { - // Skip variable type and the doublecolon - szLineBegin += nLength; - return (szLineBegin < szLineEnd && szLineBegin[0] == ':'); - } - } - } - } - } - - return false; -} - -static const char * SkipInfoVariable(const char * szLineBegin, const char * szLineEnd) -{ - while(szLineBegin < szLineEnd) - { - if(szLineBegin[0] == '|') - return szLineBegin + 1; - - szLineBegin++; - } - - return NULL; -} - -static TCHAR * CheckForIndexDirectory(TCascStorage * hs, const TCHAR * szSubDir) -{ - TCHAR * szIndexPath; - - // Cpmbine the index path - szIndexPath = CombinePath(hs->szDataPath, szSubDir); - if(DirectoryExists(szIndexPath)) - { - hs->szIndexPath = szIndexPath; - return hs->szIndexPath; - } - - CASC_FREE(szIndexPath); - return NULL; -} - -TCHAR * AppendBlobText(TCHAR * szBuffer, LPBYTE pbData, DWORD cbData, TCHAR chSeparator) -{ - // Put the separator, if any - if(chSeparator != 0) - *szBuffer++ = chSeparator; - - // Copy the blob data as text - for(DWORD i = 0; i < cbData; i++) - { - *szBuffer++ = IntToHexChar[pbData[0] >> 0x04]; - *szBuffer++ = IntToHexChar[pbData[0] & 0x0F]; - pbData++; - } - - // Terminate the string - *szBuffer = 0; - - // Return new buffer position - return szBuffer; -} - -static int StringBlobToBinaryBlob( - PQUERY_KEY pBlob, - LPBYTE pbBlobBegin, - LPBYTE pbBlobEnd) -{ - // Sanity checks - assert(pBlob != NULL && pBlob->pbData != NULL); - - // Reset the blob length - pBlob->cbData = 0; - - // Convert the blob - while(pbBlobBegin < pbBlobEnd) - { - BYTE DigitOne; - BYTE DigitTwo; - - DigitOne = (BYTE)(AsciiToUpperTable_BkSlash[pbBlobBegin[0]] - '0'); - if(DigitOne > 9) - DigitOne -= 'A' - '9' - 1; - - DigitTwo = (BYTE)(AsciiToUpperTable_BkSlash[pbBlobBegin[1]] - '0'); - if(DigitTwo > 9) - DigitTwo -= 'A' - '9' - 1; - - if(DigitOne > 0x0F || DigitTwo > 0x0F || pBlob->cbData >= MAX_CASC_KEY_LENGTH) - return ERROR_BAD_FORMAT; - - pBlob->pbData[pBlob->cbData++] = (DigitOne << 0x04) | DigitTwo; - pbBlobBegin += 2; - } - - return ERROR_SUCCESS; -} - - -static LPBYTE FindNextSeparator(PQUERY_KEY pFileBlob, LPBYTE pbFilePtr) -{ - LPBYTE pbFileBegin = pFileBlob->pbData; - LPBYTE pbFileEnd = pFileBlob->pbData + pFileBlob->cbData; - - if(pbFileBegin <= pbFilePtr && pbFilePtr < pbFileEnd) - { - while(pbFilePtr < pbFileEnd && pbFilePtr[0] != '|') - pbFilePtr++; - - return pbFilePtr; - } - - return NULL; -} - -static bool GetNextFileLine(PQUERY_KEY pFileBlob, LPBYTE * ppbLineBegin, LPBYTE * ppbLineEnd) -{ - LPBYTE pbLineBegin = *ppbLineBegin; - LPBYTE pbLineEnd = *ppbLineEnd; - LPBYTE pbFileEnd = pFileBlob->pbData + pFileBlob->cbData; - - // If there was a previous line, skip all end-of-line chars - if(pbLineEnd != NULL) - { - // Go to the next line - while(pbLineEnd < pbFileEnd && (pbLineEnd[0] == 0x0A || pbLineEnd[0] == 0x0D)) - pbLineEnd++; - pbLineBegin = pbLineEnd; - - // If there is no more data, return false - if(pbLineEnd >= pbFileEnd) - return false; - } - - // Skip all spaces before the line begins - while(pbLineBegin < pbFileEnd && (pbLineBegin[0] == 0x09 || pbLineBegin[0] == 0x20)) - pbLineBegin++; - pbLineEnd = pbLineBegin; - - // Go to the end of the line - while(pbLineEnd < pbFileEnd && pbLineEnd[0] != 0x0A && pbLineEnd[0] != 0x0D) - pbLineEnd++; - - // Give the results to the caller - *ppbLineBegin = pbLineBegin; - *ppbLineEnd = pbLineEnd; - return true; -} - -static LPBYTE CheckLineVariable(LPBYTE pbLineBegin, LPBYTE pbLineEnd, const char * szVarName) -{ - size_t nLineLength = (size_t)(pbLineEnd - pbLineBegin); - size_t nNameLength = strlen(szVarName); - - // If the line longer than the variable name? - if(nLineLength > nNameLength) - { - if(!_strnicmp((const char *)pbLineBegin, szVarName, nNameLength)) - { - // Skip the variable name - pbLineBegin += nNameLength; - - // Skip the separator(s) - while(pbLineBegin < pbLineEnd && IsValueSeparator(pbLineBegin)) - pbLineBegin++; - - // Check if there is "=" - if(pbLineBegin >= pbLineEnd || pbLineBegin[0] != '=') - return NULL; - pbLineBegin++; - - // Skip the separator(s) - while(pbLineBegin < pbLineEnd && IsValueSeparator(pbLineBegin)) - pbLineBegin++; - - // Check if there is "=" - if(pbLineBegin >= pbLineEnd) - return NULL; - - // Return the begin of the variable - return pbLineBegin; - } - } - - return NULL; -} - -static int LoadInfoVariable(PQUERY_KEY pVarBlob, const char * szLineBegin, const char * szLineEnd, bool bHexaValue) -{ - const char * szLinePtr = szLineBegin; - - // Sanity checks - assert(pVarBlob->pbData == NULL); - assert(pVarBlob->cbData == 0); - - // Check length of the variable - while(szLinePtr < szLineEnd && szLinePtr[0] != '|') - szLinePtr++; - - // Allocate space for the blob - if(bHexaValue) - { - // Initialize the blob - pVarBlob->pbData = CASC_ALLOC(BYTE, (szLinePtr - szLineBegin) / 2); - return StringBlobToBinaryBlob(pVarBlob, (LPBYTE)szLineBegin, (LPBYTE)szLinePtr); - } - - // Initialize the blob - pVarBlob->pbData = CASC_ALLOC(BYTE, (szLinePtr - szLineBegin) + 1); - pVarBlob->cbData = (DWORD)(szLinePtr - szLineBegin); - - // Check for success - if(pVarBlob->pbData == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - // Copy the string - memcpy(pVarBlob->pbData, szLineBegin, pVarBlob->cbData); - pVarBlob->pbData[pVarBlob->cbData] = 0; - return ERROR_SUCCESS; -} - - -static void AppendConfigFilePath(TCHAR * szFileName, PQUERY_KEY pFileKey) -{ - // Get to the end of the file name - szFileName = szFileName + _tcslen(szFileName); - - // Append the "config" directory - _tcscat(szFileName, _T("/config")); - szFileName += 7; - - // Append the first level directory - szFileName = AppendBlobText(szFileName, pFileKey->pbData, 1, _T('/')); - szFileName = AppendBlobText(szFileName, pFileKey->pbData + 1, 1, _T('/')); - szFileName = AppendBlobText(szFileName, pFileKey->pbData, pFileKey->cbData, _T('/')); -} - -static DWORD GetBlobCount(LPBYTE pbLineBegin, LPBYTE pbLineEnd) -{ - DWORD dwBlobCount = 0; - - // Until we find an end of the line - while(pbLineBegin < pbLineEnd) - { - // Skip the blob - while(pbLineBegin < pbLineEnd && IsValueSeparator(pbLineBegin) == false) - pbLineBegin++; - - // Increment the number of blobs - dwBlobCount++; - - // Skip the separator - while(pbLineBegin < pbLineEnd && IsValueSeparator(pbLineBegin)) - pbLineBegin++; - } - - return dwBlobCount; -} - -static int LoadBlobArray( - PQUERY_KEY pBlob, - DWORD dwMaxBlobs, - LPBYTE pbLineBegin, - LPBYTE pbLineEnd, - LPBYTE pbBuffer, - DWORD dwBufferSize) -{ - LPBYTE pbBlobBegin = pbLineBegin; - LPBYTE pbBlobEnd = pbLineBegin; - int nError = ERROR_SUCCESS; - - // Sanity check - assert(pbBuffer != NULL); - - // Until we find an end of the line - while(pbBlobBegin < pbLineEnd) - { - // Convert the blob from string to binary - if(dwBufferSize < MAX_CASC_KEY_LENGTH) - return ERROR_NOT_ENOUGH_MEMORY; - - // Find the end of the text blob - while(pbBlobEnd < pbLineEnd && IsValueSeparator(pbBlobEnd) == false) - pbBlobEnd++; - - // Convert the blob from ANSI to binary - pBlob->pbData = pbBuffer; - nError = StringBlobToBinaryBlob(pBlob, pbBlobBegin, pbBlobEnd); - if(nError != ERROR_SUCCESS || dwMaxBlobs == 1) - break; - - // Move the blob, buffer, and limits - dwBufferSize -= MAX_CASC_KEY_LENGTH; - pbBuffer += MAX_CASC_KEY_LENGTH; - dwMaxBlobs--; - pBlob++; - - // Skip the separator - while(pbBlobEnd < pbLineEnd && IsValueSeparator(pbBlobEnd)) - pbBlobEnd++; - pbBlobBegin = pbBlobEnd; - } - - return nError; -} - -static int LoadSingleBlob(PQUERY_KEY pBlob, LPBYTE pbBlobBegin, LPBYTE pbBlobEnd) -{ - LPBYTE pbBuffer; - size_t nLength = (pbBlobEnd - pbBlobBegin) / 2; - - // Check maximum size - if(nLength > MAX_CASC_KEY_LENGTH) - return ERROR_INVALID_PARAMETER; - - // Allocate the blob buffer - pbBuffer = CASC_ALLOC(BYTE, MAX_CASC_KEY_LENGTH); - if(pbBuffer == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - return LoadBlobArray(pBlob, 1, pbBlobBegin, pbBlobEnd, pbBuffer, MAX_CASC_KEY_LENGTH); -} - -static PQUERY_KEY LoadMultipleBlobs(LPBYTE pbLineBegin, LPBYTE pbLineEnd, DWORD * pdwBlobCount) -{ - PQUERY_KEY pBlobArray = NULL; - LPBYTE pbBuffer = NULL; - DWORD dwBlobCount = GetBlobCount(pbLineBegin, pbLineEnd); - int nError; - - // Only if there is at least 1 blob - if(dwBlobCount != 0) - { - // Allocate the array of blobs - pBlobArray = CASC_ALLOC(QUERY_KEY, dwBlobCount); - if(pBlobArray != NULL) - { - // Zero the blob array - memset(pBlobArray, 0, dwBlobCount * sizeof(QUERY_KEY)); - - // Allocate buffer for the blobs - pbBuffer = CASC_ALLOC(BYTE, dwBlobCount * MAX_CASC_KEY_LENGTH); - if(pbBuffer != NULL) - { - // Zero the buffer - memset(pbBuffer, 0, dwBlobCount * MAX_CASC_KEY_LENGTH); - - // Load the entire blob array - nError = LoadBlobArray(pBlobArray, dwBlobCount, pbLineBegin, pbLineEnd, pbBuffer, dwBlobCount * MAX_CASC_KEY_LENGTH); - if(nError == ERROR_SUCCESS) - { - *pdwBlobCount = dwBlobCount; - return pBlobArray; - } - - // Free the buffer - CASC_FREE(pbBuffer); - } - - // Free the array of blobs - CASC_FREE(pBlobArray); - pBlobArray = NULL; - } - - // Reset the blob count - dwBlobCount = 0; - } - - *pdwBlobCount = dwBlobCount; - return pBlobArray; -} - -static int LoadTextFile(const TCHAR * szFileName, PQUERY_KEY pFileBlob) -{ - TFileStream * pStream; - ULONGLONG FileSize = 0; - int nError = ERROR_SUCCESS; - - // Open the agent file - pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE); - if(pStream != NULL) - { - // Retrieve its size - FileStream_GetSize(pStream, &FileSize); - - // Load the file to memory - if(0 < FileSize && FileSize < 0x100000) - { - // Initialize the blob - pFileBlob->cbData = (DWORD)FileSize; - pFileBlob->pbData = CASC_ALLOC(BYTE, pFileBlob->cbData + 1); - - // Load the file data into the blob - if(pFileBlob->pbData != NULL) - { - FileStream_Read(pStream, NULL, pFileBlob->pbData, (DWORD)FileSize); - pFileBlob->pbData[pFileBlob->cbData] = 0; - } - else - nError = ERROR_NOT_ENOUGH_MEMORY; - } - else - nError = ERROR_INVALID_PARAMETER; - - FileStream_Close(pStream); - } - else - nError = GetLastError(); - - return nError; -} - -static int GetGameType(TCascStorage * hs, LPBYTE pbVarBegin, LPBYTE pbLineEnd) -{ - // Alpha build of Heroes of the Storm - if((pbLineEnd - pbVarBegin) == 4 && !_strnicmp((const char *)pbVarBegin, "Hero", 4)) - { - hs->dwGameInfo = CASC_GAME_HOTS; - return ERROR_SUCCESS; - } - - // Alpha build of World of Warcraft - Warlords of Draenor - if((pbLineEnd - pbVarBegin) == 3 && !_strnicmp((const char *)pbVarBegin, "WoW", 3)) - { - hs->dwGameInfo = CASC_GAME_WOW6; - return ERROR_SUCCESS; - } - - // Diablo III BETA 2.2.0 - if((pbLineEnd - pbVarBegin) == 7 && !_strnicmp((const char *)pbVarBegin, "Diablo3", 7)) - { - hs->dwGameInfo = CASC_GAME_DIABLO3; - return ERROR_SUCCESS; - } - - // An unknown game - assert(false); - return ERROR_BAD_FORMAT; -} - -// "B29049" -// "WOW-18125patch6.0.1" -// "30013_Win32_2_2_0_Ptr_ptr" -static int GetBuildNumber(TCascStorage * hs, LPBYTE pbVarBegin, LPBYTE pbLineEnd) -{ - DWORD dwBuildNumber = 0; - - // Skip all non-digit characters - while(pbVarBegin < pbLineEnd && IsCharDigit(pbVarBegin[0]) == false) - pbVarBegin++; - - // Convert the build number - while(pbVarBegin < pbLineEnd && IsCharDigit(pbVarBegin[0])) - dwBuildNumber = (dwBuildNumber * 10) + (*pbVarBegin++ - '0'); - - assert(dwBuildNumber != 0); - hs->dwBuildNumber = dwBuildNumber; - return (dwBuildNumber != 0) ? ERROR_SUCCESS : ERROR_BAD_FORMAT; -} - -static int GetDefaultLocaleMask(TCascStorage * hs, PQUERY_KEY pTagsString) -{ - char * szTagEnd = (char *)pTagsString->pbData + pTagsString->cbData; - char * szTagPtr = (char *)pTagsString->pbData; - char * szNext; - DWORD dwLocaleMask = 0; - - while(szTagPtr < szTagEnd) - { - // Get the next part - szNext = strchr(szTagPtr, ' '); - if(szNext != NULL) - *szNext++ = 0; - - // Check whether the current tag is a language identifier - dwLocaleMask = dwLocaleMask | GetLocaleMask(szTagPtr); - - // Get the next part - if(szNext == NULL) - break; - - // Skip spaces - while(szNext < szTagEnd && szNext[0] == ' ') - szNext++; - szTagPtr = szNext; - } - - hs->dwDefaultLocale = dwLocaleMask; - return ERROR_SUCCESS; -} - -static int FetchAndVerifyConfigFile(TCascStorage * hs, PQUERY_KEY pFileKey, PQUERY_KEY pFileBlob) -{ - TCHAR * szFileName; - int nError; - - // Construct the local file name - szFileName = NewStr(hs->szDataPath, 8 + 3 + 3 + 32); - if(szFileName == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - // Add the part where the config file path is - AppendConfigFilePath(szFileName, pFileKey); - - // Load the config file - nError = LoadTextFile(szFileName, pFileBlob); - if(nError == ERROR_SUCCESS) - { - // Verify the blob's MD5 - if(!VerifyDataBlockHash(pFileBlob->pbData, pFileBlob->cbData, pFileKey->pbData)) - { - FreeCascBlob(pFileBlob); - nError = ERROR_BAD_FORMAT; - } - } - - CASC_FREE(szFileName); - return nError; -} - -static int ParseInfoFile(TCascStorage * hs, PQUERY_KEY pFileBlob) -{ - QUERY_KEY Active = {NULL, 0}; - QUERY_KEY TagString = {NULL, 0}; - QUERY_KEY CdnHost = {NULL, 0}; - QUERY_KEY CdnPath = {NULL, 0}; - const char * szLineBegin1 = NULL; - const char * szLinePtr1 = NULL; - const char * szLineBegin2 = NULL; - const char * szLineEnd1 = NULL; - const char * szLineEnd2 = NULL; - const char * szFileEnd = (const char *)(pFileBlob->pbData + pFileBlob->cbData); - const char * szFilePtr = (const char *)pFileBlob->pbData; - int nError = ERROR_BAD_FORMAT; - - // Find the first line - szLineBegin1 = szFilePtr; - while(szFilePtr < szFileEnd) - { - // Check for the end of the line - if(szFilePtr[0] == 0x0D || szFilePtr[0] == 0x0A) - { - szLineEnd1 = szFilePtr; - break; - } - - szFilePtr++; - } - - while (szFilePtr < szFileEnd) - { - szLinePtr1 = szLineBegin1; - - // Skip the newline character(s) - while (szFilePtr < szFileEnd && (szFilePtr[0] == 0x0D || szFilePtr[0] == 0x0A)) - szFilePtr++; - - // Find the next line - szLineBegin2 = szFilePtr; - while (szFilePtr < szFileEnd) - { - // Check for the end of the line - if (szFilePtr[0] == 0x0D || szFilePtr[0] == 0x0A) - { - szLineEnd2 = szFilePtr; - break; - } - - szFilePtr++; - } - - // Find the build key, CDN config key and the URL path - while (szLinePtr1 < szLineEnd1) - { - // Check for variables we need - if (IsInfoVariable(szLinePtr1, szLineEnd1, "Active", "DEC")) - LoadInfoVariable(&Active, szLineBegin2, szLineEnd2, false); - if (IsInfoVariable(szLinePtr1, szLineEnd1, "Build Key", "HEX")) - LoadInfoVariable(&hs->CdnBuildKey, szLineBegin2, szLineEnd2, true); - if (IsInfoVariable(szLinePtr1, szLineEnd1, "CDN Key", "HEX")) - LoadInfoVariable(&hs->CdnConfigKey, szLineBegin2, szLineEnd2, true); - if (IsInfoVariable(szLinePtr1, szLineEnd1, "CDN Hosts", "STRING")) - LoadInfoVariable(&CdnHost, szLineBegin2, szLineEnd2, false); - if (IsInfoVariable(szLinePtr1, szLineEnd1, "CDN Path", "STRING")) - LoadInfoVariable(&CdnPath, szLineBegin2, szLineEnd2, false); - if (IsInfoVariable(szLinePtr1, szLineEnd1, "Tags", "STRING")) - LoadInfoVariable(&TagString, szLineBegin2, szLineEnd2, false); - - // Move both line pointers - szLinePtr1 = SkipInfoVariable(szLinePtr1, szLineEnd1); - if (szLineBegin1 == NULL) - break; - - szLineBegin2 = SkipInfoVariable(szLineBegin2, szLineEnd2); - if (szLineBegin2 == NULL) - break; - } - - // Stop parsing if found active config - if (Active.pbData != NULL && *Active.pbData == '1') - break; - } - - // All four must be present - if(hs->CdnBuildKey.pbData != NULL && - hs->CdnConfigKey.pbData != NULL && - CdnHost.pbData != NULL && - CdnPath.pbData != NULL) - { - // Merge the CDN host and CDN path - hs->szUrlPath = CASC_ALLOC(TCHAR, CdnHost.cbData + CdnPath.cbData + 1); - if(hs->szUrlPath != NULL) - { - CopyString(hs->szUrlPath, (char *)CdnHost.pbData, CdnHost.cbData); - CopyString(hs->szUrlPath + CdnHost.cbData, (char *)CdnPath.pbData, CdnPath.cbData); - nError = ERROR_SUCCESS; - } - } - - // If we found tags, we can extract language build from it - if(TagString.pbData != NULL) - GetDefaultLocaleMask(hs, &TagString); - - FreeCascBlob(&CdnHost); - FreeCascBlob(&CdnPath); - FreeCascBlob(&TagString); - return nError; -} - -static int ParseAgentFile(TCascStorage * hs, PQUERY_KEY pFileBlob) -{ - LPBYTE pbBlobBegin = pFileBlob->pbData; - LPBYTE pbBlobEnd; - int nError = ERROR_SUCCESS; - - // Extract the CDN build hash - pbBlobEnd = FindNextSeparator(pFileBlob, pbBlobBegin); - if(pbBlobEnd != NULL) - { - // Convert the string to a blob - nError = LoadSingleBlob(&hs->CdnBuildKey, pbBlobBegin, pbBlobEnd); - - // Move to the next part - if(pbBlobEnd[0] == _T('|')) - pbBlobEnd++; - pbBlobBegin = pbBlobEnd; - } - - // Extract the CDN config hash - pbBlobEnd = FindNextSeparator(pFileBlob, pbBlobBegin); - if(pbBlobEnd != NULL) - { - // Convert the string to a blob - nError = LoadSingleBlob(&hs->CdnConfigKey, pbBlobBegin, pbBlobEnd); - - // Move to the next part - if(pbBlobEnd[0] == _T('|')) - pbBlobEnd++; - pbBlobBegin = pbBlobEnd; - } - - // Skip the intermediate part - pbBlobEnd = FindNextSeparator(pFileBlob, pbBlobBegin); - if(pbBlobEnd != NULL) - { - // Move to the next part - if(pbBlobEnd[0] == _T('|')) - pbBlobEnd++; - pbBlobBegin = pbBlobEnd; - } - - // Extract the URL config hash - pbBlobEnd = FindNextSeparator(pFileBlob, pbBlobBegin); - if(pbBlobEnd != NULL) - { - // Convert the string to a blob - hs->szUrlPath = NewStrFromAnsi(pbBlobBegin, pbBlobEnd); - } - - // Verify all variables - if(hs->CdnBuildKey.pbData == NULL || hs->CdnConfigKey.pbData == NULL || hs->szUrlPath == NULL) - nError = ERROR_BAD_FORMAT; - return nError; -} - -static int LoadCdnConfigFile(TCascStorage * hs, PQUERY_KEY pFileBlob) -{ - LPBYTE pbLineBegin = pFileBlob->pbData; - LPBYTE pbVarBegin; - LPBYTE pbLineEnd = NULL; - int nError; - - while(pbLineBegin != NULL) - { - // Get the next line - if(!GetNextFileLine(pFileBlob, &pbLineBegin, &pbLineEnd)) - break; - - // Archive group - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "archive-group"); - if(pbVarBegin != NULL) - { - nError = LoadSingleBlob(&hs->ArchiveGroup, pbVarBegin, pbLineEnd); - if(nError != ERROR_SUCCESS) - return nError; - continue; - } - - // Archives - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "archives"); - if(pbVarBegin != NULL) - { - hs->pArchiveArray = LoadMultipleBlobs(pbVarBegin, pbLineEnd, &hs->ArchiveCount); - if(hs->pArchiveArray == NULL || hs->ArchiveCount == 0) - return ERROR_BAD_FORMAT; - continue; - } - - // Patch archive group - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "patch-archive-group"); - if(pbVarBegin != NULL) - { - LoadSingleBlob(&hs->PatchArchiveGroup, pbVarBegin, pbLineEnd); - continue; - } - - // Patch archives - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "patch-archives"); - if(pbVarBegin != NULL) - { - hs->pPatchArchiveArray = LoadMultipleBlobs(pbVarBegin, pbLineEnd, &hs->PatchArchiveCount); - continue; - } - } - - // Check if all required fields are present - if(hs->ArchiveGroup.pbData == NULL || hs->ArchiveGroup.cbData == 0 || hs->pArchiveArray == NULL || hs->ArchiveCount == 0) - return ERROR_BAD_FORMAT; - - return ERROR_SUCCESS; -} - -static int LoadCdnBuildFile(TCascStorage * hs, PQUERY_KEY pFileBlob) -{ - LPBYTE pbLineBegin = pFileBlob->pbData; - LPBYTE pbVarBegin; - LPBYTE pbLineEnd = NULL; - - while(pbLineBegin != NULL) - { - // Get the next line - if(!GetNextFileLine(pFileBlob, &pbLineBegin, &pbLineEnd)) - break; - - // Game name - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "build-product"); - if(pbVarBegin != NULL) - { - GetGameType(hs, pbVarBegin, pbLineEnd); - continue; - } - - // Game build number - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "build-name"); - if(pbVarBegin != NULL) - { - GetBuildNumber(hs, pbVarBegin, pbLineEnd); - continue; - } - - // Root - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "root"); - if(pbVarBegin != NULL) - { - LoadSingleBlob(&hs->RootKey, pbVarBegin, pbLineEnd); - continue; - } - - // Patch - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "patch"); - if(pbVarBegin != NULL) - { - LoadSingleBlob(&hs->PatchKey, pbVarBegin, pbLineEnd); - continue; - } - - // Download - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "download"); - if(pbVarBegin != NULL) - { - LoadSingleBlob(&hs->DownloadKey, pbVarBegin, pbLineEnd); - continue; - } - - // Install - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "install"); - if(pbVarBegin != NULL) - { - LoadSingleBlob(&hs->InstallKey, pbVarBegin, pbLineEnd); - continue; - } - - // Encoding keys - pbVarBegin = CheckLineVariable(pbLineBegin, pbLineEnd, "encoding"); - if(pbVarBegin != NULL) - { - hs->pEncodingKeys = LoadMultipleBlobs(pbVarBegin, pbLineEnd, &hs->EncodingKeys); - if(hs->pEncodingKeys == NULL || hs->EncodingKeys != 2) - return ERROR_BAD_FORMAT; - - hs->EncodingKey = hs->pEncodingKeys[0]; - hs->EncodingEKey = hs->pEncodingKeys[1]; - continue; - } - } - - // Check the encoding keys - if(hs->pEncodingKeys == NULL || hs->EncodingKeys == 0) - return ERROR_BAD_FORMAT; - return ERROR_SUCCESS; -} - -//----------------------------------------------------------------------------- -// Public functions - -int LoadBuildInfo(TCascStorage * hs) -{ - QUERY_KEY InfoFile = {NULL, 0}; - QUERY_KEY FileData = {NULL, 0}; - TCHAR * szAgentFile; - TCHAR * szInfoFile; - bool bBuildConfigComplete = false; - int nError = ERROR_SUCCESS; - - // Since HOTS build 30027, the game uses build.info file for storage info - if(bBuildConfigComplete == false) - { - szInfoFile = CombinePath(hs->szRootPath, _T(".build.info")); - if(szInfoFile != NULL) - { - nError = LoadTextFile(szInfoFile, &InfoFile); - if(nError == ERROR_SUCCESS) - { - // Parse the info file - nError = ParseInfoFile(hs, &InfoFile); - if(nError == ERROR_SUCCESS) - bBuildConfigComplete = true; - - // Free the loaded blob - FreeCascBlob(&InfoFile); - } - - CASC_FREE(szInfoFile); - } - } - - // If the info file has not been loaded, try the legacy .build.db - if(bBuildConfigComplete == false) - { - szAgentFile = CombinePath(hs->szRootPath, _T(".build.db")); - if(szAgentFile != NULL) - { - nError = LoadTextFile(szAgentFile, &FileData); - if(nError == ERROR_SUCCESS) - { - nError = ParseAgentFile(hs, &FileData); - if(nError == ERROR_SUCCESS) - bBuildConfigComplete = true; - - FreeCascBlob(&FileData); - } - CASC_FREE(szAgentFile); - } - } - - // If the .build.info and .build.db file hasn't been loaded, - if(nError == ERROR_SUCCESS && bBuildConfigComplete == false) - { - nError = ERROR_FILE_CORRUPT; - } - - // Load the configuration file - if(nError == ERROR_SUCCESS) - { - nError = FetchAndVerifyConfigFile(hs, &hs->CdnConfigKey, &FileData); - if(nError == ERROR_SUCCESS) - { - nError = LoadCdnConfigFile(hs, &FileData); - FreeCascBlob(&FileData); - } - } - - // Load the build file - if(nError == ERROR_SUCCESS) - { - nError = FetchAndVerifyConfigFile(hs, &hs->CdnBuildKey, &FileData); - if(nError == ERROR_SUCCESS) - { - nError = LoadCdnBuildFile(hs, &FileData); - FreeCascBlob(&FileData); - } - } - - // Fill the index directory - if(nError == ERROR_SUCCESS) - { - // First, check for more common "data" subdirectory - if((hs->szIndexPath = CheckForIndexDirectory(hs, _T("data"))) != NULL) - return ERROR_SUCCESS; - - // Second, try the "darch" subdirectory (older builds of HOTS - Alpha) - if((hs->szIndexPath = CheckForIndexDirectory(hs, _T("darch"))) != NULL) - return ERROR_SUCCESS; - - nError = ERROR_FILE_NOT_FOUND; - } - - return nError; -} |