bugfix(globaldata): Fix the handling of documents folder redirection by using SHGetKnownFolderPath()#2479
Conversation
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/Common/GlobalData.cpp | Wraps legacy SHGetSpecialFolderPath in #if _MSC_VER < 1300 and adds a modern SHGetKnownFolderPath path for all other compilers. CoTaskMemFree is correctly placed outside the success-check block. Logic mirrors the existing code structure cleanly. |
| GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp | Same preprocessor guard + SHGetKnownFolderPath pattern as the Generals counterpart. Registry-based leaf name lookup is preserved. CoTaskMemFree is placed outside the success block correctly. New block uses tab indentation while the surrounding #if block uses 2-space indentation — minor inconsistency. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[parseGameDataDefinition / GlobalData constructor] --> B{_MSC_VER < 1300?}
B -- Yes / VC6 --> C[SHGetSpecialFolderPath\nCSIDL_PERSONAL]
C --> D{Success?}
D -- No --> Z[m_userDataDir stays empty]
D -- Yes --> E[Append backslash if needed]
E --> F[Append leaf name + backslash]
F --> G[CreateDirectory]
G --> H[m_userDataDir = path]
B -- No / modern compiler --> I[SHGetKnownFolderPath\nFOLDERID_Documents]
I --> J[CoTaskMemFree pszPath]
I --> K{SUCCEEDED and pszPath?}
K -- No --> J
K -- Yes --> L[AsciiString::translate from PWSTR]
L --> M[Append backslash if needed]
M --> N[Append leaf name + backslash]
N --> O[CreateDirectory]
O --> P[m_userDataDir = path]
P --> J
Last reviewed commit: "bugfix(globaldata): ..."
|
Ah i didn't check building with VC6, will work on this further |
0c251b8 to
9aeb428
Compare
|
Updated by making the fix conditoinal so it only works in non VC6 builds |
…by using SHGetKnownFolderPath() - Vista+ required
9aeb428 to
0378670
Compare
|
Cleaned up the implementations by replicating the whole code block |
|
Removed controversial as this fix does not work in VC6 in the end anyway, so i had to make the fix conditional at compilation |
| AsciiString myDocumentsDirectory; | ||
| myDocumentsDirectory.translate(UnicodeString(pszPath)); | ||
|
|
||
| if (myDocumentsDirectory.getCharAt(myDocumentsDirectory.getLength() -1) != '\\') |
There was a problem hiding this comment.
Can hardcoded path separators be an issue for (future) linux support?
There was a problem hiding this comment.
All of this will need altering to support linux in the future, the main functions for getting the documents folder are windows API.
|
|
||
| TheWritableGlobalData->m_userDataDir.clear(); | ||
|
|
||
| #if defined(_MSC_VER) && _MSC_VER < 1300 |
There was a problem hiding this comment.
Better use GetProcAddress(shell32module, "SHGetKnownFolderPath") to test the system for the function. This way the compiler condition is not required.
There was a problem hiding this comment.
Will this work with compiling in VC6?
| CreateDirectory(myDocumentsDirectory.str(), nullptr); | ||
| TheWritableGlobalData->m_userDataDir = myDocumentsDirectory; | ||
| } | ||
| CoTaskMemFree(pszPath); |
There was a problem hiding this comment.
I suggest move all this into a new function to tidy up this function:
TheWritableGlobalData->m_userDataDir = BuildUserDataPath();
CreateDirectory(TheWritableGlobalData->m_userDataDir.str(), nullptr);| AsciiString myDocumentsDirectory; | ||
| myDocumentsDirectory.translate(UnicodeString(pszPath)); | ||
|
|
||
| if (myDocumentsDirectory.getCharAt(myDocumentsDirectory.getLength() -1) != '\\') |
There was a problem hiding this comment.
Simpler: !myDocumentsDirectory.endsWith("\\")
There was a problem hiding this comment.
Nice, i forgot we had those functions to use now.
| if (temp[strlen(temp)-1] != '\\') | ||
| strcat(temp, "\\"); | ||
| strcat(temp, TheWritableGlobalData->m_userDataLeafName.str()); | ||
| strcat(temp, "\\"); |
There was a problem hiding this comment.
You can probably consolidate the old string handling logic with the new logic.
This PR improves folder redirection handling that can occur due to Group Policy or OneDrive redirecting the users documents folder.
This only works for non retail builds as it required a function not supported under VC6 as it only appeared in Vista onwards.
SHGetKnownFolderPath() has better handling of folder redirection built into it compared to the legacy SHGetSpecialFolderPath()
Generals and zero hour use different ways to obtain the game folder name which is why the code is different between them.