mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 09:50:07 +00:00
[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:
parent
04488bf33d
commit
69571f3303
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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++){}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue