xref: /reactos/modules/rostests/winetests/msi/patch.c (revision f4be6dc3)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2010 Hans Leidekker for CodeWeavers
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * A test program for patching MSI products.
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
2131139640SAmine Khaldi #define _WIN32_MSI 300
2231139640SAmine Khaldi #define COBJMACROS
2331139640SAmine Khaldi 
2431139640SAmine Khaldi #include <stdio.h>
2531139640SAmine Khaldi 
2631139640SAmine Khaldi #include <windows.h>
2731139640SAmine Khaldi #include <msiquery.h>
2831139640SAmine Khaldi #include <msidefs.h>
2931139640SAmine Khaldi #include <msi.h>
3031139640SAmine Khaldi #include <wtypes.h>
3131139640SAmine Khaldi 
3231139640SAmine Khaldi #include "wine/test.h"
33*f4be6dc3SMikhail #include "utils.h"
34c2c66affSColin Finck 
35c2c66affSColin Finck static const char *msifile = "winetest-patch.msi";
36c2c66affSColin Finck static const char *mspfile = "winetest-patch.msp";
37f31e4044Swinesync static const WCHAR msifileW[] = L"winetest-patch.msi";
38f31e4044Swinesync static const WCHAR mspfileW[] = L"winetest-patch.msp";
39c2c66affSColin Finck 
40c2c66affSColin Finck /* msi database data */
41c2c66affSColin Finck 
42c2c66affSColin Finck static const char property_dat[] =
43c2c66affSColin Finck     "Property\tValue\n"
44c2c66affSColin Finck     "s72\tl0\n"
45c2c66affSColin Finck     "Property\tProperty\n"
46c2c66affSColin Finck     "Manufacturer\tWineHQ\n"
47c2c66affSColin Finck     "ProductCode\t{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}\n"
48c2c66affSColin Finck     "UpgradeCode\t{A2E3D643-4E2C-477F-A309-F76F552D5F43}\n"
49c2c66affSColin Finck     "ProductLanguage\t1033\n"
50c2c66affSColin Finck     "ProductName\tmsitest\n"
51c2c66affSColin Finck     "ProductVersion\t1.1.1\n"
52c2c66affSColin Finck     "PATCHNEWSUMMARYSUBJECT\tInstaller Database\n"
53c2c66affSColin Finck     "MSIFASTINSTALL\t1\n";
54c2c66affSColin Finck 
55c2c66affSColin Finck static const char media_dat[] =
56c2c66affSColin Finck     "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
57c2c66affSColin Finck     "i2\ti4\tL64\tS255\tS32\tS72\n"
58c2c66affSColin Finck     "Media\tDiskId\n"
59c2c66affSColin Finck     "1\t1\t\t\tDISK1\t\n";
60c2c66affSColin Finck 
61c2c66affSColin Finck static const char file_dat[] =
62c2c66affSColin Finck     "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
63c2c66affSColin Finck     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
64c2c66affSColin Finck     "File\tFile\n"
65aa0312d7Swinesync     "patch.txt\tpatch\tpatch.txt\t1000\t\t\t0\t1\n"
66aa0312d7Swinesync     "disable.txt\tdisable\tdisable.txt\t1000\t\t\t0\t1\n";
67c2c66affSColin Finck 
68c2c66affSColin Finck static const char directory_dat[] =
69c2c66affSColin Finck     "Directory\tDirectory_Parent\tDefaultDir\n"
70c2c66affSColin Finck     "s72\tS72\tl255\n"
71c2c66affSColin Finck     "Directory\tDirectory\n"
72c2c66affSColin Finck     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
73c2c66affSColin Finck     "ProgramFilesFolder\tTARGETDIR\t.\n"
74c2c66affSColin Finck     "TARGETDIR\t\tSourceDir";
75c2c66affSColin Finck 
76c2c66affSColin Finck static const char component_dat[] =
77c2c66affSColin Finck     "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
78c2c66affSColin Finck     "s72\tS38\ts72\ti2\tS255\tS72\n"
79c2c66affSColin Finck     "Component\tComponent\n"
80aa0312d7Swinesync     "patch\t{4B79D87E-6D28-4FD3-92D6-CD9B26AF64F1}\tMSITESTDIR\t0\t\tpatch.txt\n"
81aa0312d7Swinesync     "disable\t{BDDBA0EE-0031-4591-ADC0-33308175AC19}\tMSITESTDIR\t0\t\tdisable.txt\n";
82c2c66affSColin Finck 
83c2c66affSColin Finck static const char feature_dat[] =
84c2c66affSColin Finck     "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
85c2c66affSColin Finck     "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
86c2c66affSColin Finck     "Feature\tFeature\n"
87aa0312d7Swinesync     "patch\t\t\tpatch feature\t1\t1\tMSITESTDIR\t0\n"
88aa0312d7Swinesync     "disable\t\t\tdisabled feature\t1\t1\tMSITESTDIR\t0\n";
89c2c66affSColin Finck 
90c2c66affSColin Finck static const char feature_comp_dat[] =
91c2c66affSColin Finck     "Feature_\tComponent_\n"
92c2c66affSColin Finck     "s38\ts72\n"
93c2c66affSColin Finck     "FeatureComponents\tFeature_\tComponent_\n"
94aa0312d7Swinesync     "patch\tpatch\n"
95aa0312d7Swinesync     "disable\tdisable\n";
96c2c66affSColin Finck 
97c2c66affSColin Finck static const char install_exec_seq_dat[] =
98c2c66affSColin Finck     "Action\tCondition\tSequence\n"
99c2c66affSColin Finck     "s72\tS255\tI2\n"
100c2c66affSColin Finck     "InstallExecuteSequence\tAction\n"
101c2c66affSColin Finck     "LaunchConditions\t\t100\n"
102c2c66affSColin Finck     "CostInitialize\t\t800\n"
103c2c66affSColin Finck     "FileCost\t\t900\n"
104c2c66affSColin Finck     "CostFinalize\t\t1000\n"
105c2c66affSColin Finck     "InstallValidate\t\t1400\n"
106c2c66affSColin Finck     "InstallInitialize\t\t1500\n"
107c2c66affSColin Finck     "ProcessComponents\t\t1600\n"
108c2c66affSColin Finck     "RemoveFiles\t\t1700\n"
109c2c66affSColin Finck     "InstallFiles\t\t2000\n"
110c2c66affSColin Finck     "RegisterUser\t\t3000\n"
111c2c66affSColin Finck     "RegisterProduct\t\t3100\n"
112c2c66affSColin Finck     "PublishFeatures\t\t5100\n"
113c2c66affSColin Finck     "PublishProduct\t\t5200\n"
1143b27d975Swinesync     "UnpublishFeatures\t\t5300\n"
115c2c66affSColin Finck     "InstallFinalize\t\t6000\n";
116c2c66affSColin Finck 
117aa0312d7Swinesync static const char condition_dat[] =
118aa0312d7Swinesync     "Feature_\tLevel\tCondition\n"
119aa0312d7Swinesync     "s38\ti2\tS255\n"
120aa0312d7Swinesync     "Condition\tFeature_\tLevel\n"
121aa0312d7Swinesync     "disable\t0\tDISABLE_FEATURE\n";
122aa0312d7Swinesync 
123c2c66affSColin Finck struct msi_table
124c2c66affSColin Finck {
125c2c66affSColin Finck     const char *filename;
126c2c66affSColin Finck     const char *data;
127c2c66affSColin Finck     int size;
128c2c66affSColin Finck };
129c2c66affSColin Finck 
130c2c66affSColin Finck static const struct msi_table tables[] =
131c2c66affSColin Finck {
132c2c66affSColin Finck     ADD_TABLE( directory ),
133c2c66affSColin Finck     ADD_TABLE( file ),
134c2c66affSColin Finck     ADD_TABLE( component ),
135c2c66affSColin Finck     ADD_TABLE( feature ),
136c2c66affSColin Finck     ADD_TABLE( feature_comp ),
137c2c66affSColin Finck     ADD_TABLE( property ),
138c2c66affSColin Finck     ADD_TABLE( install_exec_seq ),
139aa0312d7Swinesync     ADD_TABLE( media ),
140aa0312d7Swinesync     ADD_TABLE( condition )
141c2c66affSColin Finck };
142c2c66affSColin Finck 
get_program_files_dir(char * buf,char * buf2)143c2c66affSColin Finck static BOOL get_program_files_dir( char *buf, char *buf2 )
144c2c66affSColin Finck {
145c2c66affSColin Finck     HKEY hkey;
146c2c66affSColin Finck     DWORD type, size;
147c2c66affSColin Finck 
148c2c66affSColin Finck     if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey ))
149c2c66affSColin Finck         return FALSE;
150c2c66affSColin Finck 
151c2c66affSColin Finck     size = MAX_PATH;
152c2c66affSColin Finck     if (RegQueryValueExA( hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)buf, &size ) &&
153c2c66affSColin Finck         RegQueryValueExA( hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size ))
154c2c66affSColin Finck     {
155c2c66affSColin Finck         RegCloseKey( hkey );
156c2c66affSColin Finck         return FALSE;
157c2c66affSColin Finck     }
158c2c66affSColin Finck     size = MAX_PATH;
159c2c66affSColin Finck     if (RegQueryValueExA( hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size ))
160c2c66affSColin Finck     {
161c2c66affSColin Finck         RegCloseKey( hkey );
162c2c66affSColin Finck         return FALSE;
163c2c66affSColin Finck     }
164c2c66affSColin Finck     RegCloseKey( hkey );
165c2c66affSColin Finck     return TRUE;
166c2c66affSColin Finck }
167c2c66affSColin Finck 
get_pf_file_size(const char * filename)168c2c66affSColin Finck static DWORD get_pf_file_size( const char *filename )
169c2c66affSColin Finck {
170c2c66affSColin Finck     char path[MAX_PATH];
171c2c66affSColin Finck     HANDLE file;
172c2c66affSColin Finck     DWORD size;
173c2c66affSColin Finck 
174c2c66affSColin Finck     strcpy( path, PROG_FILES_DIR );
175c2c66affSColin Finck     strcat( path, "\\");
176c2c66affSColin Finck     strcat( path, filename );
177c2c66affSColin Finck 
178c2c66affSColin Finck     file = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
179c2c66affSColin Finck     if (file == INVALID_HANDLE_VALUE)
180c2c66affSColin Finck         return INVALID_FILE_SIZE;
181c2c66affSColin Finck 
182c2c66affSColin Finck     size = GetFileSize( file, NULL );
183c2c66affSColin Finck     CloseHandle( file );
184c2c66affSColin Finck     return size;
185c2c66affSColin Finck }
186c2c66affSColin Finck 
write_file(const char * filename,const char * data,DWORD data_size)187c2c66affSColin Finck static void write_file( const char *filename, const char *data, DWORD data_size )
188c2c66affSColin Finck {
189c2c66affSColin Finck     DWORD size;
190c2c66affSColin Finck     HANDLE file = CreateFileA( filename, GENERIC_WRITE, 0, NULL,
191c2c66affSColin Finck                                CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
192c2c66affSColin Finck     WriteFile( file, data, data_size, &size, NULL );
193c2c66affSColin Finck     CloseHandle( file );
194c2c66affSColin Finck }
195c2c66affSColin Finck 
set_suminfo(const WCHAR * filename)196c2c66affSColin Finck static void set_suminfo( const WCHAR *filename )
197c2c66affSColin Finck {
198c2c66affSColin Finck     UINT r;
199c2c66affSColin Finck     MSIHANDLE hsi, hdb;
200c2c66affSColin Finck 
201c2c66affSColin Finck     r = MsiOpenDatabaseW( filename, MSIDBOPEN_DIRECT, &hdb );
202c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
203c2c66affSColin Finck 
204c2c66affSColin Finck     r = MsiGetSummaryInformationA( hdb, NULL, 7, &hsi );
205c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to open summaryinfo %u\n", r );
206c2c66affSColin Finck 
207c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 2, VT_LPSTR, 0, NULL, "Installation Database" );
208c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
209c2c66affSColin Finck 
210c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 3, VT_LPSTR, 0, NULL, "Installation Database" );
211c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
212c2c66affSColin Finck 
213c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 4, VT_LPSTR, 0, NULL, "WineHQ" );
214c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
215c2c66affSColin Finck 
216c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 7, VT_LPSTR, 0, NULL, ";1033" );
217c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
218c2c66affSColin Finck 
219c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 9, VT_LPSTR, 0, NULL, "{E528DDD6-4801-4BEC-BBB6-C5EE0FD097E9}" );
220c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
221c2c66affSColin Finck 
222c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 14, VT_I4, 100, NULL, NULL );
223c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
224c2c66affSColin Finck 
225c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA( hsi, 15, VT_I4, 0, NULL, NULL );
226c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
227c2c66affSColin Finck 
228c2c66affSColin Finck     r = MsiSummaryInfoPersist( hsi );
229c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to persist suminfo %u\n", r );
230c2c66affSColin Finck 
231c2c66affSColin Finck     r = MsiCloseHandle( hsi );
232c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to close suminfo %u\n", r );
233c2c66affSColin Finck 
234c2c66affSColin Finck     r = MsiCloseHandle( hdb );
235c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to close database %u\n", r );
236c2c66affSColin Finck }
237c2c66affSColin Finck 
create_database_suminfo(const char * filename,const struct msi_table * tables,UINT num_tables)238*f4be6dc3SMikhail static void create_database_suminfo( const char *filename, const struct msi_table *tables, UINT num_tables )
239c2c66affSColin Finck {
240c2c66affSColin Finck     MSIHANDLE hdb;
241c2c66affSColin Finck     UINT r, i;
242c2c66affSColin Finck     WCHAR *filenameW;
243c2c66affSColin Finck     int len;
244c2c66affSColin Finck 
245c2c66affSColin Finck     len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
2466aefc5b9Swinesync     if (!(filenameW = malloc( len * sizeof(WCHAR) ))) return;
247c2c66affSColin Finck     MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len );
248c2c66affSColin Finck 
249c2c66affSColin Finck     r = MsiOpenDatabaseW( filenameW, MSIDBOPEN_CREATE, &hdb );
250c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
251c2c66affSColin Finck 
252c2c66affSColin Finck     /* import the tables into the database */
253c2c66affSColin Finck     for (i = 0; i < num_tables; i++)
254c2c66affSColin Finck     {
255c2c66affSColin Finck         const struct msi_table *table = &tables[i];
256c2c66affSColin Finck 
257c2c66affSColin Finck         write_file( table->filename, table->data, (table->size - 1) * sizeof(char) );
258c2c66affSColin Finck 
259c2c66affSColin Finck         r = MsiDatabaseImportA( hdb, CURR_DIR, table->filename );
260c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
261c2c66affSColin Finck 
262c2c66affSColin Finck         DeleteFileA( table->filename );
263c2c66affSColin Finck     }
264c2c66affSColin Finck 
265c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
266c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
267c2c66affSColin Finck 
268c2c66affSColin Finck     MsiCloseHandle( hdb );
269c2c66affSColin Finck     set_suminfo( filenameW );
2706aefc5b9Swinesync     free( filenameW );
271c2c66affSColin Finck }
272c2c66affSColin Finck 
273c2c66affSColin Finck /* data for generating a patch */
274c2c66affSColin Finck 
275c2c66affSColin Finck /* table names - encoded as in an msi database file */
276c2c66affSColin Finck static const WCHAR p_name0[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
277c2c66affSColin Finck static const WCHAR p_name1[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
278c2c66affSColin Finck static const WCHAR p_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
279c2c66affSColin Finck static const WCHAR p_name3[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
280c2c66affSColin Finck static const WCHAR p_name4[] = { 0x3a8c, 0x47cb, 0x45b0, 0x45ec, 0x45a8, 0x4837, 0}; /* CAB_msitest */
281c2c66affSColin Finck static const WCHAR p_name5[] = { 0x4840, 0x4596, 0x3e6c, 0x45e4, 0x42e6, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* MsiPatchSequence */
282c2c66affSColin Finck static const WCHAR p_name6[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
283c2c66affSColin Finck                                  0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
284c2c66affSColin Finck                                  0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
285c2c66affSColin Finck /* substorage names */
286c2c66affSColin Finck static const WCHAR p_name7[] = { 0x0074, 0x0061, 0x0072, 0x0067, 0x0065, 0x0074, 0x0054, 0x006f, 0x0075, 0x0070,
287c2c66affSColin Finck                                  0x0067, 0x0072, 0x0061, 0x0064, 0x0065, 0x0064, 0 }; /* targetToupgraded */
288c2c66affSColin Finck static const WCHAR p_name8[] = { 0x0023, 0x0074, 0x0061, 0x0072, 0x0067, 0x0065, 0x0074, 0x0054, 0x006f, 0x0075,
289c2c66affSColin Finck                                  0x0070, 0x0067, 0x0072, 0x0061, 0x0064, 0x0065, 0x0064, 0 }; /* #targetToupgraded */
290c2c66affSColin Finck 
291c2c66affSColin Finck /* data in each table */
292c2c66affSColin Finck static const WCHAR p_data0[] = { /* _Columns */
293c2c66affSColin Finck     0x0001, 0x0001, 0x0001, 0x0001, 0x8001, 0x8002, 0x8003, 0x8004,
294c2c66affSColin Finck     0x0002, 0x0003, 0x0004, 0x0005, 0xad00, 0xbd26, 0x8d00, 0x9502
295c2c66affSColin Finck };
296c2c66affSColin Finck static const WCHAR p_data1[] = { /* _Tables */
297c2c66affSColin Finck     0x0001
298c2c66affSColin Finck };
299c2c66affSColin Finck static const char p_data2[] = { /* _StringData */
300c2c66affSColin Finck     "MsiPatchSequencePatchFamilyProductCodeSequenceAttributes1.1.19388.37230913B8D18FBB64CACA239C74C11E3FA74"
301c2c66affSColin Finck };
302c2c66affSColin Finck static const WCHAR p_data3[] = { /* _StringPool */
303c2c66affSColin Finck /* len, refs */
304c2c66affSColin Finck      0,  0,     /* string 0 '' */
305c2c66affSColin Finck     16,  5,     /* string 1 'MsiPatchSequence' */
306c2c66affSColin Finck     11,  1,     /* string 2 'PatchFamily' */
307c2c66affSColin Finck     11,  1,     /* string 3 'ProductCode' */
308c2c66affSColin Finck      8,  1,     /* string 4 'Sequence' */
309c2c66affSColin Finck     10,  1,     /* string 5 'Attributes' */
310c2c66affSColin Finck     15,  1,     /* string 6 '1.1.19388.37230' */
311c2c66affSColin Finck     32,  1,     /* string 7 '913B8D18FBB64CACA239C74C11E3FA74' */
312c2c66affSColin Finck };
313c2c66affSColin Finck static const char p_data4[] = { /* CAB_msitest */
3148bb4f059Swinesync     0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00,
315c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
3168bb4f059Swinesync     0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
3178bb4f059Swinesync     0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
318c2c66affSColin Finck     0xea, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
3198bb4f059Swinesync     0x3c, 0xd4, 0xb8, 0x20, 0x00, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e,
3208bb4f059Swinesync     0x74, 0x78, 0x74, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xea, 0x03, 0x00,
3218bb4f059Swinesync     0x00, 0x00, 0x00, 0xcb, 0x50, 0x17, 0x7e, 0x20, 0x00, 0x66, 0x69,
3228bb4f059Swinesync     0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0xb0, 0xb2, 0xb2, 0x25,
3238bb4f059Swinesync     0x2d, 0x00, 0xd2, 0x07, 0x43, 0x4b, 0xcb, 0x2d, 0xce, 0x2c, 0x49,
3248bb4f059Swinesync     0x2d, 0x2e, 0x89, 0x29, 0x48, 0x2c, 0x49, 0xce, 0x48, 0x4d, 0xd1,
3258bb4f059Swinesync     0x2b, 0xa9, 0x28, 0x51, 0x18, 0x05, 0xa3, 0x60, 0x14, 0x0c, 0x37,
3268bb4f059Swinesync     0x90, 0x8b, 0x9c, 0xd3, 0x41, 0xf9, 0x9c, 0x61, 0x14, 0x8c, 0x82,
3278bb4f059Swinesync     0x51, 0x30, 0xdc, 0x00, 0x00
328c2c66affSColin Finck };
329c2c66affSColin Finck static const WCHAR p_data5[] = { /* MsiPatchSequence */
330c2c66affSColin Finck     0x0007, 0x0000, 0x0006, 0x8000
331c2c66affSColin Finck };
332c2c66affSColin Finck static const char p_data6[] = { /* SummaryInformation */
333c2c66affSColin Finck     0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
334c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335c2c66affSColin Finck     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
336c2c66affSColin Finck     0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
337c2c66affSColin Finck     0x30, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
338c2c66affSColin Finck     0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00,
339c2c66affSColin Finck     0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x90,
340c2c66affSColin Finck     0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
341c2c66affSColin Finck     0x0f, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
342c2c66affSColin Finck     0x00, 0x27, 0x00, 0x00, 0x00, 0x7b, 0x30, 0x46, 0x39, 0x36, 0x43,
343c2c66affSColin Finck     0x44, 0x43, 0x30, 0x2d, 0x34, 0x43, 0x44, 0x46, 0x2d, 0x34, 0x33,
344c2c66affSColin Finck     0x30, 0x34, 0x2d, 0x42, 0x32, 0x38, 0x33, 0x2d, 0x37, 0x42, 0x39,
345c2c66affSColin Finck     0x32, 0x36, 0x34, 0x38, 0x38, 0x39, 0x45, 0x46, 0x37, 0x7d, 0x00,
346c2c66affSColin Finck     0x00, 0x1e, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x7b, 0x39,
347c2c66affSColin Finck     0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42, 0x42,
348c2c66affSColin Finck     0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33, 0x39,
349c2c66affSColin Finck     0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46, 0x41,
350c2c66affSColin Finck     0x37, 0x34, 0x7d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x25, 0x00,
351c2c66affSColin Finck     0x00, 0x00, 0x3a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x6f,
352c2c66affSColin Finck     0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x3b, 0x3a, 0x23,
353c2c66affSColin Finck     0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x6f, 0x75, 0x70, 0x67,
354c2c66affSColin Finck     0x72, 0x61, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
355c2c66affSColin Finck     0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x50, 0x61, 0x74, 0x63, 0x68,
356c2c66affSColin Finck     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x00,
357c2c66affSColin Finck     0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
358c2c66affSColin Finck };
359c2c66affSColin Finck 
360c2c66affSColin Finck struct table_data {
361c2c66affSColin Finck     LPCWSTR name;
362c2c66affSColin Finck     const void *data;
363c2c66affSColin Finck     DWORD size;
364c2c66affSColin Finck };
365c2c66affSColin Finck 
366c2c66affSColin Finck static const struct table_data table_patch_data[] = {
367c2c66affSColin Finck     { p_name0, p_data0, sizeof p_data0 },
368c2c66affSColin Finck     { p_name1, p_data1, sizeof p_data1 },
369c2c66affSColin Finck     { p_name2, p_data2, sizeof p_data2 - 1 },
370c2c66affSColin Finck     { p_name3, p_data3, sizeof p_data3 },
371c2c66affSColin Finck     { p_name4, p_data4, sizeof p_data4 },
372c2c66affSColin Finck     { p_name5, p_data5, sizeof p_data5 },
373c2c66affSColin Finck     { p_name6, p_data6, sizeof p_data6 }
374c2c66affSColin Finck };
375c2c66affSColin Finck 
376c2c66affSColin Finck static const WCHAR t1_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
377c2c66affSColin Finck static const WCHAR t1_name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
378c2c66affSColin Finck static const WCHAR t1_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
379c2c66affSColin Finck static const WCHAR t1_name3[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
380c2c66affSColin Finck                                   0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
381c2c66affSColin Finck                                   0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
382c2c66affSColin Finck 
383c2c66affSColin Finck static const WCHAR t1_data0[] = { /* File */
384c2c66affSColin Finck     0x0008, 0x0001, 0x03ea, 0x8000
385c2c66affSColin Finck };
386c2c66affSColin Finck static const char t1_data1[] = { /* _StringData */
387c2c66affSColin Finck     "patch.txt"
388c2c66affSColin Finck };
389c2c66affSColin Finck static const WCHAR t1_data2[] = { /* _StringPool */
390c2c66affSColin Finck /* len, refs */
391c2c66affSColin Finck      0,  0,     /* string 0 '' */
392c2c66affSColin Finck      9,  1,     /* string 1 'patch.txt' */
393c2c66affSColin Finck };
394c2c66affSColin Finck static const char t1_data3[] = { /* SummaryInformation */
395c2c66affSColin Finck     0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
396c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397c2c66affSColin Finck     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
398c2c66affSColin Finck     0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
399c2c66affSColin Finck     0x30, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00,
400c2c66affSColin Finck     0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00,
401c2c66affSColin Finck     0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa8,
402c2c66affSColin Finck     0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00,
403c2c66affSColin Finck     0x06, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00,
404c2c66affSColin Finck     0x00, 0xd0, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xdc, 0x00,
405c2c66affSColin Finck     0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x08,
406c2c66affSColin Finck     0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
407c2c66affSColin Finck     0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x8f, 0x01, 0x00,
408c2c66affSColin Finck     0x00, 0x10, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x1e, 0x00,
409c2c66affSColin Finck     0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x73, 0x74, 0x61,
410c2c66affSColin Finck     0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x61, 0x74,
411c2c66affSColin Finck     0x61, 0x62, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
412c2c66affSColin Finck     0x00, 0x16, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
413c2c66affSColin Finck     0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x61, 0x74, 0x61,
414c2c66affSColin Finck     0x62, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
415c2c66affSColin Finck     0x07, 0x00, 0x00, 0x00, 0x57, 0x69, 0x6e, 0x65, 0x48, 0x51, 0x00,
416c2c66affSColin Finck     0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
417c2c66affSColin Finck     0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
418c2c66affSColin Finck     0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
419c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420c2c66affSColin Finck     0x00, 0x1e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x38,
421c2c66affSColin Finck     0x36, 0x3b, 0x31, 0x30, 0x33, 0x33, 0x00, 0x00, 0x00, 0x1e, 0x00,
422c2c66affSColin Finck     0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x31, 0x30, 0x33, 0x33,
423c2c66affSColin Finck     0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
424c2c66affSColin Finck     0x7b, 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46,
425c2c66affSColin Finck     0x42, 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32,
426c2c66affSColin Finck     0x33, 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33,
427c2c66affSColin Finck     0x46, 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b,
428c2c66affSColin Finck     0x7b, 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46,
429c2c66affSColin Finck     0x42, 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32,
430c2c66affSColin Finck     0x33, 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33,
431c2c66affSColin Finck     0x46, 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b,
432c2c66affSColin Finck     0x7b, 0x41, 0x32, 0x45, 0x33, 0x44, 0x36, 0x34, 0x33, 0x2d, 0x34,
433c2c66affSColin Finck     0x45, 0x32, 0x43, 0x2d, 0x34, 0x37, 0x37, 0x46, 0x2d, 0x41, 0x33,
434c2c66affSColin Finck     0x30, 0x39, 0x2d, 0x46, 0x37, 0x36, 0x46, 0x35, 0x35, 0x32, 0x44,
435c2c66affSColin Finck     0x35, 0x46, 0x34, 0x33, 0x7d, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
436c2c66affSColin Finck     0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x22,
437c2c66affSColin Finck     0x09
438c2c66affSColin Finck };
439c2c66affSColin Finck 
440c2c66affSColin Finck static const struct table_data table_transform1_data[] = {
441c2c66affSColin Finck     { t1_name0, t1_data0, sizeof t1_data0 },
442c2c66affSColin Finck     { t1_name1, t1_data1, sizeof t1_data1 - 1 },
443c2c66affSColin Finck     { t1_name2, t1_data2, sizeof t1_data2 },
444c2c66affSColin Finck     { t1_name3, t1_data3, sizeof t1_data3 }
445c2c66affSColin Finck };
446c2c66affSColin Finck 
447c2c66affSColin Finck static const WCHAR t2_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
448c2c66affSColin Finck static const WCHAR t2_name1[] = { 0x4840, 0x4216, 0x4327, 0x4824, 0 }; /* Media */
449c2c66affSColin Finck static const WCHAR t2_name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
450c2c66affSColin Finck static const WCHAR t2_name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
451c2c66affSColin Finck static const WCHAR t2_name4[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
452c2c66affSColin Finck static const WCHAR t2_name5[] = { 0x4840, 0x4119, 0x41b7, 0x3e6b, 0x41a4, 0x412e, 0x422a, 0 }; /* PatchPackage */
453c2c66affSColin Finck static const WCHAR t2_name6[] = { 0x4840, 0x4452, 0x45f6, 0x43e4, 0x3baf, 0x423b, 0x4626,
454c2c66affSColin Finck                                   0x4237, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* InstallExecuteSequence */
455c2c66affSColin Finck static const WCHAR t2_name7[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
456c2c66affSColin Finck static const WCHAR t2_name8[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
457c2c66affSColin Finck static const WCHAR t2_name9[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
458c2c66affSColin Finck                                   0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
459c2c66affSColin Finck                                   0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
4608bb4f059Swinesync static const WCHAR t2_name10[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x3b28, 0x4432, 0x44b3,
4618bb4f059Swinesync                                    0x4231, 0x45f1, 0x4836, 0 }; /* FeatureComponents */
4628bb4f059Swinesync static const WCHAR t2_name11[] = { 0x4840, 0x448c, 0x44f0, 0x4472, 0x4468, 0x4837, 0 }; /* Component */
4638bb4f059Swinesync static const WCHAR t2_name12[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x4828, 0 }; /* Feature */
464c2c66affSColin Finck 
465c2c66affSColin Finck static const WCHAR t2_data0[] = { /* File */
4668bb4f059Swinesync     0x00c0, 0x0001, 0x9000, 0x83e8, 0x0801, 0x0002, 0x0003, 0x0002,
4678bb4f059Swinesync     0x03e8, 0x8000, 0x0000, 0x0000, 0x9000, 0x83e9
468c2c66affSColin Finck };
469c2c66affSColin Finck static const WCHAR t2_data1[] = { /* Media */
4708bb4f059Swinesync     0x0601, 0x8002, 0x03e9, 0x8000, 0x0000, 0x000d, 0x0000, 0x000e
471c2c66affSColin Finck };
472c2c66affSColin Finck static const WCHAR t2_data2[] = { /* _Columns */
4738bb4f059Swinesync     0x0401, 0x000f, 0x0000, 0x0010, 0xad48, 0x0401, 0x000f, 0x0000, /* 0x0401 = add row (1), 4 shorts */
4748bb4f059Swinesync     0x0011, 0xa502, 0x0401, 0x000f, 0x0000, 0x0012, 0x8104, 0x0401,
4758bb4f059Swinesync     0x000f, 0x0000, 0x0013, 0x8502, 0x0401, 0x000f, 0x0000, 0x0014,
4768bb4f059Swinesync     0x9900, 0x0401, 0x000f, 0x0000, 0x0015, 0x9d48, 0x0401, 0x0016,
4778bb4f059Swinesync     0x0000, 0x0017, 0xad26, 0x0401, 0x0016, 0x0000, 0x0018, 0x8502,
4788bb4f059Swinesync     0x0401, 0x001a, 0x0000, 0x001b, 0xad26, 0x0401, 0x001a, 0x0000,
4798bb4f059Swinesync     0x0014, 0x8900
480c2c66affSColin Finck };
481c2c66affSColin Finck static const WCHAR t2_data3[] = { /* _Tables */
4828bb4f059Swinesync     0x0101, 0x000f, 0x0101, 0x0016, 0x0101, 0x001a
483c2c66affSColin Finck };
484c2c66affSColin Finck static const WCHAR t2_data4[] = { /* Property */
4858bb4f059Swinesync     0x0002, 0x0008, 0x0009, 0x0201, 0x000a, 0x000b
486c2c66affSColin Finck };
487c2c66affSColin Finck static const WCHAR t2_data5[] = { /* PatchPackage */
4888bb4f059Swinesync     0x0201, 0x0019, 0x8002
489c2c66affSColin Finck };
490c2c66affSColin Finck static const WCHAR t2_data6[] = { /* InstallExecuteSequence */
4918bb4f059Swinesync     0x0301, 0x000c, 0x0000, 0x87d1
492c2c66affSColin Finck };
493c2c66affSColin Finck static const char t2_data7[] = { /* _StringData */
4948bb4f059Swinesync     "patch.txtfile.txtfile{327d9640-674f-4b9f-8b8a-547a0f6f8518}MSITESTDIRnewnew featurePATCHNEWSUMMARYSUBJECT"
4958bb4f059Swinesync     "Installation DatabasePATCHNEWPACKAGECODE{42A14A82-12F8-4E6D-970E-1B4EE7BE28B0}PatchFiles#CAB_msitestprop"
4968bb4f059Swinesync     "PatchFile_SequencePatchSizeAttributesHeaderStreamRef_PatchPackagePatchIdMedia_"
497c2c66affSColin Finck     "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}MsiPatchHeadersStreamRef"
498c2c66affSColin Finck };
499c2c66affSColin Finck static const WCHAR t2_data8[] = { /* _StringPool */
500c2c66affSColin Finck /* len, refs */
501c2c66affSColin Finck      0,  0,     /* string 0 '' */
502c2c66affSColin Finck      9,  1,     /* string 1 'patch.txt' */
5038bb4f059Swinesync      8,  3,     /* string 2 'file.txt' */
5048bb4f059Swinesync      4,  3,     /* string 3 'file' */
5058bb4f059Swinesync     38,  1,     /* string 4 '{327d9640-674f-4b9f-8b8a-547a0f6f8518}' */
5068bb4f059Swinesync     10,  2,     /* string 5 'MSITESTDIR' */
5078bb4f059Swinesync      3,  2,     /* string 6 'new' */
5088bb4f059Swinesync     11,  1,     /* string 7 'new feature' */
5098bb4f059Swinesync     22,  1,     /* string 8 'PATCHNEWSUMMARYSUBJECT' */
5108bb4f059Swinesync     21,  1,     /* string 9 'Installation Database' */
5118bb4f059Swinesync     19,  1,     /* string 10 'PATCHNEWPACKAGECODE' */
5128bb4f059Swinesync     38,  1,     /* string 11 '{42A14A82-12F8-4E6D-970E-1B4EE7BE28B0}' */
5138bb4f059Swinesync     10,  1,     /* string 12 'PatchFiles' */
5148bb4f059Swinesync     12,  1,     /* string 13 '#CAB_msitest' */
5158bb4f059Swinesync      4,  1,     /* string 14 'prop' */
5168bb4f059Swinesync      5,  7,     /* string 15 'Patch' */
5178bb4f059Swinesync      5,  1,     /* string 16 'File_' */
5188bb4f059Swinesync      8,  1,     /* string 17 'Sequence' */
5198bb4f059Swinesync      9,  1,     /* string 18 'PatchSize' */
5208bb4f059Swinesync     10,  1,     /* string 19 'Attributes' */
5218bb4f059Swinesync      6,  2,     /* string 20 'Header' */
5228bb4f059Swinesync     10,  1,     /* string 21 'StreamRef_' */
5238bb4f059Swinesync     12,  3,     /* string 22 'PatchPackage' */
5248bb4f059Swinesync      7,  1,     /* string 23 'PatchId' */
5258bb4f059Swinesync      6,  1,     /* string 24 'Media_' */
5268bb4f059Swinesync     38,  1,     /* string 25 '{0F96CDC0-4CDF-4304-B283-7B9264889EF7}' */
5278bb4f059Swinesync     15,  3,     /* string 26 'MsiPatchHeaders' */
5288bb4f059Swinesync      9,  1      /* string 27 'StreamRef' */
529c2c66affSColin Finck };
530c2c66affSColin Finck static const char t2_data9[] = { /* SummaryInformation */
531c2c66affSColin Finck     0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
532c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533c2c66affSColin Finck     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
534c2c66affSColin Finck     0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
535c2c66affSColin Finck     0x30, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00,
536c2c66affSColin Finck     0x00, 0x02, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00,
537c2c66affSColin Finck     0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78,
538c2c66affSColin Finck     0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
539c2c66affSColin Finck     0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00,
540c2c66affSColin Finck     0x00, 0x9c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xa8, 0x00,
541c2c66affSColin Finck     0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x09,
542c2c66affSColin Finck     0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
543c2c66affSColin Finck     0x4c, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00,
544c2c66affSColin Finck     0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
545c2c66affSColin Finck     0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
546c2c66affSColin Finck     0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
547c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
548c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00,
549c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01,
550c2c66affSColin Finck     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
551c2c66affSColin Finck     0x06, 0x00, 0x00, 0x00, 0x3b, 0x31, 0x30, 0x33, 0x33, 0x00, 0x00,
552c2c66affSColin Finck     0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
553c2c66affSColin Finck     0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7b,
554c2c66affSColin Finck     0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42,
555c2c66affSColin Finck     0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33,
556c2c66affSColin Finck     0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46,
557c2c66affSColin Finck     0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b, 0x7b,
558c2c66affSColin Finck     0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42,
559c2c66affSColin Finck     0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33,
560c2c66affSColin Finck     0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46,
561c2c66affSColin Finck     0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b, 0x7b,
562c2c66affSColin Finck     0x41, 0x32, 0x45, 0x33, 0x44, 0x36, 0x34, 0x33, 0x2d, 0x34, 0x45,
563c2c66affSColin Finck     0x32, 0x43, 0x2d, 0x34, 0x37, 0x37, 0x46, 0x2d, 0x41, 0x33, 0x30,
564c2c66affSColin Finck     0x39, 0x2d, 0x46, 0x37, 0x36, 0x46, 0x35, 0x35, 0x32, 0x44, 0x35,
565c2c66affSColin Finck     0x46, 0x34, 0x33, 0x7d, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2d,
566c2c66affSColin Finck     0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x27, 0x09
567c2c66affSColin Finck };
5688bb4f059Swinesync static const WCHAR t2_data10[] = { /* FeatureComponents */
5698bb4f059Swinesync     0x0201, 0x0006, 0x0003
5708bb4f059Swinesync };
5718bb4f059Swinesync static const WCHAR t2_data11[] = { /* Component */
5728bb4f059Swinesync     0x0601, 0x0003, 0x0004, 0x0005, 0x8000, 0x0000, 0x0002
5738bb4f059Swinesync };
5748bb4f059Swinesync static const WCHAR t2_data12[] = { /* Feature */
5758bb4f059Swinesync     0x0801, 0x0006, 0x0000, 0x0000, 0x0007, 0x8001, 0x8001, 0x0005,
5768bb4f059Swinesync     0x8000
5778bb4f059Swinesync };
578c2c66affSColin Finck 
579c2c66affSColin Finck static const struct table_data table_transform2_data[] = {
580c2c66affSColin Finck     { t2_name0, t2_data0, sizeof t2_data0 },
581c2c66affSColin Finck     { t2_name1, t2_data1, sizeof t2_data1 },
582c2c66affSColin Finck     { t2_name2, t2_data2, sizeof t2_data2 },
583c2c66affSColin Finck     { t2_name3, t2_data3, sizeof t2_data3 },
584c2c66affSColin Finck     { t2_name4, t2_data4, sizeof t2_data4 },
585c2c66affSColin Finck     { t2_name5, t2_data5, sizeof t2_data5 },
586c2c66affSColin Finck     { t2_name6, t2_data6, sizeof t2_data6 },
587c2c66affSColin Finck     { t2_name7, t2_data7, sizeof t2_data7 - 1 },
588c2c66affSColin Finck     { t2_name8, t2_data8, sizeof t2_data8 },
5898bb4f059Swinesync     { t2_name9, t2_data9, sizeof t2_data9 },
5908bb4f059Swinesync     { t2_name10, t2_data10, sizeof t2_data10 },
5918bb4f059Swinesync     { t2_name11, t2_data11, sizeof t2_data11 },
5928bb4f059Swinesync     { t2_name12, t2_data12, sizeof t2_data12 },
593c2c66affSColin Finck };
594c2c66affSColin Finck 
write_tables(IStorage * stg,const struct table_data * tables,UINT num_tables)595c2c66affSColin Finck static void write_tables( IStorage *stg, const struct table_data *tables, UINT num_tables )
596c2c66affSColin Finck {
597c2c66affSColin Finck     IStream *stm;
598c2c66affSColin Finck     DWORD i, count;
599c2c66affSColin Finck     HRESULT r;
600c2c66affSColin Finck 
601c2c66affSColin Finck     for (i = 0; i < num_tables; i++)
602c2c66affSColin Finck     {
603c2c66affSColin Finck         r = IStorage_CreateStream( stg, tables[i].name, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
604c2c66affSColin Finck         if (FAILED( r ))
605c2c66affSColin Finck         {
6061b4acd3cSwinesync             ok( 0, "failed to create stream %#lx\n", r );
607c2c66affSColin Finck             continue;
608c2c66affSColin Finck         }
609c2c66affSColin Finck 
610c2c66affSColin Finck         r = IStream_Write( stm, tables[i].data, tables[i].size, &count );
611c2c66affSColin Finck         if (FAILED( r ) || count != tables[i].size)
612c2c66affSColin Finck             ok( 0, "failed to write stream\n" );
613c2c66affSColin Finck         IStream_Release( stm );
614c2c66affSColin Finck     }
615c2c66affSColin Finck }
616c2c66affSColin Finck 
create_patch(const char * filename)617c2c66affSColin Finck static void create_patch( const char *filename )
618c2c66affSColin Finck {
619c2c66affSColin Finck     IStorage *stg = NULL, *stg1 = NULL, *stg2 = NULL;
620c2c66affSColin Finck     WCHAR *filenameW;
621c2c66affSColin Finck     HRESULT r;
622c2c66affSColin Finck     int len;
623c2c66affSColin Finck     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
624c2c66affSColin Finck 
625c2c66affSColin Finck     const CLSID CLSID_MsiPatch = {0xc1086, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
626c2c66affSColin Finck     const CLSID CLSID_MsiTransform = {0xc1082, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
627c2c66affSColin Finck 
628c2c66affSColin Finck     len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
6296aefc5b9Swinesync     filenameW = malloc( len * sizeof(WCHAR) );
630c2c66affSColin Finck     MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len );
631c2c66affSColin Finck 
632c2c66affSColin Finck     r = StgCreateDocfile( filenameW, mode, 0, &stg );
6336aefc5b9Swinesync     free( filenameW );
6341b4acd3cSwinesync     ok( r == S_OK, "failed to create storage %#lx\n", r );
635c2c66affSColin Finck     if (!stg)
636c2c66affSColin Finck         return;
637c2c66affSColin Finck 
638c2c66affSColin Finck     r = IStorage_SetClass( stg, &CLSID_MsiPatch );
6391b4acd3cSwinesync     ok( r == S_OK, "failed to set storage type %#lx\n", r );
640c2c66affSColin Finck 
64142961bd8Swinesync     write_tables( stg, table_patch_data, ARRAY_SIZE( table_patch_data ));
642c2c66affSColin Finck 
643c2c66affSColin Finck     r = IStorage_CreateStorage( stg, p_name7, mode, 0, 0, &stg1 );
6441b4acd3cSwinesync     ok( r == S_OK, "failed to create substorage %#lx\n", r );
645c2c66affSColin Finck 
646c2c66affSColin Finck     r = IStorage_SetClass( stg1, &CLSID_MsiTransform );
6471b4acd3cSwinesync     ok( r == S_OK, "failed to set storage type %#lx\n", r );
648c2c66affSColin Finck 
64942961bd8Swinesync     write_tables( stg1, table_transform1_data, ARRAY_SIZE( table_transform1_data ));
650c2c66affSColin Finck     IStorage_Release( stg1 );
651c2c66affSColin Finck 
652c2c66affSColin Finck     r = IStorage_CreateStorage( stg, p_name8, mode, 0, 0, &stg2 );
6531b4acd3cSwinesync     ok( r == S_OK, "failed to create substorage %#lx\n", r );
654c2c66affSColin Finck 
655c2c66affSColin Finck     r = IStorage_SetClass( stg2, &CLSID_MsiTransform );
6561b4acd3cSwinesync     ok( r == S_OK, "failed to set storage type %#lx\n", r );
657c2c66affSColin Finck 
65842961bd8Swinesync     write_tables( stg2, table_transform2_data, ARRAY_SIZE( table_transform2_data ));
659c2c66affSColin Finck     IStorage_Release( stg2 );
660c2c66affSColin Finck     IStorage_Release( stg );
661c2c66affSColin Finck }
662c2c66affSColin Finck 
test_simple_patch(void)663c2c66affSColin Finck static void test_simple_patch( void )
664c2c66affSColin Finck {
665c2c66affSColin Finck     UINT r;
666c2c66affSColin Finck     DWORD size;
667c2c66affSColin Finck     char path[MAX_PATH], install_source[MAX_PATH], buffer[32];
668c2c66affSColin Finck     const char *query;
669c2c66affSColin Finck     WCHAR pathW[MAX_PATH];
670c2c66affSColin Finck     MSIHANDLE hpackage, hdb, hview, hrec;
671c2c66affSColin Finck 
672*f4be6dc3SMikhail     if (!is_process_elevated())
673c2c66affSColin Finck     {
674c2c66affSColin Finck         skip("process is limited\n");
675c2c66affSColin Finck         return;
676c2c66affSColin Finck     }
677c2c66affSColin Finck 
678c2c66affSColin Finck     CreateDirectoryA( "msitest", NULL );
679c2c66affSColin Finck     create_file( "msitest\\patch.txt", 1000 );
680c2c66affSColin Finck 
681*f4be6dc3SMikhail     create_database_suminfo( msifile, tables, ARRAY_SIZE(tables) );
682c2c66affSColin Finck     create_patch( mspfile );
683c2c66affSColin Finck 
684c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
685c2c66affSColin Finck 
686aa0312d7Swinesync     r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
687c2c66affSColin Finck     if (r != ERROR_SUCCESS)
688c2c66affSColin Finck     {
689c2c66affSColin Finck         skip("Product installation failed with error code %u\n", r);
690c2c66affSColin Finck         goto cleanup;
691c2c66affSColin Finck     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     size = get_pf_file_size( "msitest\\patch.txt" );
6941b4acd3cSwinesync     ok( size == 1000, "expected 1000, got %lu\n", size );
695c2c66affSColin Finck 
696c2c66affSColin Finck     size = sizeof(install_source);
697c2c66affSColin Finck     r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
698c2c66affSColin Finck                             "InstallSource", install_source, &size );
699c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
700c2c66affSColin Finck 
701c2c66affSColin Finck     strcpy( path, CURR_DIR );
702c2c66affSColin Finck     strcat( path, "\\" );
703c2c66affSColin Finck     strcat( path, msifile );
704c2c66affSColin Finck 
705c2c66affSColin Finck     r = MsiOpenPackageA( path, &hpackage );
706c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
707c2c66affSColin Finck 
708c2c66affSColin Finck     hdb = MsiGetActiveDatabase( hpackage );
709c2c66affSColin Finck     ok( hdb, "failed to get database handle\n" );
710c2c66affSColin Finck 
711c2c66affSColin Finck     query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'";
712c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
713c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
714c2c66affSColin Finck 
715c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
716c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
717c2c66affSColin Finck 
718c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
719c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
720c2c66affSColin Finck 
721c2c66affSColin Finck     MsiCloseHandle( hrec );
722c2c66affSColin Finck     MsiViewClose( hview );
723c2c66affSColin Finck     MsiCloseHandle( hview );
724c2c66affSColin Finck 
725c2c66affSColin Finck     query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' "
726c2c66affSColin Finck             "AND `Value` = 'Installer Database'";
727c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
728c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
729c2c66affSColin Finck 
730c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
731c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
732c2c66affSColin Finck 
733c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
734c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
735c2c66affSColin Finck 
736c2c66affSColin Finck     MsiCloseHandle( hrec );
737c2c66affSColin Finck     MsiViewClose( hview );
738c2c66affSColin Finck     MsiCloseHandle( hview );
739c2c66affSColin Finck 
740c2c66affSColin Finck     buffer[0] = 0;
741c2c66affSColin Finck     size = sizeof(buffer);
742c2c66affSColin Finck     r = MsiGetPropertyA( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size );
743c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
744c2c66affSColin Finck     ok( !strcmp( buffer, "Installer Database" ), "expected \'Installer Database\', got \'%s\'\n", buffer );
745c2c66affSColin Finck 
746c2c66affSColin Finck     MsiCloseHandle( hdb );
747c2c66affSColin Finck     MsiCloseHandle( hpackage );
748c2c66affSColin Finck 
749c2c66affSColin Finck     r = MsiApplyPatchA( mspfile, NULL, INSTALLTYPE_DEFAULT, NULL );
750*f4be6dc3SMikhail     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
751c2c66affSColin Finck 
752c2c66affSColin Finck     size = get_pf_file_size( "msitest\\patch.txt" );
7531b4acd3cSwinesync     ok( size == 1002, "expected 1002, got %lu\n", size );
7548bb4f059Swinesync     size = get_pf_file_size( "msitest\\file.txt" );
7551b4acd3cSwinesync     ok( size == 1000, "expected 1000, got %lu\n", size );
756c2c66affSColin Finck 
757c2c66affSColin Finck     /* show that MsiOpenPackage applies registered patches */
758c2c66affSColin Finck     r = MsiOpenPackageA( path, &hpackage );
759c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
760c2c66affSColin Finck 
761c2c66affSColin Finck     hdb = MsiGetActiveDatabase( hpackage );
762c2c66affSColin Finck     ok( hdb, "failed to get database handle\n" );
763c2c66affSColin Finck 
764c2c66affSColin Finck     query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'";
765c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
766c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
767c2c66affSColin Finck 
768c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
769c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
770c2c66affSColin Finck 
771c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
772c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
773c2c66affSColin Finck 
774c2c66affSColin Finck     MsiCloseHandle( hrec );
775c2c66affSColin Finck     MsiViewClose( hview );
776c2c66affSColin Finck     MsiCloseHandle( hview );
777c2c66affSColin Finck 
778c2c66affSColin Finck     query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' "
779c2c66affSColin Finck             "AND `Value` = 'Installation Database'";
780c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
781c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
782c2c66affSColin Finck 
783c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
784c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
785c2c66affSColin Finck 
786c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
787c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
788c2c66affSColin Finck 
789c2c66affSColin Finck     MsiCloseHandle( hrec );
790c2c66affSColin Finck     MsiViewClose( hview );
791c2c66affSColin Finck     MsiCloseHandle( hview );
792c2c66affSColin Finck 
793c2c66affSColin Finck     buffer[0] = 0;
794c2c66affSColin Finck     size = sizeof(buffer);
795c2c66affSColin Finck     r = MsiGetPropertyA( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size );
796c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
797c2c66affSColin Finck     ok( !strcmp( buffer, "Installation Database" ), "expected \'Installation Database\', got \'%s\'\n", buffer );
798c2c66affSColin Finck 
799c2c66affSColin Finck     MsiCloseHandle( hdb );
800c2c66affSColin Finck     MsiCloseHandle( hpackage );
801c2c66affSColin Finck 
802c2c66affSColin Finck     /* show that patches are not committed to the local package database */
803c2c66affSColin Finck     size = sizeof(path);
804c2c66affSColin Finck     r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
805c2c66affSColin Finck                             "LocalPackage", path, &size );
806c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
807c2c66affSColin Finck 
808c2c66affSColin Finck     MultiByteToWideChar( CP_ACP, 0, path, -1, pathW, MAX_PATH );
809c2c66affSColin Finck     r = MsiOpenDatabaseW( pathW, MSIDBOPEN_READONLY, &hdb );
810c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
811c2c66affSColin Finck 
812c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
813c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
814c2c66affSColin Finck 
815c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
816c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
817c2c66affSColin Finck 
818c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
819c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
820c2c66affSColin Finck 
821c2c66affSColin Finck     MsiCloseHandle( hrec );
822c2c66affSColin Finck     MsiViewClose( hview );
823c2c66affSColin Finck     MsiCloseHandle( hview );
824c2c66affSColin Finck     MsiCloseHandle( hdb );
825c2c66affSColin Finck 
826c2c66affSColin Finck     size = sizeof(path);
827c2c66affSColin Finck     r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
828c2c66affSColin Finck                             "InstallSource", path, &size );
829c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
830c2c66affSColin Finck     ok( !strcasecmp( path, install_source ), "wrong path %s\n", path );
831c2c66affSColin Finck 
832c2c66affSColin Finck     r = MsiInstallProductA( msifile, "REMOVE=ALL" );
833c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
834c2c66affSColin Finck 
835c2c66affSColin Finck     ok( !delete_pf( "msitest\\patch.txt", TRUE ), "file not removed\n" );
8368bb4f059Swinesync     ok( !delete_pf( "msitest\\file.txt", TRUE ), "file not removed\n" );
837c2c66affSColin Finck     ok( !delete_pf( "msitest", FALSE ), "directory not removed\n" );
838c2c66affSColin Finck 
839c2c66affSColin Finck cleanup:
840c2c66affSColin Finck     DeleteFileA( msifile );
841c2c66affSColin Finck     DeleteFileA( mspfile );
842c2c66affSColin Finck     DeleteFileA( "msitest\\patch.txt" );
843c2c66affSColin Finck     RemoveDirectoryA( "msitest" );
844c2c66affSColin Finck }
845c2c66affSColin Finck 
test_MsiOpenDatabase(void)846c2c66affSColin Finck static void test_MsiOpenDatabase( void )
847c2c66affSColin Finck {
848c2c66affSColin Finck     UINT r;
849c2c66affSColin Finck     MSIHANDLE hdb;
850c2c66affSColin Finck 
851c2c66affSColin Finck     r = MsiOpenDatabaseW( mspfileW, MSIDBOPEN_CREATE, &hdb );
852c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database %u\n", r);
853c2c66affSColin Finck 
854c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
855c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to commit database %u\n", r);
856c2c66affSColin Finck     MsiCloseHandle( hdb );
857c2c66affSColin Finck 
858c2c66affSColin Finck     r = MsiOpenDatabaseW( mspfileW, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &hdb );
859c2c66affSColin Finck     ok(r == ERROR_OPEN_FAILED, "expected ERROR_OPEN_FAILED, got %u\n", r);
860c2c66affSColin Finck     DeleteFileA( mspfile );
861c2c66affSColin Finck 
862c2c66affSColin Finck     r = MsiOpenDatabaseW( mspfileW, MSIDBOPEN_CREATE + MSIDBOPEN_PATCHFILE, &hdb );
863c2c66affSColin Finck     ok(r == ERROR_SUCCESS , "failed to open database %u\n", r);
864c2c66affSColin Finck 
865c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
866c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to commit database %u\n", r);
867c2c66affSColin Finck     MsiCloseHandle( hdb );
868c2c66affSColin Finck 
869c2c66affSColin Finck     r = MsiOpenDatabaseW( mspfileW, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &hdb );
870c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database %u\n", r);
871c2c66affSColin Finck     MsiCloseHandle( hdb );
872c2c66affSColin Finck     DeleteFileA( mspfile );
873c2c66affSColin Finck 
874*f4be6dc3SMikhail     create_database_suminfo( msifile, tables, ARRAY_SIZE(tables) );
875c2c66affSColin Finck     create_patch( mspfile );
876c2c66affSColin Finck 
877c2c66affSColin Finck     r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &hdb );
878c2c66affSColin Finck     ok(r == ERROR_OPEN_FAILED, "failed to open database %u\n", r );
879c2c66affSColin Finck 
880c2c66affSColin Finck     r = MsiOpenDatabaseW( mspfileW, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &hdb );
881c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database %u\n", r );
882c2c66affSColin Finck     MsiCloseHandle( hdb );
883c2c66affSColin Finck 
884c2c66affSColin Finck     DeleteFileA( msifile );
885c2c66affSColin Finck     DeleteFileA( mspfile );
886c2c66affSColin Finck }
887c2c66affSColin Finck 
find_entry(MSIHANDLE hdb,const char * table,const char * entry)888c2c66affSColin Finck static UINT find_entry( MSIHANDLE hdb, const char *table, const char *entry )
889c2c66affSColin Finck {
890c2c66affSColin Finck     static const char fmt[] = "SELECT * FROM `%s` WHERE `Name` = '%s'";
891c2c66affSColin Finck     char query[0x100];
892c2c66affSColin Finck     UINT r;
893c2c66affSColin Finck     MSIHANDLE hview, hrec;
894c2c66affSColin Finck 
895c2c66affSColin Finck     sprintf( query, fmt, table, entry );
896c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
897c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
898c2c66affSColin Finck 
899c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
900c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
901c2c66affSColin Finck 
902c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
903c2c66affSColin Finck     MsiViewClose( hview );
904c2c66affSColin Finck     MsiCloseHandle( hview );
905c2c66affSColin Finck     MsiCloseHandle( hrec );
906c2c66affSColin Finck     return r;
907c2c66affSColin Finck }
908c2c66affSColin Finck 
find_entryW(MSIHANDLE hdb,const WCHAR * table,const WCHAR * entry)909c2c66affSColin Finck static UINT find_entryW( MSIHANDLE hdb, const WCHAR *table, const WCHAR *entry )
910c2c66affSColin Finck {
911c2c66affSColin Finck     WCHAR query[0x100];
912c2c66affSColin Finck     MSIHANDLE hview, hrec;
913c2c66affSColin Finck     UINT r;
914c2c66affSColin Finck 
915f31e4044Swinesync     wsprintfW( query, L"SELECT * FROM `%s` WHERE `Name` = '%s'", table, entry );
916c2c66affSColin Finck     r = MsiDatabaseOpenViewW( hdb, query, &hview );
917c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
918c2c66affSColin Finck 
919c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
920c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
921c2c66affSColin Finck 
922c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
923c2c66affSColin Finck     MsiViewClose( hview );
924c2c66affSColin Finck     MsiCloseHandle( hview );
925c2c66affSColin Finck     MsiCloseHandle( hrec );
926c2c66affSColin Finck     return r;
927c2c66affSColin Finck }
928c2c66affSColin Finck 
get_integer(MSIHANDLE hdb,UINT field,const char * query)929c2c66affSColin Finck static INT get_integer( MSIHANDLE hdb, UINT field, const char *query)
930c2c66affSColin Finck {
931c2c66affSColin Finck     UINT r;
932c2c66affSColin Finck     INT ret = -1;
933c2c66affSColin Finck     MSIHANDLE hview, hrec;
934c2c66affSColin Finck 
935c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
936c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
937c2c66affSColin Finck 
938c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
939c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
940c2c66affSColin Finck 
941c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
942c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
943c2c66affSColin Finck     if (r == ERROR_SUCCESS)
944c2c66affSColin Finck     {
945c2c66affSColin Finck         UINT r_tmp;
946c2c66affSColin Finck         ret = MsiRecordGetInteger( hrec, field );
947c2c66affSColin Finck         MsiCloseHandle( hrec );
948c2c66affSColin Finck 
949c2c66affSColin Finck         r_tmp = MsiViewFetch( hview, &hrec );
950c2c66affSColin Finck         ok( r_tmp == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r);
951c2c66affSColin Finck     }
952c2c66affSColin Finck 
953c2c66affSColin Finck     MsiViewClose( hview );
954c2c66affSColin Finck     MsiCloseHandle( hview );
955c2c66affSColin Finck     return ret;
956c2c66affSColin Finck }
957c2c66affSColin Finck 
get_string(MSIHANDLE hdb,UINT field,const char * query)958c2c66affSColin Finck static char *get_string( MSIHANDLE hdb, UINT field, const char *query)
959c2c66affSColin Finck {
960c2c66affSColin Finck     UINT r;
961c2c66affSColin Finck     static char ret[MAX_PATH];
962c2c66affSColin Finck     MSIHANDLE hview, hrec;
963c2c66affSColin Finck 
964c2c66affSColin Finck     ret[0] = '\0';
965c2c66affSColin Finck 
966c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
967c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
968c2c66affSColin Finck 
969c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
970c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
971c2c66affSColin Finck 
972c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
973c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
974c2c66affSColin Finck     if (r == ERROR_SUCCESS)
975c2c66affSColin Finck     {
9761b4acd3cSwinesync         DWORD size = MAX_PATH;
977c2c66affSColin Finck         r = MsiRecordGetStringA( hrec, field, ret, &size );
978c2c66affSColin Finck         ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
979c2c66affSColin Finck         MsiCloseHandle( hrec );
980c2c66affSColin Finck 
981c2c66affSColin Finck         r = MsiViewFetch( hview, &hrec );
982c2c66affSColin Finck         ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r);
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     MsiViewClose( hview );
986c2c66affSColin Finck     MsiCloseHandle( hview );
987c2c66affSColin Finck     return ret;
988c2c66affSColin Finck }
989c2c66affSColin Finck 
test_system_tables(void)990c2c66affSColin Finck static void test_system_tables( void )
991c2c66affSColin Finck {
992c2c66affSColin Finck     static const char patchsource[] = "MSPSRC0F96CDC04CDF4304B2837B9264889EF7";
993c2c66affSColin Finck     UINT r;
994c2c66affSColin Finck     char *cr;
995c2c66affSColin Finck     const char *query;
996c2c66affSColin Finck     MSIHANDLE hproduct, hdb, hview, hrec;
997c2c66affSColin Finck 
998*f4be6dc3SMikhail     if (!is_process_elevated())
999c2c66affSColin Finck     {
1000c2c66affSColin Finck         skip("process is limited\n");
1001c2c66affSColin Finck         return;
1002c2c66affSColin Finck     }
1003c2c66affSColin Finck 
1004c2c66affSColin Finck     CreateDirectoryA( "msitest", NULL );
1005c2c66affSColin Finck     create_file( "msitest\\patch.txt", 1000 );
1006c2c66affSColin Finck 
1007*f4be6dc3SMikhail     create_database_suminfo( msifile, tables, ARRAY_SIZE(tables) );
1008c2c66affSColin Finck     create_patch( mspfile );
1009c2c66affSColin Finck 
1010c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
1011c2c66affSColin Finck 
1012aa0312d7Swinesync     r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
1013c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1014c2c66affSColin Finck     {
1015c2c66affSColin Finck         skip("Product installation failed with error code %d\n", r);
1016c2c66affSColin Finck         goto cleanup;
1017c2c66affSColin Finck     }
1018c2c66affSColin Finck 
1019c2c66affSColin Finck     r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct );
1020c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1021c2c66affSColin Finck 
1022c2c66affSColin Finck     hdb = MsiGetActiveDatabase( hproduct );
1023c2c66affSColin Finck     ok( hdb, "failed to get database handle\n" );
1024c2c66affSColin Finck 
1025c2c66affSColin Finck     r = find_entry( hdb, "_Streams", "\5SummaryInformation" );
1026c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1027c2c66affSColin Finck 
1028c2c66affSColin Finck     query = "SELECT * FROM `_Storages`";
1029c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
1030c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
1033c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1034c2c66affSColin Finck 
1035c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
1036c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1037c2c66affSColin Finck 
1038c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Directory" );
1039c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1040c2c66affSColin Finck 
1041c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "File" );
1042c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Component" );
1045c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1046c2c66affSColin Finck 
1047c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Feature" );
1048c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1049c2c66affSColin Finck 
1050c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "FeatureComponents" );
1051c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Property" );
1054c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "InstallExecuteSequence" );
1057c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1058c2c66affSColin Finck 
1059c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Media" );
1060c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1061c2c66affSColin Finck 
1062c2c66affSColin Finck     r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `VolumeLabel`=\'DISK1\'");
1063c2c66affSColin Finck     ok( r == 1, "Got %u\n", r );
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "_Property" );
1066c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1067c2c66affSColin Finck 
1068c2c66affSColin Finck     MsiCloseHandle( hrec );
1069c2c66affSColin Finck     MsiViewClose( hview );
1070c2c66affSColin Finck     MsiCloseHandle( hview );
1071c2c66affSColin Finck     MsiCloseHandle( hdb );
1072c2c66affSColin Finck     MsiCloseHandle( hproduct );
1073c2c66affSColin Finck 
1074c2c66affSColin Finck     r = MsiApplyPatchA( mspfile, NULL, INSTALLTYPE_DEFAULT, NULL );
1075*f4be6dc3SMikhail     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1076c2c66affSColin Finck 
1077c2c66affSColin Finck     r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct );
1078c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1079c2c66affSColin Finck 
1080c2c66affSColin Finck     hdb = MsiGetActiveDatabase( hproduct );
1081c2c66affSColin Finck     ok( hdb, "failed to get database handle\n" );
1082c2c66affSColin Finck 
1083c2c66affSColin Finck     r = find_entry( hdb, "_Streams", "\5SummaryInformation" );
1084c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1085c2c66affSColin Finck 
1086f31e4044Swinesync     r = find_entryW( hdb, L"_Streams", L"\x3a8c\x47cb\x45b0\x45ec\x45a8\x4837" );
1087c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "failed to find entry %u\n", r );
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     query = "SELECT * FROM `_Storages`";
1090c2c66affSColin Finck     r = MsiDatabaseOpenViewA( hdb, query, &hview );
1091c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1092c2c66affSColin Finck 
1093c2c66affSColin Finck     r = MsiViewExecute( hview, 0 );
1094c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1095c2c66affSColin Finck 
1096c2c66affSColin Finck     r = MsiViewFetch( hview, &hrec );
1097c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1098c2c66affSColin Finck 
1099c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Directory" );
1100c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1101c2c66affSColin Finck 
1102c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "File" );
1103c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1104c2c66affSColin Finck 
1105c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Component" );
1106c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1107c2c66affSColin Finck 
1108c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Feature" );
1109c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1110c2c66affSColin Finck 
1111c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "FeatureComponents" );
1112c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1113c2c66affSColin Finck 
1114c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Property" );
1115c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1116c2c66affSColin Finck 
1117c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "InstallExecuteSequence" );
1118c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1119c2c66affSColin Finck 
1120c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Media" );
1121c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1122c2c66affSColin Finck 
1123c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "_Property" );
1124c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1125c2c66affSColin Finck 
1126c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "MsiPatchHeaders" );
1127c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1128c2c66affSColin Finck 
1129c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "Patch" );
1130c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1131c2c66affSColin Finck 
1132c2c66affSColin Finck     r = find_entry( hdb, "_Tables", "PatchPackage" );
1133c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1134c2c66affSColin Finck 
1135c2c66affSColin Finck     cr = get_string( hdb, 6, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1136c2c66affSColin Finck     todo_wine ok( !strcmp(cr, patchsource), "Expected \"%s\", got \"%s\"\n", patchsource, cr );
1137c2c66affSColin Finck 
1138c2c66affSColin Finck     r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1139c2c66affSColin Finck     todo_wine ok( r == 100, "Got %u\n", r );
1140c2c66affSColin Finck 
1141c2c66affSColin Finck     r = get_integer( hdb, 2, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
11428bb4f059Swinesync     todo_wine ok( r == 10001, "Got %u\n", r );
1143c2c66affSColin Finck 
1144c2c66affSColin Finck     r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `VolumeLabel`=\'DISK1\'");
1145c2c66affSColin Finck     ok( r == 1, "Got %u\n", r );
1146c2c66affSColin Finck 
1147c2c66affSColin Finck     cr = get_string( hdb, 4, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1148c2c66affSColin Finck     ok( !strcmp(cr, "#CAB_msitest"), "Expected \"#CAB_msitest\", got \"%s\"\n", cr );
1149c2c66affSColin Finck 
1150c2c66affSColin Finck     r = get_integer( hdb, 8, "SELECT * FROM `File` WHERE `File` = 'patch.txt'");
1151c2c66affSColin Finck     ok( r == 10000, "Got %u\n", r );
1152c2c66affSColin Finck 
1153c2c66affSColin Finck     MsiCloseHandle( hrec );
1154c2c66affSColin Finck     MsiViewClose( hview );
1155c2c66affSColin Finck     MsiCloseHandle( hview );
1156c2c66affSColin Finck     MsiCloseHandle( hdb );
1157c2c66affSColin Finck     MsiCloseHandle( hproduct );
1158c2c66affSColin Finck 
1159c2c66affSColin Finck     r = MsiInstallProductA( msifile, "REMOVE=ALL" );
1160c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1161c2c66affSColin Finck 
1162c2c66affSColin Finck cleanup:
1163c2c66affSColin Finck     DeleteFileA( msifile );
1164c2c66affSColin Finck     DeleteFileA( mspfile );
1165c2c66affSColin Finck     DeleteFileA( "msitest\\patch.txt" );
1166c2c66affSColin Finck     RemoveDirectoryA( "msitest" );
1167c2c66affSColin Finck }
1168c2c66affSColin Finck 
test_patch_registration(void)1169c2c66affSColin Finck static void test_patch_registration( void )
1170c2c66affSColin Finck {
11711b4acd3cSwinesync     UINT r;
11721b4acd3cSwinesync     DWORD size;
1173c2c66affSColin Finck     char buffer[MAX_PATH], patch_code[39];
1174c2c66affSColin Finck 
1175*f4be6dc3SMikhail     if (!is_process_elevated())
1176c2c66affSColin Finck     {
1177c2c66affSColin Finck         skip("process is limited\n");
1178c2c66affSColin Finck         return;
1179c2c66affSColin Finck     }
1180c2c66affSColin Finck 
1181c2c66affSColin Finck     CreateDirectoryA( "msitest", NULL );
1182c2c66affSColin Finck     create_file( "msitest\\patch.txt", 1000 );
1183c2c66affSColin Finck 
1184*f4be6dc3SMikhail     create_database_suminfo( msifile, tables, ARRAY_SIZE(tables) );
1185c2c66affSColin Finck     create_patch( mspfile );
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
1188c2c66affSColin Finck 
1189aa0312d7Swinesync     r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
1190c2c66affSColin Finck     if (r != ERROR_SUCCESS)
1191c2c66affSColin Finck     {
1192c2c66affSColin Finck         skip("Product installation failed with error code %d\n", r);
1193c2c66affSColin Finck         goto cleanup;
1194c2c66affSColin Finck     }
1195c2c66affSColin Finck 
1196c2c66affSColin Finck     r = MsiApplyPatchA( mspfile, NULL, INSTALLTYPE_DEFAULT, NULL );
1197*f4be6dc3SMikhail     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1198c2c66affSColin Finck 
1199c2c66affSColin Finck     buffer[0] = 0;
1200c2c66affSColin Finck     size = sizeof(buffer);
1201*f4be6dc3SMikhail     r = MsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1202c2c66affSColin Finck                             "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1203c2c66affSColin Finck                              NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1204c2c66affSColin Finck                              INSTALLPROPERTY_LOCALPACKAGEA, buffer, &size );
1205c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1206c2c66affSColin Finck     ok( buffer[0], "buffer empty\n" );
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     buffer[0] = 0;
1209c2c66affSColin Finck     size = sizeof(buffer);
1210*f4be6dc3SMikhail     r = MsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1211c2c66affSColin Finck                             "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1212c2c66affSColin Finck                             NULL, MSIINSTALLCONTEXT_MACHINE,
1213c2c66affSColin Finck                             INSTALLPROPERTY_LOCALPACKAGEA, buffer, &size );
1214c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r );
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     buffer[0] = 0;
1217c2c66affSColin Finck     size = sizeof(buffer);
1218*f4be6dc3SMikhail     r = MsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1219c2c66affSColin Finck                             "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1220c2c66affSColin Finck                              NULL, MSIINSTALLCONTEXT_USERMANAGED,
1221c2c66affSColin Finck                              INSTALLPROPERTY_LOCALPACKAGEA, buffer, &size );
1222c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1223c2c66affSColin Finck     ok( !buffer[0], "got %s\n", buffer );
1224c2c66affSColin Finck 
1225*f4be6dc3SMikhail     r = MsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1226c2c66affSColin Finck                           NULL, MSIINSTALLCONTEXT_USERUNMANAGED, MSIPATCHSTATE_APPLIED,
1227c2c66affSColin Finck                           0, patch_code, NULL, NULL, NULL, NULL );
1228c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1229c2c66affSColin Finck     ok( !strcmp( patch_code, "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}" ), "wrong patch code\n" );
1230c2c66affSColin Finck 
1231*f4be6dc3SMikhail     r = MsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1232c2c66affSColin Finck                           NULL, MSIINSTALLCONTEXT_MACHINE, MSIPATCHSTATE_APPLIED,
1233c2c66affSColin Finck                           0, patch_code, NULL, NULL, NULL, NULL );
1234c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1235c2c66affSColin Finck 
1236*f4be6dc3SMikhail     r = MsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1237c2c66affSColin Finck                           NULL, MSIINSTALLCONTEXT_USERMANAGED, MSIPATCHSTATE_APPLIED,
1238c2c66affSColin Finck                           0, patch_code, NULL, NULL, NULL, NULL );
1239c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1240c2c66affSColin Finck 
1241c2c66affSColin Finck     r = MsiInstallProductA( msifile, "REMOVE=ALL" );
1242c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1243c2c66affSColin Finck 
1244c2c66affSColin Finck     buffer[0] = 0;
1245c2c66affSColin Finck     size = sizeof(buffer);
1246*f4be6dc3SMikhail     r = MsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1247c2c66affSColin Finck                             "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1248c2c66affSColin Finck                              NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1249c2c66affSColin Finck                              INSTALLPROPERTY_LOCALPACKAGEA, buffer, &size );
1250c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r );
1251c2c66affSColin Finck 
1252c2c66affSColin Finck cleanup:
1253c2c66affSColin Finck     DeleteFileA( msifile );
1254c2c66affSColin Finck     DeleteFileA( mspfile );
1255c2c66affSColin Finck     DeleteFileA( "msitest\\patch.txt" );
1256c2c66affSColin Finck     RemoveDirectoryA( "msitest" );
1257c2c66affSColin Finck }
1258c2c66affSColin Finck 
START_TEST(patch)1259c2c66affSColin Finck START_TEST(patch)
1260c2c66affSColin Finck {
1261c2c66affSColin Finck     DWORD len;
1262c2c66affSColin Finck     char temp_path[MAX_PATH], prev_path[MAX_PATH];
1263c2c66affSColin Finck 
1264*f4be6dc3SMikhail     if (!is_process_elevated()) restart_as_admin_elevated();
1265c2c66affSColin Finck 
1266c2c66affSColin Finck     GetCurrentDirectoryA( MAX_PATH, prev_path );
1267c2c66affSColin Finck     GetTempPathA( MAX_PATH, temp_path );
1268c2c66affSColin Finck     SetCurrentDirectoryA( temp_path );
1269c2c66affSColin Finck 
1270c2c66affSColin Finck     strcpy( CURR_DIR, temp_path );
1271c2c66affSColin Finck     len = strlen( CURR_DIR );
1272c2c66affSColin Finck 
1273c2c66affSColin Finck     if (len && (CURR_DIR[len - 1] == '\\'))
1274c2c66affSColin Finck         CURR_DIR[len - 1] = 0;
1275c2c66affSColin Finck 
1276c2c66affSColin Finck     get_program_files_dir( PROG_FILES_DIR, COMMON_FILES_DIR );
1277c2c66affSColin Finck 
1278c2c66affSColin Finck     test_simple_patch();
1279c2c66affSColin Finck     test_MsiOpenDatabase();
1280c2c66affSColin Finck     test_system_tables();
1281c2c66affSColin Finck     test_patch_registration();
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     SetCurrentDirectoryA( prev_path );
1284c2c66affSColin Finck }
1285