diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index 59ef8c33583..a22091f95fa 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -2614,15 +2614,44 @@ static void msi_dialog_vcl_add_columns( msi_dialog *dialog, msi_control *control } } +static LONGLONG msi_vcl_get_cost( msi_dialog *dialog ) +{ + MSIFEATURE *feature; + INT each_cost; + LONGLONG total_cost = 0; + + LIST_FOR_EACH_ENTRY( feature, &dialog->package->features, MSIFEATURE, entry ) + { + if (ERROR_SUCCESS == (MSI_GetFeatureCost(dialog->package, feature, + MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &each_cost))) + { + /* each_cost is in 512-byte units */ + total_cost += each_cost * 512; + } + if (ERROR_SUCCESS == (MSI_GetFeatureCost(dialog->package, feature, + MSICOSTTREE_SELFONLY, INSTALLSTATE_ABSENT, &each_cost))) + { + /* each_cost is in 512-byte units */ + total_cost -= each_cost * 512; + } + } + return total_cost; +} + static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control ) { ULARGE_INTEGER total, free; + LONGLONG difference, cost; WCHAR size_text[MAX_PATH]; + WCHAR cost_text[MAX_PATH]; LPWSTR drives, ptr; LVITEMW lvitem; DWORD size; int i = 0; + cost = msi_vcl_get_cost(dialog); + StrFormatByteSizeW(cost, cost_text, MAX_PATH); + size = GetLogicalDriveStringsW( 0, NULL ); if ( !size ) return; @@ -2642,6 +2671,7 @@ static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control SendMessageW( control->hwnd, LVM_INSERTITEMW, 0, (LPARAM)&lvitem ); GetDiskFreeSpaceExW(ptr, &free, &total, NULL); + difference = free.QuadPart - cost; StrFormatByteSizeW(total.QuadPart, size_text, MAX_PATH); lvitem.iSubItem = 1; @@ -2655,6 +2685,17 @@ static void msi_dialog_vcl_add_drives( msi_dialog *dialog, msi_control *control lvitem.cchTextMax = lstrlenW(size_text) + 1; SendMessageW( control->hwnd, LVM_SETITEMW, 0, (LPARAM)&lvitem ); + lvitem.iSubItem = 3; + lvitem.pszText = cost_text; + lvitem.cchTextMax = lstrlenW(cost_text) + 1; + SendMessageW( control->hwnd, LVM_SETITEMW, 0, (LPARAM)&lvitem ); + + StrFormatByteSizeW(difference, size_text, MAX_PATH); + lvitem.iSubItem = 4; + lvitem.pszText = size_text; + lvitem.cchTextMax = lstrlenW(size_text) + 1; + SendMessageW( control->hwnd, LVM_SETITEMW, 0, (LPARAM)&lvitem ); + ptr += lstrlenW(ptr) + 1; i++; } diff --git a/dlls/msi/install.c b/dlls/msi/install.c index 606caba1345..1a535eb0273 100644 --- a/dlls/msi/install.c +++ b/dlls/msi/install.c @@ -934,8 +934,24 @@ UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature, UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature, MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost) { - FIXME("(%d %s %i %i %p): stub\n", hInstall, debugstr_a(szFeature), - iCostTree, iState, piCost); + LPWSTR szwFeature = NULL; + UINT rc; + + szwFeature = strdupAtoW(szFeature); + + rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost); + + msi_free(szwFeature); + + return rc; +} + +UINT MSI_GetFeatureCost(MSIPACKAGE *package, MSIFEATURE *feature, + MSICOSTTREE iCostTree, INSTALLSTATE iState, + LPINT piCost) +{ + FIXME("(%s %i %i %p): not implemented yet\n", + debugstr_w(feature->Feature), iCostTree, iState, piCost); if (piCost) *piCost = 0; return ERROR_SUCCESS; } @@ -946,10 +962,57 @@ UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature, UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature, MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost) { - FIXME("(%d %s %i %i %p): stub\n", hInstall, debugstr_w(szFeature), + MSIPACKAGE *package; + MSIFEATURE *feature; + UINT ret; + + TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature), iCostTree, iState, piCost); - if (piCost) *piCost = 0; - return ERROR_SUCCESS; + + package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); + if (!package) + { + HRESULT hr; + BSTR feature; + IWineMsiRemotePackage *remote_package; + + remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall); + if (!remote_package) + return ERROR_INVALID_HANDLE; + + feature = SysAllocString(szFeature); + if (!feature) + { + IWineMsiRemotePackage_Release(remote_package); + return ERROR_OUTOFMEMORY; + } + + hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature, + iCostTree, iState, piCost); + + SysFreeString(feature); + IWineMsiRemotePackage_Release(remote_package); + + if (FAILED(hr)) + { + if (HRESULT_FACILITY(hr) == FACILITY_WIN32) + return HRESULT_CODE(hr); + + return ERROR_FUNCTION_FAILED; + } + + return ERROR_SUCCESS; + } + + feature = get_loaded_feature(package, szFeature); + + if (feature) + ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost); + else + ret = ERROR_UNKNOWN_FEATURE; + + msiobj_release( &package->hdr ); + return ret; } /*********************************************************************** diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 38103d8d581..5b23f55b189 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -759,6 +759,7 @@ extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename ); 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_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE, LPINT); /* for deformating */ extern UINT MSI_FormatRecordW( MSIPACKAGE *, MSIRECORD *, LPWSTR, LPDWORD ); diff --git a/dlls/msi/msiserver.idl b/dlls/msi/msiserver.idl index 2189fc4c9af..753cbb06886 100644 --- a/dlls/msi/msiserver.idl +++ b/dlls/msi/msiserver.idl @@ -71,6 +71,7 @@ interface IWineMsiRemotePackage : IUnknown HRESULT SetInstallLevel( [in] int level ); HRESULT FormatRecord( [in] MSIHANDLE record, [out] BSTR *value ); HRESULT EvaluateCondition( [in] BSTR condition ); + HRESULT GetFeatureCost( [in] BSTR feature, [in] INT cost_tree, [in] INSTALLSTATE state, [out] INT *cost); } [ diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 7f1363322c2..87f1092c9e9 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -1898,6 +1898,14 @@ static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR return HRESULT_FROM_WIN32(r); } +static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature, + INT cost_tree, INSTALLSTATE state, INT *cost ) +{ + msi_remote_package_impl* This = mrp_from_IWineMsiRemotePackage( iface ); + UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost); + return HRESULT_FROM_WIN32(r); +} + static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl = { mrp_QueryInterface, @@ -1922,6 +1930,7 @@ static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl = mrp_SetInstallLevel, mrp_FormatRecord, mrp_EvaluateCondition, + mrp_GetFeatureCost, }; HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )