Sync to trunk (r44371)
[reactos.git] / reactos / dll / win32 / msi / install.c
index 08b5f70..f77da3f 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 /* Msi top level apis directly related to installs */
 
+#define COBJMACROS
+
 #include <stdarg.h>
 
 #include "windef.h"
 #include "wine/debug.h"
 #include "msi.h"
 #include "msidefs.h"
+#include "objbase.h"
+#include "oleauto.h"
+
 #include "msipriv.h"
-#include "winuser.h"
+#include "msiserver.h"
 #include "wine/unicode.h"
-#include "action.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
@@ -69,9 +73,39 @@ UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
 
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        BSTR action;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        action = SysAllocString( szAction );
+        if (!action)
+        {
+            IWineMsiRemotePackage_Release( remote_package );
+            return ERROR_OUTOFMEMORY;
+        }
+
+        hr = IWineMsiRemotePackage_DoAction( remote_package, action );
+
+        SysFreeString( action );
+        IWineMsiRemotePackage_Release( remote_package );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
  
-    ret = ACTION_PerformUIAction( package, szAction );
+    ret = ACTION_PerformUIAction( package, szAction, -1 );
     msiobj_release( &package->hdr );
 
     return ret;
@@ -108,7 +142,37 @@ UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode
 
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        BSTR table;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        table = SysAllocString( szTable );
+        if (!table)
+        {
+            IWineMsiRemotePackage_Release( remote_package );
+            return ERROR_OUTOFMEMORY;
+        }
+
+        hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode );
+
+        SysFreeString( table );
+        IWineMsiRemotePackage_Release( remote_package );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
 
     ret = MSI_Sequence( package, szTable, iSequenceMode );
     msiobj_release( &package->hdr );
@@ -138,7 +202,7 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
         if (len)
             len--;
         WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
-        if ( *sz && (len >= *sz) )
+        if ( awbuf->str.a && *sz && (len >= *sz) )
             awbuf->str.a[*sz - 1] = 0;
     }
 
@@ -151,21 +215,74 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
 /***********************************************************************
  * MsiGetTargetPath   (internal)
  */
-UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
-                               awstring *szPathBuf, DWORD* pcchPathBuf )
+static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
+                               awstring *szPathBuf, LPDWORD pcchPathBuf )
 {
     MSIPACKAGE *package;
     LPWSTR path;
-    UINT r;
+    UINT r = ERROR_FUNCTION_FAILED;
 
     if (!szFolder)
         return ERROR_INVALID_PARAMETER;
 
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        IWineMsiRemotePackage *remote_package;
+        LPWSTR value = NULL;
+        BSTR folder;
+        DWORD len;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        folder = SysAllocString( szFolder );
+        if (!folder)
+        {
+            IWineMsiRemotePackage_Release( remote_package );
+            return ERROR_OUTOFMEMORY;
+        }
 
-    path = resolve_folder( package, szFolder, FALSE, FALSE, NULL );
+        len = 0;
+        hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
+                                                  NULL, &len );
+        if (FAILED(hr))
+            goto done;
+
+        len++;
+        value = msi_alloc(len * sizeof(WCHAR));
+        if (!value)
+        {
+            r = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+
+        hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
+                                                  (BSTR *)value, &len);
+        if (FAILED(hr))
+            goto done;
+
+        r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
+
+done:
+        IWineMsiRemotePackage_Release( remote_package );
+        SysFreeString( folder );
+        msi_free( value );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return r;
+    }
+
+    path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL );
     msiobj_release( &package->hdr );
 
     if (!path)
@@ -180,7 +297,7 @@ UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
  * MsiGetTargetPathA        (MSI.@)
  */
 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 
-                               LPSTR szPathBuf, DWORD* pcchPathBuf )
+                               LPSTR szPathBuf, LPDWORD pcchPathBuf )
 {
     LPWSTR szwFolder;
     awstring path;
@@ -206,7 +323,7 @@ UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
  * MsiGetTargetPathW        (MSI.@)
  */
 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
-                               LPWSTR szPathBuf, DWORD* pcchPathBuf )
+                               LPWSTR szPathBuf, LPDWORD pcchPathBuf )
 {
     awstring path;
 
@@ -222,20 +339,73 @@ UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
  * MsiGetSourcePath   (internal)
  */
 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
-                               awstring *szPathBuf, DWORD* pcchPathBuf )
+                               awstring *szPathBuf, LPDWORD pcchPathBuf )
 {
     MSIPACKAGE *package;
     LPWSTR path;
-    UINT r;
+    UINT r = ERROR_FUNCTION_FAILED;
 
     TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
 
     if (!szFolder)
         return ERROR_INVALID_PARAMETER;
 
-    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        IWineMsiRemotePackage *remote_package;
+        LPWSTR value = NULL;
+        BSTR folder;
+        DWORD len;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        folder = SysAllocString( szFolder );
+        if (!folder)
+        {
+            IWineMsiRemotePackage_Release( remote_package );
+            return ERROR_OUTOFMEMORY;
+        }
+
+        len = 0;
+        hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
+                                                  NULL, &len );
+        if (FAILED(hr))
+            goto done;
+
+        len++;
+        value = msi_alloc(len * sizeof(WCHAR));
+        if (!value)
+        {
+            r = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+
+        hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
+                                                  (BSTR *)value, &len);
+        if (FAILED(hr))
+            goto done;
+
+        r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
+
+done:
+        IWineMsiRemotePackage_Release( remote_package );
+        SysFreeString( folder );
+        msi_free( value );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return r;
+    }
 
     if (szPathBuf->str.w && !pcchPathBuf )
     {
@@ -243,7 +413,7 @@ static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
         return ERROR_INVALID_PARAMETER;
     }
 
-    path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
+    path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL);
     msiobj_release( &package->hdr );
 
     TRACE("path = %s\n",debugstr_w(path));
@@ -259,7 +429,7 @@ static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
  * MsiGetSourcePathA     (MSI.@)
  */
 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, 
-                               LPSTR szPathBuf, DWORD* pcchPathBuf )
+                               LPSTR szPathBuf, LPDWORD pcchPathBuf )
 {
     LPWSTR folder;
     awstring str;
@@ -281,7 +451,7 @@ UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
  * MsiGetSourcePathW     (MSI.@)
  */
 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
-                               LPWSTR szPathBuf, DWORD* pcchPathBuf )
+                               LPWSTR szPathBuf, LPDWORD pcchPathBuf )
 {
     awstring str;
 
@@ -331,30 +501,21 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
     LPWSTR path = NULL;
     LPWSTR path2 = NULL;
     MSIFOLDER *folder;
+    MSIFILE *file;
 
-    TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
+    TRACE("%p %s %s\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
 
     attrib = GetFileAttributesW(szFolderPath);
+    /* native MSI tests writeability by making temporary files at each drive */
     if ( attrib != INVALID_FILE_ATTRIBUTES &&
-          (!(attrib & FILE_ATTRIBUTE_DIRECTORY) ||
-           attrib & FILE_ATTRIBUTE_OFFLINE ||
+          (attrib & FILE_ATTRIBUTE_OFFLINE ||
            attrib & FILE_ATTRIBUTE_READONLY))
         return ERROR_FUNCTION_FAILED;
 
-    path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
+    path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder);
     if (!path)
         return ERROR_DIRECTORY;
 
-    if (attrib == INVALID_FILE_ATTRIBUTES)
-    {
-        if (!CreateDirectoryW(szFolderPath,NULL))
-        {
-            msi_free( path );
-            return ERROR_FUNCTION_FAILED;
-        }
-        RemoveDirectoryW(szFolderPath);
-    }
-
     msi_free(folder->Property);
     folder->Property = build_directory_name(2, szFolderPath, NULL);
 
@@ -366,7 +527,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
          */
         msi_free(folder->ResolvedTarget);
         folder->ResolvedTarget = NULL;
-        path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
+        path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL);
         msi_free(path2);
     }
     else
@@ -381,9 +542,24 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
 
         LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
         {
-            path2 = resolve_folder(package, f->Directory, FALSE, TRUE, NULL);
+            path2 = resolve_folder(package, f->Directory, FALSE, TRUE, FALSE, NULL);
             msi_free(path2);
         }
+
+        LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
+        {
+            MSICOMPONENT *comp = file->Component;
+            LPWSTR p;
+
+            if (!comp)
+                continue;
+
+            p = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL);
+            msi_free(file->TargetPath);
+
+            file->TargetPath = build_directory_name(2, p, file->FileName);
+            msi_free(p);
+        }
     }
     msi_free(path);
 
@@ -399,14 +575,48 @@ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
     MSIPACKAGE *package;
     UINT ret;
 
-    TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
+    TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
 
     if ( !szFolder || !szFolderPath )
         return ERROR_INVALID_PARAMETER;
 
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        BSTR folder, path;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        folder = SysAllocString( szFolder );
+        path = SysAllocString( szFolderPath );
+        if (!folder || !path)
+        {
+            SysFreeString(folder);
+            SysFreeString(path);
+            IWineMsiRemotePackage_Release( remote_package );
+            return ERROR_OUTOFMEMORY;
+        }
+
+        hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path );
+
+        SysFreeString(folder);
+        SysFreeString(path);
+        IWineMsiRemotePackage_Release( remote_package );
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
 
     ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
     msiobj_release( &package->hdr );
@@ -446,11 +656,31 @@ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
  *    Not in the state: FALSE
  *
  */
-
 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
 {
+    MSIPACKAGE *package;
     BOOL r = FALSE;
 
+    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+    if (!package)
+    {
+        BOOL ret;
+        HRESULT hr;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+        if (!remote_package)
+            return FALSE;
+
+        hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret);
+        IWineMsiRemotePackage_Release(remote_package);
+
+        if (hr == S_OK)
+            return ret;
+
+        return FALSE;
+    }
+
     switch (iRunMode)
     {
     case MSIRUNMODE_WINDOWS9X:
@@ -458,18 +688,26 @@ BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
             r = TRUE;
         break;
 
+    case MSIRUNMODE_OPERATIONS:
     case MSIRUNMODE_RESERVED11:
     case MSIRUNMODE_RESERVED14:
     case MSIRUNMODE_RESERVED15:
         break;
 
     case MSIRUNMODE_SCHEDULED:
+        r = package->scheduled_action_running;
+        break;
+
     case MSIRUNMODE_ROLLBACK:
+        r = package->rollback_action_running;
+        break;
+
     case MSIRUNMODE_COMMIT:
+        r = package->commit_action_running;
         break;
 
     default:
-        FIXME("%ld %d\n", hInstall, iRunMode);
+        FIXME("%d %d\n", hInstall, iRunMode);
         r = TRUE;
     }
 
@@ -489,7 +727,7 @@ BOOL WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
     case MSIRUNMODE_RESERVED15:
         return FALSE;
     default:
-        FIXME("%ld %d %d\n", hInstall, iRunMode, fState);
+        FIXME("%d %d %d\n", hInstall, iRunMode, fState);
     }
     return TRUE;
 }
@@ -526,7 +764,7 @@ UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
     UINT rc = ERROR_SUCCESS;
     MSIFEATURE *feature, *child;
 
-    TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
+    TRACE("%s %i\n", debugstr_w(szFeature), iState);
 
     feature = get_loaded_feature(package,szFeature);
     if (!feature)
@@ -536,8 +774,7 @@ UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
         feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
         return ERROR_FUNCTION_FAILED;
 
-    feature->ActionRequest = iState;
-    feature->Action = iState;
+    msi_feature_set_state(package, feature, iState);
 
     ACTION_UpdateComponentStates(package,szFeature);
 
@@ -560,11 +797,41 @@ UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
     MSIPACKAGE* package;
     UINT rc = ERROR_SUCCESS;
 
-    TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
+    TRACE("%s %i\n",debugstr_w(szFeature), iState);
 
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        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_SetFeatureState(remote_package, feature, iState);
+
+        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;
+    }
 
     rc = MSI_SetFeatureStateW(package,szFeature,iState);
 
@@ -575,7 +842,7 @@ UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
 /***********************************************************************
 * MsiGetFeatureStateA   (MSI.@)
 */
-UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
+UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     LPWSTR szwFeature = NULL;
@@ -590,7 +857,7 @@ UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
     return rc;
 }
 
-UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
+UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     MSIFEATURE *feature;
@@ -613,23 +880,141 @@ UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
 /***********************************************************************
 * MsiGetFeatureStateW   (MSI.@)
 */
-UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
+UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     MSIPACKAGE* package;
     UINT ret;
 
-    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
-piAction);
+    TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
 
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        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_GetFeatureState(remote_package, feature,
+                                                   piInstalled, piAction);
+
+        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;
+    }
+
     ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
     msiobj_release( &package->hdr );
     return ret;
 }
 
+/***********************************************************************
+* MsiGetFeatureCostA   (MSI.@)
+*/
+UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
+                  MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT 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;
+}
+
+/***********************************************************************
+* MsiGetFeatureCostW   (MSI.@)
+*/
+UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
+                  MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
+{
+    MSIPACKAGE *package;
+    MSIFEATURE *feature;
+    UINT ret;
+
+    TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
+          iCostTree, iState, piCost);
+
+    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;
+}
+
 /***********************************************************************
  * MsiSetComponentStateA (MSI.@)
  */
@@ -649,7 +1034,7 @@ UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
 /***********************************************************************
  * MsiGetComponentStateA (MSI.@)
  */
-UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
+UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     LPWSTR szwComponent= NULL;
@@ -680,7 +1065,7 @@ static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
     return ERROR_SUCCESS;
 }
 
-UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
+UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     MSICOMPONENT *comp;
@@ -714,7 +1099,38 @@ UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
 
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        BSTR component;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        component = SysAllocString(szComponent);
+        if (!component)
+        {
+            IWineMsiRemotePackage_Release(remote_package);
+            return ERROR_OUTOFMEMORY;
+        }
+
+        hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState);
+
+        SysFreeString(component);
+        IWineMsiRemotePackage_Release(remote_package);
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
+
     ret = MSI_SetComponentStateW(package, szComponent, iState);
     msiobj_release(&package->hdr);
     return ret;
@@ -723,18 +1139,50 @@ UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
 /***********************************************************************
  * MsiGetComponentStateW (MSI.@)
  */
-UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
+UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
 {
     MSIPACKAGE* package;
     UINT ret;
 
-    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
+    TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
            piInstalled, piAction);
 
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        BSTR component;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        component = SysAllocString(szComponent);
+        if (!component)
+        {
+            IWineMsiRemotePackage_Release(remote_package);
+            return ERROR_OUTOFMEMORY;
+        }
+
+        hr = IWineMsiRemotePackage_GetComponentState(remote_package, component,
+                                                     piInstalled, piAction);
+
+        SysFreeString(component);
+        IWineMsiRemotePackage_Release(remote_package);
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
+
     ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
     msiobj_release( &package->hdr );
     return ret;
@@ -747,18 +1195,124 @@ LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
 {
     MSIPACKAGE* package;
     LANGID langid;
-    LPWSTR buffer;
     static const WCHAR szProductLanguage[] =
         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
     
     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
     if (!package)
-        return ERROR_INVALID_HANDLE;
+    {
+        HRESULT hr;
+        LANGID lang;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang);
 
-    buffer = msi_dup_property( package, szProductLanguage );
-    langid = atoiW(buffer);
+        if (SUCCEEDED(hr))
+            return lang;
+
+        return 0;
+    }
 
-    msi_free(buffer);
-    msiobj_release (&package->hdr);
+    langid = msi_get_property_int( package, szProductLanguage, 0 );
+    msiobj_release( &package->hdr );
     return langid;
 }
+
+UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
+{
+    static const WCHAR szInstallLevel[] = {
+        'I','N','S','T','A','L','L','L','E','V','E','L',0 };
+    static const WCHAR fmt[] = { '%','d',0 };
+    WCHAR level[6];
+    UINT r;
+
+    TRACE("%p %i\n", package, iInstallLevel);
+
+    if (iInstallLevel > 32767)
+        return ERROR_INVALID_PARAMETER;
+
+    if (iInstallLevel < 1)
+        return MSI_SetFeatureStates( package );
+
+    sprintfW( level, fmt, iInstallLevel );
+    r = MSI_SetPropertyW( package, szInstallLevel, level );
+    if ( r == ERROR_SUCCESS )
+        r = MSI_SetFeatureStates( package );
+
+    return r;
+}
+
+/***********************************************************************
+ * MsiSetInstallLevel (MSI.@)
+ */
+UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
+{
+    MSIPACKAGE* package;
+    UINT r;
+
+    TRACE("%d %i\n", hInstall, iInstallLevel);
+
+    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+    if (!package)
+    {
+        HRESULT hr;
+        IWineMsiRemotePackage *remote_package;
+
+        remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+        if (!remote_package)
+            return ERROR_INVALID_HANDLE;
+
+        hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel);
+
+        IWineMsiRemotePackage_Release(remote_package);
+
+        if (FAILED(hr))
+        {
+            if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                return HRESULT_CODE(hr);
+
+            return ERROR_FUNCTION_FAILED;
+        }
+
+        return ERROR_SUCCESS;
+    }
+
+    r = MSI_SetInstallLevel( package, iInstallLevel );
+
+    msiobj_release( &package->hdr );
+
+    return r;
+}
+
+/***********************************************************************
+ * MsiGetFeatureValidStatesW (MSI.@)
+ */
+UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
+                  LPDWORD pInstallState)
+{
+    if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
+    FIXME("%d %s %p stub returning %d\n",
+        hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
+
+    return ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * MsiGetFeatureValidStatesA (MSI.@)
+ */
+UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
+                  LPDWORD pInstallState)
+{
+    UINT ret;
+    LPWSTR szwFeature = strdupAtoW(szFeature);
+
+    ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
+
+    msi_free(szwFeature);
+
+    return ret;
+}