Search code examples
windowswinapispecial-folders

Check if a given path is a special folder path?


On Windows, one can get any special folder path using SHGetKnownFolderPath or SHGetSpecialFolder (If I remember correctly this last one). However, I want the reverse, I have a path and want to know which special folder it belongs to, if any. I prefer this approach, because to find out if a given path's is in a particular special folder or not, I'll have to enumerate all special folders for all users which is a bit of ugly, but if there's no other way, the sky is the limit :)

I searched it but couldn't find anything useful. So does WinApi has a function to do just that?

Thanks.


Solution

  • You can use IKnownFolderManager::FindFolderFromPath

    Available since Vista.

    PS: check out the CComPtr<> class for simpler interfacing with COM.

    Here is a sample i just made up, showing how to use it:

    #include <atlsafe.h>
    #include <Shobjidl.h>
    #include <comdef.h>
    
    void PrintKnownFolder( const CComPtr<IKnownFolder>& folder )
    {
        KNOWNFOLDER_DEFINITION def;
        HRESULT hr = folder->GetFolderDefinition( &def );
        if( SUCCEEDED(hr) ) {
            std::wcout << L"Result: " << def.pszName << std::endl;
            FreeKnownFolderDefinitionFields( &def );
        } else {
            _com_error err(hr);
            std::wcout << L"Error while querying GetFolderDefinition: " << err.ErrorMessage() << std::endl;
        }
    }
    
    
    class CCoInitialize
    {
    public:
        CCoInitialize() : m_hr(CoInitialize(NULL)) { }
        ~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
        operator HRESULT() const { return m_hr; }
    private:
        HRESULT m_hr;
    };
    
    
    bool test()
    {
        CCoInitialize co;
        CComPtr<IKnownFolderManager> knownFolderManager;
        HRESULT hr = knownFolderManager.CoCreateInstance( CLSID_KnownFolderManager );
        if( !SUCCEEDED(hr) ) {
            _com_error err(hr);
            std::wcout << L"Error while creating KnownFolderManager: " << err.ErrorMessage() << std::endl;
            return false;
        }
    
        CComPtr<IKnownFolder> folder;
        hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_NEARESTPARENTMATCH, &folder );
        if( SUCCEEDED(hr) ) {
            PrintKnownFolder(folder);
        } else {
            _com_error err(hr);
            std::wcout << L"Error while querying KnownFolderManager for nearest match: " << err.ErrorMessage() << std::endl;
        }
    
        // dispose it.
        folder.Attach( NULL );
    
        hr = knownFolderManager->FindFolderFromPath( L"C:\\Users\\All Users\\Microsoft", FFFP_EXACTMATCH, &folder );
        if( SUCCEEDED(hr) ) {
            PrintKnownFolder(folder);
        } else {
            _com_error err(hr);
            std::wcout << L"Error while querying KnownFolderManager for exact match: " << err.ErrorMessage() << std::endl;
        }
    
        return true;
    }
    

    CCoInitialize borrowed from The Old New Thing