ReactOS 0.4.15-dev-7958-gcd0bb1a
patch.c
Go to the documentation of this file.
1/*
2 * Copyright 2010 Hans Leidekker for CodeWeavers
3 *
4 * A test program for patching MSI products.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#define _WIN32_MSI 300
22#define COBJMACROS
23
24#include <stdio.h>
25
26#include <windows.h>
27#include <msiquery.h>
28#include <msidefs.h>
29#include <msi.h>
30#include <wtypes.h>
31
32#include "wine/test.h"
33
34static UINT (WINAPI *pMsiApplyPatchA)( LPCSTR, LPCSTR, INSTALLTYPE, LPCSTR );
35static UINT (WINAPI *pMsiGetPatchInfoExA)( LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT,
37static UINT (WINAPI *pMsiEnumPatchesExA)( LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR,
39
40static const char *msifile = "winetest-patch.msi";
41static const char *mspfile = "winetest-patch.msp";
42static const WCHAR msifileW[] = L"winetest-patch.msi";
43static const WCHAR mspfileW[] = L"winetest-patch.msp";
44
45static char CURR_DIR[MAX_PATH];
48
49/* msi database data */
50
51static const char property_dat[] =
52 "Property\tValue\n"
53 "s72\tl0\n"
54 "Property\tProperty\n"
55 "Manufacturer\tWineHQ\n"
56 "ProductCode\t{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}\n"
57 "UpgradeCode\t{A2E3D643-4E2C-477F-A309-F76F552D5F43}\n"
58 "ProductLanguage\t1033\n"
59 "ProductName\tmsitest\n"
60 "ProductVersion\t1.1.1\n"
61 "PATCHNEWSUMMARYSUBJECT\tInstaller Database\n"
62 "MSIFASTINSTALL\t1\n";
63
64static const char media_dat[] =
65 "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
66 "i2\ti4\tL64\tS255\tS32\tS72\n"
67 "Media\tDiskId\n"
68 "1\t1\t\t\tDISK1\t\n";
69
70static const char file_dat[] =
71 "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
72 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
73 "File\tFile\n"
74 "patch.txt\tpatch\tpatch.txt\t1000\t\t\t0\t1\n"
75 "disable.txt\tdisable\tdisable.txt\t1000\t\t\t0\t1\n";
76
77static const char directory_dat[] =
78 "Directory\tDirectory_Parent\tDefaultDir\n"
79 "s72\tS72\tl255\n"
80 "Directory\tDirectory\n"
81 "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
82 "ProgramFilesFolder\tTARGETDIR\t.\n"
83 "TARGETDIR\t\tSourceDir";
84
85static const char component_dat[] =
86 "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
87 "s72\tS38\ts72\ti2\tS255\tS72\n"
88 "Component\tComponent\n"
89 "patch\t{4B79D87E-6D28-4FD3-92D6-CD9B26AF64F1}\tMSITESTDIR\t0\t\tpatch.txt\n"
90 "disable\t{BDDBA0EE-0031-4591-ADC0-33308175AC19}\tMSITESTDIR\t0\t\tdisable.txt\n";
91
92static const char feature_dat[] =
93 "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
94 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
95 "Feature\tFeature\n"
96 "patch\t\t\tpatch feature\t1\t1\tMSITESTDIR\t0\n"
97 "disable\t\t\tdisabled feature\t1\t1\tMSITESTDIR\t0\n";
98
99static const char feature_comp_dat[] =
100 "Feature_\tComponent_\n"
101 "s38\ts72\n"
102 "FeatureComponents\tFeature_\tComponent_\n"
103 "patch\tpatch\n"
104 "disable\tdisable\n";
105
106static const char install_exec_seq_dat[] =
107 "Action\tCondition\tSequence\n"
108 "s72\tS255\tI2\n"
109 "InstallExecuteSequence\tAction\n"
110 "LaunchConditions\t\t100\n"
111 "CostInitialize\t\t800\n"
112 "FileCost\t\t900\n"
113 "CostFinalize\t\t1000\n"
114 "InstallValidate\t\t1400\n"
115 "InstallInitialize\t\t1500\n"
116 "ProcessComponents\t\t1600\n"
117 "RemoveFiles\t\t1700\n"
118 "InstallFiles\t\t2000\n"
119 "RegisterUser\t\t3000\n"
120 "RegisterProduct\t\t3100\n"
121 "PublishFeatures\t\t5100\n"
122 "PublishProduct\t\t5200\n"
123 "UnpublishFeatures\t\t5300\n"
124 "InstallFinalize\t\t6000\n";
125
126static const char condition_dat[] =
127 "Feature_\tLevel\tCondition\n"
128 "s38\ti2\tS255\n"
129 "Condition\tFeature_\tLevel\n"
130 "disable\t0\tDISABLE_FEATURE\n";
131
133{
134 const char *filename;
135 const char *data;
136 int size;
137};
138
139#define ADD_TABLE( x ) { #x".idt", x##_dat, sizeof(x##_dat) }
140
141static const struct msi_table tables[] =
142{
144 ADD_TABLE( file ),
145 ADD_TABLE( component ),
147 ADD_TABLE( feature_comp ),
149 ADD_TABLE( install_exec_seq ),
150 ADD_TABLE( media ),
152};
153
154static void init_function_pointers( void )
155{
156 HMODULE hmsi = GetModuleHandleA( "msi.dll" );
157
158#define GET_PROC( mod, func ) \
159 p ## func = (void *)GetProcAddress( mod, #func ); \
160 if (!p ## func) \
161 trace( "GetProcAddress(%s) failed\n", #func );
162
163 GET_PROC( hmsi, MsiApplyPatchA );
166
167#undef GET_PROC
168}
169
171{
173
175 {
176 BOOL ret;
178 DWORD size;
179
182 return (ret && type == TokenElevationTypeLimited);
183 }
184 return FALSE;
185}
186
187static BOOL get_program_files_dir( char *buf, char *buf2 )
188{
189 HKEY hkey;
190 DWORD type, size;
191
192 if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey ))
193 return FALSE;
194
195 size = MAX_PATH;
196 if (RegQueryValueExA( hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)buf, &size ) &&
197 RegQueryValueExA( hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size ))
198 {
199 RegCloseKey( hkey );
200 return FALSE;
201 }
202 size = MAX_PATH;
203 if (RegQueryValueExA( hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size ))
204 {
205 RegCloseKey( hkey );
206 return FALSE;
207 }
208 RegCloseKey( hkey );
209 return TRUE;
210}
211
212static void create_file_data( const char *filename, const char *data, DWORD size )
213{
214 HANDLE file;
215 DWORD written;
216
219 return;
220
221 WriteFile( file, data, strlen( data ), &written, NULL );
222 if (size)
223 {
226 }
227 CloseHandle( file );
228}
229
230#define create_file( name, size ) create_file_data( name, name, size )
231
232static BOOL delete_pf( const char *rel_path, BOOL is_file )
233{
234 char path[MAX_PATH];
235
237 strcat( path, "\\" );
238 strcat( path, rel_path );
239
240 if (is_file)
241 return DeleteFileA( path );
242 else
243 return RemoveDirectoryA( path );
244}
245
246static DWORD get_pf_file_size( const char *filename )
247{
248 char path[MAX_PATH];
249 HANDLE file;
250 DWORD size;
251
253 strcat( path, "\\");
254 strcat( path, filename );
255
258 return INVALID_FILE_SIZE;
259
261 CloseHandle( file );
262 return size;
263}
264
265static void write_file( const char *filename, const char *data, DWORD data_size )
266{
267 DWORD size;
270 WriteFile( file, data, data_size, &size, NULL );
271 CloseHandle( file );
272}
273
274static void set_suminfo( const WCHAR *filename )
275{
276 UINT r;
277 MSIHANDLE hsi, hdb;
278
280 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
281
282 r = MsiGetSummaryInformationA( hdb, NULL, 7, &hsi );
283 ok( r == ERROR_SUCCESS, "failed to open summaryinfo %u\n", r );
284
285 r = MsiSummaryInfoSetPropertyA( hsi, 2, VT_LPSTR, 0, NULL, "Installation Database" );
286 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
287
288 r = MsiSummaryInfoSetPropertyA( hsi, 3, VT_LPSTR, 0, NULL, "Installation Database" );
289 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
290
291 r = MsiSummaryInfoSetPropertyA( hsi, 4, VT_LPSTR, 0, NULL, "WineHQ" );
292 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
293
294 r = MsiSummaryInfoSetPropertyA( hsi, 7, VT_LPSTR, 0, NULL, ";1033" );
295 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
296
297 r = MsiSummaryInfoSetPropertyA( hsi, 9, VT_LPSTR, 0, NULL, "{E528DDD6-4801-4BEC-BBB6-C5EE0FD097E9}" );
298 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
299
300 r = MsiSummaryInfoSetPropertyA( hsi, 14, VT_I4, 100, NULL, NULL );
301 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
302
303 r = MsiSummaryInfoSetPropertyA( hsi, 15, VT_I4, 0, NULL, NULL );
304 ok( r == ERROR_SUCCESS, "failed to set summary info %u\n", r );
305
306 r = MsiSummaryInfoPersist( hsi );
307 ok( r == ERROR_SUCCESS, "failed to persist suminfo %u\n", r );
308
309 r = MsiCloseHandle( hsi );
310 ok( r == ERROR_SUCCESS, "failed to close suminfo %u\n", r );
311
312 r = MsiCloseHandle( hdb );
313 ok( r == ERROR_SUCCESS, "failed to close database %u\n", r );
314}
315
316static void create_database( const char *filename, const struct msi_table *tables, UINT num_tables )
317{
318 MSIHANDLE hdb;
319 UINT r, i;
321 int len;
322
323 len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
324 if (!(filenameW = malloc( len * sizeof(WCHAR) ))) return;
326
328 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
329
330 /* import the tables into the database */
331 for (i = 0; i < num_tables; i++)
332 {
333 const struct msi_table *table = &tables[i];
334
335 write_file( table->filename, table->data, (table->size - 1) * sizeof(char) );
336
337 r = MsiDatabaseImportA( hdb, CURR_DIR, table->filename );
338 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
339
340 DeleteFileA( table->filename );
341 }
342
343 r = MsiDatabaseCommit( hdb );
344 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
345
346 MsiCloseHandle( hdb );
348 free( filenameW );
349}
350
351/* data for generating a patch */
352
353/* table names - encoded as in an msi database file */
354static const WCHAR p_name0[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
355static const WCHAR p_name1[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
356static const WCHAR p_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
357static const WCHAR p_name3[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
358static const WCHAR p_name4[] = { 0x3a8c, 0x47cb, 0x45b0, 0x45ec, 0x45a8, 0x4837, 0}; /* CAB_msitest */
359static const WCHAR p_name5[] = { 0x4840, 0x4596, 0x3e6c, 0x45e4, 0x42e6, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* MsiPatchSequence */
360static const WCHAR p_name6[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
361 0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
362 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
363/* substorage names */
364static const WCHAR p_name7[] = { 0x0074, 0x0061, 0x0072, 0x0067, 0x0065, 0x0074, 0x0054, 0x006f, 0x0075, 0x0070,
365 0x0067, 0x0072, 0x0061, 0x0064, 0x0065, 0x0064, 0 }; /* targetToupgraded */
366static const WCHAR p_name8[] = { 0x0023, 0x0074, 0x0061, 0x0072, 0x0067, 0x0065, 0x0074, 0x0054, 0x006f, 0x0075,
367 0x0070, 0x0067, 0x0072, 0x0061, 0x0064, 0x0065, 0x0064, 0 }; /* #targetToupgraded */
368
369/* data in each table */
370static const WCHAR p_data0[] = { /* _Columns */
371 0x0001, 0x0001, 0x0001, 0x0001, 0x8001, 0x8002, 0x8003, 0x8004,
372 0x0002, 0x0003, 0x0004, 0x0005, 0xad00, 0xbd26, 0x8d00, 0x9502
373};
374static const WCHAR p_data1[] = { /* _Tables */
375 0x0001
376};
377static const char p_data2[] = { /* _StringData */
378 "MsiPatchSequencePatchFamilyProductCodeSequenceAttributes1.1.19388.37230913B8D18FBB64CACA239C74C11E3FA74"
379};
380static const WCHAR p_data3[] = { /* _StringPool */
381/* len, refs */
382 0, 0, /* string 0 '' */
383 16, 5, /* string 1 'MsiPatchSequence' */
384 11, 1, /* string 2 'PatchFamily' */
385 11, 1, /* string 3 'ProductCode' */
386 8, 1, /* string 4 'Sequence' */
387 10, 1, /* string 5 'Attributes' */
388 15, 1, /* string 6 '1.1.19388.37230' */
389 32, 1, /* string 7 '913B8D18FBB64CACA239C74C11E3FA74' */
390};
391static const char p_data4[] = { /* CAB_msitest */
392 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
396 0xea, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
397 0x3c, 0xd4, 0xb8, 0x20, 0x00, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e,
398 0x74, 0x78, 0x74, 0x00, 0xe8, 0x03, 0x00, 0x00, 0xea, 0x03, 0x00,
399 0x00, 0x00, 0x00, 0xcb, 0x50, 0x17, 0x7e, 0x20, 0x00, 0x66, 0x69,
400 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0xb0, 0xb2, 0xb2, 0x25,
401 0x2d, 0x00, 0xd2, 0x07, 0x43, 0x4b, 0xcb, 0x2d, 0xce, 0x2c, 0x49,
402 0x2d, 0x2e, 0x89, 0x29, 0x48, 0x2c, 0x49, 0xce, 0x48, 0x4d, 0xd1,
403 0x2b, 0xa9, 0x28, 0x51, 0x18, 0x05, 0xa3, 0x60, 0x14, 0x0c, 0x37,
404 0x90, 0x8b, 0x9c, 0xd3, 0x41, 0xf9, 0x9c, 0x61, 0x14, 0x8c, 0x82,
405 0x51, 0x30, 0xdc, 0x00, 0x00
406};
407static const WCHAR p_data5[] = { /* MsiPatchSequence */
408 0x0007, 0x0000, 0x0006, 0x8000
409};
410static const char p_data6[] = { /* SummaryInformation */
411 0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
414 0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
415 0x30, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
416 0x00, 0x09, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00,
417 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x90,
418 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
419 0x0f, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
420 0x00, 0x27, 0x00, 0x00, 0x00, 0x7b, 0x30, 0x46, 0x39, 0x36, 0x43,
421 0x44, 0x43, 0x30, 0x2d, 0x34, 0x43, 0x44, 0x46, 0x2d, 0x34, 0x33,
422 0x30, 0x34, 0x2d, 0x42, 0x32, 0x38, 0x33, 0x2d, 0x37, 0x42, 0x39,
423 0x32, 0x36, 0x34, 0x38, 0x38, 0x39, 0x45, 0x46, 0x37, 0x7d, 0x00,
424 0x00, 0x1e, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x7b, 0x39,
425 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42, 0x42,
426 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33, 0x39,
427 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46, 0x41,
428 0x37, 0x34, 0x7d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x25, 0x00,
429 0x00, 0x00, 0x3a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x6f,
430 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x3b, 0x3a, 0x23,
431 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x6f, 0x75, 0x70, 0x67,
432 0x72, 0x61, 0x64, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
433 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x50, 0x61, 0x74, 0x63, 0x68,
434 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x00,
435 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
436};
437
440 const void *data;
442};
443
444static const struct table_data table_patch_data[] = {
445 { p_name0, p_data0, sizeof p_data0 },
446 { p_name1, p_data1, sizeof p_data1 },
447 { p_name2, p_data2, sizeof p_data2 - 1 },
448 { p_name3, p_data3, sizeof p_data3 },
449 { p_name4, p_data4, sizeof p_data4 },
450 { p_name5, p_data5, sizeof p_data5 },
451 { p_name6, p_data6, sizeof p_data6 }
452};
453
454static const WCHAR t1_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
455static const WCHAR t1_name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
456static const WCHAR t1_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
457static const WCHAR t1_name3[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
458 0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
459 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
460
461static const WCHAR t1_data0[] = { /* File */
462 0x0008, 0x0001, 0x03ea, 0x8000
463};
464static const char t1_data1[] = { /* _StringData */
465 "patch.txt"
466};
467static const WCHAR t1_data2[] = { /* _StringPool */
468/* len, refs */
469 0, 0, /* string 0 '' */
470 9, 1, /* string 1 'patch.txt' */
471};
472static const char t1_data3[] = { /* SummaryInformation */
473 0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
476 0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
477 0x30, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00,
478 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00,
479 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa8,
480 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00,
481 0x06, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00,
482 0x00, 0xd0, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xdc, 0x00,
483 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x08,
484 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
485 0x07, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x8f, 0x01, 0x00,
486 0x00, 0x10, 0x00, 0x00, 0x00, 0x97, 0x01, 0x00, 0x00, 0x1e, 0x00,
487 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x73, 0x74, 0x61,
488 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x61, 0x74,
489 0x61, 0x62, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
490 0x00, 0x16, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
491 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x61, 0x74, 0x61,
492 0x62, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
493 0x07, 0x00, 0x00, 0x00, 0x57, 0x69, 0x6e, 0x65, 0x48, 0x51, 0x00,
494 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x1e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x78, 0x38,
499 0x36, 0x3b, 0x31, 0x30, 0x33, 0x33, 0x00, 0x00, 0x00, 0x1e, 0x00,
500 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0x31, 0x30, 0x33, 0x33,
501 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
502 0x7b, 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46,
503 0x42, 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32,
504 0x33, 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33,
505 0x46, 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b,
506 0x7b, 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46,
507 0x42, 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32,
508 0x33, 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33,
509 0x46, 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b,
510 0x7b, 0x41, 0x32, 0x45, 0x33, 0x44, 0x36, 0x34, 0x33, 0x2d, 0x34,
511 0x45, 0x32, 0x43, 0x2d, 0x34, 0x37, 0x37, 0x46, 0x2d, 0x41, 0x33,
512 0x30, 0x39, 0x2d, 0x46, 0x37, 0x36, 0x46, 0x35, 0x35, 0x32, 0x44,
513 0x35, 0x46, 0x34, 0x33, 0x7d, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
514 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x22,
515 0x09
516};
517
518static const struct table_data table_transform1_data[] = {
519 { t1_name0, t1_data0, sizeof t1_data0 },
520 { t1_name1, t1_data1, sizeof t1_data1 - 1 },
521 { t1_name2, t1_data2, sizeof t1_data2 },
522 { t1_name3, t1_data3, sizeof t1_data3 }
523};
524
525static const WCHAR t2_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
526static const WCHAR t2_name1[] = { 0x4840, 0x4216, 0x4327, 0x4824, 0 }; /* Media */
527static const WCHAR t2_name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
528static const WCHAR t2_name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
529static const WCHAR t2_name4[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
530static const WCHAR t2_name5[] = { 0x4840, 0x4119, 0x41b7, 0x3e6b, 0x41a4, 0x412e, 0x422a, 0 }; /* PatchPackage */
531static const WCHAR t2_name6[] = { 0x4840, 0x4452, 0x45f6, 0x43e4, 0x3baf, 0x423b, 0x4626,
532 0x4237, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* InstallExecuteSequence */
533static const WCHAR t2_name7[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
534static const WCHAR t2_name8[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
535static const WCHAR t2_name9[] = { 0x0005, 0x0053, 0x0075, 0x006d, 0x006d, 0x0061, 0x0072,
536 0x0079, 0x0049, 0x006e, 0x0066, 0x006f, 0x0072, 0x006d,
537 0x0061, 0x0074, 0x0069, 0x006f, 0x006e, 0 }; /* SummaryInformation */
538static const WCHAR t2_name10[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x3b28, 0x4432, 0x44b3,
539 0x4231, 0x45f1, 0x4836, 0 }; /* FeatureComponents */
540static const WCHAR t2_name11[] = { 0x4840, 0x448c, 0x44f0, 0x4472, 0x4468, 0x4837, 0 }; /* Component */
541static const WCHAR t2_name12[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x4828, 0 }; /* Feature */
542
543static const WCHAR t2_data0[] = { /* File */
544 0x00c0, 0x0001, 0x9000, 0x83e8, 0x0801, 0x0002, 0x0003, 0x0002,
545 0x03e8, 0x8000, 0x0000, 0x0000, 0x9000, 0x83e9
546};
547static const WCHAR t2_data1[] = { /* Media */
548 0x0601, 0x8002, 0x03e9, 0x8000, 0x0000, 0x000d, 0x0000, 0x000e
549};
550static const WCHAR t2_data2[] = { /* _Columns */
551 0x0401, 0x000f, 0x0000, 0x0010, 0xad48, 0x0401, 0x000f, 0x0000, /* 0x0401 = add row (1), 4 shorts */
552 0x0011, 0xa502, 0x0401, 0x000f, 0x0000, 0x0012, 0x8104, 0x0401,
553 0x000f, 0x0000, 0x0013, 0x8502, 0x0401, 0x000f, 0x0000, 0x0014,
554 0x9900, 0x0401, 0x000f, 0x0000, 0x0015, 0x9d48, 0x0401, 0x0016,
555 0x0000, 0x0017, 0xad26, 0x0401, 0x0016, 0x0000, 0x0018, 0x8502,
556 0x0401, 0x001a, 0x0000, 0x001b, 0xad26, 0x0401, 0x001a, 0x0000,
557 0x0014, 0x8900
558};
559static const WCHAR t2_data3[] = { /* _Tables */
560 0x0101, 0x000f, 0x0101, 0x0016, 0x0101, 0x001a
561};
562static const WCHAR t2_data4[] = { /* Property */
563 0x0002, 0x0008, 0x0009, 0x0201, 0x000a, 0x000b
564};
565static const WCHAR t2_data5[] = { /* PatchPackage */
566 0x0201, 0x0019, 0x8002
567};
568static const WCHAR t2_data6[] = { /* InstallExecuteSequence */
569 0x0301, 0x000c, 0x0000, 0x87d1
570};
571static const char t2_data7[] = { /* _StringData */
572 "patch.txtfile.txtfile{327d9640-674f-4b9f-8b8a-547a0f6f8518}MSITESTDIRnewnew featurePATCHNEWSUMMARYSUBJECT"
573 "Installation DatabasePATCHNEWPACKAGECODE{42A14A82-12F8-4E6D-970E-1B4EE7BE28B0}PatchFiles#CAB_msitestprop"
574 "PatchFile_SequencePatchSizeAttributesHeaderStreamRef_PatchPackagePatchIdMedia_"
575 "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}MsiPatchHeadersStreamRef"
576};
577static const WCHAR t2_data8[] = { /* _StringPool */
578/* len, refs */
579 0, 0, /* string 0 '' */
580 9, 1, /* string 1 'patch.txt' */
581 8, 3, /* string 2 'file.txt' */
582 4, 3, /* string 3 'file' */
583 38, 1, /* string 4 '{327d9640-674f-4b9f-8b8a-547a0f6f8518}' */
584 10, 2, /* string 5 'MSITESTDIR' */
585 3, 2, /* string 6 'new' */
586 11, 1, /* string 7 'new feature' */
587 22, 1, /* string 8 'PATCHNEWSUMMARYSUBJECT' */
588 21, 1, /* string 9 'Installation Database' */
589 19, 1, /* string 10 'PATCHNEWPACKAGECODE' */
590 38, 1, /* string 11 '{42A14A82-12F8-4E6D-970E-1B4EE7BE28B0}' */
591 10, 1, /* string 12 'PatchFiles' */
592 12, 1, /* string 13 '#CAB_msitest' */
593 4, 1, /* string 14 'prop' */
594 5, 7, /* string 15 'Patch' */
595 5, 1, /* string 16 'File_' */
596 8, 1, /* string 17 'Sequence' */
597 9, 1, /* string 18 'PatchSize' */
598 10, 1, /* string 19 'Attributes' */
599 6, 2, /* string 20 'Header' */
600 10, 1, /* string 21 'StreamRef_' */
601 12, 3, /* string 22 'PatchPackage' */
602 7, 1, /* string 23 'PatchId' */
603 6, 1, /* string 24 'Media_' */
604 38, 1, /* string 25 '{0F96CDC0-4CDF-4304-B283-7B9264889EF7}' */
605 15, 3, /* string 26 'MsiPatchHeaders' */
606 9, 1 /* string 27 'StreamRef' */
607};
608static const char t2_data9[] = { /* SummaryInformation */
609 0xfe, 0xff, 0x00, 0x00, 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x9f, 0xf2, 0xf9,
612 0x4f, 0x68, 0x10, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9,
613 0x30, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00,
614 0x00, 0x02, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00,
615 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78,
616 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
617 0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00,
618 0x00, 0x9c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xa8, 0x00,
619 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x09,
620 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
621 0x4c, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00,
622 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
625 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
626 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00,
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01,
628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
629 0x06, 0x00, 0x00, 0x00, 0x3b, 0x31, 0x30, 0x33, 0x33, 0x00, 0x00,
630 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
631 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7b,
632 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42,
633 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33,
634 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46,
635 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b, 0x7b,
636 0x39, 0x31, 0x33, 0x42, 0x38, 0x44, 0x31, 0x38, 0x2d, 0x46, 0x42,
637 0x42, 0x36, 0x2d, 0x34, 0x43, 0x41, 0x43, 0x2d, 0x41, 0x32, 0x33,
638 0x39, 0x2d, 0x43, 0x37, 0x34, 0x43, 0x31, 0x31, 0x45, 0x33, 0x46,
639 0x41, 0x37, 0x34, 0x7d, 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x3b, 0x7b,
640 0x41, 0x32, 0x45, 0x33, 0x44, 0x36, 0x34, 0x33, 0x2d, 0x34, 0x45,
641 0x32, 0x43, 0x2d, 0x34, 0x37, 0x37, 0x46, 0x2d, 0x41, 0x33, 0x30,
642 0x39, 0x2d, 0x46, 0x37, 0x36, 0x46, 0x35, 0x35, 0x32, 0x44, 0x35,
643 0x46, 0x34, 0x33, 0x7d, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2d,
644 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x27, 0x09
645};
646static const WCHAR t2_data10[] = { /* FeatureComponents */
647 0x0201, 0x0006, 0x0003
648};
649static const WCHAR t2_data11[] = { /* Component */
650 0x0601, 0x0003, 0x0004, 0x0005, 0x8000, 0x0000, 0x0002
651};
652static const WCHAR t2_data12[] = { /* Feature */
653 0x0801, 0x0006, 0x0000, 0x0000, 0x0007, 0x8001, 0x8001, 0x0005,
654 0x8000
655};
656
657static const struct table_data table_transform2_data[] = {
658 { t2_name0, t2_data0, sizeof t2_data0 },
659 { t2_name1, t2_data1, sizeof t2_data1 },
660 { t2_name2, t2_data2, sizeof t2_data2 },
661 { t2_name3, t2_data3, sizeof t2_data3 },
662 { t2_name4, t2_data4, sizeof t2_data4 },
663 { t2_name5, t2_data5, sizeof t2_data5 },
664 { t2_name6, t2_data6, sizeof t2_data6 },
665 { t2_name7, t2_data7, sizeof t2_data7 - 1 },
666 { t2_name8, t2_data8, sizeof t2_data8 },
667 { t2_name9, t2_data9, sizeof t2_data9 },
668 { t2_name10, t2_data10, sizeof t2_data10 },
669 { t2_name11, t2_data11, sizeof t2_data11 },
670 { t2_name12, t2_data12, sizeof t2_data12 },
671};
672
673static void write_tables( IStorage *stg, const struct table_data *tables, UINT num_tables )
674{
675 IStream *stm;
676 DWORD i, count;
677 HRESULT r;
678
679 for (i = 0; i < num_tables; i++)
680 {
681 r = IStorage_CreateStream( stg, tables[i].name, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
682 if (FAILED( r ))
683 {
684 ok( 0, "failed to create stream %#lx\n", r );
685 continue;
686 }
687
688 r = IStream_Write( stm, tables[i].data, tables[i].size, &count );
689 if (FAILED( r ) || count != tables[i].size)
690 ok( 0, "failed to write stream\n" );
691 IStream_Release( stm );
692 }
693}
694
695static void create_patch( const char *filename )
696{
697 IStorage *stg = NULL, *stg1 = NULL, *stg2 = NULL;
699 HRESULT r;
700 int len;
702
703 const CLSID CLSID_MsiPatch = {0xc1086, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
704 const CLSID CLSID_MsiTransform = {0xc1082, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
705
706 len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
707 filenameW = malloc( len * sizeof(WCHAR) );
709
710 r = StgCreateDocfile( filenameW, mode, 0, &stg );
711 free( filenameW );
712 ok( r == S_OK, "failed to create storage %#lx\n", r );
713 if (!stg)
714 return;
715
716 r = IStorage_SetClass( stg, &CLSID_MsiPatch );
717 ok( r == S_OK, "failed to set storage type %#lx\n", r );
718
720
721 r = IStorage_CreateStorage( stg, p_name7, mode, 0, 0, &stg1 );
722 ok( r == S_OK, "failed to create substorage %#lx\n", r );
723
724 r = IStorage_SetClass( stg1, &CLSID_MsiTransform );
725 ok( r == S_OK, "failed to set storage type %#lx\n", r );
726
728 IStorage_Release( stg1 );
729
730 r = IStorage_CreateStorage( stg, p_name8, mode, 0, 0, &stg2 );
731 ok( r == S_OK, "failed to create substorage %#lx\n", r );
732
733 r = IStorage_SetClass( stg2, &CLSID_MsiTransform );
734 ok( r == S_OK, "failed to set storage type %#lx\n", r );
735
737 IStorage_Release( stg2 );
738 IStorage_Release( stg );
739}
740
741static void test_simple_patch( void )
742{
743 UINT r;
744 DWORD size;
745 char path[MAX_PATH], install_source[MAX_PATH], buffer[32];
746 const char *query;
747 WCHAR pathW[MAX_PATH];
748 MSIHANDLE hpackage, hdb, hview, hrec;
749
750 if (!pMsiApplyPatchA)
751 {
752 win_skip("MsiApplyPatchA is not available\n");
753 return;
754 }
755 if (is_process_limited())
756 {
757 skip("process is limited\n");
758 return;
759 }
760
761 CreateDirectoryA( "msitest", NULL );
762 create_file( "msitest\\patch.txt", 1000 );
763
766
768
769 r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
770 if (r != ERROR_SUCCESS)
771 {
772 skip("Product installation failed with error code %u\n", r);
773 goto cleanup;
774 }
775
776 size = get_pf_file_size( "msitest\\patch.txt" );
777 ok( size == 1000, "expected 1000, got %lu\n", size );
778
779 size = sizeof(install_source);
780 r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
781 "InstallSource", install_source, &size );
782 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
783
784 strcpy( path, CURR_DIR );
785 strcat( path, "\\" );
786 strcat( path, msifile );
787
788 r = MsiOpenPackageA( path, &hpackage );
789 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
790
791 hdb = MsiGetActiveDatabase( hpackage );
792 ok( hdb, "failed to get database handle\n" );
793
794 query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'";
795 r = MsiDatabaseOpenViewA( hdb, query, &hview );
796 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
797
798 r = MsiViewExecute( hview, 0 );
799 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
800
801 r = MsiViewFetch( hview, &hrec );
802 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
803
804 MsiCloseHandle( hrec );
805 MsiViewClose( hview );
806 MsiCloseHandle( hview );
807
808 query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' "
809 "AND `Value` = 'Installer Database'";
810 r = MsiDatabaseOpenViewA( hdb, query, &hview );
811 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
812
813 r = MsiViewExecute( hview, 0 );
814 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
815
816 r = MsiViewFetch( hview, &hrec );
817 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
818
819 MsiCloseHandle( hrec );
820 MsiViewClose( hview );
821 MsiCloseHandle( hview );
822
823 buffer[0] = 0;
824 size = sizeof(buffer);
825 r = MsiGetPropertyA( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size );
826 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
827 ok( !strcmp( buffer, "Installer Database" ), "expected \'Installer Database\', got \'%s\'\n", buffer );
828
829 MsiCloseHandle( hdb );
830 MsiCloseHandle( hpackage );
831
833 ok( r == ERROR_SUCCESS || broken( r == ERROR_PATCH_PACKAGE_INVALID ), /* version 2.0 */
834 "expected ERROR_SUCCESS, got %u\n", r );
835
837 {
838 win_skip("Windows Installer < 3.0 detected\n");
839 goto uninstall;
840 }
841
842 size = get_pf_file_size( "msitest\\patch.txt" );
843 ok( size == 1002, "expected 1002, got %lu\n", size );
844 size = get_pf_file_size( "msitest\\file.txt" );
845 ok( size == 1000, "expected 1000, got %lu\n", size );
846
847 /* show that MsiOpenPackage applies registered patches */
848 r = MsiOpenPackageA( path, &hpackage );
849 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
850
851 hdb = MsiGetActiveDatabase( hpackage );
852 ok( hdb, "failed to get database handle\n" );
853
854 query = "SELECT * FROM `Property` where `Property` = 'PATCHNEWPACKAGECODE'";
855 r = MsiDatabaseOpenViewA( hdb, query, &hview );
856 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
857
858 r = MsiViewExecute( hview, 0 );
859 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
860
861 r = MsiViewFetch( hview, &hrec );
862 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
863
864 MsiCloseHandle( hrec );
865 MsiViewClose( hview );
866 MsiCloseHandle( hview );
867
868 query = "SELECT * FROM `Property` WHERE `Property` = 'PATCHNEWSUMMARYSUBJECT' "
869 "AND `Value` = 'Installation Database'";
870 r = MsiDatabaseOpenViewA( hdb, query, &hview );
871 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
872
873 r = MsiViewExecute( hview, 0 );
874 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
875
876 r = MsiViewFetch( hview, &hrec );
877 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
878
879 MsiCloseHandle( hrec );
880 MsiViewClose( hview );
881 MsiCloseHandle( hview );
882
883 buffer[0] = 0;
884 size = sizeof(buffer);
885 r = MsiGetPropertyA( hpackage, "PATCHNEWSUMMARYSUBJECT", buffer, &size );
886 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
887 ok( !strcmp( buffer, "Installation Database" ), "expected \'Installation Database\', got \'%s\'\n", buffer );
888
889 MsiCloseHandle( hdb );
890 MsiCloseHandle( hpackage );
891
892 /* show that patches are not committed to the local package database */
893 size = sizeof(path);
894 r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
895 "LocalPackage", path, &size );
896 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
897
898 MultiByteToWideChar( CP_ACP, 0, path, -1, pathW, MAX_PATH );
899 r = MsiOpenDatabaseW( pathW, MSIDBOPEN_READONLY, &hdb );
900 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
901
902 r = MsiDatabaseOpenViewA( hdb, query, &hview );
903 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
904
905 r = MsiViewExecute( hview, 0 );
906 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
907
908 r = MsiViewFetch( hview, &hrec );
909 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
910
911 MsiCloseHandle( hrec );
912 MsiViewClose( hview );
913 MsiCloseHandle( hview );
914 MsiCloseHandle( hdb );
915
916uninstall:
917 size = sizeof(path);
918 r = MsiGetProductInfoA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
919 "InstallSource", path, &size );
920 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
921 ok( !strcasecmp( path, install_source ), "wrong path %s\n", path );
922
923 r = MsiInstallProductA( msifile, "REMOVE=ALL" );
924 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
925
926 ok( !delete_pf( "msitest\\patch.txt", TRUE ), "file not removed\n" );
927 ok( !delete_pf( "msitest\\file.txt", TRUE ), "file not removed\n" );
928 ok( !delete_pf( "msitest", FALSE ), "directory not removed\n" );
929
930cleanup:
933 DeleteFileA( "msitest\\patch.txt" );
934 RemoveDirectoryA( "msitest" );
935}
936
937static void test_MsiOpenDatabase( void )
938{
939 UINT r;
940 MSIHANDLE hdb;
941
943 ok(r == ERROR_SUCCESS, "failed to open database %u\n", r);
944
945 r = MsiDatabaseCommit( hdb );
946 ok(r == ERROR_SUCCESS, "failed to commit database %u\n", r);
947 MsiCloseHandle( hdb );
948
950 ok(r == ERROR_OPEN_FAILED, "expected ERROR_OPEN_FAILED, got %u\n", r);
952
954 ok(r == ERROR_SUCCESS , "failed to open database %u\n", r);
955
956 r = MsiDatabaseCommit( hdb );
957 ok(r == ERROR_SUCCESS, "failed to commit database %u\n", r);
958 MsiCloseHandle( hdb );
959
961 ok(r == ERROR_SUCCESS, "failed to open database %u\n", r);
962 MsiCloseHandle( hdb );
964
967
969 ok(r == ERROR_OPEN_FAILED, "failed to open database %u\n", r );
970
972 ok(r == ERROR_SUCCESS, "failed to open database %u\n", r );
973 MsiCloseHandle( hdb );
974
977}
978
979static UINT find_entry( MSIHANDLE hdb, const char *table, const char *entry )
980{
981 static const char fmt[] = "SELECT * FROM `%s` WHERE `Name` = '%s'";
982 char query[0x100];
983 UINT r;
984 MSIHANDLE hview, hrec;
985
987 r = MsiDatabaseOpenViewA( hdb, query, &hview );
988 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
989
990 r = MsiViewExecute( hview, 0 );
991 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
992
993 r = MsiViewFetch( hview, &hrec );
994 MsiViewClose( hview );
995 MsiCloseHandle( hview );
996 MsiCloseHandle( hrec );
997 return r;
998}
999
1000static UINT find_entryW( MSIHANDLE hdb, const WCHAR *table, const WCHAR *entry )
1001{
1002 WCHAR query[0x100];
1003 MSIHANDLE hview, hrec;
1004 UINT r;
1005
1006 wsprintfW( query, L"SELECT * FROM `%s` WHERE `Name` = '%s'", table, entry );
1007 r = MsiDatabaseOpenViewW( hdb, query, &hview );
1008 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1009
1010 r = MsiViewExecute( hview, 0 );
1011 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1012
1013 r = MsiViewFetch( hview, &hrec );
1014 MsiViewClose( hview );
1015 MsiCloseHandle( hview );
1016 MsiCloseHandle( hrec );
1017 return r;
1018}
1019
1020static INT get_integer( MSIHANDLE hdb, UINT field, const char *query)
1021{
1022 UINT r;
1023 INT ret = -1;
1024 MSIHANDLE hview, hrec;
1025
1026 r = MsiDatabaseOpenViewA( hdb, query, &hview );
1027 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1028
1029 r = MsiViewExecute( hview, 0 );
1030 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1031
1032 r = MsiViewFetch( hview, &hrec );
1033 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1034 if (r == ERROR_SUCCESS)
1035 {
1036 UINT r_tmp;
1037 ret = MsiRecordGetInteger( hrec, field );
1038 MsiCloseHandle( hrec );
1039
1040 r_tmp = MsiViewFetch( hview, &hrec );
1041 ok( r_tmp == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r);
1042 }
1043
1044 MsiViewClose( hview );
1045 MsiCloseHandle( hview );
1046 return ret;
1047}
1048
1049static char *get_string( MSIHANDLE hdb, UINT field, const char *query)
1050{
1051 UINT r;
1052 static char ret[MAX_PATH];
1053 MSIHANDLE hview, hrec;
1054
1055 ret[0] = '\0';
1056
1057 r = MsiDatabaseOpenViewA( hdb, query, &hview );
1058 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1059
1060 r = MsiViewExecute( hview, 0 );
1061 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1062
1063 r = MsiViewFetch( hview, &hrec );
1064 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1065 if (r == ERROR_SUCCESS)
1066 {
1068 r = MsiRecordGetStringA( hrec, field, ret, &size );
1069 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
1070 MsiCloseHandle( hrec );
1071
1072 r = MsiViewFetch( hview, &hrec );
1073 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r);
1074 }
1075
1076 MsiViewClose( hview );
1077 MsiCloseHandle( hview );
1078 return ret;
1079}
1080
1081static void test_system_tables( void )
1082{
1083 static const char patchsource[] = "MSPSRC0F96CDC04CDF4304B2837B9264889EF7";
1084 UINT r;
1085 char *cr;
1086 const char *query;
1087 MSIHANDLE hproduct, hdb, hview, hrec;
1088
1089 if (!pMsiApplyPatchA)
1090 {
1091 win_skip("MsiApplyPatchA is not available\n");
1092 return;
1093 }
1094 if (is_process_limited())
1095 {
1096 skip("process is limited\n");
1097 return;
1098 }
1099
1100 CreateDirectoryA( "msitest", NULL );
1101 create_file( "msitest\\patch.txt", 1000 );
1102
1105
1107
1108 r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
1109 if (r != ERROR_SUCCESS)
1110 {
1111 skip("Product installation failed with error code %d\n", r);
1112 goto cleanup;
1113 }
1114
1115 r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct );
1116 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1117
1118 hdb = MsiGetActiveDatabase( hproduct );
1119 ok( hdb, "failed to get database handle\n" );
1120
1121 r = find_entry( hdb, "_Streams", "\5SummaryInformation" );
1122 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1123
1124 query = "SELECT * FROM `_Storages`";
1125 r = MsiDatabaseOpenViewA( hdb, query, &hview );
1126 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1127
1128 r = MsiViewExecute( hview, 0 );
1129 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1130
1131 r = MsiViewFetch( hview, &hrec );
1132 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1133
1134 r = find_entry( hdb, "_Tables", "Directory" );
1135 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1136
1137 r = find_entry( hdb, "_Tables", "File" );
1138 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1139
1140 r = find_entry( hdb, "_Tables", "Component" );
1141 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1142
1143 r = find_entry( hdb, "_Tables", "Feature" );
1144 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1145
1146 r = find_entry( hdb, "_Tables", "FeatureComponents" );
1147 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1148
1149 r = find_entry( hdb, "_Tables", "Property" );
1150 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1151
1152 r = find_entry( hdb, "_Tables", "InstallExecuteSequence" );
1153 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1154
1155 r = find_entry( hdb, "_Tables", "Media" );
1156 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1157
1158 r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `VolumeLabel`=\'DISK1\'");
1159 ok( r == 1, "Got %u\n", r );
1160
1161 r = find_entry( hdb, "_Tables", "_Property" );
1162 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1163
1164 MsiCloseHandle( hrec );
1165 MsiViewClose( hview );
1166 MsiCloseHandle( hview );
1167 MsiCloseHandle( hdb );
1168 MsiCloseHandle( hproduct );
1169
1171 ok( r == ERROR_SUCCESS || broken( r == ERROR_PATCH_PACKAGE_INVALID ), /* version 2.0 */
1172 "expected ERROR_SUCCESS, got %u\n", r );
1173
1175 {
1176 win_skip("Windows Installer < 3.0 detected\n");
1177 goto uninstall;
1178 }
1179
1180 r = MsiOpenProductA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}", &hproduct );
1181 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1182
1183 hdb = MsiGetActiveDatabase( hproduct );
1184 ok( hdb, "failed to get database handle\n" );
1185
1186 r = find_entry( hdb, "_Streams", "\5SummaryInformation" );
1187 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1188
1189 r = find_entryW( hdb, L"_Streams", L"\x3a8c\x47cb\x45b0\x45ec\x45a8\x4837" );
1190 ok( r == ERROR_NO_MORE_ITEMS, "failed to find entry %u\n", r );
1191
1192 query = "SELECT * FROM `_Storages`";
1193 r = MsiDatabaseOpenViewA( hdb, query, &hview );
1194 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1195
1196 r = MsiViewExecute( hview, 0 );
1197 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1198
1199 r = MsiViewFetch( hview, &hrec );
1200 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1201
1202 r = find_entry( hdb, "_Tables", "Directory" );
1203 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1204
1205 r = find_entry( hdb, "_Tables", "File" );
1206 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1207
1208 r = find_entry( hdb, "_Tables", "Component" );
1209 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1210
1211 r = find_entry( hdb, "_Tables", "Feature" );
1212 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1213
1214 r = find_entry( hdb, "_Tables", "FeatureComponents" );
1215 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1216
1217 r = find_entry( hdb, "_Tables", "Property" );
1218 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1219
1220 r = find_entry( hdb, "_Tables", "InstallExecuteSequence" );
1221 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1222
1223 r = find_entry( hdb, "_Tables", "Media" );
1224 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1225
1226 r = find_entry( hdb, "_Tables", "_Property" );
1227 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1228
1229 r = find_entry( hdb, "_Tables", "MsiPatchHeaders" );
1230 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1231
1232 r = find_entry( hdb, "_Tables", "Patch" );
1233 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1234
1235 r = find_entry( hdb, "_Tables", "PatchPackage" );
1236 ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
1237
1238 cr = get_string( hdb, 6, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1239 todo_wine ok( !strcmp(cr, patchsource), "Expected \"%s\", got \"%s\"\n", patchsource, cr );
1240
1241 r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1242 todo_wine ok( r == 100, "Got %u\n", r );
1243
1244 r = get_integer( hdb, 2, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1245 todo_wine ok( r == 10001, "Got %u\n", r );
1246
1247 r = get_integer( hdb, 1, "SELECT * FROM `Media` WHERE `VolumeLabel`=\'DISK1\'");
1248 ok( r == 1, "Got %u\n", r );
1249
1250 cr = get_string( hdb, 4, "SELECT * FROM `Media` WHERE `Source` IS NOT NULL");
1251 ok( !strcmp(cr, "#CAB_msitest"), "Expected \"#CAB_msitest\", got \"%s\"\n", cr );
1252
1253 r = get_integer( hdb, 8, "SELECT * FROM `File` WHERE `File` = 'patch.txt'");
1254 ok( r == 10000, "Got %u\n", r );
1255
1256 MsiCloseHandle( hrec );
1257 MsiViewClose( hview );
1258 MsiCloseHandle( hview );
1259 MsiCloseHandle( hdb );
1260 MsiCloseHandle( hproduct );
1261
1262uninstall:
1263 r = MsiInstallProductA( msifile, "REMOVE=ALL" );
1264 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1265
1266cleanup:
1269 DeleteFileA( "msitest\\patch.txt" );
1270 RemoveDirectoryA( "msitest" );
1271}
1272
1273static void test_patch_registration( void )
1274{
1275 UINT r;
1276 DWORD size;
1277 char buffer[MAX_PATH], patch_code[39];
1278
1279 if (!pMsiApplyPatchA || !pMsiGetPatchInfoExA || !pMsiEnumPatchesExA)
1280 {
1281 win_skip("required functions not available\n");
1282 return;
1283 }
1284 if (is_process_limited())
1285 {
1286 skip("process is limited\n");
1287 return;
1288 }
1289
1290 CreateDirectoryA( "msitest", NULL );
1291 create_file( "msitest\\patch.txt", 1000 );
1292
1295
1297
1298 r = MsiInstallProductA( msifile, "DISABLE_FEATURE=1" );
1299 if (r != ERROR_SUCCESS)
1300 {
1301 skip("Product installation failed with error code %d\n", r);
1302 goto cleanup;
1303 }
1304
1306 ok( r == ERROR_SUCCESS || broken( r == ERROR_PATCH_PACKAGE_INVALID ), /* version 2.0 */
1307 "expected ERROR_SUCCESS, got %u\n", r );
1308
1310 {
1311 win_skip("Windows Installer < 3.0 detected\n");
1312 goto uninstall;
1313 }
1314
1315 buffer[0] = 0;
1316 size = sizeof(buffer);
1317 r = pMsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1318 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1321 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1322 ok( buffer[0], "buffer empty\n" );
1323
1324 buffer[0] = 0;
1325 size = sizeof(buffer);
1326 r = pMsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1327 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1330 ok( r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r );
1331
1332 buffer[0] = 0;
1333 size = sizeof(buffer);
1334 r = pMsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1335 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1338 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1339 ok( !buffer[0], "got %s\n", buffer );
1340
1341 r = pMsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1343 0, patch_code, NULL, NULL, NULL, NULL );
1344 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1345 ok( !strcmp( patch_code, "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}" ), "wrong patch code\n" );
1346
1347 r = pMsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1349 0, patch_code, NULL, NULL, NULL, NULL );
1350 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1351
1352 r = pMsiEnumPatchesExA( "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1354 0, patch_code, NULL, NULL, NULL, NULL );
1355 ok( r == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %u\n", r );
1356
1357uninstall:
1358 r = MsiInstallProductA( msifile, "REMOVE=ALL" );
1359 ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1360
1361 buffer[0] = 0;
1362 size = sizeof(buffer);
1363 r = pMsiGetPatchInfoExA( "{0F96CDC0-4CDF-4304-B283-7B9264889EF7}",
1364 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}",
1367 ok( r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r );
1368
1369cleanup:
1372 DeleteFileA( "msitest\\patch.txt" );
1373 RemoveDirectoryA( "msitest" );
1374}
1375
1377{
1378 DWORD len;
1379 char temp_path[MAX_PATH], prev_path[MAX_PATH];
1380
1382
1383 GetCurrentDirectoryA( MAX_PATH, prev_path );
1386
1388 len = strlen( CURR_DIR );
1389
1390 if (len && (CURR_DIR[len - 1] == '\\'))
1391 CURR_DIR[len - 1] = 0;
1392
1394
1399
1400 SetCurrentDirectoryA( prev_path );
1401}
#define broken(x)
Definition: _sntprintf.h:21
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:33
#define RegCloseKey(hKey)
Definition: registry.h:49
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
#define CloseHandle
Definition: compat.h:739
#define FILE_BEGIN
Definition: compat.h:761
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetFilePointer
Definition: compat.h:743
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
@ VT_LPSTR
Definition: compat.h:2324
@ VT_I4
Definition: compat.h:2298
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:853
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
Definition: msi.c:82
UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
Definition: msi.c:1592
UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
Definition: msi.c:200
UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, LPDWORD pcchValueBuf)
Definition: msi.c:1256
INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
Definition: msi.c:2284
UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, INSTALLTYPE eInstallType, LPCSTR szCommandLine)
Definition: msi.c:288
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
Definition: package.c:1669
MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
Definition: package.c:1674
UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz)
Definition: package.c:2313
int WINAPI MsiRecordGetInteger(MSIHANDLE handle, UINT iField)
Definition: record.c:237
UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField, char *szValue, DWORD *pcchValue)
Definition: record.c:403
UINT WINAPI MsiEnumPatchesExA(const char *szProductCode, const char *szUserSid, DWORD dwContext, DWORD dwFilter, DWORD dwIndex, char *szPatchCode, char *szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext, char *szTargetUserSid, DWORD *pcchTargetUserSid)
Definition: registry.c:1618
UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, const char *szValue)
Definition: suminfo.c:937
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, const char *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:584
UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE handle)
Definition: suminfo.c:1222
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8636
#define strcasecmp
Definition: fake.h:9
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLenum condition
Definition: glext.h:9255
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
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
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 token
Definition: glfuncs.h:210
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
static void write_tables(void)
Definition: mkdosfs.c:1629
__u8 media
Definition: mkdosfs.c:9
#define CREATE_ALWAYS
Definition: disk.h:72
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const WCHAR filenameW[]
Definition: amstream.c:41
#define todo_wine
Definition: custom.c:79
static const WCHAR t1_data0[]
Definition: patch.c:461
static DWORD get_pf_file_size(const char *filename)
Definition: patch.c:246
static const WCHAR t2_name12[]
Definition: patch.c:541
static const char file_dat[]
Definition: patch.c:70
static const WCHAR p_name6[]
Definition: patch.c:360
static const WCHAR t2_data10[]
Definition: patch.c:646
static void test_system_tables(void)
Definition: patch.c:1081
static const WCHAR t2_data4[]
Definition: patch.c:562
static void set_suminfo(const WCHAR *filename)
Definition: patch.c:274
static const WCHAR msifileW[]
Definition: patch.c:42
static const WCHAR t2_data8[]
Definition: patch.c:577
static void create_file_data(const char *filename, const char *data, DWORD size)
Definition: patch.c:212
static const struct table_data table_transform1_data[]
Definition: patch.c:518
static BOOL delete_pf(const char *rel_path, BOOL is_file)
Definition: patch.c:232
static const WCHAR t2_data2[]
Definition: patch.c:550
static const char media_dat[]
Definition: patch.c:64
static const char p_data6[]
Definition: patch.c:410
static const WCHAR p_data3[]
Definition: patch.c:380
static const char p_data4[]
Definition: patch.c:391
static const WCHAR t2_data11[]
Definition: patch.c:649
static const WCHAR t1_name2[]
Definition: patch.c:456
static void create_patch(const char *filename)
Definition: patch.c:695
static const WCHAR p_data0[]
Definition: patch.c:370
static BOOL get_program_files_dir(char *buf, char *buf2)
Definition: patch.c:187
static const WCHAR t2_name11[]
Definition: patch.c:540
static const char t2_data7[]
Definition: patch.c:571
static const WCHAR t2_name7[]
Definition: patch.c:533
static void init_function_pointers(void)
Definition: patch.c:154
static const WCHAR t2_name3[]
Definition: patch.c:528
static const char property_dat[]
Definition: patch.c:51
static DWORD *static DWORD
Definition: patch.c:37
static LPCSTR
Definition: patch.c:34
static const WCHAR p_data1[]
Definition: patch.c:374
static const struct table_data table_transform2_data[]
Definition: patch.c:657
static INT get_integer(MSIHANDLE hdb, UINT field, const char *query)
Definition: patch.c:1020
static const struct table_data table_patch_data[]
Definition: patch.c:444
static const WCHAR t1_name3[]
Definition: patch.c:457
static void write_file(const char *filename, const char *data, DWORD data_size)
Definition: patch.c:265
static const char * mspfile
Definition: patch.c:41
static const WCHAR p_name4[]
Definition: patch.c:358
static LPSTR
Definition: patch.c:36
static const char p_data2[]
Definition: patch.c:377
static const char condition_dat[]
Definition: patch.c:126
static const WCHAR t2_name1[]
Definition: patch.c:526
static const WCHAR t2_data3[]
Definition: patch.c:559
static const WCHAR p_name5[]
Definition: patch.c:359
static const WCHAR t2_name9[]
Definition: patch.c:535
static const WCHAR mspfileW[]
Definition: patch.c:43
static char * get_string(MSIHANDLE hdb, UINT field, const char *query)
Definition: patch.c:1049
static char PROG_FILES_DIR[MAX_PATH]
Definition: patch.c:46
static const WCHAR p_name8[]
Definition: patch.c:366
static char COMMON_FILES_DIR[MAX_PATH]
Definition: patch.c:47
static const WCHAR p_data5[]
Definition: patch.c:407
static const WCHAR t2_data6[]
Definition: patch.c:568
static char CURR_DIR[MAX_PATH]
Definition: patch.c:45
static const WCHAR t2_name10[]
Definition: patch.c:538
#define create_file(name, size)
Definition: patch.c:230
static const char * msifile
Definition: patch.c:40
static BOOL is_process_limited(void)
Definition: patch.c:170
static const WCHAR t2_data5[]
Definition: patch.c:565
static const char feature_dat[]
Definition: patch.c:92
static const WCHAR p_name7[]
Definition: patch.c:364
static void test_simple_patch(void)
Definition: patch.c:741
static UINT find_entry(MSIHANDLE hdb, const char *table, const char *entry)
Definition: patch.c:979
static const WCHAR t2_name4[]
Definition: patch.c:529
static INSTALLTYPE
Definition: patch.c:34
static const char t1_data1[]
Definition: patch.c:464
static const WCHAR p_name1[]
Definition: patch.c:355
static const WCHAR p_name0[]
Definition: patch.c:354
static const char install_exec_seq_dat[]
Definition: patch.c:106
static const WCHAR t1_name1[]
Definition: patch.c:455
static const WCHAR t2_name8[]
Definition: patch.c:534
static const WCHAR t1_data2[]
Definition: patch.c:467
static const char directory_dat[]
Definition: patch.c:77
static MSIINSTALLCONTEXT
Definition: patch.c:35
static DWORD *static MSIINSTALLCONTEXT LPDWORD
Definition: patch.c:38
static void test_MsiOpenDatabase(void)
Definition: patch.c:937
#define ADD_TABLE(x)
Definition: patch.c:139
static const WCHAR t2_name6[]
Definition: patch.c:531
static const WCHAR t2_name2[]
Definition: patch.c:527
static const struct msi_table tables[]
Definition: patch.c:141
static const WCHAR t2_name5[]
Definition: patch.c:530
static const WCHAR t2_name0[]
Definition: patch.c:525
static const char component_dat[]
Definition: patch.c:85
static const char t1_data3[]
Definition: patch.c:472
#define GET_PROC(mod, func)
static const char feature_comp_dat[]
Definition: patch.c:99
static const WCHAR t2_data1[]
Definition: patch.c:547
static const WCHAR p_name2[]
Definition: patch.c:356
static void test_patch_registration(void)
Definition: patch.c:1273
static const char t2_data9[]
Definition: patch.c:608
static const WCHAR p_name3[]
Definition: patch.c:357
static const WCHAR t1_name0[]
Definition: patch.c:454
static const WCHAR t2_data0[]
Definition: patch.c:543
static UINT find_entryW(MSIHANDLE hdb, const WCHAR *table, const WCHAR *entry)
Definition: patch.c:1000
static const WCHAR t2_data12[]
Definition: patch.c:652
#define create_database(name, tables, num_tables)
Definition: utils.h:42
INTERNETFEATURELIST feature
Definition: misc.c:1719
@ MSIPATCHSTATE_APPLIED
Definition: msi.h:54
enum tagMSIINSTALLCONTEXT MSIINSTALLCONTEXT
Definition: action.c:49
#define INSTALLPROPERTY_LOCALPACKAGEA
Definition: msi.h:342
@ INSTALLTYPE_DEFAULT
Definition: msi.h:189
@ MSIINSTALLCONTEXT_MACHINE
Definition: msi.h:200
@ MSIINSTALLCONTEXT_USERUNMANAGED
Definition: msi.h:199
@ MSIINSTALLCONTEXT_USERMANAGED
Definition: msi.h:198
@ INSTALLUILEVEL_NONE
Definition: msi.h:66
UINT WINAPI MsiViewClose(MSIHANDLE hView)
Definition: msiquery.c:469
UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
Definition: msiquery.c:518
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, LPCWSTR szQuery, MSIHANDLE *phView)
Definition: msiquery.c:236
UINT WINAPI MsiDatabaseCommit(MSIHANDLE hdb)
Definition: msiquery.c:963
UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb, const char *szQuery, MSIHANDLE *phView)
Definition: msiquery.c:88
UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
Definition: msiquery.c:404
#define MSIDBOPEN_PATCHFILE
Definition: msiquery.h:79
#define MSIDBOPEN_DIRECT
Definition: msiquery.h:68
#define MSIDBOPEN_CREATE
Definition: msiquery.h:69
#define MSIDBOPEN_READONLY
Definition: msiquery.h:66
char temp_path[MAX_PATH]
Definition: mspatcha.c:123
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
#define L(x)
Definition: ntvdm.h:50
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_DIRECT
Definition: objbase.h:914
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_WRITE
Definition: objbase.h:918
#define win_skip
Definition: test.h:160
Definition: parser.c:44
Definition: fci.c:127
Definition: dsound.c:943
const char * filename
Definition: patch.c:134
int size
Definition: patch.c:136
const char * data
Definition: patch.c:135
Definition: name.c:39
LPCWSTR name
Definition: patch.c:439
const void * data
Definition: patch.c:440
DWORD size
Definition: patch.c:441
BYTE * data
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
int ret
#define INVALID_FILE_SIZE
Definition: winbase.h:548
#define WINAPI
Definition: msvc.h:6
unsigned long MSIHANDLE
Definition: winemsi.idl:27
#define ERROR_UNKNOWN_PRODUCT
Definition: winerror.h:963
#define ERROR_OPEN_FAILED
Definition: winerror.h:184
#define ERROR_PATCH_PACKAGE_INVALID
Definition: winerror.h:994
enum _TOKEN_ELEVATION_TYPE TOKEN_ELEVATION_TYPE
@ TokenElevationTypeLimited
Definition: winnt_old.h:2488
@ TokenElevationTypeDefault
Definition: winnt_old.h:2486
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define TOKEN_QUERY
Definition: setypes.h:928
@ TokenElevationType
Definition: setypes.h:983
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185