void GetMsiProperty (MSIHANDLE hModule, char* propertyValue, char* propertyName) { if(!propertyName) return; MSIHANDLE hRecord, hView, hDatabase; // get hView & hDatabase hDatabase = MsiGetActiveDatabase(hModule); char pSelectSql[256] = {0}; sprintf(pSelectSql, "select * from Property where `Property`='%s'", propertyName); MsiDatabaseOpenView(hDatabase, pSelectSql, &hView); MsiViewExecute(hView, NULL); DWORD dwLength = 256; if (MsiViewFetch(hView, &hRecord) != ERROR_SUCCESS) return; MsiRecordGetString(hRecord, 2, propertyValue, &dwLength); // close all handles MsiCloseHandle(hRecord); MsiViewClose(hView); MsiCloseHandle(hView); MsiCloseHandle(hDatabase); }
/*********************************************************************** * msidbExportStream * * Exports a stream to a file with an .idb extension. * * Examples (note wildcard escape for *nix/bash): * msidb -d <pathtomsi>.msi -f <workdir> -x <streamname> * msidb -d <pathtomsi>.msi -f <workdir> -x data.cab **********************************************************************/ static BOOL msidbExportStream(LPCWSTR dbfile, LPCWSTR wdir, LPCWSTR streamName) { static const char ext[] = {'.', 'i', 'd', 'b', 0}; UINT r, len; MSIHANDLE dbhandle, streamListView, rec; char queryBuffer[100]; FILE *fp = 0; char *streamNameA = strdupWtoA(CP_ACP, streamName); char *wdirA = strdupWtoA(CP_ACP, wdir); char *streamFileA = 0; char streamPath[MAX_PATH]; char *dataBuffer; DWORD dataLen = 0; r = MsiOpenDatabaseW(dbfile, (LPCWSTR) MSIDBOPEN_READONLY, &dbhandle); if (r != ERROR_SUCCESS) return FALSE; sprintf(queryBuffer, "SELECT * FROM _Streams WHERE Name = '%s'", streamNameA); MsiDatabaseOpenView(dbhandle, queryBuffer, &streamListView); MsiViewExecute(streamListView, 0); r = MsiViewFetch(streamListView, &rec); if (r != ERROR_SUCCESS) return FALSE; if (MsiRecordReadStream(rec, 2, 0, &dataLen) != ERROR_SUCCESS) return FALSE; dataBuffer = malloc(dataLen); if (!dataBuffer) return FALSE; if (MsiRecordReadStream(rec, 2, dataBuffer, &dataLen) != ERROR_SUCCESS) return FALSE; len = strlen(streamNameA) + 5; streamFileA = malloc(len); if (streamFileA == NULL) return FALSE; strcpy(streamFileA, streamNameA); strcat(streamFileA, ext); strcpy(streamPath, wdirA); strcat(streamPath, PATH_DELIMITER); strcat(streamPath, streamFileA); fp = fopen(streamPath , "wb"); if (fp != NULL) { fwrite(dataBuffer, 1, dataLen, fp); fclose(fp); } free(streamFileA); MsiCloseHandle(rec); MsiViewClose(streamListView); MsiCloseHandle(streamListView); MsiCloseHandle(dbhandle); free(wdirA); free(streamNameA); return TRUE; }
static BOOL msidbExportStorage(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR storageName) { UINT r, len; MSIHANDLE dbhandle, view, rec; char queryBuffer[100]; char *storageNameA = strdupWtoA(CP_ACP, storageName); char *wdirA = strdupWtoA(CP_ACP, wdir); char *storagePath = NULL; char *dataBuffer; DWORD dataLen = 0; FILE *fp = NULL; sprintf(queryBuffer, "SELECT * FROM _Storages WHERE Name = '%s'", storageNameA); r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_READONLY, &dbhandle); if (r != ERROR_SUCCESS) return FALSE; MsiDatabaseOpenView(dbhandle, queryBuffer, &view); MsiViewExecute(view, 0); r = MsiViewFetch(view, &rec); if (r != ERROR_SUCCESS) return FALSE; if ((r = MsiRecordReadStream(rec, 2, 0, &dataLen)) != ERROR_SUCCESS) { return FALSE; } if ((dataBuffer = malloc(dataLen)) == NULL) return FALSE; if (MsiRecordReadStream(rec, 2, dataBuffer, &dataLen) != ERROR_SUCCESS) return FALSE; len = strlen(wdirA) + strlen(storageNameA) + 2; storagePath = malloc(len * sizeof(WCHAR)); if (storagePath == NULL) return FALSE; strcpy(storagePath, wdirA); strcat(storagePath, "/"); strcat(storagePath, storageNameA); fp = fopen(storagePath , "wb"); if (fp != NULL) { fwrite(dataBuffer, 1, dataLen, fp); fclose(fp); } free(storagePath); MsiCloseHandle(rec); MsiViewClose(view); MsiCloseHandle(view); MsiCloseHandle(dbhandle); free(storageNameA); free(wdirA); return TRUE; }
static BOOL msidbImportStorages(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR storageNames[]) { static const WCHAR delim[] = {'/', 0}; UINT r, len, i; MSIHANDLE dbhandle, view, rec; WCHAR *storagePath = 0; char *query = "INSERT INTO _Storages (Name, Data) VALUES(?, ?)"; r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_TRANSACT, &dbhandle); if (r != ERROR_SUCCESS) return FALSE; r = MsiDatabaseOpenView(dbhandle, query, &view); if (r != ERROR_SUCCESS) return FALSE; MsiViewExecute(view, 0); r = MsiViewFetch(view, &rec); if (r != ERROR_SUCCESS) return FALSE; for (i = 0; i < MAX_STORAGES && storageNames[i] != 0; ++i) { len = lstrlenW(wdir) + lstrlenW(storageNames[i]) + 2; storagePath = malloc(len * sizeof(WCHAR)); if (storagePath == NULL) return FALSE; lstrcpyW(storagePath, wdir); lstrcatW(storagePath, delim); lstrcatW(storagePath, storageNames[i]); rec = MsiCreateRecord(2); MsiRecordSetStringW(rec, 1, storageNames[i]); r = MsiRecordSetStreamW(rec, 2, storagePath); if (r != ERROR_SUCCESS) { return FALSE; } r = MsiViewExecute(view, rec); if (r != ERROR_SUCCESS) { return FALSE; } MsiCloseHandle(rec); } MsiViewClose(view); MsiCloseHandle(view); MsiDatabaseCommit(dbhandle); MsiCloseHandle(dbhandle); return TRUE; }
static BOOL msidbImportStreams(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR streamNames[]) { UINT r, len; MSIHANDLE dbhandle, view, rec; int i = 0; WCHAR *streamPath = 0; char *query = "INSERT INTO _Streams (Name, Data) VALUES(?, ?)"; r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_TRANSACT, &dbhandle); if (r != ERROR_SUCCESS) return FALSE; r = MsiDatabaseOpenView(dbhandle, query, &view); if (r != ERROR_SUCCESS) return FALSE; for (i = 0; i < MAX_STREAMS && streamNames[i] != NULL; i++) { len = lstrlenW(wdir) + lstrlenW(streamNames[i]) + 2; streamPath = malloc(len * sizeof(WCHAR)); if (streamPath == NULL) return FALSE; lstrcpyW(streamPath, wdir); lstrcatW(streamPath, PATH_DELIMITERW); lstrcatW(streamPath, streamNames[i]); rec = MsiCreateRecord(2); MsiRecordSetStringW(rec, 1, streamNames[i]); r = MsiRecordSetStreamW(rec, 2, streamPath); if (r != ERROR_SUCCESS) { return FALSE; } r = MsiViewExecute(view, rec); if (r != ERROR_SUCCESS) { return FALSE; } MsiCloseHandle(rec); } MsiViewClose(view); MsiCloseHandle(view); MsiDatabaseCommit(dbhandle); MsiCloseHandle(dbhandle); return TRUE; }
/** * Extracts the jar file from the MSI database binary field * * @param hModule Specify the handle for the MSI database */ void ExtractBinaryFile (MSIHANDLE hModule, const char* pFieldName, const char* pDstFileName) { char cSelectSql[MAX_PATH_SIZE] = {0}; MSIHANDLE hRecord, hView, hDatabase; // get hView & hDatabase hDatabase = MsiGetActiveDatabase(hModule); sprintf(cSelectSql, "select * from Binary where `Name`='%s'", pFieldName); MsiDatabaseOpenView(hDatabase, cSelectSql, &hView); MsiViewExecute(hView, NULL); char szTemp[256] = {0}; DWORD dwLength = 256; if (MsiViewFetch(hView, &hRecord) != ERROR_SUCCESS) { return; } MsiRecordGetString(hRecord, 1, szTemp, &dwLength); if (strncmp(szTemp, pFieldName, strlen(pFieldName))) { return; } // write into installer.jar #define BUFFERSIZE 1024 char szBuffer[BUFFERSIZE] = {0}; DWORD cbBuf = BUFFERSIZE; DWORD countWrite = 0; FILE* fp = NULL; fp = fopen(pDstFileName, "wb+"); if (NULL == fp) { return; } do { if (MsiRecordReadStream(hRecord, 2, szBuffer, &cbBuf) !=ERROR_SUCCESS) break; // error countWrite = fwrite(szBuffer, 1, cbBuf, fp); } while (countWrite == BUFFERSIZE); fclose(fp); // close all handles MsiCloseHandle(hRecord); MsiViewClose(hView); MsiCloseHandle(hView); MsiCloseHandle(hDatabase); }
static UINT find_entry( MSIHANDLE hdb, const char *table, const char *entry ) { static char fmt[] = "SELECT * FROM `%s` WHERE `Name` = '%s'"; char query[0x100]; UINT r; MSIHANDLE hview, hrec; sprintf( query, fmt, table, entry ); r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); MsiCloseHandle( hrec ); return r; }
/*********************************************************************** * msidbExportTables * * Takes a list of tables or '*' (for all) to export to text archive * files in specified folder * * For each table, a file called <tablename>.idt is exported containing * tab separated ASCII. * * Examples (note wildcard escape for *nix/bash): * msidb -d <pathtomsi>.msi -f <workdir> -e \* * msidb -d <pathtomsi>.msi -f <workdir> -e File Directory Binary **********************************************************************/ static BOOL msidbExportTables(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR tables[]) { static const WCHAR ext[] = {'.', 'i', 'd', 't', 0}; static const WCHAR all[] = {'*', 0}; UINT r, len; MSIHANDLE dbhandle, tableListView, rec; LPWSTR tableFile = 0; WCHAR tableName[MAX_TABLE_NAME]; DWORD size = sizeof(tableName) / sizeof(tableName[0]); int i = 0; r = MsiOpenDatabaseW(dbfile, (LPCWSTR) MSIDBOPEN_READONLY, &dbhandle); if (r != ERROR_SUCCESS) return FALSE; if (strcmpW(tables[0], all) == 0) { r = MsiDatabaseOpenView(dbhandle, "SELECT Name FROM _Tables", &tableListView); r = MsiViewExecute(tableListView, 0); r = MsiViewFetch(tableListView, &rec); while (r == ERROR_SUCCESS) { size = sizeof(tableName) / sizeof(tableName[0]); r = MsiRecordGetStringW(rec, 1, tableName, &size); if (r == ERROR_SUCCESS) { len = lstrlenW(tableName) + 5; tableFile = malloc(len * sizeof (WCHAR)); if (tableFile == NULL) return FALSE; lstrcpyW(tableFile, tableName); lstrcatW(tableFile, ext); r = MsiDatabaseExportW(dbhandle, tableName, wdir, tableFile); free(tableFile); MsiCloseHandle(rec); } r = MsiViewFetch(tableListView, &rec); } MsiViewClose(tableListView); MsiCloseHandle(tableListView); } else { for (i = 0; i < MAX_TABLES && tables[i] != 0; ++i) { len = lstrlenW(tables[i]) + 5; tableFile = malloc(len * sizeof (WCHAR)); if (tableFile == NULL) return FALSE; lstrcpyW(tableFile, tables[i]); lstrcatW(tableFile, ext); r = MsiDatabaseExportW(dbhandle, tables[i], wdir, tableFile); free(tableFile); } } MsiCloseHandle(dbhandle); return TRUE; }
static void test_fieldzero(void) { MSIHANDLE hdb, hview, rec; CHAR buf[MAX_PATH]; LPCSTR query; DWORD sz; UINT r; rec = MsiCreateRecord(1); ok(rec != 0, "Expected a valid handle\n"); r = MsiRecordGetInteger(rec, 0); ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); sz = MAX_PATH; lstrcpyA(buf, "apple"); r = MsiRecordGetString(rec, 0, buf, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); ok(sz == 0, "Expectd 0, got %d\n", sz); r = MsiRecordIsNull(rec, 0); ok(r == TRUE, "Expected TRUE, got %d\n", r); r = MsiRecordGetInteger(rec, 1); ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); r = MsiRecordSetInteger(rec, 1, 42); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiRecordGetInteger(rec, 0); ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); sz = MAX_PATH; lstrcpyA(buf, "apple"); r = MsiRecordGetString(rec, 0, buf, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); ok(sz == 0, "Expectd 0, got %d\n", sz); r = MsiRecordIsNull(rec, 0); ok(r == TRUE, "Expected TRUE, got %d\n", r); r = MsiRecordGetInteger(rec, 1); ok(r == 42, "Expected 42, got %d\n", r); r = MsiRecordSetString(rec, 1, "bologna"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiRecordGetInteger(rec, 0); ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); sz = MAX_PATH; lstrcpyA(buf, "apple"); r = MsiRecordGetString(rec, 0, buf, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); ok(sz == 0, "Expectd 0, got %d\n", sz); r = MsiRecordIsNull(rec, 0); ok(r == TRUE, "Expected TRUE, got %d\n", r); sz = MAX_PATH; lstrcpyA(buf, "apple"); r = MsiRecordGetString(rec, 1, buf, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(buf, "bologna"), "Expected \"bologna\", got \"%s\"\n", buf); ok(sz == 7, "Expectd 7, got %d\n", sz); MsiCloseHandle(rec); r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); query = "CREATE TABLE `drone` ( " "`id` INT, `name` CHAR(32), `number` CHAR(32) " "PRIMARY KEY `id`)"; r = MsiDatabaseOpenView(hdb, query, &hview); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiViewExecute(hview, 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiViewClose(hview); ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); r = MsiCloseHandle(hview); ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); query = "INSERT INTO `drone` ( `id`, `name`, `number` )" "VALUES('1', 'Abe', '8675309')"; r = MsiDatabaseOpenView(hdb, query, &hview); ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); r = MsiViewExecute(hview, 0); ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); r = MsiViewClose(hview); ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); r = MsiCloseHandle(hview); ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); r = MsiDatabaseGetPrimaryKeysA(hdb, "drone", &rec); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiRecordGetInteger(rec, 0); ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); sz = MAX_PATH; lstrcpyA(buf, "apple"); r = MsiRecordGetString(rec, 0, buf, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(!lstrcmpA(buf, "drone"), "Expected \"drone\", got \"%s\"\n", buf); ok(sz == 5, "Expectd 5, got %d\n", sz); r = MsiRecordIsNull(rec, 0); ok(r == FALSE, "Expected FALSE, got %d\n", r); MsiCloseHandle(rec); r = MsiDatabaseGetPrimaryKeysA(hdb, "nosuchtable", &rec); ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r); query = "SELECT * FROM `drone` WHERE `id` = 1"; r = MsiDatabaseOpenView(hdb, query, &hview); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiViewExecute(hview, 0); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiViewFetch(hview, &rec); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiRecordGetInteger(rec, 0); ok(r != MSI_NULL_INTEGER && r != 0, "Expected non-NULL value, got %d\n", r); r = MsiRecordIsNull(rec, 0); ok(r == FALSE, "Expected FALSE, got %d\n", r); r = MsiCloseHandle(hview); ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); MsiCloseHandle(rec); MsiCloseHandle(hdb); DeleteFileA(msifile); }
static void test_system_tables( void ) { UINT r; const char *query; MSIHANDLE hproduct, hdb, hview, hrec; if (!pMsiApplyPatchA) { win_skip("MsiApplyPatchA is not available\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } CreateDirectoryA( "msitest", NULL ); create_file( "msitest\\patch.txt", 1000 ); create_database( msifile, tables, sizeof(tables) / sizeof(struct msi_table) ); create_patch( mspfile ); MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL ); r = MsiInstallProductA( msifile, NULL ); if (r != ERROR_SUCCESS) { skip("Product installation failed with error code %d\n", r); goto cleanup; } r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); hdb = MsiGetActiveDatabase( hproduct ); ok( hdb, "failed to get database handle\n" ); r = find_entry( hdb, "_Streams", "\5SummaryInformation" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); query = "SELECT * FROM `_Storages`"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r ); r = find_entry( hdb, "_Tables", "Directory" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "File" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Component" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Feature" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "FeatureComponents" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Property" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "InstallExecuteSequence" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Media" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "_Property" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); MsiCloseHandle( hdb ); MsiCloseHandle( hproduct ); r = MsiApplyPatchA( mspfile, NULL, INSTALLTYPE_DEFAULT, NULL ); ok( r == ERROR_SUCCESS || broken( r == ERROR_PATCH_PACKAGE_INVALID ), /* version 2.0 */ "expected ERROR_SUCCESS, got %u\n", r ); if (r == ERROR_PATCH_PACKAGE_INVALID) { win_skip("Windows Installer < 3.0 detected\n"); goto uninstall; } r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); hdb = MsiGetActiveDatabase( hproduct ); ok( hdb, "failed to get database handle\n" ); r = find_entry( hdb, "_Streams", "\5SummaryInformation" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); query = "SELECT * FROM `_Storages`"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r ); r = find_entry( hdb, "_Tables", "Directory" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "File" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Component" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Feature" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "FeatureComponents" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Property" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "InstallExecuteSequence" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Media" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "_Property" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "MsiPatchHeaders" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Patch" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "PatchPackage" ); ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); MsiCloseHandle( hdb ); MsiCloseHandle( hproduct ); uninstall: r = MsiInstallProductA( msifile, "REMOVE=ALL" ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); cleanup: DeleteFileA( msifile ); DeleteFileA( mspfile ); DeleteFileA( "msitest\\patch.txt" ); RemoveDirectoryA( "msitest" ); }
static void test_simple_patch( void ) { UINT r; DWORD size; char path[MAX_PATH], install_source[MAX_PATH], buffer[32]; const char *query; MSIHANDLE hpackage, hdb, hview, hrec; if (!pMsiApplyPatchA) { win_skip("MsiApplyPatchA is not available\n"); return; } if (is_process_limited()) { skip("process is limited\n"); return; } CreateDirectoryA( "msitest", NULL ); create_file( "msitest\\patch.txt", 1000 ); create_database( msifile, tables, sizeof(tables) / sizeof(struct msi_table) ); create_patch( mspfile ); MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL ); r = MsiInstallProductA( msifile, NULL ); if (r != ERROR_SUCCESS) { skip("Product installation failed with error code %u\n", r); goto cleanup; } size = get_pf_file_size( "msitest\\patch.txt" ); ok( size == 1000, "expected 1000, got %u\n", size ); size = sizeof(install_source); r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", "InstallSource", install_source, &size ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); strcpy( path, CURR_DIR ); strcat( path, "\\" ); strcat( path, msifile ); r = MsiOpenPackageA( path, &hpackage ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); hdb = MsiGetActiveDatabase( hpackage ); ok( hdb, "failed to get database handle\n" ); query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' " "AND `Value` = 'Installer Database'"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); buffer[0] = 0; size = sizeof(buffer); r = MsiGetProperty( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); ok( !strcmp( buffer, "Installer Database" ), "expected \'Installer Database\', got \'%s\'\n", buffer ); MsiCloseHandle( hdb ); MsiCloseHandle( hpackage ); r = MsiApplyPatchA( mspfile, NULL, INSTALLTYPE_DEFAULT, NULL ); ok( r == ERROR_SUCCESS || broken( r == ERROR_PATCH_PACKAGE_INVALID ), /* version 2.0 */ "expected ERROR_SUCCESS, got %u\n", r ); if (r == ERROR_PATCH_PACKAGE_INVALID) { win_skip("Windows Installer < 3.0 detected\n"); goto uninstall; } size = get_pf_file_size( "msitest\\patch.txt" ); ok( size == 1002, "expected 1002, got %u\n", size ); /* show that MsiOpenPackage applies registered patches */ r = MsiOpenPackageA( path, &hpackage ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); hdb = MsiGetActiveDatabase( hpackage ); ok( hdb, "failed to get database handle\n" ); query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' " "AND `Value` = 'Installation Database'"; r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); buffer[0] = 0; size = sizeof(buffer); r = MsiGetProperty( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); ok( !strcmp( buffer, "Installation Database" ), "expected \'Installation Database\', got \'%s\'\n", buffer ); MsiCloseHandle( hdb ); MsiCloseHandle( hpackage ); /* show that patches are not committed to the local package database */ size = sizeof(path); r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", "LocalPackage", path, &size ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiOpenDatabaseA( path, MSIDBOPEN_READONLY, &hdb ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiDatabaseOpenView( hdb, query, &hview ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewExecute( hview, 0 ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); MsiCloseHandle( hview ); MsiCloseHandle( hdb ); uninstall: size = sizeof(path); r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", "InstallSource", path, &size ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); ok( !strcasecmp( path, install_source ), "wrong path %s\n", path ); r = MsiInstallProductA( msifile, "REMOVE=ALL" ); ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); ok( !delete_pf( "msitest\\patch.txt", TRUE ), "file not removed\n" ); ok( !delete_pf( "msitest", FALSE ), "directory not removed\n" ); cleanup: DeleteFileA( msifile ); DeleteFileA( mspfile ); DeleteFileA( "msitest\\patch.txt" ); RemoveDirectoryA( "msitest" ); }
///////////////////////////////////////////////////////////////////// // // Function: GetComponentKeyFilename // // Description: // ///////////////////////////////////////////////////////////////////// UINT BOINCCABase::GetComponentKeyFilename( const tstring strComponentName, tstring& strComponentKeyFilename ) { UINT uiReturnValue = 0; tstring strMessage; tstring strQuery; TCHAR szBuffer[256]; DWORD dwBufferSize = sizeof(szBuffer); MSIHANDLE hDatabase; MSIHANDLE hView; MSIHANDLE hRecComponentName; MSIHANDLE hRec; // Get the handle to the MSI package we are executing for. hDatabase = MsiGetActiveDatabase(m_hMSIHandle); if (!hDatabase) return ERROR_INSTALL_FAILURE; // Construct the query that is going to give us the result we need. strQuery = _T("SELECT `KeyPath` FROM `Component` WHERE `Component`= ?"); // Create the view uiReturnValue = MsiDatabaseOpenView(hDatabase, strQuery.c_str(), &hView); switch(uiReturnValue) { case ERROR_BAD_QUERY_SYNTAX: MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiDatabaseOpenView reports an invalid query was issued") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_HANDLE: MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiDatabaseOpenView reports an invalid handle was used") ); return ERROR_INSTALL_FAILURE; break; } // Create query parameter hRecComponentName = MsiCreateRecord(1); uiReturnValue = MsiRecordSetString(hRecComponentName, 1, strComponentName.c_str()); switch(uiReturnValue) { case ERROR_INVALID_HANDLE: MsiCloseHandle(hRecComponentName); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiRecordSetString reports an invalid handle was used") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_PARAMETER: MsiCloseHandle(hRecComponentName); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiRecordSetString reports an invalid parameter was used") ); return ERROR_INSTALL_FAILURE; break; } // Execute the query uiReturnValue = MsiViewExecute(hView, hRecComponentName); switch(uiReturnValue) { case ERROR_FUNCTION_FAILED: MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiViewExecute failed to execute the view") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_HANDLE: MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiViewExecute reports an invalid handle was used") ); return ERROR_INSTALL_FAILURE; break; } // Only one row should be returned by the resultset, so there is no need // to execute MsiViewFetch more than once. uiReturnValue = MsiViewFetch(hView, &hRec); switch(uiReturnValue) { case ERROR_FUNCTION_FAILED: MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiViewFetch: An error occurred during fetching") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_HANDLE: MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiViewFetch reports an invalid handle was used") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_HANDLE_STATE: MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiViewFetch reports the handle was in an invalid state") ); return ERROR_INSTALL_FAILURE; break; } // Okay, now it is time to parse the string that was returned. uiReturnValue = MsiRecordGetString(hRec, 1, (LPTSTR)&szBuffer, &dwBufferSize); switch(uiReturnValue) { case ERROR_INVALID_HANDLE: MsiCloseHandle(hRec); MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiRecordGetString reports an invalid handle was used") ); return ERROR_INSTALL_FAILURE; break; case ERROR_INVALID_PARAMETER: MsiCloseHandle(hRec); MsiViewClose(hView); MsiCloseHandle(hDatabase); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, _T("MsiRecordGetString reports an invalid parameter was used") ); return ERROR_INSTALL_FAILURE; break; } // Save the string strComponentKeyFilename = szBuffer; strMessage = _T("The key filename for component '"); strMessage += strComponentName; strMessage += _T("' is '"); strMessage += strComponentKeyFilename; strMessage += _T("'"); LogMessage( INSTALLMESSAGE_INFO, NULL, NULL, NULL, NULL, strMessage.c_str() ); return ERROR_SUCCESS; }