Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
6771ed40
Commit
6771ed40
authored
Mar 22, 2011
by
David Hedberg
Committed by
Alexandre Julliard
Mar 29, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Add support for patching files.
parent
18973df9
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
252 additions
and
10 deletions
+252
-10
action.c
dlls/msi/action.c
+65
-8
files.c
dlls/msi/files.c
+153
-1
helpers.c
dlls/msi/helpers.c
+14
-0
msipriv.h
dlls/msi/msipriv.h
+14
-0
package.c
dlls/msi/package.c
+1
-0
msidefs.h
include/msidefs.h
+5
-1
No files found.
dlls/msi/action.c
View file @
6771ed40
...
...
@@ -115,8 +115,6 @@ static const WCHAR szInstallODBC[] =
{
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'l'
,
'l'
,
'O'
,
'D'
,
'B'
,
'C'
,
0
};
static
const
WCHAR
szInstallServices
[]
=
{
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'l'
,
'l'
,
'S'
,
'e'
,
'r'
,
'v'
,
'i'
,
'c'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szPatchFiles
[]
=
{
'P'
,
'a'
,
't'
,
'c'
,
'h'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szPublishComponents
[]
=
{
'P'
,
'u'
,
'b'
,
'l'
,
'i'
,
's'
,
'h'
,
'C'
,
'o'
,
'm'
,
'p'
,
'o'
,
'n'
,
'e'
,
'n'
,
't'
,
's'
,
0
};
static
const
WCHAR
szRegisterComPlus
[]
=
...
...
@@ -1847,6 +1845,70 @@ static UINT load_all_files(MSIPACKAGE *package)
return
ERROR_SUCCESS
;
}
static
UINT
load_patch
(
MSIRECORD
*
row
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
MSIFILEPATCH
*
patch
;
LPWSTR
file_key
;
patch
=
msi_alloc_zero
(
sizeof
(
MSIFILEPATCH
)
);
if
(
!
patch
)
return
ERROR_NOT_ENOUGH_MEMORY
;
file_key
=
msi_dup_record_field
(
row
,
1
);
patch
->
File
=
get_loaded_file
(
package
,
file_key
);
msi_free
(
file_key
);
if
(
!
patch
->
File
)
{
ERR
(
"Failed to find target for patch in File table
\n
"
);
msi_free
(
patch
);
return
ERROR_FUNCTION_FAILED
;
}
patch
->
Sequence
=
MSI_RecordGetInteger
(
row
,
2
);
/* FIXME: The database should be properly transformed */
patch
->
Sequence
+=
MSI_INITIAL_MEDIA_TRANSFORM_OFFSET
;
patch
->
PatchSize
=
MSI_RecordGetInteger
(
row
,
3
);
patch
->
Attributes
=
MSI_RecordGetInteger
(
row
,
4
);
patch
->
IsApplied
=
FALSE
;
/* FIXME:
* Header field - for patch validation.
* _StreamRef - External key into MsiPatchHeaders (instead of the header field)
*/
TRACE
(
"Patch Loaded (%s)
\n
"
,
debugstr_w
(
patch
->
File
->
File
));
list_add_tail
(
&
package
->
filepatches
,
&
patch
->
entry
);
return
ERROR_SUCCESS
;
}
static
UINT
load_all_patches
(
MSIPACKAGE
*
package
)
{
MSIQUERY
*
view
;
UINT
rc
;
static
const
WCHAR
Query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'P'
,
'a'
,
't'
,
'c'
,
'h'
,
'`'
,
' '
,
'O'
,
'R'
,
'D'
,
'E'
,
'R'
,
' '
,
'B'
,
'Y'
,
' '
,
'`'
,
'S'
,
'e'
,
'q'
,
'u'
,
'e'
,
'n'
,
'c'
,
'e'
,
'`'
,
0
};
if
(
!
list_empty
(
&
package
->
filepatches
))
return
ERROR_SUCCESS
;
rc
=
MSI_DatabaseOpenViewW
(
package
->
db
,
Query
,
&
view
);
if
(
rc
!=
ERROR_SUCCESS
)
return
ERROR_SUCCESS
;
rc
=
MSI_IterateRecords
(
view
,
NULL
,
load_patch
,
package
);
msiobj_release
(
&
view
->
hdr
);
return
ERROR_SUCCESS
;
}
static
UINT
load_folder
(
MSIRECORD
*
row
,
LPVOID
param
)
{
MSIPACKAGE
*
package
=
param
;
...
...
@@ -1955,6 +2017,7 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
load_all_components
(
package
);
load_all_features
(
package
);
load_all_files
(
package
);
load_all_patches
(
package
);
return
ERROR_SUCCESS
;
}
...
...
@@ -7351,12 +7414,6 @@ static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
return
ERROR_SUCCESS
;
}
static
UINT
ACTION_PatchFiles
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
table
[]
=
{
'P'
,
'a'
,
't'
,
'c'
,
'h'
,
0
};
return
msi_unimplemented_action_stub
(
package
,
"PatchFiles"
,
table
);
}
static
UINT
ACTION_BindImage
(
MSIPACKAGE
*
package
)
{
static
const
WCHAR
table
[]
=
{
'B'
,
'i'
,
'n'
,
'd'
,
'I'
,
'm'
,
'a'
,
'g'
,
'e'
,
0
};
...
...
dlls/msi/files.c
View file @
6771ed40
...
...
@@ -25,7 +25,7 @@
* InstallFiles
* DuplicateFiles
* MoveFiles
* PatchFiles
(TODO)
* PatchFiles
* RemoveDuplicateFiles
* RemoveFiles
*/
...
...
@@ -47,6 +47,9 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
msi
);
static
HMODULE
hmspatcha
;
static
BOOL
(
WINAPI
*
ApplyPatchToFileW
)(
LPCWSTR
,
LPCWSTR
,
LPCWSTR
,
ULONG
);
static
void
msi_file_update_ui
(
MSIPACKAGE
*
package
,
MSIFILE
*
f
,
const
WCHAR
*
action
)
{
MSIRECORD
*
uirow
;
...
...
@@ -388,6 +391,155 @@ done:
return
rc
;
}
static
BOOL
load_mspatcha
(
void
)
{
hmspatcha
=
LoadLibraryA
(
"mspatcha.dll"
);
if
(
!
hmspatcha
)
{
ERR
(
"Failed to load mspatcha.dll: %d
\n
"
,
GetLastError
());
return
FALSE
;
}
ApplyPatchToFileW
=
(
void
*
)
GetProcAddress
(
hmspatcha
,
"ApplyPatchToFileW"
);
if
(
!
ApplyPatchToFileW
)
{
ERR
(
"GetProcAddress(ApplyPatchToFileW) failed: %d.
\n
"
,
GetLastError
());
return
FALSE
;
}
return
TRUE
;
}
static
void
unload_mspatch
(
void
)
{
FreeLibrary
(
hmspatcha
);
}
static
BOOL
patchfiles_cb
(
MSIPACKAGE
*
package
,
LPCWSTR
file
,
DWORD
action
,
LPWSTR
*
path
,
DWORD
*
attrs
,
PVOID
user
)
{
static
MSIFILEPATCH
*
p
=
NULL
;
static
WCHAR
patch_path
[
MAX_PATH
]
=
{
0
};
static
WCHAR
temp_folder
[
MAX_PATH
]
=
{
0
};
if
(
action
==
MSICABEXTRACT_BEGINEXTRACT
)
{
if
(
temp_folder
[
0
]
==
'\0'
)
GetTempPathW
(
MAX_PATH
,
temp_folder
);
p
=
get_loaded_filepatch
(
package
,
file
);
if
(
!
p
)
{
TRACE
(
"unknown file in cabinet (%s)
\n
"
,
debugstr_w
(
file
));
return
FALSE
;
}
msi_file_update_ui
(
package
,
p
->
File
,
szPatchFiles
);
GetTempFileNameW
(
temp_folder
,
NULL
,
0
,
patch_path
);
*
path
=
strdupW
(
patch_path
);
*
attrs
=
p
->
File
->
Attributes
;
}
else
if
(
action
==
MSICABEXTRACT_FILEEXTRACTED
)
{
WCHAR
patched_file
[
MAX_PATH
];
BOOL
br
;
GetTempFileNameW
(
temp_folder
,
NULL
,
0
,
patched_file
);
br
=
ApplyPatchToFileW
(
patch_path
,
p
->
File
->
TargetPath
,
patched_file
,
0
);
if
(
br
)
{
/* FIXME: baseline cache */
DeleteFileW
(
p
->
File
->
TargetPath
);
MoveFileW
(
patched_file
,
p
->
File
->
TargetPath
);
p
->
IsApplied
=
TRUE
;
}
else
ERR
(
"Failed patch %s: %d.
\n
"
,
debugstr_w
(
p
->
File
->
TargetPath
),
GetLastError
());
DeleteFileW
(
patch_path
);
p
=
NULL
;
}
return
TRUE
;
}
UINT
ACTION_PatchFiles
(
MSIPACKAGE
*
package
)
{
MSIFILEPATCH
*
patch
;
MSIMEDIAINFO
*
mi
;
UINT
rc
=
ERROR_SUCCESS
;
BOOL
mspatcha_loaded
=
FALSE
;
TRACE
(
"%p
\n
"
,
package
);
/* increment progress bar each time action data is sent */
ui_progress
(
package
,
1
,
1
,
0
,
0
);
mi
=
msi_alloc_zero
(
sizeof
(
MSIMEDIAINFO
)
);
LIST_FOR_EACH_ENTRY
(
patch
,
&
package
->
filepatches
,
MSIFILEPATCH
,
entry
)
{
MSIFILE
*
file
=
patch
->
File
;
rc
=
msi_load_media_info
(
package
,
patch
->
Sequence
,
mi
);
if
(
rc
!=
ERROR_SUCCESS
)
{
ERR
(
"Unable to load media info for %s (%u)
\n
"
,
debugstr_w
(
file
->
File
),
rc
);
return
ERROR_FUNCTION_FAILED
;
}
if
(
!
file
->
Component
->
Enabled
)
continue
;
if
(
!
patch
->
IsApplied
)
{
MSICABDATA
data
;
rc
=
ready_media
(
package
,
patch
->
Sequence
,
TRUE
,
mi
);
if
(
rc
!=
ERROR_SUCCESS
)
{
ERR
(
"Failed to ready media for %s
\n
"
,
debugstr_w
(
file
->
File
));
goto
done
;
}
if
(
!
mspatcha_loaded
&&
!
load_mspatcha
())
{
rc
=
ERROR_FUNCTION_FAILED
;
goto
done
;
}
mspatcha_loaded
=
TRUE
;
data
.
mi
=
mi
;
data
.
package
=
package
;
data
.
cb
=
patchfiles_cb
;
data
.
user
=
(
PVOID
)(
UINT_PTR
)
mi
->
disk_id
;
if
(
!
msi_cabextract
(
package
,
mi
,
&
data
))
{
ERR
(
"Failed to extract cabinet: %s
\n
"
,
debugstr_w
(
mi
->
cabinet
));
rc
=
ERROR_INSTALL_FAILURE
;
goto
done
;
}
}
if
(
!
patch
->
IsApplied
&&
!
(
patch
->
Attributes
&
msidbPatchAttributesNonVital
))
{
ERR
(
"Failed to apply patch to file: %s
\n
"
,
debugstr_w
(
file
->
File
));
rc
=
ERROR_INSTALL_FAILURE
;
goto
done
;
}
}
done:
msi_free_media_info
(
mi
);
if
(
mspatcha_loaded
)
unload_mspatch
();
return
rc
;
}
#define is_dot_dir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
typedef
struct
...
...
dlls/msi/helpers.c
View file @
6771ed40
...
...
@@ -134,6 +134,20 @@ MSIFILE* get_loaded_file( MSIPACKAGE* package, LPCWSTR key )
return
NULL
;
}
MSIFILEPATCH
*
get_loaded_filepatch
(
MSIPACKAGE
*
package
,
LPCWSTR
key
)
{
MSIFILEPATCH
*
patch
;
/* FIXME: There might be more than one patch */
LIST_FOR_EACH_ENTRY
(
patch
,
&
package
->
filepatches
,
MSIFILEPATCH
,
entry
)
{
if
(
!
strcmpW
(
key
,
patch
->
File
->
File
))
return
patch
;
}
return
NULL
;
}
int
track_tempfile
(
MSIPACKAGE
*
package
,
LPCWSTR
path
)
{
MSITEMPFILE
*
temp
;
...
...
dlls/msi/msipriv.h
View file @
6771ed40
...
...
@@ -346,6 +346,7 @@ typedef struct tagMSIPACKAGE
struct
list
components
;
struct
list
features
;
struct
list
files
;
struct
list
filepatches
;
struct
list
tempfiles
;
struct
list
folders
;
struct
list
binaries
;
...
...
@@ -531,6 +532,16 @@ typedef struct tagMSITEMPFILE
LPWSTR
Path
;
}
MSITEMPFILE
;
typedef
struct
tagMSIFILEPATCH
{
struct
list
entry
;
MSIFILE
*
File
;
INT
Sequence
;
INT
PatchSize
;
INT
Attributes
;
BOOL
IsApplied
;
}
MSIFILEPATCH
;
typedef
struct
tagMSIAPPID
{
struct
list
entry
;
...
...
@@ -921,6 +932,7 @@ extern UINT ACTION_AppSearch(MSIPACKAGE *package);
extern
UINT
ACTION_CCPSearch
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_FindRelatedProducts
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_InstallFiles
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_PatchFiles
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_RemoveFiles
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_MoveFiles
(
MSIPACKAGE
*
package
);
extern
UINT
ACTION_DuplicateFiles
(
MSIPACKAGE
*
package
);
...
...
@@ -952,6 +964,7 @@ extern void msi_reset_folders( MSIPACKAGE *package, BOOL source );
extern
MSICOMPONENT
*
get_loaded_component
(
MSIPACKAGE
*
package
,
LPCWSTR
Component
);
extern
MSIFEATURE
*
get_loaded_feature
(
MSIPACKAGE
*
package
,
LPCWSTR
Feature
);
extern
MSIFILE
*
get_loaded_file
(
MSIPACKAGE
*
package
,
LPCWSTR
file
);
extern
MSIFILEPATCH
*
get_loaded_filepatch
(
MSIPACKAGE
*
package
,
LPCWSTR
key
);
extern
MSIFOLDER
*
get_loaded_folder
(
MSIPACKAGE
*
package
,
LPCWSTR
dir
);
extern
int
track_tempfile
(
MSIPACKAGE
*
package
,
LPCWSTR
path
);
extern
UINT
schedule_action
(
MSIPACKAGE
*
package
,
UINT
script
,
LPCWSTR
action
);
...
...
@@ -1049,6 +1062,7 @@ static const WCHAR szRegisterMIMEInfo[] = {'R','e','g','i','s','t','e','r','M','
static
const
WCHAR
szDuplicateFiles
[]
=
{
'D'
,
'u'
,
'p'
,
'l'
,
'i'
,
'c'
,
'a'
,
't'
,
'e'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szRemoveDuplicateFiles
[]
=
{
'R'
,
'e'
,
'm'
,
'o'
,
'v'
,
'e'
,
'D'
,
'u'
,
'p'
,
'l'
,
'i'
,
'c'
,
'a'
,
't'
,
'e'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szInstallFiles
[]
=
{
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'l'
,
'l'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szPatchFiles
[]
=
{
'P'
,
'a'
,
't'
,
'c'
,
'h'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szRemoveFiles
[]
=
{
'R'
,
'e'
,
'm'
,
'o'
,
'v'
,
'e'
,
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
0
};
static
const
WCHAR
szFindRelatedProducts
[]
=
{
'F'
,
'i'
,
'n'
,
'd'
,
'R'
,
'e'
,
'l'
,
'a'
,
't'
,
'e'
,
'd'
,
'P'
,
'r'
,
'o'
,
'd'
,
'u'
,
'c'
,
't'
,
's'
,
0
};
static
const
WCHAR
szAllUsers
[]
=
{
'A'
,
'L'
,
'L'
,
'U'
,
'S'
,
'E'
,
'R'
,
'S'
,
0
};
...
...
dlls/msi/package.c
View file @
6771ed40
...
...
@@ -1065,6 +1065,7 @@ static MSIPACKAGE *msi_alloc_package( void )
list_init
(
&
package
->
components
);
list_init
(
&
package
->
features
);
list_init
(
&
package
->
files
);
list_init
(
&
package
->
filepatches
);
list_init
(
&
package
->
tempfiles
);
list_init
(
&
package
->
folders
);
list_init
(
&
package
->
subscriptions
);
...
...
include/msidefs.h
View file @
6771ed40
...
...
@@ -38,7 +38,11 @@ enum msidbFileAttributes {
msidbFileAttributesNoncompressed
=
0x00002000
,
msidbFileAttributesCompressed
=
0x00004000
};
enum
msidbPatchAttributes
{
msidbPatchAttributesNonVital
=
0x00000001
};
enum
msidbDialogAttributes
{
msidbDialogAttributesVisible
=
0x00000001
,
msidbDialogAttributesModal
=
0x00000002
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment