ReactOS 0.4.15-dev-8344-g0574987
patch.c File Reference
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "objbase.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "msipriv.h"
Include dependency graph for patch.c:

Go to the source code of this file.

Classes

struct  transform_desc
 
struct  patch_offset
 
struct  patch_offset_list
 
struct  patch_media
 

Macros

#define COBJMACROS
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (msi)
 
static BOOL match_language (MSIPACKAGE *package, LANGID langid)
 
static void free_transform_desc (struct transform_desc *desc)
 
static struct transform_descparse_transform_desc (const WCHAR *str)
 
static UINT check_transform_applicable (MSIPACKAGE *package, IStorage *transform)
 
static UINT apply_substorage_transform (MSIPACKAGE *package, MSIDATABASE *patch_db, LPCWSTR name)
 
UINT msi_check_patch_applicable (MSIPACKAGE *package, MSISUMMARYINFO *si)
 
static UINT msi_parse_patch_summary (MSISUMMARYINFO *si, MSIPATCHINFO **patch)
 
static UINT patch_set_media_source_prop (MSIPACKAGE *package)
 
static struct patch_offset_listpatch_offset_list_create (void)
 
static void patch_offset_list_free (struct patch_offset_list *pos)
 
static void patch_offset_get_filepatches (MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos)
 
static void patch_offset_get_files (MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos)
 
static UINT patch_update_file_sequence (MSIDATABASE *db, const struct patch_offset_list *pos, MSIQUERY *view, MSIRECORD *rec)
 
static UINT patch_update_filepatch_sequence (MSIDATABASE *db, const struct patch_offset_list *pos, MSIQUERY *view, MSIRECORD *rec)
 
static UINT patch_offset_modify_db (MSIDATABASE *db, struct patch_offset_list *pos)
 
static UINT patch_add_media (MSIPACKAGE *package, IStorage *storage, MSIPATCHINFO *patch)
 
static UINT patch_set_offsets (MSIDATABASE *db, MSIPATCHINFO *patch)
 
static DWORD is_uninstallable (MSIDATABASE *db)
 
static UINT msi_apply_patch_db (MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch)
 
void msi_free_patchinfo (MSIPATCHINFO *patch)
 
static UINT msi_apply_patch_package (MSIPACKAGE *package, const WCHAR *file)
 
UINT msi_apply_patches (MSIPACKAGE *package)
 
UINT msi_apply_transforms (MSIPACKAGE *package)
 
UINT msi_apply_registered_patch (MSIPACKAGE *package, LPCWSTR patch_code)
 

Variables

static const WCHAR patch_media_query []
 

Macro Definition Documentation

◆ COBJMACROS

#define COBJMACROS

Definition at line 23 of file patch.c.

Function Documentation

◆ apply_substorage_transform()

static UINT apply_substorage_transform ( MSIPACKAGE package,
MSIDATABASE patch_db,
LPCWSTR  name 
)
static

Definition at line 259 of file patch.c.

260{
262 IStorage *stg = NULL;
263 HRESULT r;
264
265 TRACE("%p %s\n", package, debugstr_w(name));
266
267 if (*name++ != ':')
268 {
269 ERR("expected a colon in %s\n", debugstr_w(name));
271 }
272 r = IStorage_OpenStorage( patch_db->storage, name, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg );
273 if (SUCCEEDED(r))
274 {
275 ret = check_transform_applicable( package, stg );
276 if (ret == ERROR_SUCCESS)
277 {
279 msi_table_apply_transform( package->db, stg, 0 );
280 }
281 else
282 {
283 TRACE("substorage transform %s wasn't applicable\n", debugstr_w(name));
284 }
285 IStorage_Release( stg );
286 }
287 else
288 {
289 ERR("failed to open substorage %s\n", debugstr_w(name));
290 }
291 return ERROR_SUCCESS;
292}
#define ERR(fmt,...)
Definition: precomp.h:57
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
static UINT check_transform_applicable(MSIPACKAGE *package, IStorage *transform)
Definition: patch.c:120
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define debugstr_w
Definition: kernel32.h:32
UINT msi_table_apply_transform(MSIDATABASE *db, IStorage *stg, int err_cond) DECLSPEC_HIDDEN
Definition: table.c:3371
@ MSITRANSFORM_ERROR_VIEWTRANSFORM
Definition: msiquery.h:156
unsigned int UINT
Definition: ndis.h:50
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define TRACE(s)
Definition: solgame.cpp:4
Definition: name.c:39
IStorage * storage
Definition: msipriv.h:109
MSIDATABASE * db
Definition: msipriv.h:394
int ret
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985

Referenced by msi_apply_patch_db(), and msi_apply_transforms().

◆ check_transform_applicable()

static UINT check_transform_applicable ( MSIPACKAGE package,
IStorage transform 
)
static

Definition at line 120 of file patch.c.

121{
122 static const UINT supported_flags =
126 MSISUMMARYINFO *si;
127 UINT r, valid_flags = 0, wanted_flags = 0;
128 WCHAR *template, *product, *p;
129 struct transform_desc *desc;
130
131 r = msi_get_suminfo( transform, 0, &si );
132 if (r != ERROR_SUCCESS)
133 {
134 WARN("no summary information!\n");
135 return r;
136 }
137 wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
138 wanted_flags &= 0xffff; /* mask off error condition flags */
139 TRACE("validation flags 0x%04x\n", wanted_flags);
140
141 /* native is not validating platform */
142 wanted_flags &= ~MSITRANSFORM_VALIDATE_PLATFORM;
143
144 if (wanted_flags & ~supported_flags)
145 {
146 FIXME("unsupported validation flags 0x%04x\n", wanted_flags);
147 msiobj_release( &si->hdr );
149 }
150 if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
151 {
152 WARN("no template property!\n");
153 msiobj_release( &si->hdr );
155 }
156 TRACE("template property: %s\n", debugstr_w(template));
157 if (!(product = msi_get_suminfo_product( transform )))
158 {
159 WARN("no product property!\n");
160 msi_free( template );
161 msiobj_release( &si->hdr );
163 }
164 TRACE("product property: %s\n", debugstr_w(product));
165 if (!(desc = parse_transform_desc( product )))
166 {
167 msi_free( template );
168 msiobj_release( &si->hdr );
170 }
171 msi_free( product );
172
173 if (wanted_flags & MSITRANSFORM_VALIDATE_LANGUAGE)
174 {
175 if (!template[0] || ((p = wcschr( template, ';' )) && match_language( package, wcstol( p + 1, NULL, 10 ) )))
176 {
177 valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
178 }
179 }
180 if (wanted_flags & MSITRANSFORM_VALIDATE_PRODUCT)
181 {
182 WCHAR *product_code_installed = msi_dup_property( package->db, L"ProductCode" );
183
184 if (!product_code_installed)
185 {
186 msi_free( template );
188 msiobj_release( &si->hdr );
190 }
191 if (!wcscmp( desc->product_code_from, product_code_installed ))
192 {
193 valid_flags |= MSITRANSFORM_VALIDATE_PRODUCT;
194 }
195 msi_free( product_code_installed );
196 }
197 msi_free( template );
198 if (wanted_flags & MSITRANSFORM_VALIDATE_MAJORVERSION)
199 {
200 WCHAR *product_version_installed = msi_dup_property( package->db, L"ProductVersion" );
201 DWORD major_installed, minor_installed, major, minor;
202
203 if (!product_version_installed)
204 {
206 msiobj_release( &si->hdr );
208 }
209 msi_parse_version_string( product_version_installed, &major_installed, &minor_installed );
210 msi_parse_version_string( desc->version_from, &major, &minor );
211
212 if (major_installed == major)
213 {
215 wanted_flags &= ~MSITRANSFORM_VALIDATE_MINORVERSION;
216 }
217 msi_free( product_version_installed );
218 }
219 else if (wanted_flags & MSITRANSFORM_VALIDATE_MINORVERSION)
220 {
221 WCHAR *product_version_installed = msi_dup_property( package->db, L"ProductVersion" );
222 DWORD major_installed, minor_installed, major, minor;
223
224 if (!product_version_installed)
225 {
227 msiobj_release( &si->hdr );
229 }
230 msi_parse_version_string( product_version_installed, &major_installed, &minor_installed );
231 msi_parse_version_string( desc->version_from, &major, &minor );
232
233 if (major_installed == major && minor_installed == minor)
235 msi_free( product_version_installed );
236 }
237 if (wanted_flags & MSITRANSFORM_VALIDATE_UPGRADECODE)
238 {
239 WCHAR *upgrade_code_installed = msi_dup_property( package->db, L"UpgradeCode" );
240
241 if (!upgrade_code_installed)
242 {
244 msiobj_release( &si->hdr );
246 }
247 if (!wcscmp( desc->upgrade_code, upgrade_code_installed ))
249 msi_free( upgrade_code_installed );
250 }
251
253 msiobj_release( &si->hdr );
254 if ((valid_flags & wanted_flags) != wanted_flags) return ERROR_FUNCTION_FAILED;
255 TRACE("applicable transform\n");
256 return ERROR_SUCCESS;
257}
void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
Definition: appsearch.c:52
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define wcschr
Definition: compat.h:17
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
static struct transform_desc * parse_transform_desc(const WCHAR *str)
Definition: patch.c:65
static void free_transform_desc(struct transform_desc *desc)
Definition: patch.c:55
static BOOL match_language(MSIPACKAGE *package, LANGID langid)
Definition: patch.c:34
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLfloat GLfloat p
Definition: glext.h:8902
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
static const WCHAR desc[]
Definition: protectdata.c:36
#define PID_TEMPLATE
Definition: suminfo.c:49
#define PID_CHARCOUNT
Definition: suminfo.c:58
INT msi_suminfo_get_int32(MSISUMMARYINFO *si, UINT uiProperty) DECLSPEC_HIDDEN
Definition: suminfo.c:708
LPWSTR msi_suminfo_dup_string(MSISUMMARYINFO *si, UINT uiProperty) DECLSPEC_HIDDEN
Definition: suminfo.c:696
static void msi_free(void *mem)
Definition: msipriv.h:1159
UINT msi_get_suminfo(IStorage *stg, UINT uiUpdateCount, MSISUMMARYINFO **si) DECLSPEC_HIDDEN
Definition: suminfo.c:457
LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop) DECLSPEC_HIDDEN
Definition: package.c:2283
LPWSTR msi_get_suminfo_product(IStorage *stg) DECLSPEC_HIDDEN
Definition: suminfo.c:720
@ MSITRANSFORM_VALIDATE_LANGUAGE
Definition: msiquery.h:161
@ MSITRANSFORM_VALIDATE_PLATFORM
Definition: msiquery.h:163
@ MSITRANSFORM_VALIDATE_UPGRADECODE
Definition: msiquery.h:172
@ MSITRANSFORM_VALIDATE_MAJORVERSION
Definition: msiquery.h:164
@ MSITRANSFORM_VALIDATE_PRODUCT
Definition: msiquery.h:162
@ MSITRANSFORM_VALIDATE_MINORVERSION
Definition: msiquery.h:165
#define L(x)
Definition: ntvdm.h:50
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
MSIOBJECTHDR hdr
Definition: msipriv.h:486
#define ERROR_INSTALL_PACKAGE_INVALID
Definition: winerror.h:978
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by apply_substorage_transform().

◆ free_transform_desc()

static void free_transform_desc ( struct transform_desc desc)
static

Definition at line 55 of file patch.c.

56{
57 msi_free( desc->product_code_from );
58 msi_free( desc->product_code_to );
59 msi_free( desc->version_from );
60 msi_free( desc->version_to );
61 msi_free( desc->upgrade_code );
62 msi_free( desc );
63}

Referenced by check_transform_applicable(), and parse_transform_desc().

◆ is_uninstallable()

static DWORD is_uninstallable ( MSIDATABASE db)
static

Definition at line 807 of file patch.c.

808{
809 MSIQUERY *view;
810 MSIRECORD *rec;
811 DWORD ret = 0;
812
813 if (MSI_DatabaseOpenViewW( db, L"SELECT `Value` FROM `MsiPatchMetadata` WHERE `Company` IS NULL "
814 L"AND `Property`='AllowRemoval'", &view ) != ERROR_SUCCESS) return 0;
816 {
817 msiobj_release( &view->hdr );
818 return 0;
819 }
820
821 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
822 {
823 const WCHAR *value = MSI_RecordGetString( rec, 1 );
824 ret = wcstol( value, NULL, 10 );
825 msiobj_release( &rec->hdr );
826 }
827
828 FIXME( "check other criteria\n" );
829
830 msiobj_release( &view->hdr );
831 return ret;
832}
UINT MSI_ViewFetch(MSIQUERY *, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:377
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *) DECLSPEC_HIDDEN
Definition: msiquery.c:502
MSIOBJECTHDR hdr
Definition: msipriv.h:151
Definition: pdh_main.c:94

Referenced by msi_apply_patch_db().

◆ match_language()

static BOOL match_language ( MSIPACKAGE package,
LANGID  langid 
)
static

Definition at line 34 of file patch.c.

35{
36 UINT i;
37
38 if (!package->num_langids || !langid) return TRUE;
39 for (i = 0; i < package->num_langids; i++)
40 {
41 if (package->langids[i] == langid) return TRUE;
42 }
43 return FALSE;
44}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LANGID langid
Definition: msctf.idl:644
UINT num_langids
Definition: msipriv.h:397
LANGID * langids
Definition: msipriv.h:398

Referenced by check_transform_applicable().

◆ msi_apply_patch_db()

static UINT msi_apply_patch_db ( MSIPACKAGE package,
MSIDATABASE patch_db,
MSIPATCHINFO patch 
)
static

Definition at line 834 of file patch.c.

835{
837 WCHAR **substorage;
838
839 /* apply substorage transforms */
840 substorage = msi_split_string( patch->transforms, ';' );
841 for (i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++)
842 {
843 r = apply_substorage_transform( package, patch_db, substorage[i] );
844 if (r == ERROR_SUCCESS)
845 {
846 r = patch_set_offsets( package->db, patch );
847 if (r == ERROR_SUCCESS)
848 r = patch_add_media( package, patch_db->storage, patch );
849 }
850 }
851 msi_free( substorage );
852 if (r != ERROR_SUCCESS)
853 return r;
854
855 r = patch_set_media_source_prop( package );
856 if (r != ERROR_SUCCESS)
857 return r;
858
859 patch->uninstallable = is_uninstallable( patch_db );
861 list_add_tail( &package->patches, &patch->entry );
862 return ERROR_SUCCESS;
863}
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
WCHAR ** msi_split_string(const WCHAR *str, WCHAR sep)
Definition: action.c:305
static UINT patch_add_media(MSIPACKAGE *package, IStorage *storage, MSIPATCHINFO *patch)
Definition: patch.c:644
static UINT patch_set_offsets(MSIDATABASE *db, MSIPATCHINFO *patch)
Definition: patch.c:751
static UINT apply_substorage_transform(MSIPACKAGE *package, MSIDATABASE *patch_db, LPCWSTR name)
Definition: patch.c:259
static DWORD is_uninstallable(MSIDATABASE *db)
Definition: patch.c:807
static UINT patch_set_media_source_prop(MSIPACKAGE *package)
Definition: patch.c:369
@ MSIPATCHSTATE_APPLIED
Definition: msi.h:54
struct list patches
Definition: msipriv.h:400
DWORD uninstallable
Definition: msipriv.h:207
LPWSTR transforms
Definition: msipriv.h:203
struct list entry
Definition: msipriv.h:200
MSIPATCHSTATE state
Definition: msipriv.h:206

Referenced by msi_apply_patch_package(), and msi_apply_registered_patch().

◆ msi_apply_patch_package()

static UINT msi_apply_patch_package ( MSIPACKAGE package,
const WCHAR file 
)
static

Definition at line 875 of file patch.c.

876{
877 MSIDATABASE *patch_db = NULL;
878 WCHAR localfile[MAX_PATH];
879 MSISUMMARYINFO *si;
880 MSIPATCHINFO *patch = NULL;
881 UINT r;
882
883 TRACE("%p, %s\n", package, debugstr_w(file));
884
886 if (r != ERROR_SUCCESS)
887 {
888 ERR("failed to open patch collection %s\n", debugstr_w( file ) );
889 return r;
890 }
891 r = msi_get_suminfo( patch_db->storage, 0, &si );
892 if (r != ERROR_SUCCESS)
893 {
894 msiobj_release( &patch_db->hdr );
895 return r;
896 }
897 r = msi_check_patch_applicable( package, si );
898 if (r != ERROR_SUCCESS)
899 {
900 TRACE("patch not applicable\n");
902 goto done;
903 }
904 r = msi_parse_patch_summary( si, &patch );
905 if ( r != ERROR_SUCCESS )
906 goto done;
907
908 r = msi_create_empty_local_file( localfile, L".msp" );
909 if ( r != ERROR_SUCCESS )
910 goto done;
911
913 patch->registered = FALSE;
914 if (!(patch->filename = strdupW( file ))) goto done;
915 if (!(patch->localfile = strdupW( localfile ))) goto done;
916
917 r = msi_apply_patch_db( package, patch_db, patch );
918 if (r != ERROR_SUCCESS) WARN("patch failed to apply %u\n", r);
919
920done:
921 msiobj_release( &si->hdr );
922 msiobj_release( &patch_db->hdr );
923 if (patch && r != ERROR_SUCCESS)
924 {
925 DeleteFileW( patch->localfile );
926 msi_free_patchinfo( patch );
927 }
928 return r;
929}
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
Definition: database.c:140
static UINT msi_parse_patch_summary(MSISUMMARYINFO *si, MSIPATCHINFO **patch)
Definition: patch.c:318
UINT msi_check_patch_applicable(MSIPACKAGE *package, MSISUMMARYINFO *si)
Definition: patch.c:294
static UINT msi_apply_patch_db(MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch)
Definition: patch.c:834
void msi_free_patchinfo(MSIPATCHINFO *patch)
Definition: patch.c:865
UINT msi_create_empty_local_file(LPWSTR path, LPCWSTR suffix) DECLSPEC_HIDDEN
Definition: package.c:1063
#define MSIDBOPEN_PATCHFILE
Definition: msiquery.h:79
#define MSIDBOPEN_READONLY
Definition: msiquery.h:66
Definition: fci.c:127
MSIOBJECTHDR hdr
Definition: msipriv.h:108
BOOL registered
Definition: msipriv.h:209
LPWSTR localfile
Definition: msipriv.h:205
LPWSTR filename
Definition: msipriv.h:204

Referenced by msi_apply_patches().

◆ msi_apply_patches()

UINT msi_apply_patches ( MSIPACKAGE package)

Definition at line 932 of file patch.c.

933{
934 LPWSTR patch_list, *patches;
936
937 patch_list = msi_dup_property( package->db, L"PATCH" );
938
939 TRACE("patches to be applied: %s\n", debugstr_w(patch_list));
940
941 patches = msi_split_string( patch_list, ';' );
942 for (i = 0; patches && patches[i] && r == ERROR_SUCCESS; i++)
943 r = msi_apply_patch_package( package, patches[i] );
944
945 msi_free( patches );
946 msi_free( patch_list );
947 return r;
948}
static UINT msi_apply_patch_package(MSIPACKAGE *package, const WCHAR *file)
Definition: patch.c:875
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by MSI_InstallPackage().

◆ msi_apply_registered_patch()

UINT msi_apply_registered_patch ( MSIPACKAGE package,
LPCWSTR  patch_code 
)

Definition at line 990 of file patch.c.

991{
992 UINT r;
993 DWORD len;
995 MSIDATABASE *patch_db;
996 MSIPATCHINFO *patch_info;
997 MSISUMMARYINFO *si;
998
999 TRACE("%p, %s\n", package, debugstr_w(patch_code));
1000
1002 r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context,
1004 if (r != ERROR_SUCCESS)
1005 {
1006 ERR("failed to get patch filename %u\n", r);
1007 return r;
1008 }
1010 if (r != ERROR_SUCCESS)
1011 {
1012 ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
1013 return r;
1014 }
1015 r = msi_get_suminfo( patch_db->storage, 0, &si );
1016 if (r != ERROR_SUCCESS)
1017 {
1018 msiobj_release( &patch_db->hdr );
1019 return r;
1020 }
1021 r = msi_parse_patch_summary( si, &patch_info );
1022 msiobj_release( &si->hdr );
1023 if (r != ERROR_SUCCESS)
1024 {
1025 ERR("failed to parse patch summary %u\n", r);
1026 msiobj_release( &patch_db->hdr );
1027 return r;
1028 }
1029 patch_info->registered = TRUE;
1030 patch_info->localfile = strdupW( patch_file );
1031 if (!patch_info->localfile)
1032 {
1033 msiobj_release( &patch_db->hdr );
1034 msi_free_patchinfo( patch_info );
1035 return ERROR_OUTOFMEMORY;
1036 }
1037 r = msi_apply_patch_db( package, patch_db, patch_info );
1038 msiobj_release( &patch_db->hdr );
1039 if (r != ERROR_SUCCESS)
1040 {
1041 ERR("failed to apply patch %u\n", r);
1042 msi_free_patchinfo( patch_info );
1043 }
1044 return r;
1045}
#define ARRAY_SIZE(A)
Definition: main.h:33
static UINT patch_file(MSIPACKAGE *package, MSIFILEPATCH *patch)
Definition: files.c:712
UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode, LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCWSTR szProperty, LPWSTR lpValue, DWORD *pcchValue)
Definition: msi.c:1659
GLenum GLsizei len
Definition: glext.h:6722
static const WCHAR INSTALLPROPERTY_LOCALPACKAGEW[]
Definition: msi.h:343
LPWSTR ProductCode
Definition: msipriv.h:448
UINT Context
Definition: msipriv.h:459

Referenced by MSI_OpenPackageW().

◆ msi_apply_transforms()

UINT msi_apply_transforms ( MSIPACKAGE package)

Definition at line 950 of file patch.c.

951{
952 LPWSTR xform_list, *xforms;
954
955 xform_list = msi_dup_property( package->db, L"TRANSFORMS" );
956 xforms = msi_split_string( xform_list, ';' );
957
958 for (i = 0; xforms && xforms[i] && r == ERROR_SUCCESS; i++)
959 {
960 if (xforms[i][0] == ':')
961 r = apply_substorage_transform( package, package->db, xforms[i] );
962 else
963 {
965
966 if (!PathIsRelativeW( xforms[i] )) transform = xforms[i];
967 else
968 {
969 WCHAR *p = wcsrchr( package->PackagePath, '\\' );
970 DWORD len = p - package->PackagePath + 1;
971
972 if (!(transform = msi_alloc( (len + lstrlenW( xforms[i] ) + 1) * sizeof(WCHAR)) ))
973 {
974 msi_free( xforms );
975 msi_free( xform_list );
976 return ERROR_OUTOFMEMORY;
977 }
978 memcpy( transform, package->PackagePath, len * sizeof(WCHAR) );
979 memcpy( transform + len, xforms[i], (lstrlenW( xforms[i] ) + 1) * sizeof(WCHAR) );
980 }
981 r = MSI_DatabaseApplyTransformW( package->db, transform, 0 );
982 if (transform != xforms[i]) msi_free( transform );
983 }
984 }
985 msi_free( xforms );
986 msi_free( xform_list );
987 return r;
988}
#define wcsrchr
Definition: compat.h:16
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: path.c:1579
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
UINT MSI_DatabaseApplyTransformW(MSIDATABASE *db, LPCWSTR szTransformFile, int iErrorCond) DECLSPEC_HIDDEN
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
LPWSTR PackagePath
Definition: msipriv.h:447

Referenced by MSI_InstallPackage().

◆ msi_check_patch_applicable()

UINT msi_check_patch_applicable ( MSIPACKAGE package,
MSISUMMARYINFO si 
)

Definition at line 294 of file patch.c.

295{
296 LPWSTR guid_list, *guids, product_code;
298
299 product_code = msi_dup_property( package->db, L"ProductCode" );
300 if (!product_code)
301 {
302 /* FIXME: the property ProductCode should be written into the DB somewhere */
303 ERR("no product code to check\n");
304 return ERROR_SUCCESS;
305 }
307 guids = msi_split_string( guid_list, ';' );
308 for (i = 0; guids[i] && ret != ERROR_SUCCESS; i++)
309 {
310 if (!wcscmp( guids[i], product_code )) ret = ERROR_SUCCESS;
311 }
312 msi_free( guids );
314 msi_free( product_code );
315 return ret;
316}
static const GUID * guid_list[]
Definition: metadata.c:2260

Referenced by MSI_ApplicablePatchW(), and msi_apply_patch_package().

◆ msi_free_patchinfo()

void msi_free_patchinfo ( MSIPATCHINFO patch)

Definition at line 865 of file patch.c.

866{
867 msi_free( patch->patchcode );
868 msi_free( patch->products );
869 msi_free( patch->transforms );
870 msi_free( patch->filename );
871 msi_free( patch->localfile );
872 msi_free( patch );
873}
LPWSTR patchcode
Definition: msipriv.h:201
LPWSTR products
Definition: msipriv.h:202

Referenced by free_package_structures(), msi_apply_patch_package(), and msi_apply_registered_patch().

◆ msi_parse_patch_summary()

static UINT msi_parse_patch_summary ( MSISUMMARYINFO si,
MSIPATCHINFO **  patch 
)
static

Definition at line 318 of file patch.c.

319{
322 WCHAR *p;
323
324 if (!(pi = msi_alloc_zero( sizeof(MSIPATCHINFO) )))
325 {
326 return ERROR_OUTOFMEMORY;
327 }
328 if (!(pi->patchcode = msi_suminfo_dup_string( si, PID_REVNUMBER )))
329 {
330 msi_free( pi );
331 return ERROR_OUTOFMEMORY;
332 }
333 p = pi->patchcode;
334 if (*p != '{')
335 {
336 msi_free( pi->patchcode );
337 msi_free( pi );
339 }
340 if (!(p = wcschr( p + 1, '}' )))
341 {
342 msi_free( pi->patchcode );
343 msi_free( pi );
345 }
346 if (p[1])
347 {
348 FIXME("patch obsoletes %s\n", debugstr_w(p + 1));
349 p[1] = 0;
350 }
351 TRACE("patch code %s\n", debugstr_w(pi->patchcode));
352 if (!(pi->products = msi_suminfo_dup_string( si, PID_TEMPLATE )))
353 {
354 msi_free( pi->patchcode );
355 msi_free( pi );
356 return ERROR_OUTOFMEMORY;
357 }
358 if (!(pi->transforms = msi_suminfo_dup_string( si, PID_LASTAUTHOR )))
359 {
360 msi_free( pi->patchcode );
361 msi_free( pi->products );
362 msi_free( pi );
363 return ERROR_OUTOFMEMORY;
364 }
365 *patch = pi;
366 return r;
367}
#define PID_LASTAUTHOR
Definition: suminfo.c:50
#define PID_REVNUMBER
Definition: suminfo.c:51
static refpint_t pi[]
Definition: server.c:96
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
#define ERROR_PATCH_PACKAGE_INVALID
Definition: winerror.h:994

Referenced by msi_apply_patch_package(), and msi_apply_registered_patch().

◆ parse_transform_desc()

static struct transform_desc * parse_transform_desc ( const WCHAR str)
static

Definition at line 65 of file patch.c.

66{
67 struct transform_desc *ret;
68 const WCHAR *p = str, *q;
69 UINT len;
70
71 if (!(ret = msi_alloc_zero( sizeof(*ret) ))) return NULL;
72
73 q = wcschr( p, '}' );
74 if (*p != '{' || !q) goto error;
75
76 len = q - p + 1;
77 if (!(ret->product_code_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
78 memcpy( ret->product_code_from, p, len * sizeof(WCHAR) );
79 ret->product_code_from[len] = 0;
80
81 p = q + 1;
82 if (!(q = wcschr( p, ';' ))) goto error;
83 len = q - p;
84 if (!(ret->version_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
85 memcpy( ret->version_from, p, len * sizeof(WCHAR) );
86 ret->version_from[len] = 0;
87
88 p = q + 1;
89 q = wcschr( p, '}' );
90 if (*p != '{' || !q) goto error;
91
92 len = q - p + 1;
93 if (!(ret->product_code_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
94 memcpy( ret->product_code_to, p, len * sizeof(WCHAR) );
95 ret->product_code_to[len] = 0;
96
97 p = q + 1;
98 if (!(q = wcschr( p, ';' ))) goto error;
99 len = q - p;
100 if (!(ret->version_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
101 memcpy( ret->version_to, p, len * sizeof(WCHAR) );
102 ret->version_to[len] = 0;
103
104 p = q + 1;
105 q = wcschr( p, '}' );
106 if (*p != '{' || !q) goto error;
107
108 len = q - p + 1;
109 if (!(ret->upgrade_code = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
110 memcpy( ret->upgrade_code, p, len * sizeof(WCHAR) );
111 ret->upgrade_code[len] = 0;
112
113 return ret;
114
115error:
117 return NULL;
118}
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
#define error(str)
Definition: mkdosfs.c:1605
const WCHAR * str

Referenced by check_transform_applicable().

◆ patch_add_media()

static UINT patch_add_media ( MSIPACKAGE package,
IStorage storage,
MSIPATCHINFO patch 
)
static

Definition at line 644 of file patch.c.

645{
646 MSIQUERY *view;
647 MSIRECORD *rec;
648 UINT r, disk_id;
649 struct list media_list;
650 struct patch_media *media, *next;
651
653 if (r != ERROR_SUCCESS) return r;
654
655 r = MSI_ViewExecute( view, 0 );
656 if (r != ERROR_SUCCESS)
657 {
658 msiobj_release( &view->hdr );
659 TRACE("query failed %u\n", r);
660 return r;
661 }
662 list_init( &media_list );
663 while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
664 {
665 disk_id = MSI_RecordGetInteger( rec, 1 );
666 TRACE("disk_id %u\n", disk_id);
668 {
669 msiobj_release( &rec->hdr );
670 continue;
671 }
672 if (!(media = msi_alloc( sizeof( *media ))))
673 {
674 msiobj_release( &rec->hdr );
675 goto done;
676 }
677 media->disk_id = disk_id;
678 media->last_sequence = MSI_RecordGetInteger( rec, 2 );
679 media->prompt = msi_dup_record_field( rec, 3 );
680 media->cabinet = msi_dup_record_field( rec, 4 );
681 media->volume = msi_dup_record_field( rec, 5 );
682 media->source = msi_dup_record_field( rec, 6 );
683
684 list_add_tail( &media_list, &media->entry );
685 msiobj_release( &rec->hdr );
686 }
687 LIST_FOR_EACH_ENTRY( media, &media_list, struct patch_media, entry )
688 {
689 MSIQUERY *delete_view, *insert_view;
690
691 r = MSI_DatabaseOpenViewW( package->db, L"DELETE FROM `Media` WHERE `DiskId`=?", &delete_view );
692 if (r != ERROR_SUCCESS) goto done;
693
694 rec = MSI_CreateRecord( 1 );
695 MSI_RecordSetInteger( rec, 1, media->disk_id );
696
697 r = MSI_ViewExecute( delete_view, rec );
698 msiobj_release( &delete_view->hdr );
699 msiobj_release( &rec->hdr );
700 if (r != ERROR_SUCCESS) goto done;
701
702 r = MSI_DatabaseOpenViewW( package->db, L"INSERT INTO `Media` (`DiskId`,`LastSequence`,`DiskPrompt`,"
703 L"`Cabinet`,`VolumeLabel`,`Source`) VALUES (?,?,?,?,?,?)",
704 &insert_view );
705 if (r != ERROR_SUCCESS) goto done;
706
708 TRACE("disk id %u\n", disk_id);
709 TRACE("last sequence %u\n", media->last_sequence);
710 TRACE("prompt %s\n", debugstr_w(media->prompt));
711 TRACE("cabinet %s\n", debugstr_w(media->cabinet));
712 TRACE("volume %s\n", debugstr_w(media->volume));
713 TRACE("source %s\n", debugstr_w(media->source));
714
715 rec = MSI_CreateRecord( 6 );
716 MSI_RecordSetInteger( rec, 1, disk_id );
717 MSI_RecordSetInteger( rec, 2, media->last_sequence );
718 MSI_RecordSetStringW( rec, 3, media->prompt );
719 MSI_RecordSetStringW( rec, 4, media->cabinet );
720 MSI_RecordSetStringW( rec, 5, media->volume );
721 MSI_RecordSetStringW( rec, 6, media->source );
722
723 r = MSI_ViewExecute( insert_view, rec );
724 msiobj_release( &insert_view->hdr );
725 msiobj_release( &rec->hdr );
726 if (r != ERROR_SUCCESS) goto done;
727
728 r = msi_add_cabinet_stream( package, disk_id, storage, media->cabinet );
729 if (r != ERROR_SUCCESS) ERR("failed to add cabinet stream %u\n", r);
730 else
731 {
732 patch->disk_id = disk_id;
733 package->db->media_transform_disk_id++;
734 }
735 }
736
737done:
738 msiobj_release( &view->hdr );
739 LIST_FOR_EACH_ENTRY_SAFE( media, next, &media_list, struct patch_media, entry )
740 {
741 list_remove( &media->entry );
742 msi_free( media->prompt );
743 msi_free( media->cabinet );
744 msi_free( media->volume );
745 msi_free( media->source );
746 msi_free( media );
747 }
748 return r;
749}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_init(struct list_entry *head)
Definition: list.h:51
Definition: list.h:37
UINT msi_add_cabinet_stream(MSIPACKAGE *package, UINT disk_id, IStorage *storage, const WCHAR *name)
Definition: media.c:935
static const WCHAR patch_media_query[]
Definition: patch.c:630
uint32_t entry
Definition: isohybrid.c:63
__u8 media
Definition: mkdosfs.c:9
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1002
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:280
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
static unsigned __int64 next
Definition: rand_nt.c:6
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
UINT disk_id
Definition: patch.c:636
UINT media_transform_disk_id
Definition: msipriv.h:117
MSIOBJECTHDR hdr
Definition: msipriv.h:129

Referenced by msi_apply_patch_db().

◆ patch_offset_get_filepatches()

static void patch_offset_get_filepatches ( MSIDATABASE db,
UINT  last_sequence,
struct patch_offset_list pos 
)
static

Definition at line 441 of file patch.c.

442{
443 MSIQUERY *view;
444 MSIRECORD *rec;
445 UINT r;
446
447 r = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Patch` WHERE `Sequence` <= ? ORDER BY `Sequence`", &view );
448 if (r != ERROR_SUCCESS)
449 return;
450
451 rec = MSI_CreateRecord( 1 );
452 MSI_RecordSetInteger( rec, 1, last_sequence );
453
454 r = MSI_ViewExecute( view, rec );
455 msiobj_release( &rec->hdr );
456 if (r != ERROR_SUCCESS)
457 return;
458
459 while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
460 {
461 struct patch_offset *po = msi_alloc( sizeof(struct patch_offset) );
462
463 po->name = msi_dup_record_field( rec, 1 );
464 po->sequence = MSI_RecordGetInteger( rec, 2 );
465 pos->min = min( pos->min, po->sequence );
466 pos->max = max( pos->max, po->sequence );
467 list_add_tail( &pos->patches, &po->entry );
468 pos->count++;
469
470 msiobj_release( &rec->hdr );
471 }
472 msiobj_release( &view->hdr );
473}
#define min(a, b)
Definition: monoChain.cc:55
UINT sequence
Definition: patch.c:403
struct list entry
Definition: patch.c:401
WCHAR * name
Definition: patch.c:402
#define max(a, b)
Definition: svc.c:63

Referenced by patch_set_offsets().

◆ patch_offset_get_files()

static void patch_offset_get_files ( MSIDATABASE db,
UINT  last_sequence,
struct patch_offset_list pos 
)
static

Definition at line 475 of file patch.c.

476{
477 MSIQUERY *view;
478 MSIRECORD *rec;
479 UINT r;
480
481 r = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `File` WHERE `Sequence` <= ? ORDER BY `Sequence`", &view );
482 if (r != ERROR_SUCCESS)
483 return;
484
485 rec = MSI_CreateRecord( 1 );
486 MSI_RecordSetInteger( rec, 1, last_sequence );
487
488 r = MSI_ViewExecute( view, rec );
489 msiobj_release( &rec->hdr );
490 if (r != ERROR_SUCCESS)
491 return;
492
493 while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
494 {
495 UINT attributes = MSI_RecordGetInteger( rec, 7 );
496 if (attributes & msidbFileAttributesPatchAdded)
497 {
498 struct patch_offset *po = msi_alloc( sizeof(struct patch_offset) );
499
500 po->name = msi_dup_record_field( rec, 1 );
501 po->sequence = MSI_RecordGetInteger( rec, 8 );
502 pos->min = min( pos->min, po->sequence );
503 pos->max = max( pos->max, po->sequence );
504 list_add_tail( &pos->files, &po->entry );
505 pos->count++;
506 }
507 msiobj_release( &rec->hdr );
508 }
509 msiobj_release( &view->hdr );
510}
@ msidbFileAttributesPatchAdded
Definition: msidefs.h:37

Referenced by patch_set_offsets().

◆ patch_offset_list_create()

static struct patch_offset_list * patch_offset_list_create ( void  )
static

Definition at line 414 of file patch.c.

415{
416 struct patch_offset_list *pos = msi_alloc( sizeof(struct patch_offset_list) );
417 list_init( &pos->files );
418 list_init( &pos->patches );
419 pos->count = pos->max = 0;
420 pos->min = 999999;
421 return pos;
422}

Referenced by patch_set_offsets().

◆ patch_offset_list_free()

static void patch_offset_list_free ( struct patch_offset_list pos)
static

Definition at line 424 of file patch.c.

425{
426 struct patch_offset *po, *po2;
427
428 LIST_FOR_EACH_ENTRY_SAFE( po, po2, &pos->files, struct patch_offset, entry )
429 {
430 msi_free( po->name );
431 msi_free( po );
432 }
433 LIST_FOR_EACH_ENTRY_SAFE( po, po2, &pos->patches, struct patch_offset, entry )
434 {
435 msi_free( po->name );
436 msi_free( po );
437 }
438 msi_free( pos );
439}

Referenced by patch_set_offsets().

◆ patch_offset_modify_db()

static UINT patch_offset_modify_db ( MSIDATABASE db,
struct patch_offset_list pos 
)
static

Definition at line 574 of file patch.c.

575{
576 MSIRECORD *rec;
577 MSIQUERY *view;
578 UINT r, min = pos->min, max = pos->max, r_fetch;
579
581 L"SELECT * FROM `File` WHERE `Sequence` >= ? AND `Sequence` <= ? ORDER BY `Sequence`",
582 &view );
583 if (r != ERROR_SUCCESS)
584 return ERROR_SUCCESS;
585
586 rec = MSI_CreateRecord( 2 );
587 MSI_RecordSetInteger( rec, 1, min );
588 MSI_RecordSetInteger( rec, 2, max );
589
590 r = MSI_ViewExecute( view, rec );
591 msiobj_release( &rec->hdr );
592 if (r != ERROR_SUCCESS)
593 goto done;
594
595 while ((r_fetch = MSI_ViewFetch( view, &rec )) == ERROR_SUCCESS)
596 {
597 r = patch_update_file_sequence( db, pos, view, rec );
598 msiobj_release( &rec->hdr );
599 if (r != ERROR_SUCCESS) goto done;
600 }
601 msiobj_release( &view->hdr );
602
604 L"SELECT *FROM `Patch` WHERE `Sequence` >= ? AND `Sequence` <= ? ORDER BY `Sequence`",
605 &view );
606 if (r != ERROR_SUCCESS)
607 return ERROR_SUCCESS;
608
609 rec = MSI_CreateRecord( 2 );
610 MSI_RecordSetInteger( rec, 1, min );
611 MSI_RecordSetInteger( rec, 2, max );
612
613 r = MSI_ViewExecute( view, rec );
614 msiobj_release( &rec->hdr );
615 if (r != ERROR_SUCCESS)
616 goto done;
617
618 while ((r_fetch = MSI_ViewFetch( view, &rec )) == ERROR_SUCCESS)
619 {
621 msiobj_release( &rec->hdr );
622 if (r != ERROR_SUCCESS) goto done;
623 }
624
625done:
626 msiobj_release( &view->hdr );
627 return r;
628}
static UINT patch_update_file_sequence(MSIDATABASE *db, const struct patch_offset_list *pos, MSIQUERY *view, MSIRECORD *rec)
Definition: patch.c:512
static UINT patch_update_filepatch_sequence(MSIDATABASE *db, const struct patch_offset_list *pos, MSIQUERY *view, MSIRECORD *rec)
Definition: patch.c:533

Referenced by patch_set_offsets().

◆ patch_set_media_source_prop()

static UINT patch_set_media_source_prop ( MSIPACKAGE package)
static

Definition at line 369 of file patch.c.

370{
371 MSIQUERY *view;
372 MSIRECORD *rec;
373 const WCHAR *property;
374 WCHAR *patch;
375 UINT r;
376
377 r = MSI_DatabaseOpenViewW( package->db, L"SELECT `Source` FROM `Media` WHERE `Source` IS NOT NULL", &view );
378 if (r != ERROR_SUCCESS)
379 return r;
380
381 r = MSI_ViewExecute( view, 0 );
382 if (r != ERROR_SUCCESS)
383 goto done;
384
385 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
386 {
387 property = MSI_RecordGetString( rec, 1 );
388 patch = msi_dup_property( package->db, L"PATCH" );
389 msi_set_property( package->db, property, patch, -1 );
390 msi_free( patch );
391 msiobj_release( &rec->hdr );
392 }
393
394done:
395 msiobj_release( &view->hdr );
396 return r;
397}
UINT msi_set_property(MSIDATABASE *, const WCHAR *, const WCHAR *, int) DECLSPEC_HIDDEN
Definition: package.c:2100

Referenced by msi_apply_patch_db().

◆ patch_set_offsets()

static UINT patch_set_offsets ( MSIDATABASE db,
MSIPATCHINFO patch 
)
static

Definition at line 751 of file patch.c.

752{
753 MSIQUERY *view;
754 MSIRECORD *rec;
755 UINT r;
756
758 if (r != ERROR_SUCCESS)
759 return r;
760
761 r = MSI_ViewExecute( view, 0 );
762 if (r != ERROR_SUCCESS)
763 goto done;
764
765 while (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
766 {
767 UINT offset, last_sequence = MSI_RecordGetInteger( rec, 2 );
768 struct patch_offset_list *pos;
769
770 /* FIXME: set/check Source field instead? */
771 if (last_sequence >= MSI_INITIAL_MEDIA_TRANSFORM_OFFSET)
772 {
773 msiobj_release( &rec->hdr );
774 continue;
775 }
777 patch_offset_get_files( db, last_sequence, pos );
778 patch_offset_get_filepatches( db, last_sequence, pos );
779
780 offset = db->media_transform_offset - pos->min;
781 last_sequence = offset + pos->max;
782
783 last_sequence += pos->min;
784 pos->offset_to_apply = offset;
785 if (pos->count)
786 {
788 if (r != ERROR_SUCCESS)
789 ERR("Failed to set offsets, expect breakage (%u)\n", r);
790 }
791 MSI_RecordSetInteger( rec, 2, last_sequence );
793 if (r != ERROR_SUCCESS)
794 ERR("Failed to update Media table entry, expect breakage (%u)\n", r);
795
796 db->media_transform_offset = last_sequence + 1;
797
799 msiobj_release( &rec->hdr );
800 }
801
802done:
803 msiobj_release( &view->hdr );
804 return r;
805}
static void patch_offset_get_filepatches(MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos)
Definition: patch.c:441
static struct patch_offset_list * patch_offset_list_create(void)
Definition: patch.c:414
static void patch_offset_get_files(MSIDATABASE *db, UINT last_sequence, struct patch_offset_list *pos)
Definition: patch.c:475
static UINT patch_offset_modify_db(MSIDATABASE *db, struct patch_offset_list *pos)
Definition: patch.c:574
static void patch_offset_list_free(struct patch_offset_list *pos)
Definition: patch.c:424
GLintptr offset
Definition: glext.h:5920
UINT MSI_ViewModify(MSIQUERY *, MSIMODIFY, MSIRECORD *) DECLSPEC_HIDDEN
Definition: msiquery.c:698
#define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET
Definition: msipriv.h:83
@ MSIMODIFY_UPDATE
Definition: msiquery.h:53
UINT media_transform_offset
Definition: msipriv.h:116

Referenced by msi_apply_patch_db().

◆ patch_update_file_sequence()

static UINT patch_update_file_sequence ( MSIDATABASE db,
const struct patch_offset_list pos,
MSIQUERY view,
MSIRECORD rec 
)
static

Definition at line 512 of file patch.c.

514{
515 struct patch_offset *po;
516 const WCHAR *file = MSI_RecordGetString( rec, 1 );
517 UINT r = ERROR_SUCCESS, seq = MSI_RecordGetInteger( rec, 8 );
518
519 LIST_FOR_EACH_ENTRY( po, &pos->files, struct patch_offset, entry )
520 {
521 if (!wcsicmp( file, po->name ))
522 {
523 MSI_RecordSetInteger( rec, 8, seq + pos->offset_to_apply );
525 if (r != ERROR_SUCCESS)
526 ERR("Failed to update offset for file %s (%u)\n", debugstr_w(file), r);
527 break;
528 }
529 }
530 return r;
531}
#define wcsicmp
Definition: compat.h:15

Referenced by patch_offset_modify_db().

◆ patch_update_filepatch_sequence()

static UINT patch_update_filepatch_sequence ( MSIDATABASE db,
const struct patch_offset_list pos,
MSIQUERY view,
MSIRECORD rec 
)
static

Definition at line 533 of file patch.c.

535{
536 struct patch_offset *po;
537 const WCHAR *file = MSI_RecordGetString( rec, 1 );
538 UINT r = ERROR_SUCCESS, seq = MSI_RecordGetInteger( rec, 2 );
539
540 LIST_FOR_EACH_ENTRY( po, &pos->patches, struct patch_offset, entry )
541 {
542 if (seq == po->sequence && !wcsicmp( file, po->name ))
543 {
544 MSIQUERY *delete_view, *insert_view;
545 MSIRECORD *rec2;
546
547 r = MSI_DatabaseOpenViewW( db, L"DELETE FROM `Patch` WHERE `File_` = ? AND `Sequence` = ?", &delete_view );
548 if (r != ERROR_SUCCESS) return r;
549
550 rec2 = MSI_CreateRecord( 2 );
551 MSI_RecordSetStringW( rec2, 1, po->name );
552 MSI_RecordSetInteger( rec2, 2, po->sequence );
553 r = MSI_ViewExecute( delete_view, rec2 );
554 msiobj_release( &delete_view->hdr );
555 msiobj_release( &rec2->hdr );
556 if (r != ERROR_SUCCESS) return r;
557
558 r = MSI_DatabaseOpenViewW( db, L"INSERT INTO `Patch` (`File_`,`Sequence`,`PatchSize`,`Attributes`,"
559 L"`Header`,`StreamRef_`) VALUES (?,?,?,?,?,?)", &insert_view );
560 if (r != ERROR_SUCCESS) return r;
561
562 MSI_RecordSetInteger( rec, 2, po->sequence + pos->offset_to_apply );
563
564 r = MSI_ViewExecute( insert_view, rec );
565 msiobj_release( &insert_view->hdr );
566 if (r != ERROR_SUCCESS)
567 ERR("Failed to update offset for filepatch %s (%u)\n", debugstr_w(file), r);
568 break;
569 }
570 }
571 return r;
572}

Referenced by patch_offset_modify_db().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( msi  )

Variable Documentation

◆ patch_media_query

const WCHAR patch_media_query[]
static
Initial value:
=
L"SELECT * FROM `Media` WHERE `Source` IS NOT NULL AND `Cabinet` IS NOT NULL ORDER BY `DiskId`"

Definition at line 630 of file patch.c.

Referenced by patch_add_media(), and patch_set_offsets().