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; }
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; }
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; }