[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; 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) UINT MSI_SetFeatureStates(MSIPACKAGE *package)
{ {
int level; int level;
@ -1794,24 +1833,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
/* disable child features of unselected parent or follow parent */ /* disable child features of unselected parent or follow parent */
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
FeatureList *fl; if (feature->Feature_Parent) continue;
disable_children( feature, level );
LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) follow_parent( feature );
{
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;
}
}
} }
} }
else /* preselected */ else /* preselected */
@ -1836,22 +1860,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
} }
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
FeatureList *fl; if (feature->Feature_Parent) continue;
disable_children( feature, level );
if (!is_feature_selected( feature, level )) continue; follow_parent( feature );
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;
}
}
} }
} }
@ -4404,7 +4415,16 @@ static UINT msi_publish_patches( MSIPACKAGE *package )
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
goto done; 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 ); RegCloseKey( patch_key );
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
goto done; goto done;

View file

@ -1174,11 +1174,11 @@ UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
static INT feature_cost( MSIFEATURE *feature ) static INT feature_cost( MSIFEATURE *feature )
{ {
INT cost = 0; 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; return cost;
} }

View file

@ -1051,26 +1051,26 @@ done:
return rc; 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; 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 (*type == REG_SZ) return msi_reg_get_val_str( hkey, name );
if (res != ERROR_SUCCESS) if (*type == REG_DWORD)
return NULL; {
static const WCHAR fmt[] = {'%','u',0};
WCHAR temp[11];
DWORD val;
if (*type == REG_SZ) if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL;
return msi_reg_get_val_str(hkey, name); sprintfW( temp, fmt, val );
return strdupW( temp );
}
if (!msi_reg_get_val_dword(hkey, name, &dval)) ERR( "unhandled value type %u\n", *type );
return NULL; return NULL;
sprintfW(temp, format, dval);
return strdupW(temp);
} }
static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, 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 )) else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW ))
szAttribute = display_version; szAttribute = display_version;
val = msi_reg_get_value(userdata, szAttribute, &type); val = reg_get_value(userdata, szAttribute, &type);
if (!val) if (!val)
val = empty; val = empty;
RegCloseKey(userdata); RegCloseKey(userdata);
@ -1178,7 +1178,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
goto done; goto done;
} }
val = msi_reg_get_value(source, szAttribute, &type); val = reg_get_value(source, szAttribute, &type);
if (!val) if (!val)
val = empty; val = empty;
@ -1186,7 +1186,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute,
} }
else else
{ {
val = msi_reg_get_value(prodkey, szAttribute, &type); val = reg_get_value(prodkey, szAttribute, &type);
if (!val) if (!val)
val = empty; val = empty;
} }
@ -1468,7 +1468,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
!strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) || !strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) ||
!strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW )) !strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW ))
{ {
val = msi_reg_get_value(props, package, &type); val = reg_get_value(props, package, &type);
if (!val) if (!val)
{ {
if (prod || classes) if (prod || classes)
@ -1484,7 +1484,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW )) else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW ))
szProperty = displayversion; szProperty = displayversion;
val = msi_reg_get_value(props, szProperty, &type); val = reg_get_value(props, szProperty, &type);
if (!val) if (!val)
val = strdupW(szEmpty); val = strdupW(szEmpty);
@ -1509,7 +1509,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
else if (dwContext == MSIINSTALLCONTEXT_MACHINE) else if (dwContext == MSIINSTALLCONTEXT_MACHINE)
hkey = classes; hkey = classes;
val = msi_reg_get_value(hkey, szProperty, &type); val = reg_get_value(hkey, szProperty, &type);
if (!val) if (!val)
val = strdupW(szEmpty); val = strdupW(szEmpty);
@ -1521,7 +1521,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
{ {
if (props) if (props)
{ {
val = msi_reg_get_value(props, package, &type); val = reg_get_value(props, package, &type);
if (!val) if (!val)
goto done; goto done;
@ -1534,7 +1534,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
r = msi_copy_outval(val, szValue, pcchValue); r = msi_copy_outval(val, szValue, pcchValue);
goto done; 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); msi_free(val);
val = strdupW(five); val = strdupW(five);
@ -1571,6 +1571,22 @@ done:
return r; 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, UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode,
LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue) LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
@ -1650,7 +1666,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode,
HKEY udpatch = 0, datakey = 0; HKEY udpatch = 0, datakey = 0;
HKEY prodpatches = 0; HKEY prodpatches = 0;
UINT r = ERROR_UNKNOWN_PRODUCT; UINT r = ERROR_UNKNOWN_PRODUCT;
DWORD len; DWORD len, type;
LONG res; LONG res;
TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode), 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) if (!val)
val = strdupW(szEmpty); val = strdupW(szEmpty);
@ -2754,8 +2770,28 @@ UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage )
return r; return r;
} }
static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx,
awstring* lpPathBuf, LPDWORD pcchBuf) 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[] = static const WCHAR wininstaller[] =
{'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; {'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 )) if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp ))
return INSTALLSTATE_INVALIDARG; return INSTALLSTATE_INVALIDARG;
if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE)
return INSTALLSTATE_INVALIDARG;
state = INSTALLSTATE_UNKNOWN; state = INSTALLSTATE_UNKNOWN;
if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
{ {
path = msi_reg_get_val_str( hkey, squashed_pc ); path = msi_reg_get_val_str( hkey, squashed_pc );
RegCloseKey(hkey); RegCloseKey(hkey);
state = INSTALLSTATE_ABSENT; state = INSTALLSTATE_ABSENT;
if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) ||
&hkey, FALSE) == ERROR_SUCCESS || !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) &&
MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
NULL, &hkey, FALSE) == ERROR_SUCCESS) &&
msi_reg_get_val_dword(hkey, wininstaller, &version) && msi_reg_get_val_dword(hkey, wininstaller, &version) &&
GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
{ {
@ -2796,16 +2832,12 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent,
} }
if (state != INSTALLSTATE_LOCAL && if (state != INSTALLSTATE_LOCAL &&
(MSIREG_OpenProductKey(szProduct, NULL, (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) ||
MSIINSTALLCONTEXT_USERUNMANAGED, !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE)))
&hkey, FALSE) == ERROR_SUCCESS ||
MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
&hkey, FALSE) == ERROR_SUCCESS))
{ {
RegCloseKey(hkey); RegCloseKey(hkey);
if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey ))
MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS)
{ {
msi_free(path); msi_free(path);
path = msi_reg_get_val_str( hkey, squashed_pc ); 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, INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid,
LPWSTR lpPathBuf, LPDWORD pcchBuf) MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen )
{ {
awstring path; 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.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.@] * MsiGetComponentPathA [MSI.@]
*/ */
INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent, INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen )
LPSTR lpPathBuf, LPDWORD pcchBuf)
{ {
LPWSTR szwProduct, szwComponent = NULL; return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen );
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;
} }
static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, 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]) ); 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_MOREDATA) return ERROR_MORE_DATA;
if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND; if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND;

View file

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

View file

@ -206,6 +206,7 @@ typedef struct tagMSIPATCHINFO
LPWSTR filename; LPWSTR filename;
LPWSTR localfile; LPWSTR localfile;
MSIPATCHSTATE state; MSIPATCHSTATE state;
DWORD uninstallable;
BOOL delete_on_close; BOOL delete_on_close;
BOOL registered; BOOL registered;
UINT disk_id; 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 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 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 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 */ /* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);

View file

@ -827,6 +827,38 @@ done:
return r; 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 ) static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch )
{ {
UINT i, r = ERROR_SUCCESS; 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) if (r != ERROR_SUCCESS)
return r; return r;
patch->state = MSIPATCHSTATE_APPLIED; patch->uninstallable = is_uninstallable( patch_db );
patch->state = MSIPATCHSTATE_APPLIED;
list_add_tail( &package->patches, &patch->entry ); list_add_tail( &package->patches, &patch->entry );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View file

@ -405,13 +405,11 @@ static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg
goto err; goto err;
} }
t->row_count = rawsize / row_size; if ((t->row_count = rawsize / row_size))
t->data = msi_alloc_zero( t->row_count * sizeof (USHORT*) ); {
if( !t->data ) if (!(t->data = msi_alloc_zero( t->row_count * sizeof(USHORT *) ))) goto err;
goto err; if (!(t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL) ))) goto err;
t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL)); }
if ( !t->data_persistent )
goto err;
/* transpose all the data */ /* transpose all the data */
TRACE("Transposing data from %d rows\n", t->row_count ); 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 */ 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 ** 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; *skip = 0;
switch( *z ){ switch( *z ){
case ' ': case '\t': case '\n': case '\f': 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; *tokenType = TK_SPACE;
return i; return i;
case '-': case '-':
@ -258,7 +273,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){
return i; return i;
} }
case '.': case '.':
if( !isdigit(z[1]) ){ if( !isDigit(z[1]) ){
*tokenType = TK_DOT; *tokenType = TK_DOT;
return 1; 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 '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
*tokenType = TK_INTEGER; *tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){} for(i=1; isDigit(z[i]); i++){}
return i; return i;
case '[': case '[':
for(i=1; z[i] && z[i-1]!=']'; i++){} 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/msgsm32.acm # Synced to WineStaging-1.9.11
reactos/dll/win32/mshtml # Synced to WineStaging-1.7.55 reactos/dll/win32/mshtml # Synced to WineStaging-1.7.55
reactos/dll/win32/mshtml.tlb # 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/msimg32 # Synced to WineStaging-1.9.11
reactos/dll/win32/msimtf # Synced to WineStaging-1.9.23 reactos/dll/win32/msimtf # Synced to WineStaging-1.9.23
reactos/dll/win32/msisip # Synced to WineStaging-1.9.11 reactos/dll/win32/msisip # Synced to WineStaging-1.9.11