Sync to trunk (r44371)
[reactos.git] / reactos / dll / win32 / msi / install.c
index 63b1d64..f77da3f 100644 (file)
 
 /* Msi top level apis directly related to installs */
 
+#define COBJMACROS
+
 #include <stdarg.h>
 
-#include "stdio.h"
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
 #include "wine/debug.h"
 #include "msi.h"
 #include "msidefs.h"
+#include "objbase.h"
+#include "oleauto.h"
+
 #include "msipriv.h"
+#include "msiserver.h"
 #include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
@@ -68,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;
@@ -107,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 );
@@ -150,21 +215,74 @@ UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
 /***********************************************************************
  * MsiGetTargetPath   (internal)
  */
-static 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;
+        }
+
+        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;
 
-    path = resolve_folder( package, szFolder, FALSE, FALSE, NULL );
+        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)
@@ -179,7 +297,7 @@ static 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;
@@ -205,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;
 
@@ -221,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 )
     {
@@ -242,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));
@@ -258,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;
@@ -280,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;
 
@@ -341,7 +512,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
            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;
 
@@ -356,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
@@ -371,7 +542,7 @@ 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);
         }
 
@@ -383,7 +554,7 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
             if (!comp)
                 continue;
 
-            p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
+            p = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL);
             msi_free(file->TargetPath);
 
             file->TargetPath = build_directory_name(2, p, file->FileName);
@@ -411,7 +582,41 @@ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
 
     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 );
@@ -453,8 +658,29 @@ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
  */
 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:
@@ -462,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;
     }
 
@@ -493,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;
 }
@@ -540,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);
 
@@ -568,7 +801,37 @@ UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
 
     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);
 
@@ -623,11 +886,43 @@ UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
     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;
@@ -637,10 +932,26 @@ UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
 * MsiGetFeatureCostA   (MSI.@)
 */
 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
-                  MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
+                  MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
 {
-    FIXME("(%ld %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;
 }
@@ -649,14 +960,61 @@ UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
 * MsiGetFeatureCostW   (MSI.@)
 */
 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
-                  MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
+                  MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
 {
-    FIXME("(%ld %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;
+
+    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.@)
  */
@@ -741,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;
@@ -756,12 +1145,44 @@ UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
     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;
@@ -779,7 +1200,22 @@ LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
     
     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);
+
+        if (SUCCEEDED(hr))
+            return lang;
+
+        return 0;
+    }
 
     langid = msi_get_property_int( package, szProductLanguage, 0 );
     msiobj_release( &package->hdr );
@@ -796,15 +1232,16 @@ UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
 
     TRACE("%p %i\n", package, iInstallLevel);
 
-    if (iInstallLevel<1 || iInstallLevel>32767)
+    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;
 }
@@ -817,11 +1254,32 @@ UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
     MSIPACKAGE* package;
     UINT r;
 
-    TRACE("%ld %i\n", hInstall, iInstallLevel);
+    TRACE("%d %i\n", hInstall, iInstallLevel);
 
-    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
-    if ( !package )
-        return ERROR_INVALID_HANDLE;
+    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 );
 
@@ -829,3 +1287,32 @@ UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
 
     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;
+}