Skip to content

Commit f3f8473

Browse files
Ladislav ZezulaLadislav Zezula
authored andcommitted
Opening storage can now be cancelled via progress callback
1 parent 973ef31 commit f3f8473

File tree

7 files changed

+106
-21
lines changed

7 files changed

+106
-21
lines changed

src/CascCommon.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ struct TCascStorage
206206

207207
static TCascStorage * IsValid(HANDLE hStorage);
208208

209+
PFNPROGRESSCALLBACK PfnCallback; // Callback to be called during CascOpen(Online)Storage
210+
void * PtrCallbackParam;
211+
209212
const TCHAR * szIndexFormat; // Format of the index file name
210213
const char * szClassName; // "TCascStorage"
211214
const char * szProductName; // String representation of the product name
212-
const char * szErrorMsg; // If not NULL, contains the error message string
213215
TCHAR * szRootPath; // Path where the build file is
214216
TCHAR * szDataPath; // This is the directory where data files are
215217
TCHAR * szIndexPath; // This is the directory where index files are

src/CascFiles.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,11 +1209,14 @@ int LoadBuildInfo(TCascStorage * hs)
12091209
// If the storage is online storage, we need to download "versions"
12101210
if(hs->dwFeatures & CASC_FEATURE_ONLINE)
12111211
{
1212+
// Inform the user about loading the build.info/build.db/versions
1213+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Downloading the \"versions\" file", NULL, 0, 0))
1214+
return ERROR_CANCELLED;
1215+
12121216
// Attempt to download the "versions" file
12131217
nError = DownloadFile(hs, _T("us.patch.battle.net"), hs->szCodeName, _T("versions"), NULL, NULL, 0, NULL, 0, STREAM_FLAG_USE_PORT_1119, true, false);
12141218
if(nError != ERROR_SUCCESS)
12151219
{
1216-
hs->szErrorMsg = "Error downloading \"versions\"";
12171220
return nError;
12181221
}
12191222
}
@@ -1248,7 +1251,11 @@ int LoadCdnsInfo(TCascStorage * hs)
12481251

12491252
// Sanity checks
12501253
assert(hs->dwFeatures & CASC_FEATURE_ONLINE);
1251-
1254+
1255+
// Inform the user about what we are doing
1256+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Downloading the \"cdns\" file", NULL, 0, 0))
1257+
return ERROR_CANCELLED;
1258+
12521259
// Download file and parse it
12531260
nError = DownloadFile(hs, _T("us.patch.battle.net"), hs->szCodeName, _T("cdns"), NULL, NULL, 0, szLocalPath, _countof(szLocalPath), STREAM_FLAG_USE_PORT_1119, false, true);
12541261
if(nError == ERROR_SUCCESS)
@@ -1264,17 +1271,23 @@ int LoadCdnConfigFile(TCascStorage * hs)
12641271
// The CKey for the CDN config should have been loaded already
12651272
assert(hs->CdnConfigKey.pbData != NULL && hs->CdnConfigKey.cbData == MD5_HASH_SIZE);
12661273

1267-
// Load the CDN config file. Note that we don't
1268-
// need it for anything, really, so we don't care if it fails
1269-
FetchAndLoadConfigFile(hs, &hs->CdnConfigKey, ParseFile_CdnConfig);
1270-
return ERROR_SUCCESS;
1274+
// Inform the user about what we are doing
1275+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Downloading CDN config file", NULL, 0, 0))
1276+
return ERROR_CANCELLED;
1277+
1278+
// Load the CDN config file
1279+
return FetchAndLoadConfigFile(hs, &hs->CdnConfigKey, ParseFile_CdnConfig);
12711280
}
12721281

12731282
int LoadCdnBuildFile(TCascStorage * hs)
12741283
{
12751284
// The CKey for the CDN config should have been loaded already
12761285
assert(hs->CdnBuildKey.pbData != NULL && hs->CdnBuildKey.cbData == MD5_HASH_SIZE);
12771286

1287+
// Inform the user about what we are doing
1288+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Downloading CDN build file", NULL, 0, 0))
1289+
return ERROR_CANCELLED;
1290+
12781291
// Load the CDN config file. Note that we don't
12791292
// need it for anything, really, so we don't care if it fails
12801293
return FetchAndLoadConfigFile(hs, &hs->CdnBuildKey, ParseFile_CdnBuild);

src/CascIndexFiles.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
/*****************************************************************************/
2-
/* CascOpenStorage.cpp Copyright (c) Ladislav Zezula 2014 */
2+
/* CascIndexFiles.cpp Copyright (c) Ladislav Zezula 2019 */
33
/*---------------------------------------------------------------------------*/
4-
/* Storage functions for CASC */
5-
/* Note: WoW6 offsets refer to WoW.exe 6.0.3.19116 (32-bit) */
6-
/* SHA1: c10e9ffb7d040a37a356b96042657e1a0c95c0dd */
4+
/* Index file support */
75
/*---------------------------------------------------------------------------*/
86
/* Date Ver Who Comment */
97
/* -------- ---- --- ------- */
10-
/* 29.04.14 1.00 Lad The first version of CascOpenStorage.cpp */
8+
/* 23.05.19 1.00 Lad Created */
119
/*****************************************************************************/
1210

1311
#define __CASCLIB_SELF__
@@ -523,6 +521,14 @@ static int LoadLocalIndexFiles(TCascStorage * hs)
523521
// Create the name of the index file
524522
if((szFileName = CreateIndexFileName(hs, i, IndexArray[i])) != NULL)
525523
{
524+
// Inform the user about what we are doing
525+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Loading index files", NULL, i, CASC_INDEX_COUNT))
526+
{
527+
nError = ERROR_CANCELLED;
528+
break;
529+
}
530+
531+
// Load the index file
526532
if((nError = LoadIndexFile(hs, szFileName, i)) != ERROR_SUCCESS)
527533
break;
528534
CASC_FREE(szFileName);
@@ -707,6 +713,7 @@ static int LoadArchiveIndexFiles(TCascStorage * hs)
707713
LPBYTE pbFileData;
708714
TCHAR szLocalPath[MAX_PATH];
709715
DWORD cbFileData = 0;
716+
size_t nArchiveCount = (hs->ArchivesKey.cbData / MD5_HASH_SIZE);
710717
int nError = ERROR_SUCCESS;
711718

712719
// Create the array object for the indices
@@ -715,9 +722,16 @@ static int LoadArchiveIndexFiles(TCascStorage * hs)
715722
return nError;
716723

717724
// Load all the indices
718-
for (size_t i = 0; i < hs->ArchivesKey.cbData; i += MD5_HASH_SIZE)
725+
for (size_t i = 0; i < nArchiveCount; i++)
719726
{
720-
LPBYTE pbIndexHash = hs->ArchivesKey.pbData + i;
727+
LPBYTE pbIndexHash = hs->ArchivesKey.pbData + (i * MD5_HASH_SIZE);
728+
729+
// Inform the user about what we are doing
730+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Downloading archive indexes", NULL, (DWORD)(i), (DWORD)(nArchiveCount)))
731+
{
732+
nError = ERROR_CANCELLED;
733+
break;
734+
}
721735

722736
// Make sure that we have local copy of the file
723737
nError = DownloadFileFromCDN(hs, _T("data"), pbIndexHash, _T(".index"), szLocalPath, _countof(szLocalPath));

src/CascLib.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,22 @@ typedef struct _CASC_FILE_FULL_INFO
287287
} CASC_FILE_FULL_INFO, *PCASC_FILE_FULL_INFO;
288288

289289
//-----------------------------------------------------------------------------
290-
// Callback functions
291-
292-
typedef struct TFileStream TFileStream;
293-
typedef void (WINAPI * STREAM_DOWNLOAD_CALLBACK)(void * pvUserData, ULONGLONG ByteOffset, DWORD dwTotalBytes);
290+
// Some operations (e.g. opening an online storage) may take long time.
291+
// This callback allows an application to be notified about loading progress.
292+
// This callback only works for a single CascOpen(Online)Storage call.
293+
294+
typedef bool (WINAPI * PFNPROGRESSCALLBACK)( // Return 'true' to cancel the loading process
295+
void * PtrUserParam, // User-specific parameter passed to the callback
296+
LPCSTR szWork, // Text for the current activity (example: "Loading "ENCODING" file")
297+
LPCSTR szObject, // (optional) name of the object tied to the activity (example: index file name)
298+
DWORD nCurrent, // (optional) current object being processed
299+
DWORD nTotal // (optional) If non-zero, this is the total number of objects to process
300+
);
301+
302+
void WINAPI CascSetProgressCallback(
303+
PFNPROGRESSCALLBACK PtrUserCallback, // Pointer to the callback function that will be called during opening the storage
304+
void * PtrUserParam // Arbitrary user parameter that will be passed to the callback
305+
);
294306

295307
//-----------------------------------------------------------------------------
296308
// Functions for storage manipulation

src/CascOpenStorage.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
// Limit for "orphaned" items - those that are in index files, but are not in ENCODING manifest
2121
#define CASC_MAX_ORPHANED_ITEMS 0x100
2222

23+
//-----------------------------------------------------------------------------
24+
// Local variables
25+
26+
static PFNPROGRESSCALLBACK PfnProgressCallback = NULL;
27+
static void * PtrProgressParam = NULL;
28+
2329
//-----------------------------------------------------------------------------
2430
// TCascStorage service functions
2531

@@ -32,7 +38,7 @@ TCascStorage::TCascStorage()
3238
dwRefCount = 1;
3339

3440
szRootPath = szDataPath = szIndexPath = szBuildFile = szCdnServers = szCdnPath = szCodeName = NULL;
35-
szProductName = szErrorMsg = NULL;
41+
szProductName = NULL;
3642
szIndexFormat = NULL;
3743
szRegion = NULL;
3844

@@ -44,6 +50,12 @@ TCascStorage::TCascStorage()
4450
BuildFileType = CascBuildNone;
4551

4652
LocalFiles = TotalFiles = EKeyEntries = OrphanItems = SkippedItems = EKeyLength = FileOffsetBits = 0;
53+
54+
// Take the callback param and data. Zero the global pointers
55+
PfnCallback = PfnProgressCallback;
56+
PtrCallbackParam = PtrProgressParam;
57+
PfnProgressCallback = NULL;
58+
PtrProgressParam = NULL;
4759
}
4860

4961
TCascStorage::~TCascStorage()
@@ -401,6 +413,10 @@ static int LoadEncodingManifest(TCascStorage * hs)
401413
DWORD cbEncodingFile = 0;
402414
int nError = ERROR_SUCCESS;
403415

416+
// Inform the user about what we are doing
417+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Loading ENCODING manifest", NULL, 0, 0))
418+
return ERROR_CANCELLED;
419+
404420
// Load the entire encoding file to memory
405421
pbEncodingFile = LoadInternalFileToMemory(hs, &hs->EncodingCKey, &cbEncodingFile);
406422
if(pbEncodingFile != NULL && cbEncodingFile != 0)
@@ -728,6 +744,10 @@ static int LoadDownloadManifest(TCascStorage * hs)
728744
DWORD cbDownloadFile = 0;
729745
int nError = ERROR_SUCCESS;
730746

747+
// Inform the user about what we are doing
748+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Loading DOWNLOAD manifest", NULL, 0, 0))
749+
return ERROR_CANCELLED;
750+
731751
// Load the entire DOWNLOAD file to memory
732752
pbDownloadFile = LoadInternalFileToMemory(hs, pCKeyEntry, &cbDownloadFile);
733753
if(pbDownloadFile != NULL && cbDownloadFile != 0)
@@ -761,6 +781,10 @@ static int LoadInstallManifest(TCascStorage * hs)
761781
DWORD cbInstallFile = 0;
762782
int nError = ERROR_SUCCESS;
763783

784+
// Inform the user about what we are doing
785+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Loading INSTALL manifest", NULL, 0, 0))
786+
return ERROR_CANCELLED;
787+
764788
// Load the entire DOWNLOAD file to memory
765789
pbInstallFile = LoadInternalFileToMemory(hs, pCKeyEntry, &cbInstallFile);
766790
if (pbInstallFile != NULL && cbInstallFile != 0)
@@ -818,7 +842,11 @@ static int LoadBuildManifest(TCascStorage * hs, DWORD dwLocaleMask)
818842
pCKeyEntry = (hs->VfsRoot.ContentSize != CASC_INVALID_SIZE) ? &hs->VfsRoot : &hs->RootFile;
819843
pCKeyEntry = FindCKeyEntry_CKey(hs, pCKeyEntry->CKey);
820844

821-
// Load the entire ROOT file to memory. Ignore
845+
// Inform the user about what we are doing
846+
if(hs->PfnCallback && hs->PfnCallback(hs->PtrCallbackParam, "Loading ROOT manifest", NULL, 0, 0))
847+
return ERROR_CANCELLED;
848+
849+
// Load the entire ROOT file to memory
822850
pbRootFile = LoadInternalFileToMemory(hs, pCKeyEntry, &cbRootFile);
823851
if(pbRootFile != NULL)
824852
{
@@ -1134,6 +1162,12 @@ static int LoadCascStorage(TCascStorage * hs, DWORD dwLocaleMask)
11341162
//-----------------------------------------------------------------------------
11351163
// Public functions
11361164

1165+
void WINAPI CascSetProgressCallback(PFNPROGRESSCALLBACK PtrUserCallback, void * PtrUserParam)
1166+
{
1167+
PfnProgressCallback = PtrUserCallback;
1168+
PtrProgressParam = PtrUserParam;
1169+
}
1170+
11371171
bool WINAPI CascOpenStorage(LPCTSTR szPath, DWORD dwLocaleMask, HANDLE * phStorage)
11381172
{
11391173
TCascStorage * hs;

src/CascPort.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,11 @@
250250
#ifndef ERROR_BUFFER_OVERFLOW
251251
#define ERROR_BUFFER_OVERFLOW 1008
252252
#endif
253-
253+
254+
#ifndef ERROR_CANCELLED
255+
#define ERROR_CANCELLED 1009
256+
#endif
257+
254258
#ifndef _countof
255259
#define _countof(x) (sizeof(x) / sizeof(x[0]))
256260
#endif

src/common/FileStream.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ typedef void (*BLOCK_SAVEMAP)(
103103
struct TFileStream * pStream // Pointer to a block-oriented stream
104104
);
105105

106+
typedef void (WINAPI * STREAM_DOWNLOAD_CALLBACK)(
107+
void * pvUserData,
108+
ULONGLONG ByteOffset,
109+
DWORD dwTotalBytes
110+
);
111+
106112
//-----------------------------------------------------------------------------
107113
// Local structures - partial file structure and bitmap footer
108114

0 commit comments

Comments
 (0)