2

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.

Davita
  • 8,928
  • 14
  • 67
  • 119
  • The WinAPI does not have a reverse lookup. – MicroVirus Aug 11 '15 at 12:16
  • @MicroVirus you sure about that? :) If that's so, just post it as answer so I could accept it. – Davita Aug 11 '15 at 12:17
  • 1
    I'd prefer an answer to this question to be the API functions/code that you could reliably use to get the reverse lookup, so even if I am right (which I think I am), then I feel this is not 'the answer'. – MicroVirus Aug 11 '15 at 12:19
  • Note that such an answer would, at the very least, need to account for environment variables to be robust enough, and probably there are more caveats too, so I'd give it a while and maybe you can update your answer with a partial solution if you have it, so that this can be improved. – MicroVirus Aug 11 '15 at 12:21
  • Why would you want to know if a path is a special folder? – Mark Jansen Aug 11 '15 at 12:33

1 Answers1

5

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

Mark Jansen
  • 1,491
  • 12
  • 24