ladislav-zezula / CascLib

An open-source implementation of library for reading CASC storages from Blizzard games since 2014
MIT License
419 stars 123 forks source link

Weird behavior when opened in online mode if cache directory is inside a local casc storage #238

Closed Shauren closed 1 year ago

Shauren commented 1 year ago

Example: Local casc storage: "D:\World of Warcraft" remote cache: "D:\World of Warcraft\CascCache"

Attempting to read any file fails

Name: DBFilesClient\Achievement.db2
FileDataID: 1260179

The reason for this is I believe is a different EKEY value

"Local" 7f9344203188ec03df65df16387767fe (when opened casc storage using remote cache in D:\World of Warcraft\CascCache)
Remote: 9c1803860e4308f3c99a05132f618587 (when opened in a completely different directory)

Both local storage and remote storages point to the same build, wow 10.1.0.50000 with buildkey 26f9ff71801755f7cfc70519c32e41b5 and cdnkey 84904d5782e063b87455d8312fa800c5

I believe this part of the code is responsible for this behavior, more specifically build info lookup order, that then causes LoadIndexFiles to take a different code path https://github.com/ladislav-zezula/CascLib/blob/0d65a1caa6927a440999fe9a341ae6aaccbd5f65/src/CascOpenStorage.cpp#L1388-L1413

Should anything be done about it on casclib side or should applications detect this kind of edge case and protect themselves from it?

Yes, I agree that using remote mode of casclib inside a local storage is dumb but somebody did this and I had to spend a lot of time figuring out why remote mode was not working for that user

ladislav-zezula commented 1 year ago

I downloaded the build 50000. I also made extra online storage and copied it into the CascCache subfolder of the local storage. It seems that in both local and online storage, the file DBFilesClient\Achievement.db2 is encrypted and the key is not known.

Shauren commented 1 year ago

db2 files are only partially encrypted (which is why #138 and CASC_OVERCOME_ENCRYPTED are a thing)

but that should not make a difference for this specific issue (EKEY difference and cdn servers returning 404 for one of them)

ladislav-zezula commented 1 year ago

The bug comes from different setting of file locale.

Now the question is what to do with it.

Personally, I would simply set the default file locale to CASC_LOCALE_ALL for reading all WoW storages (non-WoW storages don't have locale anyway).

Another option would be to deduce the locale mask from the region.

Shauren commented 1 year ago

I don't think thats the case for me because the tool that I'm using CascLib in explicitly passes locale to CascOpenStorageEx in both local and remote cases,

this part doesn't apply to me https://github.com/ladislav-zezula/CascLib/blob/8ec142dffda174e1a5f0deb776d684afb852ff64/src/CascOpenStorage.cpp#L1207-L1214

ladislav-zezula commented 1 year ago

Another possible reason to your problem could be invalid structure of the online cache. By design, unless you pass the exact file name (CascOpenStorageEx(_T("d:\\World of Warcraft\\CascCache\\versions"), ...);), CascLib search folders upwards. This is by design - you can enter any subdirectory or a file in the game folder, and it should work. Now if you just create an empty subfolder World of Warcraft\CascCache and open is, it will go up and find the World of Warcraft\.build.info file, which is not something you want. What I did was I created the online cache folder completely away from the game folder, let CascLib download both versions and cdns files, then moved them into World of Warcraft\CascCache subfolder. That way, CascLib will find version as one of the supported main files and load that one.

Hard to say where exactly is your problem without having exact copy of your game folder. Maybe if you create the online cache separately and then move it into a subfolder, it will work. It certainly worked for me.

Shauren commented 1 year ago

Yes, thats exactly what happened (it found .build.info)

I don't actually need or want to support having online caches inside a game subdirectory

This issue is more like an observation that many functions inside CascLib think that storage was opened in online mode when it actually was not

240 is my answer to this situation

ladislav-zezula commented 1 year ago

I want to trigger online behavior anytime when a versions file is found, which can be in these cases:

Thus, I am offering you a "counter-merge-request": https://github.com/ladislav-zezula/CascLib/pull/241

Shauren commented 1 year ago

That also works for me, both our changes ensure that ((dwFeatures & CASC_FEATURE_ONLINE) != 0) == (BuildFileType == CascVersions)