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