{'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y','S','p','a','c','e',0};
static const WCHAR szBindImage[] =
{'B','i','n','d','I','m','a','g','e',0};
-static const WCHAR szCCPSearch[] =
- {'C','C','P','S','e','a','r','c','h',0};
static const WCHAR szDeleteServices[] =
{'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0};
static const WCHAR szDisableRollback[] =
{'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szRegisterComPlus[] =
{'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
-static const WCHAR szRegisterFonts[] =
- {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
static const WCHAR szRegisterUser[] =
{'R','e','g','i','s','t','e','r','U','s','e','r',0};
static const WCHAR szRemoveEnvironmentStrings[] =
{'U','n','p','u','b','l','i','s','h', 'C','o','m','p','o','n','e','n','t','s',0};
static const WCHAR szUnpublishFeatures[] =
{'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
-static const WCHAR szUnregisterClassInfo[] =
- {'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
static const WCHAR szUnregisterComPlus[] =
{'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
-static const WCHAR szUnregisterExtensionInfo[] =
- {'U','n','r','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n','I','n','f','o',0};
-static const WCHAR szUnregisterFonts[] =
- {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
-static const WCHAR szUnregisterMIMEInfo[] =
- {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
-static const WCHAR szUnregisterProgIdInfo[] =
- {'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
static const WCHAR szUnregisterTypeLibraries[] =
{'U','n','r','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r','i','e','s',0};
static const WCHAR szValidateProductID[] =
if (lstrlenW(prop) > 0)
{
+ UINT r = msi_set_property( package->db, prop, val );
+
TRACE("Found commandline property (%s) = (%s)\n",
debugstr_w(prop), debugstr_w(val));
- MSI_SetPropertyW(package,prop,val);
+
+ if (r == ERROR_SUCCESS && !strcmpW( prop, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
}
msi_free(val);
msi_free(prop);
LPWSTR prod_code, patch_product, langid = NULL, template = NULL;
UINT ret = ERROR_FUNCTION_FAILED;
- prod_code = msi_dup_property( package, szProductCode );
+ prod_code = msi_dup_property( package->db, szProductCode );
patch_product = msi_get_suminfo_product( patch );
TRACE("db = %s patch = %s\n", debugstr_w(prod_code), debugstr_w(patch_product));
goto end;
}
- langid = msi_dup_property( package, szSystemLanguageID );
+ langid = msi_dup_property( package->db, szSystemLanguageID );
if (!langid)
{
msiobj_release( &si->hdr );
LPWSTR guid_list, *guids, product_code;
UINT i, ret = ERROR_FUNCTION_FAILED;
- product_code = msi_dup_property( package, szProductCode );
+ product_code = msi_dup_property( package->db, szProductCode );
if (!product_code)
{
/* FIXME: the property ProductCode should be written into the DB somewhere */
if (MSI_ViewFetch(view, &rec) == ERROR_SUCCESS)
{
prop = MSI_RecordGetString(rec, 1);
- patch = msi_dup_property(package, szPatch);
- MSI_SetPropertyW(package, prop, patch);
+ patch = msi_dup_property(package->db, szPatch);
+ msi_set_property(package->db, prop, patch);
msi_free(patch);
}
return r;
}
-static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db )
+UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
{
- MSISUMMARYINFO *si;
- LPWSTR str, *substorage;
- UINT i, r = ERROR_SUCCESS;
+ MSIPATCHINFO *pi;
+ UINT r = ERROR_SUCCESS;
- si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
- if (!si)
- return ERROR_FUNCTION_FAILED;
+ pi = msi_alloc_zero( sizeof(MSIPATCHINFO) );
+ if (!pi)
+ return ERROR_OUTOFMEMORY;
- if (msi_check_patch_applicable( package, si ) != ERROR_SUCCESS)
+ pi->patchcode = msi_suminfo_dup_string( si, PID_REVNUMBER );
+ if (!pi->patchcode)
{
- TRACE("Patch not applicable\n");
- return ERROR_SUCCESS;
+ msi_free( pi );
+ return ERROR_OUTOFMEMORY;
}
- package->patch = msi_alloc(sizeof(MSIPATCHINFO));
- if (!package->patch)
+ pi->transforms = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
+ if (!pi->transforms)
+ {
+ msi_free( pi->patchcode );
+ msi_free( pi );
return ERROR_OUTOFMEMORY;
+ }
- package->patch->patchcode = msi_suminfo_dup_string(si, PID_REVNUMBER);
- if (!package->patch->patchcode)
- return ERROR_OUTOFMEMORY;
+ *patch = pi;
+ return r;
+}
- /* enumerate the substorage */
- str = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
- package->patch->transforms = str;
+UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch )
+{
+ UINT i, r = ERROR_SUCCESS;
+ WCHAR **substorage;
- substorage = msi_split_string( str, ';' );
- for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ )
+ /* apply substorage transforms */
+ substorage = msi_split_string( patch->transforms, ';' );
+ for (i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++)
r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
msi_free( substorage );
- msiobj_release( &si->hdr );
+ if (r != ERROR_SUCCESS)
+ return r;
- msi_set_media_source_prop(package);
+ msi_set_media_source_prop( package );
- return r;
+ /*
+ * There might be a CAB file in the patch package,
+ * so append it to the list of storages to search for streams.
+ */
+ append_storage_to_db( package->db, patch_db->storage );
+
+ list_add_tail( &package->patches, &patch->entry );
+ return ERROR_SUCCESS;
}
static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
{
+ static const WCHAR dotmsp[] = {'.','m','s','p',0};
MSIDATABASE *patch_db = NULL;
- UINT r;
+ WCHAR localfile[MAX_PATH];
+ MSISUMMARYINFO *si;
+ MSIPATCHINFO *patch = NULL;
+ UINT r = ERROR_SUCCESS;
TRACE("%p %s\n", package, debugstr_w( file ) );
- /* FIXME:
- * We probably want to make sure we only open a patch collection here.
- * Patch collections (.msp) and databases (.msi) have different GUIDs
- * but currently MSI_OpenDatabaseW will accept both.
- */
- r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &patch_db );
+ r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db );
if ( r != ERROR_SUCCESS )
{
ERR("failed to open patch collection %s\n", debugstr_w( file ) );
return r;
}
- msi_parse_patch_summary( package, patch_db );
+ si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
+ if (!si)
+ {
+ msiobj_release( &patch_db->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
- /*
- * There might be a CAB file in the patch package,
- * so append it to the list of storage to search for streams.
- */
- append_storage_to_db( package->db, patch_db->storage );
+ r = msi_check_patch_applicable( package, si );
+ if (r != ERROR_SUCCESS)
+ {
+ TRACE("patch not applicable\n");
+ r = ERROR_SUCCESS;
+ goto done;
+ }
+
+ r = msi_parse_patch_summary( si, &patch );
+ if ( r != ERROR_SUCCESS )
+ goto done;
+
+ r = msi_get_local_package_name( localfile, dotmsp );
+ if ( r != ERROR_SUCCESS )
+ goto done;
+
+ TRACE("copying to local package %s\n", debugstr_w(localfile));
+
+ if (!CopyFileW( file, localfile, FALSE ))
+ {
+ ERR("Unable to copy package (%s -> %s) (error %u)\n",
+ debugstr_w(file), debugstr_w(localfile), GetLastError());
+ r = GetLastError();
+ goto done;
+ }
+ patch->localfile = strdupW( localfile );
+ r = msi_apply_patch_db( package, patch_db, patch );
+ if ( r != ERROR_SUCCESS )
+ WARN("patch failed to apply %u\n", r);
+
+done:
+ msiobj_release( &si->hdr );
msiobj_release( &patch_db->hdr );
+ if (patch && r != ERROR_SUCCESS)
+ {
+ if (patch->localfile)
+ DeleteFileW( patch->localfile );
- return ERROR_SUCCESS;
+ msi_free( patch->patchcode );
+ msi_free( patch->transforms );
+ msi_free( patch->localfile );
+ msi_free( patch );
+ }
+ return r;
}
/* get the PATCH property, and apply all the patches it specifies */
LPWSTR patch_list, *patches;
UINT i, r = ERROR_SUCCESS;
- patch_list = msi_dup_property( package, szPatch );
+ patch_list = msi_dup_property( package->db, szPatch );
TRACE("patches to be applied: %s\n", debugstr_w( patch_list ) );
LPWSTR xform_list, *xforms;
UINT i, r = ERROR_SUCCESS;
- xform_list = msi_dup_property( package, szTransforms );
+ xform_list = msi_dup_property( package->db, szTransforms );
xforms = msi_split_string( xform_list, ';' );
for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
static UINT msi_set_sourcedir_props(MSIPACKAGE *package, BOOL replace)
{
- LPWSTR p, db;
LPWSTR source, check;
- DWORD len;
-
- static const WCHAR szOriginalDatabase[] =
- {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
- db = msi_dup_property( package, szOriginalDatabase );
- if (!db)
- return ERROR_OUTOFMEMORY;
+ if (msi_get_property_int( package->db, szInstalled, 0 ))
+ {
+ HKEY hkey;
- p = strrchrW( db, '\\' );
- if (!p)
+ MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE );
+ source = msi_reg_get_val_str( hkey, INSTALLPROPERTY_INSTALLSOURCEW );
+ RegCloseKey( hkey );
+ }
+ else
{
- p = strrchrW( db, '/' );
+ LPWSTR p, db;
+ DWORD len;
+
+ db = msi_dup_property( package->db, szOriginalDatabase );
+ if (!db)
+ return ERROR_OUTOFMEMORY;
+
+ p = strrchrW( db, '\\' );
if (!p)
{
- msi_free(db);
- return ERROR_SUCCESS;
+ p = strrchrW( db, '/' );
+ if (!p)
+ {
+ msi_free(db);
+ return ERROR_SUCCESS;
+ }
}
- }
- len = p - db + 2;
- source = msi_alloc( len * sizeof(WCHAR) );
- lstrcpynW( source, db, len );
+ len = p - db + 2;
+ source = msi_alloc( len * sizeof(WCHAR) );
+ lstrcpynW( source, db, len );
+ msi_free( db );
+ }
- check = msi_dup_property( package, cszSourceDir );
+ check = msi_dup_property( package->db, cszSourceDir );
if (!check || replace)
- MSI_SetPropertyW( package, cszSourceDir, source );
-
+ {
+ UINT r = msi_set_property( package->db, cszSourceDir, source );
+ if (r == ERROR_SUCCESS)
+ msi_reset_folders( package, TRUE );
+ }
msi_free( check );
- check = msi_dup_property( package, cszSOURCEDIR );
+ check = msi_dup_property( package->db, cszSOURCEDIR );
if (!check || replace)
- MSI_SetPropertyW( package, cszSOURCEDIR, source );
+ msi_set_property( package->db, cszSOURCEDIR, source );
msi_free( check );
msi_free( source );
- msi_free( db );
return ERROR_SUCCESS;
}
static BOOL needs_ui_sequence(MSIPACKAGE *package)
{
- INT level = msi_get_property_int(package, szUILevel, 0);
+ INT level = msi_get_property_int(package->db, szUILevel, 0);
return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
}
-static UINT msi_set_context(MSIPACKAGE *package)
+UINT msi_set_context(MSIPACKAGE *package)
{
- WCHAR val[10];
- DWORD sz = 10;
- DWORD num;
- UINT r;
+ int num;
package->Context = MSIINSTALLCONTEXT_USERUNMANAGED;
- r = MSI_GetPropertyW(package, szAllUsers, val, &sz);
- if (r == ERROR_SUCCESS)
- {
- num = atolW(val);
- if (num == 1 || num == 2)
- package->Context = MSIINSTALLCONTEXT_MACHINE;
- }
+ num = msi_get_property_int(package->db, szAllUsers, 0);
+ if (num == 1 || num == 2)
+ package->Context = MSIINSTALLCONTEXT_MACHINE;
return ERROR_SUCCESS;
}
return r;
}
+static UINT load_file_disk_id( MSIPACKAGE *package, MSIFILE *file )
+{
+ MSIRECORD *row;
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','`','D','i','s','k','I','d','`',' ', 'F','R','O','M',' ',
+ '`','M','e','d','i','a','`',' ','W','H','E','R','E',' ',
+ '`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',' ','%','i',0};
+
+ row = MSI_QueryGetRecord( package->db, query, file->Sequence );
+ if (!row)
+ {
+ WARN("query failed\n");
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ file->disk_id = MSI_RecordGetInteger( row, 1 );
+ msiobj_release( &row->hdr );
+ return ERROR_SUCCESS;
+}
+
static UINT load_file(MSIRECORD *row, LPVOID param)
{
MSIPACKAGE* package = param;
}
load_file_hash(package, file);
+ load_file_disk_id(package, file);
TRACE("File Loaded (%s)\n",debugstr_w(file->File));
folder->Parent = msi_dup_record_field( row, 2 );
- folder->Property = msi_dup_property( package, folder->Directory );
+ folder->Property = msi_dup_property( package->db, folder->Directory );
list_add_tail( &package->folders, &folder->entry );
static const WCHAR szCosting[] =
{'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
- MSI_SetPropertyW(package, szCosting, szZero);
- MSI_SetPropertyW(package, cszRootDrive, c_colon);
+ msi_set_property( package->db, szCosting, szZero );
+ msi_set_property( package->db, cszRootDrive, c_colon );
load_all_folders( package );
load_all_components( package );
LPWSTR override;
MSIFEATURE *feature;
- override = msi_dup_property( package, property );
+ override = msi_dup_property( package->db, property );
if (!override)
return FALSE;
ret |= process_state_property( package, level, szAdvertise, INSTALLSTATE_ADVERTISED );
if (ret)
- MSI_SetPropertyW( package, szPreselected, szOne );
+ msi_set_property( package->db, szPreselected, szOne );
return ret;
}
TRACE("Checking Install Level\n");
- level = msi_get_property_int(package, szlevel, 1);
+ level = msi_get_property_int(package->db, szlevel, 1);
- if (!msi_get_property_int( package, szPreselected, 0 ))
+ if (!msi_get_property_int( package->db, szPreselected, 0 ))
{
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
return ERROR_SUCCESS;
}
-static LPWSTR msi_get_disk_file_version( LPCWSTR filename )
+static LPWSTR get_disk_file_version( LPCWSTR filename )
{
static const WCHAR name_fmt[] =
{'%','u','.','%','u','.','%','u','.','%','u',0};
return strdupW( filever );
}
-static UINT msi_check_file_install_states( MSIPACKAGE *package )
+static DWORD get_disk_file_size( LPCWSTR filename )
+{
+ HANDLE file;
+ DWORD size;
+
+ TRACE("%s\n", debugstr_w(filename));
+
+ file = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
+ if (file == INVALID_HANDLE_VALUE)
+ return INVALID_FILE_SIZE;
+
+ size = GetFileSize( file, NULL );
+ CloseHandle( file );
+ return size;
+}
+
+static BOOL hash_matches( MSIFILE *file )
+{
+ UINT r;
+ MSIFILEHASHINFO hash;
+
+ hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
+ r = MsiGetFileHashW( file->TargetPath, 0, &hash );
+ if (r != ERROR_SUCCESS)
+ return FALSE;
+
+ return !memcmp( &hash, &file->hash, sizeof(MSIFILEHASHINFO) );
+}
+
+static UINT set_file_install_states( MSIPACKAGE *package )
{
LPWSTR file_version;
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
MSICOMPONENT* comp = file->Component;
+ DWORD file_size;
LPWSTR p;
if (!comp)
TRACE("file %s resolves to %s\n",
debugstr_w(file->File), debugstr_w(file->TargetPath));
- /* don't check files of components that aren't installed */
- if (comp->Installed == INSTALLSTATE_UNKNOWN ||
- comp->Installed == INSTALLSTATE_ABSENT)
- {
- file->state = msifs_missing; /* assume files are missing */
- continue;
- }
-
if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
{
file->state = msifs_missing;
comp->Cost += file->FileSize;
continue;
}
-
- if (file->Version &&
- (file_version = msi_get_disk_file_version( file->TargetPath )))
+ if (file->Version && (file_version = get_disk_file_version( file->TargetPath )))
{
- TRACE("new %s old %s\n", debugstr_w(file->Version),
- debugstr_w(file_version));
- /* FIXME: seems like a bad way to compare version numbers */
- if (lstrcmpiW(file_version, file->Version)<0)
+ TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(file_version));
+
+ if (strcmpiW(file_version, file->Version) < 0)
{
file->state = msifs_overwrite;
comp->Cost += file->FileSize;
}
else
+ {
+ TRACE("Destination file version equal or greater, not overwriting\n");
file->state = msifs_present;
+ }
msi_free( file_version );
+ continue;
}
- else
+ if ((file_size = get_disk_file_size( file->TargetPath )) != file->FileSize)
+ {
+ file->state = msifs_overwrite;
+ comp->Cost += file->FileSize - file_size;
+ continue;
+ }
+ if (file->hash.dwFileHashInfoSize && hash_matches( file ))
+ {
+ TRACE("File hashes match, not overwriting\n");
file->state = msifs_present;
+ continue;
+ }
+ file->state = msifs_overwrite;
+ comp->Cost += file->FileSize - file_size;
}
return ERROR_SUCCESS;
ACTION_GetComponentInstallStates(package);
ACTION_GetFeatureInstallStates(package);
- TRACE("File calculations\n");
- msi_check_file_install_states( package );
+ TRACE("Calculating file install states\n");
+ set_file_install_states( package );
- if (!process_overrides( package, msi_get_property_int( package, szlevel, 1 ) ))
+ if (!process_overrides( package, msi_get_property_int( package->db, szlevel, 1 ) ))
{
- TRACE("Evaluating Condition Table\n");
+ TRACE("Evaluating feature conditions\n");
rc = MSI_DatabaseOpenViewW( package->db, ConditionQuery, &view );
if (rc == ERROR_SUCCESS)
rc = MSI_IterateRecords( view, NULL, ITERATE_CostFinalizeConditions, package );
msiobj_release( &view->hdr );
}
+ }
+ TRACE("Evaluating component conditions\n");
- TRACE("Enabling or Disabling Components\n");
- LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+ LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+ {
+ if (MSI_EvaluateConditionW( package, comp->Condition ) == MSICONDITION_FALSE)
{
- if (MSI_EvaluateConditionW( package, comp->Condition ) == MSICONDITION_FALSE)
- {
- TRACE("Disabling component %s\n", debugstr_w(comp->Component));
- comp->Enabled = FALSE;
- }
- else
- comp->Enabled = TRUE;
+ TRACE("Disabling component %s\n", debugstr_w(comp->Component));
+ comp->Enabled = FALSE;
}
+ else
+ comp->Enabled = TRUE;
}
- MSI_SetPropertyW(package,szCosting,szOne);
+ msi_set_property( package->db, szCosting, szOne );
/* set default run level if not set */
- level = msi_dup_property( package, szlevel );
+ level = msi_dup_property( package->db, szlevel );
if (!level)
- MSI_SetPropertyW(package,szlevel, szOne);
+ msi_set_property( package->db, szlevel, szOne );
msi_free(level);
/* FIXME: check volume disk space */
- MSI_SetPropertyW(package, szOutOfDiskSpace, szZero);
+ msi_set_property( package->db, szOutOfDiskSpace, szZero );
return MSI_SetFeatureStates(package);
}
switch (root)
{
case -1:
- if (msi_get_property_int( package, szAllUsers, 0 ))
+ if (msi_get_property_int( package->db, szAllUsers, 0 ))
{
*root_key = HKEY_LOCAL_MACHINE;
ret = szHLM;
uirow = MSI_CreateRecord(3);
MSI_RecordSetStringW(uirow,2,deformated);
MSI_RecordSetStringW(uirow,1,uikey);
-
- if (type == REG_SZ)
+ if (type == REG_SZ || type == REG_EXPAND_SZ)
MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
- else
- MSI_RecordSetStringW(uirow,3,value);
-
ui_actiondata(package,szWriteRegistryValues,uirow);
msiobj_release( &uirow->hdr );
else
MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL);
}
+ comp->Action = comp->ActionRequest;
/* UI stuff */
uirow = MSI_CreateRecord(3);
{
LPCWSTR guid;
guid = MSI_RecordGetString(row,1);
- CLSIDFromString((LPWSTR)guid, &tl_struct.clsid);
+ CLSIDFromString((LPCWSTR)guid, &tl_struct.clsid);
tl_struct.source = strdupW( file->TargetPath );
tl_struct.path = NULL;
ui_actiondata( package, szUnregisterTypeLibraries, row );
guid = MSI_RecordGetString( row, 1 );
- CLSIDFromString( (LPWSTR)guid, &libid );
+ CLSIDFromString( (LPCWSTR)guid, &libid );
version = MSI_RecordGetInteger( row, 4 );
language = MSI_RecordGetInteger( row, 2 );
{'C','l','i','e','n','t','s',0};
static const WCHAR szColon[] = {':',0};
- buffer = msi_dup_property(package, INSTALLPROPERTY_PRODUCTNAMEW);
+ buffer = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
msi_reg_set_val_str(hkey, INSTALLPROPERTY_PRODUCTNAMEW, buffer);
msi_free(buffer);
- langid = msi_get_property_int(package, szProductLanguage, 0);
+ langid = msi_get_property_int(package->db, szProductLanguage, 0);
msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid);
/* FIXME */
msi_reg_set_val_dword(hkey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0);
- buffer = msi_dup_property(package, szARPProductIcon);
+ buffer = msi_dup_property(package->db, szARPProductIcon);
if (buffer)
{
LPWSTR path = build_icon_path(package,buffer);
msi_free(buffer);
}
- buffer = msi_dup_property(package, szProductVersion);
+ buffer = msi_dup_property(package->db, szProductVersion);
if (buffer)
{
DWORD verdword = msi_version_str_to_dword(buffer);
static const WCHAR szUpgradeCode[] =
{'U','p','g','r','a','d','e','C','o','d','e',0};
- upgrade = msi_dup_property(package, szUpgradeCode);
+ upgrade = msi_dup_property(package->db, szUpgradeCode);
if (!upgrade)
return ERROR_SUCCESS;
return TRUE;
}
-static UINT msi_publish_patch(MSIPACKAGE *package, HKEY prodkey, HKEY hudkey)
+static UINT msi_publish_patches( MSIPACKAGE *package, HKEY prodkey )
{
+ static const WCHAR szAllPatches[] = {'A','l','l','P','a','t','c','h','e','s',0};
WCHAR patch_squashed[GUID_SIZE];
- HKEY patches;
+ HKEY patches_key = NULL, product_patches_key;
LONG res;
- UINT r = ERROR_FUNCTION_FAILED;
+ MSIPATCHINFO *patch;
+ UINT r;
+ WCHAR *p, *all_patches = NULL;
+ DWORD len = 0;
- res = RegCreateKeyExW(prodkey, szPatches, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
- &patches, NULL);
+ res = RegCreateKeyExW( prodkey, szPatches, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &patches_key, NULL );
if (res != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
- squash_guid(package->patch->patchcode, patch_squashed);
+ r = MSIREG_OpenUserDataProductPatchesKey( package->ProductCode, package->Context, &product_patches_key, TRUE );
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
+ {
+ squash_guid( patch->patchcode, patch_squashed );
+ len += strlenW( patch_squashed ) + 1;
+ }
+
+ p = all_patches = msi_alloc( (len + 1) * sizeof(WCHAR) );
+ if (!all_patches)
+ goto done;
+
+ LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
+ {
+ HKEY patch_key;
- res = RegSetValueExW(patches, szPatches, 0, REG_MULTI_SZ,
- (const BYTE *)patch_squashed,
- (lstrlenW(patch_squashed) + 1) * sizeof(WCHAR));
+ squash_guid( patch->patchcode, p );
+ p += strlenW( p ) + 1;
+
+ res = RegSetValueExW( patches_key, patch_squashed, 0, REG_SZ,
+ (const BYTE *)patch->transforms,
+ (strlenW(patch->transforms) + 1) * sizeof(WCHAR) );
+ if (res != ERROR_SUCCESS)
+ goto done;
+
+ r = MSIREG_OpenUserDataPatchKey( patch->patchcode, package->Context, &patch_key, TRUE );
+ if (r != ERROR_SUCCESS)
+ goto done;
+
+ res = RegSetValueExW( patch_key, szLocalPackage, 0, REG_SZ,
+ (const BYTE *)patch->localfile,
+ (strlenW(patch->localfile) + 1) * sizeof(WCHAR) );
+ RegCloseKey( patch_key );
+ if (res != ERROR_SUCCESS)
+ goto done;
+
+ res = RegCreateKeyExW( product_patches_key, patch_squashed, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &patch_key, NULL );
+ RegCloseKey( patch_key );
+ if (res != ERROR_SUCCESS)
+ goto done;
+ }
+
+ all_patches[len] = 0;
+ res = RegSetValueExW( patches_key, szPatches, 0, REG_MULTI_SZ,
+ (const BYTE *)all_patches, (len + 1) * sizeof(WCHAR) );
if (res != ERROR_SUCCESS)
goto done;
- res = RegSetValueExW(patches, patch_squashed, 0, REG_SZ,
- (const BYTE *)package->patch->transforms,
- (lstrlenW(package->patch->transforms) + 1) * sizeof(WCHAR));
- if (res == ERROR_SUCCESS)
- r = ERROR_SUCCESS;
+ res = RegSetValueExW( product_patches_key, szAllPatches, 0, REG_MULTI_SZ,
+ (const BYTE *)all_patches, (len + 1) * sizeof(WCHAR) );
+ if (res != ERROR_SUCCESS)
+ r = ERROR_FUNCTION_FAILED;
done:
- RegCloseKey(patches);
+ RegCloseKey( product_patches_key );
+ RegCloseKey( patches_key );
+ msi_free( all_patches );
return r;
}
if (rc != ERROR_SUCCESS)
goto end;
- if (package->patch)
+ if (!list_empty(&package->patches))
{
- rc = msi_publish_patch(package, hukey, hudkey);
+ rc = msi_publish_patches(package, hukey);
if (rc != ERROR_SUCCESS)
goto end;
}
{
folder = resolve_folder( package, dirprop, FALSE, FALSE, TRUE, NULL );
if (!folder)
- folder = msi_dup_property( package, dirprop );
+ folder = msi_dup_property( package->db, dirprop );
}
else
- folder = msi_dup_property( package, szWindowsFolder );
+ folder = msi_dup_property( package->db, szWindowsFolder );
if (!folder)
{
CloseHandle(info.hProcess);
}
- msi_free(FullName);
-
- /* the UI chunk */
uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, filename );
uipath = strdupW( file->TargetPath );
- p = strrchrW(uipath,'\\');
- if (p)
- p[0]=0;
- MSI_RecordSetStringW( uirow, 1, &p[1] );
- MSI_RecordSetStringW( uirow, 2, uipath);
- ui_actiondata( package, szSelfRegModules, uirow);
+ if ((p = strrchrW( uipath,'\\' ))) *p = 0;
+ MSI_RecordSetStringW( uirow, 2, uipath );
+ ui_actiondata( package, szSelfRegModules, uirow );
msiobj_release( &uirow->hdr );
- msi_free( uipath );
- /* FIXME: call ui_progress? */
+ msi_free( FullName );
+ msi_free( uipath );
return ERROR_SUCCESS;
}
CloseHandle( pi.hProcess );
}
- msi_free( cmdline );
-
uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, filename );
uipath = strdupW( file->TargetPath );
- if ((p = strrchrW( uipath, '\\' )))
- {
- *p = 0;
- MSI_RecordSetStringW( uirow, 1, ++p );
- }
+ if ((p = strrchrW( uipath,'\\' ))) *p = 0;
MSI_RecordSetStringW( uirow, 2, uipath );
ui_actiondata( package, szSelfUnregModules, uirow );
msiobj_release( &uirow->hdr );
- msi_free( uipath );
- /* FIXME call ui_progress? */
+ msi_free( cmdline );
+ msi_free( uipath );
return ERROR_SUCCESS;
}
{
size += sizeof(WCHAR);
RegSetValueExW(hkey,feature->Feature,0,REG_SZ,
- (LPBYTE)(feature->Feature_Parent ? feature->Feature_Parent : szEmpty),size);
+ (const BYTE*)(feature->Feature_Parent ? feature->Feature_Parent : szEmpty),size);
}
else
{
{
UINT r;
HKEY hkey;
+ MSIRECORD *uirow;
TRACE("unpublishing feature %s\n", debugstr_w(feature->Feature));
RegCloseKey(hkey);
}
+ uirow = MSI_CreateRecord( 1 );
+ MSI_RecordSetStringW( uirow, 1, feature->Feature );
+ ui_actiondata( package, szUnpublishFeatures, uirow );
+ msiobj_release( &uirow->hdr );
+
return ERROR_SUCCESS;
}
static UINT msi_publish_install_properties(MSIPACKAGE *package, HKEY hkey)
{
- LPWSTR prop, val, key;
SYSTEMTIME systime;
DWORD size, langid;
- WCHAR date[9];
- LPWSTR buffer;
+ WCHAR date[9], *val, *buffer;
+ const WCHAR *prop, *key;
static const WCHAR date_fmt[] = {'%','i','%','0','2','i','%','0','2','i',0};
static const WCHAR szWindowsInstaller[] =
{'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
static const WCHAR szProductVersion[] =
{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
+ static const WCHAR szDisplayVersion[] =
+ {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
+ static const WCHAR szInstallSource[] =
+ {'I','n','s','t','a','l','l','S','o','u','r','c','e',0};
+ static const WCHAR szARPAUTHORIZEDCDFPREFIX[] =
+ {'A','R','P','A','U','T','H','O','R','I','Z','E','D','C','D','F','P','R','E','F','I','X',0};
+ static const WCHAR szAuthorizedCDFPrefix[] =
+ {'A','u','t','h','o','r','i','z','e','d','C','D','F','P','r','e','f','i','x',0};
+ static const WCHAR szARPCONTACT[] =
+ {'A','R','P','C','O','N','T','A','C','T',0};
+ static const WCHAR szContact[] =
+ {'C','o','n','t','a','c','t',0};
+ static const WCHAR szARPCOMMENTS[] =
+ {'A','R','P','C','O','M','M','E','N','T','S',0};
+ static const WCHAR szComments[] =
+ {'C','o','m','m','e','n','t','s',0};
static const WCHAR szProductName[] =
{'P','r','o','d','u','c','t','N','a','m','e',0};
static const WCHAR szDisplayName[] =
{'D','i','s','p','l','a','y','N','a','m','e',0};
- static const WCHAR szDisplayVersion[] =
- {'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0};
+ static const WCHAR szARPHELPLINK[] =
+ {'A','R','P','H','E','L','P','L','I','N','K',0};
+ static const WCHAR szHelpLink[] =
+ {'H','e','l','p','L','i','n','k',0};
+ static const WCHAR szARPHELPTELEPHONE[] =
+ {'A','R','P','H','E','L','P','T','E','L','E','P','H','O','N','E',0};
+ static const WCHAR szHelpTelephone[] =
+ {'H','e','l','p','T','e','l','e','p','h','o','n','e',0};
+ static const WCHAR szARPINSTALLLOCATION[] =
+ {'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0};
+ static const WCHAR szInstallLocation[] =
+ {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0};
static const WCHAR szManufacturer[] =
{'M','a','n','u','f','a','c','t','u','r','e','r',0};
-
- static const LPCSTR propval[] = {
- "ARPAUTHORIZEDCDFPREFIX", "AuthorizedCDFPrefix",
- "ARPCONTACT", "Contact",
- "ARPCOMMENTS", "Comments",
- "ProductName", "DisplayName",
- "ProductVersion", "DisplayVersion",
- "ARPHELPLINK", "HelpLink",
- "ARPHELPTELEPHONE", "HelpTelephone",
- "ARPINSTALLLOCATION", "InstallLocation",
- "SourceDir", "InstallSource",
- "Manufacturer", "Publisher",
- "ARPREADME", "Readme",
- "ARPSIZE", "Size",
- "ARPURLINFOABOUT", "URLInfoAbout",
- "ARPURLUPDATEINFO", "URLUpdateInfo",
- NULL,
+ static const WCHAR szPublisher[] =
+ {'P','u','b','l','i','s','h','e','r',0};
+ static const WCHAR szARPREADME[] =
+ {'A','R','P','R','E','A','D','M','E',0};
+ static const WCHAR szReadme[] =
+ {'R','e','a','d','M','e',0};
+ static const WCHAR szARPSIZE[] =
+ {'A','R','P','S','I','Z','E',0};
+ static const WCHAR szSize[] =
+ {'S','i','z','e',0};
+ static const WCHAR szARPURLINFOABOUT[] =
+ {'A','R','P','U','R','L','I','N','F','O','A','B','O','U','T',0};
+ static const WCHAR szURLInfoAbout[] =
+ {'U','R','L','I','n','f','o','A','b','o','u','t',0};
+ static const WCHAR szARPURLUPDATEINFO[] =
+ {'A','R','P','U','R','L','U','P','D','A','T','E','I','N','F','O',0};
+ static const WCHAR szURLUpdateInfo[] =
+ {'U','R','L','U','p','d','a','t','e','I','n','f','o',0};
+
+ static const WCHAR *propval[] = {
+ szARPAUTHORIZEDCDFPREFIX, szAuthorizedCDFPrefix,
+ szARPCONTACT, szContact,
+ szARPCOMMENTS, szComments,
+ szProductName, szDisplayName,
+ szARPHELPLINK, szHelpLink,
+ szARPHELPTELEPHONE, szHelpTelephone,
+ szARPINSTALLLOCATION, szInstallLocation,
+ cszSourceDir, szInstallSource,
+ szManufacturer, szPublisher,
+ szARPREADME, szReadme,
+ szARPSIZE, szSize,
+ szARPURLINFOABOUT, szURLInfoAbout,
+ szARPURLUPDATEINFO, szURLUpdateInfo,
+ NULL
};
- const LPCSTR *p = propval;
+ const WCHAR **p = propval;
while (*p)
{
- prop = strdupAtoW(*p++);
- key = strdupAtoW(*p++);
- val = msi_dup_property(package, prop);
+ prop = *p++;
+ key = *p++;
+ val = msi_dup_property(package->db, prop);
msi_reg_set_val_str(hkey, key, val);
msi_free(val);
- msi_free(key);
- msi_free(prop);
}
msi_reg_set_val_dword(hkey, szWindowsInstaller, 1);
/* FIXME: Write real Estimated Size when we have it */
msi_reg_set_val_dword(hkey, szEstimatedSize, 0);
- buffer = msi_dup_property(package, szProductName);
- msi_reg_set_val_str(hkey, szDisplayName, buffer);
- msi_free(buffer);
-
- buffer = msi_dup_property(package, cszSourceDir);
- msi_reg_set_val_str(hkey, INSTALLPROPERTY_INSTALLSOURCEW, buffer);
- msi_free(buffer);
-
- buffer = msi_dup_property(package, szManufacturer);
- msi_reg_set_val_str(hkey, INSTALLPROPERTY_PUBLISHERW, buffer);
- msi_free(buffer);
-
GetLocalTime(&systime);
sprintfW(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
msi_reg_set_val_str(hkey, INSTALLPROPERTY_INSTALLDATEW, date);
- langid = msi_get_property_int(package, szProductLanguage, 0);
+ langid = msi_get_property_int(package->db, szProductLanguage, 0);
msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid);
- buffer = msi_dup_property(package, szProductVersion);
+ buffer = msi_dup_property(package->db, szProductVersion);
msi_reg_set_val_str(hkey, szDisplayVersion, buffer);
if (buffer)
{
if (rc != ERROR_SUCCESS)
goto done;
- upgrade_code = msi_dup_property(package, szUpgradeCode);
+ upgrade_code = msi_dup_property(package->db, szUpgradeCode);
if (upgrade_code)
{
MSIREG_OpenUpgradeCodesKey(upgrade_code, &upgrade, TRUE);
LPWSTR *features = NULL;
BOOL full_uninstall = TRUE;
MSIFEATURE *feature;
+ MSIPATCHINFO *patch;
static const WCHAR szUpgradeCode[] =
{'U','p','g','r','a','d','e','C','o','d','e',0};
- remove = msi_dup_property(package, szRemove);
+ remove = msi_dup_property(package->db, szRemove);
if (!remove)
return ERROR_SUCCESS;
MSIREG_DeleteUserFeaturesKey(package->ProductCode);
}
- upgrade = msi_dup_property(package, szUpgradeCode);
+ upgrade = msi_dup_property(package->db, szUpgradeCode);
if (upgrade)
{
MSIREG_DeleteUserUpgradeCodesKey(upgrade);
msi_free(upgrade);
}
+ LIST_FOR_EACH_ENTRY(patch, &package->patches, MSIPATCHINFO, entry)
+ {
+ MSIREG_DeleteUserDataPatchKey(patch->patchcode, package->Context);
+ }
+
done:
msi_free(remove);
msi_free(features);
goto end;
}
- productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
+ productid = msi_dup_property( package->db, INSTALLPROPERTY_PRODUCTIDW );
if (!productid)
goto end;
for( i = 0; szPropKeys[i][0]; i++ )
{
- buffer = msi_dup_property( package, szPropKeys[i] );
+ buffer = msi_dup_property( package->db, szPropKeys[i] );
msi_reg_set_val_str( hkey, szRegKeys[i], buffer );
msi_free( buffer );
}
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
+ MSIRECORD *uirow;
SC_HANDLE scm = NULL, service = NULL;
LPCWSTR component, *vector = NULL;
- LPWSTR name, args;
- DWORD event, numargs;
+ LPWSTR name, args, display_name = NULL;
+ DWORD event, numargs, len;
UINT r = ERROR_FUNCTION_FAILED;
component = MSI_RecordGetString(rec, 6);
goto done;
}
+ len = 0;
+ if (!GetServiceDisplayNameW( scm, name, NULL, &len ) &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if ((display_name = msi_alloc( ++len * sizeof(WCHAR ))))
+ GetServiceDisplayNameW( scm, name, display_name, &len );
+ }
+
service = OpenServiceW(scm, name, SERVICE_START);
if (!service)
{
r = ERROR_SUCCESS;
done:
+ uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, display_name );
+ MSI_RecordSetStringW( uirow, 2, name );
+ ui_actiondata( package, szStartServices, uirow );
+ msiobj_release( &uirow->hdr );
+
CloseServiceHandle(service);
CloseServiceHandle(scm);
msi_free(name);
msi_free(args);
msi_free(vector);
+ msi_free(display_name);
return r;
}
{
MSIPACKAGE *package = param;
MSICOMPONENT *comp;
+ MSIRECORD *uirow;
LPCWSTR component;
- LPWSTR name;
- DWORD event;
+ LPWSTR name = NULL, display_name = NULL;
+ DWORD event, len;
+ SC_HANDLE scm;
event = MSI_RecordGetInteger( rec, 3 );
if (!(event & msidbServiceControlEventStop))
}
comp->Action = INSTALLSTATE_ABSENT;
+ scm = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
+ if (!scm)
+ {
+ ERR("Failed to open the service control manager\n");
+ goto done;
+ }
+
+ len = 0;
+ if (!GetServiceDisplayNameW( scm, name, NULL, &len ) &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if ((display_name = msi_alloc( ++len * sizeof(WCHAR ))))
+ GetServiceDisplayNameW( scm, name, display_name, &len );
+ }
+ CloseServiceHandle( scm );
+
deformat_string( package, MSI_RecordGetString( rec, 2 ), &name );
stop_service( name );
- msi_free( name );
+done:
+ uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, display_name );
+ MSI_RecordSetStringW( uirow, 2, name );
+ ui_actiondata( package, szStopServices, uirow );
+ msiobj_release( &uirow->hdr );
+
+ msi_free( name );
+ msi_free( display_name );
return ERROR_SUCCESS;
}
LPWSTR key, template, id;
UINT r = ERROR_SUCCESS;
- id = msi_dup_property( package, szProductID );
+ id = msi_dup_property( package->db, szProductID );
if (id)
{
msi_free( id );
return ERROR_SUCCESS;
}
- template = msi_dup_property( package, szPIDTemplate );
- key = msi_dup_property( package, szPIDKEY );
+ template = msi_dup_property( package->db, szPIDTemplate );
+ key = msi_dup_property( package->db, szPIDKEY );
if (key && template)
{
FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
- r = MSI_SetPropertyW( package, szProductID, key );
+ r = msi_set_property( package->db, szProductID, key );
}
msi_free( template );
msi_free( key );
static const WCHAR szAvailableFreeReg[] =
{'A','V','A','I','L','A','B','L','E','F','R','E','E','R','E','G',0};
MSIRECORD *uirow;
- int space = msi_get_property_int( package, szAvailableFreeReg, 0 );
+ int space = msi_get_property_int( package->db, szAvailableFreeReg, 0 );
TRACE("%p %d kilobytes\n", package, space);
return ERROR_SUCCESS;
}
+static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
+{
+ UINT r, count;
+ MSIQUERY *view;
+
+ static const WCHAR driver_query[] = {
+ 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ 'O','D','B','C','D','r','i','v','e','r',0 };
+
+ static const WCHAR translator_query[] = {
+ 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ 'O','D','B','C','T','r','a','n','s','l','a','t','o','r',0 };
+
+ r = MSI_DatabaseOpenViewW( package->db, driver_query, &view );
+ if (r == ERROR_SUCCESS)
+ {
+ count = 0;
+ r = MSI_IterateRecords( view, &count, NULL, package );
+ msiobj_release( &view->hdr );
+ if (count) FIXME("ignored %u rows in ODBCDriver table\n", count);
+ }
+
+ r = MSI_DatabaseOpenViewW( package->db, translator_query, &view );
+ if (r == ERROR_SUCCESS)
+ {
+ count = 0;
+ r = MSI_IterateRecords( view, &count, NULL, package );
+ msiobj_release( &view->hdr );
+ if (count) FIXME("ignored %u rows in ODBCTranslator table\n", count);
+ }
+
+ return ERROR_SUCCESS;
+}
+
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
LPCSTR action, LPCWSTR table )
{
return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table );
}
-static UINT ACTION_SetODBCFolders( MSIPACKAGE *package )
-{
- static const WCHAR table[] = { 'D','i','r','e','c','t','o','r','y',0 };
- return msi_unimplemented_action_stub( package, "SetODBCFolders", table );
-}
-
-static UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
-{
- static const WCHAR table[] = { 'A','p','p','I','d',0 };
- return msi_unimplemented_action_stub( package, "UnregisterClassInfo", table );
-}
-
-static UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
-{
- static const WCHAR table[] = { 'E','x','t','e','n','s','i','o','n',0 };
- return msi_unimplemented_action_stub( package, "UnregisterExtensionInfo", table );
-}
-
-static UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
-{
- static const WCHAR table[] = { 'M','I','M','E',0 };
- return msi_unimplemented_action_stub( package, "UnregisterMIMEInfo", table );
-}
-
-static UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
-{
- static const WCHAR table[] = { 'P','r','o','g','I','d',0 };
- return msi_unimplemented_action_stub( package, "UnregisterProgIdInfo", table );
-}
-
typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
static const struct
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
- MSI_SetPropertyW(package, szAction, szInstall);
+ msi_set_property( package->db, szAction, szInstall );
package->script->InWhatSequence = SEQUENCE_INSTALL;
msi_apply_transforms( package );
msi_apply_patches( package );
- if (!szCommandLine && msi_get_property_int( package, szInstalled, 0 ))
+ if (!szCommandLine && msi_get_property_int( package->db, szInstalled, 0 ))
{
TRACE("setting reinstall property\n");
- MSI_SetPropertyW( package, szReinstall, szAll );
+ msi_set_property( package->db, szReinstall, szAll );
}
/* properties may have been added by a transform */
'D','r','L','o','c','a','t','o','r',' ',
'w','h','e','r','e',' ',
'S','i','g','n','a','t','u','r','e','_',' ','=',' ', '\'','%','s','\'',0};
- LPWSTR parentName = NULL, parent = NULL;
+ LPWSTR parent = NULL;
+ LPCWSTR parentName;
WCHAR path[MAX_PATH];
WCHAR expanded[MAX_PATH];
MSIRECORD *row;
}
/* check whether parent is set */
- parentName = msi_dup_record_field(row,2);
+ parentName = MSI_RecordGetString(row, 2);
if (parentName)
{
MSISIGNATURE parentSig;
rc = ACTION_AppSearchSigName(package, parentName, &parentSig, &parent);
ACTION_FreeSignature(&parentSig);
- msi_free(parentName);
+ if (!parent)
+ return ERROR_SUCCESS;
}
sz = MAX_PATH;
r = ACTION_AppSearchSigName(package, sigName, &sig, &value);
if (value)
{
- MSI_SetPropertyW(package, propName, value);
+ r = msi_set_property( package->db, propName, value );
+ if (r == ERROR_SUCCESS && !strcmpW( propName, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
+
msi_free(value);
}
ACTION_FreeSignature(&sig);
MSIQUERY *view = NULL;
UINT r;
+ if (check_unique_action(package, szAppSearch))
+ {
+ TRACE("Skipping AppSearch action: already done in UI sequence\n");
+ return ERROR_SUCCESS;
+ }
+ else
+ register_unique_action(package, szAppSearch);
+
r = MSI_OpenQuery( package->db, &view, query );
if (r != ERROR_SUCCESS)
return ERROR_SUCCESS;
if (value)
{
TRACE("Found signature %s\n", debugstr_w(signature));
- MSI_SetPropertyW(package, success, szOne);
+ msi_set_property(package->db, success, szOne);
msi_free(value);
r = ERROR_NO_MORE_ITEMS;
}
MSIQUERY *view = NULL;
UINT r;
+ if (check_unique_action(package, szCCPSearch))
+ {
+ TRACE("Skipping AppSearch action: already done in UI sequence\n");
+ return ERROR_SUCCESS;
+ }
+ else
+ register_unique_action(package, szCCPSearch);
+
r = MSI_OpenQuery(package->db, &view, query);
if (r != ERROR_SUCCESS)
return ERROR_SUCCESS;
if( pUnkOuter )
return CLASS_E_NOAGGREGATION;
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AutomationObject)+sizetPrivateData);
+ object = msi_alloc_zero( sizeof(AutomationObject) + sizetPrivateData );
/* Set all the VTable references */
object->lpVtbl = &AutomationObject_Vtbl;
object->iTypeInfo = NULL;
hr = load_type_info((IDispatch *)object, &object->iTypeInfo, clsid, 0x0);
if (FAILED(hr)) {
- HeapFree(GetProcessHeap(), 0, object);
+ msi_free( object );
return hr;
}
if( pUnkOuter )
return CLASS_E_NOAGGREGATION;
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ListEnumerator));
+ object = msi_alloc_zero( sizeof(ListEnumerator) );
/* Set all the VTable references */
object->lpVtbl = &ListEnumerator_Vtbl;
if (This->funcFree) This->funcFree(This);
ITypeInfo_Release(This->iTypeInfo);
MsiCloseHandle(This->msiHandle);
- HeapFree(GetProcessHeap(), 0, This);
+ msi_free(This);
}
return ref;
if (!ref)
{
if (This->pObj) IDispatch_Release((IDispatch *)This->pObj);
- HeapFree(GetProcessHeap(), 0, This);
+ msi_free(This);
}
return ref;
for (idx=0; idx<data->ulCount; idx++)
VariantClear(&data->pVars[idx]);
- HeapFree(GetProcessHeap(), 0, data->pVars);
+ msi_free(data->pVars);
}
static HRESULT WINAPI ViewImpl_Invoke(
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/* actions handled in this module
+/* Actions handled in this module:
+ *
* RegisterClassInfo
* RegisterProgIdInfo
* RegisterExtensionInfo
* RegisterMIMEInfo
- * UnRegisterClassInfo (TODO)
- * UnRegisterProgIdInfo (TODO)
- * UnRegisterExtensionInfo (TODO)
- * UnRegisterMIMEInfo (TODO)
+ * UnregisterClassInfo
+ * UnregisterProgIdInfo
+ * UnregisterExtensionInfo
+ * UnregisterMIMEInfo
*/
#include <stdarg.h>
static MSIMIME *load_mime( MSIPACKAGE* package, MSIRECORD *row )
{
- LPCWSTR buffer;
+ LPCWSTR extension;
MSIMIME *mt;
/* fill in the data */
mt->ContentType = msi_dup_record_field( row, 1 );
TRACE("loading mime %s\n", debugstr_w(mt->ContentType));
- buffer = MSI_RecordGetString( row, 2 );
- mt->Extension = load_given_extension( package, buffer );
+ extension = MSI_RecordGetString( row, 2 );
+ mt->Extension = load_given_extension( package, extension );
+ mt->suffix = strdupW( extension );
mt->clsid = msi_dup_record_field( row, 3 );
mt->Class = load_given_class( package, mt->clsid );
}
}
+static void mark_progid_for_uninstall( MSIPACKAGE *package, MSIPROGID *progid )
+{
+ MSIPROGID *child;
+
+ if (!progid)
+ return;
+
+ if (!progid->InstallMe)
+ return;
+
+ progid->InstallMe = FALSE;
+
+ LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
+ {
+ if (child->Parent == progid)
+ mark_progid_for_uninstall( package, child );
+ }
+}
+
static void mark_mime_for_install( MSIMIME *mime )
{
if (!mime)
mime->InstallMe = TRUE;
}
+static void mark_mime_for_uninstall( MSIMIME *mime )
+{
+ if (!mime)
+ return;
+ mime->InstallMe = FALSE;
+}
+
static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
{
- static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
static const WCHAR szRemoteServerName[] =
{'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
static const WCHAR szLocalService[] =
UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
{
- /*
- * Again I am assuming the words, "Whose key file represents" when referring
- * to a Component as to meaning that Components KeyPath file
- */
-
- UINT rc;
- MSIRECORD *uirow;
- static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
- static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
- static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
- static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
+ MSIRECORD *uirow;
HKEY hkey,hkey2,hkey3;
MSICLASS *cls;
load_classes_and_such(package);
- rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
- if (rc != ERROR_SUCCESS)
+ if (RegCreateKeyW(HKEY_CLASSES_ROOT, szCLSID, &hkey) != ERROR_SUCCESS)
return ERROR_FUNCTION_FAILED;
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
if (!feature)
continue;
- /*
- * MSDN says that these are based on Feature not on Component.
- */
if (feature->ActionRequest != INSTALLSTATE_LOCAL &&
feature->ActionRequest != INSTALLSTATE_ADVERTISED )
{
- TRACE("Feature %s not scheduled for installation, skipping regstration of class %s\n",
+ TRACE("Feature %s not scheduled for installation, skipping registration of class %s\n",
debugstr_w(feature->Feature), debugstr_w(cls->clsid));
continue;
}
+ feature->Action = feature->ActionRequest;
+
+ file = get_loaded_file( package, comp->KeyPath );
+ if (!file)
+ {
+ TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
+ continue;
+ }
TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls);
msi_reg_set_val_str( hkey2, NULL, cls->Description );
RegCreateKeyW( hkey2, cls->Context, &hkey3 );
- file = get_loaded_file( package, comp->KeyPath );
- if (!file)
- {
- TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
- continue;
- }
/*
* FIXME: Implement install on demand (advertised components).
if (cls->AppID)
{
MSIAPPID *appid = cls->AppID;
-
msi_reg_set_val_str( hkey2, szAppID, appid->AppID );
-
register_appid( appid, cls->Description );
}
if (cls->IconPath)
- {
- static const WCHAR szDefaultIcon[] =
- {'D','e','f','a','u','l','t','I','c','o','n',0};
-
msi_reg_set_subkey_val( hkey2, szDefaultIcon, NULL, cls->IconPath );
- }
if (cls->DefInprocHandler)
- {
- static const WCHAR szInproc[] =
- {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
-
- msi_reg_set_subkey_val( hkey2, szInproc, NULL, cls->DefInprocHandler );
- }
+ msi_reg_set_subkey_val( hkey2, szInprocHandler, NULL, cls->DefInprocHandler );
if (cls->DefInprocHandler32)
- {
- static const WCHAR szInproc32[] =
- {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0};
-
- msi_reg_set_subkey_val( hkey2, szInproc32, NULL, cls->DefInprocHandler32 );
- }
+ msi_reg_set_subkey_val( hkey2, szInprocHandler32, NULL, cls->DefInprocHandler32 );
RegCloseKey(hkey2);
}
uirow = MSI_CreateRecord(1);
-
MSI_RecordSetStringW( uirow, 1, cls->clsid );
ui_actiondata(package,szRegisterClassInfo,uirow);
msiobj_release(&uirow->hdr);
}
RegCloseKey(hkey);
- return rc;
+ return ERROR_SUCCESS;
+}
+
+UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
+{
+ static const WCHAR szFileType[] = {'F','i','l','e','T','y','p','e','\\',0};
+ MSIRECORD *uirow;
+ MSICLASS *cls;
+ HKEY hkey, hkey2;
+
+ load_classes_and_such( package );
+ if (RegOpenKeyW( HKEY_CLASSES_ROOT, szCLSID, &hkey ) != ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
+ {
+ MSIFEATURE *feature;
+ MSICOMPONENT *comp;
+ LPWSTR filetype;
+ LONG res;
+
+ comp = cls->Component;
+ if (!comp)
+ continue;
+
+ feature = cls->Feature;
+ if (!feature)
+ continue;
+
+ if (feature->ActionRequest != INSTALLSTATE_ABSENT)
+ {
+ TRACE("Feature %s not scheduled for removal, skipping unregistration of class %s\n",
+ debugstr_w(feature->Feature), debugstr_w(cls->clsid));
+ continue;
+ }
+ feature->Action = feature->ActionRequest;
+
+ TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls);
+
+ cls->Installed = FALSE;
+ mark_progid_for_uninstall( package, cls->ProgID );
+
+ res = RegDeleteTreeW( hkey, cls->clsid );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete class key %d\n", res);
+
+ if (cls->AppID)
+ {
+ res = RegOpenKeyW( HKEY_CLASSES_ROOT, szAppID, &hkey2 );
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegDeleteKeyW( hkey2, cls->AppID->AppID );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete appid key %d\n", res);
+ RegCloseKey( hkey2 );
+ }
+ }
+ if (cls->FileTypeMask)
+ {
+ filetype = msi_alloc( (strlenW( szFileType ) + strlenW( cls->clsid ) + 1) * sizeof(WCHAR) );
+ if (filetype)
+ {
+ strcpyW( filetype, szFileType );
+ strcatW( filetype, cls->clsid );
+ res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
+ msi_free( filetype );
+
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete file type %d\n", res);
+ }
+ }
+
+ uirow = MSI_CreateRecord( 1 );
+ MSI_RecordSetStringW( uirow, 1, cls->clsid );
+ ui_actiondata( package, szUnregisterClassInfo, uirow );
+ msiobj_release( &uirow->hdr );
+ }
+
+ RegCloseKey( hkey );
+ return ERROR_SUCCESS;
}
static LPCWSTR get_clsid_of_progid( const MSIPROGID *progid )
static UINT register_progid( const MSIPROGID* progid )
{
- static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
- static const WCHAR szDefaultIcon[] =
- {'D','e','f','a','u','l','t','I','c','o','n',0};
- static const WCHAR szCurVer[] =
- {'C','u','r','V','e','r',0};
+ static const WCHAR szCurVer[] = {'C','u','r','V','e','r',0};
HKEY hkey = 0;
UINT rc;
return ERROR_SUCCESS;
}
+UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
+{
+ MSIPROGID *progid;
+ MSIRECORD *uirow;
+ LONG res;
+
+ load_classes_and_such( package );
+
+ LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
+ {
+ /* check if this progid is to be removed */
+ if (progid->Class && !progid->Class->Installed)
+ progid->InstallMe = FALSE;
+
+ if (progid->InstallMe)
+ {
+ TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID));
+ continue;
+ }
+
+ TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
+
+ res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete progid key %d\n", res);
+
+ uirow = MSI_CreateRecord( 1 );
+ MSI_RecordSetStringW( uirow, 1, progid->ProgID );
+ ui_actiondata( package, szUnregisterProgIdInfo, uirow );
+ msiobj_release( &uirow->hdr );
+ }
+
+ return ERROR_SUCCESS;
+}
+
static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
MSICOMPONENT* component, const MSIEXTENSION* extension,
MSIVERB* verb, INT* Sequence )
{
static const WCHAR szContentType[] =
{'C','o','n','t','e','n','t',' ','T','y','p','e',0 };
- HKEY hkey;
+ HKEY hkey = NULL;
MSIEXTENSION *ext;
MSIRECORD *uirow;
BOOL install_on_demand = TRUE;
+ LONG res;
load_classes_and_such(package);
debugstr_w(feature->Feature), debugstr_w(ext->Extension));
continue;
}
+ feature->Action = feature->ActionRequest;
TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext);
mark_mime_for_install(ext->Mime);
- extension = msi_alloc( (lstrlenW( ext->Extension ) + 2)*sizeof(WCHAR) );
- extension[0] = '.';
- lstrcpyW(extension+1,ext->Extension);
-
- RegCreateKeyW(HKEY_CLASSES_ROOT,extension,&hkey);
- msi_free( extension );
+ extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
+ if (extension)
+ {
+ extension[0] = '.';
+ strcpyW( extension + 1, ext->Extension );
+ res = RegCreateKeyW( HKEY_CLASSES_ROOT, extension, &hkey );
+ msi_free( extension );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to create extension key %d\n", res);
+ }
if (ext->Mime)
msi_reg_set_val_str( hkey, szContentType, ext->Mime->ContentType );
return ERROR_SUCCESS;
}
+UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
+{
+ MSIEXTENSION *ext;
+ MSIRECORD *uirow;
+ LONG res;
+
+ load_classes_and_such( package );
+
+ LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
+ {
+ LPWSTR extension;
+ MSIFEATURE *feature;
+
+ if (!ext->Component)
+ continue;
+
+ feature = ext->Feature;
+ if (!feature)
+ continue;
+
+ if (feature->ActionRequest != INSTALLSTATE_ABSENT)
+ {
+ TRACE("Feature %s not scheduled for removal, skipping unregistration of extension %s\n",
+ debugstr_w(feature->Feature), debugstr_w(ext->Extension));
+ continue;
+ }
+
+ TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension));
+
+ ext->Installed = FALSE;
+
+ if (ext->ProgID && !list_empty( &ext->verbs ))
+ mark_progid_for_uninstall( package, ext->ProgID );
+
+ mark_mime_for_uninstall( ext->Mime );
+
+ extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
+ if (extension)
+ {
+ extension[0] = '.';
+ strcpyW( extension + 1, ext->Extension );
+ res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
+ msi_free( extension );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete extension key %d\n", res);
+ }
+
+ if (ext->ProgID || ext->ProgIDText)
+ {
+ static const WCHAR shellW[] = {'\\','s','h','e','l','l',0};
+ LPCWSTR progid;
+ LPWSTR progid_shell;
+
+ if (ext->ProgID)
+ progid = ext->ProgID->ProgID;
+ else
+ progid = ext->ProgIDText;
+
+ progid_shell = msi_alloc( (strlenW( progid ) + strlenW( shellW ) + 1) * sizeof(WCHAR) );
+ if (progid_shell)
+ {
+ strcpyW( progid_shell, progid );
+ strcatW( progid_shell, shellW );
+ res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
+ msi_free( progid_shell );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete shell key %d\n", res);
+ RegDeleteKeyW( HKEY_CLASSES_ROOT, progid );
+ }
+ }
+
+ uirow = MSI_CreateRecord( 1 );
+ MSI_RecordSetStringW( uirow, 1, ext->Extension );
+ ui_actiondata( package, szUnregisterExtensionInfo, uirow );
+ msiobj_release( &uirow->hdr );
+ }
+
+ return ERROR_SUCCESS;
+}
+
UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
{
static const WCHAR szExten[] =
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
{
LPWSTR extension;
- LPCWSTR exten;
- LPCWSTR mime;
- static const WCHAR fmt[] =
- {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\',
- 'C','o','n','t','e','n','t',' ','T','y','p','e','\\', '%','s',0};
LPWSTR key;
/*
if (!mt->InstallMe)
{
- TRACE("MIME %s not scheduled to be installed\n",
- debugstr_w(mt->ContentType));
+ TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType));
continue;
}
-
- mime = mt->ContentType;
- exten = mt->Extension->Extension;
- extension = msi_alloc( (lstrlenW( exten ) + 2)*sizeof(WCHAR) );
- extension[0] = '.';
- lstrcpyW(extension+1,exten);
+ TRACE("Registering MIME type %s\n", debugstr_w(mt->ContentType));
+
+ extension = msi_alloc( (strlenW( mt->Extension->Extension ) + 2) * sizeof(WCHAR) );
+ key = msi_alloc( (strlenW( mt->ContentType ) + strlenW( szMIMEDatabase ) + 1) * sizeof(WCHAR) );
- key = msi_alloc( (strlenW(mime)+strlenW(fmt)+1) * sizeof(WCHAR) );
- sprintfW(key,fmt,mime);
- msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szExten, extension );
+ if (extension && key)
+ {
+ extension[0] = '.';
+ strcpyW( extension + 1, mt->Extension->Extension );
- msi_free(extension);
- msi_free(key);
+ strcpyW( key, szMIMEDatabase );
+ strcatW( key, mt->ContentType );
+ msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szExten, extension );
- if (mt->clsid)
- FIXME("Handle non null for field 3\n");
+ if (mt->clsid)
+ msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szCLSID, mt->clsid );
+ }
+ msi_free( extension );
+ msi_free( key );
- uirow = MSI_CreateRecord(2);
- MSI_RecordSetStringW(uirow,1,mt->ContentType);
- MSI_RecordSetStringW(uirow,2,exten);
- ui_actiondata(package,szRegisterMIMEInfo,uirow);
- msiobj_release(&uirow->hdr);
+ uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, mt->ContentType );
+ MSI_RecordSetStringW( uirow, 2, mt->suffix );
+ ui_actiondata( package, szRegisterMIMEInfo, uirow );
+ msiobj_release( &uirow->hdr );
+ }
+
+ return ERROR_SUCCESS;
+}
+
+UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
+{
+ MSIRECORD *uirow;
+ MSIMIME *mime;
+
+ load_classes_and_such( package );
+
+ LIST_FOR_EACH_ENTRY( mime, &package->mimes, MSIMIME, entry )
+ {
+ LONG res;
+ LPWSTR mime_key;
+
+ mime->InstallMe = (mime->InstallMe ||
+ (mime->Class && mime->Class->Installed) ||
+ (mime->Extension && mime->Extension->Installed));
+
+ if (mime->InstallMe)
+ {
+ TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType));
+ continue;
+ }
+
+ TRACE("Unregistering MIME type %s\n", debugstr_w(mime->ContentType));
+
+ mime_key = msi_alloc( (strlenW( szMIMEDatabase ) + strlenW( mime->ContentType ) + 1) * sizeof(WCHAR) );
+ if (mime_key)
+ {
+ strcpyW( mime_key, szMIMEDatabase );
+ strcatW( mime_key, mime->ContentType );
+ res = RegDeleteKeyW( HKEY_CLASSES_ROOT, mime_key );
+ if (res != ERROR_SUCCESS)
+ WARN("Failed to delete MIME key %d\n", res);
+ msi_free( mime_key );
+ }
+
+ uirow = MSI_CreateRecord( 2 );
+ MSI_RecordSetStringW( uirow, 1, mime->ContentType );
+ MSI_RecordSetStringW( uirow, 2, mime->suffix );
+ ui_actiondata( package, szUnregisterMIMEInfo, uirow );
+ msiobj_release( &uirow->hdr );
}
return ERROR_SUCCESS;
COND_input* cond = (COND_input*) info;
UINT len;
- (yyval.string) = msi_dup_property( cond->package, (yyvsp[(1) - (1)].string) );
+ (yyval.string) = msi_dup_property( cond->package->db, (yyvsp[(1) - (1)].string) );
if ((yyval.string))
{
len = (lstrlenW((yyval.string)) + 1) * sizeof (WCHAR);
COND_input* cond = (COND_input*) info;
UINT len;
- $$ = msi_dup_property( cond->package, $1 );
+ $$ = msi_dup_property( cond->package->db, $1 );
if ($$)
{
len = (lstrlenW($$) + 1) * sizeof (WCHAR);
end = strstrW(beg, sep);
*end = '\0';
- MSI_SetPropertyW(package, szCustomActionData, beg);
+ msi_set_property(package->db, szCustomActionData, beg);
beg = end + 3;
end = strstrW(beg, sep);
*end = '\0';
- MSI_SetPropertyW(package, szUserSID, beg);
+ msi_set_property(package->db, szUserSID, beg);
beg = end + 3;
end = strchrW(beg, ']');
*end = '\0';
- MSI_SetPropertyW(package, szProductCode, beg);
+ msi_set_property(package->db, szProductCode, beg);
}
UINT ACTION_CustomAction(MSIPACKAGE *package, LPCWSTR action, UINT script, BOOL execute)
}
if (!execute)
{
- LPWSTR actiondata = msi_dup_property(package, action);
- LPWSTR usersid = msi_dup_property(package, szUserSID);
- LPWSTR prodcode = msi_dup_property(package, szProductCode);
+ LPWSTR actiondata = msi_dup_property(package->db, action);
+ LPWSTR usersid = msi_dup_property(package->db, szUserSID);
+ LPWSTR prodcode = msi_dup_property(package->db, szProductCode);
LPWSTR deferred = msi_get_deferred_action(action, actiondata, usersid, prodcode);
if (type & msidbCustomActionTypeCommit)
}
else
{
- LPWSTR actiondata = msi_dup_property( package, action );
+ LPWSTR actiondata = msi_dup_property( package->db, action );
switch (script)
{
if (deferred_data)
set_deferred_action_props(package, deferred_data);
else if (actiondata)
- MSI_SetPropertyW(package, szCustomActionData, actiondata);
+ msi_set_property(package->db, szCustomActionData, actiondata);
else
- MSI_SetPropertyW(package, szCustomActionData, szEmpty);
+ msi_set_property(package->db, szCustomActionData, szEmpty);
msi_free(actiondata);
}
break;
deformat_string(package,target,&deformated);
- rc = MSI_SetPropertyW(package,source,deformated);
+ rc = msi_set_property( package->db, source, deformated );
+ if (rc == ERROR_SUCCESS && !strcmpW( source, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
msi_free(deformated);
break;
case 37: /* JScript/VBScript text stored in target column. */
DWORD sz = MAX_PATH;
UINT r;
- if (MSI_GetPropertyW(package, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
+ if (msi_get_property(package->db, cszTempFolder, fmt, &sz) != ERROR_SUCCESS)
GetTempPathW(MAX_PATH, fmt);
if (GetTempFileNameW(fmt, szMsi, 0, tmp_file) == 0)
UINT r;
size = MAX_PATH;
- MSI_GetPropertyW(package, cszSourceDir, package_path, &size);
+ msi_get_property(package->db, cszSourceDir, package_path, &size);
lstrcatW(package_path, szBackSlash);
lstrcatW(package_path, source);
memset(&si,0,sizeof(STARTUPINFOW));
memset(&info,0,sizeof(PROCESS_INFORMATION));
- prop = msi_dup_property( package, source );
+ prop = msi_dup_property( package->db, source );
if (!prop)
return ERROR_SUCCESS;
TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
- prop = msi_dup_property(package,source);
+ prop = msi_dup_property( package->db, source );
if (!prop)
return ERROR_SUCCESS;
EnterCriticalSection( &msi_custom_action_cs );
handle_count = list_count( &msi_pending_custom_actions );
- wait_handles = HeapAlloc( GetProcessHeap(), 0, handle_count * sizeof(HANDLE) );
+ wait_handles = msi_alloc( handle_count * sizeof(HANDLE) );
handle_count = 0;
LIST_FOR_EACH_ENTRY_SAFE( info, cursor, &msi_pending_custom_actions, msi_custom_action_info, entry )
CloseHandle( wait_handles[i] );
}
- HeapFree( GetProcessHeap(), 0, wait_handles );
+ msi_free( wait_handles );
}
typedef struct _msi_custom_remote_impl {
return SUCCEEDED(r) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
}
-UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
- USHORT **pdata, UINT *psz )
-{
- HRESULT r;
- UINT ret = ERROR_FUNCTION_FAILED;
- VOID *data;
- ULONG sz, count;
- IStream *stm = NULL;
- STATSTG stat;
- LPWSTR encname;
-
- encname = encode_streamname( FALSE, stname );
- r = db_get_raw_stream( db, encname, &stm );
- msi_free( encname );
-
- if( r != ERROR_SUCCESS)
- return ret;
-
- r = IStream_Stat(stm, &stat, STATFLAG_NONAME );
- if( FAILED( r ) )
- {
- WARN("open stream failed r = %08x!\n", r);
- goto end;
- }
-
- if( stat.cbSize.QuadPart >> 32 )
- {
- WARN("Too big!\n");
- goto end;
- }
-
- sz = stat.cbSize.QuadPart;
- data = msi_alloc( sz );
- if( !data )
- {
- WARN("couldn't allocate memory r=%08x!\n", r);
- ret = ERROR_NOT_ENOUGH_MEMORY;
- goto end;
- }
-
- r = IStream_Read(stm, data, sz, &count );
- if( FAILED( r ) || ( count != sz ) )
- {
- msi_free( data );
- WARN("read stream failed r = %08x!\n", r);
- goto end;
- }
-
- *pdata = data;
- *psz = sz;
- ret = ERROR_SUCCESS;
-
-end:
- IStream_Release( stm );
-
- return ret;
-}
-
static void free_transforms( MSIDATABASE *db )
{
while( !list_empty( &db->transforms ) )
}
}
+void db_destroy_stream( MSIDATABASE *db, LPCWSTR stname )
+{
+ MSISTREAM *stream, *stream2;
+
+ LIST_FOR_EACH_ENTRY_SAFE( stream, stream2, &db->streams, MSISTREAM, entry )
+ {
+ HRESULT r;
+ STATSTG stat;
+
+ r = IStream_Stat( stream->stm, &stat, 0 );
+ if (FAILED(r))
+ {
+ WARN("failed to stat stream r = %08x\n", r);
+ continue;
+ }
+
+ if (!strcmpW( stname, stat.pwcsName ))
+ {
+ TRACE("destroying %s\n", debugstr_w(stname));
+
+ list_remove( &stream->entry );
+ IStream_Release( stream->stm );
+ msi_free( stream );
+ IStorage_DestroyElement( db->storage, stname );
+ CoTaskMemFree( stat.pwcsName );
+ break;
+ }
+ CoTaskMemFree( stat.pwcsName );
+ }
+}
+
static void free_streams( MSIDATABASE *db )
{
while( !list_empty( &db->streams ) )
UINT ret = ERROR_FUNCTION_FAILED;
LPCWSTR szMode, save_path;
STATSTG stat;
- BOOL created = FALSE;
+ BOOL created = FALSE, patch = FALSE;
WCHAR path[MAX_PATH];
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
{
TRACE("Database is a patch\n");
szPersist -= MSIDBOPEN_PATCHFILE;
+ patch = TRUE;
}
save_path = szDBPath;
STGM_CREATE|STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, &stg);
if( r == ERROR_SUCCESS )
{
- IStorage_SetClass( stg, &CLSID_MsiDatabase );
+ IStorage_SetClass( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
/* create the _Tables stream */
r = write_stream_data(stg, szTables, NULL, 0, TRUE);
if (SUCCEEDED(r))
goto end;
}
+ if ( patch && !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) )
+ {
+ ERR("storage GUID is not the MSI patch GUID %s\n",
+ debugstr_guid(&stat.clsid) );
+ ret = ERROR_OPEN_FAILED;
+ goto end;
+ }
+
db = alloc_msiobject( MSIHANDLETYPE_DATABASE, sizeof (MSIDATABASE),
MSI_CloseDatabase );
if( !db )
static DWORD uiThreadId;
static HWND hMsiHiddenWindow;
+static LPWSTR msi_get_window_text( HWND hwnd );
+
static INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
{
return MulDiv( val, dialog->scale, 12 );
return NULL;
if (indirect)
- prop = msi_dup_property( dialog->package, property );
+ prop = msi_dup_property( dialog->package->db, property );
if (!prop)
prop = strdupW( property );
}
}
+static void msi_dialog_set_property( MSIPACKAGE *package, LPCWSTR property, LPCWSTR value )
+{
+ UINT r = msi_set_property( package->db, property, value );
+ if (r == ERROR_SUCCESS && !strcmpW( property, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
+}
+
/* called from the Control Event subscription code */
void msi_dialog_handle_event( msi_dialog* dialog, LPCWSTR control,
LPCWSTR attribute, MSIRECORD *rec )
else if ( !lstrcmpW(attribute, szProperty) )
{
MSIFEATURE *feature = msi_seltree_get_selected_feature( ctrl );
- MSI_SetPropertyW( dialog->package, ctrl->property, feature->Directory );
+ msi_dialog_set_property( dialog->package, ctrl->property, feature->Directory );
}
else if ( !lstrcmpW(attribute, szSelectionPath) )
{
LPWSTR prop = msi_dialog_dup_property( dialog, ctrl->property, TRUE );
LPWSTR path;
if (!prop) return;
- path = msi_dup_property( dialog->package, prop );
+ path = msi_dup_property( dialog->package->db, prop );
SetWindowTextW( ctrl->hwnd, path );
msi_free(prop);
msi_free(path);
if (ret)
return ret;
- ret = msi_dup_property( dialog->package, prop );
+ ret = msi_dup_property( dialog->package->db, prop );
if( ret && !ret[0] )
{
msi_free( ret );
return ERROR_SUCCESS;
}
+/******************** Combo Box ***************************************/
+
+struct msi_combobox_info
+{
+ msi_dialog *dialog;
+ HWND hwnd;
+ WNDPROC oldproc;
+ DWORD num_items;
+ DWORD addpos_items;
+ LPWSTR *items;
+};
+
+static LRESULT WINAPI MSIComboBox_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct msi_combobox_info *info;
+ LRESULT r;
+ DWORD j;
+
+ TRACE("%p %04x %08lx %08lx\n", hWnd, msg, wParam, lParam);
+
+ info = GetPropW( hWnd, szButtonData );
+ if (!info)
+ return 0;
+
+ r = CallWindowProcW( info->oldproc, hWnd, msg, wParam, lParam );
+
+ switch (msg)
+ {
+ case WM_NCDESTROY:
+ for (j = 0; j < info->num_items; j++)
+ msi_free( info->items[j] );
+ msi_free( info->items );
+ msi_free( info );
+ RemovePropW( hWnd, szButtonData );
+ break;
+ }
+
+ return r;
+}
+
+static UINT msi_combobox_add_item( MSIRECORD *rec, LPVOID param )
+{
+ struct msi_combobox_info *info = param;
+ LPCWSTR value, text;
+ int pos;
+
+ value = MSI_RecordGetString( rec, 3 );
+ text = MSI_RecordGetString( rec, 4 );
+
+ info->items[info->addpos_items] = strdupW( value );
+
+ pos = SendMessageW( info->hwnd, CB_ADDSTRING, 0, (LPARAM)text );
+ SendMessageW( info->hwnd, CB_SETITEMDATA, pos, (LPARAM)info->items[info->addpos_items] );
+ info->addpos_items++;
+
+ return ERROR_SUCCESS;
+}
+
+static UINT msi_combobox_add_items( struct msi_combobox_info *info, LPCWSTR property )
+{
+ UINT r;
+ MSIQUERY *view = NULL;
+ DWORD count;
+
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','*',' ',
+ 'F','R','O','M',' ','`','C','o','m','b','o','B','o','x','`',' ',
+ 'W','H','E','R','E',' ',
+ '`','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',' ',
+ 'O','R','D','E','R',' ','B','Y',' ','`','O','r','d','e','r','`',0
+ };
+
+ r = MSI_OpenQuery( info->dialog->package->db, &view, query, property );
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ /* just get the number of records */
+ count = 0;
+ r = MSI_IterateRecords( view, &count, NULL, NULL );
+
+ info->num_items = count;
+ info->items = msi_alloc( sizeof(*info->items) * count );
+
+ r = MSI_IterateRecords( view, NULL, msi_combobox_add_item, info );
+ msiobj_release( &view->hdr );
+
+ return r;
+}
+
+static UINT msi_dialog_combobox_handler( msi_dialog *dialog,
+ msi_control *control, WPARAM param )
+{
+ struct msi_combobox_info *info;
+ int index;
+ LPWSTR value;
+
+ if (HIWORD(param) != CBN_SELCHANGE && HIWORD(param) != CBN_EDITCHANGE)
+ return ERROR_SUCCESS;
+
+ info = GetPropW( control->hwnd, szButtonData );
+ index = SendMessageW( control->hwnd, CB_GETCURSEL, 0, 0 );
+ if (index == CB_ERR)
+ value = msi_get_window_text( control->hwnd );
+ else
+ value = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, index, 0 );
+
+ msi_dialog_set_property( info->dialog->package, control->property, value );
+ msi_dialog_evaluate_control_conditions( info->dialog );
+
+ if (index == CB_ERR)
+ msi_free( value );
+
+ return ERROR_SUCCESS;
+}
+
+static void msi_dialog_combobox_update( msi_dialog *dialog,
+ msi_control *control )
+{
+ struct msi_combobox_info *info;
+ LPWSTR value, tmp;
+ DWORD j;
+
+ info = GetPropW( control->hwnd, szButtonData );
+
+ value = msi_dup_property( dialog->package->db, control->property );
+ if (!value)
+ {
+ SendMessageW( control->hwnd, CB_SETCURSEL, -1, 0 );
+ return;
+ }
+
+ for (j = 0; j < info->num_items; j++)
+ {
+ tmp = (LPWSTR) SendMessageW( control->hwnd, CB_GETITEMDATA, j, 0 );
+ if (!lstrcmpW( value, tmp ))
+ break;
+ }
+
+ if (j < info->num_items)
+ {
+ SendMessageW( control->hwnd, CB_SETCURSEL, j, 0 );
+ }
+ else
+ {
+ SendMessageW( control->hwnd, CB_SETCURSEL, -1, 0 );
+ SetWindowTextW( control->hwnd, value );
+ }
+
+ msi_free(value);
+}
+
static UINT msi_dialog_combo_control( msi_dialog *dialog, MSIRECORD *rec )
{
- static const WCHAR szCombo[] = { 'C','O','M','B','O','B','O','X',0 };
+ struct msi_combobox_info *info;
+ msi_control *control;
DWORD attributes, style;
+ LPCWSTR prop;
+
+ info = msi_alloc( sizeof *info );
+ if (!info)
+ return ERROR_FUNCTION_FAILED;
style = CBS_AUTOHSCROLL | WS_TABSTOP | WS_GROUP | WS_CHILD;
attributes = MSI_RecordGetInteger( rec, 8 );
else
style |= CBS_DROPDOWN;
- msi_dialog_add_control( dialog, rec, szCombo, style );
+ control = msi_dialog_add_control( dialog, rec, WC_COMBOBOXW, style );
+ if (!control)
+ {
+ msi_free( info );
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ control->handler = msi_dialog_combobox_handler;
+ control->update = msi_dialog_combobox_update;
+
+ prop = MSI_RecordGetString( rec, 9 );
+ control->property = msi_dialog_dup_property( dialog, prop, FALSE );
+
+ /* subclass */
+ info->dialog = dialog;
+ info->hwnd = control->hwnd;
+ info->items = NULL;
+ info->addpos_items = 0;
+ info->oldproc = (WNDPROC)SetWindowLongPtrW( control->hwnd, GWLP_WNDPROC,
+ (LONG_PTR)MSIComboBox_WndProc );
+ SetPropW( control->hwnd, szButtonData, info );
+
+ if (control->property)
+ msi_combobox_add_items( info, control->property );
+
+ msi_dialog_combobox_update( dialog, control );
+
return ERROR_SUCCESS;
}
if( prop )
control->property = strdupW( prop );
- val = msi_dup_property( dialog->package, control->property );
+ val = msi_dup_property( dialog->package->db, control->property );
SetWindowTextW( control->hwnd, val );
msi_free( val );
return ERROR_SUCCESS;
if( i == info->num_groups )
{
- TRACE("Set property %s to %s\n",
- debugstr_w(info->prop), debugstr_w(val) );
+ TRACE("Set property %s to %s\n", debugstr_w(info->prop), debugstr_w(val));
CharUpperBuffW( val, info->num_chars );
- MSI_SetPropertyW( info->dialog->package, info->prop, val );
+ msi_dialog_set_property( info->dialog->package, info->prop, val );
msi_dialog_evaluate_control_conditions( info->dialog );
}
msi_free( val );
if( prop )
{
- val = msi_dup_property( dialog->package, prop );
+ val = msi_dup_property( dialog->package->db, prop );
if( val )
{
msi_maskedit_set_text( info, val );
else
{
valid = TRUE;
- MSI_SetPropertyW( dialog->package, prop, buf );
+ msi_dialog_set_property( dialog->package, prop, buf );
}
msi_dialog_update_pathedit( dialog, control );
group.dialog = dialog;
group.parent = control;
group.attributes = MSI_RecordGetInteger( rec, 8 );
- group.propval = msi_dup_property( dialog->package, control->property );
+ group.propval = msi_dup_property( dialog->package->db, control->property );
r = MSI_IterateRecords( view, 0, msi_dialog_create_radiobutton, &group );
msiobj_release( &view->hdr );
index = SendMessageW( control->hwnd, LB_GETCURSEL, 0, 0 );
value = (LPCWSTR) SendMessageW( control->hwnd, LB_GETITEMDATA, index, 0 );
- MSI_SetPropertyW( info->dialog->package,
- control->property, value );
+ msi_dialog_set_property( info->dialog->package, control->property, value );
msi_dialog_evaluate_control_conditions( info->dialog );
return ERROR_SUCCESS;
if (ptr != path) *(ptr - 1) = '\0';
PathAddBackslashW( path );
- MSI_SetPropertyW( dialog->package, prop, path );
+ msi_dialog_set_property( dialog->package, prop, path );
msi_dialog_update_directory_list( dialog, NULL );
msi_dialog_update_directory_combo( dialog, NULL );
lstrcatW( new_path, text );
lstrcatW( new_path, szBackSlash );
- MSI_SetPropertyW( dialog->package, prop, new_path );
+ msi_dialog_set_property( dialog->package, prop, new_path );
msi_dialog_update_directory_list( dialog, NULL );
msi_dialog_update_directory_combo( dialog, NULL );
indirect = control->attributes & msidbControlAttributesIndirect;
prop = msi_dialog_dup_property( dialog, control->property, indirect );
- MSI_SetPropertyW( dialog->package, prop, text );
+ msi_dialog_set_property( dialog->package, prop, text );
msi_free( prop );
return ERROR_SUCCESS;
sz.cx = msi_dialog_scale_unit( dialog, sz.cx );
sz.cy = msi_dialog_scale_unit( dialog, sz.cy );
- xres = msi_get_property_int( dialog->package, szScreenX, 0 );
- yres = msi_get_property_int( dialog->package, szScreenY, 0 );
+ xres = msi_get_property_int( dialog->package->db, szScreenX, 0 );
+ yres = msi_get_property_int( dialog->package->db, szScreenY, 0 );
center.x = MulDiv( center.x, xres, 100 );
center.y = MulDiv( center.y, yres, 100 );
dialog->attributes = MSI_RecordGetInteger( rec, 6 );
- dialog->default_font = msi_dup_property( dialog->package, df );
+ dialog->default_font = msi_dup_property( dialog->package->db, df );
if (!dialog->default_font)
{
dialog->default_font = strdupW(dfv);
return ERROR_SUCCESS;
}
-static UINT msi_dialog_set_property( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg )
+static UINT msi_dialog_set_property_event( msi_dialog *dialog, LPCWSTR event, LPCWSTR arg )
{
static const WCHAR szNullArg[] = { '{','}',0 };
LPWSTR p, prop, arg_fmt = NULL;
*p = 0;
if( strcmpW( szNullArg, arg ) )
deformat_string( dialog->package, arg, &arg_fmt );
- MSI_SetPropertyW( dialog->package, prop, arg_fmt );
+ msi_dialog_set_property( dialog->package, prop, arg_fmt );
msi_dialog_update_controls( dialog, prop );
msi_free( arg_fmt );
}
event = MSI_RecordGetString( rec, 3 );
arg = MSI_RecordGetString( rec, 4 );
if( event[0] == '[' )
- msi_dialog_set_property( dialog, event, arg );
+ msi_dialog_set_property_event( dialog, event, arg );
else
msi_dialog_send_event( dialog, event, arg );
}
WCHAR state[2] = { 0 };
DWORD sz = 2;
- MSI_GetPropertyW( dialog->package, control->property, state, &sz );
+ msi_get_property( dialog->package->db, control->property, state, &sz );
return state[0] ? 1 : 0;
}
/* if uncheck then the property is set to NULL */
if (!state)
{
- MSI_SetPropertyW( dialog->package, control->property, NULL );
+ msi_dialog_set_property( dialog->package, control->property, NULL );
return;
}
else
val = szState;
- MSI_SetPropertyW( dialog->package, control->property, val );
+ msi_dialog_set_property( dialog->package, control->property, val );
}
static void msi_dialog_checkbox_sync_state( msi_dialog *dialog,
debugstr_w(control->property));
buf = msi_get_window_text( control->hwnd );
- MSI_SetPropertyW( dialog->package, control->property, buf );
-
+ msi_dialog_set_property( dialog->package, control->property, buf );
msi_free( buf );
return ERROR_SUCCESS;
TRACE("clicked radio button %s, set %s\n", debugstr_w(control->name),
debugstr_w(control->property));
- MSI_SetPropertyW( dialog->package, control->property, control->name );
+ msi_dialog_set_property( dialog->package, control->property, control->name );
return msi_dialog_button_handler( dialog, control, param );
}
if ( !lstrcmpW( argument, error_abort ) || !lstrcmpW( argument, error_cancel ) ||
!lstrcmpW( argument, error_no ) )
{
- MSI_SetPropertyW( package, result_prop, error_abort );
+ msi_set_property( package->db, result_prop, error_abort );
}
ControlEvent_CleanupSubscriptions(package);
'M','S','I','E','r','r','o','r','D','i','a','l','o','g','R','e','s','u','l','t',0
};
- if ( (msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE )
+ if ( (msi_get_property_int( package->db, szUILevel, 0 ) & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE )
return ERROR_SUCCESS;
if ( !error_dialog )
{
- LPWSTR product_name = msi_dup_property( package, pn_prop );
+ LPWSTR product_name = msi_dup_property( package->db, pn_prop );
WCHAR title[MAX_PATH];
sprintfW( title, title_fmt, product_name );
if ( r != ERROR_SUCCESS )
goto done;
- r = MSI_GetPropertyW( package, result_prop, result, &size );
+ r = msi_get_property( package->db, result_prop, result, &size );
if ( r != ERROR_SUCCESS)
r = ERROR_SUCCESS;
static UINT ControlEvent_SetTargetPath(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog)
{
- LPWSTR path = msi_dup_property( package, argument );
+ LPWSTR path = msi_dup_property( package->db, argument );
MSIRECORD *rec = MSI_CreateRecord( 1 );
UINT r;
static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument,
msi_dialog *dialog)
{
- return MSI_SetPropertyW( package, szReinstallMode, argument );
+ return msi_set_property( package->db, szReinstallMode, argument );
+}
+
+static UINT ControlEvent_Reinstall( MSIPACKAGE *package, LPCWSTR argument,
+ msi_dialog *dialog )
+{
+ return msi_set_property( package->db, szReinstall, argument );
}
static UINT ControlEvent_ValidateProductID(MSIPACKAGE *package, LPCWSTR argument,
LPWSTR key, template;
UINT ret = ERROR_SUCCESS;
- template = msi_dup_property( package, szPIDTemplate );
- key = msi_dup_property( package, szPIDKEY );
+ template = msi_dup_property( package->db, szPIDTemplate );
+ key = msi_dup_property( package->db, szPIDKEY );
if (key && template)
{
FIXME( "partial stub: template %s key %s\n", debugstr_w(template), debugstr_w(key) );
- ret = MSI_SetPropertyW( package, szProductID, key );
+ ret = msi_set_property( package->db, szProductID, key );
}
msi_free( template );
msi_free( key );
{ "DirectoryListUp",ControlEvent_DirectoryListUp },
{ "SelectionBrowse",ControlEvent_SpawnDialog },
{ "ReinstallMode",ControlEvent_ReinstallMode },
+ { "Reinstall",ControlEvent_Reinstall },
{ "ValidateProductID",ControlEvent_ValidateProductID },
{ NULL,NULL },
};
ui_progress(package,2,file->FileSize,0,0);
file->state = msifs_skipped;
}
+ else
+ file->Component->Action = INSTALLSTATE_LOCAL;
}
}
{
UINT gle;
- TRACE("Copying %s to %s\n", debugstr_w(source),
- debugstr_w(file->TargetPath));
+ TRACE("Copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
gle = copy_file(file, source);
if (gle == ERROR_SUCCESS)
GetTempFileNameW(szBackSlash, szMsi, 0, tmpfileW);
len = strlenW(file->TargetPath) + strlenW(tmpfileW) + 1;
- if (!(pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
+ if (!(pathW = msi_alloc(len * sizeof(WCHAR))))
return ERROR_OUTOFMEMORY;
strcpyW(pathW, file->TargetPath);
gle = GetLastError();
WARN("failed to schedule rename operation: %d)\n", gle);
}
- HeapFree(GetProcessHeap(), 0, pathW);
+ msi_free(pathW);
}
return gle;
}
-static BOOL check_dest_hash_matches(MSIFILE *file)
-{
- MSIFILEHASHINFO hash;
- UINT r;
-
- if (!file->hash.dwFileHashInfoSize)
- return FALSE;
-
- hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
- r = MsiGetFileHashW(file->TargetPath, 0, &hash);
- if (r != ERROR_SUCCESS)
- return FALSE;
-
- return !memcmp(&hash, &file->hash, sizeof(MSIFILEHASHINFO));
-}
-
static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
LPWSTR *path, DWORD *attrs, PVOID user)
{
static MSIFILE *f = NULL;
+ MSIMEDIAINFO *mi = user;
if (action == MSICABEXTRACT_BEGINEXTRACT)
{
return FALSE;
}
- if (f->state != msifs_missing && f->state != msifs_overwrite)
- {
- TRACE("Skipping extraction of %s\n", debugstr_w(file));
+ if (f->disk_id != mi->disk_id || (f->state != msifs_missing && f->state != msifs_overwrite))
return FALSE;
- }
msi_file_update_ui(package, f, szInstallFiles);
if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
continue;
- if (check_dest_hash_matches(file))
- {
- TRACE("File hashes match, not overwriting\n");
- continue;
- }
-
- if (MsiGetFileVersionW(file->TargetPath, NULL, NULL, NULL, NULL) == ERROR_SUCCESS &&
- msi_compare_file_version(file) >= 0)
- {
- TRACE("Destination file version greater, not overwriting\n");
- continue;
- }
-
if (file->Sequence > mi->last_sequence || mi->is_continuous ||
(file->IsCompressed && !mi->is_extracted))
{
rc = ready_media(package, file, mi);
if (rc != ERROR_SUCCESS)
{
- ERR("Failed to ready media\n");
+ ERR("Failed to ready media for %s\n", debugstr_w(file->File));
break;
}
data.mi = mi;
data.package = package;
data.cb = installfiles_cb;
- data.user = NULL;
+ data.user = mi;
if (file->IsCompressed &&
!msi_cabextract(package, mi, &data))
{
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
- rc = ERROR_FUNCTION_FAILED;
+ rc = ERROR_INSTALL_FAILURE;
break;
}
}
}
else if (file->state != msifs_installed)
{
- ERR("compressed file wasn't extracted (%s)\n",
- debugstr_w(file->TargetPath));
+ ERR("compressed file wasn't installed (%s)\n", debugstr_w(file->TargetPath));
rc = ERROR_INSTALL_FAILURE;
break;
}
sourcename = MSI_RecordGetString(rec, 3);
options = MSI_RecordGetInteger(rec, 7);
- sourcedir = msi_dup_property(package, MSI_RecordGetString(rec, 5));
+ sourcedir = msi_dup_property(package->db, MSI_RecordGetString(rec, 5));
if (!sourcedir)
goto done;
- destdir = msi_dup_property(package, MSI_RecordGetString(rec, 6));
+ destdir = msi_dup_property(package->db, MSI_RecordGetString(rec, 6));
if (!destdir)
goto done;
if (!dst_path)
{
/* try a property */
- dst_path = msi_dup_property( package, dst_key );
+ dst_path = msi_dup_property( package->db, dst_key );
if (!dst_path)
{
FIXME("Unable to get destination folder, try AppSearch properties\n");
UINT install_mode;
LPWSTR dir = NULL, path = NULL;
DWORD size;
- UINT r;
+ UINT ret = ERROR_SUCCESS;
component = MSI_RecordGetString(row, 2);
filename = MSI_RecordGetString(row, 3);
return ERROR_SUCCESS;
}
- dir = msi_dup_property(package, dirprop);
+ dir = msi_dup_property(package->db, dirprop);
if (!dir)
return ERROR_OUTOFMEMORY;
path = msi_alloc(size * sizeof(WCHAR));
if (!path)
{
- r = ERROR_OUTOFMEMORY;
+ ret = ERROR_OUTOFMEMORY;
goto done;
}
msi_free(path);
msi_free(dir);
- return ERROR_SUCCESS;
+ return ret;
}
UINT ACTION_RemoveFiles( MSIPACKAGE *package )
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
-static const WCHAR szRegisterFonts[] =
- {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
-static const WCHAR szUnregisterFonts[] =
- {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
-
static const WCHAR regfont1[] =
{'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
val = msi_alloc((str->len + 1) * sizeof(WCHAR));
lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
- ret = msi_dup_property(format->package, val);
+ ret = msi_dup_property(format->package->db, val);
msi_free(val);
return ret;
format.deformatted = *data;
format.len = *len;
- stack = create_stack();
- temp = create_stack();
-
if (!verify_format(*data))
return ERROR_SUCCESS;
+ stack = create_stack();
+ temp = create_stack();
+
while ((type = format_lex(&format, &str)) != FORMAT_NULL)
{
if (type == FORMAT_LBRACK || type == FORMAT_LBRACE ||
static const WCHAR szFolder[] =
{'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
- SystemFolder = msi_dup_property( package, szFolder );
+ SystemFolder = msi_dup_property( package->db, szFolder );
dest = build_directory_name(3, SystemFolder, szInstaller, package->ProductCode);
{
LPWSTR path, p;
- path = msi_dup_property( package, cszSourceDir );
+ path = msi_dup_property( package->db, cszSourceDir );
if (path)
return path;
- path = msi_dup_property( package, cszDatabase );
+ path = msi_dup_property( package->db, cszDatabase );
if (path)
{
p = strrchrW(path,'\\');
if (!f->ResolvedTarget && !f->Property)
{
LPWSTR check_path;
- check_path = msi_dup_property( package, cszTargetDir );
+ check_path = msi_dup_property( package->db, cszTargetDir );
if (!check_path)
{
- check_path = msi_dup_property( package, cszRootDrive );
+ check_path = msi_dup_property( package->db, cszRootDrive );
if (set_prop)
- MSI_SetPropertyW(package,cszTargetDir,check_path);
+ msi_set_property( package->db, cszTargetDir, check_path );
}
/* correct misbuilt target dir */
path = build_directory_name(2, check_path, NULL);
clean_spaces_from_path( path );
if (strcmpiW(path,check_path)!=0)
- MSI_SetPropertyW(package,cszTargetDir,path);
+ msi_set_property( package->db, cszTargetDir, path );
msi_free(check_path);
f->ResolvedTarget = path;
TRACE(" internally set to %s\n",debugstr_w(path));
if (set_prop)
- MSI_SetPropertyW( package, name, path );
+ msi_set_property( package->db, name, path );
return path;
}
- if (!source && load_prop && (path = msi_dup_property( package, name )))
+ if (!source && load_prop && (path = msi_dup_property( package->db, name )))
{
f->ResolvedTarget = strdupW( path );
TRACE(" property set to %s\n", debugstr_w(path));
f->ResolvedTarget = strdupW( path );
TRACE("target -> %s\n", debugstr_w(path));
if (set_prop)
- MSI_SetPropertyW(package,name,path);
+ msi_set_property( package->db, name, path );
}
else
{
break;
case MSIRUNMODE_MAINTENANCE:
- r = msi_get_property_int( package, szInstalled, 0 ) != 0;
+ r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
break;
case MSIRUNMODE_REBOOTATEND:
r = TRUE;
}
+ msiobj_release( &package->hdr );
return r;
}
r = ERROR_ACCESS_DENIED;
}
+ msiobj_release( &package->hdr );
return r;
}
return 0;
}
- langid = msi_get_property_int( package, szProductLanguage, 0 );
+ langid = msi_get_property_int( package->db, szProductLanguage, 0 );
msiobj_release( &package->hdr );
return langid;
}
return MSI_SetFeatureStates( package );
sprintfW( level, fmt, iInstallLevel );
- r = MSI_SetPropertyW( package, szInstallLevel, level );
+ r = msi_set_property( package->db, szInstallLevel, level );
if ( r == ERROR_SUCCESS )
r = MSI_SetFeatureStates( package );
#include <stdarg.h>
+#define COBJMACROS
+
#include "windef.h"
#include "winerror.h"
#include "wine/debug.h"
#include "winuser.h"
#include "winreg.h"
#include "shlwapi.h"
+#include "objidl.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};
- if ((msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) ==
+ if ((msi_get_property_int(package->db, szUILevel, 0) & INSTALLUILEVEL_MASK) ==
INSTALLUILEVEL_NONE && !gUIHandlerA && !gUIHandlerW && !gUIHandlerRecord)
return ERROR_SUCCESS;
error = generate_error_string(package, 1302, 1, mi->disk_prompt);
- error_dialog = msi_dup_property(package, error_prop);
- source_dir = msi_dup_property(package, cszSourceDir);
+ error_dialog = msi_dup_property(package->db, error_prop);
+ source_dir = msi_dup_property(package->db, cszSourceDir);
while (r == ERROR_SUCCESS && !source_matches_volume(mi, source_dir))
{
return r;
}
-static UINT writeout_cabinet_stream(MSIPACKAGE *package, LPCWSTR stream,
- WCHAR* source)
-{
- UINT rc;
- USHORT* data;
- UINT size;
- DWORD write;
- HANDLE hfile;
- WCHAR tmp[MAX_PATH];
-
- static const WCHAR cszTempFolder[]= {
- 'T','e','m','p','F','o','l','d','e','r',0};
-
- rc = read_raw_stream_data(package->db, stream, &data, &size);
- if (rc != ERROR_SUCCESS)
- return rc;
-
- write = MAX_PATH;
- if (MSI_GetPropertyW(package, cszTempFolder, tmp, &write))
- GetTempPathW(MAX_PATH, tmp);
-
- GetTempFileNameW(tmp, stream, 0, source);
-
- track_tempfile(package, source);
- hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (hfile == INVALID_HANDLE_VALUE)
- {
- ERR("Unable to create file %s\n", debugstr_w(source));
- rc = ERROR_FUNCTION_FAILED;
- goto end;
- }
-
- WriteFile(hfile, data, size, &write, NULL);
- CloseHandle(hfile);
- TRACE("wrote %i bytes to %s\n", write, debugstr_w(source));
-
-end:
- msi_free(data);
- return rc;
-}
-
static void * CDECL cabinet_alloc(ULONG cb)
{
return msi_alloc(cb);
return SetFilePointer(handle, dist, NULL, seektype);
}
+struct cab_stream
+{
+ MSIDATABASE *db;
+ WCHAR *name;
+};
+
+static struct cab_stream cab_stream;
+
+static INT_PTR CDECL cabinet_open_stream( char *pszFile, int oflag, int pmode )
+{
+ UINT r;
+ IStream *stm;
+
+ if (oflag)
+ WARN("ignoring open flags 0x%08x\n", oflag);
+
+ r = db_get_raw_stream( cab_stream.db, cab_stream.name, &stm );
+ if (r != ERROR_SUCCESS)
+ {
+ WARN("Failed to get cabinet stream %u\n", r);
+ return 0;
+ }
+
+ return (INT_PTR)stm;
+}
+
+static UINT CDECL cabinet_read_stream( INT_PTR hf, void *pv, UINT cb )
+{
+ IStream *stm = (IStream *)hf;
+ DWORD read;
+ HRESULT hr;
+
+ hr = IStream_Read( stm, pv, cb, &read );
+ if (hr == S_OK || hr == S_FALSE)
+ return read;
+
+ return 0;
+}
+
+static int CDECL cabinet_close_stream( INT_PTR hf )
+{
+ IStream *stm = (IStream *)hf;
+ IStream_Release( stm );
+ return 0;
+}
+
+static LONG CDECL cabinet_seek_stream( INT_PTR hf, LONG dist, int seektype )
+{
+ IStream *stm = (IStream *)hf;
+ LARGE_INTEGER move;
+ ULARGE_INTEGER newpos;
+ HRESULT hr;
+
+ move.QuadPart = dist;
+ hr = IStream_Seek( stm, move, seektype, &newpos );
+ if (SUCCEEDED(hr))
+ {
+ if (newpos.QuadPart <= MAXLONG) return newpos.QuadPart;
+ ERR("Too big!\n");
+ }
+ return -1;
+}
+
static UINT CDECL msi_media_get_disk_info(MSIPACKAGE *package, MSIMEDIAINFO *mi)
{
MSIRECORD *row;
- LPWSTR ptr;
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
if (!mi->first_volume)
mi->first_volume = strdupW(mi->volume_label);
- ptr = strrchrW(mi->source, '\\') + 1;
- lstrcpyW(ptr, mi->cabinet);
msiobj_release(&row->hdr);
-
return ERROR_SUCCESS;
}
return 0;
}
+static WCHAR *get_cabinet_filename(MSIMEDIAINFO *mi)
+{
+ int len;
+ WCHAR *ret;
+
+ len = strlenW(mi->sourcedir) + strlenW(mi->cabinet) + 1;
+ if (!(ret = msi_alloc(len * sizeof(WCHAR)))) return NULL;
+ strcpyW(ret, mi->sourcedir);
+ strcatW(ret, mi->cabinet);
+ return ret;
+}
+
static INT_PTR cabinet_next_cabinet(FDINOTIFICATIONTYPE fdint,
PFDINOTIFICATION pfdin)
{
MSICABDATA *data = pfdin->pv;
MSIMEDIAINFO *mi = data->mi;
- LPWSTR cab = strdupAtoW(pfdin->psz1);
+ LPWSTR cabinet_file = NULL, cab = strdupAtoW(pfdin->psz1);
INT_PTR res = -1;
UINT rc;
goto done;
}
- TRACE("Searching for %s\n", debugstr_w(mi->source));
+ if (!(cabinet_file = get_cabinet_filename(mi)))
+ goto done;
+
+ TRACE("Searching for %s\n", debugstr_w(cabinet_file));
res = 0;
- if (GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
+ if (GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
{
if (msi_change_media(data->package, mi) != ERROR_SUCCESS)
res = -1;
done:
msi_free(cab);
+ msi_free(cabinet_file);
return res;
}
GetTempFileNameW(szBackSlash, szMsi, 0, tmpfileW);
len = strlenW(path) + strlenW(tmpfileW) + 1;
- if (!(tmppathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
+ if (!(tmppathW = msi_alloc(len * sizeof(WCHAR))))
return ERROR_OUTOFMEMORY;
strcpyW(tmppathW, path);
else
WARN("failed to schedule rename operation %s (error %d)\n", debugstr_w(path), GetLastError());
- HeapFree(GetProcessHeap(), 0, tmppathW);
+ msi_free(tmppathW);
}
else
WARN("failed to create %s (error %d)\n", debugstr_w(path), err);
static INT_PTR CDECL cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
{
- TRACE("(%d)\n", fdint);
-
switch (fdint)
{
case fdintPARTIAL_FILE:
}
}
-/***********************************************************************
- * msi_cabextract
- *
- * Extract files from a cab file.
- */
-BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data)
+static INT_PTR CDECL cabinet_notify_stream( FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin )
+{
+ switch (fdint)
+ {
+ case fdintCOPY_FILE:
+ return cabinet_copy_file( fdint, pfdin );
+
+ case fdintCLOSE_FILE_INFO:
+ return cabinet_close_file_info( fdint, pfdin );
+
+ case fdintCABINET_INFO:
+ return 0;
+
+ default:
+ ERR("Unexpected notification %d\n", fdint);
+ return 0;
+ }
+}
+
+static BOOL extract_cabinet( MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data )
{
LPSTR cabinet, cab_path = NULL;
- LPWSTR ptr;
HFDI hfdi;
ERF erf;
BOOL ret = FALSE;
- TRACE("Extracting %s\n", debugstr_w(mi->source));
+ TRACE("Extracting %s\n", debugstr_w(mi->cabinet));
- hfdi = FDICreate(cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
- cabinet_write, cabinet_close, cabinet_seek, 0, &erf);
+ hfdi = FDICreate( cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
+ cabinet_write, cabinet_close, cabinet_seek, 0, &erf );
if (!hfdi)
{
ERR("FDICreate failed\n");
return FALSE;
}
- ptr = strrchrW(mi->source, '\\') + 1;
- cabinet = strdupWtoA(ptr);
+ cabinet = strdupWtoA( mi->cabinet );
if (!cabinet)
goto done;
- cab_path = strdupWtoA(mi->source);
+ cab_path = strdupWtoA( mi->sourcedir );
if (!cab_path)
goto done;
- cab_path[ptr - mi->source] = '\0';
+ ret = FDICopy( hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data );
+ if (!ret)
+ ERR("FDICopy failed\n");
+
+done:
+ FDIDestroy( hfdi );
+ msi_free(cabinet );
+ msi_free( cab_path );
+
+ if (ret)
+ mi->is_extracted = TRUE;
- ret = FDICopy(hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, data);
+ return ret;
+}
+
+static BOOL extract_cabinet_stream( MSIPACKAGE *package, MSIMEDIAINFO *mi, LPVOID data )
+{
+ static char filename[] = {'<','S','T','R','E','A','M','>',0};
+ HFDI hfdi;
+ ERF erf;
+ BOOL ret = FALSE;
+
+ TRACE("Extracting %s\n", debugstr_w(mi->cabinet));
+
+ hfdi = FDICreate( cabinet_alloc, cabinet_free, cabinet_open_stream, cabinet_read_stream,
+ cabinet_write, cabinet_close_stream, cabinet_seek_stream, 0, &erf );
+ if (!hfdi)
+ {
+ ERR("FDICreate failed\n");
+ return FALSE;
+ }
+
+ cab_stream.db = package->db;
+ cab_stream.name = encode_streamname( FALSE, mi->cabinet + 1 );
+ if (!cab_stream.name)
+ goto done;
+
+ ret = FDICopy( hfdi, filename, NULL, 0, cabinet_notify_stream, NULL, data );
if (!ret)
ERR("FDICopy failed\n");
done:
- FDIDestroy(hfdi);
- msi_free(cabinet);
- msi_free(cab_path);
+ FDIDestroy( hfdi );
+ msi_free( cab_stream.name );
if (ret)
mi->is_extracted = TRUE;
return ret;
}
+/***********************************************************************
+ * msi_cabextract
+ *
+ * Extract files from a cabinet file or stream.
+ */
+BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, LPVOID data)
+{
+ if (mi->cabinet[0] == '#')
+ {
+ return extract_cabinet_stream( package, mi, data );
+ }
+ return extract_cabinet( package, mi, data );
+}
+
void msi_free_media_info(MSIMEDIAINFO *mi)
{
msi_free(mi->disk_prompt);
LPWSTR source_dir;
LPWSTR source;
DWORD options;
- UINT r;
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
if (!mi->first_volume)
mi->first_volume = strdupW(mi->volume_label);
- source_dir = msi_dup_property(package, cszSourceDir);
- lstrcpyW(mi->source, source_dir);
+ source_dir = msi_dup_property(package->db, cszSourceDir);
+ lstrcpyW(mi->sourcedir, source_dir);
mi->type = get_drive_type(source_dir);
- if (file->IsCompressed && mi->cabinet)
- {
- if (mi->cabinet[0] == '#')
- {
- r = writeout_cabinet_stream(package, &mi->cabinet[1], mi->source);
- if (r != ERROR_SUCCESS)
- {
- ERR("Failed to extract cabinet stream\n");
- return ERROR_FUNCTION_FAILED;
- }
- }
- else
- lstrcatW(mi->source, mi->cabinet);
- }
-
options = MSICODE_PRODUCT;
if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE)
{
}
else
{
- source = mi->source;
+ source = mi->sourcedir;
options |= MSISOURCETYPE_NETWORK;
}
return ERROR_SUCCESS;
}
-/* FIXME: search NETWORK and URL sources as well */
+/* FIXME: search URL sources as well */
static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
{
WCHAR source[MAX_PATH];
WCHAR prompt[MAX_PATH];
DWORD volumesz, promptsz;
DWORD index, size, id;
+ WCHAR last_type[2];
UINT r;
+ size = 2;
+ r = MsiSourceListGetInfoW(package->ProductCode, NULL,
+ package->Context, MSICODE_PRODUCT,
+ INSTALLPROPERTY_LASTUSEDTYPEW, last_type, &size);
+ if (r != ERROR_SUCCESS)
+ return r;
+
size = MAX_PATH;
r = MsiSourceListGetInfoW(package->ProductCode, NULL,
package->Context, MSICODE_PRODUCT,
if (r != ERROR_SUCCESS)
return r;
+ index = 0;
+ volumesz = MAX_PATH;
+ promptsz = MAX_PATH;
+
+ if (last_type[0] == 'n')
+ {
+ while (MsiSourceListEnumSourcesW(package->ProductCode, NULL,
+ package->Context,
+ MSISOURCETYPE_NETWORK, index++,
+ volume, &volumesz) == ERROR_SUCCESS)
+ {
+ if (!strncmpiW(source, volume, strlenW(source)))
+ {
+ lstrcpyW(mi->sourcedir, source);
+ TRACE("Found network source %s\n", debugstr_w(mi->sourcedir));
+ return ERROR_SUCCESS;
+ }
+ }
+ }
+
index = 0;
volumesz = MAX_PATH;
promptsz = MAX_PATH;
if (source_matches_volume(mi, source))
{
/* FIXME: what about SourceDir */
- lstrcpyW(mi->source, source);
+ lstrcpyW(mi->sourcedir, source);
+ TRACE("Found disk source %s\n", debugstr_w(mi->sourcedir));
return ERROR_SUCCESS;
}
}
UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
{
UINT rc = ERROR_SUCCESS;
+ WCHAR *cabinet_file;
/* media info for continuous cabinet is already loaded */
if (mi->is_continuous)
rc = msi_load_media_info(package, file, mi);
if (rc != ERROR_SUCCESS)
{
- ERR("Unable to load media info\n");
+ ERR("Unable to load media info %u\n", rc);
return ERROR_FUNCTION_FAILED;
}
if (!mi->cabinet || mi->cabinet[0] == '#')
return ERROR_SUCCESS;
+ cabinet_file = get_cabinet_filename(mi);
+
/* package should be downloaded */
if (file->IsCompressed &&
- GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES &&
+ GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES &&
package->BaseURL && UrlIsW(package->BaseURL, URLIS_URL))
{
- WCHAR temppath[MAX_PATH];
+ WCHAR temppath[MAX_PATH], *p;
- msi_download_file(mi->source, temppath);
- lstrcpyW(mi->source, temppath);
+ msi_download_file(cabinet_file, temppath);
+ if ((p = strrchrW(temppath, '\\'))) *p = 0;
+
+ msi_free(mi->sourcedir);
+ strcpyW(mi->sourcedir, temppath);
+ msi_free(mi->cabinet);
+ strcpyW(mi->cabinet, p + 1);
+
+ msi_free(cabinet_file);
return ERROR_SUCCESS;
}
if (mi->volume_label && mi->disk_id > 1 &&
lstrcmpW(mi->first_volume, mi->volume_label))
{
- LPWSTR source = msi_dup_property(package, cszSourceDir);
+ LPWSTR source = msi_dup_property(package->db, cszSourceDir);
BOOL matches;
matches = source_matches_volume(mi, source);
{
rc = msi_change_media(package, mi);
if (rc != ERROR_SUCCESS)
+ {
+ msi_free(cabinet_file);
return rc;
+ }
}
}
if (file->IsCompressed &&
- GetFileAttributesW(mi->source) == INVALID_FILE_ATTRIBUTES)
+ GetFileAttributesW(cabinet_file) == INVALID_FILE_ATTRIBUTES)
{
rc = find_published_source(package, mi);
if (rc != ERROR_SUCCESS)
{
- ERR("Cabinet not found: %s\n", debugstr_w(mi->source));
+ ERR("Cabinet not found: %s\n", debugstr_w(cabinet_file));
+ msi_free(cabinet_file);
return ERROR_INSTALL_FAILURE;
}
}
+ msi_free(cabinet_file);
return ERROR_SUCCESS;
}
UINT r = ERROR_SUCCESS, type;
DWORD size = 0;
LPCWSTR cmd_ptr = szCommandLine;
- LPCWSTR product_code = szProductCode;
- LPWSTR beg, end;
- LPWSTR cmd = NULL, codes = NULL;
+ LPWSTR beg, end, cmd = NULL, codes = NULL;
+ BOOL succeeded = FALSE;
static const WCHAR patcheq[] = {'P','A','T','C','H','=',0};
static WCHAR empty[] = {0};
r = MsiSummaryInfoGetPropertyW(info, PID_TEMPLATE, &type, NULL, NULL, codes, &size);
if (r != ERROR_SUCCESS)
goto done;
-
- product_code = codes;
}
if (!szCommandLine)
lstrcatW(cmd, patcheq);
lstrcatW(cmd, szPatchPackage);
- beg = codes;
- while ((end = strchrW(beg, '}')))
+ if (szProductCode)
+ r = MsiConfigureProductExW(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
+ else
{
- *(end + 1) = '\0';
-
- r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
- if (r != ERROR_SUCCESS)
- goto done;
+ beg = codes;
+ while ((end = strchrW(beg, '}')))
+ {
+ *(end + 1) = '\0';
+ r = MsiConfigureProductExW(beg, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, cmd);
+ if (r == ERROR_SUCCESS)
+ {
+ TRACE("patch applied\n");
+ succeeded = TRUE;
+ }
+ beg = end + 2;
+ }
- beg = end + 2;
+ if (succeeded)
+ r = ERROR_SUCCESS;
}
done:
UINT WINAPI MsiDetermineApplicablePatchesA(LPCSTR szProductPackagePath,
DWORD cPatchInfo, PMSIPATCHSEQUENCEINFOA pPatchInfo)
{
- FIXME("(%s, %d, %p): stub!\n", debugstr_a(szProductPackagePath),
- cPatchInfo, pPatchInfo);
+ UINT i, r;
+ WCHAR *package_path = NULL;
+ MSIPATCHSEQUENCEINFOW *psi;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ TRACE("(%s, %d, %p)\n", debugstr_a(szProductPackagePath), cPatchInfo, pPatchInfo);
+
+ if (szProductPackagePath && !(package_path = strdupAtoW( szProductPackagePath )))
+ return ERROR_OUTOFMEMORY;
+
+ psi = msi_alloc( cPatchInfo * sizeof(*psi) );
+ if (!psi)
+ {
+ msi_free( package_path );
+ return ERROR_OUTOFMEMORY;
+ }
+
+ for (i = 0; i < cPatchInfo; i++)
+ {
+ psi[i].szPatchData = strdupAtoW( pPatchInfo[i].szPatchData );
+ psi[i].ePatchDataType = pPatchInfo[i].ePatchDataType;
+ }
+
+ r = MsiDetermineApplicablePatchesW( package_path, cPatchInfo, psi );
+ if (r == ERROR_SUCCESS)
+ {
+ for (i = 0; i < cPatchInfo; i++)
+ {
+ pPatchInfo[i].dwOrder = psi[i].dwOrder;
+ pPatchInfo[i].uStatus = psi[i].uStatus;
+ }
+ }
+
+ msi_free( package_path );
+ for (i = 0; i < cPatchInfo; i++)
+ msi_free( (WCHAR *)psi[i].szPatchData );
+ msi_free( psi );
+ return r;
}
static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
if (!si)
{
- r = ERROR_FUNCTION_FAILED;
- goto done;
+ msiobj_release( &patch_db->hdr );
+ return ERROR_FUNCTION_FAILED;
}
r = msi_check_patch_applicable( package, si );
if (r != ERROR_SUCCESS)
TRACE("patch not applicable\n");
-done:
msiobj_release( &patch_db->hdr );
msiobj_release( &si->hdr );
return r;
WCHAR sourcepath[MAX_PATH];
WCHAR filename[MAX_PATH];
- static const WCHAR szLocalPackage[] = {
- 'L','o','c','a','l','P','a','c','k','a','g','e',0};
-
-
r = MSIREG_OpenInstallProps(product, context, NULL, &props, FALSE);
if (r != ERROR_SUCCESS)
return ERROR_BAD_CONFIGURATION;
static UINT msi_copy_outval(LPWSTR val, LPWSTR out, LPDWORD size)
{
- UINT r;
+ UINT r = ERROR_SUCCESS;
if (!val)
return ERROR_UNKNOWN_PROPERTY;
if (size)
*size = lstrlenW(val);
- return ERROR_SUCCESS;
+ return r;
}
UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
return MessageBoxExW(hWnd,lpText,lpCaption,uType,wLanguageId);
}
+UINT WINAPI MsiMessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType,
+ DWORD unknown, WORD wLanguageId, DWORD f)
+{
+ FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_a(lpText),
+ debugstr_a(lpCaption), uType, unknown, wLanguageId, f);
+ return MessageBoxExA(hWnd, lpText, lpCaption, uType, wLanguageId);
+}
+
+UINT WINAPI MsiMessageBoxExW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType,
+ DWORD unknown, WORD wLanguageId, DWORD f)
+{
+ FIXME("(%p, %s, %s, %u, 0x%08x, 0x%08x, 0x%08x): semi-stub\n", hWnd, debugstr_w(lpText),
+ debugstr_w(lpCaption), uType, unknown, wLanguageId, f);
+ return MessageBoxExW(hWnd, lpText, lpCaption, uType, wLanguageId);
+}
+
UINT WINAPI MsiProvideAssemblyA( LPCSTR szAssemblyName, LPCSTR szAppContext,
DWORD dwInstallMode, DWORD dwAssemblyInfo, LPSTR lpPathBuf,
LPDWORD pcchPathBuf )
r = ERROR_SUCCESS;
}
+ msiobj_release(&package->hdr);
return r;
}
if (r != ERROR_SUCCESS)
return r;
- MSI_SetPropertyW( package, szReinstallMode, reinstallmode );
- MSI_SetPropertyW( package, szInstalled, szOne );
- MSI_SetPropertyW( package, szLogVerbose, szOne );
- MSI_SetPropertyW( package, szReinstall, szFeature );
+ msi_set_property( package->db, szReinstallMode, reinstallmode );
+ msi_set_property( package->db, szInstalled, szOne );
+ msi_set_property( package->db, szLogVerbose, szOne );
+ msi_set_property( package->db, szReinstall, szFeature );
r = MSI_InstallPackage( package, sourcepath, NULL );
276 stub MsiSourceListClearMediaDiskW
277 stdcall MsiDetermineApplicablePatchesA(str long ptr)
278 stdcall MsiDetermineApplicablePatchesW(wstr long ptr)
-279 stub MsiMessageBoxExA
-280 stub MsiMessageBoxExW
+279 stdcall MsiMessageBoxExA(long str str long long long long)
+280 stdcall MsiMessageBoxExW(long wstr wstr long long long long)
281 stdcall MsiSetExternalUIRecord(ptr long ptr ptr)
@ stdcall -private DllCanUnloadNow()
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "ïúòÿò %s íå å íàìåðåí"
9 "ïîñòàâåòå äèñê %s"
- 10 "íåêîðåêòíè ïàðàìåòðè"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "âúâåäåòå ïàïêàòà, êîÿòî ñúäúðæà %s"
12 "èçòî÷íèêà çà èíñòàëàöèÿ íà ôóíêöèîíàëíîñòòà ëèïñâà"
13 "ìðåæîâîòî óñòðîéñòâà íóæíî çà ôóíêöèîíàëíîñòòà ëèïñâà "
4 "Kunne ikke åbne den specificerede installationspakke. Kontroller stien og prøv igen."
5 "kunne ikke finden stien '%s'."
9 "indsæt disk '%s'"
- 10 "forkerte parametere."
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "angiv kataloget som indeholder '%s'."
12 "featurens installationskilde mangler."
13 "featurens netværksdrev mangler."
* German resources for MSI
*
* Copyright 2005 Henning Gerhardt
+ * Copyright 2010 Detlef Riekenberg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
4 "Das angegebene Installationspaket konnte nicht geöffnet werden. Bitte überprüfen Sie den Pfadnamen und versuchen Sie es noch einmal."
5 "Der Pfad %s wurde nicht gefunden."
9 "Bitte Disk %s einlegen."
- 10 "Falsche Parameter"
+ 10 "Windows Installer %s\n\n" \
+ "Benutzung:\n" \
+ "msiexec Befehl {Parameter} [Zusätzliche Parammeter]\n\n" \
+ "Produkt installieren:\n" \
+ "\t/i {Paket|Produktcode} [Eigenschaft]\n" \
+ "\t/package {Paket|Produktcode} [Eigenschaft]\n" \
+ "\t/a Paket [Eigenschaft]\n" \
+ "Installation reparieren:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {Paket|Produktcode}\n" \
+ "Produkt deinstallieren:\n" \
+ "\t/uninstall {Paket|Produktcode} [Eigenschaft]\n" \
+ "\t/x {Paket|Produktcode} [Eigenschaft]\n" \
+ "Produkt ankündigen:\n" \
+ "\t/j[u|m] Paket [/t Transformationspaket] [/g Sprachkennung]\n" \
+ "Patch integrieren:\n" \
+ "\t/p Patchpaket [Eigenschaft]\n" \
+ "\t/p Patchpaket /a Paket [Eigenschaft]\n" \
+ "Protokollierung und Benutzeroberfläche für die oberen Befehle anpassen:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] Protokolldatei\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "MSI Service registrieren:\n" \
+ "\t/y\n" \
+ "Registrierung des MSI Service aufheben:\n" \
+ "\t/z\n" \
+ "Hilfe anzeigen:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "Geben Sie das Verzeichnis ein, dass %s enthält."
12 "Die Installationsquelle für das Feature fehlt."
13 "Das Netzwerklaufwerk für das Feature fehlt."
* English resources for MSI
*
* Copyright 2005 Mike McCormack
+ * Copyright 2010 Detlef Riekenberg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "path %s not found"
9 "insert disk %s"
- 10 "bad parameters"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parameter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "enter which folder contains %s"
12 "install source for feature missing"
13 "network drive for feature missing"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Mi ne trovis la vojon %s"
9 "enþovu la diskon %s"
- 10 "nekorektaj parametroj"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "enigu la nomon de dosierujo kiu enhavas %s"
12 "instalad-fonto por mankanta taýgeco"
13 "retdrajvo por mankanta taýgeco"
4 "No se ha podido abrir el paquete de instalación especificado. Por favor, compruebe la ruta del archivo y vuelva a intentarlo."
5 "ruta %s no encontrada"
9 "inserte el disco %s"
- 10 "parámetros incorrectos"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "introduzca qué carpeta contiene %s"
12 "instalar fuente para característica ausente"
13 "unidad de red para característica ausente"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "Polkua %s ei löydy."
9 "Anna levy %s"
- 10 "Virheelliset parametrit."
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "Anna kansio, joka sisältää %s"
12 "Ominaisuuden asennuslähde puuttuu."
13 "Ominaisuuden verkkolevy puuttuu."
* French resources for MSI
*
* Copyright 2005 Jonathan Ernst
+ * Copyright 2009-2010 Frédéric Delanoy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
4 "Le paquet d'installation spécifié n'a pu être ouvert. Veuillez vérifier le chemin du fichier et réessayer."
5 "Le chemin %s est introuvable"
9 "insérez le disque %s"
- 10 "mauvais paramètres"
+ 10 "Programme d'installation Windows %s\n\n" \
+ "Usage :\n" \
+ "msiexec commande {paramètre obligatoire} [paramètre optionnel]\n\n" \
+ "Installer un produit :\n" \
+ "\t/i {paquet|code_produit} [propriété]\n" \
+ "\t/package {paquet|code_produit} [propriété]\n" \
+ "\t/a paquet [propriété]\n" \
+ "Réparer une installation :\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {paquet|code_produit}\n" \
+ "Désinstaller un produit :\n" \
+ "\t/uninstall {paquet|code_produit} [propriété]\n" \
+ "\t/x {paquet|code_produit} [propriété]\n" \
+ "Publier un produit :\n" \
+ "\t/j[u|m] paquet [/t transformation] [/g id_langue]\n" \
+ "Appliquer un patch :\n" \
+ "\t/p paquet_patch [propriété]\n" \
+ "\t/p paquet_patch /a paquet [propriété]\n" \
+ "Modificateurs de journalisation et d'interface utilisateur pour les commandes ci-dessus :\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] fichier_journal\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Enregistrer le service MSI :\n" \
+ "\t/y\n" \
+ "Annuler l'enregistrement du service MSI :\n" \
+ "\t/z\n" \
+ "Afficher cette aide :\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "saisissez le nom du dossier contenant %s"
12 "source d'installation pour la fonctionnalité manquante"
13 "lecteur réseau pour la fonctionnalité manquante"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "%s útvonal nem található"
9 "helyezze be a lemezt: %s"
- 10 "rossz paraméterek"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "adja meg melyik mappa tartalmazza ezt: %s"
12 "hiányzó tulajdonság a telepítési forráshoz"
13 "hiányzó tulajdonság a hálózati meghajtóhoz"
4 "Impossibile aprire il pacchetto di installazione specificato. Per favore controlla l'indirizzo del file e riprova."
5 "percorso %s non trovato"
9 "inserire disco %s"
- 10 "parametri incorretti"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "immettere il nome della cartella che contiene %s"
12 "sorgente di installazione per la funzionalità mancante"
13 "periferica di rete per la funzionalità mancante"
4 " ÁöÁ¤ÇÑ ¼³Ä¡ ÆÐŰÁö¸¦ ¿ ¼ö ¾ø½À´Ï´Ù. ÆÄÀÏ °æ·Î¸¦ È®ÀÎÇÏ°í ´Ù½Ã ½ÃµµÇϽʽÿÀ."
5 "%s °æ·Î¸¦ ãÀ»¼ö ¾ø½À´Ï´Ù"
9 "µð½ºÅ© %s »ðÀÔ"
- 10 "À߸øµÈ ¸Å°³º¯¼ö"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "%s¸¦ Æ÷ÇÔÇÏ´Â Æú´õ¸¦ ÀÔ·ÂÇϼ¼¿©"
12 "ºüÁø ºÎºÐ(feature)À» À§ÇÑ ¼³Ä¡ ¿øº»"
13 "ºüÁø ºÎºÐ(feature)À» À§ÇÑ ³×Æ®¿öÅ© µå¶óÀ̺ê"
4 "Nepavyko atverti nurodyto diegimo paketo. Patikrinkite failo kelią ir mėginkite dar kartą."
5 "kelias %s nerastas"
9 "įdėkite diską %s"
- 10 "blogi parametrai"
+ 10 "Windows diegimo programa %s\n\n" \
+ "Naudojimas:\n" \
+ "msiexec komanda {būtinas parametras} [nebūtinas parametras]\n\n" \
+ "Įdiegti produktą:\n" \
+ "\t/i {paketas|produkto_kodas} [savybė]\n" \
+ "\t/package {paketas|produkto_kodas} [savybė]\n" \
+ "\t/a paketas [savybė]\n" \
+ "Taisyti įdiegimą:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {paketas|produkto_kodas}\n" \
+ "Pašalinti produktą:\n" \
+ "\t/uninstall {paketas|produkto_kodas} [savybė]\n" \
+ "\t/x {paketas|produkto_kodas} [savybė]\n" \
+ "Skelbti produktą:\n" \
+ "\t/j[u|m] paketas [/t pakeitimas] [/g kalbos_identifikatorius]\n" \
+ "Pritaikyti pataisą:\n" \
+ "\t/p pataisos_paketas [savybė]\n" \
+ "\t/p pataisos_paketas /a paketas [savybė]\n" \
+ "Žurnalo ir sąsajos modifikatoriai aukščiau išvardintoms komandoms:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] žurnalo_failas\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Registruoti MSI tarnybą:\n" \
+ "\t/y\n" \
+ "Išregistruoti MSI tarnybą:\n" \
+ "\t/z\n" \
+ "Parodyti šią pagalbą:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "įveskite aplanką, kuris turi %s"
12 "trūksta diegimo šaltinio komponentui"
13 "trūksta tinklo disko komponentui"
/*
- * Durch resources for MSI
+ * Dutch resources for MSI
*
* Copyright 2005 Hans Leidekker
*
STRINGTABLE DISCARDABLE
{
- 4 "The specified installation package could not be opened. Please check the file path and try again."
+ 4 "Het opgegeven installatie pakket kon niet worden geopend. Verifieer het bestandspad en probeer opnieuw."
5 "Pad %s niet gevonden"
9 "Plaats disk %s"
- 10 "Ongeldige parameters"
+ 10 "Windows Installer %s\n\n" \
+ "Gebruik:\n" \
+ "msiexec commando {vereiste parameter} [optionele parameter]\n\n" \
+ "Installeer een product:\n" \
+ "\t/i {pakket|productcode} [eigenschap]\n" \
+ "\t/package {pakket|productcode} [eigenschap]\n" \
+ "\t/a pakket [eigenschap]\n" \
+ "Herstel een installatie:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {pakket|productcode}\n" \
+ "Verwijder een product:\n" \
+ "\t/uninstall {pakket|productcode} [eigenschap]\n" \
+ "\t/x {pakket|productcode} [eigenschap]\n" \
+ "Adverteer een product:\n" \
+ "\t/j[u|m] pakket [/t transform] [/g languageid]\n" \
+ "Pas een patch toe:\n" \
+ "\t/p patchpakket [eigenschap]\n" \
+ "\t/p patchpakket /a pakket [eigenschap]\n" \
+ "Log en UI Modifiers voor bovenstaande commando's:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logbestand\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Registreer MSI Service:\n" \
+ "\t/y\n" \
+ "Maak registratie MSI Service ongedaan:\n" \
+ "\t/z\n" \
+ "Laat dit helpvenster zien:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "Voer de map in die %s bevat"
- 12 "De installatiebron van het feature ontbreekt"
- 13 "De netwerkschijf met het feature ontbreekt"
+ 12 "De installatiebron van de feature ontbreekt"
+ 13 "De netwerkschijf met de feature ontbreekt"
14 "Feature van:"
15 "Kies de map die %s bevat"
}
4 "Klarte ikke åpne den oppgitte installasjonspakken. Kontroller filbanen og prøv igjen."
5 "Fant ikke stien '%s'."
9 "Sett i disk '%s'"
- 10 "Gale parametere."
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "Oppgi katalogen som inneholder '%s'."
12 "Egenskapens installasjonskilde mangler."
13 "Egenskapens nettverksstasjon mangler."
4 "Nie uda³o siê otworzyæ wybranego pakietu instalacyjnego. Sprawd\9f czy \9ccie¿ka jest poprawna i spróbuj ponownie."
5 "\9ccie¿ka '%s' nie zosta³a odnaleziona"
9 "w³ó¿ dysk '%s'"
- 10 "z³e parametry"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "wprowad\9f sice¿kê do folderu zawieraj¹cego '%s'"
12 "\9fród³o danych zawieraj¹ce ¿¹danê funkcjê jest niedostêpne"
13 "dysk siecowy zawieraj¹cy ¿¹dan¹ funckje jest niedostêpny"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "caminho %s não encontrado"
9 "insira disco %s"
- 10 "parâmetros inválidos"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "entre qual pasta contém %s"
12 "instalar fonte para característica faltando"
13 "drive de rede para característica faltando"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "localização %s não encontrada"
9 "insira o disco %s"
- 10 "parâmetros inválidos"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "indique que pasta contém %s"
12 "instalar fonte para a opção em falta"
13 "controlador de rede para a opção em falta"
4 "Pachetul de instalare menționat nu a putut fi deschis. Verificați calea și încercați din nou."
5 "calea %s nu a fost găsită"
9 "inserați discul %s"
- 10 "parameteri greșiți"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "introduceți fișierul care conține %s"
12 "lipsește sursa de instalare pentru această caracteristică"
13 "lipsește unitatea de rețea pentru această caracteristică"
4 "Указанный пакет не может быть открыт. Проверьте файл и повторите попытку."
5 "путь %s не найден"
9 "вставьте диск %s"
- 10 "неверные параметры"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "укажите каталог, содержащий %s"
12 "источник установки данной возможности не указан"
13 "сетевой диск для данной возможности не указан"
4 "Navedenega namestitvenega paketa ni mogoče odpreti. Preverite ime datoteke in poskusite znova."
5 "pot %s ne obstaja"
9 "vnesite disk %s"
- 10 "neveljavni parametri"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "vnesite ime mape, ki vsebuje %s"
12 "manjkajoč namestitveni vir za namestitev funkcije"
13 "manjkajoč omrežni pogon za namestitev funkcijo"
4 "Det angivna installationspaketet kunde inte öppnas. Kontrollera filsökvägen och försök igen."
5 "sökvägen %s hittades inte"
9 "mata in %s"
- 10 "felaktiga parametrar"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "ange vilken mapp som innehåller %s"
12 "installationskälla för funktion saknar"
13 "nätverksenhet för funktion saknar"
4 "The specified installation package could not be opened. Please check the file path and try again."
5 "%s yolu bulunamadý"
9 "%s nolu diski yerleþtirin"
- 10 "bozuk parametreler"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "%s öðesini içeren dizini girin"
12 "eksik özellik için kurulum kaynaðý"
13 "eksik özellik için að sürücüsü"
4 "Не вдалося відкрити вказаний пакет інсталяції. Перевірте шлях до файлу та спробуйте знов."
5 "шлях %s не знайдено"
9 "вставте диск %s"
- 10 "невірні параметри"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "вкажіть папку, що містить %s"
12 "джерело встановлення даної можливості не вказане"
13 "мережевий диск для даної можливості не вказаний"
4 "不能打开所指定的安装软件包. 请检查文件路径后再试."
5 "路径 %s 没找到"
9 "插入软盘 %s"
- 10 "错误参数"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "输入包含 %s 的文件夹"
12 "本功能的安装源不存在"
13 "本功能的网络驱动器不存在"
4 "不能開啟所指定的安裝軟件包. 請檢查檔案路徑後再試."
5 "路徑 %s 沒找到"
9 "插入軟碟 %s"
- 10 "錯誤參數"
+ 10 "Windows Installer %s\n\n" \
+ "Usage:\n" \
+ "msiexec command {required parameter} [optional parammeter]\n\n" \
+ "Install a product:\n" \
+ "\t/i {package|productcode} [property]\n" \
+ "\t/package {package|productcode} [property]\n" \
+ "\t/a package [property]\n" \
+ "Repair an installation:\n" \
+ "\t/f[p|o|e|d|c|a|u|m|s|v] {package|productcode}\n" \
+ "Uninstall a product:\n" \
+ "\t/uninstall {package|productcode} [property]\n" \
+ "\t/x {package|productcode} [property]\n" \
+ "Advertise a product:\n" \
+ "\t/j[u|m] package [/t transform] [/g languageid]\n" \
+ "Apply a patch:\n" \
+ "\t/p patchpackage [property]\n" \
+ "\t/p patchpackage /a package [property]\n" \
+ "Log and UI Modifiers for above commands:\n" \
+ "\t/l[*][i|w|e|a|r|u|c|m|o|p|v|][+|!] logfile\n" \
+ "\t/q{|n|b|r|f|n+|b+|b-}\n" \
+ "Register MSI Service:\n" \
+ "\t/y\n" \
+ "Unregister MSI Service:\n" \
+ "\t/z\n" \
+ "Display this help:\n" \
+ "\t/help\n" \
+ "\t/?\n"
11 "輸入包含 %s 的檔案夾"
12 "本功能的安裝源不存在"
13 "本功能的網路儲存槽不存在"
LPWSTR volume_label;
BOOL is_continuous;
BOOL is_extracted;
- WCHAR source[MAX_PATH];
+ WCHAR sourcedir[MAX_PATH];
} MSIMEDIAINFO;
typedef struct tagMSIPATCHINFO
{
+ struct list entry;
LPWSTR patchcode;
LPWSTR transforms;
+ LPWSTR localfile;
} MSIPATCHINFO;
typedef struct _column_info
{
MSIOBJECTHDR hdr;
MSIDATABASE *db;
- MSIPATCHINFO *patch;
+ struct list patches;
struct list components;
struct list features;
struct list files;
LPWSTR TargetPath;
BOOL IsCompressed;
MSIFILEHASHINFO hash;
+ UINT disk_id;
} MSIFILE;
typedef struct tagMSITEMPFILE
struct list entry;
LPWSTR ContentType; /* Primary Key */
MSIEXTENSION *Extension;
+ LPWSTR suffix;
LPWSTR clsid;
MSICLASS *Class;
/* not in the table, set during installation */
StringNonPersistent = 1
};
-extern BOOL msi_addstringW( string_table *st, UINT string_no, const WCHAR *data, int len, UINT refcount, enum StringPersistence persistence );
-
+extern BOOL msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum StringPersistence persistence );
extern UINT msi_string2idW( const string_table *st, LPCWSTR buffer, UINT *id );
extern VOID msi_destroy_stringtable( string_table *st );
extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id );
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
-extern UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname,
- USHORT **pdata, UINT *psz );
extern UINT read_stream_data( IStorage *stg, LPCWSTR stname, BOOL table,
BYTE **pdata, UINT *psz );
extern UINT write_stream_data( IStorage *stg, LPCWSTR stname,
LPCWSTR szTransformFile, int iErrorCond );
extern void append_storage_to_db( MSIDATABASE *db, IStorage *stg );
+/* patch functions */
extern UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si );
+extern UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch );
+extern UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch );
/* action internals */
extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR );
/* database internals */
extern UINT db_get_raw_stream( MSIDATABASE *, LPCWSTR, IStream ** );
+void db_destroy_stream( MSIDATABASE *, LPCWSTR );
extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** );
extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** );
extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... );
extern MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *, LPCWSTR );
extern UINT MSI_OpenPackageW( LPCWSTR szPackage, MSIPACKAGE **pPackage );
extern UINT MSI_SetTargetPathW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
-extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
extern INT MSI_ProcessMessage( MSIPACKAGE *, INSTALLMESSAGE, MSIRECORD * );
-extern UINT MSI_GetPropertyW( MSIPACKAGE *, LPCWSTR, LPWSTR, LPDWORD );
-extern UINT MSI_GetPropertyA(MSIPACKAGE *, LPCSTR, LPSTR, LPDWORD );
extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR );
extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * );
extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR);
extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR);
extern UINT msi_clone_properties(MSIPACKAGE *);
+extern UINT msi_set_context(MSIPACKAGE *);
extern UINT MSI_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE, LPINT);
/* for deformating */
LPCWSTR szUserSid, HKEY *key, BOOL create);
extern UINT MSIREG_OpenUserDataPatchKey(LPCWSTR szPatch, MSIINSTALLCONTEXT dwContext,
HKEY *key, BOOL create);
+extern UINT MSIREG_OpenUserDataProductPatchesKey(LPCWSTR product, MSIINSTALLCONTEXT context,
+ HKEY *key, BOOL create);
extern UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext,
LPCWSTR szUserSid, HKEY *key, BOOL create);
extern UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create);
extern UINT MSIREG_DeleteProductKey(LPCWSTR szProduct);
extern UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct);
+extern UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context);
extern UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct);
extern UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct);
extern UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid);
extern UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
extern UINT ACTION_RegisterFonts(MSIPACKAGE *package);
+extern UINT ACTION_UnregisterClassInfo(MSIPACKAGE *package);
+extern UINT ACTION_UnregisterExtensionInfo(MSIPACKAGE *package);
extern UINT ACTION_UnregisterFonts(MSIPACKAGE *package);
+extern UINT ACTION_UnregisterMIMEInfo(MSIPACKAGE *package);
+extern UINT ACTION_UnregisterProgIdInfo(MSIPACKAGE *package);
/* Helpers */
extern DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data );
extern LPWSTR msi_dup_record_field(MSIRECORD *row, INT index);
-extern LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop);
-extern int msi_get_property_int( MSIPACKAGE *package, LPCWSTR prop, int def );
+extern LPWSTR msi_dup_property( MSIDATABASE *db, LPCWSTR prop );
+extern UINT msi_set_property( MSIDATABASE *, LPCWSTR, LPCWSTR );
+extern UINT msi_get_property( MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD );
+extern int msi_get_property_int( MSIDATABASE *package, LPCWSTR prop, int def );
extern LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
BOOL set_prop, BOOL load_prop, MSIFOLDER **folder);
extern LPWSTR resolve_file_source(MSIPACKAGE *package, MSIFILE *file);
+extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
extern MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
extern MSIFEATURE *get_loaded_feature( MSIPACKAGE* package, LPCWSTR Feature );
extern MSIFILE *get_loaded_file( MSIPACKAGE* package, LPCWSTR file );
extern UINT msi_create_component_directories( MSIPACKAGE *package );
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
+extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
/* media */
static const WCHAR szWindowsFolder[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
static const WCHAR szAppSearch[] = {'A','p','p','S','e','a','r','c','h',0};
static const WCHAR szMoveFiles[] = {'M','o','v','e','F','i','l','e','s',0};
+static const WCHAR szCCPSearch[] = {'C','C','P','S','e','a','r','c','h',0};
+static const WCHAR szUnregisterClassInfo[] = {'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
+static const WCHAR szUnregisterExtensionInfo[] = {'U','n','r','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n','I','n','f','o',0};
+static const WCHAR szUnregisterMIMEInfo[] = {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
+static const WCHAR szUnregisterProgIdInfo[] = {'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
+static const WCHAR szRegisterFonts[] = {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
+static const WCHAR szUnregisterFonts[] = {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
+static const WCHAR szCLSID[] = {'C','L','S','I','D',0};
+static const WCHAR szProgID[] = {'P','r','o','g','I','D',0};
+static const WCHAR szVIProgID[] = {'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0};
+static const WCHAR szAppID[] = {'A','p','p','I','D',0};
+static const WCHAR szDefaultIcon[] = {'D','e','f','a','u','l','t','I','c','o','n',0};
+static const WCHAR szInprocHandler[] = {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
+static const WCHAR szInprocHandler32[] = {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0};
+static const WCHAR szMIMEDatabase[] = {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',' ','T','y','p','e','\\',0};
+static const WCHAR szLocalPackage[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
+static const WCHAR szOriginalDatabase[] = {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);
MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
list_remove( &mt->entry );
+ msi_free( mt->suffix );
msi_free( mt->clsid );
msi_free( mt->ContentType );
msi_free( mt );
msi_free( package->script );
}
- if (package->patch)
+ LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
{
- msi_free( package->patch->patchcode );
- msi_free( package->patch->transforms );
- msi_free( package->patch );
+ MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
+
+ list_remove( &patch->entry );
+ msi_free( patch->patchcode );
+ msi_free( patch->transforms );
+ msi_free( patch->localfile );
+ msi_free( patch );
}
msi_free( package->BaseURL );
if (r == ERROR_SUCCESS)
{
RegCloseKey( hkey );
- MSI_SetPropertyW( package, szInstalled, szOne );
+ msi_set_property( package->db, szInstalled, szOne );
}
return r;
if (!ConvertSidToStringSidW( psid, &sid_str ))
goto done;
- r = MSI_SetPropertyW( package, szUserSID, sid_str );
+ r = msi_set_property( package->db, szUserSID, sid_str );
done:
LocalFree( sid_str );
if (!val_len || !verstr)
goto done;
- MSI_SetPropertyW(package, netasm, verstr);
+ msi_set_property(package->db, netasm, verstr);
done:
msi_free(fusion);
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, CFF, pth);
+ msi_set_property(package->db, CFF, pth);
SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, PFF, pth);
+ msi_set_property(package->db, PFF, pth);
SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, CADF, pth);
+ msi_set_property(package->db, CADF, pth);
SHGetFolderPathW(NULL,CSIDL_FAVORITES,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, FaF, pth);
+ msi_set_property(package->db, FaF, pth);
SHGetFolderPathW(NULL,CSIDL_FONTS,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, FoF, pth);
+ msi_set_property(package->db, FoF, pth);
SHGetFolderPathW(NULL,CSIDL_SENDTO,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, SendTF, pth);
+ msi_set_property(package->db, SendTF, pth);
SHGetFolderPathW(NULL,CSIDL_STARTMENU,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, SMF, pth);
+ msi_set_property(package->db, SMF, pth);
SHGetFolderPathW(NULL,CSIDL_STARTUP,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, StF, pth);
+ msi_set_property(package->db, StF, pth);
SHGetFolderPathW(NULL,CSIDL_TEMPLATES,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, TemplF, pth);
+ msi_set_property(package->db, TemplF, pth);
SHGetFolderPathW(NULL,CSIDL_DESKTOP,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, DF, pth);
+ msi_set_property(package->db, DF, pth);
SHGetFolderPathW(NULL,CSIDL_PROGRAMS,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, PMF, pth);
+ msi_set_property(package->db, PMF, pth);
SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, ATF, pth);
+ msi_set_property(package->db, ATF, pth);
SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, ADF, pth);
+ msi_set_property(package->db, ADF, pth);
SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, SF, pth);
- MSI_SetPropertyW(package, SF16, pth);
+ msi_set_property(package->db, SF, pth);
+ msi_set_property(package->db, SF16, pth);
SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, LADF, pth);
+ msi_set_property(package->db, LADF, pth);
SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, MPF, pth);
+ msi_set_property(package->db, MPF, pth);
SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, PF, pth);
+ msi_set_property(package->db, PF, pth);
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
strcatW(pth, szBackSlash);
- MSI_SetPropertyW(package, WF, pth);
+ msi_set_property(package->db, WF, pth);
/* Physical Memory is specified in MB. Using total amount. */
msex.dwLength = sizeof(msex);
GlobalMemoryStatusEx( &msex );
sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys/1024/1024));
- MSI_SetPropertyW(package, szPhysicalMemory, bufstr);
+ msi_set_property(package->db, szPhysicalMemory, bufstr);
SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
ptr = strchrW(pth,'\\');
if (ptr)
*(ptr+1) = 0;
- MSI_SetPropertyW(package, WV, pth);
+ msi_set_property(package->db, WV, pth);
GetTempPathW(MAX_PATH,pth);
- MSI_SetPropertyW(package, TF, pth);
+ msi_set_property(package->db, TF, pth);
/* in a wine environment the user is always admin and privileged */
- MSI_SetPropertyW(package,szAdminUser,szOne);
- MSI_SetPropertyW(package,szPriv,szOne);
+ msi_set_property(package->db, szAdminUser, szOne);
+ msi_set_property(package->db, szPriv, szOne);
/* set the os things */
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
switch (OSVersion.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
- MSI_SetPropertyW(package,v9x,verstr);
+ msi_set_property(package->db, v9x, verstr);
break;
case VER_PLATFORM_WIN32_NT:
- MSI_SetPropertyW(package,vNT,verstr);
+ msi_set_property(package->db, vNT, verstr);
sprintfW(verstr,szFormat,OSVersion.wProductType);
- MSI_SetPropertyW(package,szMsiNTProductType,verstr);
+ msi_set_property(package->db, szMsiNTProductType, verstr);
break;
}
sprintfW(verstr,szFormat,OSVersion.dwBuildNumber);
- MSI_SetPropertyW(package,szWinBuild,verstr);
+ msi_set_property(package->db, szWinBuild, verstr);
/* just fudge this */
- MSI_SetPropertyW(package,szSPL,szSix);
+ msi_set_property(package->db, szSPL, szSix);
sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
- MSI_SetPropertyW( package, szVersionMsi, bufstr );
+ msi_set_property( package->db, szVersionMsi, bufstr );
sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
- MSI_SetPropertyW( package, szVersionDatabase, bufstr );
+ msi_set_property( package->db, szVersionDatabase, bufstr );
GetSystemInfo( &sys_info );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
- MSI_SetPropertyW( package, szIntel, bufstr );
+ msi_set_property( package->db, szIntel, bufstr );
}
/* Screen properties. */
dc = GetDC(0);
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
- MSI_SetPropertyW( package, szScreenX, bufstr );
+ msi_set_property( package->db, szScreenX, bufstr );
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
- MSI_SetPropertyW( package, szScreenY, bufstr );
+ msi_set_property( package->db, szScreenY, bufstr );
sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
- MSI_SetPropertyW( package, szColorBits, bufstr );
+ msi_set_property( package->db, szColorBits, bufstr );
ReleaseDC(0, dc);
/* USERNAME and COMPANYNAME */
- username = msi_dup_property( package, szUSERNAME );
- companyname = msi_dup_property( package, szCOMPANYNAME );
+ username = msi_dup_property( package->db, szUSERNAME );
+ companyname = msi_dup_property( package->db, szCOMPANYNAME );
if ((!username || !companyname) &&
RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
{
if (!username &&
(username = msi_reg_get_val_str( hkey, szDefName )))
- MSI_SetPropertyW( package, szUSERNAME, username );
+ msi_set_property( package->db, szUSERNAME, username );
if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szDefCompany )))
- MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
+ msi_set_property( package->db, szCOMPANYNAME, companyname );
CloseHandle( hkey );
}
if ((!username || !companyname) &&
{
if (!username &&
(username = msi_reg_get_val_str( hkey, szRegisteredUser )))
- MSI_SetPropertyW( package, szUSERNAME, username );
+ msi_set_property( package->db, szUSERNAME, username );
if (!companyname &&
(companyname = msi_reg_get_val_str( hkey, szRegisteredOrg )))
- MSI_SetPropertyW( package, szCOMPANYNAME, companyname );
+ msi_set_property( package->db, szCOMPANYNAME, companyname );
CloseHandle( hkey );
}
msi_free( username );
GetSystemTime( &systemtime );
if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
- MSI_SetPropertyW( package, szDate, bufstr );
+ msi_set_property( package->db, szDate, bufstr );
else
ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
&systemtime, NULL, bufstr,
sizeof(bufstr)/sizeof(bufstr[0]) ))
- MSI_SetPropertyW( package, szTime, bufstr );
+ msi_set_property( package->db, szTime, bufstr );
else
ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
langid = GetUserDefaultLangID();
sprintfW(bufstr, szIntFormat, langid);
-
- MSI_SetPropertyW( package, szUserLangID, bufstr );
+ msi_set_property( package->db, szUserLangID, bufstr );
langid = GetSystemDefaultLangID();
sprintfW(bufstr, szIntFormat, langid);
-
- MSI_SetPropertyW( package, szSystemLangID, bufstr );
+ msi_set_property( package->db, szSystemLangID, bufstr );
sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
- MSI_SetPropertyW( package, szProductState, bufstr );
+ msi_set_property( package->db, szProductState, bufstr );
len = 0;
if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_MORE_DATA)
{
WCHAR *username;
- if ((username = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+ if ((username = msi_alloc( len * sizeof(WCHAR) )))
{
if (GetUserNameW( username, &len ))
- MSI_SetPropertyW( package, szLogonUser, username );
- HeapFree( GetProcessHeap(), 0, username );
+ msi_set_property( package->db, szLogonUser, username );
+ msi_free( username );
}
}
}
goto done;
}
- MSI_SetPropertyW( package, szPackageCode, package_code );
+ msi_set_property( package->db, szPackageCode, package_code );
msi_free( package_code );
/* load package attributes */
list_init( &package->RunningActions );
list_init( &package->sourcelist_info );
list_init( &package->sourcelist_media );
+ list_init( &package->patches );
}
return package;
static void adjust_allusers_property( MSIPACKAGE *package )
{
/* FIXME: this should depend on the user's privileges */
- if (msi_get_property_int( package, szAllUsers, 0 ) == 2)
+ if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
{
TRACE("resetting ALLUSERS property from 2 to 1\n");
- MSI_SetPropertyW( package, szAllUsers, szOne );
+ msi_set_property( package->db, szAllUsers, szOne );
}
}
create_temp_property_table( package );
msi_clone_properties( package );
- package->ProductCode = msi_dup_property( package, szProductCode );
+ package->ProductCode = msi_dup_property( package->db, szProductCode );
+ package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
+
set_installed_prop( package );
set_installer_properties( package );
sprintfW(uilevel,szpi,gUILevel);
- MSI_SetPropertyW(package, szLevel, uilevel);
+ msi_set_property(package->db, szLevel, uilevel);
r = msi_load_summary_properties( package );
if (r != ERROR_SUCCESS)
GetUrlCacheEntryInfoW( szUrl, NULL, &size );
if ( GetLastError() != ERROR_FILE_NOT_FOUND )
{
- cache_entry = HeapAlloc( GetProcessHeap(), 0, size );
+ cache_entry = msi_alloc( size );
if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
{
UINT error = GetLastError();
- HeapFree( GetProcessHeap(), 0, cache_entry );
+ msi_free( cache_entry );
return error;
}
lstrcpyW( filename, cache_entry->lpszLocalFileName );
- HeapFree( GetProcessHeap(), 0, cache_entry );
+ msi_free( cache_entry );
return ERROR_SUCCESS;
}
return ERROR_SUCCESS;
}
-static UINT msi_get_local_package_name( LPWSTR path )
+UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix )
{
static const WCHAR szInstaller[] = {
'\\','I','n','s','t','a','l','l','e','r','\\',0};
- static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
- DWORD time, len, i;
+ static const WCHAR fmt[] = {'%','x',0};
+ DWORD time, len, i, offset;
HANDLE handle;
time = GetTickCount();
len = strlenW(path);
for (i = 0; i < 0x10000; i++)
{
- snprintfW( &path[len], MAX_PATH - len, fmt, (time + i)&0xffff );
+ offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff );
+ memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) );
handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
if (handle != INVALID_HANDLE_VALUE)
return ERROR_SUCCESS;
}
+static UINT apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code )
+{
+ UINT r;
+ DWORD len;
+ WCHAR patch_file[MAX_PATH];
+ MSIDATABASE *patch_db;
+ MSIPATCHINFO *patch_info;
+ MSISUMMARYINFO *si;
+
+ len = sizeof(patch_file) / sizeof(WCHAR);
+ r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context,
+ INSTALLPROPERTY_LOCALPACKAGEW, patch_file, &len );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("failed to get patch filename %u\n", r);
+ return r;
+ }
+
+ r = MSI_OpenDatabaseW( patch_file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
+ return r;
+ }
+
+ si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
+ if (!si)
+ {
+ msiobj_release( &patch_db->hdr );
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ r = msi_parse_patch_summary( si, &patch_info );
+ msiobj_release( &si->hdr );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("failed to parse patch summary %u\n", r);
+ msiobj_release( &patch_db->hdr );
+ return r;
+ }
+
+ r = msi_apply_patch_db( package, patch_db, patch_info );
+ msiobj_release( &patch_db->hdr );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("failed to apply patch %u\n", r);
+ msi_free( patch_info->patchcode );
+ msi_free( patch_info->transforms );
+ msi_free( patch_info->localfile );
+ msi_free( patch_info );
+ }
+ return r;
+}
+
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
{
- static const WCHAR OriginalDatabase[] =
- {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
+ static const WCHAR dotmsi[] = {'.','m','s','i',0};
MSIDATABASE *db = NULL;
MSIPACKAGE *package;
MSIHANDLE handle;
UINT r;
WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
LPCWSTR file = szPackage;
+ DWORD index = 0;
TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
file = temppath;
}
- r = msi_get_local_package_name( localfile );
+ r = msi_get_local_package_name( localfile, dotmsi );
if (r != ERROR_SUCCESS)
return r;
if( file != szPackage )
track_tempfile( package, file );
- MSI_SetPropertyW( package, Database, db->path );
+ msi_set_property( package->db, Database, db->path );
if( UrlIsW( szPackage, URLIS_URL ) )
- MSI_SetPropertyW( package, OriginalDatabase, szPackage );
+ msi_set_property( package->db, szOriginalDatabase, szPackage );
else if( szPackage[0] == '#' )
- MSI_SetPropertyW( package, OriginalDatabase, db->path );
+ msi_set_property( package->db, szOriginalDatabase, db->path );
else
{
WCHAR fullpath[MAX_PATH];
GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
- MSI_SetPropertyW( package, OriginalDatabase, fullpath );
+ msi_set_property( package->db, szOriginalDatabase, fullpath );
}
- package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
- *pPackage = package;
+ msi_set_context( package );
+
+ while (1)
+ {
+ WCHAR patch_code[GUID_SIZE];
+ r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
+ MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
+ if (r != ERROR_SUCCESS)
+ break;
+
+ TRACE("found registered patch %s\n", debugstr_w(patch_code));
+
+ r = apply_registered_patch( package, patch_code );
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("registered patch failed to apply %u\n", r);
+ MSI_FreePackage( (MSIOBJECTHDR *)package );
+ return r;
+ }
+
+ index++;
+ }
+ *pPackage = package;
return ERROR_SUCCESS;
}
{
MSIPACKAGE *package;
MSIHANDLE handle = 0;
+ IUnknown *remote_unk;
IWineMsiRemotePackage *remote_package;
TRACE("(%d)\n",hInstall);
handle = alloc_msihandle( &package->db->hdr );
msiobj_release( &package->hdr );
}
- else if ((remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall )))
+ else if ((remote_unk = msi_get_remote(hInstall)))
{
- IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
- IWineMsiRemotePackage_Release(remote_package);
+ if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage,
+ (LPVOID *)&remote_package) == S_OK)
+ {
+ IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
+ IWineMsiRemotePackage_Release(remote_package);
+ }
+ else
+ {
+ WARN("remote handle %d is not a package\n", hInstall);
+ }
+ IUnknown_Release(remote_unk);
}
return handle;
return r;
}
-static void msi_reset_folders( MSIPACKAGE *package, BOOL source )
+void msi_reset_folders( MSIPACKAGE *package, BOOL source )
{
MSIFOLDER *folder;
}
}
-UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue)
+UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
{
MSIQUERY *view;
MSIRECORD *row = NULL;
'`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
- TRACE("%p %s %s\n", package, debugstr_w(szName), debugstr_w(szValue));
+ TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue));
if (!szName)
return ERROR_INVALID_PARAMETER;
if (!szName[0])
return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
- rc = MSI_GetPropertyW(package, szName, 0, &sz);
+ rc = msi_get_property(db, szName, 0, &sz);
if (!szValue || !*szValue)
{
sprintfW(Query, Delete, szName);
MSI_RecordSetStringW(row, 2, szValue);
}
- rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
+ rc = MSI_DatabaseOpenViewW(db, Query, &view);
if (rc == ERROR_SUCCESS)
{
rc = MSI_ViewExecute(view, row);
if (row)
msiobj_release(&row->hdr);
- if (rc == ERROR_SUCCESS && (!lstrcmpW(szName, cszSourceDir)))
- msi_reset_folders(package, TRUE);
-
return rc;
}
return ERROR_SUCCESS;
}
- ret = MSI_SetPropertyW( package, szName, szValue);
+ ret = msi_set_property( package->db, szName, szValue );
+ if (ret == ERROR_SUCCESS && !strcmpW( szName, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
+
msiobj_release( &package->hdr );
return ret;
}
-static MSIRECORD *MSI_GetPropertyRow( MSIPACKAGE *package, LPCWSTR name )
+static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
{
MSIQUERY *view;
MSIRECORD *rec, *row = NULL;
MSI_RecordSetStringW(rec, 1, name);
- r = MSI_DatabaseOpenViewW(package->db, query, &view);
+ r = MSI_DatabaseOpenViewW(db, query, &view);
if (r == ERROR_SUCCESS)
{
MSI_ViewExecute(view, rec);
}
/* internal function, not compatible with MsiGetPropertyW */
-UINT MSI_GetPropertyW( MSIPACKAGE *package, LPCWSTR szName,
+UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
LPWSTR szValueBuf, LPDWORD pchValueBuf )
{
MSIRECORD *row;
UINT rc = ERROR_FUNCTION_FAILED;
- row = MSI_GetPropertyRow( package, szName );
+ row = msi_get_property_row( db, szName );
if (*pchValueBuf > 0)
szValueBuf[0] = 0;
return rc;
}
-LPWSTR msi_dup_property(MSIPACKAGE *package, LPCWSTR prop)
+LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
{
DWORD sz = 0;
LPWSTR str;
UINT r;
- r = MSI_GetPropertyW(package, prop, NULL, &sz);
+ r = msi_get_property(db, prop, NULL, &sz);
if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
return NULL;
sz++;
str = msi_alloc(sz * sizeof(WCHAR));
- r = MSI_GetPropertyW(package, prop, str, &sz);
+ r = msi_get_property(db, prop, str, &sz);
if (r != ERROR_SUCCESS)
{
msi_free(str);
return str;
}
-int msi_get_property_int(MSIPACKAGE *package, LPCWSTR prop, int def)
+int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
{
- LPWSTR str = msi_dup_property(package, prop);
+ LPWSTR str = msi_dup_property( db, prop );
int val = str ? atoiW(str) : def;
msi_free(str);
return val;
return r;
}
- row = MSI_GetPropertyRow( package, name );
+ row = msi_get_property_row( package->db, name );
if (row)
val = MSI_RecordGetString( row, 1 );
'U','s','e','r','D','a','t','a','\\',
'%','s','\\','P','a','t','c','h','e','s','\\','%','s',0};
+static const WCHAR szUserDataProductPatches_fmt[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'W','i','n','d','o','w','s','\\',
+'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'U','s','e','r','D','a','t','a','\\',
+'%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
+'P','a','t','c','h','e','s',0};
+
static const WCHAR szInstallProperties_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
out[0] = 0;
- if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
+ if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
return FALSE;
for(i=0; i<8; i++)
return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
}
+UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context)
+{
+ UINT r;
+ WCHAR squished_patch[GUID_SIZE];
+ WCHAR keypath[0x200];
+ LPWSTR usersid;
+
+ TRACE("%s\n", debugstr_w(patch));
+ if (!squash_guid(patch, squished_patch))
+ return ERROR_FUNCTION_FAILED;
+ TRACE("squished (%s)\n", debugstr_w(squished_patch));
+
+ if (context == MSIINSTALLCONTEXT_MACHINE)
+ sprintfW(keypath, szUserDataPatch_fmt, szLocalSid, squished_patch);
+ else
+ {
+ r = get_user_sid(&usersid);
+ if (r != ERROR_SUCCESS || !usersid)
+ {
+ ERR("Failed to retrieve user SID: %d\n", r);
+ return r;
+ }
+
+ sprintfW(keypath, szUserDataPatch_fmt, usersid, squished_patch);
+ LocalFree(usersid);
+ }
+
+ return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
+}
+
+UINT MSIREG_OpenUserDataProductPatchesKey(LPCWSTR product, MSIINSTALLCONTEXT context,
+ HKEY *key, BOOL create)
+{
+ UINT rc;
+ WCHAR squished_product[GUID_SIZE];
+ WCHAR keypath[0x200];
+ LPWSTR usersid;
+
+ TRACE("%s\n", debugstr_w(product));
+ if (!squash_guid(product, squished_product))
+ return ERROR_FUNCTION_FAILED;
+
+ if (context == MSIINSTALLCONTEXT_MACHINE)
+ sprintfW(keypath, szUserDataProductPatches_fmt, szLocalSid, squished_product);
+ else
+ {
+ rc = get_user_sid(&usersid);
+ if (rc != ERROR_SUCCESS || !usersid)
+ {
+ ERR("Failed to retrieve user SID: %d\n", rc);
+ return rc;
+ }
+
+ sprintfW(keypath, szUserDataProductPatches_fmt, usersid, squished_product);
+ LocalFree(usersid);
+ }
+
+ if (create)
+ return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+
+ return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+}
+
UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext,
LPCWSTR szUserSid, HKEY *key, BOOL create)
{
len = ( &p[21] - szDescriptor );
TRACE("length = %d\n", len);
- *pUsed = len;
+ if (pUsed) *pUsed = len;
return ERROR_SUCCESS;
}
if (index && index - last_index != 1)
return ERROR_INVALID_PARAMETER;
+ key = 0;
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProd, &key);
- if( r != ERROR_SUCCESS )
- return ERROR_NO_MORE_ITEMS;
+ if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &machine_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
- if( r != ERROR_SUCCESS )
- {
- RegCloseKey(key);
- return ERROR_NO_MORE_ITEMS;
- }
+ if( r != ERROR_SUCCESS ) goto failed;
if (machine_count && index <= machine_count)
{
}
RegCloseKey(key);
+ key = 0;
r = get_user_sid(&usersid);
if (r != ERROR_SUCCESS || !usersid)
{
ERR("Failed to retrieve user SID: %d\n", r);
+ last_index = 0;
return r;
}
sprintfW(keypath, szInstaller_LocalManaged_fmt, usersid);
LocalFree(usersid);
r = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, &key);
- if( r != ERROR_SUCCESS )
- return ERROR_NO_MORE_ITEMS;
+ if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &managed_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
- if( r != ERROR_SUCCESS )
- {
- RegCloseKey(key);
- return ERROR_NO_MORE_ITEMS;
- }
+ if( r != ERROR_SUCCESS ) goto failed;
if (managed_count && index <= machine_count + managed_count)
{
}
RegCloseKey(key);
+ key = 0;
r = RegCreateKeyW(HKEY_CURRENT_USER, szUserProduct, &key);
- if( r != ERROR_SUCCESS )
- return ERROR_NO_MORE_ITEMS;
+ if( r != ERROR_SUCCESS ) goto failed;
r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &unmanaged_count, NULL, NULL,
NULL, NULL, NULL, NULL, NULL);
- if( r != ERROR_SUCCESS )
- {
- RegCloseKey(key);
- return ERROR_NO_MORE_ITEMS;
- }
+ if( r != ERROR_SUCCESS ) goto failed;
if (unmanaged_count && index <= machine_count + managed_count + unmanaged_count)
{
return ERROR_SUCCESS;
}
}
+failed:
RegCloseKey(key);
-
+ last_index = 0;
return ERROR_NO_MORE_ITEMS;
}
DWORD idx = 0;
UINT r;
- static int last_index = 0;
+ static DWORD last_index;
TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter,
if (r == ERROR_SUCCESS)
last_index = dwIndex;
+ else
+ last_index = 0;
return r;
}
if( pUnkOuter )
return CLASS_E_NOAGGREGATION;
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MsiActiveScriptSite));
+ object = msi_alloc_zero( sizeof(MsiActiveScriptSite) );
object->lpVtbl.lpVtbl = &ASS_Vtbl;
object->ref = 1;
TRACE("(%p/%p)\n", iface, This);
if (!ref)
- HeapFree(GetProcessHeap(), 0, This);
+ msi_free(This);
return ref;
}
typedef struct tabSTORAGE
{
UINT str_index;
- LPWSTR name;
IStorage *storage;
} STORAGE;
return TRUE;
}
-static STORAGE *create_storage(MSISTORAGESVIEW *sv, LPWSTR name, IStorage *stg)
+static STORAGE *create_storage(MSISTORAGESVIEW *sv, LPCWSTR name, IStorage *stg)
{
STORAGE *storage;
if (!storage)
return NULL;
- storage->name = strdupW(name);
- if (!storage->name)
- {
- msi_free(storage);
- return NULL;
- }
-
- storage->str_index = msi_addstringW(sv->db->strings, 0, storage->name, -1, 1, StringNonPersistent);
+ storage->str_index = msi_addstringW(sv->db->strings, name, -1, 1, StringNonPersistent);
storage->storage = stg;
if (storage->storage)
{
if (sv->storages[i]->storage)
IStorage_Release(sv->storages[i]->storage);
-
- msi_free(sv->storages[i]->name);
msi_free(sv->storages[i]);
}
return TRUE;
}
-static STREAM *create_stream(MSISTREAMSVIEW *sv, LPWSTR name, BOOL encoded, IStream *stm)
+static STREAM *create_stream(MSISTREAMSVIEW *sv, LPCWSTR name, BOOL encoded, IStream *stm)
{
STREAM *stream;
WCHAR decoded[MAX_STREAM_NAME_LEN];
name = decoded;
}
- stream->str_index = msi_addstringW(sv->db->strings, 0, name, -1, 1, StringNonPersistent);
+ stream->str_index = msi_addstringW(sv->db->strings, name, -1, 1, StringNonPersistent);
stream->stream = stm;
return stream;
}
}
encname = encode_streamname(FALSE, name);
- IStorage_DestroyElement(sv->db->storage, encname);
+ db_destroy_stream(sv->db, encname);
r = write_stream_data(sv->db->storage, name, data, count, FALSE);
if (r != ERROR_SUCCESS)
typedef struct _msistring
{
- UINT persistent_refcount;
- UINT nonpersistent_refcount;
+ USHORT persistent_refcount;
+ USHORT nonpersistent_refcount;
LPWSTR str;
} msistring;
st->sortcount++;
}
-static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, enum StringPersistence persistence )
+static void set_st_entry( string_table *st, UINT n, LPWSTR str, USHORT refcount, enum StringPersistence persistence )
{
if (persistence == StringPersistent)
{
return r;
}
-static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, UINT refcount, enum StringPersistence persistence )
+static int msi_addstring( string_table *st, UINT n, const CHAR *data, int len, USHORT refcount, enum StringPersistence persistence )
{
LPWSTR str;
int sz;
return n;
}
-int msi_addstringW( string_table *st, UINT n, const WCHAR *data, int len, UINT refcount, enum StringPersistence persistence )
+int msi_addstringW( string_table *st, const WCHAR *data, int len, USHORT refcount, enum StringPersistence persistence )
{
+ UINT n;
LPWSTR str;
- /* TRACE("[%2d] = %s\n", string_no, debugstr_an(data,len) ); */
-
if( !data )
return 0;
if( !data[0] )
return 0;
- if( n > 0 )
- {
- if( st->strings[n].persistent_refcount ||
- st->strings[n].nonpersistent_refcount )
- return -1;
- }
- else
+
+ if( msi_string2idW( st, data, &n ) == ERROR_SUCCESS )
{
- if( ERROR_SUCCESS == msi_string2idW( st, data, &n ) )
- {
- if (persistence == StringPersistent)
- st->strings[n].persistent_refcount += refcount;
- else
- st->strings[n].nonpersistent_refcount += refcount;
- return n;
- }
- n = st_find_free_entry( st );
- if( n == -1 )
- return -1;
+ if (persistence == StringPersistent)
+ st->strings[n].persistent_refcount += refcount;
+ else
+ st->strings[n].nonpersistent_refcount += refcount;
+ return n;
}
- if( n < 1 )
- {
- ERR("invalid index adding %s (%d)\n", debugstr_w( data ), n );
+ n = st_find_free_entry( st );
+ if( n == -1 )
return -1;
- }
/* allocate a new string */
if(len<0)
if ( r != ERROR_SUCCESS )
{
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
- val = msi_addstringW( tv->db->strings, 0, sval, -1, 1,
+ val = msi_addstringW( tv->db->strings, sval, -1, 1,
persistent ? StringPersistent : StringNonPersistent );
}
LPWSTR prop;
LPWSTR newprop;
DWORD len;
+ UINT r;
- prop = msi_dup_property(package, action_property );
+ prop = msi_dup_property(package->db, action_property );
if (prop)
len = strlenW(prop);
else
newprop[0] = 0;
strcatW(newprop,productid);
- MSI_SetPropertyW(package, action_property, newprop);
- TRACE("Found Related Product... %s now %s\n",debugstr_w(action_property),
- debugstr_w(newprop));
+ r = msi_set_property( package->db, action_property, newprop );
+ if (r == ERROR_SUCCESS && !strcmpW( action_property, cszSourceDir ))
+ msi_reset_folders( package, TRUE );
+
+ TRACE("Found Related Product... %s now %s\n",
+ debugstr_w(action_property), debugstr_w(newprop));
+
msi_free( prop );
msi_free( newprop );
}
(LPBYTE)&check, &sz);
/* check min */
ver = MSI_RecordGetString(rec,2);
- comp_ver = msi_version_str_to_dword(ver);
- r = check - comp_ver;
- if (r < 0 || (r == 0 && !(attributes &
- msidbUpgradeAttributesVersionMinInclusive)))
+ if (ver)
{
- RegCloseKey(hukey);
- index ++;
- continue;
+ comp_ver = msi_version_str_to_dword(ver);
+ r = check - comp_ver;
+ if (r < 0 || (r == 0 && !(attributes & msidbUpgradeAttributesVersionMinInclusive)))
+ {
+ RegCloseKey(hukey);
+ index ++;
+ continue;
+ }
}
/* check max */
ver = MSI_RecordGetString(rec,3);
- comp_ver = msi_version_str_to_dword(ver);
- r = check - comp_ver;
- if (r > 0 || (r == 0 && !(attributes &
- msidbUpgradeAttributesVersionMaxInclusive)))
+ if (ver)
{
- RegCloseKey(hukey);
- index ++;
- continue;
+ comp_ver = msi_version_str_to_dword(ver);
+ r = check - comp_ver;
+ if (r > 0 || (r == 0 && !(attributes & msidbUpgradeAttributesVersionMaxInclusive)))
+ {
+ RegCloseKey(hukey);
+ index ++;
+ continue;
+ }
}
/* check language*/
UINT rc = ERROR_SUCCESS;
MSIQUERY *view;
- if (msi_get_property_int(package, szInstalled, 0))
+ if (msi_get_property_int(package->db, szInstalled, 0))
{
TRACE("Skipping FindRelatedProducts action: product already installed\n");
return ERROR_SUCCESS;
}
- if (check_unique_action(package,szFindRelatedProducts))
+ if (check_unique_action(package, szFindRelatedProducts))
{
- TRACE("Skipping FindRelatedProducts action: already done on client side\n");
+ TRACE("Skipping FindRelatedProducts action: already done in UI sequence\n");
return ERROR_SUCCESS;
}
else
- register_unique_action(package,szFindRelatedProducts);
+ register_unique_action(package, szFindRelatedProducts);
rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
if (rc != ERROR_SUCCESS)