diff --git a/dlls/msi/action.c b/dlls/msi/action.c index ab701c2dd74..16652000ee5 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -4431,7 +4431,16 @@ static UINT msi_publish_patches( MSIPACKAGE *package ) if (res != ERROR_SUCCESS) goto done; - res = RegSetValueExW( patch_key, szState, 0, REG_DWORD, (const BYTE *)&patch->state, sizeof(patch->state) ); + res = RegSetValueExW( patch_key, szState, 0, REG_DWORD, (const BYTE *)&patch->state, + sizeof(patch->state) ); + if (res != ERROR_SUCCESS) + { + RegCloseKey( patch_key ); + goto done; + } + + res = RegSetValueExW( patch_key, szUninstallable, 0, REG_DWORD, (const BYTE *)&patch->uninstallable, + sizeof(patch->uninstallable) ); RegCloseKey( patch_key ); if (res != ERROR_SUCCESS) goto done; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 56ba72540ae..2e9e91e754e 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -192,6 +192,7 @@ typedef struct tagMSIPATCHINFO LPWSTR filename; LPWSTR localfile; MSIPATCHSTATE state; + DWORD uninstallable; BOOL delete_on_close; BOOL registered; UINT disk_id; @@ -1198,6 +1199,7 @@ static const WCHAR szData[] = {'D','a','t','a',0}; static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','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 szProperty[] = {'P','r','o','p','e','r','t','y',0}; +static const WCHAR szUninstallable[] = {'U','n','i','n','s','t','a','l','l','a','b','l','e',0}; /* memory allocation macro functions */ static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); diff --git a/dlls/msi/patch.c b/dlls/msi/patch.c index eb91e06e9a9..f6ed3c1f1a4 100644 --- a/dlls/msi/patch.c +++ b/dlls/msi/patch.c @@ -836,6 +836,38 @@ done: return r; } +static DWORD is_uninstallable( MSIDATABASE *db ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ','F','R','O','M',' ', + '`','M','s','i','P','a','t','c','h','M','e','t','a','d','a','t','a','`',' ', + 'W','H','E','R','E',' ','`','C','o','m','p','a','n','y','`',' ','I','S',' ', + 'N','U','L','L',' ','A','N','D',' ','`','P','r','o','p','e','r','t','y','`','=', + '\'','A','l','l','o','w','R','e','m','o','v','a','l','\'',0}; + MSIQUERY *view; + MSIRECORD *rec; + DWORD ret = 0; + + if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) return 0; + if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) + { + msiobj_release( &view->hdr ); + return 0; + } + + if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) + { + const WCHAR *value = MSI_RecordGetString( rec, 1 ); + ret = atoiW( value ); + msiobj_release( &rec->hdr ); + } + + FIXME( "check other criteria\n" ); + + msiobj_release( &view->hdr ); + return ret; +} + static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ) { UINT i, r = ERROR_SUCCESS; @@ -861,7 +893,8 @@ static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIP if (r != ERROR_SUCCESS) return r; - patch->state = MSIPATCHSTATE_APPLIED; + patch->uninstallable = is_uninstallable( patch_db ); + patch->state = MSIPATCHSTATE_APPLIED; list_add_tail( &package->patches, &patch->entry ); return ERROR_SUCCESS; }