GetSystemDirectoryA to String Variable

I'm trying to pass the result of GetSystemDirectoryA to a string variable or const char *.

What's the best way to do it?

https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya
Last edited on
The out parameter of the function is LPSTR/PSTR (char*/CHAR*, a C string). Trying to modify a const C string is gonna bomb. You can't modify a const.
https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya

A newer shell function should be used instead, SHGetFolderPathA if targeting before Vista and SHGetKnownFolderPath when targeting Vista or later.

https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpatha

https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
Theoretically you could use a C++ std::string and access the underlying char array using std::string::data.
https://en.cppreference.com/w/cpp/string/basic_string/data

I personally wouldn't do that, I simply use a non-const CHAR array.
Edit: already figured the conversion.

George P, Thanks for the added info.
Last edited on
Should first determine the required buffer length, then allocate the buffer as needed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::string get_system_directory(void)
{
    std::string result;
    const UINT len = GetSystemDirectoryA(NULL, 0U);
    if (len > 0)
    {
        std::vector<CHAR> buffer(len);
        const UINT ret = GetSystemDirectoryA(buffer.data(), len);
        if ((ret > 0) && (ret < len))
        {
            result = std::string(buffer.data(), ret);
        }
    }
    return result;
}


Note: If GetSystemDirectoryA() returns a value greater than uSize, then the function has failed because of insufficient buffer size, and it tells you the required buffer size, including the terminating NULL character.

So, you can call the function with uSize set to 0 to determine the required buffer size.

(BTW: In case of success, the return value will always be smaller than the given uSize, because in that case the return value does not include the terminating NULL character!)

________


SHGetKnownFolderPath only has a wide-string version. And you should be working with wide-strings anyway, if you are dealing with paths on the Windows platform – because NTFS is fully Unicode-aware, and therefore an ANSI-string can not represent all possible file/path names that may exist on an NTFS volume!

1
2
3
4
5
6
7
8
9
10
11
std::wstring get_known_folder_path(const GUID &folder_id)
{
    std::wstring result;
    WCHAR *buffer;
    if (SHGetKnownFolderPath(folder_id, KF_FLAG_DEFAULT, NULL, &buffer) == S_OK)
    {
        result = std::wstring(buffer);
        CoTaskMemFree(buffer);
    }
    return result;
}


If you really want to, you can convert the wide string into an ANSI-string, but this will get you into troubles if the wide-string path contains characters that can not be represented in the user's local ANSI codepage!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::string wstring_to_string(const std::wstring& wide_string)
{
    const wchar_t *wstr = wide_string.c_str();
    size_t len;
    mbstate_t state;
    memset(&state, 0, sizeof state);
    if (wcsrtombs_s(&len, NULL, 0, &wstr, _TRUNCATE, &state) == 0)
    {
        std::vector<char> buffer(len);
        if (wcsrtombs_s(&len, buffer.data(), buffer.size(), &wstr, _TRUNCATE, &state) == 0)
        {
            return std::string(buffer.data());
        }
    }
    return std::string();
}


Last edited on
Topic archived. No new replies allowed.