Ejemplo n.º 1
0
HRESULT LegacySyncSetProduct(
    __in CFGDB_STRUCT *pcdb,
    __inout LEGACY_SYNC_SESSION *pSyncSession,
    __in LPCWSTR wzName
    )
{
    HRESULT hr = S_OK;
    LEGACY_SYNC_PRODUCT_SESSION *pSyncProductSession = &pSyncSession->syncProductSession;
    LEGACY_FILE *pFile = NULL;
    LEGACY_FILE_SPECIAL *pFileSpecial = NULL;
    LEGACY_INI_FILE *pIniFile = NULL;
    CONFIG_VALUE cvManifestContents = { };
    CONFIG_VALUE cvManifestConvertedToBlob = { };
    SCE_ROW_HANDLE sceManifestValueRow = NULL;
    LPWSTR sczManifestValueName = NULL;
    BOOL fWasRegistered = FALSE;
    BYTE *pbManifestBuffer = NULL;
    SIZE_T iManifestBuffer = 0;
    LPWSTR sczBlobManifestAsString = NULL;

    if (pSyncSession->fInSceTransaction)
    {
        SceRollbackTransaction(pcdb->psceDb);
        pSyncSession->fInSceTransaction = FALSE;
    }

    hr = ProductGetLegacyManifestValueName(wzName, &sczManifestValueName);
    ExitOnFailure(hr, "Failed to get legacy manifest value name");

    ManifestFreeProductStruct(&pSyncProductSession->product);
    ZeroMemory(&pSyncProductSession->product, sizeof(pSyncProductSession->product));

    for (DWORD i = 0; i < pSyncProductSession->cIniFiles; ++i)
    {
        IniFree(pSyncProductSession->rgIniFiles + i);
    }
    ReleaseNullMem(pSyncProductSession->rgIniFiles);
    pSyncProductSession->cIniFiles = 0;

    ReleaseNullDict(pSyncProductSession->shDictValuesSeen);
    ReleaseNullDict(pSyncProductSession->shIniFilesByNamespace);

    hr = DictCreateStringList(&pSyncProductSession->shDictValuesSeen, 0, DICT_FLAG_CASEINSENSITIVE);
    ExitOnFailure(hr, "Failed to create dictionary of values seen");

    hr = DictCreateWithEmbeddedKey(&pSyncProductSession->shIniFilesByNamespace, 0, reinterpret_cast<void **>(&pSyncProductSession->rgIniFiles), offsetof(LEGACY_INI_FILE, sczNamespace), DICT_FLAG_CASEINSENSITIVE);
    ExitOnFailure(hr, "Failed to create ini file dictionary");

    hr = DictCreateWithEmbeddedKey(&pSyncProductSession->product.detect.shCachedDetectionPropertyValues, offsetof(LEGACY_CACHED_DETECTION_RESULT, sczPropertyName), reinterpret_cast<void **>(&pSyncProductSession->product.detect.rgCachedDetectionProperties), 0, DICT_FLAG_CASEINSENSITIVE);
    ExitOnFailure(hr, "Failed to create cached detection property values dictionary");

    hr = ValueFindRow(pcdb, pcdb->dwCfgAppID, sczManifestValueName, &sceManifestValueRow);
    ExitOnFailure(hr, "Failed to find config value for legacy manifest (AppID: %u, Config Value named: %ls)", pcdb->dwCfgAppID, sczManifestValueName);

    hr = ValueRead(pcdb, sceManifestValueRow, &cvManifestContents);
    ExitOnFailure(hr, "Failed to read manifest contents");

    // TODO: someday remove this temporary conversion code when we feel confident nobody has old databases with old manifests laying around
    if (VALUE_STRING == cvManifestContents.cvType)
    {
        LogStringLine(REPORT_STANDARD, "Converting manifest value named %ls from string to blob value", sczManifestValueName);

        hr = ValueSetBlob(reinterpret_cast<BYTE *>(cvManifestContents.string.sczValue), lstrlenW(cvManifestContents.string.sczValue) * sizeof(WCHAR), FALSE, NULL, pcdb->sczGuid, &cvManifestConvertedToBlob);
        ExitOnFailure(hr, "Failed to set converted manifest value in memory");

        hr = ValueWrite(pcdb, pcdb->dwCfgAppID, sczManifestValueName, &cvManifestConvertedToBlob, TRUE, NULL);
        ExitOnFailure(hr, "Failed to set converted manifest blob: %ls", sczManifestValueName);

        ReleaseNullSceRow(sceManifestValueRow);
        ReleaseNullCfgValue(cvManifestContents);
        hr = ValueFindRow(pcdb, pcdb->dwCfgAppID, sczManifestValueName, &sceManifestValueRow);
        ExitOnFailure(hr, "Failed to find config value for legacy manifest after conversion (AppID: %u, Config Value named: %ls)", pcdb->dwCfgAppID, sczManifestValueName);

        hr = ValueRead(pcdb, sceManifestValueRow, &cvManifestContents);
        ExitOnFailure(hr, "Failed to read converted manifest contents");
    }

    if (VALUE_BLOB != cvManifestContents.cvType)
    {
        hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
        ExitOnFailure(hr, "Stored manifest value was not of type blob");
    }

    if (CFG_BLOB_DB_STREAM != cvManifestContents.blob.cbType)
    {
        hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
        ExitOnFailure(hr, "Stored manifest blob was not a database stream");
    }

    hr = StreamRead(pcdb, cvManifestContents.blob.dbstream.dwContentID, NULL, &pbManifestBuffer, &iManifestBuffer);
    ExitOnFailure(hr, "Failed to get binary content of blob named: %ls, with content ID: %u", sczManifestValueName, pcdb->dwCfgAppID);

    hr = StrAllocString(&sczBlobManifestAsString, reinterpret_cast<LPWSTR>(pbManifestBuffer), iManifestBuffer / sizeof(WCHAR));
    ExitOnFailure(hr, "Failed to add null terminator to manifest blob");

    hr = ParseManifest(sczBlobManifestAsString, &pSyncProductSession->product);
    ExitOnFailure(hr, "Failed to parse manifest");

    hr = ProductSet(pcdb, wzName, wzLegacyVersion, wzLegacyPublicKey, FALSE, NULL);
    ExitOnFailure(hr, "Failed to set product");

    hr = ProductIsRegistered(pcdb, pcdb->sczProductName, wzLegacyVersion, wzLegacyPublicKey, &fWasRegistered);
    ExitOnFailure(hr, "Failed to check if product is registered");

    hr = DetectProduct(pcdb, !pSyncSession->fDetect, &pSyncSession->arpProducts, &pSyncSession->exeProducts, pSyncProductSession);
    ExitOnFailure(hr, "Failed to detect product with AppID: %u", pcdb->dwAppID);

    // Don't bother writing new registration state data to the database if detect is disabled
    if (pSyncSession->fDetect)
    {
        hr = UpdateProductRegistrationState(pcdb, pSyncProductSession, pcdb->sczProductName, wzLegacyVersion, wzLegacyPublicKey);
        ExitOnFailure(hr, "Failed to update product registration state");
    }

    hr = ProductIsRegistered(pcdb, pcdb->sczProductName, wzLegacyVersion, wzLegacyPublicKey, &pSyncProductSession->fRegistered);
    ExitOnFailure(hr, "Failed to check if product is registered");

    pSyncProductSession->fNewlyRegistered = (!fWasRegistered && pSyncProductSession->fRegistered);

    for (DWORD i = 0; i < pSyncProductSession->product.cFiles; ++i)
    {
        pFile = pSyncProductSession->product.rgFiles + i;

        hr = UtilExpandLegacyPath(pFile->sczLocation, &pSyncProductSession->product.detect, &pFile->sczExpandedPath);
        if (E_NOTFOUND == hr)
        {
            hr = S_OK;
        }

        if (NULL != pFile->sczExpandedPath)
        {
            for (DWORD j = 0; j < pFile->cFileSpecials; ++j)
            {
                pFileSpecial = pFile->rgFileSpecials + j;

                if (0 < pFileSpecial->cIniInfo)
                {
                    hr = MemEnsureArraySize(reinterpret_cast<void **>(&pSyncProductSession->rgIniFiles), pSyncProductSession->cIniFiles + 1, sizeof(LEGACY_INI_FILE), 5);
                    ExitOnFailure(hr, "Failed to grow active IniFiles array");

                    pIniFile = pSyncProductSession->rgIniFiles + pSyncProductSession->cIniFiles;

                    hr = IniFileOpen(pFile, pFileSpecial, pFileSpecial->rgIniInfo, pIniFile);
                    ExitOnFailure(hr, "Failed to parse INI file");

                    hr = DictAddValue(pSyncProductSession->shIniFilesByNamespace, pIniFile);
                    ExitOnFailure(hr, "Failed to add INI file to dict for namespace: %ls", pIniFile->sczNamespace);

                    ++pSyncProductSession->cIniFiles;
                }
            }
        }
    }

    // IMPORTANT: Put all legacy database actions into a separate transaction
    // for each product. In the case of any kind of failure, it's OK to leave
    // changes written to local machine registry / file system, but not the
    // legacy database - they'll just appear as local machine changes on next
    // sync, and everything will be happy. The other way around is NOT happy,
    // because every sync would create another history entry, ad infinitum!
    hr = SceBeginTransaction(pcdb->psceDb);
    ExitOnFailure(hr, "Failed to begin transaction");
    pSyncSession->fInSceTransaction = TRUE;

LExit:
    ReleaseSceRow(sceManifestValueRow);
    ReleaseCfgValue(cvManifestContents);
    ReleaseCfgValue(cvManifestConvertedToBlob);
    ReleaseStr(sczManifestValueName);
    ReleaseMem(pbManifestBuffer);
    ReleaseStr(sczBlobManifestAsString);

    return hr;
}
Ejemplo n.º 2
0
static int Retrieve( addons_finder_t *p_finder, addon_entry_t *p_entry )
{
    if ( !p_entry->psz_archive_uri )
        return VLC_EGENERIC;

    /* get archive and parse manifest */
    stream_t *p_stream;

    if ( p_entry->psz_archive_uri[0] == '/' )
    {
        /* Relative path */
        char *psz_uri;
        if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"%s", p_entry->psz_archive_uri ) )
            return VLC_ENOMEM;
        p_stream = stream_UrlNew( p_finder, psz_uri );
        free( psz_uri );
    }
    else
    {
        p_stream = stream_UrlNew( p_finder, p_entry->psz_archive_uri );
    }

    msg_Dbg( p_finder, "downloading archive %s", p_entry->psz_archive_uri );
    if ( !p_stream ) return VLC_EGENERIC;

    /* In case of pf_ reuse */
    if ( p_finder->p_sys->psz_tempfile )
    {
        vlc_unlink( p_finder->p_sys->psz_tempfile );
        FREENULL( p_finder->p_sys->psz_tempfile );
    }

    p_finder->p_sys->psz_tempfile = tempnam( NULL, "vlp" );
    if ( !p_finder->p_sys->psz_tempfile )
    {
        msg_Err( p_finder, "Can't create temp storage file" );
        stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    FILE *p_destfile = vlc_fopen( p_finder->p_sys->psz_tempfile, "w" );
    if( !p_destfile )
    {
        msg_Err( p_finder, "Failed to open addon temp storage file" );
        FREENULL(p_finder->p_sys->psz_tempfile);
        stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    char buffer[1<<10];
    int i_read = 0;
    while ( ( i_read = stream_Read( p_stream, &buffer, 1<<10 ) ) )
    {
        if ( fwrite( &buffer, i_read, 1, p_destfile ) < 1 )
        {
            msg_Err( p_finder, "Failed to write to Addon file" );
            fclose( p_destfile );
            stream_Delete( p_stream );
            return VLC_EGENERIC;
        }
    }
    fclose( p_destfile );
    stream_Delete( p_stream );

    msg_Dbg( p_finder, "Reading manifest from %s", p_finder->p_sys->psz_tempfile );

    char *psz_manifest;
    if ( asprintf( &psz_manifest, "unzip://%s!/manifest.xml",
                   p_finder->p_sys->psz_tempfile ) < 1 )
        return VLC_ENOMEM;

    p_stream = stream_UrlNew( p_finder, psz_manifest );
    free( psz_manifest );

    int i_ret = ( ParseManifest( p_finder, p_entry,
                                 p_finder->p_sys->psz_tempfile, p_stream ) > 0 )
                    ? VLC_SUCCESS : VLC_EGENERIC;

    stream_Delete( p_stream );

    return i_ret;
}
Ejemplo n.º 3
0
static int Retrieve( addons_finder_t *p_finder, addon_entry_t *p_entry )
{
    vlc_mutex_lock( &p_entry->lock );
    if ( !p_entry->psz_archive_uri )
    {
        vlc_mutex_unlock( &p_entry->lock );
        return VLC_EGENERIC;
    }
    char *psz_archive_uri = strdup( p_entry->psz_archive_uri );
    vlc_mutex_unlock( &p_entry->lock );
    if ( !psz_archive_uri )
        return VLC_ENOMEM;

    /* get archive and parse manifest */
    stream_t *p_stream;

    if ( psz_archive_uri[0] == '/' )
    {
        /* Relative path */
        char *psz_uri;
        if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"%s", psz_archive_uri ) )
        {
            free( psz_archive_uri );
            return VLC_ENOMEM;
        }
        p_stream = vlc_stream_NewURL_ND( p_finder, psz_uri );
        free( psz_uri );
    }
    else
    {
        p_stream = vlc_stream_NewURL_ND( p_finder, psz_archive_uri );
    }

    msg_Dbg( p_finder, "downloading archive %s", psz_archive_uri );
    free ( psz_archive_uri );
    if ( !p_stream ) return VLC_EGENERIC;

    /* In case of pf_ reuse */
    if ( p_finder->p_sys->psz_tempfile )
    {
        vlc_unlink( p_finder->p_sys->psz_tempfile );
        FREENULL( p_finder->p_sys->psz_tempfile );
    }

    p_finder->p_sys->psz_tempfile = tempnam( NULL, "vlp" );
    if ( !p_finder->p_sys->psz_tempfile )
    {
        msg_Err( p_finder, "Can't create temp storage file" );
        vlc_stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    int fd = vlc_open( p_finder->p_sys->psz_tempfile,
                       O_WRONLY | O_CREAT | O_EXCL, 0600 );
    if( fd == -1 )
    {
        msg_Err( p_finder, "Failed to open addon temp storage file" );
        FREENULL(p_finder->p_sys->psz_tempfile);
        vlc_stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    char buffer[1<<10];
    ssize_t i_read = 0;
    int i_ret = VLC_SUCCESS;

    while ( ( i_read = vlc_stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 )
    {
        if ( write( fd, buffer, i_read ) != i_read )
        {
            msg_Err( p_finder, "Failed to write to Addon file" );
            i_ret = VLC_EGENERIC;
            break;
        }
    }

    vlc_close( fd );
    vlc_stream_Delete( p_stream );

    if (i_ret)
        return i_ret;

    msg_Dbg( p_finder, "Reading manifest from %s", p_finder->p_sys->psz_tempfile );

    char *psz_tempfileuri = vlc_path2uri( p_finder->p_sys->psz_tempfile, NULL );
    if ( !psz_tempfileuri )
        return VLC_ENOMEM;

    char *psz_manifest_uri;
    if ( asprintf( &psz_manifest_uri, "%s#!/manifest.xml", psz_tempfileuri ) < 1 )
    {
        free( psz_tempfileuri );
        return VLC_ENOMEM;
    }

    p_stream = vlc_stream_NewMRL( p_finder, psz_manifest_uri );
    free( psz_manifest_uri );
    if ( !p_stream )
    {
        free( psz_tempfileuri );
        return VLC_EGENERIC;
    }

    vlc_mutex_lock( &p_entry->lock );
    i_ret = ( ParseManifest( p_finder, p_entry, psz_tempfileuri, p_stream ) > 0 )
                    ? VLC_SUCCESS : VLC_EGENERIC;
    vlc_mutex_unlock( &p_entry->lock );
    free( psz_tempfileuri );
    vlc_stream_Delete( p_stream );

    return i_ret;
}