//+----------------------------------------------------------------------------
//
// File:     allcmdir.cpp
//
// Module:   CMCFG32.DLL and CMSTP.EXE
//
// Synopsis: Implementation of GetAllUsersCmDir
//
// Copyright (c) 1999 Microsoft Corporation
//
// Author:   quintinb       Created Header      08/19/99
//
//+----------------------------------------------------------------------------



//+----------------------------------------------------------------------------
//
// Function:  GetAllUsersCmDir
//
// Synopsis:  This function fills in the string passed in with the path to the
//            path where CM should be installed.  For instance, it should return
//            c:\Documents and Settings\All Users\Application Data\Microsoft\Network\Connections\Cm
//
// Arguments: LPTSTR  pszDir - String to the Users Connection Manager Directory
//
// Returns:   LPTSTR - String to the Users Connection Manager Directory
//
// History:   quintinb Created Header    2/19/98
//
//+----------------------------------------------------------------------------
BOOL GetAllUsersCmDir(LPTSTR  pszDir, HINSTANCE hInstance)
{
    MYDBGASSERT(pszDir);
    pszDir[0] = TEXT('\0');

    LPMALLOC pMalloc;
    HRESULT hr = SHGetMalloc(&pMalloc);
    if (FAILED (hr))
    {
        CMASSERTMSG(FALSE, TEXT("Failed to get a Shell Malloc Pointer."));
        return FALSE;
    }

    TCHAR szCmSubFolder[MAX_PATH+1];
    TCHAR szAppData[MAX_PATH+1];
    TCHAR szDesktop[MAX_PATH+1];
    LPITEMIDLIST pidl;
    BOOL bReturn = FALSE;

    //
    //  We really want the Common App Data dir, but this CSIDL value is only supported on
    //  NT5 so far.  If this succeeds, we only need to append the path to it.
    //
    hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_APPDATA, &pidl);
    if (SUCCEEDED(hr))
    {
        if (!SHGetPathFromIDList(pidl, pszDir))
        {
            CMASSERTMSG(FALSE, TEXT("GetAllUsersCmDir -- SHGetPathFromIDList Failed to retrieve CSIDL_COMMON_APPDATA"));
            goto exit;
        }
        
        pMalloc->Free(pidl);
        pidl = NULL;
    }
    else
    {
        //
        //  Of course, things aren't always that easy, lets try getting the regular
        //  Application Data dir.  We can hopefully combine the returns from two
        //  CSIDL's like CSIDL_APPDATA and CSIDL_COMMON_DESKTOPDIRECTORY to acheive the
        //  same affect on older machines.
        //

        hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
        if (SUCCEEDED(hr))
        {
            if (!SHGetPathFromIDList(pidl, szAppData))
            {
                goto exit;
            }

            pMalloc->Free(pidl);
            pidl = NULL;
        }
        else
        {
            //
            //  CSIDL_APPDATA isn't even supported on win95 gold
            //
            MYVERIFY(0 != LoadString(hInstance, IDS_APPDATA, szAppData, MAX_PATH));
        }

        //
        //  Now lets try to get the Common Desktop Directory to combine the two
        //
        BOOL bCommonFound = FALSE;

        hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &pidl);
        if (SUCCEEDED(hr))
        {
            if (SHGetPathFromIDList(pidl, szDesktop))
            {
                bCommonFound = TRUE;
            }

            pMalloc->Free(pidl);
            pidl = NULL;
        }

        if (!bCommonFound)
        {
            //
            //  Okay, next lets try the Reg Key for the common desktop directory.
            //  (Win98 gold with profiling contains the reg key but the CSIDL fails)
            //
            const TCHAR* const c_pszRegShellFolders = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
            const TCHAR* const c_pszRegCommonDesktop = TEXT("Common Desktop");
            HKEY hKey;

            if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_pszRegShellFolders, 
                0, KEY_READ, &hKey))
            {
                DWORD dwSize = MAX_PATH;
                DWORD dwType = REG_SZ;

                if (ERROR_SUCCESS == RegQueryValueEx(hKey, c_pszRegCommonDesktop, 
                                                     NULL, &dwType, (LPBYTE)szDesktop, 
                                                     &dwSize))
                {
                    bCommonFound = TRUE;
                }
                RegCloseKey(hKey);
            }
        }

        if (!bCommonFound)
        {
            //
            //  As a fall back lets try the windows directory, NTRAID 374912
            //
            if (GetWindowsDirectory(szDesktop, MAX_PATH))
            {
                //
                //  Then we have the windows directory, but we need to append
                //  \\Desktop so that the parsing logic which follows parses
                //  this correctly.  It is expecting the path to the desktop dir
                //  not a path to the windows dir (if we didn't we would end up with
                //  c:\Application Data instead of c:\windows\Application data as we
                //  want and expect).  Note that there is no need to worry about 
                //  localization of Desktop because we are going to remove it anyway.
                //
                lstrcat(szDesktop, TEXT("\\Desktop"));
            }
        }

        CFileNameParts AppData(szAppData);
        CFileNameParts CommonDesktop(szDesktop);

        wsprintf(pszDir, TEXT("%s%s%s"), CommonDesktop.m_Drive, CommonDesktop.m_Dir, 
            AppData.m_FileName, AppData.m_Extension);
    }

    //
    //  Now append the CM sub directory structure
    //
    if (!LoadString(hInstance, IDS_CMSUBFOLDER, szCmSubFolder, MAX_PATH))
    {
        goto exit;
    }

    MYVERIFY(NULL != lstrcat(pszDir, szCmSubFolder));    

    bReturn = TRUE;

exit:
    //
    //  Free the allocated pidl if necessary
    //
    if (pidl)
    {
        pMalloc->Free(pidl);
    }

    //
    // release the shell's IMalloc ptr
    //
    pMalloc->Release();

    return bReturn;
}