I purposely set a bad path for a CreateDirectory call so that my exception handling code would execute:
I am not sure if this is off topic, but you might have more experience with this. Why is the error text:
An attempt was made to reference a token that does not exist.
Why are they using the word token instead of file or folder?
I will close the question if off topic.
The return value of GetLastError is: 123
According to here:
ERROR_INVALID_NAME
123 (0x7B)The filename, directory name, or volume label syntax is incorrect.
Now that message makes sense. So why is my Windows 10 showing the other message?

There is no issue with the call to
FormatMessage. It works as advertised. However, you aren't passing in the value 123 (ERROR_INVALID_NAME). You are passing 1008 (ERROR_NO_TOKEN), by accident, due to callingGetLastErrorat the wrong time. GetLastError has a strong requirement:It's fairly straightforward to satisfy this in C. With C++, things get more complicated, with all the invisible code the compiler generates. The code in question apparently captures the calling thread's last error code only after it enters the
CWin32FileErrorc'tor. That's too late.Based on the assumption that
GetWorkingPath()returns aCStringinstance by value, andCWin32FileErrortakes its arguments asCString const&, this is what happens behind the scenes:GetWorkingPath()constructs a temporaryCStringinstance.operator+(CString const&, LPCTSTR)constructs yet another temporaryCStringinstance, concatenating both inputs.operator LPCTSTR()is implicitly invoked on the temporary constructed in step 2.CreateDirectoryis called and returns.Steps 5 and 6 are fatal already, potentially changing the calling thread's last error code. And yet, there's even more code getting in the way:
_T("whatever")triggersCString's conversion constructor (CString(LPCTSTR)), producing a temporary.GetWorkingPath()constructs a temporary, invokingCString's copy-c'tor.operator+(CString const&, LPCTSTR)constructs yet another temporary.CWin32FileErrorc'tor finally runs, presumably callingGetLastError.This adds another 3 candidates (at least) that can modify the calling thread's last error code. To solve this, you're going to have to make sure, that absolutely no code runs in between a failed Windows API call and the call to
GetLastError.To do this, you're going to have to get rid of the temporaries, and move capturing of the last error code outside the
CWin32FileErrorc'tor. A simple solution to the former would be to construct the path name up front, e.g.(or use an init-statement in the if statement to limit the scope, if you are using C++17). Either way, your very next call must be
GetLastErrorto capture the last error code while it is still meaningful. However you pass that value intoCWin32FileError's c'tor, or which argument types it uses, is up to you. But you cannot rely on that c'tor to capture the last error code for you.