ReactOS  0.4.15-dev-5499-g1341c38
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 
34 static UINT (WINAPI *pMsiApplyPatchA)( LPCSTR, LPCSTR, INSTALLTYPE, LPCSTR );
35 static UINT (WINAPI *pMsiGetPatchInfoExA)( LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT,
36  LPCSTR, LPSTR, DWORD * );
37 static UINT (WINAPI *pMsiEnumPatchesExA)( LPCSTR, LPCSTR, DWORD, DWORD, DWORD, LPSTR,
39 
40 static const char *msifile = "winetest-patch.msi";
41 static const char *mspfile = "winetest-patch.msp";
42 static const WCHAR msifileW[] = L"winetest-patch.msi";
43 static const WCHAR mspfileW[] = L"winetest-patch.msp";
44 
45 static char CURR_DIR[MAX_PATH];
46 static char PROG_FILES_DIR[MAX_PATH];
48 
49 /* msi database data */
50 
51 static 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 
64 static 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 
70 static 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 
77 static 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 
85 static 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 
92 static 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 
99 static 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 
106 static 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 
126 static 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 
132 struct msi_table
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 
141 static const struct msi_table tables[] =
142 {
143  ADD_TABLE( directory ),
144  ADD_TABLE( file ),
145  ADD_TABLE( component ),
146  ADD_TABLE( feature ),
147  ADD_TABLE( feature_comp ),
148  ADD_TABLE( property ),
149  ADD_TABLE( install_exec_seq ),
150  ADD_TABLE( media ),
152 };
153 
154 static 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 );
164  GET_PROC( hmsi, MsiGetPatchInfoExA );
165  GET_PROC( hmsi, MsiEnumPatchesExA );
166 
167 #undef GET_PROC
168 }
169 
171 {
172  HANDLE token;
173 
175  {
176  BOOL ret;
178  DWORD size;
179 
182  return (ret && type == TokenElevationTypeLimited);
183  }
184  return FALSE;
185 }
186 
187 static 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 
212 static void create_file_data( const char *filename, const char *data, DWORD size )
213 {
214  HANDLE file;
215  DWORD written;
216 
218  if (file == INVALID_HANDLE_VALUE)
219  return;
220 
221  WriteFile( file, data, strlen( data ), &written, NULL );
222  if (size)
223  {
225  SetEndOfFile( file );
226  }
227  CloseHandle( file );
228 }
229 
230 #define create_file( name, size ) create_file_data( name, name, size )
231 
232 static 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 
246 static 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 
257  if (file == INVALID_HANDLE_VALUE)
258  return INVALID_FILE_SIZE;
259 
260  size = GetFileSize( file, NULL );
261  CloseHandle( file );
262  return size;
263 }
264 
265 static 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 
274 static 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 
316 static void create_database( const char *filename, const struct msi_table *tables, UINT num_tables )
317 {
318  MSIHANDLE hdb;
319  UINT r, i;
320  WCHAR *filenameW;
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 */
354 static const WCHAR p_name0[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
355 static const WCHAR p_name1[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
356 static const WCHAR p_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
357 static const WCHAR p_name3[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
358 static const WCHAR p_name4[] = { 0x3a8c, 0x47cb, 0x45b0, 0x45ec, 0x45a8, 0x4837, 0}; /* CAB_msitest */
359 static const WCHAR p_name5[] = { 0x4840, 0x4596, 0x3e6c, 0x45e4, 0x42e6, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* MsiPatchSequence */
360 static 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 */
364 static const WCHAR p_name7[] = { 0x0074, 0x0061, 0x0072, 0x0067, 0x0065, 0x0074, 0x0054, 0x006f, 0x0075, 0x0070,
365  0x0067, 0x0072, 0x0061, 0x0064, 0x0065, 0x0064, 0 }; /* targetToupgraded */
366 static 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 */
370 static const WCHAR p_data0[] = { /* _Columns */
371  0x0001, 0x0001, 0x0001, 0x0001, 0x8001, 0x8002, 0x8003, 0x8004,
372  0x0002, 0x0003, 0x0004, 0x0005, 0xad00, 0xbd26, 0x8d00, 0x9502
373 };
374 static const WCHAR p_data1[] = { /* _Tables */
375  0x0001
376 };
377 static const char p_data2[] = { /* _StringData */
378  "MsiPatchSequencePatchFamilyProductCodeSequenceAttributes1.1.19388.37230913B8D18FBB64CACA239C74C11E3FA74"
379 };
380 static 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 };
391 static 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 };
407 static const WCHAR p_data5[] = { /* MsiPatchSequence */
408  0x0007, 0x0000, 0x0006, 0x8000
409 };
410 static 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 
438 struct table_data {
440  const void *data;
442 };
443 
444 static 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 
454 static const WCHAR t1_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
455 static const WCHAR t1_name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
456 static const WCHAR t1_name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
457 static 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 
461 static const WCHAR t1_data0[] = { /* File */
462  0x0008, 0x0001, 0x03ea, 0x8000
463 };
464 static const char t1_data1[] = { /* _StringData */
465  "patch.txt"
466 };
467 static const WCHAR t1_data2[] = { /* _StringPool */
468 /* len, refs */
469  0, 0, /* string 0 '' */
470  9, 1, /* string 1 'patch.txt' */
471 };
472 static 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 
518 static 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 
525 static const WCHAR t2_name0[] = { 0x4840, 0x430f, 0x422f, 0 }; /* File */
526 static const WCHAR t2_name1[] = { 0x4840, 0x4216, 0x4327, 0x4824, 0 }; /* Media */
527 static const WCHAR t2_name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
528 static const WCHAR t2_name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
529 static const WCHAR t2_name4[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
530 static const WCHAR t2_name5[] = { 0x4840, 0x4119, 0x41b7, 0x3e6b, 0x41a4, 0x412e, 0x422a, 0 }; /* PatchPackage */
531 static const WCHAR t2_name6[] = { 0x4840, 0x4452, 0x45f6, 0x43e4, 0x3baf, 0x423b, 0x4626,
532  0x4237, 0x421c, 0x4634, 0x4468, 0x4226, 0 }; /* InstallExecuteSequence */
533 static const WCHAR t2_name7[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
534 static const WCHAR t2_name8[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
535 static 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 */
538 static const WCHAR t2_name10[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x3b28, 0x4432, 0x44b3,
539  0x4231, 0x45f1, 0x4836, 0 }; /* FeatureComponents */
540 static const WCHAR t2_name11[] = { 0x4840, 0x448c, 0x44f0, 0x4472, 0x4468, 0x4837, 0 }; /* Component */
541 static const WCHAR t2_name12[] = { 0x4840, 0x420f, 0x45e4, 0x4578, 0x4828, 0 }; /* Feature */
542 
543 static const WCHAR t2_data0[] = { /* File */
544  0x00c0, 0x0001, 0x9000, 0x83e8, 0x0801, 0x0002, 0x0003, 0x0002,
545  0x03e8, 0x8000, 0x0000, 0x0000, 0x9000, 0x83e9
546 };
547 static const WCHAR t2_data1[] = { /* Media */
548  0x0601, 0x8002, 0x03e9, 0x8000, 0x0000, 0x000d, 0x0000, 0x000e
549 };
550 static 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 };
559 static const WCHAR t2_data3[] = { /* _Tables */
560  0x0101, 0x000f, 0x0101, 0x0016, 0x0101, 0x001a
561 };
562 static const WCHAR t2_data4[] = { /* Property */
563  0x0002, 0x0008, 0x0009, 0x0201, 0x000a, 0x000b
564 };
565 static const WCHAR t2_data5[] = { /* PatchPackage */
566  0x0201, 0x0019, 0x8002
567 };
568 static const WCHAR t2_data6[] = { /* InstallExecuteSequence */
569  0x0301, 0x000c, 0x0000, 0x87d1
570 };
571 static 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 };
577 static 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 };
608 static 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 };
646 static const WCHAR t2_data10[] = { /* FeatureComponents */
647  0x0201, 0x0006, 0x0003
648 };
649 static const WCHAR t2_data11[] = { /* Component */
650  0x0601, 0x0003, 0x0004, 0x0005, 0x8000, 0x0000, 0x0002
651 };
652 static const WCHAR t2_data12[] = { /* Feature */
653  0x0801, 0x0006, 0x0000, 0x0000, 0x0007, 0x8001, 0x8001, 0x0005,
654  0x8000
655 };
656 
657 static 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 
673 static 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 
695 static void create_patch( const char *filename )
696 {
697  IStorage *stg = NULL, *stg1 = NULL, *stg2 = NULL;
698  WCHAR *filenameW;
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 
741 static 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 
916 uninstall:
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 
930 cleanup:
931  DeleteFileA( msifile );
932  DeleteFileA( mspfile );
933  DeleteFileA( "msitest\\patch.txt" );
934  RemoveDirectoryA( "msitest" );
935 }
936 
937 static 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);
951  DeleteFileA( mspfile );
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 );
963  DeleteFileA( mspfile );
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 
975  DeleteFileA( msifile );
976  DeleteFileA( mspfile );
977 }
978 
979 static 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 
986  sprintf( query, fmt, table, entry );
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 
1000 static 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 
1020 static 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 
1049 static 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  {
1067  DWORD size = MAX_PATH;
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 
1081 static 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 
1104  create_patch( mspfile );
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 
1262 uninstall:
1263  r = MsiInstallProductA( msifile, "REMOVE=ALL" );
1264  ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
1265 
1266 cleanup:
1267  DeleteFileA( msifile );
1268  DeleteFileA( mspfile );
1269  DeleteFileA( "msitest\\patch.txt" );
1270  RemoveDirectoryA( "msitest" );
1271 }
1272 
1273 static 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 
1294  create_patch( mspfile );
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 
1357 uninstall:
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 
1369 cleanup:
1370  DeleteFileA( msifile );
1371  DeleteFileA( mspfile );
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 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static const struct table_data table_transform2_data[]
Definition: patch.c:657
INTERNETFEATURELIST feature
Definition: misc.c:1719
#define MSIDBOPEN_READONLY
Definition: msiquery.h:66
static UINT find_entryW(MSIHANDLE hdb, const WCHAR *table, const WCHAR *entry)
Definition: patch.c:1000
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3257
UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
Definition: msiquery.c:518
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static const WCHAR p_name8[]
Definition: patch.c:366
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:4027
static BOOL is_process_limited(void)
Definition: patch.c:170
UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
Definition: package.c:1669
enum _TOKEN_ELEVATION_TYPE TOKEN_ELEVATION_TYPE
static const WCHAR p_name0[]
Definition: patch.c:354
static BOOL get_program_files_dir(char *buf, char *buf2)
Definition: patch.c:187
#define CloseHandle
Definition: compat.h:739
Definition: compat.h:2298
#define ERROR_SUCCESS
Definition: deptool.c:10
enum tagMSIINSTALLCONTEXT MSIINSTALLCONTEXT
Definition: action.c:49
UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField, char *szValue, DWORD *pcchValue)
Definition: record.c:403
#define MSIDBOPEN_PATCHFILE
Definition: msiquery.h:79
static UINT find_entry(MSIHANDLE hdb, const char *table, const char *entry)
Definition: patch.c:979
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define strcasecmp
Definition: fake.h:9
UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
Definition: msi.c:200
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static const char t1_data3[]
Definition: patch.c:472
#define TRUE
Definition: types.h:120
GLsizei const GLchar ** path
Definition: glext.h:7234
static const char p_data4[]
Definition: patch.c:391
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
int WINAPI MsiRecordGetInteger(MSIHANDLE handle, UINT iField)
Definition: record.c:237
#define CP_ACP
Definition: compat.h:109
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
static const WCHAR t2_name5[]
Definition: patch.c:530
#define STGM_CREATE
Definition: objbase.h:926
static const WCHAR t2_data2[]
Definition: patch.c:550
UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue)
Definition: msi.c:1592
static char CURR_DIR[MAX_PATH]
Definition: patch.c:45
static const char file_dat[]
Definition: patch.c:70
static INSTALLTYPE
Definition: patch.c:34
static void test_patch_registration(void)
Definition: patch.c:1273
#define GET_PROC(mod, func)
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define todo_wine
Definition: custom.c:79
#define MSIDBOPEN_DIRECT
Definition: msiquery.h:68
GLuint buffer
Definition: glext.h:5915
#define create_file(name, size)
Definition: patch.c:230
INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
Definition: msi.c:2284
#define INVALID_FILE_SIZE
Definition: winbase.h:548
static const WCHAR msifileW[]
Definition: patch.c:42
#define FILE_BEGIN
Definition: compat.h:761
static void write_file(const char *filename, const char *data, DWORD data_size)
Definition: patch.c:265
const char * filename
Definition: ioapi.h:137
static const WCHAR p_name5[]
Definition: patch.c:359
static const WCHAR mspfileW[]
Definition: patch.c:43
static INT get_integer(MSIHANDLE hdb, UINT field, const char *query)
Definition: patch.c:1020
const void * data
Definition: patch.c:440
UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz)
Definition: package.c:2313
static const char component_dat[]
Definition: patch.c:85
int32_t INT
Definition: typedefs.h:58
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR t2_data1[]
Definition: patch.c:547
static void create_database(const char *filename, const struct msi_table *tables, UINT num_tables)
Definition: patch.c:316
static const WCHAR filenameW[]
Definition: amstream.c:41
#define sprintf(buf, format,...)
Definition: sprintf.c:55
UINT WINAPI MsiViewClose(MSIHANDLE hView)
Definition: msiquery.c:469
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static DWORD *static DWORD
Definition: patch.c:37
const char * data
Definition: patch.c:135
START_TEST(patch)
Definition: patch.c:1376
#define ADD_TABLE(x)
Definition: patch.c:139
#define L(x)
Definition: ntvdm.h:50
static const struct table_data table_patch_data[]
Definition: patch.c:444
static const WCHAR t2_data4[]
Definition: patch.c:562
static const WCHAR t2_data8[]
Definition: patch.c:577
unsigned char * LPBYTE
Definition: typedefs.h:53
MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
Definition: package.c:1674
#define FALSE
Definition: types.h:117
UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb, const char *szQuery, MSIHANDLE *phView)
Definition: msiquery.c:88
unsigned int BOOL
Definition: ntddk_ex.h:94
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 GENERIC_WRITE
Definition: nt_native.h:90
unsigned long MSIHANDLE
Definition: winemsi.idl:24
#define ERROR_PATCH_PACKAGE_INVALID
Definition: winerror.h:994
static const char p_data2[]
Definition: patch.c:377
GLenum condition
Definition: glext.h:9255
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
static const WCHAR t1_data0[]
Definition: patch.c:461
static const WCHAR t2_data6[]
Definition: patch.c:568
static const struct msi_table tables[]
Definition: patch.c:141
static char COMMON_FILES_DIR[MAX_PATH]
Definition: patch.c:47
#define STGM_WRITE
Definition: objbase.h:918
static LPCSTR
Definition: patch.c:34
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
static const WCHAR p_name1[]
Definition: patch.c:355
static const char media_dat[]
Definition: patch.c:64
static const WCHAR t2_name0[]
Definition: patch.c:525
static const char condition_dat[]
Definition: patch.c:126
static void test_simple_patch(void)
Definition: patch.c:741
static char * get_string(MSIHANDLE hdb, UINT field, const char *query)
Definition: patch.c:1049
static const char feature_comp_dat[]
Definition: patch.c:99
#define OPEN_EXISTING
Definition: compat.h:775
static void create_patch(const char *filename)
Definition: patch.c:695
LPCWSTR name
Definition: patch.c:439
static DWORD get_pf_file_size(const char *filename)
Definition: patch.c:246
static LPSTR
Definition: patch.c:35
UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct)
Definition: msi.c:82
static const WCHAR t2_data11[]
Definition: patch.c:649
DWORD size
Definition: patch.c:441
static const char property_dat[]
Definition: patch.c:51
static const char t2_data9[]
Definition: patch.c:608
__u8 media
Definition: mkdosfs.c:367
static const WCHAR p_name7[]
Definition: patch.c:364
GLsizeiptr size
Definition: glext.h:5919
static const WCHAR t1_name3[]
Definition: patch.c:457
static const WCHAR t2_data10[]
Definition: patch.c:646
#define TOKEN_QUERY
Definition: setypes.h:924
__wchar_t WCHAR
Definition: xmlstorage.h:180
static const WCHAR t2_name6[]
Definition: patch.c:531
static const char t2_data7[]
Definition: patch.c:571
static void init_function_pointers(void)
Definition: patch.c:154
Definition: parser.c:43
UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
Definition: msiquery.c:404
LONG HRESULT
Definition: typedefs.h:79
static const WCHAR p_data0[]
Definition: patch.c:370
#define ERROR_UNKNOWN_PRODUCT
Definition: winerror.h:963
static void create_file_data(const char *filename, const char *data, DWORD size)
Definition: patch.c:212
#define STGM_DIRECT
Definition: objbase.h:914
UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, const char *szValue)
Definition: suminfo.c:937
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
static const WCHAR t2_name3[]
Definition: patch.c:528
#define MSIDBOPEN_CREATE
Definition: msiquery.h:69
static const WCHAR t1_name1[]
Definition: patch.c:455
static void set_suminfo(const WCHAR *filename)
Definition: patch.c:274
static const WCHAR t2_name8[]
Definition: patch.c:534
unsigned long DWORD
Definition: ntddk_ex.h:95
static const WCHAR t2_name1[]
Definition: patch.c:526
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
static const WCHAR t2_name9[]
Definition: patch.c:535
static const WCHAR t2_name4[]
Definition: patch.c:529
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static const char directory_dat[]
Definition: patch.c:77
static void test_MsiOpenDatabase(void)
Definition: patch.c:937
static const WCHAR p_data3[]
Definition: patch.c:380
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const WCHAR p_name4[]
Definition: patch.c:358
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
uint32_t entry
Definition: isohybrid.c:63
GLenum GLsizei len
Definition: glext.h:6722
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8636
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
GLenum mode
Definition: glext.h:6217
#define STGM_READWRITE
Definition: objbase.h:919
static const WCHAR t2_data12[]
Definition: patch.c:652
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
#define broken(x)
Definition: _sntprintf.h:21
static const WCHAR t2_name10[]
Definition: patch.c:538
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, const char *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:584
static const WCHAR t1_name0[]
Definition: patch.c:454
#define S_OK
Definition: intsafe.h:52
#define CREATE_ALWAYS
Definition: disk.h:72
static const struct table_data table_transform1_data[]
Definition: patch.c:518
static const WCHAR t2_name2[]
Definition: patch.c:527
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
static const WCHAR p_name6[]
Definition: patch.c:360
static const WCHAR p_data5[]
Definition: patch.c:407
#define ERROR_OPEN_FAILED
Definition: winerror.h:184
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
BYTE * data
#define ARRAY_SIZE(a)
Definition: main.h:24
static const char p_data6[]
Definition: patch.c:410
UINT WINAPI MsiDatabaseCommit(MSIHANDLE hdb)
Definition: msiquery.c:963
static const WCHAR t2_name12[]
Definition: patch.c:541
#define ok(value,...)
Definition: atltest.h:57
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
static const WCHAR t1_data2[]
Definition: patch.c:467
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
static char PROG_FILES_DIR[MAX_PATH]
Definition: patch.c:46
static BOOL delete_pf(const char *rel_path, BOOL is_file)
Definition: patch.c:232
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:296
const char * filename
Definition: patch.c:134
static const WCHAR p_name3[]
Definition: patch.c:357
static const WCHAR t2_data3[]
Definition: patch.c:559
#define MultiByteToWideChar
Definition: compat.h:110
#define skip(...)
Definition: atltest.h:64
UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE handle)
Definition: suminfo.c:1222
static const char * mspfile
Definition: patch.c:41
int size
Definition: patch.c:136
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, LPCWSTR szQuery, MSIHANDLE *phView)
Definition: msiquery.c:236
Definition: name.c:38
#define INSTALLPROPERTY_LOCALPACKAGEA
Definition: msi.h:342
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:413
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
static const WCHAR t2_data5[]
Definition: patch.c:565
char * cleanup(char *str)
Definition: wpickclick.c:99
#define malloc
Definition: debug_ros.c:4
static MSIINSTALLCONTEXT
Definition: patch.c:35
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:853
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static const WCHAR t2_name7[]
Definition: patch.c:533
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
static const char * msifile
Definition: patch.c:40
UINT WINAPI MsiApplyPatchA(LPCSTR szPatchPackage, LPCSTR szInstallPackage, INSTALLTYPE eInstallType, LPCSTR szCommandLine)
Definition: msi.c:288
static const WCHAR t2_name11[]
Definition: patch.c:540
UINT WINAPI MsiGetProductInfoA(LPCSTR szProduct, LPCSTR szAttribute, LPSTR szBuffer, LPDWORD pcchValueBuf)
Definition: msi.c:1256
static const char feature_dat[]
Definition: patch.c:92
#define win_skip
Definition: test.h:160
GLenum query
Definition: glext.h:7781
static const WCHAR p_name2[]
Definition: patch.c:356
static void test_system_tables(void)
Definition: patch.c:1081
Definition: dsound.c:943
static const WCHAR p_data1[]
Definition: patch.c:374
static const WCHAR t1_name2[]
Definition: patch.c:456
#define RegCloseKey(hKey)
Definition: registry.h:47
#define SetFilePointer
Definition: compat.h:743
static const char install_exec_seq_dat[]
Definition: patch.c:106
static void write_tables(IStorage *stg, const struct table_data *tables, UINT num_tables)
Definition: patch.c:673
static const char t1_data1[]
Definition: patch.c:464
static const WCHAR t2_data0[]
Definition: patch.c:543
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
static UINT(WINAPI *pMsiApplyPatchA)(LPCSTR
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
static DWORD *static MSIINSTALLCONTEXT LPDWORD
Definition: patch.c:37
Definition: fci.c:126
char temp_path[MAX_PATH]
Definition: mspatcha.c:123