SVERROR SVMakeSureDirectoryPathExists()

in host/common/win32/portablehelpersmajor.cpp [2535:2636]


SVERROR SVMakeSureDirectoryPathExists(const char* pszDestPathname)
{
    //TODO: re-use tal code which creates missing directories.
    ACE_Guard<ACE_Recursive_Thread_Mutex> dirCreateMutexGuard(dirCreateMutex);
    SVERROR rc = SVS_OK;
    if (NULL == pszDestPathname || 0 == pszDestPathname[0])
    {
        rc = SVE_INVALIDARG;
        return rc;
    }

    size_t pathnamelen;
    INM_SAFE_ARITHMETIC(pathnamelen = InmSafeInt<size_t>::Type(strlen(pszDestPathname)) + 2, INMAGE_EX(strlen(pszDestPathname)))
        char *szPathname = new char[pathnamelen];
    memset(szPathname, 0, pathnamelen);
    inm_strcpy_s(szPathname, pathnamelen, pszDestPathname);

    do
    {
        SVERROR hr = ReplaceChar(szPathname, '/', '\\');
        if (hr.failed())
        {
            rc = hr;
            break;
        }

        size_t cch = strlen(szPathname);

        if (cch < (MAX_PATH - 20))
        {
            if ('\\' != szPathname[cch - 1])
            {
                szPathname[cch + 1] = 0;
                szPathname[cch] = '\\';
            }

            try
            {
                CreatePaths::createPathsAsNeeded(szPathname);
            }
            catch (std::exception ex)
            {
                DebugPrintf(SV_LOG_ERROR, "%s failed: %s\n", FUNCTION_NAME, ex.what());
                rc = SVS_FALSE;
                break;
            }
        }
        else
        {
            std::wstring szPrefix;
            USES_CONVERSION;
            std::wstring tempName = A2W(szPathname);
            std::wstring::size_type index1 = 0;
            std::wstring::size_type index2;
            index2 = tempName.find(L'\\', 2);

            while (index2 < tempName.size())
            {
                index1 = index2 + sizeof(std::wstring::value_type);
                index2 = tempName.find(L'\\', index1);
                if (index2 == std::string::npos)
                    index2 = tempName.size();
                if (szPathname[0] == '\\' && szPathname[1] == '\\' &&
                    szPathname[2] == '?' &&	szPathname[3] == '\\')
                {
                    szPrefix = L"";
                }
                else
                {
                    szPrefix = L"\\\\?\\";
                }
                szPrefix += tempName.substr(0, index2);

                //remove repeting '\\' if any
                std::wstring::size_type index = -1;
                while ((index = szPrefix.find(L'\\', ++index)) != szPrefix.npos)
                    if (index >= 4 && szPrefix[index - 1] == L'\\')
                        szPrefix.erase(szPrefix.begin() + index--);

                DebugPrintf(SV_LOG_DEBUG, "Directory Path: %S\n", szPrefix.c_str());
                if (szPrefix.size() > 0)
                {
                    bool bCreated = CreateDirectoryW(szPrefix.c_str(), 0);
                    if (!bCreated)
                    {
                        DWORD dwError = GetLastError();
                        if (dwError != ERROR_ALREADY_EXISTS)
                        {
                            DebugPrintf(SV_LOG_ERROR, "FAILED Couldn't mkdir %S, "
                                "error = %d\n", szPrefix.c_str(), dwError);
                            rc = dwError;
                            break;
                        }
                    }
                }
            }
        }
    } while (FALSE);

    delete[] szPathname;
    return(rc);
}