[MSI] Sync with Wine Staging 2.9. CORE-13362

f6ced24 msi: Avoid using isspace()/isdigit() for WCHARs.
635457b msi: Add MsiGetPatchFileListA/W stubs.
b956b1f msi: Set patch property Uninstallable.
f3adb4a msi: Properly handle DWORD registry values in MsiGetPatchInfoEx.
d94653d msi: Apply feature selection to the whole feature subtree.
d12728a msi: Avoid zero size allocations (Valgrind).
b53957d msi: Use the correct type when calculating feature cost.
64c0625 msi: Implement MsiGetComponentPathExA/W.
5aa2d48 msi: Fix some more spec file entries.

svn path=/trunk/; revision=74818
This commit is contained in:
Amine Khaldi 2017-06-03 22:29:55 +00:00
parent 04488bf33d
commit 69571f3303
9 changed files with 244 additions and 132 deletions

View file

@ -1756,6 +1756,45 @@ static BOOL process_overrides( MSIPACKAGE *package, int level )
return ret;
}
static void disable_children( MSIFEATURE *feature, int level )
{
FeatureList *fl;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
if (!is_feature_selected( feature, level ))
{
TRACE("child %s (level %d request %d) follows disabled parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Level = feature->Level;
fl->feature->Action = INSTALLSTATE_UNKNOWN;
fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN;
}
disable_children( fl->feature, level );
}
}
static void follow_parent( MSIFEATURE *feature )
{
FeatureList *fl;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
if (fl->feature->Attributes & msidbFeatureAttributesFollowParent)
{
TRACE("child %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest;
}
follow_parent( fl->feature );
}
}
UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{
int level;
@ -1794,24 +1833,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
/* disable child features of unselected parent or follow parent */
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
FeatureList *fl;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
if (!is_feature_selected( feature, level ))
{
fl->feature->Action = INSTALLSTATE_UNKNOWN;
fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN;
}
else if (fl->feature->Attributes & msidbFeatureAttributesFollowParent)
{
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest;
}
}
if (feature->Feature_Parent) continue;
disable_children( feature, level );
follow_parent( feature );
}
}
else /* preselected */
@ -1836,22 +1860,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
FeatureList *fl;
if (!is_feature_selected( feature, level )) continue;
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
{
if (fl->feature->Attributes & msidbFeatureAttributesFollowParent &&
(!(feature->Attributes & msidbFeatureAttributesFavorAdvertise)))
{
TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n",
debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest,
debugstr_w(feature->Feature), feature->Level, feature->ActionRequest);
fl->feature->Action = feature->Action;
fl->feature->ActionRequest = feature->ActionRequest;
}
}
if (feature->Feature_Parent) continue;
disable_children( feature, level );
follow_parent( feature );
}
}
@ -4404,7 +4415,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;

View file

@ -1174,11 +1174,11 @@ UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
static INT feature_cost( MSIFEATURE *feature )
{
INT cost = 0;
MSICOMPONENT *comp;
ComponentList *cl;
LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry )
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{
cost += comp->Cost;
cost += cl->component->Cost;
}
return cost;
}

View file

@ -1051,26 +1051,26 @@ done:
return rc;
}
static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type)
static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type )
{
DWORD dval;
LONG res;
WCHAR temp[20];
static const WCHAR format[] = {'%','d',0};
if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL;
res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL);
if (res != ERROR_SUCCESS)
return NULL;
if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name );
if (*type == REG_DWORD)
{
static const WCHAR fmt[] = {'%','u',0};
WCHAR temp[11];
DWORD val;
if (*type == REG_SZ)
return msi_reg_get_val_str(hkey, name);
if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL;
sprintfW( temp, fmt, val );
return strdupW( temp );
}
if (!msi_reg_get_val_dword(hkey, name, &dval))
return NULL;
sprintfW(temp, format, dval);
return strdupW(temp);
ERR( "unhandled value type %u\n", *type );
return NULL;
}
static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
@ -1144,7 +1144,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
szAttribute = display_version;
val = msi_reg_get_value(userdata, szAttribute, &type);
val = reg_get_value(userdata, szAttribute, &type);
if (!val)
val = empty;
RegCloseKey(userdata);
@ -1178,7 +1178,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
goto done;
}
val = msi_reg_get_value(source, szAttribute, &type);
val = reg_get_value(source, szAttribute, &type);
if (!val)
val = empty;
@ -1186,7 +1186,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
}
else
{
val = msi_reg_get_value(prodkey, szAttribute, &type);
val = reg_get_value(prodkey, szAttribute, &type);
if (!val)
val = empty;
}
@ -1468,7 +1468,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
!strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
!strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
{
val = msi_reg_get_value(props, package, &type);
val = reg_get_value(props, package, &type);
if (!val)
{
if (prod || classes)
@ -1484,7 +1484,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
szProperty = displayversion;
val = msi_reg_get_value(props, szProperty, &type);
val = reg_get_value(props, szProperty, &type);
if (!val)
val = strdupW(szEmpty);
@ -1509,7 +1509,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
hkey = classes;
val = msi_reg_get_value(hkey, szProperty, &type);
val = reg_get_value(hkey, szProperty, &type);
if (!val)
val = strdupW(szEmpty);
@ -1521,7 +1521,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
{
if (props)
{
val = msi_reg_get_value(props, package, &type);
val = reg_get_value(props, package, &type);
if (!val)
goto done;
@ -1534,7 +1534,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
r = msi_copy_outval(val, szValue, pcchValue);
goto done;
}
else if (props && (val = msi_reg_get_value(props, package, &type)))
else if (props && (val = reg_get_value(props, package, &type)))
{
msi_free(val);
val = strdupW(five);
@ -1571,6 +1571,22 @@ done:
return r;
}
UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList,
LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
{
FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode),
debugstr_a(szPatchList), pcFiles, pphFileRecords);
return ERROR_FUNCTION_FAILED;
}
UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList,
LPDWORD pcFiles, MSIHANDLE **pphFileRecords)
{
FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode),
debugstr_w(szPatchList), pcFiles, pphFileRecords);
return ERROR_FUNCTION_FAILED;
}
UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
@ -1650,7 +1666,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
HKEY udpatch = 0, datakey = 0;
HKEY prodpatches = 0;
UINT r = ERROR_UNKNOWN_PRODUCT;
DWORD len;
DWORD len, type;
LONG res;
TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode),
@ -1742,7 +1758,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
}
}
val = msi_reg_get_val_str(datakey, szProperty);
val = reg_get_value(datakey, szProperty, &type);
if (!val)
val = strdupW(szEmpty);
@ -2754,8 +2770,28 @@ UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
return r;
}
static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
awstring* lpPathBuf, LPDWORD pcchBuf)
static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx,
HKEY *hkey )
{
if (ctx & MSIINSTALLCONTEXT_MACHINE)
{
if (!MSIREG_OpenUserDataComponentKey( comp, szLocalSid, hkey, FALSE )) return TRUE;
}
if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED))
{
if (usersid && !strcmpiW( usersid, szAllSid ))
{
FIXME( "only looking at the current user\n" );
usersid = NULL;
}
if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE;
}
return FALSE;
}
static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent,
const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx,
awstring *lpPathBuf, DWORD *pcchBuf )
{
static const WCHAR wininstaller[] =
{'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
@ -2773,20 +2809,20 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp ))
return INSTALLSTATE_INVALIDARG;
if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE)
return INSTALLSTATE_INVALIDARG;
state = INSTALLSTATE_UNKNOWN;
if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
{
path = msi_reg_get_val_str( hkey, squashed_pc );
RegCloseKey(hkey);
state = INSTALLSTATE_ABSENT;
if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL,
&hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) ||
!MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) &&
msi_reg_get_val_dword(hkey, wininstaller, &version) &&
GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
{
@ -2796,16 +2832,12 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
}
if (state != INSTALLSTATE_LOCAL &&
(MSIREG_OpenProductKey(szProduct, NULL,
MSIINSTALLCONTEXT_USERUNMANAGED,
&hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&hkey, FALSE) == ERROR_SUCCESS))
(!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) ||
!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE)))
{
RegCloseKey(hkey);
if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
{
msi_free(path);
path = msi_reg_get_val_str( hkey, squashed_pc );
@ -2832,51 +2864,63 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
}
/******************************************************************
* MsiGetComponentPathW [MSI.@]
* MsiGetComponentPathExW [MSI.@]
*/
INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent,
LPWSTR lpPathBuf, LPDWORD pcchBuf)
INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid,
MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen )
{
awstring path;
TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szComponent), lpPathBuf, pcchBuf);
TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid),
ctx, buf, buflen );
path.unicode = TRUE;
path.str.w = lpPathBuf;
path.str.w = buf;
return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf );
return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen );
}
INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid,
MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen )
{
WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL;
INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
awstring path;
TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid),
ctx, buf, buflen );
if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN;
if (comp && !(compW = strdupAtoW( comp ))) goto end;
if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end;
path.unicode = FALSE;
path.str.a = buf;
r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen );
end:
msi_free( productW );
msi_free( compW );
msi_free( usersidW );
return r;
}
/******************************************************************
* MsiGetComponentPathW [MSI.@]
*/
INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen )
{
return MsiGetComponentPathExW( product, comp, szAllSid, MSIINSTALLCONTEXT_ALL, buf, buflen );
}
/******************************************************************
* MsiGetComponentPathA [MSI.@]
*/
INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent,
LPSTR lpPathBuf, LPDWORD pcchBuf)
INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen )
{
LPWSTR szwProduct, szwComponent = NULL;
INSTALLSTATE r = INSTALLSTATE_UNKNOWN;
awstring path;
TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szComponent), lpPathBuf, pcchBuf);
szwProduct = strdupAtoW( szProduct );
if( szProduct && !szwProduct)
goto end;
szwComponent = strdupAtoW( szComponent );
if( szComponent && !szwComponent )
goto end;
path.unicode = FALSE;
path.str.a = lpPathBuf;
r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf );
end:
msi_free( szwProduct );
msi_free( szwComponent );
return r;
return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
}
static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid,
@ -3398,7 +3442,7 @@ static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent,
StringFromGUID2( &guid, comp, sizeof(comp)/sizeof(comp[0]) );
}
state = MSI_GetComponentPath( szProduct, comp, lpPathBuf, pcchPathBuf );
state = MSI_GetComponentPath( szProduct, comp, szAllSid, MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf );
if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA;
if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND;

View file

@ -20,8 +20,8 @@
24 stdcall MsiDatabaseGenerateTransformW(long long wstr long long)
25 stdcall MsiDatabaseGetPrimaryKeysA(long str ptr)
26 stdcall MsiDatabaseGetPrimaryKeysW(long wstr ptr)
27 stdcall MsiDatabaseImportA(str str long)
28 stdcall MsiDatabaseImportW(wstr wstr long)
27 stdcall MsiDatabaseImportA(str str str)
28 stdcall MsiDatabaseImportW(wstr wstr wstr)
29 stdcall MsiDatabaseMergeA(long long str)
30 stdcall MsiDatabaseMergeW(long long wstr)
31 stdcall MsiDatabaseOpenViewA(long str ptr)
@ -189,10 +189,10 @@
193 stdcall MsiUseFeatureExW(wstr wstr long long)
194 stdcall MsiGetFileVersionA(str ptr ptr ptr ptr)
195 stdcall MsiGetFileVersionW(wstr ptr ptr ptr ptr)
196 stdcall MsiLoadStringA(long long long long long)
197 stdcall MsiLoadStringW(long long long long long)
198 stdcall MsiMessageBoxA(long long long long long long)
199 stdcall MsiMessageBoxW(long long long long long long)
196 stdcall MsiLoadStringA(long long ptr long long)
197 stdcall MsiLoadStringW(long long ptr long long)
198 stdcall MsiMessageBoxA(long str str long long long)
199 stdcall MsiMessageBoxW(long wstr wstr long long long)
200 stdcall MsiDecomposeDescriptorA(str ptr ptr ptr ptr)
201 stdcall MsiDecomposeDescriptorW(wstr ptr ptr ptr ptr)
202 stdcall MsiProvideQualifiedComponentExA(str str long str long long ptr ptr)
@ -275,8 +275,8 @@
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)
282 stub MsiGetPatchFileListA
283 stub MsiGetPatchFileListW
282 stdcall MsiGetPatchFileListA(str str ptr ptr)
283 stdcall MsiGetPatchFileListW(wstr wstr ptr ptr)
284 stdcall MsiBeginTransactionA(str long ptr ptr)
285 stdcall MsiBeginTransactionW(wstr long ptr ptr)
286 stdcall MsiEndTransaction(long)
@ -286,8 +286,8 @@
290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr)
291 stdcall MsiEnumClientsExA(str str long long ptr ptr ptr ptr)
292 stdcall MsiEnumClientsExW(wstr wstr long long ptr ptr ptr ptr)
293 stub MsiGetComponentPathExA
294 stub MsiGetComponentPathExW
293 stdcall MsiGetComponentPathExA(str str str long ptr ptr)
294 stdcall MsiGetComponentPathExW(wstr wstr wstr long ptr ptr)
295 stub QueryInstanceCount
@ stdcall -private DllCanUnloadNow()

View file

@ -206,6 +206,7 @@ typedef struct tagMSIPATCHINFO
LPWSTR filename;
LPWSTR localfile;
MSIPATCHSTATE state;
DWORD uninstallable;
BOOL delete_on_close;
BOOL registered;
UINT disk_id;
@ -1213,6 +1214,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);

View file

@ -827,6 +827,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;
@ -852,7 +884,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;
}

View file

@ -405,13 +405,11 @@ static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg
goto err;
}
t->row_count = rawsize / row_size;
t->data = msi_alloc_zero( t->row_count * sizeof (USHORT*) );
if( !t->data )
goto err;
t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL));
if ( !t->data_persistent )
goto err;
if ((t->row_count = rawsize / row_size))
{
if (!(t->data = msi_alloc_zero( t->row_count * sizeof(USHORT *) ))) goto err;
if (!(t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL) ))) goto err;
}
/* transpose all the data */
TRACE("Transposing data from %d rows\n", t->row_count );

View file

@ -180,6 +180,21 @@ static const char isIdChar[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Fx */
};
/*
** WCHAR safe version of isdigit()
*/
static inline int isDigit(WCHAR c)
{
return c >= '0' && c <= '9';
}
/*
** WCHAR safe version of isspace(), except '\r'
*/
static inline int isSpace(WCHAR c)
{
return c == ' ' || c == '\t' || c == '\n' || c == '\f';
}
/*
** Return the length of the token that begins at z[0]. Return
@ -192,7 +207,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){
*skip = 0;
switch( *z ){
case ' ': case '\t': case '\n': case '\f':
for(i=1; isspace(z[i]) && z[i] != '\r'; i++){}
for(i=1; isSpace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
case '-':
@ -258,7 +273,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){
return i;
}
case '.':
if( !isdigit(z[1]) ){
if( !isDigit(z[1]) ){
*tokenType = TK_DOT;
return 1;
}
@ -266,7 +281,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
for(i=1; isDigit(z[i]); i++){}
return i;
case '[':
for(i=1; z[i] && z[i-1]!=']'; i++){}

View file

@ -112,7 +112,7 @@ reactos/dll/win32/msg711.acm # Synced to WineStaging-2.2
reactos/dll/win32/msgsm32.acm # Synced to WineStaging-1.9.11
reactos/dll/win32/mshtml # Synced to WineStaging-1.7.55
reactos/dll/win32/mshtml.tlb # Synced to WineStaging-1.7.55
reactos/dll/win32/msi # Synced to WineStaging-2.2
reactos/dll/win32/msi # Synced to WineStaging-2.9
reactos/dll/win32/msimg32 # Synced to WineStaging-1.9.11
reactos/dll/win32/msimtf # Synced to WineStaging-1.9.23
reactos/dll/win32/msisip # Synced to WineStaging-1.9.11