How can I get the canonical name for a known folder?

Date:February 8, 2016 / year-entry #29
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20160208-00/?p=93001
Comments:    19
Summary:You ask it.

A customer had a question about the IKnown­Folder::Get­Folder­By­Name method: "What is the canonical name for the Documents folder? We tried "Documents" but that didn't work."

One question that comes to mind is why you are using this method to begin with. If you already know that you want the Documents folder, then use IKnown­Folder::Get­Folder and pass FOLDERID_Documents. Just go straight for the thing you want; don't play around with canonical names.

But okay, let's answer the question anyway. The way to get the canonical name for a folder is to ask it!

Today's smart pointer library is (rolls dice) ATL!

#include <windows.h>
#include <shlobj.h>
#include <stdio.h> // horrors! Mixing stdio and C++!
#include <atlbase.h>
#include <atlalloc.h>

int __cdecl main()
{
 CCoInitialize init;

 CComPtr<IKnownFolderManager> mgr;
 CoCreateInstance(CLSID_KnownFolderManager, 0,
                  CLSCTX_ALL, IID_PPV_ARGS(&mgr));

 CComPtr<IKnownFolder> kf;
 mgr->GetFolder(FOLDERID_Documents, &kf);
 KNOWNFOLDER_DEFINITION def;
 kf->GetFolderDefinition(&def);
 printf("%ls\n", def.pszName);
 FreeKnownFolderDefinitionFields(&def);
 return 0;
}

Run this program and it tells you that the canonical name is Personal.

Let's go one step further: Let's print the canonical names for all of the known folders.

#include <windows.h>
#include <shlobj.h>
#include <stdio.h> // horrors! Mixing stdio and C++!
#include <atlbase.h>
#include <atlalloc.h>

int __cdecl main()
{
 CCoInitialize init;

 CComPtr<IKnownFolderManager> mgr;
 CoCreateInstance(CLSID_KnownFolderManager, 0,
                  CLSCTX_ALL, IID_PPV_ARGS(&mgr));

 UINT count;
 CComHeapPtr<KNOWNFOLDERID> kfids;
 mgr->GetFolderIds(&kfids, &count);
 for (UINT index = 0; index < count; index++) {
  CComPtr<IKnownFolder> kf;
  mgr->GetFolder(kfids[index], &kf);
  KNOWNFOLDER_DEFINITION def;
  kf->GetFolderDefinition(&def);
  printf("%ls\n", def.pszName);
  FreeKnownFolderDefinitionFields(&def);
 }
 return 0;
}

Comments (19)
  1. Searches
    Windows
    ProgramFilesCommon
    MusicLibrary
    PublicLibraries
    Common Desktop
    CD Burning
    OneDriveCameraRoll
    SavedPicturesLibrary
    MAPIFolder
    Common Start Menu
    Games
    My Video
    Quick Launch
    ProgramFilesCommonX86
    OneDriveDocuments
    3D Objects
    ConnectionsFolder
    PrintersFolder
    VideosLibrary
    My Pictures
    ResourceDir
    Common Startup
    PublicGameTasks
    SyncSetupFolder
    CommonVideo
    Desktop
    History
    SamplePictures
    SyncResultsFolder
    ConflictFolder
    RecycleBinFolder
    OneDrive
    CSCFolder
    Ringtones
    Common Programs
    NetHood
    Contacts
    UserProgramFilesCommon
    Roaming Tiles
    Local Pictures
    UsersLibrariesFolder
    Cookies
    LocalizedResourcesDir
    CommonRingtones
    GameTasks
    Favorites
    Local Videos
    SampleMusic
    HomeGroupFolder
    SendTo
    PublicAccountPictures
    ImplicitAppShortcuts
    Administrative Tools
    My Music
    AddNewProgramsFolder
    Captures
    UserProfiles
    InternetFolder
    CameraRollLibrary
    System
    Programs
    Camera Roll
    UsersFilesFolder
    MyComputerFolder
    Common Administrative Tools
    DocumentsLibrary
    Application Shortcuts
    Recent
    Screenshots
    SavedPictures
    Common AppData
    Local AppData
    ThisPCDesktopFolder
    CommonPictures
    AppsFolder
    PrintHood
    Development Files
    Profile
    PhotoAlbums
    Downloads
    SampleVideos
    Local Music
    AppUpdatesFolder
    CommonDownloads
    Local Downloads
    OneDriveMusic
    Common Start Menu Places
    PicturesLibrary
    Public
    RecordedTVLibrary
    HomeGroupCurrentUserFolder
    LocalAppDataLow
    Roamed Tile Images
    CryptoKeys
    Original Images
    User Pinned
    ChangeRemoveProgramsFolder
    Common Documents
    SystemX86
    AccountPictures
    OneDrivePictures
    CommonMusic
    SearchHistoryFolder
    ProgramFiles
    Fonts
    Startup
    Recorded Calls
    Start Menu
    NetworkPlacesFolder
    Playlists
    DpapiKeys
    Personal
    OEM Links
    SearchHomeFolder
    Local Documents
    AppData
    Libraries
    ThisDeviceFolder
    SystemCertificates
    Links
    UserProgramFiles
    Common Templates
    Cache
    Templates
    Device Metadata Store
    ControlPanelFolder
    ProgramFilesX86
    SyncCenterFolder
    CredentialManager
    SearchTemplatesFolder
    SavedGames

    1. Noting that known folders can be added dynamically, so this list can change.

    2. Medinoc says:

      It’s a bit weird that some names use CamelCase while others use spaces.

  2. skSdnW says:

    And for a trip down memory lane from before Vista when these things were called special folders:

    There is no official way to get the canonical names (IIRC) but they are the same as the value names in the User Shell Folders key. You can however go from the canonical name to the path if you prefix the name with “shell:” before handing it to SHParseDisplayName.

  3. — “Run this program and it tells you that the canonical name is Personal.”

    LOL! There is nothing personal about “Documents” folder. It is a hybrid of “temp” folder and “AppData\Local”.

    1. Henri Hein says:

      What do you mean? Few, if any, users treat “Documents” as temporary. Temp and AppData are both personal folders.

      1. Koro says:

        He means that so many programs treat it as their Temp or AppData folder, that it’s pretty much unusable as a documents folder.

      2. DWalker says:

        Right. I keep my permanent documents in the “Documents” folder. Temp stuff is in %appdata%\Local\temp, or whatever magic name is given to C:\Windows\Temp. The first one is in the %username% hierarchy but not in Documents.

        1. I just wish more software that used %TEMP% actually cleaned up after itself. Mine contains about a gig of data right now.

    2. Juan says:

      I guess that, as often happens, is something inherited from the past. “My Documents” Folder was introduced by Office for Windows 95. Windows NT had a Personal folder in the user profile. In fact if Office installation detected that it was being installed in Windows NT it used the personal folder as “My Documents” and created a new folder altogether if it detected it was being installed in Windows 9x since Windows 95 didn’t come with user profiles and only created a very basic one if a network was set up but with no security at all.

      1. Neil says:

        User profiles were an option in Windows 95 and they didn’t need a network.

        1. Juan says:

          True. I had forgotten that part.

      2. skSdnW says:

        Windows 95 RTM supports (My) Documents, Desktop, Start Menu etc and AppData (but not Local AppData) and the virtual folders like My Computer, Control Panel and Recycle Bin no matter what the setup is. In single user mode these folders just live in the root of %WinDir%.

        1. Juan says:

          Windows 95 RTM did not come with the folder My documents when it came out. It was installed with Office for Windows 95 and later versions. Windows 95 OSR2 and later versions of the Windows 9x had them out of the box. Windows NT did not renamed the Personal folder to “My Documents” to match with Windows 9x until Windows 2000.

          1. skSdnW says:

            This is what I get from trusting a old MSJ article :/

            Turns out we are both wrong. OSR2 (at least the first version) does not have a Documents folder out of the box and you cannot create one either but one noticeable change from RTM is that CSIDL_FAVORITES can now be created if you call a undocumented shell function. SHGetSpecialFolderLocation(CSIDL_FAVORITES) is unable to create it so this API only starts working after the folder exists.

            SHGetSpecialFolderLocation(CSIDL_PERSONAL) fails with the documented and undocumented APIs on both versions when I tested on clean systems: http://i.imgur.com/uVYsrNZ.png

            I did not test to see if anything changes in multi-user mode. Maybe Raymond remembers the details?

  4. Ray Koopa says:

    And then there are these “developers” who don’t care at all and deal with “known folders” by abusing a specifc registry key which includes a warning to not use it by _someone_… ;)

  5. aaron says:

    Raymond,
    You seem to mix-n-match your api-idioms. Is there a reason why?

    After starting with CComPtr, you use win32-Api ::CoCreateInstance instead of CComPtr::CoCreateInstance.
    I generally feel that if you’re going adopt a tool/feature/library (like CComPtr), you should generally go all-in on it, or not use it at all.

    1. I neglected to mention that the dice roll specifically picked ATL 2.1, which doesn’t support CComPtr.CoCreateInstance. (This is actually a lie, because ATL 2.1 doesn’t have atlalloc.h. The real reason is that I learned ATL with ATL 2.1, so I always forget that there is a CoCreateInstance method directly on CComPtr.)

      1. aaron says:

        Thank you! I wasn’t aware that CoCreateInstance ever *wasn’t* part of CComPtr, as it seems so essential. But I can see how old habits die hard. :)

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index