Esempio n. 1
0
extern "C" HRESULT DependencyAddIgnoreDependencies(
    __in STRINGDICT_HANDLE sdIgnoreDependencies,
    __in_z LPCWSTR wzAddIgnoreDependencies
    )
{
    HRESULT hr = S_OK;
    LPWSTR wzContext = NULL;

    // Parse through the semicolon-delimited tokens and add to the array.
    for (LPCWSTR wzToken = ::wcstok_s(const_cast<LPWSTR>(wzAddIgnoreDependencies), vcszIgnoreDependenciesDelim, &wzContext); wzToken; wzToken = ::wcstok_s(NULL, vcszIgnoreDependenciesDelim, &wzContext))
    {
        hr = DictKeyExists(sdIgnoreDependencies, wzToken);
        if (E_NOTFOUND != hr)
        {
            ExitOnFailure(hr, "Failed to check the dictionary of unique dependencies.");
        }
        else
        {
            hr = DictAddKey(sdIgnoreDependencies, wzToken);
            ExitOnFailure1(hr, "Failed to add \"%ls\" to the string dictionary.", wzToken);
        }
    }

LExit:
    return hr;
}
Esempio n. 2
0
extern "C" HRESULT DependencyPlanPackageBegin(
    __in BOOL fPerMachine,
    __in BURN_PACKAGE* pPackage,
    __in BURN_PLAN* pPlan
    )
{
    HRESULT hr = S_OK;
    STRINGDICT_HANDLE sdIgnoredDependents = NULL;
    DEPENDENCY* rgDependents = NULL;
    UINT cDependents = 0;
    HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
    BURN_DEPENDENCY_ACTION dependencyExecuteAction = BURN_DEPENDENCY_ACTION_NONE;
    BURN_DEPENDENCY_ACTION dependencyRollbackAction = BURN_DEPENDENCY_ACTION_NONE;

    pPackage->dependencyExecute = BURN_DEPENDENCY_ACTION_NONE;
    pPackage->dependencyRollback = BURN_DEPENDENCY_ACTION_NONE;

    // Make sure the package defines at least one provider.
    if (0 == pPackage->cDependencyProviders)
    {
        LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_SKIP_NOPROVIDERS, pPackage->sczId);
        ExitFunction1(hr = S_OK);
    }

    // Make sure the package is in the same scope as the bundle.
    if (fPerMachine != pPackage->fPerMachine)
    {
        LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_SKIP_WRONGSCOPE, pPackage->sczId, LoggingPerMachineToString(fPerMachine), LoggingPerMachineToString(pPackage->fPerMachine));
        ExitFunction1(hr = S_OK);
    }

    // If we're uninstalling the package, check if any dependents are registered.
    if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute)
    {
        // Build up a list of dependents to ignore, including the current bundle.
        hr = GetIgnoredDependents(pPackage, pPlan, &sdIgnoredDependents);
        ExitOnFailure(hr, "Failed to build the list of ignored dependents.");

        // Skip the dependency check if "ALL" was authored for IGNOREDEPENDENCIES.
        hr = DictKeyExists(sdIgnoredDependents, L"ALL");
        if (E_NOTFOUND != hr)
        {
            ExitOnFailure(hr, "Failed to check if \"ALL\" was set in IGNOREDEPENDENCIES.");
        }
        else
        {
            for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
            {
                const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];

                hr = DepCheckDependents(hkHive, pProvider->sczKey, 0, sdIgnoredDependents, &rgDependents, &cDependents);
                if (E_FILENOTFOUND != hr)
                {
                    ExitOnFailure1(hr, "Failed dependents check on package provider: %ls", pProvider->sczKey);
                }
                else
                {
                    hr = S_OK;
                }
            }
        }
    }

    // Calculate the dependency actions before the package itself is planned.
    CalculateDependencyActionStates(pPackage, pPlan->action, &dependencyExecuteAction, &dependencyRollbackAction);

    // If dependents were found, change the action to not uninstall the package.
    if (0 < cDependents)
    {
        LogId(REPORT_STANDARD, MSG_DEPENDENCY_PACKAGE_HASDEPENDENTS, pPackage->sczId, cDependents);

        for (DWORD i = 0; i < cDependents; ++i)
        {
            const DEPENDENCY* pDependency = &rgDependents[i];
            LogId(REPORT_VERBOSE, MSG_DEPENDENCY_PACKAGE_DEPENDENT, pDependency->sczKey, LoggingStringOrUnknownIfNull(pDependency->sczName));
        }

        pPackage->fDependencyManagerWasHere = TRUE;
        pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
        pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
    }
    else // use the calculated dependency actions as the provider actions if there are any non-imported providers
    {    // that will need to be registered.
        BOOL fAllImportedProviders = TRUE; // assume all providers were imported.
        for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
        {
            const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];
            if (!pProvider->fImported)
            {
                fAllImportedProviders = FALSE;
                break;
            }
        }

        if (!fAllImportedProviders)
        {
            pPackage->providerExecute = dependencyExecuteAction;
            pPackage->providerRollback = dependencyRollbackAction;
        }
    }

    // If the package will be removed, add its providers to the growing list in the plan.
    if (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pPackage->execute)
    {
        for (DWORD i = 0; i < pPackage->cDependencyProviders; ++i)
        {
            const BURN_DEPENDENCY_PROVIDER* pProvider = &pPackage->rgDependencyProviders[i];

            hr = DepDependencyArrayAlloc(&pPlan->rgPlannedProviders, &pPlan->cPlannedProviders, pProvider->sczKey, NULL);
            ExitOnFailure1(hr, "Failed to add the package provider key \"%ls\" to the planned list.", pProvider->sczKey);
        }
    }

    pPackage->dependencyExecute = dependencyExecuteAction;
    pPackage->dependencyRollback = dependencyRollbackAction;

LExit:
    ReleaseDependencyArray(rgDependents, cDependents);
    ReleaseDict(sdIgnoredDependents);

    return hr;
}
Esempio n. 3
0
HRESULT ProductSyncValues(
    __in CFGDB_STRUCT *pcdb1,
    __in CFGDB_STRUCT *pcdb2,
    __in BOOL fAllowLocalToReceiveData,
    __in STRINGDICT_HANDLE shDictValuesSeen,
    __out CONFLICT_PRODUCT **ppcpProduct
    )
{
    HRESULT hr = S_OK;
    LPWSTR sczName = NULL;
    DWORD dwInserting = 0;
    SCE_QUERY_HANDLE sqhHandle = NULL;
    SCE_QUERY_RESULTS_HANDLE sqrhResults = NULL;
    SCE_ROW_HANDLE sceRow = NULL;
    DWORD dwFoundIndex = 0;
    DWORD dwSubsumeIndex = 0;
    BOOL fSame = FALSE;
    BOOL fFirstIsLocal = (NULL == pcdb1->pcdbLocal);

    CFG_ENUMERATION * valueHistory1 = NULL;
    DWORD dwCfgCount1 = 0;
    CFG_ENUMERATION * valueHistory2 = NULL;
    DWORD dwCfgCount2 = 0;

    hr = SceBeginQuery(pcdb1->psceDb, VALUE_INDEX_TABLE, 0, &sqhHandle);
    ExitOnFailure(hr, "Failed to begin query into value table");

    hr = SceSetQueryColumnDword(sqhHandle, pcdb1->dwAppID);
    ExitOnFailure(hr, "Failed to set query column dword to: %u", pcdb1->dwAppID);

    hr = SceRunQueryRange(&sqhHandle, &sqrhResults);
    if (E_NOTFOUND == hr)
    {
        ExitFunction1(hr = S_OK);
    }
    ExitOnFailure(hr, "Failed to enumerate values for product %u", pcdb1->dwAppID);

    hr = SceGetNextResultRow(sqrhResults, &sceRow);
    while (E_NOTFOUND != hr)
    {
        ExitOnFailure(hr, "Failed to get next row from query into value table");

        CfgReleaseEnumeration(valueHistory1);
        valueHistory1 = NULL;
        CfgReleaseEnumeration(valueHistory2);
        valueHistory2 = NULL;

        hr = SceGetColumnString(sceRow, VALUE_COMMON_NAME, &sczName);
        ExitOnFailure(hr, "Failed to get value name");

        if (NULL != shDictValuesSeen)
        {
            hr = DictKeyExists(shDictValuesSeen, sczName);
            if (E_NOTFOUND == hr)
            {
                hr = DictAddKey(shDictValuesSeen, sczName);
                ExitOnFailure(hr, "Failed to add to dictionary value: %ls", sczName);
            }
            else
            {
                ExitOnFailure(hr, "Failed to check if key exists: %ls", sczName);

                // This value was already synced; skip it!
                goto Skip;
            }
        }

        // Exclude legacy detect cache values, they should never be synced off the machine
        // TODO: when we support per-machine settings, migrate this to use that feature
        if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczName, lstrlenW(wzLegacyDetectCacheValuePrefix), wzLegacyDetectCacheValuePrefix, lstrlenW(wzLegacyDetectCacheValuePrefix)))
        {
            goto Skip;
        }

        // First check if the values are identical. Even if they were set by different folks at different times,
        // same value means nothing to sync.
        hr = ValueMatch(sczName, pcdb1, pcdb2, sceRow, &fSame);
        ExitOnFailure(hr, "Failed to check if values are identical");

        if (fSame)
        {
            goto Skip;
        }

        // Get history of the value in db2
        hr = EnumPastValues(pcdb2, sczName, &valueHistory2, &dwCfgCount2);
        if (E_NOTFOUND == hr)
        {
            hr = S_OK;
        }
        ExitOnFailure(hr, "Failed to enumerate previous values in db2");

        // Get history of the value in db1
        hr = EnumPastValues(pcdb1, sczName, &valueHistory1, &dwCfgCount1);
        ExitOnFailure(hr, "Found value in db1, but failed to enumerate previous values in db1 while searching for conflicts");

        if (0 == dwCfgCount2)
        {
            if (fFirstIsLocal || fAllowLocalToReceiveData)
            {
                hr = ValueTransferFromHistory(pcdb2, valueHistory1, 0, pcdb1);
                ExitOnFailure(hr, "Failed to transfer history (due to value not present) from db 2 to db 1 for value %ls", sczName);
            }

            goto Skip;
        }

        // Don't write anything to db2 if it's local and we're told not to
        if (fFirstIsLocal || fAllowLocalToReceiveData)
        {
            // We first check the latest value. However, if the previous value is identical (same type & value, just different source), check for subsumation of that too.
            // This reduces unnecessary conflicts in rare corner case scenarios.
            dwSubsumeIndex = dwCfgCount2;
            do
            {
                --dwSubsumeIndex;

                // Check if the last history entry for database 2 exists in the database 1 - if it does, database 2's changes are subsumed
                hr = EnumFindValueInHistory(valueHistory1, dwCfgCount1, valueHistory2->valueHistory.rgcValues + dwSubsumeIndex, &dwFoundIndex);
                if (S_OK == hr)
                {
                    // Database 2 is subsumed - pipe over all the newest history entries
                    hr = ValueTransferFromHistory(pcdb2, valueHistory1, dwFoundIndex + 1, pcdb1);
                    ExitOnFailure(hr, "Failed to transfer history (due to history subsumed) from db 1 to db 2 for value %ls", sczName);

                    goto Skip;
                }
                else if (E_NOTFOUND == hr)
                {
                    hr = S_OK;
                }
                else
                {
                    ExitOnFailure(hr, "Failed to check if db2's value history is subsumed by db1's value history");
                }

                if (0 < dwSubsumeIndex)
                {
                    hr = ValueCompare(valueHistory2->valueHistory.rgcValues + dwSubsumeIndex, valueHistory2->valueHistory.rgcValues + dwSubsumeIndex - 1, FALSE, &fSame);
                    ExitOnFailure(hr, "Failed to check if value and previous value in database 2 are equivalent");
                }
            }
            while (0 < dwSubsumeIndex && fSame);
        }

        // Don't write anything to db1 if it's local and we're told not to
        if (!fFirstIsLocal || fAllowLocalToReceiveData)
        {
            // We first check the latest value. However, if the previous value is identical (same type & value, just different source), check for subsumation of that too.
            // This reduces unnecessary conflicts in rare corner case scenarios.
            dwSubsumeIndex = dwCfgCount1;
            do
            {
                --dwSubsumeIndex;

                hr = EnumFindValueInHistory(valueHistory2, dwCfgCount2, valueHistory1->valueHistory.rgcValues + dwSubsumeIndex, &dwFoundIndex);
                if (S_OK == hr)
                {
                    // Database 1 is subsumed - pipe over all the newest history entries
                    hr = ValueTransferFromHistory(pcdb1, valueHistory2, dwFoundIndex + 1, pcdb2);
                    ExitOnFailure(hr, "Failed to transfer history (due to history subsumed) from db 2 to db 1 for value %ls", sczName);

                    goto Skip;
                }
                else if (E_NOTFOUND == hr)
                {
                    hr = S_OK;
                }
                else
                {
                    ExitOnFailure(hr, "Failed to check if db1's value history is subsumed by db2's value history");
                }

                if (0 < dwSubsumeIndex)
                {
                    hr = ValueCompare(valueHistory1->valueHistory.rgcValues + dwSubsumeIndex, valueHistory1->valueHistory.rgcValues + dwSubsumeIndex - 1, FALSE, &fSame);
                    ExitOnFailure(hr, "Failed to check if value and previous value in database 1 are equivalent");
                }
            }
            while (0 < dwSubsumeIndex && fSame);
        }

        // OK, we have a conflict. Report it.
        if (NULL == *ppcpProduct)
        {
            *ppcpProduct = static_cast<CONFLICT_PRODUCT *>(MemAlloc(sizeof(CONFLICT_PRODUCT), TRUE));
            ExitOnNull(*ppcpProduct, hr, E_OUTOFMEMORY, "Failed to allocate product conflict struct");

            (*ppcpProduct)->cValues = 1;
        }
        else
        {
            ++(*ppcpProduct)->cValues;
        }

        hr = MemEnsureArraySize(reinterpret_cast<void **>(&(*ppcpProduct)->rgcesValueEnumLocal), (*ppcpProduct)->cValues, sizeof(CFG_ENUMERATION *), 10);
        ExitOnFailure(hr, "Failed to ensure product local value conflict array size");
        hr = MemEnsureArraySize(reinterpret_cast<void **>(&(*ppcpProduct)->rgdwValueCountLocal), (*ppcpProduct)->cValues, sizeof(DWORD), 10);
        ExitOnFailure(hr, "Failed to ensure product local value conflict count array size");
        hr = MemEnsureArraySize(reinterpret_cast<void **>(&(*ppcpProduct)->rgcesValueEnumRemote), (*ppcpProduct)->cValues, sizeof(CFG_ENUMERATION *), 10);
        ExitOnFailure(hr, "Failed to ensure product remote value conflict array size");
        hr = MemEnsureArraySize(reinterpret_cast<void **>(&(*ppcpProduct)->rgdwValueCountRemote), (*ppcpProduct)->cValues, sizeof(DWORD), 10);
        ExitOnFailure(hr, "Failed to ensure product remote value conflict count array size");
        hr = MemEnsureArraySize(reinterpret_cast<void **>(&(*ppcpProduct)->rgrcValueChoices), (*ppcpProduct)->cValues, sizeof(RESOLUTION_CHOICE), 10);
        ExitOnFailure(hr, "Failed to ensure product value resolution choice array size");

        dwInserting = (*ppcpProduct)->cValues - 1;

        // Neither is subsumed by the other, so we have conflicts - report them
        if (fFirstIsLocal)
        {
            hr = ConflictGetList(reinterpret_cast<const CFG_ENUMERATION *>(valueHistory1), dwCfgCount1,
                reinterpret_cast<const CFG_ENUMERATION *>(valueHistory2), dwCfgCount2,
                &((*ppcpProduct)->rgcesValueEnumLocal[dwInserting]), &(*ppcpProduct)->rgdwValueCountLocal[dwInserting],
                &((*ppcpProduct)->rgcesValueEnumRemote[dwInserting]), &(*ppcpProduct)->rgdwValueCountRemote[dwInserting]);
        }
        else
        {
            hr = ConflictGetList(reinterpret_cast<const CFG_ENUMERATION *>(valueHistory2), dwCfgCount2,
                reinterpret_cast<const CFG_ENUMERATION *>(valueHistory1), dwCfgCount1,
                &((*ppcpProduct)->rgcesValueEnumLocal[dwInserting]), &(*ppcpProduct)->rgdwValueCountLocal[dwInserting],
                &((*ppcpProduct)->rgcesValueEnumRemote[dwInserting]), &(*ppcpProduct)->rgdwValueCountRemote[dwInserting]);
        }
        ExitOnFailure(hr, "Failed to get conflict list");

    Skip:
        ReleaseNullSceRow(sceRow);
        hr = SceGetNextResultRow(sqrhResults, &sceRow);
    }

    hr = S_OK;

LExit:
    ReleaseSceQuery(sqhHandle);
    ReleaseSceQueryResults(sqrhResults);
    ReleaseSceRow(sceRow);
    CfgReleaseEnumeration(valueHistory1);
    CfgReleaseEnumeration(valueHistory2);
    ReleaseStr(sczName);

    return hr;
}
Esempio n. 4
0
static HRESULT ProductDbToMachine(
    __in CFGDB_STRUCT *pcdb,
    __in LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession
   )
{
    HRESULT hr = S_OK;
    SCE_QUERY_HANDLE sqhHandle = NULL;
    SCE_QUERY_RESULTS_HANDLE sqrhResults = NULL;
    SCE_ROW_HANDLE sceRow = NULL;
    BOOL fIgnore = FALSE;
    LPWSTR sczName = NULL;
    BOOL fHandled = FALSE;
    CONFIG_VALUE cvValue = { };

    // First handle all special values
    hr = RegSpecialsProductWrite(pcdb, pSyncProductSession);
    ExitOnFailure(hr, "Failed to write specially handled values back to registry");

    // Now handle all the regular values, minus exceptions from when we processed special values
    hr = SceBeginQuery(pcdb->psceDb, VALUE_INDEX_TABLE, 0, &sqhHandle);
    ExitOnFailure(hr, "Failed to begin query into VALUE_INDEX_TABLE table");

    hr = SceSetQueryColumnDword(sqhHandle, pcdb->dwAppID);
    ExitOnFailure(hr, "Failed to set AppID for query");

    hr = SceRunQueryRange(&sqhHandle, &sqrhResults);
    if (E_NOTFOUND == hr)
    {
        ExitFunction1(hr = S_OK);
    }
    ExitOnFailure(hr, "Failed to run query into VALUE_INDEX_TABLE table for AppID: %u", pcdb->dwAppID);

    hr = SceGetNextResultRow(sqrhResults, &sceRow);
    while (E_NOTFOUND != hr)
    {
        ExitOnFailure(hr, "Failed to get next results row from VALUE_INDEX_TABLE table");

        hr = SceGetColumnString(sceRow, VALUE_COMMON_NAME, &sczName);
        ExitOnFailure(hr, "Failed to get name from row while querying VALUE_INDEX_TABLE table");

        hr = FilterCheckValue(&pSyncProductSession->product, sczName, &fIgnore, NULL);
        ExitOnFailure(hr, "Failed to check if cfg setting should be ignored: %ls", sczName);

        if (!fIgnore)
        {
            fHandled = FALSE;

            hr = DictKeyExists(pSyncProductSession->product.shRegistrySpeciallyHandled, sczName);
            if (S_OK == hr)
            {
                // On a registry value exception, simply skip handling this value
                fHandled = TRUE;
            }
            else if (E_NOTFOUND == hr)
            {
                hr = S_OK;
            }
            ExitOnFailure(hr, "Failed to check if registry value exists in reg value exceptions dictionary");

            ReleaseNullCfgValue(cvValue);
            hr = ValueRead(pcdb, sceRow, &cvValue);
            ExitOnFailure(hr, "Failed to read value %ls", sczName);

            if (!fHandled)
            {
                hr = RegDefaultWriteValue(&pSyncProductSession->product, sczName, &cvValue, &fHandled);
                ExitOnFailure(hr, "Failed to write value through registry default handler: %ls", sczName);
            }

            if (!fHandled)
            {
                hr = IniFileSetValue(pSyncProductSession, sczName, &cvValue, &fHandled);
                ExitOnFailure(hr, "Failed to write registry value through ini handler: %ls", sczName);
            }

            if (!fHandled)
            {
                hr = DirDefaultWriteFile(&pSyncProductSession->product, sczName, &cvValue, &fHandled);
                ExitOnFailure(hr, "Failed to write file through default handler: %ls", sczName);
            }
        }

        ReleaseNullSceRow(sceRow);
        hr = SceGetNextResultRow(sqrhResults, &sceRow);
    }
    hr = S_OK;
    ReleaseNullSceQueryResults(sqrhResults);

    for (DWORD i = 0; i < pSyncProductSession->cIniFiles; ++i)
    {
        hr = IniFileWrite(pSyncProductSession->rgIniFiles + i);
        ExitOnFailure(hr, "Failed to write INI file");
    }

    if (!pSyncProductSession->fRegistered)
    {
        hr = DeleteEmptyRegistryKeys(pSyncProductSession);
        ExitOnFailure(hr, "Failed to delete empty registry keys");

        hr = DeleteEmptyDirectories(pSyncProductSession);
        ExitOnFailure(hr, "Failed to delete empty directories");
    }

LExit:
    ReleaseStr(sczName);
    ReleaseSceQuery(sqhHandle);
    ReleaseSceQueryResults(sqrhResults);
    ReleaseSceRow(sceRow);
    ReleaseCfgValue(cvValue);

    return hr;
}
Esempio n. 5
0
HRESULT LegacySyncPullDeletedValues(
    __in CFGDB_STRUCT *pcdb,
    __in LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession
    )
{
    HRESULT hr = S_OK;
    SCE_QUERY_HANDLE sqhHandle = NULL;
    SCE_QUERY_RESULTS_HANDLE sqrhResults = NULL;
    SCE_ROW_HANDLE sceRow = NULL;
    CONFIG_VALUE cvExistingValue = { };
    CONFIG_VALUE cvNewValue = { };
    LPWSTR sczName = NULL;

    if (pcdb->dwAppID == pcdb->dwCfgAppID)
    {
        hr = E_INVALIDARG;
        ExitOnFailure(hr, "Error - tried to pull deleted values for dwCfgAppID!");
    }

    hr = SceBeginQuery(pcdb->psceDb, VALUE_INDEX_TABLE, 0, &sqhHandle);
    ExitOnFailure(hr, "Failed to begin query into VALUE_INDEX_TABLE table");

    hr = SceSetQueryColumnDword(sqhHandle, pcdb->dwAppID);
    ExitOnFailure(hr, "Failed to set AppID for query");

    hr = SceRunQueryRange(&sqhHandle, &sqrhResults);
    if (E_NOTFOUND == hr)
    {
        ExitFunction1(hr = S_OK);
    }
    ExitOnFailure(hr, "Failed to run query into VALUE_INDEX_TABLE table for AppID: %u", pcdb->dwAppID);

    hr = SceGetNextResultRow(sqrhResults, &sceRow);
    while (E_NOTFOUND != hr)
    {
        ExitOnFailure(hr, "Failed to get next result row from VALUE_INDEX_TABLE table");

        hr = SceGetColumnString(sceRow, VALUE_COMMON_NAME, &sczName);
        ExitOnFailure(hr, "Failed to get name from row while querying VALUE_INDEX_TABLE table");

        hr = DictKeyExists(pSyncProductSession->shDictValuesSeen, sczName);
        if (E_NOTFOUND == hr)
        {
            hr = S_OK;

            ReleaseNullCfgValue(cvExistingValue);
            hr = ValueRead(pcdb, sceRow, &cvExistingValue);
            ExitOnFailure(hr, "Failed to read value into memory while querying VALUE_INDEX_TABLE table");

            if (VALUE_DELETED != cvExistingValue.cvType)
            {
                hr = ValueSetDelete(NULL, pcdb->sczGuid, &cvNewValue);
                ExitOnFailure(hr, "Failed to set deleted value in memory");

                hr = ValueWrite(pcdb, pcdb->dwAppID, sczName, &cvNewValue, TRUE, NULL);
                ExitOnFailure(hr, "Failed to write deleted value to db: %ls", sczName);
            }
        }
        ExitOnFailure(hr, "Failed to check if registry value exists in reg values seen database");

        ReleaseNullSceRow(sceRow);
        hr = SceGetNextResultRow(sqrhResults, &sceRow);
    }

    if (E_NOTFOUND == hr)
    {
        hr = S_OK;
    }

LExit:
    ReleaseSceRow(sceRow);
    ReleaseSceQuery(sqhHandle);
    ReleaseSceQueryResults(sqrhResults);
    ReleaseStr(sczName);
    ReleaseCfgValue(cvExistingValue);
    ReleaseCfgValue(cvNewValue);

    return hr;
}
Esempio n. 6
0
static HRESULT ReadFileWriteLegacyDb(
    __in CFGDB_STRUCT *pcdb,
    __in LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession,
    __in LEGACY_FILE *pFile,
    __in_z LPCWSTR wzFilePath,
    __in BOOL fVirtualStoreCheck
    )
{
    HRESULT hr = S_OK;
    LPCWSTR wzSubPath = wzFilePath;
    LPWSTR sczVirtualStorePath = NULL;
    BOOL fContinueProcessing = FALSE;
    BOOL fWritePermission = TRUE;

    if (lstrlenW(pFile->sczExpandedPath) > lstrlenW(wzFilePath))
    {
        hr = E_INVALIDARG;
        ExitOnFailure(hr, "Legacy file path %ls was longer than the file path sent to ReadFileWriteLegacyDb, %ls", pFile->sczExpandedPath, wzFilePath);
    }

    // Make the key reflect only the sub-portion under the original base key path
    wzSubPath += lstrlenW(pFile->sczExpandedPath);
    while (L'\\' == wzSubPath[0])
    {
        ++wzSubPath;
    }

    if (fVirtualStoreCheck)
    {
        hr = UtilTestWriteAccess(pcdb->hToken, wzFilePath);
        if (E_ACCESSDENIED == hr)
        {
            fWritePermission = FALSE;
            hr = S_OK;
        }
        else if (E_PATHNOTFOUND == hr)
        {
            ExitFunction();
        }
        ExitOnFailure(hr, "Failed to check for write access to directory of file: %ls", wzFilePath);

        if (!fWritePermission)
        {
            hr = UtilConvertToVirtualStorePath(wzFilePath, &sczVirtualStorePath);
            ExitOnFailure(hr, "Failed to convert file path to virtualstore path: %ls", wzFilePath);

            // Pass the value up to check for special handling first
            hr = DirSpecialFileRead(pcdb, pSyncProductSession, pFile, sczVirtualStorePath, wzSubPath, &fContinueProcessing);
            ExitOnFailure(hr, "Failed to appropriately check for and handle special directory file under virtualstore, file path: %ls", wzFilePath);

            // If special handling tells us to avoid normal processing for this file, skip it
            if (!fContinueProcessing)
            {
                ExitFunction1(hr = S_OK);
            }

            hr = DirDefaultReadFile(pcdb, pSyncProductSession, pFile->sczName, sczVirtualStorePath, NULL);
            ExitOnFailure(hr, "Failed to read virtualstore file with default handler, path: %ls", sczVirtualStorePath);

            // Check if DirDefaultReadFile found the file or not
            hr = DictKeyExists(pSyncProductSession->shDictValuesSeen, pFile->sczName);
            if (E_NOTFOUND == hr)
            {
                hr = S_OK;
            }
            else
            {
                ExitOnFailure(hr, "Failed to check if file was seen under virtual store path: %ls", pFile->sczName);

                // It saw the file, so let's not proceed to check the non-virtualstore path
                ExitFunction1(hr = S_OK);
            }
        }
    }

    // Pass the value up to check for special handling first
    hr = DirSpecialFileRead(pcdb, pSyncProductSession, pFile, wzFilePath, wzSubPath, &fContinueProcessing);
    ExitOnFailure(hr, "Failed to appropriately check for and handle special directory file, file path: %ls", wzFilePath);

    // If special handling tells us to avoid normal processing for this file, skip it
    if (!fContinueProcessing)
    {
        ExitFunction1(hr = S_OK);
    }

    hr = DirDefaultReadFile(pcdb, pSyncProductSession, pFile->sczName, wzFilePath, wzSubPath);
    ExitOnFailure(hr, "Failed to read file with default handler, path: %ls", wzFilePath);

LExit:
    ReleaseStr(sczVirtualStorePath);

    return hr;
}