-1

So, i have a piece of code (c++) that gets the users name (in windows) and with the retrieved string the code creates respective directories...

BOOL DirectoryExists(const char* dirName) {

    TCHAR nameu[UNLEN + 1];
    DWORD size = UNLEN + 1;
    if (GetUserName((TCHAR*)nameu, &size))
    {
        TCHAR* t = nameu;
        wcout << t;
        //_getch();
        std::string str;
        std::wstring wStr = t;
        str = std::string(wStr.begin(), wStr.end());
        usr = str;

        dir[0] = (std::string("C:\\Users\\") + str + "\\Documents\\Folder").c_str();
    }

    DWORD attribs = ::GetFileAttributesA(dirName);
    if (attribs == INVALID_FILE_ATTRIBUTES) {
        return false;
    }
    return (attribs & FILE_ATTRIBUTE_DIRECTORY);
}

here, the GetUserName() functions gets the user name and this piece of code works fine if the user name is just one straight string, but if the usr name had two parts split by space (eg: "example account"), then the code only takes the first part and leaves the 2nd part/name....

how do i solve this ?

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • 1
    Is `GetUserName` a Windows API function or is it one you wrote? If it is the latter, pleace include the function definition. – NathanOliver May 28 '20 at 17:21
  • @NathanOliver: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getusernamea – selbie May 28 '20 at 17:22
  • You can also simply say: `dir[0] = "C:\\Users\\" + str + "\\Documents\\Folder";` – selbie May 28 '20 at 17:24
  • 2
    This `str = std::string(wStr.begin(), wStr.end());` is the wrong way to convert a unicode string. – selbie May 28 '20 at 17:31
  • 1
    Don't build the directory name yourself, use the appropriate Win32 call instead, e.g. https://stackoverflow.com/q/9542611/1741542 – Olaf Dietsche May 28 '20 at 17:37
  • I'm also confused because I see no code here that does anything with spaces. It should work fine. Even `GetFileAttributesA` accepts spaces – Mooing Duck May 28 '20 at 17:44

1 Answers1

4

You have a lot of redundant and unnecessary string copies.

I'm fairly certain this is what you want to have:

wchar_t nameu[UNLEN + 1];
DWORD size = UNLEN + 1;
if (GetUserNameW(nameu, &size))
{
    dir[0] = L"C:\\Users\\" + std::wstring(nameu) + L"\\Documents\\Folder";
}

Ideally dir[0] is of type wstring, not string. You really should be using unicode everywhere when dealing with Windows APIs. That will support users with unicode characters in their name properly.

Otherwise, if dir[0] is a string, then this:

char nameu[UNLEN + 1];
DWORD size = UNLEN + 1;
if (GetUserNameA(nameu, &size))
{
    dir[0] = "C:\\Users\\" + std::string(nameu) + "\\Documents\\Folder";
}

And finally, hardcoded Documents at the end of the assumed user profile path is also the incorrect way to get the users default Documents folder. There's lots of scenarios where users move their Documents folder elsewhere.

Use SHGetKnownFolderPath instead. That might be what you really need after all. Just invoke SHGetKnownFolderPath(FOLDERID_Documents) and then append "Folder" to the end of it.

So this is what you really want:

wchar_t* path=nullptr;
SHGetKnownFolderPathW(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &path);
dir[0] = std::wstring(path) + L"\\Folder";
CoTaskMemFree(path);

Or non-unicode:

char* path=nullptr;
SHGetKnownFolderPathA(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &path);
dir[0] = std::string(path) + "\\Folder";
CoTaskMemFree(path);
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
selbie
  • 100,020
  • 15
  • 103
  • 173