0

I'm using ExpandEnvironmentStringsForUser function to expand a directory which includes environment variable. However, the returned value is sometimes wrong.

My process is running with system privilege.

E.g:

  • Input string: "C:\Users\%username%\Documents\"

  • Output string (maybe one of following strings)

C:\Users\cuong.huynh\Documents\ (expected output)

C:\Users\cuong.huynh\AppData\Roaming (wrong)

C:\Program Files\Common Files (wrong)

My brief code is as follows:

DWORD dwSessionID = WTSGetActiveConsoleSessionId();
WTSQueryUserToken(dwSessionID, &hUserToken);
DuplicateToken(hUserToken, SecurityImpersonation, &hDuplicated)
hToken = hDuplicated;

LPCWSTR DesPath = (StringUtil::StrToWstr(setting)).c_str(); //(input)
wchar_t ExpandedDesPath[MAX_PATH]; //(output)

ExpandEnvironmentStringsForUser(hToken, DesPath, ExpandedDesPath, MAX_PATH - 1)

Does anyone know the reason why the output is not stable?

CH4
  • 85
  • 2
  • 13
  • I've never once had it return the wrong value. Please provide an actual, full [mcve] that demonstrates the issue. (That [mcve] should be able to be copied, pasted, compiled and executed, and demonstrate the issue you're having. It should contain the exact input that you're providing that produces different results when used multiple times.) – Ken White Feb 21 '19 at 03:55
  • 2
    Sounds like `setting` isn't what you think it is. – Jonathan Potter Feb 21 '19 at 03:55
  • for what you call `DuplicateToken` ?! – RbMm Feb 21 '19 at 06:14
  • Thank everyone, The issue was fixed as below Remy's solution. – CH4 Feb 21 '19 at 09:41
  • 2
    You should be using the shell functions to get these paths. – Anders Feb 21 '19 at 11:02
  • 1
    Possible duplicate of [Why does calling std::string.c\_str() on a function that returns a string not work?](https://stackoverflow.com/questions/35980664/why-does-calling-stdstring-c-str-on-a-function-that-returns-a-string-not-wor) – Raymond Chen Feb 21 '19 at 23:41

1 Answers1

1
LPCWSTR DesPath = (StringUtil::StrToWstr(setting)).c_str();`

This creates a temporary wstring that goes out of scope immediately after DesPath is assigned, leaving DestPath dangling and pointing at invalid memory. You need to store the result of StrToWstr() to a local wstring variable first before then calling c_str() on it, so the string memory stays in scope:

wstring wstr = StringUtil::StrToWstr(setting);
LPCWSTR DesPath = wstr.c_str();

Otherwise, call StrToWstr().c_str() directly in the input parameter of ExpandEnvironmentStringsForUser():

ExpandEnvironmentStringsForUser(hToken, StringUtil::StrToWstr(setting).c_str(), ExpandedDesPath, MAX_PATH - 1);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770