[PATCH] msi: Disable filesystem redirection only when really needed.

Hans Leidekker hans at codeweavers.com
Wed Mar 20 03:43:44 CDT 2019


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46846
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/msi/action.c    | 236 ++++++++++++-------------------------
 dlls/msi/appsearch.c | 172 ++++++++++++---------------
 dlls/msi/custom.c    |   2 +-
 dlls/msi/files.c     | 319 +++++++++++++++++++++++++++++++++++++++++----------
 dlls/msi/font.c      |  20 ++--
 dlls/msi/install.c   |   2 +-
 dlls/msi/media.c     |  13 +--
 dlls/msi/msi.c       |  11 +-
 dlls/msi/msipriv.h   |  31 ++++-
 dlls/msi/package.c   |   7 ++
 10 files changed, 467 insertions(+), 346 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index d95960590c..b51a21d457 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -718,50 +718,6 @@ MSIFOLDER *msi_get_loaded_folder( MSIPACKAGE *package, const WCHAR *dir )
     return NULL;
 }
 
-/*
- * Recursively create all directories in the path.
- * shamelessly stolen from setupapi/queue.c
- */
-BOOL msi_create_full_path( const WCHAR *path )
-{
-    BOOL ret = TRUE;
-    WCHAR *new_path;
-    int len;
-
-    new_path = msi_alloc( (strlenW( path ) + 1) * sizeof(WCHAR) );
-    strcpyW( new_path, path );
-
-    while ((len = strlenW( new_path )) && new_path[len - 1] == '\\')
-    new_path[len - 1] = 0;
-
-    while (!CreateDirectoryW( new_path, NULL ))
-    {
-        WCHAR *slash;
-        DWORD last_error = GetLastError();
-        if (last_error == ERROR_ALREADY_EXISTS) break;
-        if (last_error != ERROR_PATH_NOT_FOUND)
-        {
-            ret = FALSE;
-            break;
-        }
-        if (!(slash = strrchrW( new_path, '\\' )))
-        {
-            ret = FALSE;
-            break;
-        }
-        len = slash - new_path;
-        new_path[len] = 0;
-        if (!msi_create_full_path( new_path ))
-        {
-            ret = FALSE;
-            break;
-        }
-        new_path[len] = '\\';
-    }
-    msi_free( new_path );
-    return ret;
-}
-
 void msi_ui_progress( MSIPACKAGE *package, int a, int b, int c, int d )
 {
     MSIRECORD *row;
@@ -843,8 +799,9 @@ static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
     TRACE("folder is %s\n", debugstr_w(full_path));
 
     folder = msi_get_loaded_folder( package, dir );
-    if (folder->State == FOLDER_STATE_UNINITIALIZED) msi_create_full_path( full_path );
+    if (folder->State == FOLDER_STATE_UNINITIALIZED) msi_create_full_path( package, full_path );
     folder->State = FOLDER_STATE_CREATED;
+
     return ERROR_SUCCESS;
 }
 
@@ -2054,37 +2011,6 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
     return ERROR_SUCCESS;
 }
 
-VS_FIXEDFILEINFO *msi_get_disk_file_version( LPCWSTR filename )
-{
-    static const WCHAR name[] = {'\\',0};
-    VS_FIXEDFILEINFO *ptr, *ret;
-    LPVOID version;
-    DWORD versize, handle;
-    UINT sz;
-
-    versize = GetFileVersionInfoSizeW( filename, &handle );
-    if (!versize)
-        return NULL;
-
-    version = msi_alloc( versize );
-    if (!version)
-        return NULL;
-
-    GetFileVersionInfoW( filename, 0, versize, version );
-
-    if (!VerQueryValueW( version, name, (LPVOID *)&ptr, &sz ))
-    {
-        msi_free( version );
-        return NULL;
-    }
-
-    ret = msi_alloc( sz );
-    memcpy( ret, ptr, sz );
-
-    msi_free( version );
-    return ret;
-}
-
 int msi_compare_file_versions( VS_FIXEDFILEINFO *fi, const WCHAR *version )
 {
     DWORD ms, ls;
@@ -2110,33 +2036,6 @@ int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
     return 0;
 }
 
-DWORD msi_get_disk_file_size( LPCWSTR filename )
-{
-    HANDLE file;
-    DWORD size;
-
-    file = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
-    if (file == INVALID_HANDLE_VALUE)
-        return INVALID_FILE_SIZE;
-
-    size = GetFileSize( file, NULL );
-    CloseHandle( file );
-    return size;
-}
-
-BOOL msi_file_hash_matches( MSIFILE *file )
-{
-    UINT r;
-    MSIFILEHASHINFO hash;
-
-    hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
-    r = msi_get_filehash( file->TargetPath, &hash );
-    if (r != ERROR_SUCCESS)
-        return FALSE;
-
-    return !memcmp( &hash, &file->hash, sizeof(MSIFILEHASHINFO) );
-}
-
 static WCHAR *create_temp_dir( MSIDATABASE *db )
 {
     static UINT id;
@@ -2262,17 +2161,17 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
         set_target_path( package, file );
 
         if ((comp->assembly && !comp->assembly->installed) ||
-            GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
+            msi_get_file_attributes( package, file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
         {
             comp->Cost += file->FileSize;
             continue;
         }
-        file_size = msi_get_disk_file_size( file->TargetPath );
+        file_size = msi_get_disk_file_size( package, file->TargetPath );
         TRACE("%s (size %u)\n", debugstr_w(file->TargetPath), file_size);
 
         if (file->Version)
         {
-            if ((file_version = msi_get_disk_file_version( file->TargetPath )))
+            if ((file_version = msi_get_disk_file_version( package, file->TargetPath )))
             {
                 if (msi_compare_file_versions( file_version, file->Version ) < 0)
                 {
@@ -2281,7 +2180,7 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
                 msi_free( file_version );
                 continue;
             }
-            else if ((font_version = msi_font_version_from_file( file->TargetPath )))
+            else if ((font_version = msi_get_font_file_version( package, file->TargetPath )))
             {
                 if (msi_compare_font_versions( font_version, file->Version ) < 0)
                 {
@@ -2296,6 +2195,7 @@ static UINT calculate_file_cost( MSIPACKAGE *package )
             comp->Cost += file->FileSize - file_size;
         }
     }
+
     return ERROR_SUCCESS;
 }
 
@@ -3754,6 +3654,24 @@ static BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType,
     return TRUE;
 }
 
+static HMODULE msi_load_library( MSIPACKAGE *package, const WCHAR *filename, DWORD flags )
+{
+    HMODULE module;
+    msi_disable_fs_redirection( package );
+    module = LoadLibraryExW( filename, NULL, flags );
+    msi_revert_fs_redirection( package );
+    return module;
+}
+
+static HRESULT msi_load_typelib( MSIPACKAGE *package, const WCHAR *filename, REGKIND kind, ITypeLib **lib )
+{
+    HRESULT hr;
+    msi_disable_fs_redirection( package );
+    hr = LoadTypeLibEx( filename, kind, lib );
+    msi_revert_fs_redirection( package );
+    return hr;
+}
+
 static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE* package = param;
@@ -3784,7 +3702,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
     }
     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
 
-    module = LoadLibraryExW( file->TargetPath, NULL, LOAD_LIBRARY_AS_DATAFILE );
+    module = msi_load_library( package, file->TargetPath, LOAD_LIBRARY_AS_DATAFILE );
     if (module)
     {
         LPCWSTR guid;
@@ -3821,7 +3739,7 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
     }
     else
     {
-        hr = LoadTypeLibEx(file->TargetPath, REGKIND_REGISTER, &tlib);
+        hr = msi_load_typelib( package, file->TargetPath, REGKIND_REGISTER, &tlib );
         if (FAILED(hr))
         {
             ERR("Failed to load type library: %08x\n", hr);
@@ -3932,7 +3850,7 @@ static WCHAR *get_link_file( MSIPACKAGE *package, MSIRECORD *row )
         return NULL;
     }
     /* may be needed because of a bug somewhere else */
-    msi_create_full_path( link_folder );
+    msi_create_full_path( package, link_folder );
 
     filename = msi_dup_record_field( row, 3 );
     msi_reduce_to_long_filename( filename );
@@ -3965,7 +3883,7 @@ WCHAR *msi_build_icon_path( MSIPACKAGE *package, const WCHAR *icon_name )
         msi_free( appdata );
     }
     dest = msi_build_directory_name( 3, folder, szInstaller, package->ProductCode );
-    msi_create_full_path( dest );
+    msi_create_full_path( package, dest );
     path = msi_build_directory_name( 2, dest, icon_name );
     msi_free( folder );
     msi_free( dest );
@@ -4069,10 +3987,14 @@ static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
         full_path = msi_get_target_folder( package, wkdir );
         if (full_path) IShellLinkW_SetWorkingDirectory( sl, full_path );
     }
-    link_file = get_link_file(package, row);
 
+    link_file = get_link_file(package, row);
     TRACE("Writing shortcut to %s\n", debugstr_w(link_file));
+
+    msi_disable_fs_redirection( package );
     IPersistFile_Save(pf, link_file, FALSE);
+    msi_revert_fs_redirection( package );
+
     msi_free(link_file);
 
 err:
@@ -4130,12 +4052,8 @@ static UINT ITERATE_RemoveShortcuts( MSIRECORD *row, LPVOID param )
     MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
 
     link_file = get_link_file( package, row );
-
     TRACE("Removing shortcut file %s\n", debugstr_w( link_file ));
-    if (!DeleteFileW( link_file ))
-    {
-        WARN("Failed to remove shortcut file %u\n", GetLastError());
-    }
+    if (!msi_delete_file( package, link_file )) WARN("Failed to remove shortcut file %u\n", GetLastError());
     msi_free( link_file );
 
     return ERROR_SUCCESS;
@@ -4163,51 +4081,49 @@ static UINT ACTION_RemoveShortcuts( MSIPACKAGE *package )
 
 static UINT ITERATE_PublishIcon(MSIRECORD *row, LPVOID param)
 {
-    MSIPACKAGE* package = param;
-    HANDLE the_file;
-    LPWSTR FilePath;
-    LPCWSTR FileName;
-    CHAR buffer[1024];
+    MSIPACKAGE *package = param;
+    HANDLE handle;
+    WCHAR *icon_path;
+    const WCHAR *filename;
+    char buffer[1024];
     DWORD sz;
     UINT rc;
 
-    FileName = MSI_RecordGetString(row,1);
-    if (!FileName)
+    filename = MSI_RecordGetString( row, 1 );
+    if (!filename)
     {
-        ERR("Unable to get FileName\n");
+        ERR("Unable to get filename\n");
         return ERROR_SUCCESS;
     }
 
-    FilePath = msi_build_icon_path(package, FileName);
-
-    TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
+    icon_path = msi_build_icon_path( package, filename );
 
-    the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
-                        FILE_ATTRIBUTE_NORMAL, NULL);
+    TRACE("Creating icon file at %s\n", debugstr_w(icon_path));
 
-    if (the_file == INVALID_HANDLE_VALUE)
+    handle = msi_create_file( package, icon_path, GENERIC_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL );
+    if (handle == INVALID_HANDLE_VALUE)
     {
-        ERR("Unable to create file %s\n",debugstr_w(FilePath));
-        msi_free(FilePath);
+        ERR("Unable to create file %s\n", debugstr_w(icon_path));
+        msi_free( icon_path );
         return ERROR_SUCCESS;
     }
 
-    do 
+    do
     {
-        DWORD write;
+        DWORD count;
         sz = 1024;
-        rc = MSI_RecordReadStream(row,2,buffer,&sz);
+        rc = MSI_RecordReadStream( row, 2, buffer, &sz );
         if (rc != ERROR_SUCCESS)
         {
             ERR("Failed to get stream\n");
-            DeleteFileW(FilePath);
+            msi_delete_file( package, icon_path );
             break;
         }
-        WriteFile(the_file,buffer,sz,&write,NULL);
+        WriteFile( handle, buffer, sz, &count, NULL );
     } while (sz == 1024);
 
-    msi_free(FilePath);
-    CloseHandle(the_file);
+    msi_free( icon_path );
+    CloseHandle( handle );
 
     return ERROR_SUCCESS;
 }
@@ -5405,11 +5321,11 @@ static UINT ITERATE_UnpublishIcon( MSIRECORD *row, LPVOID param )
     if ((icon_path = msi_build_icon_path( package, icon )))
     {
         TRACE("removing icon file %s\n", debugstr_w(icon_path));
-        DeleteFileW( icon_path );
+        msi_delete_file( package, icon_path );
         if ((p = strrchrW( icon_path, '\\' )))
         {
             *p = 0;
-            RemoveDirectoryW( icon_path );
+            msi_remove_directory( package, icon_path );
         }
         msi_free( icon_path );
     }
@@ -7827,9 +7743,18 @@ static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
     return ERROR_SUCCESS;
 }
 
-static void bind_image( const char *filename, const char *path )
+static BOOL msi_bind_image( MSIPACKAGE *package, const char *filename, const char *path )
 {
-    if (!BindImageEx( 0, filename, path, NULL, NULL ))
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = BindImage( filename, path, NULL );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+static void bind_image( MSIPACKAGE *package, const char *filename, const char *path )
+{
+    if (!msi_bind_image( package, filename, path ))
     {
         WARN("failed to bind image %u\n", GetLastError());
     }
@@ -7851,8 +7776,9 @@ static UINT ITERATE_BindImage( MSIRECORD *rec, LPVOID param )
         return ERROR_SUCCESS;
     }
     if (!(filenameA = strdupWtoA( file->TargetPath ))) return ERROR_SUCCESS;
+
     path_list = msi_split_string( paths, ';' );
-    if (!path_list) bind_image( filenameA, NULL );
+    if (!path_list) bind_image( package, filenameA, NULL );
     else
     {
         for (i = 0; path_list[i] && path_list[i][0]; i++)
@@ -7860,7 +7786,7 @@ static UINT ITERATE_BindImage( MSIRECORD *rec, LPVOID param )
             deformat_string( package, path_list[i], &pathW );
             if ((pathA = strdupWtoA( pathW )))
             {
-                bind_image( filenameA, pathA );
+                bind_image( package, filenameA, pathA );
                 msi_free( pathA );
             }
             msi_free( pathW );
@@ -7868,6 +7794,7 @@ static UINT ITERATE_BindImage( MSIRECORD *rec, LPVOID param )
     }
     msi_free( path_list );
     msi_free( filenameA );
+
     return ERROR_SUCCESS;
 }
 
@@ -7884,10 +7811,8 @@ static UINT ACTION_BindImage( MSIPACKAGE *package )
     {
         r = MSI_IterateRecords( view, NULL, ITERATE_BindImage, package );
         msiobj_release( &view->hdr );
-        if (r != ERROR_SUCCESS)
-            return r;
     }
-    return ERROR_SUCCESS;
+    return r;
 }
 
 static UINT msi_unimplemented_action_stub( MSIPACKAGE *package, LPCSTR action, LPCWSTR table )
@@ -8034,12 +7959,8 @@ StandardActions[] =
 static UINT ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action)
 {
     UINT rc = ERROR_FUNCTION_NOT_CALLED;
-    void *cookie;
     UINT i;
 
-    if (is_wow64 && package->platform == PLATFORM_X64)
-        Wow64DisableWow64FsRedirection(&cookie);
-
     i = 0;
     while (StandardActions[i].action != NULL)
     {
@@ -8075,9 +7996,6 @@ static UINT ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action)
         i++;
     }
 
-    if (is_wow64 && package->platform == PLATFORM_X64)
-        Wow64RevertWow64FsRedirection(cookie);
-
     return rc;
 }
 
@@ -8087,12 +8005,6 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
 
     TRACE("Performing action (%s)\n", debugstr_w(action));
 
-    if (!msi_init_assembly_caches( package ))
-    {
-        ERR("can't initialize assembly caches\n");
-        return ERROR_FUNCTION_FAILED;
-    }
-
     package->action_progress_increment = 0;
     rc = ACTION_HandleStandardAction(package, action);
 
diff --git a/dlls/msi/appsearch.c b/dlls/msi/appsearch.c
index 806365191d..047085d1f3 100644
--- a/dlls/msi/appsearch.c
+++ b/dlls/msi/appsearch.c
@@ -81,7 +81,7 @@ void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
  * Returns ERROR_SUCCESS upon success (where not finding the record counts as
  * success), something else on error.
  */
-static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig, LPCWSTR name)
+static UINT get_signature( MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *name )
 {
     static const WCHAR query[] = {
         's','e','l','e','c','t',' ','*',' ',
@@ -155,16 +155,16 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
 }
 
 /* Frees any memory allocated in sig */
-static void ACTION_FreeSignature(MSISIGNATURE *sig)
+static void free_signature( MSISIGNATURE *sig )
 {
     msi_free(sig->File);
     msi_free(sig->Languages);
 }
 
-static LPWSTR app_search_file(LPWSTR path, MSISIGNATURE *sig)
+static WCHAR *search_file( MSIPACKAGE *package, WCHAR *path, MSISIGNATURE *sig )
 {
     VS_FIXEDFILEINFO *info;
-    DWORD attr, handle, size;
+    DWORD attr, size;
     LPWSTR val = NULL;
     LPBYTE buffer;
 
@@ -173,20 +173,18 @@ static LPWSTR app_search_file(LPWSTR path, MSISIGNATURE *sig)
         PathRemoveFileSpecW(path);
         PathAddBackslashW(path);
 
-        attr = GetFileAttributesW(path);
-        if (attr != INVALID_FILE_ATTRIBUTES &&
-            (attr & FILE_ATTRIBUTE_DIRECTORY))
+        attr = msi_get_file_attributes( package, path );
+        if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
             return strdupW(path);
 
         return NULL;
     }
 
-    attr = GetFileAttributesW(path);
-    if (attr == INVALID_FILE_ATTRIBUTES ||
-        (attr & FILE_ATTRIBUTE_DIRECTORY))
+    attr = msi_get_file_attributes( package, path );
+    if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY))
         return NULL;
 
-    size = GetFileVersionInfoSizeW(path, &handle);
+    size = msi_get_file_version_info( package, path, 0, NULL );
     if (!size)
         return strdupW(path);
 
@@ -194,7 +192,8 @@ static LPWSTR app_search_file(LPWSTR path, MSISIGNATURE *sig)
     if (!buffer)
         return NULL;
 
-    if (!GetFileVersionInfoW(path, 0, size, buffer))
+    size = msi_get_file_version_info( package, path, size, buffer );
+    if (!size)
         goto done;
 
     if (!VerQueryValueW(buffer, szBackSlash, (LPVOID)&info, &size) || !info)
@@ -227,7 +226,7 @@ done:
     return val;
 }
 
-static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATURE *sig)
+static UINT search_components( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
 {
     static const WCHAR query[] =  {
         'S','E','L','E','C','T',' ','*',' ',
@@ -240,7 +239,6 @@ static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MS
         '`','S','i','g','n','a','t','u','r','e','`',' ',
         'W','H','E','R','E',' ','`','S','i','g','n','a','t','u','r','e','`',' ','=',' ',
         '\'','%','s','\'',0};
-
     MSIRECORD *row, *rec;
     LPCWSTR signature, guid;
     BOOL sigpresent = TRUE;
@@ -275,7 +273,7 @@ static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MS
     if (!*path)
         goto done;
 
-    attr = GetFileAttributesW(path);
+    attr = msi_get_file_attributes( package, path );
     if (attr == INVALID_FILE_ATTRIBUTES)
         goto done;
 
@@ -283,7 +281,7 @@ static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MS
 
     if (type != msidbLocatorTypeDirectory && sigpresent && !isdir)
     {
-        *appValue = app_search_file(path, sig);
+        *appValue = search_file( package, path, sig );
     }
     else if (!sigpresent && (type != msidbLocatorTypeDirectory || isdir))
     {
@@ -302,9 +300,8 @@ static UINT ACTION_AppSearchComponents(MSIPACKAGE *package, LPWSTR *appValue, MS
         PathAddBackslashW(path);
         lstrcatW(path, MSI_RecordGetString(rec, 2));
 
-        attr = GetFileAttributesW(path);
-        if (attr != INVALID_FILE_ATTRIBUTES &&
-            !(attr & FILE_ATTRIBUTE_DIRECTORY))
+        attr = msi_get_file_attributes( package, path );
+        if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
             *appValue = strdupW(path);
     }
 
@@ -314,8 +311,7 @@ done:
     return ERROR_SUCCESS;
 }
 
-static void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
- LPWSTR *appValue)
+static void convert_reg_value( DWORD regType, const BYTE *value, DWORD sz, WCHAR **appValue )
 {
     static const WCHAR dwordFmt[] = { '#','%','d','\0' };
     static const WCHAR binPre[] = { '#','x','\0' };
@@ -365,10 +361,9 @@ static void ACTION_ConvertRegValue(DWORD regType, const BYTE *value, DWORD sz,
     }
 }
 
-static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
- LPCWSTR path, int depth, LPWSTR *appValue);
+static UINT search_directory( MSIPACKAGE *, MSISIGNATURE *, const WCHAR *, int, WCHAR ** );
 
-static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATURE *sig)
+static UINT search_reg( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
 {
     static const WCHAR query[] =  {
         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
@@ -473,13 +468,13 @@ static UINT ACTION_AppSearchReg(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNAT
     switch (type & 0x0f)
     {
     case msidbLocatorTypeDirectory:
-        ACTION_SearchDirectory(package, sig, ptr, 0, appValue);
+        search_directory( package, sig, ptr, 0, appValue );
         break;
     case msidbLocatorTypeFileName:
-        *appValue = app_search_file(ptr, sig);
+        *appValue = search_file( package, ptr, sig );
         break;
     case msidbLocatorTypeRawValue:
-        ACTION_ConvertRegValue(regType, value, sz, appValue);
+        convert_reg_value( regType, value, sz, appValue );
         break;
     default:
         FIXME("unimplemented for type %d (key path %s, value %s)\n",
@@ -520,8 +515,7 @@ static LPWSTR get_ini_field(LPWSTR buf, int field)
     return strdupW(beg);
 }
 
-static UINT ACTION_AppSearchIni(MSIPACKAGE *package, LPWSTR *appValue,
- MSISIGNATURE *sig)
+static UINT search_ini( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
 {
     static const WCHAR query[] =  {
         's','e','l','e','c','t',' ','*',' ',
@@ -561,10 +555,10 @@ static UINT ACTION_AppSearchIni(MSIPACKAGE *package, LPWSTR *appValue,
         switch (type & 0x0f)
         {
         case msidbLocatorTypeDirectory:
-            ACTION_SearchDirectory(package, sig, buf, 0, appValue);
+            search_directory( package, sig, buf, 0, appValue );
             break;
         case msidbLocatorTypeFileName:
-            *appValue = app_search_file(buf, sig);
+            *appValue = search_file( package, buf, sig );
             break;
         case msidbLocatorTypeRawValue:
             *appValue = get_ini_field(buf, field);
@@ -590,8 +584,7 @@ static UINT ACTION_AppSearchIni(MSIPACKAGE *package, LPWSTR *appValue,
  * - what does AppSearch return if the table values are invalid?
  * - what if dst is too small?
  */
-static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
- size_t len)
+static void expand_any_path( MSIPACKAGE *package, WCHAR *src, WCHAR *dst, size_t len )
 {
     WCHAR *ptr, *deformatted;
 
@@ -685,20 +678,20 @@ done:
  * Return ERROR_SUCCESS in case of success (whether or not the file matches),
  * something else if an install-halting error occurs.
  */
-static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath,
- BOOL *matches)
+static UINT file_version_matches( MSIPACKAGE *package, const MSISIGNATURE *sig, const WCHAR *filePath,
+                                  BOOL *matches )
 {
     UINT len;
     void *version;
     VS_FIXEDFILEINFO *info = NULL;
-    DWORD zero, size = GetFileVersionInfoSizeW( filePath, &zero );
+    DWORD size = msi_get_file_version_info( package, filePath, 0, NULL );
 
     *matches = FALSE;
 
     if (!size) return ERROR_SUCCESS;
     if (!(version = msi_alloc( size ))) return ERROR_OUTOFMEMORY;
 
-    if (GetFileVersionInfoW( filePath, 0, size, version ))
+    if (msi_get_file_version_info( package, filePath, size, version ))
         VerQueryValueW( version, szBackSlash, (void **)&info, &len );
 
     if (info)
@@ -745,8 +738,8 @@ static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath,
  * Return ERROR_SUCCESS in case of success (whether or not the file matches),
  * something else if an install-halting error occurs.
  */
-static UINT ACTION_FileMatchesSig(const MSISIGNATURE *sig,
- const WIN32_FIND_DATAW *findData, LPCWSTR fullFilePath, BOOL *matches)
+static UINT file_matches_sig( MSIPACKAGE *package, const MSISIGNATURE *sig, const WIN32_FIND_DATAW *findData,
+                              const WCHAR *fullFilePath, BOOL *matches )
 {
     UINT rc = ERROR_SUCCESS;
 
@@ -778,7 +771,7 @@ static UINT ACTION_FileMatchesSig(const MSISIGNATURE *sig,
         *matches = FALSE;
     if (*matches && (sig->MinVersionMS || sig->MinVersionLS ||
      sig->MaxVersionMS || sig->MaxVersionLS))
-        rc = ACTION_FileVersionMatches(sig, fullFilePath, matches);
+        rc = file_version_matches( package, sig, fullFilePath, matches );
     return rc;
 }
 
@@ -790,9 +783,10 @@ static UINT ACTION_FileMatchesSig(const MSISIGNATURE *sig,
  * Returns ERROR_SUCCESS on success (which may include non-critical errors),
  * something else on failures which should halt the install.
  */
-static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
- MSISIGNATURE *sig, LPCWSTR dir, int depth)
+static UINT recurse_search_directory( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig, const WCHAR *dir,
+                                      int depth )
 {
+    static const WCHAR starDotStarW[] = { '*','.','*',0 };
     HANDLE hFind;
     WIN32_FIND_DATAW findData;
     UINT rc = ERROR_SUCCESS;
@@ -801,10 +795,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
     WCHAR *buf;
     DWORD len;
 
-    static const WCHAR starDotStarW[] = { '*','.','*',0 };
-
-    TRACE("Searching directory %s for file %s, depth %d\n", debugstr_w(dir),
-          debugstr_w(sig->File), depth);
+    TRACE("Searching directory %s for file %s, depth %d\n", debugstr_w(dir), debugstr_w(sig->File), depth);
 
     if (depth < 0)
         return ERROR_SUCCESS;
@@ -823,14 +814,14 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
     PathAddBackslashW(buf);
     lstrcatW(buf, sig->File);
 
-    hFind = FindFirstFileW(buf, &findData);
+    hFind = msi_find_first_file( package, buf, &findData );
     if (hFind != INVALID_HANDLE_VALUE)
     {
         if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
         {
             BOOL matches;
 
-            rc = ACTION_FileMatchesSig(sig, &findData, buf, &matches);
+            rc = file_matches_sig( package, sig, &findData, buf, &matches );
             if (rc == ERROR_SUCCESS && matches)
             {
                 TRACE("found file, returning %s\n", debugstr_w(buf));
@@ -846,7 +837,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
         PathAddBackslashW(buf);
         lstrcatW(buf, starDotStarW);
 
-        hFind = FindFirstFileW(buf, &findData);
+        hFind = msi_find_first_file( package, buf, &findData );
         if (hFind != INVALID_HANDLE_VALUE)
         {
             if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
@@ -855,12 +846,10 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
             {
                 lstrcpyW(subpath, dir);
                 PathAppendW(subpath, findData.cFileName);
-                rc = ACTION_RecurseSearchDirectory(package, appValue, sig,
-                                                   subpath, depth - 1);
+                rc = recurse_search_directory( package, appValue, sig, subpath, depth - 1 );
             }
 
-            while (rc == ERROR_SUCCESS && !*appValue &&
-                   FindNextFileW(hFind, &findData) != 0)
+            while (rc == ERROR_SUCCESS && !*appValue && msi_find_next_file( package, hFind, &findData ))
             {
                 if (!strcmpW( findData.cFileName, szDot ) ||
                     !strcmpW( findData.cFileName, szDotDot ))
@@ -869,8 +858,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
                 lstrcpyW(subpath, dir);
                 PathAppendW(subpath, findData.cFileName);
                 if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                    rc = ACTION_RecurseSearchDirectory(package, appValue,
-                                                       sig, subpath, depth - 1);
+                    rc = recurse_search_directory( package, appValue, sig, subpath, depth - 1 );
             }
 
             FindClose(hFind);
@@ -883,10 +871,9 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue,
     return rc;
 }
 
-static UINT ACTION_CheckDirectory(MSIPACKAGE *package, LPCWSTR dir,
- LPWSTR *appValue)
+static UINT check_directory( MSIPACKAGE *package, const WCHAR *dir, WCHAR **appValue )
 {
-    DWORD attr = GetFileAttributesW(dir);
+    DWORD attr = msi_get_file_attributes( package, dir );
 
     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
     {
@@ -897,7 +884,7 @@ static UINT ACTION_CheckDirectory(MSIPACKAGE *package, LPCWSTR dir,
     return ERROR_SUCCESS;
 }
 
-static BOOL ACTION_IsFullPath(LPCWSTR path)
+static BOOL is_full_path( const WCHAR *path )
 {
     WCHAR first = toupperW(path[0]);
     BOOL ret;
@@ -911,26 +898,24 @@ static BOOL ACTION_IsFullPath(LPCWSTR path)
     return ret;
 }
 
-static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
- LPCWSTR path, int depth, LPWSTR *appValue)
+static UINT search_directory( MSIPACKAGE *package, MSISIGNATURE *sig, const WCHAR *path, int depth, WCHAR **appValue )
 {
     UINT rc;
     DWORD attr;
     LPWSTR val = NULL;
 
-    TRACE("%p, %p, %s, %d, %p\n", package, sig, debugstr_w(path), depth,
-     appValue);
+    TRACE("%p, %p, %s, %d, %p\n", package, sig, debugstr_w(path), depth, appValue);
 
-    if (ACTION_IsFullPath(path))
+    if (is_full_path( path ))
     {
         if (sig->File)
-            rc = ACTION_RecurseSearchDirectory(package, &val, sig, path, depth);
+            rc = recurse_search_directory( package, &val, sig, path, depth );
         else
         {
             /* Recursively searching a directory makes no sense when the
              * directory to search is the thing you're trying to find.
              */
-            rc = ACTION_CheckDirectory(package, path, &val);
+            rc = check_directory( package, path, &val );
         }
     }
     else
@@ -952,16 +937,14 @@ static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
             lstrcpynW(pathWithDrive + 3, path, ARRAY_SIZE(pathWithDrive) - 3);
 
             if (sig->File)
-                rc = ACTION_RecurseSearchDirectory(package, &val, sig,
-                                                   pathWithDrive, depth);
+                rc = recurse_search_directory( package, &val, sig, pathWithDrive, depth );
             else
-                rc = ACTION_CheckDirectory(package, pathWithDrive, &val);
+                rc = check_directory( package, pathWithDrive, &val );
         }
     }
 
-    attr = GetFileAttributesW(val);
-    if (attr != INVALID_FILE_ATTRIBUTES &&
-        (attr & FILE_ATTRIBUTE_DIRECTORY) &&
+    attr = msi_get_file_attributes( package, val );
+    if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY) &&
         val && val[lstrlenW(val) - 1] != '\\')
     {
         val = msi_realloc(val, (lstrlenW(val) + 2) * sizeof(WCHAR));
@@ -977,10 +960,9 @@ static UINT ACTION_SearchDirectory(MSIPACKAGE *package, MSISIGNATURE *sig,
     return rc;
 }
 
-static UINT ACTION_AppSearchSigName(MSIPACKAGE *package, LPCWSTR sigName,
- MSISIGNATURE *sig, LPWSTR *appValue);
+static UINT search_sig_name( MSIPACKAGE *, const WCHAR *, MSISIGNATURE *, WCHAR ** );
 
-static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATURE *sig)
+static UINT search_dr( MSIPACKAGE *package, WCHAR **appValue, MSISIGNATURE *sig )
 {
     static const WCHAR query[] =  {
         's','e','l','e','c','t',' ','*',' ',
@@ -1014,8 +996,8 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
     {
         MSISIGNATURE parentSig;
 
-        ACTION_AppSearchSigName(package, parentName, &parentSig, &parent);
-        ACTION_FreeSignature(&parentSig);
+        search_sig_name( package, parentName, &parentSig, &parent );
+        free_signature( &parentSig );
         if (!parent)
         {
             msiobj_release(&row->hdr);
@@ -1032,13 +1014,13 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
         depth = MSI_RecordGetInteger(row,4);
 
     if (sz)
-        ACTION_ExpandAnyPath(package, path, expanded, MAX_PATH);
+        expand_any_path( package, path, expanded, MAX_PATH );
     else
         strcpyW(expanded, path);
 
     if (parent)
     {
-        attr = GetFileAttributesW(parent);
+        attr = msi_get_file_attributes( package, parent );
         if (attr != INVALID_FILE_ATTRIBUTES &&
             !(attr & FILE_ATTRIBUTE_DIRECTORY))
         {
@@ -1049,45 +1031,42 @@ static UINT ACTION_AppSearchDr(MSIPACKAGE *package, LPWSTR *appValue, MSISIGNATU
         strcpyW(path, parent);
         strcatW(path, expanded);
     }
-    else if (sz)
-        strcpyW(path, expanded);
+    else if (sz) strcpyW(path, expanded);
 
     PathAddBackslashW(path);
 
-    rc = ACTION_SearchDirectory(package, sig, path, depth, appValue);
+    rc = search_directory( package, sig, path, depth, appValue );
 
     msi_free(parent);
     msiobj_release(&row->hdr);
-
     TRACE("returning %d\n", rc);
     return rc;
 }
 
-static UINT ACTION_AppSearchSigName(MSIPACKAGE *package, LPCWSTR sigName,
- MSISIGNATURE *sig, LPWSTR *appValue)
+static UINT search_sig_name( MSIPACKAGE *package, const WCHAR *sigName, MSISIGNATURE *sig, WCHAR **appValue )
 {
     UINT rc;
 
     *appValue = NULL;
-    rc = ACTION_AppSearchGetSignature(package, sig, sigName);
+    rc = get_signature( package, sig, sigName );
     if (rc == ERROR_SUCCESS)
     {
-        rc = ACTION_AppSearchComponents(package, appValue, sig);
+        rc = search_components( package, appValue, sig );
         if (rc == ERROR_SUCCESS && !*appValue)
         {
-            rc = ACTION_AppSearchReg(package, appValue, sig);
+            rc = search_reg( package, appValue, sig );
             if (rc == ERROR_SUCCESS && !*appValue)
             {
-                rc = ACTION_AppSearchIni(package, appValue, sig);
+                rc = search_ini( package, appValue, sig );
                 if (rc == ERROR_SUCCESS && !*appValue)
-                    rc = ACTION_AppSearchDr(package, appValue, sig);
+                    rc = search_dr( package, appValue, sig );
             }
         }
     }
     return rc;
 }
 
-static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
+static UINT ITERATE_AppSearch(MSIRECORD *row, LPVOID param)
 {
     MSIPACKAGE *package = param;
     LPCWSTR propName, sigName;
@@ -1102,7 +1081,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
 
     TRACE("%s %s\n", debugstr_w(propName), debugstr_w(sigName));
 
-    r = ACTION_AppSearchSigName(package, sigName, &sig, &value);
+    r = search_sig_name( package, sigName, &sig, &value );
     if (value)
     {
         r = msi_set_property( package->db, propName, value, -1 );
@@ -1111,7 +1090,7 @@ static UINT iterate_appsearch(MSIRECORD *row, LPVOID param)
 
         msi_free(value);
     }
-    ACTION_FreeSignature(&sig);
+    free_signature( &sig );
 
     uirow = MSI_CreateRecord( 2 );
     MSI_RecordSetStringW( uirow, 1, propName );
@@ -1142,7 +1121,7 @@ UINT ACTION_AppSearch(MSIPACKAGE *package)
     if (r != ERROR_SUCCESS)
         return ERROR_SUCCESS;
 
-    r = MSI_IterateRecords( view, NULL, iterate_appsearch, package );
+    r = MSI_IterateRecords( view, NULL, ITERATE_AppSearch, package );
     msiobj_release( &view->hdr );
     return r;
 }
@@ -1161,7 +1140,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
 
     TRACE("%s\n", debugstr_w(signature));
 
-    ACTION_AppSearchSigName(package, signature, &sig, &value);
+    search_sig_name( package, signature, &sig, &value );
     if (value)
     {
         TRACE("Found signature %s\n", debugstr_w(signature));
@@ -1170,8 +1149,7 @@ static UINT ITERATE_CCPSearch(MSIRECORD *row, LPVOID param)
         r = ERROR_NO_MORE_ITEMS;
     }
 
-    ACTION_FreeSignature(&sig);
-
+    free_signature(&sig);
     return r;
 }
 
diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c
index 3cb0f3170a..8bf0902914 100644
--- a/dlls/msi/custom.c
+++ b/dlls/msi/custom.c
@@ -1188,7 +1188,7 @@ static UINT HANDLE_CustomType21_22( MSIPACKAGE *package, const WCHAR *source, co
         return ERROR_FUNCTION_FAILED;
     }
 
-    hFile = CreateFileW(file->TargetPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+    hFile = msi_create_file( package, file->TargetPath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 );
     if (hFile == INVALID_HANDLE_VALUE) return ERROR_FUNCTION_FAILED;
 
     sz = GetFileSize(hFile, &szHighWord);
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index 5a88c147e0..92a98f1eca 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -18,7 +18,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-
 /*
  * Actions dealing with files:
  *
@@ -37,7 +36,6 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
-#include "wine/debug.h"
 #include "fdi.h"
 #include "msi.h"
 #include "msidefs.h"
@@ -46,10 +44,202 @@
 #include "winreg.h"
 #include "shlwapi.h"
 #include "patchapi.h"
+#include "wine/debug.h"
 #include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
+HANDLE msi_create_file( MSIPACKAGE *package, const WCHAR *filename, DWORD access, DWORD sharing, DWORD creation,
+                        DWORD flags )
+{
+    HANDLE handle;
+    msi_disable_fs_redirection( package );
+    handle = CreateFileW( filename, access, sharing, NULL, creation, flags, NULL );
+    msi_revert_fs_redirection( package );
+    return handle;
+}
+
+static BOOL msi_copy_file( MSIPACKAGE *package, const WCHAR *src, const WCHAR *dst, BOOL fail_if_exists )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = CopyFileW( src, dst, fail_if_exists );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+BOOL msi_delete_file( MSIPACKAGE *package, const WCHAR *filename )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = DeleteFileW( filename );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+static BOOL msi_create_directory( MSIPACKAGE *package, const WCHAR *path )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = CreateDirectoryW( path, NULL );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+BOOL msi_remove_directory( MSIPACKAGE *package, const WCHAR *path )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = RemoveDirectoryW( path );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+BOOL msi_set_file_attributes( MSIPACKAGE *package, const WCHAR *filename, DWORD attrs )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = SetFileAttributesW( filename, attrs );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+DWORD msi_get_file_attributes( MSIPACKAGE *package, const WCHAR *path )
+{
+    DWORD attrs;
+    msi_disable_fs_redirection( package );
+    attrs = GetFileAttributesW( path );
+    msi_revert_fs_redirection( package );
+    return attrs;
+}
+
+HANDLE msi_find_first_file( MSIPACKAGE *package, const WCHAR *filename, WIN32_FIND_DATAW *data )
+{
+    HANDLE handle;
+    msi_disable_fs_redirection( package );
+    handle = FindFirstFileW( filename, data );
+    msi_revert_fs_redirection( package );
+    return handle;
+}
+
+BOOL msi_find_next_file( MSIPACKAGE *package, HANDLE handle, WIN32_FIND_DATAW *data )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = FindNextFileW( handle, data );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+BOOL msi_move_file( MSIPACKAGE *package, const WCHAR *from, const WCHAR *to, DWORD flags )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = MoveFileExW( from, to, flags );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+static BOOL msi_apply_filepatch( MSIPACKAGE *package, const WCHAR *patch, const WCHAR *old, const WCHAR *new )
+{
+    BOOL ret;
+    msi_disable_fs_redirection( package );
+    ret = ApplyPatchToFileW( patch, old, new, 0 );
+    msi_revert_fs_redirection( package );
+    return ret;
+}
+
+DWORD msi_get_file_version_info( MSIPACKAGE *package, const WCHAR *path, DWORD buflen, BYTE *buffer )
+{
+    DWORD size, handle;
+    msi_disable_fs_redirection( package );
+    if (buffer) size = GetFileVersionInfoW( path, 0, buflen, buffer );
+    else size = GetFileVersionInfoSizeW( path, &handle );
+    msi_revert_fs_redirection( package );
+    return size;
+}
+
+VS_FIXEDFILEINFO *msi_get_disk_file_version( MSIPACKAGE *package, const WCHAR *filename )
+{
+    static const WCHAR name[] = {'\\',0};
+    VS_FIXEDFILEINFO *ptr, *ret;
+    DWORD version_size, size;
+    void *version;
+
+    if (!(version_size = msi_get_file_version_info( package, filename, 0, NULL ))) return NULL;
+    if (!(version = msi_alloc( version_size ))) return NULL;
+
+    msi_get_file_version_info( package, filename, version_size, version );
+
+    if (!VerQueryValueW( version, name, (void **)&ptr, &size ))
+    {
+        msi_free( version );
+        return NULL;
+    }
+
+    if (!(ret = msi_alloc( size )))
+    {
+        msi_free( version );
+        return NULL;
+    }
+
+    memcpy( ret, ptr, size );
+    msi_free( version );
+    return ret;
+}
+
+DWORD msi_get_disk_file_size( MSIPACKAGE *package, const WCHAR *filename )
+{
+    DWORD size;
+    HANDLE file;
+    file = msi_create_file( package, filename, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0 );
+    if (file == INVALID_HANDLE_VALUE) return INVALID_FILE_SIZE;
+    size = GetFileSize( file, NULL );
+    CloseHandle( file );
+    return size;
+}
+
+/* Recursively create all directories in the path. */
+BOOL msi_create_full_path( MSIPACKAGE *package, const WCHAR *path )
+{
+    BOOL ret = TRUE;
+    WCHAR *new_path;
+    int len;
+
+    if (!(new_path = msi_alloc( (strlenW( path ) + 1) * sizeof(WCHAR) ))) return FALSE;
+    strcpyW( new_path, path );
+
+    while ((len = strlenW( new_path )) && new_path[len - 1] == '\\')
+    new_path[len - 1] = 0;
+
+    while (!msi_create_directory( package, new_path ))
+    {
+        WCHAR *slash;
+        DWORD last_error = GetLastError();
+        if (last_error == ERROR_ALREADY_EXISTS) break;
+        if (last_error != ERROR_PATH_NOT_FOUND)
+        {
+            ret = FALSE;
+            break;
+        }
+        if (!(slash = strrchrW( new_path, '\\' )))
+        {
+            ret = FALSE;
+            break;
+        }
+        len = slash - new_path;
+        new_path[len] = 0;
+        if (!msi_create_full_path( package, new_path ))
+        {
+            ret = FALSE;
+            break;
+        }
+        new_path[len] = '\\';
+    }
+    msi_free( new_path );
+    return ret;
+}
+
 static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *action )
 {
     MSIRECORD *uirow;
@@ -85,6 +275,19 @@ static BOOL is_obsoleted_by_patch( MSIPACKAGE *package, MSIFILE *file )
     return FALSE;
 }
 
+static BOOL file_hash_matches( MSIPACKAGE *package, MSIFILE *file )
+{
+    UINT r;
+    MSIFILEHASHINFO hash;
+
+    hash.dwFileHashInfoSize = sizeof(hash);
+    r = msi_get_filehash( package, file->TargetPath, &hash );
+    if (r != ERROR_SUCCESS)
+        return FALSE;
+
+    return !memcmp( &hash, &file->hash, sizeof(hash) );
+}
+
 static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *file )
 {
     MSICOMPONENT *comp = file->Component;
@@ -105,14 +308,14 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
         return msifs_skipped;
     }
     if ((msi_is_global_assembly( comp ) && !comp->assembly->installed) ||
-        GetFileAttributesW( file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
+        msi_get_file_attributes( package, file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
     {
         TRACE("installing %s (missing)\n", debugstr_w(file->File));
         return msifs_missing;
     }
     if (file->Version)
     {
-        if ((file_version = msi_get_disk_file_version( file->TargetPath )))
+        if ((file_version = msi_get_disk_file_version( package, file->TargetPath )))
         {
             if (msi_compare_file_versions( file_version, file->Version ) < 0)
             {
@@ -133,7 +336,7 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
             msi_free( file_version );
             return state;
         }
-        else if ((font_version = msi_font_version_from_file( file->TargetPath )))
+        else if ((font_version = msi_get_font_file_version( package, file->TargetPath )))
         {
             if (msi_compare_font_versions( font_version, file->Version ) < 0)
             {
@@ -151,14 +354,14 @@ static msi_file_state calculate_install_state( MSIPACKAGE *package, MSIFILE *fil
             return state;
         }
     }
-    if ((size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
+    if ((size = msi_get_disk_file_size( package, file->TargetPath )) != file->FileSize)
     {
         TRACE("overwriting %s (old size %u new size %u)\n", debugstr_w(file->File), size, file->FileSize);
         return msifs_overwrite;
     }
     if (file->hash.dwFileHashInfoSize)
     {
-        if (msi_file_hash_matches( file ))
+        if (file_hash_matches( package, file ))
         {
             TRACE("keeping %s (hash match)\n", debugstr_w(file->File));
             return msifs_hashmatch;
@@ -191,15 +394,15 @@ static void schedule_install_files(MSIPACKAGE *package)
     }
 }
 
-static UINT copy_file(MSIFILE *file, LPWSTR source)
+static UINT copy_file( MSIPACKAGE *package, MSIFILE *file, WCHAR *source )
 {
     BOOL ret;
 
-    ret = CopyFileW(source, file->TargetPath, FALSE);
+    ret = msi_copy_file( package, source, file->TargetPath, FALSE );
     if (!ret)
         return GetLastError();
 
-    SetFileAttributesW(file->TargetPath, FILE_ATTRIBUTE_NORMAL);
+    msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
     return ERROR_SUCCESS;
 }
 
@@ -209,7 +412,7 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
 
     TRACE("Copying %s to %s\n", debugstr_w(source), debugstr_w(file->TargetPath));
 
-    gle = copy_file(file, source);
+    gle = copy_file( package, file, source );
     if (gle == ERROR_SUCCESS)
         return gle;
 
@@ -220,9 +423,9 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
     }
     else if (gle == ERROR_ACCESS_DENIED)
     {
-        SetFileAttributesW(file->TargetPath, FILE_ATTRIBUTE_NORMAL);
+        msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
 
-        gle = copy_file(file, source);
+        gle = copy_file( package, file, source );
         TRACE("Overwriting existing file: %d\n", gle);
     }
     if (gle == ERROR_SHARING_VIOLATION || gle == ERROR_USER_MAPPED_FILE)
@@ -243,9 +446,9 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
         if (!GetTempFileNameW( pathW, szMsi, 0, tmpfileW )) tmpfileW[0] = 0;
         msi_free( pathW );
 
-        if (CopyFileW(source, tmpfileW, FALSE) &&
-            MoveFileExW(file->TargetPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) &&
-            MoveFileExW(tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT))
+        if (msi_copy_file( package, source, tmpfileW, FALSE ) &&
+            msi_move_file( package, file->TargetPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) &&
+            msi_move_file( package, tmpfileW, file->TargetPath, MOVEFILE_DELAY_UNTIL_REBOOT ))
         {
             package->need_reboot_at_end = 1;
             gle = ERROR_SUCCESS;
@@ -262,7 +465,7 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source)
     return gle;
 }
 
-static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
+static UINT create_directory( MSIPACKAGE *package, const WCHAR *dir )
 {
     MSIFOLDER *folder;
     const WCHAR *install_path;
@@ -273,7 +476,7 @@ static UINT msi_create_directory( MSIPACKAGE *package, const WCHAR *dir )
     folder = msi_get_loaded_folder( package, dir );
     if (folder->State == FOLDER_STATE_UNINITIALIZED)
     {
-        msi_create_full_path( install_path );
+        msi_create_full_path( package, install_path );
         folder->State = FOLDER_STATE_CREATED;
     }
     return ERROR_SUCCESS;
@@ -309,7 +512,7 @@ static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR filename, DWORD action,
 
         if (!msi_is_global_assembly( file->Component ))
         {
-            msi_create_directory( package, file->Component->Directory );
+            create_directory( package, file->Component->Directory );
         }
         *path = strdupW( file->TargetPath );
         *attrs = file->Attributes;
@@ -334,7 +537,7 @@ WCHAR *msi_resolve_file_source( MSIPACKAGE *package, MSIFILE *file )
     p = msi_resolve_source_folder( package, file->Component->Directory, NULL );
     path = msi_build_directory_name( 2, p, file->ShortName );
 
-    if (file->LongName && GetFileAttributesW( path ) == INVALID_FILE_ATTRIBUTES)
+    if (file->LongName && msi_get_file_attributes( package, path ) == INVALID_FILE_ATTRIBUTES)
     {
         msi_free( path );
         path = msi_build_directory_name( 2, p, file->LongName );
@@ -418,7 +621,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
 
             if (!is_global_assembly)
             {
-                msi_create_directory(package, file->Component->Directory);
+                create_directory(package, file->Component->Directory);
             }
             rc = copy_install_file(package, file, source);
             if (rc != ERROR_SUCCESS)
@@ -513,10 +716,10 @@ static UINT patch_file( MSIPACKAGE *package, MSIFILEPATCH *patch )
     WCHAR *tmpfile = msi_create_temp_file( package->db );
 
     if (!tmpfile) return ERROR_INSTALL_FAILURE;
-    if (ApplyPatchToFileW( patch->path, patch->File->TargetPath, tmpfile, 0 ))
+    if (msi_apply_filepatch( package, patch->path, patch->File->TargetPath, tmpfile ))
     {
-        DeleteFileW( patch->File->TargetPath );
-        MoveFileW( tmpfile, patch->File->TargetPath );
+        msi_delete_file( package, patch->File->TargetPath );
+        msi_move_file( package, tmpfile, patch->File->TargetPath, 0 );
     }
     else
     {
@@ -557,7 +760,7 @@ static UINT patch_assembly( MSIPACKAGE *package, MSIASSEMBLY *assembly, MSIFILEP
 
         if ((path = msi_get_assembly_path( package, displayname )))
         {
-            if (!CopyFileW( path, patch->File->TargetPath, FALSE ))
+            if (!msi_copy_file( package, path, patch->File->TargetPath, FALSE ))
             {
                 ERR("Failed to copy file %s -> %s (%u)\n", debugstr_w(path),
                     debugstr_w(patch->File->TargetPath), GetLastError() );
@@ -679,12 +882,12 @@ typedef struct
     LPWSTR dest;
 } FILE_LIST;
 
-static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
+static BOOL move_file( MSIPACKAGE *package, const WCHAR *source, const WCHAR *dest, int options )
 {
     BOOL ret;
 
-    if (GetFileAttributesW(source) == FILE_ATTRIBUTE_DIRECTORY ||
-        GetFileAttributesW(dest) == FILE_ATTRIBUTE_DIRECTORY)
+    if (msi_get_file_attributes( package, source ) == FILE_ATTRIBUTE_DIRECTORY ||
+        msi_get_file_attributes( package, dest ) == FILE_ATTRIBUTE_DIRECTORY)
     {
         WARN("Source or dest is directory, not moving\n");
         return FALSE;
@@ -693,20 +896,20 @@ static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
     if (options == msidbMoveFileOptionsMove)
     {
         TRACE("moving %s -> %s\n", debugstr_w(source), debugstr_w(dest));
-        ret = MoveFileExW(source, dest, MOVEFILE_REPLACE_EXISTING);
+        ret = msi_move_file( package, source, dest, MOVEFILE_REPLACE_EXISTING );
         if (!ret)
         {
-            WARN("MoveFile failed: %d\n", GetLastError());
+            WARN("msi_move_file failed: %u\n", GetLastError());
             return FALSE;
         }
     }
     else
     {
         TRACE("copying %s -> %s\n", debugstr_w(source), debugstr_w(dest));
-        ret = CopyFileW(source, dest, FALSE);
+        ret = msi_copy_file( package, source, dest, FALSE );
         if (!ret)
         {
-            WARN("CopyFile failed: %d\n", GetLastError());
+            WARN("msi_copy_file failed: %u\n", GetLastError());
             return FALSE;
         }
     }
@@ -714,16 +917,17 @@ static BOOL msi_move_file(LPCWSTR source, LPCWSTR dest, int options)
     return TRUE;
 }
 
-static LPWSTR wildcard_to_file(LPWSTR wildcard, LPWSTR filename)
+static WCHAR *wildcard_to_file( const WCHAR *wildcard, const WCHAR *filename )
 {
-    LPWSTR path, ptr;
+    const WCHAR *ptr;
+    WCHAR *path;
     DWORD dirlen, pathlen;
 
     ptr = strrchrW(wildcard, '\\');
     dirlen = ptr - wildcard + 1;
 
     pathlen = dirlen + lstrlenW(filename) + 1;
-    path = msi_alloc(pathlen * sizeof(WCHAR));
+    if (!(path = msi_alloc(pathlen * sizeof(WCHAR)))) return NULL;
 
     lstrcpynW(path, wildcard, dirlen + 1);
     lstrcatW(path, filename);
@@ -749,10 +953,10 @@ static void free_list(FILE_LIST *list)
     }
 }
 
-static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
+static BOOL add_wildcard( FILE_LIST *files, const WCHAR *source, WCHAR *dest )
 {
     FILE_LIST *new, *file;
-    LPWSTR ptr, filename;
+    WCHAR *ptr, *filename;
     DWORD size;
 
     new = msi_alloc_zero(sizeof(FILE_LIST));
@@ -800,7 +1004,7 @@ static BOOL add_wildcard(FILE_LIST *files, LPWSTR source, LPWSTR dest)
     return TRUE;
 }
 
-static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
+static BOOL move_files_wildcard( MSIPACKAGE *package, const WCHAR *source, WCHAR *dest, int options )
 {
     WIN32_FIND_DATAW wfd;
     HANDLE hfile;
@@ -809,16 +1013,16 @@ static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
     FILE_LIST files, *file;
     DWORD size;
 
-    hfile = FindFirstFileW(source, &wfd);
+    hfile = msi_find_first_file( package, source, &wfd );
     if (hfile == INVALID_HANDLE_VALUE) return FALSE;
 
     list_init(&files.entry);
 
-    for (res = TRUE; res; res = FindNextFileW(hfile, &wfd))
+    for (res = TRUE; res; res = msi_find_next_file( package, hfile, &wfd ))
     {
         if (is_dot_dir(wfd.cFileName)) continue;
 
-        path = wildcard_to_file(source, wfd.cFileName);
+        path = wildcard_to_file( source, wfd.cFileName );
         if (!path)
         {
             res = FALSE;
@@ -854,7 +1058,7 @@ static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options)
     {
         file = LIST_ENTRY(list_head(&files.entry), FILE_LIST, entry);
 
-        msi_move_file(file->source, file->dest, options);
+        move_file( package, file->source, file->dest, options );
 
         list_remove(&file->entry);
         free_file_entry(file);
@@ -910,7 +1114,7 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
 
     if (!sourcename)
     {
-        if (GetFileAttributesW(sourcedir) == INVALID_FILE_ATTRIBUTES)
+        if (msi_get_file_attributes( package, sourcedir ) == INVALID_FILE_ATTRIBUTES)
             goto done;
 
         source = strdupW(sourcedir);
@@ -969,9 +1173,9 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
     if (destname)
         lstrcatW(dest, destname);
 
-    if (GetFileAttributesW(destdir) == INVALID_FILE_ATTRIBUTES)
+    if (msi_get_file_attributes( package, destdir ) == INVALID_FILE_ATTRIBUTES)
     {
-        if (!msi_create_full_path(destdir))
+        if (!msi_create_full_path( package, destdir ))
         {
             WARN("failed to create directory %u\n", GetLastError());
             goto done;
@@ -979,9 +1183,9 @@ static UINT ITERATE_MoveFiles( MSIRECORD *rec, LPVOID param )
     }
 
     if (!wildcards)
-        msi_move_file(source, dest, options);
+        move_file( package, source, dest, options );
     else
-        move_files_wildcard(source, dest, options);
+        move_files_wildcard( package, source, dest, options );
 
 done:
     uirow = MSI_CreateRecord( 9 );
@@ -1065,7 +1269,7 @@ static WCHAR *get_duplicate_filename( MSIPACKAGE *package, MSIRECORD *row, const
     }
 
     dst = msi_build_directory_name( 2, dst_path, dst_name );
-    msi_create_full_path( dst_path );
+    msi_create_full_path( package, dst_path );
 
     msi_free( dst_name );
     msi_free( dst_path );
@@ -1115,14 +1319,12 @@ static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
     }
 
     TRACE("Duplicating file %s to %s\n", debugstr_w(file->TargetPath), debugstr_w(dest));
-
-    if (!CopyFileW( file->TargetPath, dest, TRUE ))
+    if (!msi_copy_file( package, file->TargetPath, dest, TRUE ))
     {
         WARN("Failed to copy file %s -> %s (%u)\n",
              debugstr_w(file->TargetPath), debugstr_w(dest), GetLastError());
     }
-
-    FIXME("We should track these duplicate files as well\n");   
+    FIXME("We should track these duplicate files as well\n");
 
     uirow = MSI_CreateRecord( 9 );
     MSI_RecordSetStringW( uirow, 1, MSI_RecordGetString( row, 1 ) );
@@ -1198,8 +1400,7 @@ static UINT ITERATE_RemoveDuplicateFiles( MSIRECORD *row, LPVOID param )
     }
 
     TRACE("Removing duplicate %s of %s\n", debugstr_w(dest), debugstr_w(file->TargetPath));
-
-    if (!DeleteFileW( dest ))
+    if (!msi_delete_file( package, dest ))
     {
         WARN("Failed to delete duplicate file %s (%u)\n", debugstr_w(dest), GetLastError());
     }
@@ -1320,12 +1521,12 @@ static UINT ITERATE_RemoveFiles(MSIRECORD *row, LPVOID param)
         lstrcatW(path, filename);
 
         TRACE("Deleting misc file: %s\n", debugstr_w(path));
-        DeleteFileW(path);
+        msi_delete_file( package, path );
     }
     else
     {
         TRACE("Removing misc directory: %s\n", debugstr_w(dir));
-        RemoveDirectoryW(dir);
+        msi_remove_directory( package, dir );
     }
 
 done:
@@ -1400,7 +1601,7 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
 
         if (file->Version)
         {
-            ver = msi_get_disk_file_version( file->TargetPath );
+            ver = msi_get_disk_file_version( package, file->TargetPath );
             if (ver && msi_compare_file_versions( ver, file->Version ) > 0)
             {
                 TRACE("newer version detected, not removing file\n");
@@ -1415,8 +1616,8 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
 
         TRACE("removing %s\n", debugstr_w(file->File) );
 
-        SetFileAttributesW( file->TargetPath, FILE_ATTRIBUTE_NORMAL );
-        if (!DeleteFileW( file->TargetPath ))
+        msi_set_file_attributes( package, file->TargetPath, FILE_ATTRIBUTE_NORMAL );
+        if (!msi_delete_file( package, file->TargetPath ))
         {
             WARN("failed to delete %s (%u)\n",  debugstr_w(file->TargetPath), GetLastError());
         }
diff --git a/dlls/msi/font.c b/dlls/msi/font.c
index fc050060c0..08dcc14957 100644
--- a/dlls/msi/font.c
+++ b/dlls/msi/font.c
@@ -84,7 +84,7 @@ static const WCHAR regfont2[] =
  * Code based off of code located here
  * http://www.codeproject.com/gdi/fontnamefromfile.asp
  */
-static WCHAR *load_ttf_name_id( const WCHAR *filename, DWORD id )
+static WCHAR *load_ttf_name_id( MSIPACKAGE *package, const WCHAR *filename, DWORD id )
 {
     TT_TABLE_DIRECTORY tblDir;
     BOOL bFound = FALSE;
@@ -96,8 +96,10 @@ static WCHAR *load_ttf_name_id( const WCHAR *filename, DWORD id )
     LPWSTR ret = NULL;
     int i;
 
-    handle = CreateFileW(filename ,GENERIC_READ, 0, NULL, OPEN_EXISTING,
-                    FILE_ATTRIBUTE_NORMAL, 0 );
+    if (package)
+        handle = msi_create_file( package, filename, GENERIC_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL );
+    else
+        handle = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
     if (handle == INVALID_HANDLE_VALUE)
     {
         ERR("Unable to open font file %s\n", debugstr_w(filename));
@@ -175,12 +177,12 @@ end:
     return ret;
 }
 
-static WCHAR *font_name_from_file( const WCHAR *filename )
+static WCHAR *font_name_from_file( MSIPACKAGE *package, const WCHAR *filename )
 {
     static const WCHAR truetypeW[] = {' ','(','T','r','u','e','T','y','p','e',')',0};
     WCHAR *name, *ret = NULL;
 
-    if ((name = load_ttf_name_id( filename, NAME_ID_FULL_FONT_NAME )))
+    if ((name = load_ttf_name_id( package, filename, NAME_ID_FULL_FONT_NAME )))
     {
         if (!name[0])
         {
@@ -196,12 +198,12 @@ static WCHAR *font_name_from_file( const WCHAR *filename )
     return ret;
 }
 
-WCHAR *msi_font_version_from_file( const WCHAR *filename )
+WCHAR *msi_get_font_file_version( MSIPACKAGE *package, const WCHAR *filename )
 {
     static const WCHAR fmtW[] = {'%','u','.','%','u','.','0','.','0',0};
     WCHAR *version, *p, *q, *ret = NULL;
 
-    if ((version = load_ttf_name_id( filename, NAME_ID_VERSION )))
+    if ((version = load_ttf_name_id( package, filename, NAME_ID_VERSION )))
     {
         int len, major = 0, minor = 0;
         if ((p = strchrW( version, ';' ))) *p = 0;
@@ -258,7 +260,7 @@ static UINT ITERATE_RegisterFonts(MSIRECORD *row, LPVOID param)
     RegCreateKeyW(HKEY_LOCAL_MACHINE,regfont2,&hkey2);
 
     if (MSI_RecordIsNull(row,2))
-        name = font_name_from_file( file->TargetPath );
+        name = font_name_from_file( package, file->TargetPath );
     else
         name = msi_dup_record_field(row,2);
 
@@ -341,7 +343,7 @@ static UINT ITERATE_UnregisterFonts( MSIRECORD *row, LPVOID param )
     RegCreateKeyW( HKEY_LOCAL_MACHINE, regfont2, &hkey2 );
 
     if (MSI_RecordIsNull( row, 2 ))
-        name = font_name_from_file( file->TargetPath );
+        name = font_name_from_file( package, file->TargetPath );
     else
         name = msi_dup_record_field( row, 2 );
 
diff --git a/dlls/msi/install.c b/dlls/msi/install.c
index 2cdebd2ad3..f4a231195b 100644
--- a/dlls/msi/install.c
+++ b/dlls/msi/install.c
@@ -571,7 +571,7 @@ UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolder
 
     TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
 
-    attrib = GetFileAttributesW(szFolderPath);
+    attrib = msi_get_file_attributes( package, szFolderPath );
     /* native MSI tests writeability by making temporary files at each drive */
     if (attrib != INVALID_FILE_ATTRIBUTES &&
         (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
diff --git a/dlls/msi/media.c b/dlls/msi/media.c
index 09aac09418..e334c5b6ea 100644
--- a/dlls/msi/media.c
+++ b/dlls/msi/media.c
@@ -439,12 +439,11 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
     attrs = attrs & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
     if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
 
-    handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0,
-                         NULL, CREATE_ALWAYS, attrs, NULL);
+    handle = msi_create_file( data->package, path, GENERIC_READ | GENERIC_WRITE, 0, CREATE_ALWAYS, attrs );
     if (handle == INVALID_HANDLE_VALUE)
     {
         DWORD err = GetLastError();
-        DWORD attrs2 = GetFileAttributesW(path);
+        DWORD attrs2 = msi_get_file_attributes( data->package, path );
 
         if (attrs2 == INVALID_FILE_ATTRIBUTES)
         {
@@ -454,8 +453,8 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
         else if (err == ERROR_ACCESS_DENIED && (attrs2 & FILE_ATTRIBUTE_READONLY))
         {
             TRACE("removing read-only attribute on %s\n", debugstr_w(path));
-            SetFileAttributesW( path, attrs2 & ~FILE_ATTRIBUTE_READONLY );
-            handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, attrs, NULL);
+            msi_set_file_attributes( data->package, path, attrs2 & ~FILE_ATTRIBUTE_READONLY );
+            handle = msi_create_file( data->package, path, GENERIC_READ | GENERIC_WRITE, 0, CREATE_ALWAYS, attrs );
 
             if (handle != INVALID_HANDLE_VALUE) goto done;
             err = GetLastError();
@@ -481,8 +480,8 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint,
             handle = CreateFileW(tmpfileW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, attrs, NULL);
 
             if (handle != INVALID_HANDLE_VALUE &&
-                MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT) &&
-                MoveFileExW(tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT))
+                msi_move_file( data->package, path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ) &&
+                msi_move_file( data->package, tmpfileW, path, MOVEFILE_DELAY_UNTIL_REBOOT ))
             {
                 data->package->need_reboot_at_end = 1;
             }
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 39b9354552..3eca3bfb8d 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -3298,7 +3298,7 @@ UINT WINAPI MsiGetFileVersionW( LPCWSTR path, LPWSTR verbuf, LPDWORD verlen,
     if (ret == ERROR_RESOURCE_DATA_NOT_FOUND && verlen)
     {
         int len;
-        WCHAR *version = msi_font_version_from_file( path );
+        WCHAR *version = msi_get_font_file_version( NULL, path );
         if (!version) return ERROR_FILE_INVALID;
         len = strlenW( version );
         if (len >= *verlen) ret = ERROR_MORE_DATA;
@@ -4107,14 +4107,17 @@ extern VOID WINAPI MD5Init( MD5_CTX *);
 extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
 extern VOID WINAPI MD5Final( MD5_CTX *);
 
-UINT msi_get_filehash( const WCHAR *path, MSIFILEHASHINFO *hash )
+UINT msi_get_filehash( MSIPACKAGE *package, const WCHAR *path, MSIFILEHASHINFO *hash )
 {
     HANDLE handle, mapping;
     void *p;
     DWORD length;
     UINT r = ERROR_FUNCTION_FAILED;
 
-    handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
+    if (package)
+        handle = msi_create_file( package, path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, OPEN_EXISTING, 0 );
+    else
+        handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL );
     if (handle == INVALID_HANDLE_VALUE)
     {
         WARN("can't open file %u\n", GetLastError());
@@ -4171,7 +4174,7 @@ UINT WINAPI MsiGetFileHashW( LPCWSTR szFilePath, DWORD dwOptions,
     if (pHash->dwFileHashInfoSize < sizeof *pHash)
         return ERROR_INVALID_PARAMETER;
 
-    return msi_get_filehash( szFilePath, pHash );
+    return msi_get_filehash( NULL, szFilePath, pHash );
 }
 
 /***********************************************************************
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 39219a646f..dbab8e2292 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -389,6 +389,7 @@ typedef struct tagMSIPACKAGE
     enum platform platform;
     UINT num_langids;
     LANGID *langids;
+    void *cookie;
     struct list patches;
     struct list components;
     struct list features;
@@ -937,12 +938,8 @@ extern BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val) DECLSPEC
 
 extern DWORD msi_version_str_to_dword(LPCWSTR p) DECLSPEC_HIDDEN;
 extern void msi_parse_version_string(LPCWSTR, PDWORD, PDWORD) DECLSPEC_HIDDEN;
-extern VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR) DECLSPEC_HIDDEN;
 extern int msi_compare_file_versions(VS_FIXEDFILEINFO *, const WCHAR *) DECLSPEC_HIDDEN;
 extern int msi_compare_font_versions(const WCHAR *, const WCHAR *) DECLSPEC_HIDDEN;
-extern DWORD msi_get_disk_file_size(LPCWSTR) DECLSPEC_HIDDEN;
-extern BOOL msi_file_hash_matches(MSIFILE *) DECLSPEC_HIDDEN;
-extern UINT msi_get_filehash(const WCHAR *, MSIFILEHASHINFO *) DECLSPEC_HIDDEN;
 
 extern LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value ) DECLSPEC_HIDDEN;
 extern LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value ) DECLSPEC_HIDDEN;
@@ -1034,7 +1031,6 @@ extern WCHAR *msi_create_temp_file(MSIDATABASE *db) DECLSPEC_HIDDEN;
 extern void msi_free_action_script(MSIPACKAGE *package, UINT script) DECLSPEC_HIDDEN;
 extern WCHAR *msi_build_icon_path(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR *msi_build_directory_name(DWORD , ...) DECLSPEC_HIDDEN;
-extern BOOL msi_create_full_path(const WCHAR *path) DECLSPEC_HIDDEN;
 extern void msi_reduce_to_long_filename(WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR *msi_create_component_advertise_string(MSIPACKAGE *, MSICOMPONENT *, const WCHAR *) DECLSPEC_HIDDEN;
 extern void ACTION_UpdateComponentStates(MSIPACKAGE *package, MSIFEATURE *feature) DECLSPEC_HIDDEN;
@@ -1052,7 +1048,6 @@ extern void msi_destroy_assembly_caches(MSIPACKAGE *) DECLSPEC_HIDDEN;
 extern BOOL msi_is_global_assembly(MSICOMPONENT *) DECLSPEC_HIDDEN;
 extern IAssemblyEnum *msi_create_assembly_enum(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR *msi_get_assembly_path(MSIPACKAGE *, const WCHAR *) DECLSPEC_HIDDEN;
-extern WCHAR *msi_font_version_from_file(const WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR **msi_split_string(const WCHAR *, WCHAR) DECLSPEC_HIDDEN;
 extern UINT msi_set_original_database_property(MSIDATABASE *, const WCHAR *) DECLSPEC_HIDDEN;
 extern WCHAR *msi_get_error_message(MSIDATABASE *, int) DECLSPEC_HIDDEN;
@@ -1060,6 +1055,30 @@ extern UINT msi_strncpyWtoA(const WCHAR *str, int len, char *buf, DWORD *sz, BOO
 extern UINT msi_strncpyW(const WCHAR *str, int len, WCHAR *buf, DWORD *sz) DECLSPEC_HIDDEN;
 extern WCHAR *msi_get_package_code(MSIDATABASE *db) DECLSPEC_HIDDEN;
 
+/* wrappers for filesystem functions */
+static inline void msi_disable_fs_redirection( MSIPACKAGE *package )
+{
+    if (is_wow64 && package->platform == PLATFORM_X64) Wow64DisableWow64FsRedirection( &package->cookie );
+}
+static inline void msi_revert_fs_redirection( MSIPACKAGE *package )
+{
+    if (is_wow64 && package->platform == PLATFORM_X64) Wow64RevertWow64FsRedirection( package->cookie );
+}
+extern HANDLE msi_create_file( MSIPACKAGE *, const WCHAR *, DWORD, DWORD, DWORD, DWORD ) DECLSPEC_HIDDEN;
+extern BOOL msi_delete_file( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern BOOL msi_remove_directory( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern DWORD msi_get_file_attributes( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern BOOL msi_set_file_attributes( MSIPACKAGE *, const WCHAR *, DWORD ) DECLSPEC_HIDDEN;
+extern HANDLE msi_find_first_file( MSIPACKAGE *, const WCHAR *, WIN32_FIND_DATAW * ) DECLSPEC_HIDDEN;
+extern BOOL msi_find_next_file( MSIPACKAGE *, HANDLE, WIN32_FIND_DATAW * ) DECLSPEC_HIDDEN;
+extern BOOL msi_move_file( MSIPACKAGE *, const WCHAR *, const WCHAR *, DWORD ) DECLSPEC_HIDDEN;
+extern DWORD msi_get_file_version_info( MSIPACKAGE *, const WCHAR *, DWORD, BYTE * ) DECLSPEC_HIDDEN;
+extern BOOL msi_create_full_path( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern DWORD msi_get_disk_file_size( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern VS_FIXEDFILEINFO *msi_get_disk_file_version( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+extern UINT msi_get_filehash( MSIPACKAGE *, const WCHAR *, MSIFILEHASHINFO * ) DECLSPEC_HIDDEN;
+extern WCHAR *msi_get_font_file_version( MSIPACKAGE *, const WCHAR * ) DECLSPEC_HIDDEN;
+
 /* media */
 
 typedef BOOL (*PMSICABEXTRACTCB)(MSIPACKAGE *, LPCWSTR, DWORD, LPWSTR *, DWORD *, PVOID);
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index b57e89d077..563f55a123 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1630,6 +1630,13 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage)
         package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
                                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
 
+    if (!msi_init_assembly_caches( package ))
+    {
+        ERR("can't initialize assembly caches\n");
+        msiobj_release( &package->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+
     /* FIXME: when should these messages be sent? */
     data_row = MSI_CreateRecord(3);
     if (!data_row)
-- 
2.11.0




More information about the wine-devel mailing list