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