blob: e81fcb7d5a42d321d08bdc1e10de94b51acd7f59 [file] [log] [blame]
Aric Stewart401bd3f2004-06-28 20:34:35 +00001/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
Aric Stewartc6689522005-06-17 20:56:55 +00004 * Copyright 2004,2005 Aric Stewart for CodeWeavers
Aric Stewart401bd3f2004-06-28 20:34:35 +00005 *
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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Aric Stewart401bd3f2004-06-28 20:34:35 +000019 */
20
21/*
Mike McCormack6e2bca32004-07-04 00:25:00 +000022 * Pages I need
Aric Stewart401bd3f2004-06-28 20:34:35 +000023 *
24http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/installexecutesequence_table.asp
25
26http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/standard_actions_reference.asp
Aric Stewart401bd3f2004-06-28 20:34:35 +000027 */
28
29#include <stdarg.h>
Aric Stewart401bd3f2004-06-28 20:34:35 +000030
Francois Gouget486d0202004-10-07 03:06:48 +000031#define COBJMACROS
32
Aric Stewart401bd3f2004-06-28 20:34:35 +000033#include "windef.h"
34#include "winbase.h"
35#include "winerror.h"
36#include "winreg.h"
James Hawkins9bc12ad2006-10-19 15:49:54 -070037#include "winsvc.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000038#include "wine/debug.h"
Aric Stewartb6bc6aa2005-02-24 12:47:43 +000039#include "msidefs.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000040#include "msipriv.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000041#include "winuser.h"
42#include "shlobj.h"
43#include "wine/unicode.h"
Steven Edwards98efef12005-04-11 16:10:33 +000044#include "winver.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000045
Aric Stewartbd1bbc12005-01-03 20:00:13 +000046#define REG_PROGRESS_VALUE 13200
47#define COMPONENT_PROGRESS_VALUE 24000
Aric Stewart401bd3f2004-06-28 20:34:35 +000048
Aric Stewart401bd3f2004-06-28 20:34:35 +000049WINE_DEFAULT_DEBUG_CHANNEL(msi);
50
51/*
52 * Prototypes
53 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +000054static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
55static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
Aric Stewartf8f64402005-03-24 19:03:45 +000056static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
Aric Stewart90c57392005-01-31 16:23:12 +000057
Aric Stewart401bd3f2004-06-28 20:34:35 +000058/*
59 * consts and values used
60 */
Juan Lang014ad3b2005-03-01 10:41:52 +000061static const WCHAR c_colon[] = {'C',':','\\',0};
Aric Stewartc6689522005-06-17 20:56:55 +000062
Mike McCormack9ba8ba32005-10-30 19:04:26 +000063static const WCHAR szCreateFolders[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000064 {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000065static const WCHAR szCostFinalize[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000066 {'C','o','s','t','F','i','n','a','l','i','z','e',0};
Aric Stewartc6689522005-06-17 20:56:55 +000067const WCHAR szInstallFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000068 {'I','n','s','t','a','l','l','F','i','l','e','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +000069const WCHAR szDuplicateFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000070 {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000071static const WCHAR szWriteRegistryValues[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000072 {'W','r','i','t','e','R','e','g','i','s','t','r','y',
73 'V','a','l','u','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000074static const WCHAR szCostInitialize[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000075 {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000076static const WCHAR szFileCost[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000077 {'F','i','l','e','C','o','s','t',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000078static const WCHAR szInstallInitialize[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000079 {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000080static const WCHAR szInstallValidate[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000081 {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000082static const WCHAR szLaunchConditions[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000083 {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000084static const WCHAR szProcessComponents[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000085 {'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000086static const WCHAR szRegisterTypeLibraries[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000087 {'R','e','g','i','s','t','e','r','T','y','p','e',
88 'L','i','b','r','a','r','i','e','s',0};
Aric Stewartdb982e22005-06-16 15:51:44 +000089const WCHAR szRegisterClassInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000090 {'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
Aric Stewartdb982e22005-06-16 15:51:44 +000091const WCHAR szRegisterProgIdInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000092 {'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000093static const WCHAR szCreateShortcuts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000094 {'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000095static const WCHAR szPublishProduct[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000096 {'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000097static const WCHAR szWriteIniValues[] =
Aric Stewart8e233e92005-03-01 11:45:19 +000098 {'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +000099static const WCHAR szSelfRegModules[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000100 {'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000101static const WCHAR szPublishFeatures[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000102 {'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000103static const WCHAR szRegisterProduct[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000104 {'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000105static const WCHAR szInstallExecute[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000106 {'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000107static const WCHAR szInstallExecuteAgain[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000108 {'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
109 'A','g','a','i','n',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000110static const WCHAR szInstallFinalize[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000111 {'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000112static const WCHAR szForceReboot[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000113 {'F','o','r','c','e','R','e','b','o','o','t',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000114static const WCHAR szResolveSource[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000115 {'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
Alexandre Julliardb79a53e2006-06-12 13:39:59 +0200116static const WCHAR szAppSearch[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000117 {'A','p','p','S','e','a','r','c','h',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000118static const WCHAR szAllocateRegistrySpace[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000119 {'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y',
120 'S','p','a','c','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000121static const WCHAR szBindImage[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000122 {'B','i','n','d','I','m','a','g','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000123static const WCHAR szCCPSearch[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000124 {'C','C','P','S','e','a','r','c','h',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000125static const WCHAR szDeleteServices[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000126 {'D','e','l','e','t','e','S','e','r','v','i','c','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000127static const WCHAR szDisableRollback[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000128 {'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000129static const WCHAR szExecuteAction[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000130 {'E','x','e','c','u','t','e','A','c','t','i','o','n',0};
Aric Stewartdb982e22005-06-16 15:51:44 +0000131const WCHAR szFindRelatedProducts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000132 {'F','i','n','d','R','e','l','a','t','e','d',
133 'P','r','o','d','u','c','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000134static const WCHAR szInstallAdminPackage[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000135 {'I','n','s','t','a','l','l','A','d','m','i','n',
136 'P','a','c','k','a','g','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000137static const WCHAR szInstallSFPCatalogFile[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000138 {'I','n','s','t','a','l','l','S','F','P','C','a','t','a','l','o','g',
139 'F','i','l','e',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000140static const WCHAR szIsolateComponents[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000141 {'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000142const WCHAR szMigrateFeatureStates[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000143 {'M','i','g','r','a','t','e','F','e','a','t','u','r','e',
144 'S','t','a','t','e','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000145const WCHAR szMoveFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000146 {'M','o','v','e','F','i','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000147static const WCHAR szMsiPublishAssemblies[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000148 {'M','s','i','P','u','b','l','i','s','h',
149 'A','s','s','e','m','b','l','i','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000150static const WCHAR szMsiUnpublishAssemblies[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000151 {'M','s','i','U','n','p','u','b','l','i','s','h',
152 'A','s','s','e','m','b','l','i','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000153static const WCHAR szInstallODBC[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000154 {'I','n','s','t','a','l','l','O','D','B','C',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000155static const WCHAR szInstallServices[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000156 {'I','n','s','t','a','l','l','S','e','r','v','i','c','e','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000157const WCHAR szPatchFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000158 {'P','a','t','c','h','F','i','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000159static const WCHAR szPublishComponents[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000160 {'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000161static const WCHAR szRegisterComPlus[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000162 {'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
Aric Stewartdb982e22005-06-16 15:51:44 +0000163const WCHAR szRegisterExtensionInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000164 {'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n',
165 'I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000166static const WCHAR szRegisterFonts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000167 {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
Aric Stewartdb982e22005-06-16 15:51:44 +0000168const WCHAR szRegisterMIMEInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000169 {'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000170static const WCHAR szRegisterUser[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000171 {'R','e','g','i','s','t','e','r','U','s','e','r',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000172const WCHAR szRemoveDuplicateFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000173 {'R','e','m','o','v','e','D','u','p','l','i','c','a','t','e',
174 'F','i','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000175static const WCHAR szRemoveEnvironmentStrings[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000176 {'R','e','m','o','v','e','E','n','v','i','r','o','n','m','e','n','t',
177 'S','t','r','i','n','g','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000178const WCHAR szRemoveExistingProducts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000179 {'R','e','m','o','v','e','E','x','i','s','t','i','n','g',
180 'P','r','o','d','u','c','t','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000181const WCHAR szRemoveFiles[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000182 {'R','e','m','o','v','e','F','i','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000183static const WCHAR szRemoveFolders[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000184 {'R','e','m','o','v','e','F','o','l','d','e','r','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000185static const WCHAR szRemoveIniValues[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000186 {'R','e','m','o','v','e','I','n','i','V','a','l','u','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000187static const WCHAR szRemoveODBC[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000188 {'R','e','m','o','v','e','O','D','B','C',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000189static const WCHAR szRemoveRegistryValues[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000190 {'R','e','m','o','v','e','R','e','g','i','s','t','r','y',
191 'V','a','l','u','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000192static const WCHAR szRemoveShortcuts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000193 {'R','e','m','o','v','e','S','h','o','r','t','c','u','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000194static const WCHAR szRMCCPSearch[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000195 {'R','M','C','C','P','S','e','a','r','c','h',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000196static const WCHAR szScheduleReboot[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000197 {'S','c','h','e','d','u','l','e','R','e','b','o','o','t',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000198static const WCHAR szSelfUnregModules[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000199 {'S','e','l','f','U','n','r','e','g','M','o','d','u','l','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000200static const WCHAR szSetODBCFolders[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000201 {'S','e','t','O','D','B','C','F','o','l','d','e','r','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000202static const WCHAR szStartServices[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000203 {'S','t','a','r','t','S','e','r','v','i','c','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000204static const WCHAR szStopServices[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000205 {'S','t','o','p','S','e','r','v','i','c','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000206static const WCHAR szUnpublishComponents[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000207 {'U','n','p','u','b','l','i','s','h',
208 'C','o','m','p','o','n','e','n','t','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000209static const WCHAR szUnpublishFeatures[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000210 {'U','n','p','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000211const WCHAR szUnregisterClassInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000212 {'U','n','r','e','g','i','s','t','e','r','C','l','a','s','s',
213 'I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000214static const WCHAR szUnregisterComPlus[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000215 {'U','n','r','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000216const WCHAR szUnregisterExtensionInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000217 {'U','n','r','e','g','i','s','t','e','r',
218 'E','x','t','e','n','s','i','o','n','I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000219static const WCHAR szUnregisterFonts[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000220 {'U','n','r','e','g','i','s','t','e','r','F','o','n','t','s',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000221const WCHAR szUnregisterMIMEInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000222 {'U','n','r','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
Aric Stewartc6689522005-06-17 20:56:55 +0000223const WCHAR szUnregisterProgIdInfo[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000224 {'U','n','r','e','g','i','s','t','e','r','P','r','o','g','I','d',
225 'I','n','f','o',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000226static const WCHAR szUnregisterTypeLibraries[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000227 {'U','n','r','e','g','i','s','t','e','r','T','y','p','e',
228 'L','i','b','r','a','r','i','e','s',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000229static const WCHAR szValidateProductID[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000230 {'V','a','l','i','d','a','t','e','P','r','o','d','u','c','t','I','D',0};
Mike McCormack9ba8ba32005-10-30 19:04:26 +0000231static const WCHAR szWriteEnvironmentStrings[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000232 {'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t',
233 'S','t','r','i','n','g','s',0};
Aric Stewart90c57392005-01-31 16:23:12 +0000234
Mike McCormack3b955152005-09-28 18:10:44 +0000235/* action handlers */
236typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
237
Aric Stewart90c57392005-01-31 16:23:12 +0000238struct _actions {
239 LPCWSTR action;
240 STANDARDACTIONHANDLER handler;
241};
242
Mike McCormack3b955152005-09-28 18:10:44 +0000243static struct _actions StandardActions[];
Aric Stewart90c57392005-01-31 16:23:12 +0000244
Aric Stewart2703d712005-06-20 15:33:10 +0000245
246/********************************************************
247 * helper functions
248 ********************************************************/
249
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000250static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
Aric Stewartd2c395a2004-07-06 18:48:15 +0000251{
Aric Stewartd2c395a2004-07-06 18:48:15 +0000252 static const WCHAR Query_t[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000253 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000254 '`','A','c','t','i','o', 'n','T','e','x','t','`',' ',
255 'W','H','E','R','E', ' ','`','A','c','t','i','o','n','`',' ','=',
256 ' ','\'','%','s','\'',0};
Robert Shearmand679bc52006-01-23 17:30:31 +0100257 MSIRECORD * row;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000258
Mike McCormack0b352c72005-06-02 10:29:57 +0000259 row = MSI_QueryGetRecord( package->db, Query_t, action );
260 if (!row)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000261 return;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000262 MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
263 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000264}
265
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000266static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
Aric Stewartd2c395a2004-07-06 18:48:15 +0000267 UINT rc)
268{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000269 MSIRECORD * row;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000270 static const WCHAR template_s[]=
Aric Stewart8e233e92005-03-01 11:45:19 +0000271 {'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ',
272 '%','s', '.',0};
Aric Stewartd2c395a2004-07-06 18:48:15 +0000273 static const WCHAR template_e[]=
Aric Stewart8e233e92005-03-01 11:45:19 +0000274 {'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ',
275 '%','s', '.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ',
276 '%','i','.',0};
Aric Stewartd2c395a2004-07-06 18:48:15 +0000277 static const WCHAR format[] =
Aric Stewart8e233e92005-03-01 11:45:19 +0000278 {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
Aric Stewartd2c395a2004-07-06 18:48:15 +0000279 WCHAR message[1024];
280 WCHAR timet[0x100];
281
282 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
283 if (start)
284 sprintfW(message,template_s,timet,action);
285 else
286 sprintfW(message,template_e,timet,action,rc);
287
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000288 row = MSI_CreateRecord(1);
289 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000290
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000291 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row);
292 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000293}
294
Mike McCormacke3452222005-09-28 15:12:32 +0000295static UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine )
296{
297 LPCWSTR ptr,ptr2;
298 BOOL quote;
299 DWORD len;
300 LPWSTR prop = NULL, val = NULL;
301
302 if (!szCommandLine)
303 return ERROR_SUCCESS;
304
305 ptr = szCommandLine;
306
307 while (*ptr)
308 {
309 if (*ptr==' ')
310 {
311 ptr++;
312 continue;
313 }
314
315 TRACE("Looking at %s\n",debugstr_w(ptr));
316
317 ptr2 = strchrW(ptr,'=');
318 if (!ptr2)
319 {
320 ERR("command line contains unknown string : %s\n", debugstr_w(ptr));
321 break;
322 }
323
324 quote = FALSE;
325
326 len = ptr2-ptr;
327 prop = msi_alloc((len+1)*sizeof(WCHAR));
328 memcpy(prop,ptr,len*sizeof(WCHAR));
329 prop[len]=0;
330 ptr2++;
331
332 len = 0;
333 ptr = ptr2;
334 while (*ptr && (quote || (!quote && *ptr!=' ')))
335 {
336 if (*ptr == '"')
337 quote = !quote;
338 ptr++;
339 len++;
340 }
341
342 if (*ptr2=='"')
343 {
344 ptr2++;
345 len -= 2;
346 }
347 val = msi_alloc((len+1)*sizeof(WCHAR));
348 memcpy(val,ptr2,len*sizeof(WCHAR));
349 val[len] = 0;
350
351 if (lstrlenW(prop) > 0)
352 {
353 TRACE("Found commandline property (%s) = (%s)\n",
354 debugstr_w(prop), debugstr_w(val));
355 MSI_SetPropertyW(package,prop,val);
356 }
357 msi_free(val);
358 msi_free(prop);
359 }
360
361 return ERROR_SUCCESS;
362}
363
Mike McCormack965a72a2005-10-26 12:06:21 +0000364
365static LPWSTR* msi_split_string( LPCWSTR str, WCHAR sep )
366{
Andrew Talbot2e372c02006-09-17 08:52:49 +0100367 LPCWSTR pc;
Mike McCormack965a72a2005-10-26 12:06:21 +0000368 LPWSTR p, *ret = NULL;
369 UINT count = 0;
370
371 if (!str)
372 return ret;
373
374 /* count the number of substrings */
Andrew Talbot2e372c02006-09-17 08:52:49 +0100375 for ( pc = str, count = 0; pc; count++ )
Mike McCormack965a72a2005-10-26 12:06:21 +0000376 {
Andrew Talbot2e372c02006-09-17 08:52:49 +0100377 pc = strchrW( pc, sep );
378 if (pc)
379 pc++;
Mike McCormack965a72a2005-10-26 12:06:21 +0000380 }
381
382 /* allocate space for an array of substring pointers and the substrings */
383 ret = msi_alloc( (count+1) * sizeof (LPWSTR) +
384 (lstrlenW(str)+1) * sizeof(WCHAR) );
385 if (!ret)
386 return ret;
387
388 /* copy the string and set the pointers */
389 p = (LPWSTR) &ret[count+1];
390 lstrcpyW( p, str );
391 for( count = 0; (ret[count] = p); count++ )
392 {
393 p = strchrW( p, sep );
394 if (p)
395 *p++ = 0;
396 }
397
398 return ret;
399}
400
401static UINT msi_apply_substorage_transform( MSIPACKAGE *package,
402 MSIDATABASE *patch_db, LPCWSTR name )
403{
404 UINT ret = ERROR_FUNCTION_FAILED;
405 IStorage *stg = NULL;
406 HRESULT r;
407
408 TRACE("%p %s\n", package, debugstr_w(name) );
409
410 if (*name++ != ':')
411 {
412 ERR("expected a colon in %s\n", debugstr_w(name));
413 return ERROR_FUNCTION_FAILED;
414 }
415
416 r = IStorage_OpenStorage( patch_db->storage, name, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg );
417 if (SUCCEEDED(r))
418 {
Mike McCormackf8fef6e2005-10-26 13:56:33 +0000419 ret = msi_table_apply_transform( package->db, stg );
Mike McCormack965a72a2005-10-26 12:06:21 +0000420 IStorage_Release( stg );
421 ret = ERROR_SUCCESS;
422 }
423 else
424 ERR("failed to open substorage %s\n", debugstr_w(name));
425
426 return ret;
427}
428
429static UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si )
430{
431 static const WCHAR szProdID[] = { 'P','r','o','d','u','c','t','I','D',0 };
432 LPWSTR guid_list, *guids, product_id;
433 UINT i, ret = ERROR_FUNCTION_FAILED;
434
435 product_id = msi_dup_property( package, szProdID );
436 if (!product_id)
437 {
438 /* FIXME: the property ProductID should be written into the DB somewhere */
439 ERR("no product ID to check\n");
440 return ERROR_SUCCESS;
441 }
442
443 guid_list = msi_suminfo_dup_string( si, PID_TEMPLATE );
444 guids = msi_split_string( guid_list, ';' );
445 for ( i = 0; guids[i] && ret != ERROR_SUCCESS; i++ )
446 {
447 if (!lstrcmpW( guids[i], product_id ))
448 ret = ERROR_SUCCESS;
449 }
450 msi_free( guids );
451 msi_free( guid_list );
452 msi_free( product_id );
453
454 return ret;
455}
456
457static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db )
458{
459 MSISUMMARYINFO *si;
460 LPWSTR str, *substorage;
461 UINT i, r = ERROR_SUCCESS;
462
463 si = MSI_GetSummaryInformationW( patch_db, 0 );
464 if (!si)
465 return ERROR_FUNCTION_FAILED;
466
467 msi_check_patch_applicable( package, si );
468
469 /* enumerate the substorage */
470 str = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
471 substorage = msi_split_string( str, ';' );
472 for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ )
473 r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
474 msi_free( substorage );
475 msi_free( str );
476
477 /* FIXME: parse the sources in PID_REVNUMBER and do something with them... */
478
479 msiobj_release( &si->hdr );
480
481 return r;
482}
483
484static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
485{
486 MSIDATABASE *patch_db = NULL;
487 UINT r;
488
489 TRACE("%p %s\n", package, debugstr_w( file ) );
490
491 /* FIXME:
492 * We probably want to make sure we only open a patch collection here.
493 * Patch collections (.msp) and databases (.msi) have different GUIDs
494 * but currently MSI_OpenDatabaseW will accept both.
495 */
496 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &patch_db );
497 if ( r != ERROR_SUCCESS )
498 {
499 ERR("failed to open patch collection %s\n", debugstr_w( file ) );
500 return r;
501 }
502
503 msi_parse_patch_summary( package, patch_db );
504 msiobj_release( &patch_db->hdr );
505
506 return ERROR_SUCCESS;
507}
508
509/* get the PATCH property, and apply all the patches it specifies */
510static UINT msi_apply_patches( MSIPACKAGE *package )
511{
512 static const WCHAR szPatch[] = { 'P','A','T','C','H',0 };
513 LPWSTR patch_list, *patches;
514 UINT i, r = ERROR_SUCCESS;
515
516 patch_list = msi_dup_property( package, szPatch );
517
518 TRACE("patches to be applied: %s\n", debugstr_w( patch_list ) );
519
520 patches = msi_split_string( patch_list, ';' );
521 for( i=0; patches && patches[i] && r == ERROR_SUCCESS; i++ )
522 r = msi_apply_patch_package( package, patches[i] );
523
524 msi_free( patches );
525 msi_free( patch_list );
526
527 return r;
528}
529
Mike McCormacke534e772006-01-04 14:51:25 +0100530static UINT msi_apply_transforms( MSIPACKAGE *package )
531{
532 static const WCHAR szTransforms[] = {
533 'T','R','A','N','S','F','O','R','M','S',0 };
534 LPWSTR xform_list, *xforms;
535 UINT i, r = ERROR_SUCCESS;
536
537 xform_list = msi_dup_property( package, szTransforms );
538 xforms = msi_split_string( xform_list, ';' );
539
540 for( i=0; xforms && xforms[i] && r == ERROR_SUCCESS; i++ )
541 {
542 if (xforms[i][0] == ':')
543 r = msi_apply_substorage_transform( package, package->db, &xforms[i][1] );
544 else
545 r = MSI_DatabaseApplyTransformW( package->db, xforms[i], 0 );
546 }
547
548 msi_free( xforms );
549 msi_free( xform_list );
550
551 return r;
552}
553
Aric Stewart401bd3f2004-06-28 20:34:35 +0000554/****************************************************
555 * TOP level entry points
556 *****************************************************/
557
Mike McCormack61f24a42005-09-30 10:32:41 +0000558UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
559 LPCWSTR szCommandLine )
Aric Stewart401bd3f2004-06-28 20:34:35 +0000560{
Aric Stewart401bd3f2004-06-28 20:34:35 +0000561 UINT rc;
Aric Stewartf8f64402005-03-24 19:03:45 +0000562 BOOL ui = FALSE;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000563 static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
Aric Stewart6269f002005-01-17 13:40:39 +0000564 static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
565 static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
566
567 MSI_SetPropertyW(package, szAction, szInstall);
Aric Stewart9cd707d2005-05-27 19:24:22 +0000568
Mike McCormack3a940112006-04-19 02:29:03 +0900569 package->script = msi_alloc_zero(sizeof(MSISCRIPT));
Aric Stewart401bd3f2004-06-28 20:34:35 +0000570
Aric Stewartc9802932005-06-30 20:45:43 +0000571 package->script->InWhatSequence = SEQUENCE_INSTALL;
572
Aric Stewarte95136b2004-06-29 03:44:01 +0000573 if (szPackagePath)
574 {
Mike McCormackba8200b2004-12-22 15:25:30 +0000575 LPWSTR p, check, path;
Aric Stewarte95136b2004-06-29 03:44:01 +0000576
Mike McCormack95dea492005-03-16 11:31:35 +0000577 path = strdupW(szPackagePath);
Mike McCormackba8200b2004-12-22 15:25:30 +0000578 p = strrchrW(path,'\\');
Aric Stewarte95136b2004-06-29 03:44:01 +0000579 if (p)
580 {
581 p++;
582 *p=0;
583 }
Aric Stewartc1e5c4a2005-02-08 14:26:49 +0000584 else
585 {
Mike McCormackee034ba2005-09-20 11:59:14 +0000586 msi_free(path);
587 path = msi_alloc(MAX_PATH*sizeof(WCHAR));
Aric Stewartc1e5c4a2005-02-08 14:26:49 +0000588 GetCurrentDirectoryW(MAX_PATH,path);
589 strcatW(path,cszbs);
590 }
Aric Stewarte95136b2004-06-29 03:44:01 +0000591
Mike McCormack062ad502005-09-15 15:04:08 +0000592 check = msi_dup_property( package, cszSourceDir );
Aric Stewartd0c971a2004-12-22 18:15:50 +0000593 if (!check)
Mike McCormackba8200b2004-12-22 15:25:30 +0000594 MSI_SetPropertyW(package, cszSourceDir, path);
James Hawkinsc5075432006-10-10 13:39:50 -0700595
James Hawkins3797e6c2006-10-13 14:08:52 -0700596 check = msi_dup_property( package, cszSOURCEDIR );
597 if (!check)
598 MSI_SetPropertyW(package, cszSOURCEDIR, path);
599
Mike McCormack4047cc72006-10-17 16:11:42 +0900600 msi_free( package->PackagePath );
James Hawkinsc5075432006-10-10 13:39:50 -0700601 package->PackagePath = path;
602
Mike McCormackee034ba2005-09-20 11:59:14 +0000603 msi_free(check);
Aric Stewarte95136b2004-06-29 03:44:01 +0000604 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000605
Mike McCormacke3452222005-09-28 15:12:32 +0000606 msi_parse_command_line( package, szCommandLine );
Mike McCormack74f0de92005-09-29 10:32:39 +0000607
Mike McCormacke534e772006-01-04 14:51:25 +0100608 msi_apply_transforms( package );
Mike McCormack965a72a2005-10-26 12:06:21 +0000609 msi_apply_patches( package );
610
Mike McCormack74f0de92005-09-29 10:32:39 +0000611 if ( msi_get_property_int(package, szUILevel, 0) >= INSTALLUILEVEL_REDUCED )
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000612 {
Mike McCormack74f0de92005-09-29 10:32:39 +0000613 package->script->InWhatSequence |= SEQUENCE_UI;
614 rc = ACTION_ProcessUISequence(package);
615 ui = TRUE;
616 if (rc == ERROR_SUCCESS)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000617 {
Mike McCormack74f0de92005-09-29 10:32:39 +0000618 package->script->InWhatSequence |= SEQUENCE_EXEC;
619 rc = ACTION_ProcessExecSequence(package,TRUE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000620 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000621 }
622 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000623 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewart6b16f292005-01-27 11:12:56 +0000624
625 if (rc == -1)
626 {
627 /* install was halted but should be considered a success */
628 rc = ERROR_SUCCESS;
629 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000630
Aric Stewart9cd707d2005-05-27 19:24:22 +0000631 package->script->CurrentlyScripting= FALSE;
632
Aric Stewart09d35c32004-12-27 19:00:26 +0000633 /* process the ending type action */
634 if (rc == ERROR_SUCCESS)
Aric Stewartf8f64402005-03-24 19:03:45 +0000635 ACTION_PerformActionSequence(package,-1,ui);
Aric Stewart6b16f292005-01-27 11:12:56 +0000636 else if (rc == ERROR_INSTALL_USEREXIT)
Aric Stewartf8f64402005-03-24 19:03:45 +0000637 ACTION_PerformActionSequence(package,-2,ui);
Aric Stewart6b16f292005-01-27 11:12:56 +0000638 else if (rc == ERROR_INSTALL_SUSPEND)
Aric Stewartf8f64402005-03-24 19:03:45 +0000639 ACTION_PerformActionSequence(package,-4,ui);
Aric Stewart9cd707d2005-05-27 19:24:22 +0000640 else /* failed */
641 ACTION_PerformActionSequence(package,-3,ui);
Aric Stewart54c67dd2005-01-25 20:17:09 +0000642
643 /* finish up running custom actions */
644 ACTION_FinishCustomActions(package);
Aric Stewart09d35c32004-12-27 19:00:26 +0000645
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000646 return rc;
647}
648
Aric Stewartf8f64402005-03-24 19:03:45 +0000649static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
Aric Stewart09d35c32004-12-27 19:00:26 +0000650{
Mike McCormack0b352c72005-06-02 10:29:57 +0000651 UINT rc = ERROR_SUCCESS;
Aric Stewart09d35c32004-12-27 19:00:26 +0000652 MSIRECORD * row = 0;
Aric Stewart8e233e92005-03-01 11:45:19 +0000653 static const WCHAR ExecSeqQuery[] =
654 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000655 '`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
656 'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
657 '`','S','e','q','u','e','n','c','e','`',' ', '=',' ','%','i',0};
Aric Stewart09d35c32004-12-27 19:00:26 +0000658
Aric Stewartf8f64402005-03-24 19:03:45 +0000659 static const WCHAR UISeqQuery[] =
660 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000661 '`','I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
662 '`', ' ', 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',
Aric Stewartf8f64402005-03-24 19:03:45 +0000663 ' ', '=',' ','%','i',0};
664
665 if (UI)
Mike McCormack0b352c72005-06-02 10:29:57 +0000666 row = MSI_QueryGetRecord(package->db, UISeqQuery, seq);
Aric Stewartf8f64402005-03-24 19:03:45 +0000667 else
Mike McCormack0b352c72005-06-02 10:29:57 +0000668 row = MSI_QueryGetRecord(package->db, ExecSeqQuery, seq);
Aric Stewart09d35c32004-12-27 19:00:26 +0000669
Mike McCormack0b352c72005-06-02 10:29:57 +0000670 if (row)
Aric Stewart09d35c32004-12-27 19:00:26 +0000671 {
Mike McCormack20806c72005-06-07 21:34:05 +0000672 LPCWSTR action, cond;
673
Aric Stewart09d35c32004-12-27 19:00:26 +0000674 TRACE("Running the actions\n");
675
Aric Stewart09d35c32004-12-27 19:00:26 +0000676 /* check conditions */
Mike McCormack20806c72005-06-07 21:34:05 +0000677 cond = MSI_RecordGetString(row,2);
678 if (cond)
Aric Stewart09d35c32004-12-27 19:00:26 +0000679 {
Mike McCormack20806c72005-06-07 21:34:05 +0000680 /* this is a hack to skip errors in the condition code */
681 if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
682 goto end;
Aric Stewart09d35c32004-12-27 19:00:26 +0000683 }
684
Mike McCormack20806c72005-06-07 21:34:05 +0000685 action = MSI_RecordGetString(row,1);
686 if (!action)
Aric Stewart09d35c32004-12-27 19:00:26 +0000687 {
Mike McCormack20806c72005-06-07 21:34:05 +0000688 ERR("failed to fetch action\n");
689 rc = ERROR_FUNCTION_FAILED;
Aric Stewart09d35c32004-12-27 19:00:26 +0000690 goto end;
691 }
692
Aric Stewartf8f64402005-03-24 19:03:45 +0000693 if (UI)
Mike McCormack20806c72005-06-07 21:34:05 +0000694 rc = ACTION_PerformUIAction(package,action);
Aric Stewartf8f64402005-03-24 19:03:45 +0000695 else
Mike McCormack20806c72005-06-07 21:34:05 +0000696 rc = ACTION_PerformAction(package,action,FALSE);
Aric Stewart09d35c32004-12-27 19:00:26 +0000697end:
Mike McCormack0b352c72005-06-02 10:29:57 +0000698 msiobj_release(&row->hdr);
Aric Stewart09d35c32004-12-27 19:00:26 +0000699 }
700 else
701 rc = ERROR_SUCCESS;
702
703 return rc;
704}
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000705
Aric Stewart2703d712005-06-20 15:33:10 +0000706typedef struct {
707 MSIPACKAGE* package;
708 BOOL UI;
709} iterate_action_param;
710
711static UINT ITERATE_Actions(MSIRECORD *row, LPVOID param)
712{
713 iterate_action_param *iap= (iterate_action_param*)param;
714 UINT rc;
715 LPCWSTR cond, action;
716
717 action = MSI_RecordGetString(row,1);
718 if (!action)
719 {
720 ERR("Error is retrieving action name\n");
721 return ERROR_FUNCTION_FAILED;
722 }
723
724 /* check conditions */
725 cond = MSI_RecordGetString(row,2);
726 if (cond)
727 {
728 /* this is a hack to skip errors in the condition code */
729 if (MSI_EvaluateConditionW(iap->package, cond) == MSICONDITION_FALSE)
730 {
731 TRACE("Skipping action: %s (condition is false)\n",
732 debugstr_w(action));
733 return ERROR_SUCCESS;
734 }
735 }
736
737 if (iap->UI)
738 rc = ACTION_PerformUIAction(iap->package,action);
739 else
740 rc = ACTION_PerformAction(iap->package,action,FALSE);
741
Mike McCormack4f634a32005-07-06 15:44:51 +0000742 msi_dialog_check_messages( NULL );
743
744 if (iap->package->CurrentInstallState != ERROR_SUCCESS )
745 rc = iap->package->CurrentInstallState;
746
Aric Stewart2703d712005-06-20 15:33:10 +0000747 if (rc == ERROR_FUNCTION_NOT_CALLED)
748 rc = ERROR_SUCCESS;
749
750 if (rc != ERROR_SUCCESS)
Mike McCormack558abec2005-10-27 12:39:28 +0000751 ERR("Execution halted, action %s returned %i\n", debugstr_w(action), rc);
Aric Stewart2703d712005-06-20 15:33:10 +0000752
753 return rc;
754}
755
Mike McCormackd34b1c22005-09-21 10:55:23 +0000756UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode )
757{
758 MSIQUERY * view;
759 UINT r;
760 static const WCHAR query[] =
761 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
762 '`','%','s','`',
763 ' ','W','H','E','R','E',' ',
764 '`','S','e','q','u','e','n','c','e','`',' ',
765 '>',' ','0',' ','O','R','D','E','R',' ','B','Y',' ',
766 '`','S','e','q','u','e','n','c','e','`',0};
767 iterate_action_param iap;
768
769 /*
770 * FIXME: probably should be checking UILevel in the
771 * ACTION_PerformUIAction/ACTION_PerformAction
772 * rather than saving the UI level here. Those
773 * two functions can be merged too.
774 */
775 iap.package = package;
776 iap.UI = TRUE;
777
778 TRACE("%p %s %i\n", package, debugstr_w(szTable), iSequenceMode );
779
780 r = MSI_OpenQuery( package->db, &view, query, szTable );
781 if (r == ERROR_SUCCESS)
782 {
783 r = MSI_IterateRecords( view, NULL, ITERATE_Actions, &iap );
784 msiobj_release(&view->hdr);
785 }
786
787 return r;
788}
789
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000790static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000791{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000792 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000793 UINT rc;
Aric Stewart8e233e92005-03-01 11:45:19 +0000794 static const WCHAR ExecSeqQuery[] =
795 {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000796 '`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
797 'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
798 '`','S','e','q','u','e','n','c','e','`',' ', '>',' ','%','i',' ',
Aric Stewart8e233e92005-03-01 11:45:19 +0000799 'O','R','D','E','R',' ', 'B','Y',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000800 '`','S','e','q','u','e','n','c','e','`',0 };
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000801 MSIRECORD * row = 0;
Aric Stewart8e233e92005-03-01 11:45:19 +0000802 static const WCHAR IVQuery[] =
Aric Stewart98e38082005-05-20 09:40:42 +0000803 {'S','E','L','E','C','T',' ','`','S','e','q','u','e','n','c','e','`',
804 ' ', 'F','R','O','M',' ','`','I','n','s','t','a','l','l',
805 'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e','`',' ',
806 'W','H','E','R','E',' ','`','A','c','t','i','o','n','`',' ','=',
807 ' ','\'', 'I','n','s','t','a','l','l',
808 'V','a','l','i','d','a','t','e','\'', 0};
Mike McCormack9db0e072004-12-22 15:05:07 +0000809 INT seq = 0;
Aric Stewart2703d712005-06-20 15:33:10 +0000810 iterate_action_param iap;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000811
Aric Stewart2703d712005-06-20 15:33:10 +0000812 iap.package = package;
813 iap.UI = FALSE;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +0000814
Aric Stewart9cd707d2005-05-27 19:24:22 +0000815 if (package->script->ExecuteSequenceRun)
Aric Stewartb6bc6aa2005-02-24 12:47:43 +0000816 {
817 TRACE("Execute Sequence already Run\n");
818 return ERROR_SUCCESS;
819 }
820
Aric Stewart9cd707d2005-05-27 19:24:22 +0000821 package->script->ExecuteSequenceRun = TRUE;
Aric Stewart2703d712005-06-20 15:33:10 +0000822
Mike McCormack9db0e072004-12-22 15:05:07 +0000823 /* get the sequence number */
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000824 if (UIran)
825 {
Mike McCormack0b352c72005-06-02 10:29:57 +0000826 row = MSI_QueryGetRecord(package->db, IVQuery);
827 if( !row )
828 return ERROR_FUNCTION_FAILED;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000829 seq = MSI_RecordGetInteger(row,1);
830 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000831 }
Mike McCormack9db0e072004-12-22 15:05:07 +0000832
Mike McCormack0c238852005-01-21 16:19:11 +0000833 rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000834 if (rc == ERROR_SUCCESS)
835 {
Aric Stewart2703d712005-06-20 15:33:10 +0000836 TRACE("Running the actions\n");
Aric Stewart401bd3f2004-06-28 20:34:35 +0000837
Aric Stewart2703d712005-06-20 15:33:10 +0000838 rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, &iap);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000839 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000840 }
841
Aric Stewart401bd3f2004-06-28 20:34:35 +0000842 return rc;
843}
844
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000845static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000846{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000847 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000848 UINT rc;
Aric Stewart8e233e92005-03-01 11:45:19 +0000849 static const WCHAR ExecSeqQuery [] =
850 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000851 '`','I','n','s','t','a','l','l',
852 'U','I','S','e','q','u','e','n','c','e','`',
853 ' ','W','H','E','R','E',' ',
854 '`','S','e','q','u','e','n','c','e','`',' ',
Aric Stewart8e233e92005-03-01 11:45:19 +0000855 '>',' ','0',' ','O','R','D','E','R',' ','B','Y',' ',
Aric Stewart98e38082005-05-20 09:40:42 +0000856 '`','S','e','q','u','e','n','c','e','`',0};
Aric Stewart2703d712005-06-20 15:33:10 +0000857 iterate_action_param iap;
858
859 iap.package = package;
860 iap.UI = TRUE;
861
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000862 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000863
864 if (rc == ERROR_SUCCESS)
865 {
Francois Gouget0edbaf72005-11-10 12:14:56 +0000866 TRACE("Running the actions\n");
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000867
Aric Stewart2703d712005-06-20 15:33:10 +0000868 rc = MSI_IterateRecords(view, NULL, ITERATE_Actions, &iap);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000869 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000870 }
871
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000872 return rc;
873}
874
Aric Stewart401bd3f2004-06-28 20:34:35 +0000875/********************************************************
876 * ACTION helper functions and functions that perform the actions
877 *******************************************************/
Aric Stewart9cd707d2005-05-27 19:24:22 +0000878static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
879 UINT* rc, BOOL force )
Aric Stewart3f318602005-02-01 18:46:26 +0000880{
881 BOOL ret = FALSE;
Aric Stewart9cd707d2005-05-27 19:24:22 +0000882 BOOL run = force;
Aric Stewart3f318602005-02-01 18:46:26 +0000883 int i;
Aric Stewart9cd707d2005-05-27 19:24:22 +0000884
885 if (!run && !package->script->CurrentlyScripting)
886 run = TRUE;
887
888 if (!run)
889 {
890 if (strcmpW(action,szInstallFinalize) == 0 ||
891 strcmpW(action,szInstallExecute) == 0 ||
892 strcmpW(action,szInstallExecuteAgain) == 0)
893 run = TRUE;
894 }
895
Aric Stewart3f318602005-02-01 18:46:26 +0000896 i = 0;
897 while (StandardActions[i].action != NULL)
898 {
899 if (strcmpW(StandardActions[i].action, action)==0)
900 {
Aric Stewart9cd707d2005-05-27 19:24:22 +0000901 if (!run)
Aric Stewartd6ecf582005-02-02 09:29:30 +0000902 {
Aric Stewart9cd707d2005-05-27 19:24:22 +0000903 ui_actioninfo(package, action, TRUE, 0);
904 *rc = schedule_action(package,INSTALL_SCRIPT,action);
905 ui_actioninfo(package, action, FALSE, *rc);
Aric Stewartd6ecf582005-02-02 09:29:30 +0000906 }
907 else
908 {
Aric Stewart9cd707d2005-05-27 19:24:22 +0000909 ui_actionstart(package, action);
910 if (StandardActions[i].handler)
911 {
912 *rc = StandardActions[i].handler(package);
913 }
914 else
915 {
Mike McCormack54a28912005-09-06 09:23:18 +0000916 FIXME("unhandled standard action %s\n",debugstr_w(action));
Aric Stewart9cd707d2005-05-27 19:24:22 +0000917 *rc = ERROR_SUCCESS;
918 }
Aric Stewartd6ecf582005-02-02 09:29:30 +0000919 }
Aric Stewart3f318602005-02-01 18:46:26 +0000920 ret = TRUE;
921 break;
922 }
923 i++;
924 }
925 return ret;
926}
927
Mike McCormackf9acfe62005-06-07 20:29:51 +0000928static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
929 UINT* rc, BOOL force )
Aric Stewart3f318602005-02-01 18:46:26 +0000930{
931 BOOL ret=FALSE;
932 UINT arc;
933
Aric Stewart9cd707d2005-05-27 19:24:22 +0000934 arc = ACTION_CustomAction(package,action, force);
Aric Stewart3f318602005-02-01 18:46:26 +0000935
936 if (arc != ERROR_CALL_NOT_IMPLEMENTED)
937 {
938 *rc = arc;
939 ret = TRUE;
940 }
941 return ret;
942}
Aric Stewart401bd3f2004-06-28 20:34:35 +0000943
944/*
Francois Gougetda8b3dd2005-01-26 21:09:04 +0000945 * A lot of actions are really important even if they don't do anything
946 * explicit... Lots of properties are set at the beginning of the installation
947 * CostFinalize does a bunch of work to translate the directories and such
Aric Stewart401bd3f2004-06-28 20:34:35 +0000948 *
Mike McCormack6e2bca32004-07-04 00:25:00 +0000949 * But until I get write access to the database that is hard, so I am going to
Aric Stewart401bd3f2004-06-28 20:34:35 +0000950 * hack it to see if I can get something to run.
951 */
Aric Stewart9cd707d2005-05-27 19:24:22 +0000952UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force)
Aric Stewart401bd3f2004-06-28 20:34:35 +0000953{
Aric Stewartd2c395a2004-07-06 18:48:15 +0000954 UINT rc = ERROR_SUCCESS;
Aric Stewart3f318602005-02-01 18:46:26 +0000955 BOOL handled;
Aric Stewart401bd3f2004-06-28 20:34:35 +0000956
957 TRACE("Performing action (%s)\n",debugstr_w(action));
958
Aric Stewart9cd707d2005-05-27 19:24:22 +0000959 handled = ACTION_HandleStandardAction(package, action, &rc, force);
Aric Stewart7d3e5972004-07-04 00:36:58 +0000960
Aric Stewart3f318602005-02-01 18:46:26 +0000961 if (!handled)
Aric Stewart9cd707d2005-05-27 19:24:22 +0000962 handled = ACTION_HandleCustomAction(package, action, &rc, force);
Aric Stewart3f318602005-02-01 18:46:26 +0000963
Aric Stewart90c57392005-01-31 16:23:12 +0000964 if (!handled)
965 {
Mike McCormack54a28912005-09-06 09:23:18 +0000966 FIXME("unhandled msi action %s\n",debugstr_w(action));
Aric Stewart3f318602005-02-01 18:46:26 +0000967 rc = ERROR_FUNCTION_NOT_CALLED;
968 }
Aric Stewart7d3e5972004-07-04 00:36:58 +0000969
Aric Stewart3f318602005-02-01 18:46:26 +0000970 return rc;
971}
972
973UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
974{
975 UINT rc = ERROR_SUCCESS;
976 BOOL handled = FALSE;
977
978 TRACE("Performing action (%s)\n",debugstr_w(action));
979
Aric Stewart9cd707d2005-05-27 19:24:22 +0000980 handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
Aric Stewart3f318602005-02-01 18:46:26 +0000981
982 if (!handled)
Aric Stewart9cd707d2005-05-27 19:24:22 +0000983 handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
Aric Stewart3f318602005-02-01 18:46:26 +0000984
Mike McCormack4f634a32005-07-06 15:44:51 +0000985 if( !handled && ACTION_DialogBox(package,action) == ERROR_SUCCESS )
986 handled = TRUE;
Mike McCormack34d4a022005-02-09 13:24:31 +0000987
Aric Stewart3f318602005-02-01 18:46:26 +0000988 if (!handled)
989 {
Mike McCormack54a28912005-09-06 09:23:18 +0000990 FIXME("unhandled msi action %s\n",debugstr_w(action));
Aric Stewart3f318602005-02-01 18:46:26 +0000991 rc = ERROR_FUNCTION_NOT_CALLED;
Aric Stewart90c57392005-01-31 16:23:12 +0000992 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000993
Aric Stewartd2c395a2004-07-06 18:48:15 +0000994 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +0000995}
996
Aric Stewart2274ff12005-06-21 20:03:46 +0000997
998/*
999 * Actual Action Handlers
1000 */
1001
1002static UINT ITERATE_CreateFolders(MSIRECORD *row, LPVOID param)
1003{
1004 MSIPACKAGE *package = (MSIPACKAGE*)param;
1005 LPCWSTR dir;
1006 LPWSTR full_path;
1007 MSIRECORD *uirow;
1008 MSIFOLDER *folder;
1009
1010 dir = MSI_RecordGetString(row,1);
1011 if (!dir)
1012 {
Francois Gouget0edbaf72005-11-10 12:14:56 +00001013 ERR("Unable to get folder id\n");
Aric Stewart2274ff12005-06-21 20:03:46 +00001014 return ERROR_SUCCESS;
1015 }
1016
1017 full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);
1018 if (!full_path)
1019 {
1020 ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
1021 return ERROR_SUCCESS;
1022 }
1023
1024 TRACE("Folder is %s\n",debugstr_w(full_path));
1025
1026 /* UI stuff */
1027 uirow = MSI_CreateRecord(1);
1028 MSI_RecordSetStringW(uirow,1,full_path);
1029 ui_actiondata(package,szCreateFolders,uirow);
1030 msiobj_release( &uirow->hdr );
1031
1032 if (folder->State == 0)
1033 create_full_pathW(full_path);
1034
1035 folder->State = 3;
1036
Mike McCormackee034ba2005-09-20 11:59:14 +00001037 msi_free(full_path);
Aric Stewart2274ff12005-06-21 20:03:46 +00001038 return ERROR_SUCCESS;
1039}
1040
Mike McCormack03b4dbb2005-10-28 09:39:29 +00001041/* FIXME: probably should merge this with the above function */
1042static UINT msi_create_directory( MSIPACKAGE* package, LPCWSTR dir )
1043{
1044 UINT rc = ERROR_SUCCESS;
1045 MSIFOLDER *folder;
1046 LPWSTR install_path;
1047
1048 install_path = resolve_folder(package, dir, FALSE, FALSE, &folder);
1049 if (!install_path)
1050 return ERROR_FUNCTION_FAILED;
1051
1052 /* create the path */
1053 if (folder->State == 0)
1054 {
1055 create_full_pathW(install_path);
1056 folder->State = 2;
1057 }
1058 msi_free(install_path);
1059
1060 return rc;
1061}
Aric Stewart2274ff12005-06-21 20:03:46 +00001062
Mike McCormack9c845852005-10-29 11:29:17 +00001063UINT msi_create_component_directories( MSIPACKAGE *package )
1064{
1065 MSICOMPONENT *comp;
1066
1067 /* create all the folders required by the components are going to install */
1068 LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
1069 {
Mike McCormackd693f462005-10-29 11:36:48 +00001070 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
Mike McCormack9c845852005-10-29 11:29:17 +00001071 continue;
1072 msi_create_directory( package, comp->Directory );
1073 }
1074
1075 return ERROR_SUCCESS;
1076}
1077
Aric Stewart401bd3f2004-06-28 20:34:35 +00001078/*
1079 * Also we cannot enable/disable components either, so for now I am just going
Mike McCormack6e2bca32004-07-04 00:25:00 +00001080 * to do all the directories for all the components.
Aric Stewart401bd3f2004-06-28 20:34:35 +00001081 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001082static UINT ACTION_CreateFolders(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001083{
Aric Stewart8e233e92005-03-01 11:45:19 +00001084 static const WCHAR ExecSeqQuery[] =
Aric Stewart98e38082005-05-20 09:40:42 +00001085 {'S','E','L','E','C','T',' ',
1086 '`','D','i','r','e','c','t','o','r','y','_','`',
Aric Stewart8e233e92005-03-01 11:45:19 +00001087 ' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00001088 '`','C','r','e','a','t','e','F','o','l','d','e','r','`',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00001089 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001090 MSIQUERY *view;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001091
Mike McCormack03b4dbb2005-10-28 09:39:29 +00001092 /* create all the empty folders specified in the CreateFolder table */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001093 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001094 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00001095 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001096
Aric Stewart2274ff12005-06-21 20:03:46 +00001097 rc = MSI_IterateRecords(view, NULL, ITERATE_CreateFolders, package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001098 msiobj_release(&view->hdr);
Mike McCormack03b4dbb2005-10-28 09:39:29 +00001099
Mike McCormack9c845852005-10-29 11:29:17 +00001100 msi_create_component_directories( package );
Mike McCormack03b4dbb2005-10-28 09:39:29 +00001101
Aric Stewart401bd3f2004-06-28 20:34:35 +00001102 return rc;
1103}
1104
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001105static UINT load_component( MSIRECORD *row, LPVOID param )
Aric Stewartbdb29552004-07-04 00:32:48 +00001106{
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001107 MSIPACKAGE *package = param;
Mike McCormack38d67a42005-08-22 09:15:23 +00001108 MSICOMPONENT *comp;
Aric Stewartbdb29552004-07-04 00:32:48 +00001109
Mike McCormackee034ba2005-09-20 11:59:14 +00001110 comp = msi_alloc_zero( sizeof(MSICOMPONENT) );
Mike McCormack38d67a42005-08-22 09:15:23 +00001111 if (!comp)
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001112 return ERROR_FUNCTION_FAILED;
1113
1114 list_add_tail( &package->components, &comp->entry );
Mike McCormack38d67a42005-08-22 09:15:23 +00001115
Aric Stewartbdb29552004-07-04 00:32:48 +00001116 /* fill in the data */
Mike McCormack51c66182005-10-27 12:36:12 +00001117 comp->Component = msi_dup_record_field( row, 1 );
Aric Stewartbdb29552004-07-04 00:32:48 +00001118
Mike McCormackefcc1ec2005-09-12 12:07:15 +00001119 TRACE("Loading Component %s\n", debugstr_w(comp->Component));
Aric Stewartbdb29552004-07-04 00:32:48 +00001120
Mike McCormack51c66182005-10-27 12:36:12 +00001121 comp->ComponentId = msi_dup_record_field( row, 2 );
1122 comp->Directory = msi_dup_record_field( row, 3 );
Mike McCormack38d67a42005-08-22 09:15:23 +00001123 comp->Attributes = MSI_RecordGetInteger(row,4);
Mike McCormack51c66182005-10-27 12:36:12 +00001124 comp->Condition = msi_dup_record_field( row, 5 );
1125 comp->KeyPath = msi_dup_record_field( row, 6 );
Aric Stewartbdb29552004-07-04 00:32:48 +00001126
James Hawkinsd893cb72006-09-20 19:55:01 -07001127 comp->Installed = INSTALLSTATE_UNKNOWN;
1128 comp->Action = INSTALLSTATE_UNKNOWN;
1129 comp->ActionRequest = INSTALLSTATE_UNKNOWN;
Aric Stewartfbdd7092004-12-27 19:06:22 +00001130
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001131 return ERROR_SUCCESS;
1132}
Aric Stewartbdb29552004-07-04 00:32:48 +00001133
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001134static UINT load_all_components( MSIPACKAGE *package )
1135{
1136 static const WCHAR query[] = {
1137 'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ',
1138 '`','C','o','m','p','o','n','e','n','t','`',0 };
1139 MSIQUERY *view;
1140 UINT r;
1141
1142 if (!list_empty(&package->components))
1143 return ERROR_SUCCESS;
1144
1145 r = MSI_DatabaseOpenViewW( package->db, query, &view );
1146 if (r != ERROR_SUCCESS)
1147 return r;
1148
1149 r = MSI_IterateRecords(view, NULL, load_component, package);
1150 msiobj_release(&view->hdr);
1151 return r;
Aric Stewartbdb29552004-07-04 00:32:48 +00001152}
1153
Aric Stewart04598242005-06-23 16:43:24 +00001154typedef struct {
1155 MSIPACKAGE *package;
Mike McCormack1da28582005-08-22 14:09:17 +00001156 MSIFEATURE *feature;
Aric Stewart04598242005-06-23 16:43:24 +00001157} _ilfs;
1158
Mike McCormack38d67a42005-08-22 09:15:23 +00001159static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001160{
1161 ComponentList *cl;
1162
Mike McCormackee034ba2005-09-20 11:59:14 +00001163 cl = msi_alloc( sizeof (*cl) );
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001164 if ( !cl )
1165 return ERROR_NOT_ENOUGH_MEMORY;
Mike McCormack38d67a42005-08-22 09:15:23 +00001166 cl->component = comp;
Mike McCormack1da28582005-08-22 14:09:17 +00001167 list_add_tail( &feature->Components, &cl->entry );
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001168
1169 return ERROR_SUCCESS;
1170}
1171
James Hawkins545d0e72006-09-20 19:59:19 -07001172static UINT add_feature_child( MSIFEATURE *parent, MSIFEATURE *child )
1173{
1174 FeatureList *fl;
1175
1176 fl = msi_alloc( sizeof(*fl) );
1177 if ( !fl )
1178 return ERROR_NOT_ENOUGH_MEMORY;
1179 fl->feature = child;
1180 list_add_tail( &parent->Children, &fl->entry );
1181
1182 return ERROR_SUCCESS;
1183}
1184
Aric Stewart04598242005-06-23 16:43:24 +00001185static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
1186{
1187 _ilfs* ilfs= (_ilfs*)param;
1188 LPCWSTR component;
Mike McCormack38d67a42005-08-22 09:15:23 +00001189 MSICOMPONENT *comp;
Aric Stewart04598242005-06-23 16:43:24 +00001190
1191 component = MSI_RecordGetString(row,1);
1192
1193 /* check to see if the component is already loaded */
Mike McCormack38d67a42005-08-22 09:15:23 +00001194 comp = get_loaded_component( ilfs->package, component );
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001195 if (!comp)
Aric Stewart04598242005-06-23 16:43:24 +00001196 {
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001197 ERR("unknown component %s\n", debugstr_w(component));
1198 return ERROR_FUNCTION_FAILED;
Aric Stewart04598242005-06-23 16:43:24 +00001199 }
1200
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001201 add_feature_component( ilfs->feature, comp );
1202 comp->Enabled = TRUE;
Aric Stewart04598242005-06-23 16:43:24 +00001203
1204 return ERROR_SUCCESS;
1205}
1206
James Hawkins545d0e72006-09-20 19:59:19 -07001207static MSIFEATURE *find_feature_by_name( MSIPACKAGE *package, LPCWSTR name )
1208{
1209 MSIFEATURE *feature;
1210
1211 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
1212 {
1213 if ( !lstrcmpW( feature->Feature, name ) )
1214 return feature;
1215 }
1216
1217 return NULL;
1218}
1219
Aric Stewart04598242005-06-23 16:43:24 +00001220static UINT load_feature(MSIRECORD * row, LPVOID param)
1221{
1222 MSIPACKAGE* package = (MSIPACKAGE*)param;
Mike McCormack1da28582005-08-22 14:09:17 +00001223 MSIFEATURE* feature;
Aric Stewart8e233e92005-03-01 11:45:19 +00001224 static const WCHAR Query1[] =
Aric Stewart98e38082005-05-20 09:40:42 +00001225 {'S','E','L','E','C','T',' ',
1226 '`','C','o','m','p','o','n','e','n','t','_','`',
1227 ' ','F','R','O','M',' ','`','F','e','a','t','u','r','e',
1228 'C','o','m','p','o','n','e','n','t','s','`',' ',
1229 'W','H','E','R','E',' ',
1230 '`','F','e', 'a','t','u','r','e','_','`',' ','=','\'','%','s','\'',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001231 MSIQUERY * view;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001232 UINT rc;
Aric Stewart04598242005-06-23 16:43:24 +00001233 _ilfs ilfs;
1234
Aric Stewartbdb29552004-07-04 00:32:48 +00001235 /* fill in the data */
1236
Mike McCormackee034ba2005-09-20 11:59:14 +00001237 feature = msi_alloc_zero( sizeof (MSIFEATURE) );
Mike McCormack1da28582005-08-22 14:09:17 +00001238 if (!feature)
1239 return ERROR_NOT_ENOUGH_MEMORY;
Aric Stewartbdb29552004-07-04 00:32:48 +00001240
James Hawkins545d0e72006-09-20 19:59:19 -07001241 list_init( &feature->Children );
Mike McCormack1da28582005-08-22 14:09:17 +00001242 list_init( &feature->Components );
Aric Stewartbdb29552004-07-04 00:32:48 +00001243
Mike McCormack51c66182005-10-27 12:36:12 +00001244 feature->Feature = msi_dup_record_field( row, 1 );
Aric Stewartbdb29552004-07-04 00:32:48 +00001245
Mike McCormack1da28582005-08-22 14:09:17 +00001246 TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
Aric Stewartbdb29552004-07-04 00:32:48 +00001247
Mike McCormack51c66182005-10-27 12:36:12 +00001248 feature->Feature_Parent = msi_dup_record_field( row, 2 );
1249 feature->Title = msi_dup_record_field( row, 3 );
1250 feature->Description = msi_dup_record_field( row, 4 );
Aric Stewartbdb29552004-07-04 00:32:48 +00001251
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001252 if (!MSI_RecordIsNull(row,5))
Mike McCormack1da28582005-08-22 14:09:17 +00001253 feature->Display = MSI_RecordGetInteger(row,5);
Aric Stewartbdb29552004-07-04 00:32:48 +00001254
Mike McCormack1da28582005-08-22 14:09:17 +00001255 feature->Level= MSI_RecordGetInteger(row,6);
Mike McCormack51c66182005-10-27 12:36:12 +00001256 feature->Directory = msi_dup_record_field( row, 7 );
Mike McCormack1da28582005-08-22 14:09:17 +00001257 feature->Attributes = MSI_RecordGetInteger(row,8);
Aric Stewartfbdd7092004-12-27 19:06:22 +00001258
James Hawkinsca5c1102006-09-20 19:53:56 -07001259 feature->Installed = INSTALLSTATE_UNKNOWN;
Mike McCormack1da28582005-08-22 14:09:17 +00001260 feature->Action = INSTALLSTATE_UNKNOWN;
1261 feature->ActionRequest = INSTALLSTATE_UNKNOWN;
1262
1263 list_add_tail( &package->features, &feature->entry );
Aric Stewartbdb29552004-07-04 00:32:48 +00001264
1265 /* load feature components */
1266
Mike McCormack1da28582005-08-22 14:09:17 +00001267 rc = MSI_OpenQuery( package->db, &view, Query1, feature->Feature );
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001268 if (rc != ERROR_SUCCESS)
Aric Stewart04598242005-06-23 16:43:24 +00001269 return ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00001270
Mike McCormack1da28582005-08-22 14:09:17 +00001271 ilfs.package = package;
1272 ilfs.feature = feature;
1273
Aric Stewart04598242005-06-23 16:43:24 +00001274 MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001275 msiobj_release(&view->hdr);
Aric Stewart04598242005-06-23 16:43:24 +00001276
1277 return ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00001278}
1279
James Hawkins545d0e72006-09-20 19:59:19 -07001280static UINT find_feature_children(MSIRECORD * row, LPVOID param)
1281{
1282 MSIPACKAGE* package = (MSIPACKAGE*)param;
1283 MSIFEATURE *parent, *child;
1284
1285 child = find_feature_by_name( package, MSI_RecordGetString( row, 1 ) );
1286 if (!child)
1287 return ERROR_FUNCTION_FAILED;
1288
1289 if (!child->Feature_Parent)
1290 return ERROR_SUCCESS;
1291
1292 parent = find_feature_by_name( package, child->Feature_Parent );
1293 if (!parent)
1294 return ERROR_FUNCTION_FAILED;
1295
1296 add_feature_child( parent, child );
1297 return ERROR_SUCCESS;
1298}
1299
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001300static UINT load_all_features( MSIPACKAGE *package )
1301{
1302 static const WCHAR query[] = {
1303 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
1304 '`','F','e','a','t','u','r','e','`',' ','O','R','D','E','R',
1305 ' ','B','Y',' ','`','D','i','s','p','l','a','y','`',0};
1306 MSIQUERY *view;
1307 UINT r;
1308
1309 if (!list_empty(&package->features))
1310 return ERROR_SUCCESS;
1311
1312 r = MSI_DatabaseOpenViewW( package->db, query, &view );
1313 if (r != ERROR_SUCCESS)
1314 return r;
1315
1316 r = MSI_IterateRecords( view, NULL, load_feature, package );
James Hawkins545d0e72006-09-20 19:59:19 -07001317 if (r != ERROR_SUCCESS)
1318 return r;
1319
1320 r = MSI_IterateRecords( view, NULL, find_feature_children, package );
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001321 msiobj_release( &view->hdr );
James Hawkins545d0e72006-09-20 19:59:19 -07001322
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001323 return r;
1324}
1325
Mike McCormackc1513be2006-03-21 19:40:36 +09001326static LPWSTR folder_split_path(LPWSTR p, WCHAR ch)
1327{
1328 if (!p)
1329 return p;
1330 p = strchrW(p, ch);
1331 if (!p)
1332 return p;
1333 *p = 0;
1334 return p+1;
1335}
1336
Aric Stewart04598242005-06-23 16:43:24 +00001337static UINT load_file(MSIRECORD *row, LPVOID param)
Aric Stewartc5a14432005-05-18 17:46:12 +00001338{
Aric Stewart04598242005-06-23 16:43:24 +00001339 MSIPACKAGE* package = (MSIPACKAGE*)param;
Aric Stewart09b0aba2005-06-09 20:30:59 +00001340 LPCWSTR component;
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001341 MSIFILE *file;
Aric Stewartc5a14432005-05-18 17:46:12 +00001342
1343 /* fill in the data */
1344
Mike McCormackee034ba2005-09-20 11:59:14 +00001345 file = msi_alloc_zero( sizeof (MSIFILE) );
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001346 if (!file)
1347 return ERROR_NOT_ENOUGH_MEMORY;
Aric Stewartc5a14432005-05-18 17:46:12 +00001348
Mike McCormack51c66182005-10-27 12:36:12 +00001349 file->File = msi_dup_record_field( row, 1 );
Aric Stewartc5a14432005-05-18 17:46:12 +00001350
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001351 component = MSI_RecordGetString( row, 2 );
1352 file->Component = get_loaded_component( package, component );
Aric Stewart09b0aba2005-06-09 20:30:59 +00001353
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001354 if (!file->Component)
Aric Stewart09b0aba2005-06-09 20:30:59 +00001355 ERR("Unfound Component %s\n",debugstr_w(component));
Aric Stewartc5a14432005-05-18 17:46:12 +00001356
Mike McCormack51c66182005-10-27 12:36:12 +00001357 file->FileName = msi_dup_record_field( row, 3 );
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001358 reduce_to_longfilename( file->FileName );
Aric Stewartc5a14432005-05-18 17:46:12 +00001359
Mike McCormack51c66182005-10-27 12:36:12 +00001360 file->ShortName = msi_dup_record_field( row, 3 );
Mike McCormackc1513be2006-03-21 19:40:36 +09001361 file->LongName = strdupW( folder_split_path(file->ShortName, '|'));
Aric Stewartc5a14432005-05-18 17:46:12 +00001362
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001363 file->FileSize = MSI_RecordGetInteger( row, 4 );
Mike McCormack51c66182005-10-27 12:36:12 +00001364 file->Version = msi_dup_record_field( row, 5 );
1365 file->Language = msi_dup_record_field( row, 6 );
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001366 file->Attributes = MSI_RecordGetInteger( row, 7 );
1367 file->Sequence = MSI_RecordGetInteger( row, 8 );
Aric Stewartc5a14432005-05-18 17:46:12 +00001368
Mike McCormackdded8fb2005-11-02 10:56:42 +00001369 file->state = msifs_invalid;
Aric Stewartc5a14432005-05-18 17:46:12 +00001370
James Hawkinsf84fa0c2006-08-07 11:37:49 -07001371 /* if the compressed bits are not set in the file attributes,
1372 * then read the information from the package word count property
1373 */
James Hawkins98d14862006-07-31 11:15:52 -07001374 if (file->Attributes & msidbFileAttributesCompressed)
1375 {
James Hawkinsf84fa0c2006-08-07 11:37:49 -07001376 file->IsCompressed = TRUE;
1377 }
1378 else if (file->Attributes & msidbFileAttributesNoncompressed)
1379 {
1380 file->IsCompressed = FALSE;
1381 }
1382 else
1383 {
1384 file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED;
1385 }
1386
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001387 TRACE("File Loaded (%s)\n",debugstr_w(file->File));
1388
1389 list_add_tail( &package->files, &file->entry );
Aric Stewartc5a14432005-05-18 17:46:12 +00001390
1391 return ERROR_SUCCESS;
1392}
1393
1394static UINT load_all_files(MSIPACKAGE *package)
1395{
1396 MSIQUERY * view;
Aric Stewartc5a14432005-05-18 17:46:12 +00001397 UINT rc;
1398 static const WCHAR Query[] =
1399 {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00001400 '`','F','i','l','e','`',' ', 'O','R','D','E','R',' ','B','Y',' ',
1401 '`','S','e','q','u','e','n','c','e','`', 0};
Aric Stewartc5a14432005-05-18 17:46:12 +00001402
Mike McCormack9a9195d2006-07-19 17:01:07 +09001403 if (!list_empty(&package->files))
1404 return ERROR_SUCCESS;
1405
Aric Stewartc5a14432005-05-18 17:46:12 +00001406 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
1407 if (rc != ERROR_SUCCESS)
1408 return ERROR_SUCCESS;
Aric Stewartc5a14432005-05-18 17:46:12 +00001409
Aric Stewart04598242005-06-23 16:43:24 +00001410 rc = MSI_IterateRecords(view, NULL, load_file, package);
Aric Stewartc5a14432005-05-18 17:46:12 +00001411 msiobj_release(&view->hdr);
1412
1413 return ERROR_SUCCESS;
1414}
1415
1416
Aric Stewartbdb29552004-07-04 00:32:48 +00001417/*
Mike McCormack9a9195d2006-07-19 17:01:07 +09001418 * I am not doing any of the costing functionality yet.
Aric Stewartbdb29552004-07-04 00:32:48 +00001419 * Mostly looking at doing the Component and Feature loading
1420 *
Francois Gougetda8b3dd2005-01-26 21:09:04 +00001421 * The native MSI does A LOT of modification to tables here. Mostly adding
Mike McCormack9a9195d2006-07-19 17:01:07 +09001422 * a lot of temporary columns to the Feature and Component tables.
Aric Stewartbdb29552004-07-04 00:32:48 +00001423 *
Francois Gougetda8b3dd2005-01-26 21:09:04 +00001424 * note: Native msi also tracks the short filename. But I am only going to
Aric Stewartbdb29552004-07-04 00:32:48 +00001425 * track the long ones. Also looking at this directory table
1426 * it appears that the directory table does not get the parents
Mike McCormack9a9195d2006-07-19 17:01:07 +09001427 * resolved base on property only based on their entries in the
Aric Stewartbdb29552004-07-04 00:32:48 +00001428 * directory table.
1429 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001430static UINT ACTION_CostInitialize(MSIPACKAGE *package)
Aric Stewartbdb29552004-07-04 00:32:48 +00001431{
Aric Stewart8e233e92005-03-01 11:45:19 +00001432 static const WCHAR szCosting[] =
1433 {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001434 static const WCHAR szZero[] = { '0', 0 };
Aric Stewartbdb29552004-07-04 00:32:48 +00001435
Mike McCormack9293f862005-10-30 19:16:45 +00001436 if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001437 return ERROR_SUCCESS;
Mike McCormack9a9195d2006-07-19 17:01:07 +09001438
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001439 MSI_SetPropertyW(package, szCosting, szZero);
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001440 MSI_SetPropertyW(package, cszRootDrive, c_colon);
Aric Stewartbdb29552004-07-04 00:32:48 +00001441
Mike McCormack1d46cdf2006-07-25 21:49:44 +09001442 load_all_components( package );
1443 load_all_features( package );
1444 load_all_files( package );
Aric Stewartec688fb2004-07-04 00:35:52 +00001445
Aric Stewartec688fb2004-07-04 00:35:52 +00001446 return ERROR_SUCCESS;
1447}
1448
Mike McCormackf9acfe62005-06-07 20:29:51 +00001449static UINT execute_script(MSIPACKAGE *package, UINT script )
Aric Stewart9cd707d2005-05-27 19:24:22 +00001450{
1451 int i;
1452 UINT rc = ERROR_SUCCESS;
1453
1454 TRACE("Executing Script %i\n",script);
1455
Mike McCormackaa81e4f2006-01-10 12:09:19 +01001456 if (!package->script)
1457 {
1458 ERR("no script!\n");
1459 return ERROR_FUNCTION_FAILED;
1460 }
1461
Aric Stewart9cd707d2005-05-27 19:24:22 +00001462 for (i = 0; i < package->script->ActionCount[script]; i++)
1463 {
1464 LPWSTR action;
1465 action = package->script->Actions[script][i];
1466 ui_actionstart(package, action);
1467 TRACE("Executing Action (%s)\n",debugstr_w(action));
1468 rc = ACTION_PerformAction(package, action, TRUE);
Mike McCormackee034ba2005-09-20 11:59:14 +00001469 msi_free(package->script->Actions[script][i]);
Aric Stewart9cd707d2005-05-27 19:24:22 +00001470 if (rc != ERROR_SUCCESS)
1471 break;
1472 }
Mike McCormackee034ba2005-09-20 11:59:14 +00001473 msi_free(package->script->Actions[script]);
Aric Stewart9cd707d2005-05-27 19:24:22 +00001474
1475 package->script->ActionCount[script] = 0;
1476 package->script->Actions[script] = NULL;
1477 return rc;
1478}
1479
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001480static UINT ACTION_FileCost(MSIPACKAGE *package)
Aric Stewartec688fb2004-07-04 00:35:52 +00001481{
Aric Stewartbdb29552004-07-04 00:32:48 +00001482 return ERROR_SUCCESS;
1483}
1484
Mike McCormack979511f2005-08-23 18:15:44 +00001485static MSIFOLDER *load_folder( MSIPACKAGE *package, LPCWSTR dir )
Aric Stewartbdb29552004-07-04 00:32:48 +00001486{
Mike McCormackba8200b2004-12-22 15:25:30 +00001487 static const WCHAR Query[] =
Aric Stewart8e233e92005-03-01 11:45:19 +00001488 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00001489 '`','D','i','r','e','c', 't','o','r','y','`',' ',
1490 'W','H','E','R','E',' ', '`', 'D','i','r','e','c','t', 'o','r','y','`',
1491 ' ','=',' ','\'','%','s','\'',
Aric Stewart8e233e92005-03-01 11:45:19 +00001492 0};
Mike McCormackc1513be2006-03-21 19:40:36 +09001493 static const WCHAR szDot[] = { '.',0 };
James Hawkinsa1910e12006-06-20 15:46:41 -07001494 static WCHAR szEmpty[] = { 0 };
Mike McCormackc1513be2006-03-21 19:40:36 +09001495 LPWSTR p, tgt_short, tgt_long, src_short, src_long;
Aric Stewart09b0aba2005-06-09 20:30:59 +00001496 LPCWSTR parent;
Mike McCormackc1513be2006-03-21 19:40:36 +09001497 MSIRECORD *row;
Mike McCormack979511f2005-08-23 18:15:44 +00001498 MSIFOLDER *folder;
Aric Stewarte95136b2004-06-29 03:44:01 +00001499
Aric Stewartbdb29552004-07-04 00:32:48 +00001500 TRACE("Looking for dir %s\n",debugstr_w(dir));
Aric Stewart401bd3f2004-06-28 20:34:35 +00001501
Mike McCormack979511f2005-08-23 18:15:44 +00001502 folder = get_loaded_folder( package, dir );
1503 if (folder)
1504 return folder;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001505
Aric Stewartbdb29552004-07-04 00:32:48 +00001506 TRACE("Working to load %s\n",debugstr_w(dir));
1507
Mike McCormackee034ba2005-09-20 11:59:14 +00001508 folder = msi_alloc_zero( sizeof (MSIFOLDER) );
Mike McCormack979511f2005-08-23 18:15:44 +00001509 if (!folder)
1510 return NULL;
Aric Stewartbdb29552004-07-04 00:32:48 +00001511
Mike McCormack979511f2005-08-23 18:15:44 +00001512 folder->Directory = strdupW(dir);
Aric Stewartbdb29552004-07-04 00:32:48 +00001513
Mike McCormack0b352c72005-06-02 10:29:57 +00001514 row = MSI_QueryGetRecord(package->db, Query, dir);
1515 if (!row)
Mike McCormack979511f2005-08-23 18:15:44 +00001516 return NULL;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001517
Mike McCormackc1513be2006-03-21 19:40:36 +09001518 p = msi_dup_record_field(row, 3);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001519
1520 /* split src and target dir */
Mike McCormackc1513be2006-03-21 19:40:36 +09001521 tgt_short = p;
1522 src_short = folder_split_path( p, ':' );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001523
Francois Gougete739ba92006-05-12 00:06:31 +02001524 /* split the long and short paths */
Mike McCormackc1513be2006-03-21 19:40:36 +09001525 tgt_long = folder_split_path( tgt_short, '|' );
1526 src_long = folder_split_path( src_short, '|' );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001527
James Hawkinsa1910e12006-06-20 15:46:41 -07001528 /* check for no-op dirs */
Mike McCormackc1513be2006-03-21 19:40:36 +09001529 if (!lstrcmpW(szDot, tgt_short))
James Hawkinsa1910e12006-06-20 15:46:41 -07001530 tgt_short = szEmpty;
1531 if (!lstrcmpW(szDot, src_short))
1532 src_short = szEmpty;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001533
Mike McCormackc1513be2006-03-21 19:40:36 +09001534 if (!tgt_long)
1535 tgt_long = tgt_short;
Labrousse Jeand0862c32006-05-21 17:27:29 +02001536
1537 if (!src_short) {
1538 src_short = tgt_short;
1539 src_long = tgt_long;
1540 }
1541
Mike McCormackc1513be2006-03-21 19:40:36 +09001542 if (!src_long)
1543 src_long = src_short;
Mike McCormackba8200b2004-12-22 15:25:30 +00001544
Mike McCormackc1513be2006-03-21 19:40:36 +09001545 /* FIXME: use the target short path too */
1546 folder->TargetDefault = strdupW(tgt_long);
Labrousse Jeand0862c32006-05-21 17:27:29 +02001547 folder->SourceShortPath = strdupW(src_short);
Mike McCormackc1513be2006-03-21 19:40:36 +09001548 folder->SourceLongPath = strdupW(src_long);
1549 msi_free(p);
1550
1551 TRACE("TargetDefault = %s\n",debugstr_w( folder->TargetDefault ));
1552 TRACE("SourceLong = %s\n", debugstr_w( folder->SourceLongPath ));
1553 TRACE("SourceShort = %s\n", debugstr_w( folder->SourceShortPath ));
1554
1555 parent = MSI_RecordGetString(row, 2);
Mike McCormackba8200b2004-12-22 15:25:30 +00001556 if (parent)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001557 {
Mike McCormack979511f2005-08-23 18:15:44 +00001558 folder->Parent = load_folder( package, parent );
1559 if ( folder->Parent )
1560 TRACE("loaded parent %p %s\n", folder->Parent,
1561 debugstr_w(folder->Parent->Directory));
1562 else
1563 ERR("failed to load parent folder %s\n", debugstr_w(parent));
Aric Stewartbdb29552004-07-04 00:32:48 +00001564 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001565
Mike McCormack062ad502005-09-15 15:04:08 +00001566 folder->Property = msi_dup_property( package, dir );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001567
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001568 msiobj_release(&row->hdr);
Mike McCormack979511f2005-08-23 18:15:44 +00001569
1570 list_add_tail( &package->folders, &folder->entry );
1571
1572 TRACE("%s returning %p\n",debugstr_w(dir),folder);
1573
1574 return folder;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001575}
1576
Aric Stewart78a04e32005-02-22 15:47:00 +00001577/* scan for and update current install states */
Mike McCormackf9acfe62005-06-07 20:29:51 +00001578static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
Aric Stewart78a04e32005-02-22 15:47:00 +00001579{
Mike McCormack38d67a42005-08-22 09:15:23 +00001580 MSICOMPONENT *comp;
Mike McCormack1da28582005-08-22 14:09:17 +00001581 MSIFEATURE *feature;
Aric Stewart78a04e32005-02-22 15:47:00 +00001582
James Hawkins32f57022006-09-20 19:57:03 -07001583 /* FIXME: component's installed state should be determined
1584 * by the component's registration
1585 */
Mike McCormack38d67a42005-08-22 09:15:23 +00001586 LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
Aric Stewart78a04e32005-02-22 15:47:00 +00001587 {
1588 INSTALLSTATE res;
James Hawkins32f57022006-09-20 19:57:03 -07001589
1590 if (!comp->ComponentId)
1591 continue;
1592
Mike McCormack38d67a42005-08-22 09:15:23 +00001593 res = MsiGetComponentPathW( package->ProductCode,
1594 comp->ComponentId, NULL, NULL);
Aric Stewart78a04e32005-02-22 15:47:00 +00001595 if (res < 0)
1596 res = INSTALLSTATE_ABSENT;
Mike McCormack38d67a42005-08-22 09:15:23 +00001597 comp->Installed = res;
Aric Stewart78a04e32005-02-22 15:47:00 +00001598 }
1599
Mike McCormack1da28582005-08-22 14:09:17 +00001600 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewart78a04e32005-02-22 15:47:00 +00001601 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001602 ComponentList *cl;
James Hawkins545d0e72006-09-20 19:59:19 -07001603 INSTALLSTATE res = INSTALLSTATE_ABSENT;
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001604
Mike McCormack1da28582005-08-22 14:09:17 +00001605 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Aric Stewart78a04e32005-02-22 15:47:00 +00001606 {
Mike McCormack38d67a42005-08-22 09:15:23 +00001607 comp= cl->component;
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001608
James Hawkins32f57022006-09-20 19:57:03 -07001609 if (!comp->ComponentId)
1610 {
1611 res = INSTALLSTATE_ABSENT;
1612 break;
1613 }
1614
James Hawkins545d0e72006-09-20 19:59:19 -07001615 if (res == INSTALLSTATE_ABSENT)
Mike McCormack38d67a42005-08-22 09:15:23 +00001616 res = comp->Installed;
Aric Stewart78a04e32005-02-22 15:47:00 +00001617 else
1618 {
Mike McCormack38d67a42005-08-22 09:15:23 +00001619 if (res == comp->Installed)
Aric Stewart78a04e32005-02-22 15:47:00 +00001620 continue;
1621
James Hawkins32f57022006-09-20 19:57:03 -07001622 if (res != INSTALLSTATE_DEFAULT || res != INSTALLSTATE_LOCAL ||
1623 res != INSTALLSTATE_SOURCE)
1624 {
1625 res = INSTALLSTATE_INCOMPLETE;
1626 }
Aric Stewart78a04e32005-02-22 15:47:00 +00001627 }
1628 }
Mike McCormack8aa1a912005-08-25 19:19:10 +00001629 feature->Installed = res;
Aric Stewart78a04e32005-02-22 15:47:00 +00001630 }
1631}
1632
Aric Stewart78a04e32005-02-22 15:47:00 +00001633static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
1634 INSTALLSTATE state)
Aric Stewartae1aa322004-12-27 19:02:59 +00001635{
Aric Stewartae1aa322004-12-27 19:02:59 +00001636 static const WCHAR all[]={'A','L','L',0};
Mike McCormack72faac02005-09-08 11:03:35 +00001637 LPWSTR override;
Mike McCormack1da28582005-08-22 14:09:17 +00001638 MSIFEATURE *feature;
Aric Stewartae1aa322004-12-27 19:02:59 +00001639
Mike McCormack062ad502005-09-15 15:04:08 +00001640 override = msi_dup_property( package, property );
Mike McCormack72faac02005-09-08 11:03:35 +00001641 if (!override)
1642 return FALSE;
1643
1644 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartae1aa322004-12-27 19:02:59 +00001645 {
Mike McCormack72faac02005-09-08 11:03:35 +00001646 if (strcmpiW(override,all)==0)
Aric Stewartfbdd7092004-12-27 19:06:22 +00001647 {
Mike McCormack72faac02005-09-08 11:03:35 +00001648 feature->ActionRequest= state;
1649 feature->Action = state;
1650 }
1651 else
1652 {
1653 LPWSTR ptr = override;
1654 LPWSTR ptr2 = strchrW(override,',');
Aric Stewartd900b532004-12-27 19:12:35 +00001655
Mike McCormack72faac02005-09-08 11:03:35 +00001656 while (ptr)
1657 {
1658 if ((ptr2 && strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
1659 || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
Aric Stewartd900b532004-12-27 19:12:35 +00001660 {
Mike McCormack72faac02005-09-08 11:03:35 +00001661 feature->ActionRequest= state;
1662 feature->Action = state;
1663 break;
Aric Stewartd900b532004-12-27 19:12:35 +00001664 }
Mike McCormack72faac02005-09-08 11:03:35 +00001665 if (ptr2)
1666 {
1667 ptr=ptr2+1;
1668 ptr2 = strchrW(ptr,',');
1669 }
1670 else
1671 break;
Aric Stewartd900b532004-12-27 19:12:35 +00001672 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001673 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001674 }
Mike McCormackee034ba2005-09-20 11:59:14 +00001675 msi_free(override);
Aric Stewart78a04e32005-02-22 15:47:00 +00001676
Mike McCormack72faac02005-09-08 11:03:35 +00001677 return TRUE;
Aric Stewart78a04e32005-02-22 15:47:00 +00001678}
1679
James Hawkins7bcac312006-07-19 11:17:16 -07001680UINT MSI_SetFeatureStates(MSIPACKAGE *package)
Aric Stewart78a04e32005-02-22 15:47:00 +00001681{
Mike McCormack74f0de92005-09-29 10:32:39 +00001682 int install_level;
Aric Stewart8e233e92005-03-01 11:45:19 +00001683 static const WCHAR szlevel[] =
1684 {'I','N','S','T','A','L','L','L','E','V','E','L',0};
1685 static const WCHAR szAddLocal[] =
1686 {'A','D','D','L','O','C','A','L',0};
1687 static const WCHAR szRemove[] =
1688 {'R','E','M','O','V','E',0};
Aric Stewartd5655f92005-11-02 14:21:17 +00001689 static const WCHAR szReinstall[] =
1690 {'R','E','I','N','S','T','A','L','L',0};
Aric Stewart78a04e32005-02-22 15:47:00 +00001691 BOOL override = FALSE;
Mike McCormack38d67a42005-08-22 09:15:23 +00001692 MSICOMPONENT* component;
Mike McCormack1da28582005-08-22 14:09:17 +00001693 MSIFEATURE *feature;
1694
Aric Stewart78a04e32005-02-22 15:47:00 +00001695
1696 /* I do not know if this is where it should happen.. but */
1697
1698 TRACE("Checking Install Level\n");
1699
Mike McCormack74f0de92005-09-29 10:32:39 +00001700 install_level = msi_get_property_int( package, szlevel, 1 );
Aric Stewart78a04e32005-02-22 15:47:00 +00001701
Francois Gouget58162f82006-10-13 02:19:42 +02001702 /* ok here is the _real_ rub
Francois Gougetfbb33432005-03-02 13:53:50 +00001703 * all these activation/deactivation things happen in order and things
1704 * later on the list override things earlier on the list.
Aric Stewart78a04e32005-02-22 15:47:00 +00001705 * 1) INSTALLLEVEL processing
1706 * 2) ADDLOCAL
1707 * 3) REMOVE
1708 * 4) ADDSOURCE
1709 * 5) ADDDEFAULT
1710 * 6) REINSTALL
1711 * 7) COMPADDLOCAL
1712 * 8) COMPADDSOURCE
1713 * 9) FILEADDLOCAL
1714 * 10) FILEADDSOURCE
1715 * 11) FILEADDDEFAULT
Francois Gougetfbb33432005-03-02 13:53:50 +00001716 * I have confirmed that if ADDLOCAL is stated then the INSTALLLEVEL is
1717 * ignored for all the features. seems strange, especially since it is not
Aric Stewart78a04e32005-02-22 15:47:00 +00001718 * documented anywhere, but it is how it works.
1719 *
Francois Gougetfbb33432005-03-02 13:53:50 +00001720 * I am still ignoring a lot of these. But that is ok for now, ADDLOCAL and
1721 * REMOVE are the big ones, since we don't handle administrative installs
1722 * yet anyway.
Aric Stewart78a04e32005-02-22 15:47:00 +00001723 */
1724 override |= process_state_property(package,szAddLocal,INSTALLSTATE_LOCAL);
1725 override |= process_state_property(package,szRemove,INSTALLSTATE_ABSENT);
Aric Stewartd5655f92005-11-02 14:21:17 +00001726 override |= process_state_property(package,szReinstall,INSTALLSTATE_LOCAL);
Aric Stewart78a04e32005-02-22 15:47:00 +00001727
1728 if (!override)
Aric Stewartfbdd7092004-12-27 19:06:22 +00001729 {
Mike McCormack1da28582005-08-22 14:09:17 +00001730 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartfbdd7092004-12-27 19:06:22 +00001731 {
Mike McCormack1da28582005-08-22 14:09:17 +00001732 BOOL feature_state = ((feature->Level > 0) &&
1733 (feature->Level <= install_level));
Aric Stewartae1aa322004-12-27 19:02:59 +00001734
Mike McCormack1da28582005-08-22 14:09:17 +00001735 if ((feature_state) && (feature->Action == INSTALLSTATE_UNKNOWN))
Aric Stewartfbdd7092004-12-27 19:06:22 +00001736 {
Mike McCormack1da28582005-08-22 14:09:17 +00001737 if (feature->Attributes & msidbFeatureAttributesFavorSource)
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001738 {
Mike McCormack1da28582005-08-22 14:09:17 +00001739 feature->ActionRequest = INSTALLSTATE_SOURCE;
1740 feature->Action = INSTALLSTATE_SOURCE;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001741 }
Mike McCormack1da28582005-08-22 14:09:17 +00001742 else if (feature->Attributes & msidbFeatureAttributesFavorAdvertise)
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001743 {
Mike McCormack1da28582005-08-22 14:09:17 +00001744 feature->ActionRequest = INSTALLSTATE_ADVERTISED;
1745 feature->Action = INSTALLSTATE_ADVERTISED;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001746 }
1747 else
1748 {
Mike McCormack1da28582005-08-22 14:09:17 +00001749 feature->ActionRequest = INSTALLSTATE_LOCAL;
1750 feature->Action = INSTALLSTATE_LOCAL;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001751 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001752 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001753 }
James Hawkins545d0e72006-09-20 19:59:19 -07001754
1755 /* disable child features of unselected parent features */
1756 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
1757 {
1758 FeatureList *fl;
1759
1760 if (feature->Level > 0 && feature->Level <= install_level)
1761 continue;
1762
1763 LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
1764 {
1765 fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN;
1766 fl->feature->Action = INSTALLSTATE_UNKNOWN;
1767 }
1768 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001769 }
Aric Stewart6999a042005-06-08 19:20:02 +00001770 else
1771 {
1772 /* set the Preselected Property */
1773 static const WCHAR szPreselected[] = {'P','r','e','s','e','l','e','c','t','e','d',0};
1774 static const WCHAR szOne[] = { '1', 0 };
1775
1776 MSI_SetPropertyW(package,szPreselected,szOne);
1777 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001778
Aric Stewartfbdd7092004-12-27 19:06:22 +00001779 /*
1780 * now we want to enable or disable components base on feature
1781 */
1782
Mike McCormack1da28582005-08-22 14:09:17 +00001783 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartfbdd7092004-12-27 19:06:22 +00001784 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00001785 ComponentList *cl;
1786
Aric Stewartfbdd7092004-12-27 19:06:22 +00001787 TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n",
1788 debugstr_w(feature->Feature), feature->Installed, feature->Action,
1789 feature->ActionRequest);
1790
Mike McCormack1da28582005-08-22 14:09:17 +00001791 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Aric Stewartae1aa322004-12-27 19:02:59 +00001792 {
Mike McCormack38d67a42005-08-22 09:15:23 +00001793 component = cl->component;
Aric Stewartfbdd7092004-12-27 19:06:22 +00001794
1795 if (!component->Enabled)
1796 {
Aric Stewart78a04e32005-02-22 15:47:00 +00001797 component->Action = INSTALLSTATE_UNKNOWN;
1798 component->ActionRequest = INSTALLSTATE_UNKNOWN;
Aric Stewartfbdd7092004-12-27 19:06:22 +00001799 }
1800 else
1801 {
James Hawkins38f2ba22006-07-31 14:50:44 -07001802 if (feature->Attributes == msidbFeatureAttributesFavorLocal)
Aric Stewart78a04e32005-02-22 15:47:00 +00001803 {
James Hawkins38f2ba22006-07-31 14:50:44 -07001804 if (!(component->Attributes & msidbComponentAttributesSourceOnly))
1805 {
1806 component->Action = INSTALLSTATE_LOCAL;
1807 component->ActionRequest = INSTALLSTATE_LOCAL;
1808 }
Aric Stewart78a04e32005-02-22 15:47:00 +00001809 }
James Hawkins38f2ba22006-07-31 14:50:44 -07001810 else if (feature->Attributes == msidbFeatureAttributesFavorSource)
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001811 {
1812 if ((component->Action == INSTALLSTATE_UNKNOWN) ||
1813 (component->Action == INSTALLSTATE_ABSENT) ||
James Hawkins38f2ba22006-07-31 14:50:44 -07001814 (component->Action == INSTALLSTATE_ADVERTISED) ||
1815 (component->Action == INSTALLSTATE_DEFAULT))
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001816
1817 {
1818 component->Action = INSTALLSTATE_SOURCE;
1819 component->ActionRequest = INSTALLSTATE_SOURCE;
1820 }
1821 }
1822 else if (feature->ActionRequest == INSTALLSTATE_ADVERTISED)
1823 {
1824 if ((component->Action == INSTALLSTATE_UNKNOWN) ||
1825 (component->Action == INSTALLSTATE_ABSENT))
1826
1827 {
1828 component->Action = INSTALLSTATE_ADVERTISED;
1829 component->ActionRequest = INSTALLSTATE_ADVERTISED;
1830 }
1831 }
Aric Stewart78a04e32005-02-22 15:47:00 +00001832 else if (feature->ActionRequest == INSTALLSTATE_ABSENT)
1833 {
1834 if (component->Action == INSTALLSTATE_UNKNOWN)
1835 {
1836 component->Action = INSTALLSTATE_ABSENT;
1837 component->ActionRequest = INSTALLSTATE_ABSENT;
1838 }
1839 }
James Hawkinsbbd4d1e2006-09-25 20:05:25 -07001840 else if (feature->ActionRequest == INSTALLSTATE_UNKNOWN)
1841 {
1842 component->Action = INSTALLSTATE_UNKNOWN;
1843 component->ActionRequest = INSTALLSTATE_UNKNOWN;
1844 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001845 }
James Hawkins7edea0c2006-08-01 10:14:15 -07001846
James Hawkins937b9b22006-09-20 19:53:07 -07001847 if (component->ForceLocalState && feature->Action == INSTALLSTATE_SOURCE)
James Hawkins7edea0c2006-08-01 10:14:15 -07001848 {
1849 feature->Action = INSTALLSTATE_LOCAL;
1850 feature->ActionRequest = INSTALLSTATE_LOCAL;
1851 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001852 }
1853 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001854
Mike McCormack38d67a42005-08-22 09:15:23 +00001855 LIST_FOR_EACH_ENTRY( component, &package->components, MSICOMPONENT, entry )
Aric Stewartfbdd7092004-12-27 19:06:22 +00001856 {
Aric Stewartfbdd7092004-12-27 19:06:22 +00001857 TRACE("Result: Component %s (Installed %i, Action %i, Request %i)\n",
1858 debugstr_w(component->Component), component->Installed,
1859 component->Action, component->ActionRequest);
1860 }
1861
1862
Aric Stewartae1aa322004-12-27 19:02:59 +00001863 return ERROR_SUCCESS;
1864}
1865
Aric Stewart443ad4d2005-06-21 20:50:12 +00001866static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param)
1867{
1868 MSIPACKAGE *package = (MSIPACKAGE*)param;
1869 LPCWSTR name;
1870 LPWSTR path;
1871
1872 name = MSI_RecordGetString(row,1);
1873
1874 /* This helper function now does ALL the work */
1875 TRACE("Dir %s ...\n",debugstr_w(name));
1876 load_folder(package,name);
1877 path = resolve_folder(package,name,FALSE,TRUE,NULL);
1878 TRACE("resolves to %s\n",debugstr_w(path));
Mike McCormackee034ba2005-09-20 11:59:14 +00001879 msi_free(path);
Aric Stewart443ad4d2005-06-21 20:50:12 +00001880
1881 return ERROR_SUCCESS;
1882}
1883
1884static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
1885{
1886 MSIPACKAGE *package = (MSIPACKAGE*)param;
Mike McCormack1da28582005-08-22 14:09:17 +00001887 LPCWSTR name;
1888 MSIFEATURE *feature;
Aric Stewart443ad4d2005-06-21 20:50:12 +00001889
Mike McCormack1da28582005-08-22 14:09:17 +00001890 name = MSI_RecordGetString( row, 1 );
Aric Stewart443ad4d2005-06-21 20:50:12 +00001891
Mike McCormack1da28582005-08-22 14:09:17 +00001892 feature = get_loaded_feature( package, name );
1893 if (!feature)
1894 ERR("FAILED to find loaded feature %s\n",debugstr_w(name));
Aric Stewart443ad4d2005-06-21 20:50:12 +00001895 else
1896 {
1897 LPCWSTR Condition;
1898 Condition = MSI_RecordGetString(row,3);
1899
Aric Stewart0713f092005-06-24 11:51:29 +00001900 if (MSI_EvaluateConditionW(package,Condition) == MSICONDITION_TRUE)
Aric Stewart443ad4d2005-06-21 20:50:12 +00001901 {
1902 int level = MSI_RecordGetInteger(row,2);
Mike McCormack1da28582005-08-22 14:09:17 +00001903 TRACE("Reseting feature %s to level %i\n", debugstr_w(name), level);
1904 feature->Level = level;
Aric Stewart443ad4d2005-06-21 20:50:12 +00001905 }
1906 }
1907 return ERROR_SUCCESS;
1908}
1909
James Hawkinsd893cb72006-09-20 19:55:01 -07001910static void load_all_component_states(MSIPACKAGE *package)
1911{
1912 MSICOMPONENT *comp;
1913
1914 LIST_FOR_EACH_ENTRY(comp, &package->components, MSICOMPONENT, entry)
1915 {
1916 switch (comp->Attributes)
1917 {
1918 case msidbComponentAttributesLocalOnly:
1919 comp->Action = INSTALLSTATE_LOCAL;
1920 comp->ActionRequest = INSTALLSTATE_LOCAL;
1921 break;
1922 case msidbComponentAttributesSourceOnly:
1923 comp->Action = INSTALLSTATE_SOURCE;
1924 comp->ActionRequest = INSTALLSTATE_SOURCE;
1925 break;
1926 case msidbComponentAttributesOptional:
1927 comp->Action = INSTALLSTATE_DEFAULT;
1928 comp->ActionRequest = INSTALLSTATE_DEFAULT;
1929 break;
1930 default:
1931 comp->Action = INSTALLSTATE_LOCAL;
1932 comp->ActionRequest = INSTALLSTATE_LOCAL;
1933 }
1934 }
1935}
Aric Stewart443ad4d2005-06-21 20:50:12 +00001936
Aric Stewart401bd3f2004-06-28 20:34:35 +00001937/*
Francois Gougetda8b3dd2005-01-26 21:09:04 +00001938 * A lot is done in this function aside from just the costing.
Mike McCormack6e2bca32004-07-04 00:25:00 +00001939 * The costing needs to be implemented at some point but for now I am going
Aric Stewart401bd3f2004-06-28 20:34:35 +00001940 * to focus on the directory building
1941 *
Aric Stewart401bd3f2004-06-28 20:34:35 +00001942 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001943static UINT ACTION_CostFinalize(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001944{
Aric Stewart8e233e92005-03-01 11:45:19 +00001945 static const WCHAR ExecSeqQuery[] =
1946 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00001947 '`','D','i','r','e','c','t','o','r','y','`',0};
Aric Stewart8e233e92005-03-01 11:45:19 +00001948 static const WCHAR ConditionQuery[] =
1949 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00001950 '`','C','o','n','d','i','t','i','o','n','`',0};
Aric Stewart8e233e92005-03-01 11:45:19 +00001951 static const WCHAR szCosting[] =
1952 {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
1953 static const WCHAR szlevel[] =
1954 {'I','N','S','T','A','L','L','L','E','V','E','L',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001955 static const WCHAR szOne[] = { '1', 0 };
Mike McCormack38d67a42005-08-22 09:15:23 +00001956 MSICOMPONENT *comp;
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001957 MSIFILE *file;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001958 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001959 MSIQUERY * view;
Aric Stewart8cc14a92004-12-27 18:56:30 +00001960 LPWSTR level;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001961
Mike McCormack9293f862005-10-30 19:16:45 +00001962 if ( 1 == msi_get_property_int( package, szCosting, 0 ) )
Aric Stewartb39d8fc2005-05-13 13:56:39 +00001963 return ERROR_SUCCESS;
Mike McCormack9293f862005-10-30 19:16:45 +00001964
Aric Stewart401bd3f2004-06-28 20:34:35 +00001965 TRACE("Building Directory properties\n");
1966
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001967 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00001968 if (rc == ERROR_SUCCESS)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001969 {
Aric Stewart443ad4d2005-06-21 20:50:12 +00001970 rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeDirectories,
1971 package);
Aric Stewart84837d92004-07-20 01:22:37 +00001972 msiobj_release(&view->hdr);
1973 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001974
James Hawkinsd893cb72006-09-20 19:55:01 -07001975 load_all_component_states(package);
1976
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001977 TRACE("File calculations\n");
Aric Stewartec688fb2004-07-04 00:35:52 +00001978
Mike McCormacke18f8ab2005-08-23 10:03:17 +00001979 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
Aric Stewartec688fb2004-07-04 00:35:52 +00001980 {
Mike McCormackf11c8b02005-09-09 14:48:51 +00001981 MSICOMPONENT* comp = file->Component;
1982 LPWSTR p;
Aric Stewartec688fb2004-07-04 00:35:52 +00001983
Mike McCormackf11c8b02005-09-09 14:48:51 +00001984 if (!comp)
1985 continue;
Aric Stewartec688fb2004-07-04 00:35:52 +00001986
James Hawkinsd893cb72006-09-20 19:55:01 -07001987 if (file->IsCompressed)
1988 {
1989 comp->ForceLocalState = TRUE;
1990 comp->Action = INSTALLSTATE_LOCAL;
1991 comp->ActionRequest = INSTALLSTATE_LOCAL;
1992 }
1993
Mike McCormackf11c8b02005-09-09 14:48:51 +00001994 /* calculate target */
1995 p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
1996
Mike McCormackee034ba2005-09-20 11:59:14 +00001997 msi_free(file->TargetPath);
Mike McCormackf11c8b02005-09-09 14:48:51 +00001998
1999 TRACE("file %s is named %s\n",
2000 debugstr_w(file->File),debugstr_w(file->FileName));
2001
2002 file->TargetPath = build_directory_name(2, p, file->FileName);
2003
Mike McCormackee034ba2005-09-20 11:59:14 +00002004 msi_free(p);
Mike McCormackf11c8b02005-09-09 14:48:51 +00002005
2006 TRACE("file %s resolves to %s\n",
2007 debugstr_w(file->File),debugstr_w(file->TargetPath));
2008
2009 if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
Aric Stewartec688fb2004-07-04 00:35:52 +00002010 {
Mike McCormackdded8fb2005-11-02 10:56:42 +00002011 file->state = msifs_missing;
Mike McCormackf11c8b02005-09-09 14:48:51 +00002012 comp->Cost += file->FileSize;
2013 continue;
2014 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002015
Mike McCormackf11c8b02005-09-09 14:48:51 +00002016 if (file->Version)
2017 {
2018 DWORD handle;
2019 DWORD versize;
2020 UINT sz;
2021 LPVOID version;
Ivan Leo Puoti5b22e4d2005-11-03 11:35:11 +00002022 static WCHAR name[] = {'\\',0};
Mike McCormackf11c8b02005-09-09 14:48:51 +00002023 static const WCHAR name_fmt[] =
2024 {'%','u','.','%','u','.','%','u','.','%','u',0};
2025 WCHAR filever[0x100];
2026 VS_FIXEDFILEINFO *lpVer;
Aric Stewartfa384f62004-12-22 18:46:17 +00002027
Francois Gouget0edbaf72005-11-10 12:14:56 +00002028 TRACE("Version comparison..\n");
Mike McCormackf11c8b02005-09-09 14:48:51 +00002029 versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
Mike McCormackee034ba2005-09-20 11:59:14 +00002030 version = msi_alloc(versize);
Mike McCormackf11c8b02005-09-09 14:48:51 +00002031 GetFileVersionInfoW(file->TargetPath, 0, versize, version);
Aric Stewartfa384f62004-12-22 18:46:17 +00002032
Mike McCormackf11c8b02005-09-09 14:48:51 +00002033 VerQueryValueW(version, name, (LPVOID*)&lpVer, &sz);
Aric Stewartfa384f62004-12-22 18:46:17 +00002034
Mike McCormackf11c8b02005-09-09 14:48:51 +00002035 sprintfW(filever,name_fmt,
2036 HIWORD(lpVer->dwFileVersionMS),
2037 LOWORD(lpVer->dwFileVersionMS),
2038 HIWORD(lpVer->dwFileVersionLS),
2039 LOWORD(lpVer->dwFileVersionLS));
Aric Stewartec688fb2004-07-04 00:35:52 +00002040
Mike McCormackf11c8b02005-09-09 14:48:51 +00002041 TRACE("new %s old %s\n", debugstr_w(file->Version),
2042 debugstr_w(filever));
2043 if (strcmpiW(filever,file->Version)<0)
Aric Stewartec688fb2004-07-04 00:35:52 +00002044 {
Mike McCormackdded8fb2005-11-02 10:56:42 +00002045 file->state = msifs_overwrite;
2046 /* FIXME: cost should be diff in size */
Aric Stewartec688fb2004-07-04 00:35:52 +00002047 comp->Cost += file->FileSize;
2048 }
2049 else
Mike McCormackdded8fb2005-11-02 10:56:42 +00002050 file->state = msifs_present;
Mike McCormackee034ba2005-09-20 11:59:14 +00002051 msi_free(version);
Mike McCormackf11c8b02005-09-09 14:48:51 +00002052 }
2053 else
Mike McCormackdded8fb2005-11-02 10:56:42 +00002054 file->state = msifs_present;
Aric Stewartec688fb2004-07-04 00:35:52 +00002055 }
2056
Aric Stewart7d3e5972004-07-04 00:36:58 +00002057 TRACE("Evaluating Condition Table\n");
Aric Stewart2e9b5f72004-07-04 00:31:17 +00002058
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002059 rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00002060 if (rc == ERROR_SUCCESS)
2061 {
Aric Stewart443ad4d2005-06-21 20:50:12 +00002062 rc = MSI_IterateRecords(view, NULL, ITERATE_CostFinalizeConditions,
2063 package);
Mike McCormackac6a4132005-01-04 20:36:12 +00002064 msiobj_release(&view->hdr);
Aric Stewart84837d92004-07-20 01:22:37 +00002065 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002066
2067 TRACE("Enabling or Disabling Components\n");
Mike McCormack38d67a42005-08-22 09:15:23 +00002068 LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
Aric Stewart7d3e5972004-07-04 00:36:58 +00002069 {
Mike McCormack298cdae2005-09-06 11:39:01 +00002070 if (comp->Condition)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002071 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002072 if (MSI_EvaluateConditionW(package,
Mike McCormack38d67a42005-08-22 09:15:23 +00002073 comp->Condition) == MSICONDITION_FALSE)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002074 {
Mike McCormack38d67a42005-08-22 09:15:23 +00002075 TRACE("Disabling component %s\n", debugstr_w(comp->Component));
2076 comp->Enabled = FALSE;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002077 }
2078 }
2079 }
2080
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002081 MSI_SetPropertyW(package,szCosting,szOne);
Aric Stewart8cc14a92004-12-27 18:56:30 +00002082 /* set default run level if not set */
Mike McCormack062ad502005-09-15 15:04:08 +00002083 level = msi_dup_property( package, szlevel );
Aric Stewart8cc14a92004-12-27 18:56:30 +00002084 if (!level)
2085 MSI_SetPropertyW(package,szlevel, szOne);
Mike McCormackee034ba2005-09-20 11:59:14 +00002086 msi_free(level);
Aric Stewartae1aa322004-12-27 19:02:59 +00002087
Aric Stewart78a04e32005-02-22 15:47:00 +00002088 ACTION_UpdateInstallStates(package);
Aric Stewartae1aa322004-12-27 19:02:59 +00002089
James Hawkins7c7f0bb2006-07-19 11:15:37 -07002090 return MSI_SetFeatureStates(package);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002091}
2092
Francois Gougetda8b3dd2005-01-26 21:09:04 +00002093/* OK this value is "interpreted" and then formatted based on the
Aric Stewart6e160f12004-06-29 04:07:22 +00002094 first few characters */
Aric Stewart09b0aba2005-06-09 20:30:59 +00002095static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type,
Aric Stewart401bd3f2004-06-28 20:34:35 +00002096 DWORD *size)
2097{
2098 LPSTR data = NULL;
Aric Stewart6e160f12004-06-29 04:07:22 +00002099 if (value[0]=='#' && value[1]!='#' && value[1]!='%')
Aric Stewart401bd3f2004-06-28 20:34:35 +00002100 {
Aric Stewart6e160f12004-06-29 04:07:22 +00002101 if (value[1]=='x')
2102 {
2103 LPWSTR ptr;
2104 CHAR byte[5];
Aric Stewart6186b2b2005-05-16 21:37:35 +00002105 LPWSTR deformated = NULL;
Aric Stewart6e160f12004-06-29 04:07:22 +00002106 int count;
2107
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002108 deformat_string(package, &value[2], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002109
2110 /* binary value type */
Aric Stewart6186b2b2005-05-16 21:37:35 +00002111 ptr = deformated;
2112 *type = REG_BINARY;
2113 if (strlenW(ptr)%2)
2114 *size = (strlenW(ptr)/2)+1;
2115 else
2116 *size = strlenW(ptr)/2;
2117
Mike McCormackee034ba2005-09-20 11:59:14 +00002118 data = msi_alloc(*size);
Aric Stewart6186b2b2005-05-16 21:37:35 +00002119
Aric Stewart6e160f12004-06-29 04:07:22 +00002120 byte[0] = '0';
2121 byte[1] = 'x';
2122 byte[4] = 0;
2123 count = 0;
Aric Stewart6186b2b2005-05-16 21:37:35 +00002124 /* if uneven pad with a zero in front */
2125 if (strlenW(ptr)%2)
2126 {
2127 byte[2]= '0';
2128 byte[3]= *ptr;
2129 ptr++;
2130 data[count] = (BYTE)strtol(byte,NULL,0);
2131 count ++;
2132 TRACE("Uneven byte count\n");
2133 }
Aric Stewart6e160f12004-06-29 04:07:22 +00002134 while (*ptr)
2135 {
2136 byte[2]= *ptr;
2137 ptr++;
2138 byte[3]= *ptr;
2139 ptr++;
2140 data[count] = (BYTE)strtol(byte,NULL,0);
2141 count ++;
2142 }
Mike McCormackee034ba2005-09-20 11:59:14 +00002143 msi_free(deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002144
Mike McCormackf1d46462006-10-05 13:41:22 +09002145 TRACE("Data %i bytes(%i)\n",*size,count);
Aric Stewart6e160f12004-06-29 04:07:22 +00002146 }
2147 else
2148 {
2149 LPWSTR deformated;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002150 LPWSTR p;
2151 DWORD d = 0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002152 deformat_string(package, &value[1], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002153
2154 *type=REG_DWORD;
2155 *size = sizeof(DWORD);
Mike McCormackee034ba2005-09-20 11:59:14 +00002156 data = msi_alloc(*size);
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002157 p = deformated;
2158 if (*p == '-')
2159 p++;
2160 while (*p)
2161 {
2162 if ( (*p < '0') || (*p > '9') )
2163 break;
2164 d *= 10;
2165 d += (*p - '0');
2166 p++;
2167 }
2168 if (deformated[0] == '-')
2169 d = -d;
2170 *(LPDWORD)data = d;
Mike McCormackf1d46462006-10-05 13:41:22 +09002171 TRACE("DWORD %i\n",*(LPDWORD)data);
Aric Stewart6e160f12004-06-29 04:07:22 +00002172
Mike McCormackee034ba2005-09-20 11:59:14 +00002173 msi_free(deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002174 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002175 }
2176 else
2177 {
Aric Stewart54c67dd2005-01-25 20:17:09 +00002178 static const WCHAR szMulti[] = {'[','~',']',0};
Aric Stewart09b0aba2005-06-09 20:30:59 +00002179 LPCWSTR ptr;
Aric Stewart6e160f12004-06-29 04:07:22 +00002180 *type=REG_SZ;
2181
Aric Stewart401bd3f2004-06-28 20:34:35 +00002182 if (value[0]=='#')
Aric Stewart6e160f12004-06-29 04:07:22 +00002183 {
2184 if (value[1]=='%')
2185 {
2186 ptr = &value[2];
2187 *type=REG_EXPAND_SZ;
2188 }
2189 else
2190 ptr = &value[1];
2191 }
2192 else
Aric Stewart401bd3f2004-06-28 20:34:35 +00002193 ptr=value;
2194
Aric Stewart54c67dd2005-01-25 20:17:09 +00002195 if (strstrW(value,szMulti))
2196 *type = REG_MULTI_SZ;
2197
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002198 *size = deformat_string(package, ptr,(LPWSTR*)&data);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002199 }
2200 return data;
2201}
2202
Aric Stewart92ef78e2005-06-21 20:21:18 +00002203static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
2204{
2205 MSIPACKAGE *package = (MSIPACKAGE*)param;
2206 static const WCHAR szHCR[] =
2207 {'H','K','E','Y','_','C','L','A','S','S','E','S','_',
2208 'R','O','O','T','\\',0};
2209 static const WCHAR szHCU[] =
2210 {'H','K','E','Y','_','C','U','R','R','E','N','T','_',
2211 'U','S','E','R','\\',0};
2212 static const WCHAR szHLM[] =
2213 {'H','K','E','Y','_','L','O','C','A','L','_',
2214 'M','A','C','H','I','N','E','\\',0};
2215 static const WCHAR szHU[] =
2216 {'H','K','E','Y','_','U','S','E','R','S','\\',0};
2217
2218 LPSTR value_data = NULL;
2219 HKEY root_key, hkey;
2220 DWORD type,size;
2221 LPWSTR deformated;
2222 LPCWSTR szRoot, component, name, key, value;
Mike McCormack38d67a42005-08-22 09:15:23 +00002223 MSICOMPONENT *comp;
Aric Stewart92ef78e2005-06-21 20:21:18 +00002224 MSIRECORD * uirow;
2225 LPWSTR uikey;
2226 INT root;
2227 BOOL check_first = FALSE;
2228 UINT rc;
2229
2230 ui_progress(package,2,0,0,0);
2231
2232 value = NULL;
2233 key = NULL;
2234 uikey = NULL;
2235 name = NULL;
2236
2237 component = MSI_RecordGetString(row, 6);
Mike McCormack38d67a42005-08-22 09:15:23 +00002238 comp = get_loaded_component(package,component);
Johan Dahlin0946c422005-08-24 10:57:27 +00002239 if (!comp)
2240 return ERROR_SUCCESS;
Aric Stewart92ef78e2005-06-21 20:21:18 +00002241
Mike McCormackd693f462005-10-29 11:36:48 +00002242 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
Aric Stewart92ef78e2005-06-21 20:21:18 +00002243 {
2244 TRACE("Skipping write due to disabled component %s\n",
2245 debugstr_w(component));
2246
Mike McCormack38d67a42005-08-22 09:15:23 +00002247 comp->Action = comp->Installed;
Aric Stewart92ef78e2005-06-21 20:21:18 +00002248
2249 return ERROR_SUCCESS;
2250 }
2251
Mike McCormack38d67a42005-08-22 09:15:23 +00002252 comp->Action = INSTALLSTATE_LOCAL;
Aric Stewart92ef78e2005-06-21 20:21:18 +00002253
2254 name = MSI_RecordGetString(row, 4);
2255 if( MSI_RecordIsNull(row,5) && name )
2256 {
2257 /* null values can have special meanings */
2258 if (name[0]=='-' && name[1] == 0)
2259 return ERROR_SUCCESS;
2260 else if ((name[0]=='+' && name[1] == 0) ||
2261 (name[0] == '*' && name[1] == 0))
2262 name = NULL;
2263 check_first = TRUE;
2264 }
2265
2266 root = MSI_RecordGetInteger(row,2);
2267 key = MSI_RecordGetString(row, 3);
2268
2269 /* get the root key */
2270 switch (root)
2271 {
Aric Stewart0713f092005-06-24 11:51:29 +00002272 case -1:
2273 {
2274 static const WCHAR szALLUSER[] = {'A','L','L','U','S','E','R','S',0};
Mike McCormack062ad502005-09-15 15:04:08 +00002275 LPWSTR all_users = msi_dup_property( package, szALLUSER );
Aric Stewart0713f092005-06-24 11:51:29 +00002276 if (all_users && all_users[0] == '1')
2277 {
2278 root_key = HKEY_LOCAL_MACHINE;
2279 szRoot = szHLM;
2280 }
2281 else
2282 {
2283 root_key = HKEY_CURRENT_USER;
2284 szRoot = szHCU;
2285 }
Mike McCormackee034ba2005-09-20 11:59:14 +00002286 msi_free(all_users);
Aric Stewart0713f092005-06-24 11:51:29 +00002287 }
2288 break;
Aric Stewart92ef78e2005-06-21 20:21:18 +00002289 case 0: root_key = HKEY_CLASSES_ROOT;
2290 szRoot = szHCR;
2291 break;
2292 case 1: root_key = HKEY_CURRENT_USER;
2293 szRoot = szHCU;
2294 break;
2295 case 2: root_key = HKEY_LOCAL_MACHINE;
2296 szRoot = szHLM;
2297 break;
2298 case 3: root_key = HKEY_USERS;
2299 szRoot = szHU;
2300 break;
2301 default:
2302 ERR("Unknown root %i\n",root);
2303 root_key=NULL;
2304 szRoot = NULL;
2305 break;
2306 }
2307 if (!root_key)
2308 return ERROR_SUCCESS;
2309
2310 deformat_string(package, key , &deformated);
2311 size = strlenW(deformated) + strlenW(szRoot) + 1;
Mike McCormackee034ba2005-09-20 11:59:14 +00002312 uikey = msi_alloc(size*sizeof(WCHAR));
Aric Stewart92ef78e2005-06-21 20:21:18 +00002313 strcpyW(uikey,szRoot);
2314 strcatW(uikey,deformated);
2315
2316 if (RegCreateKeyW( root_key, deformated, &hkey))
2317 {
2318 ERR("Could not create key %s\n",debugstr_w(deformated));
Mike McCormackee034ba2005-09-20 11:59:14 +00002319 msi_free(deformated);
2320 msi_free(uikey);
Aric Stewart92ef78e2005-06-21 20:21:18 +00002321 return ERROR_SUCCESS;
2322 }
Mike McCormackee034ba2005-09-20 11:59:14 +00002323 msi_free(deformated);
Aric Stewart92ef78e2005-06-21 20:21:18 +00002324
2325 value = MSI_RecordGetString(row,5);
2326 if (value)
2327 value_data = parse_value(package, value, &type, &size);
2328 else
2329 {
2330 static const WCHAR szEmpty[] = {0};
2331 value_data = (LPSTR)strdupW(szEmpty);
2332 size = 0;
2333 type = REG_SZ;
2334 }
2335
2336 deformat_string(package, name, &deformated);
2337
2338 /* get the double nulls to terminate SZ_MULTI */
2339 if (type == REG_MULTI_SZ)
2340 size +=sizeof(WCHAR);
2341
2342 if (!check_first)
2343 {
2344 TRACE("Setting value %s of %s\n",debugstr_w(deformated),
2345 debugstr_w(uikey));
Mike McCormack16466af2005-07-06 10:33:30 +00002346 RegSetValueExW(hkey, deformated, 0, type, (LPBYTE)value_data, size);
Aric Stewart92ef78e2005-06-21 20:21:18 +00002347 }
2348 else
2349 {
2350 DWORD sz = 0;
2351 rc = RegQueryValueExW(hkey, deformated, NULL, NULL, NULL, &sz);
2352 if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA)
2353 {
2354 TRACE("value %s of %s checked already exists\n",
2355 debugstr_w(deformated), debugstr_w(uikey));
2356 }
2357 else
2358 {
2359 TRACE("Checked and setting value %s of %s\n",
2360 debugstr_w(deformated), debugstr_w(uikey));
2361 if (deformated || size)
Mike McCormack16466af2005-07-06 10:33:30 +00002362 RegSetValueExW(hkey, deformated, 0, type, (LPBYTE) value_data, size);
Aric Stewart92ef78e2005-06-21 20:21:18 +00002363 }
2364 }
2365 RegCloseKey(hkey);
2366
2367 uirow = MSI_CreateRecord(3);
2368 MSI_RecordSetStringW(uirow,2,deformated);
2369 MSI_RecordSetStringW(uirow,1,uikey);
2370
2371 if (type == REG_SZ)
2372 MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
2373 else
2374 MSI_RecordSetStringW(uirow,3,value);
2375
2376 ui_actiondata(package,szWriteRegistryValues,uirow);
2377 msiobj_release( &uirow->hdr );
2378
Mike McCormackee034ba2005-09-20 11:59:14 +00002379 msi_free(value_data);
2380 msi_free(deformated);
2381 msi_free(uikey);
Aric Stewart92ef78e2005-06-21 20:21:18 +00002382
2383 return ERROR_SUCCESS;
2384}
2385
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002386static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002387{
2388 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002389 MSIQUERY * view;
Aric Stewart8e233e92005-03-01 11:45:19 +00002390 static const WCHAR ExecSeqQuery[] =
2391 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00002392 '`','R','e','g','i','s','t','r','y','`',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00002393
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002394 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002395 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002396 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002397
Aric Stewartd2c395a2004-07-06 18:48:15 +00002398 /* increment progress bar each time action data is sent */
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002399 ui_progress(package,1,REG_PROGRESS_VALUE,1,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002400
Aric Stewart92ef78e2005-06-21 20:21:18 +00002401 rc = MSI_IterateRecords(view, NULL, ITERATE_WriteRegistryValues, package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002402
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002403 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002404 return rc;
2405}
2406
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002407static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002408{
Aric Stewart9cd707d2005-05-27 19:24:22 +00002409 package->script->CurrentlyScripting = TRUE;
2410
Aric Stewart7d3e5972004-07-04 00:36:58 +00002411 return ERROR_SUCCESS;
2412}
2413
Aric Stewartae1aa322004-12-27 19:02:59 +00002414
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002415static UINT ACTION_InstallValidate(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002416{
Mike McCormack38d67a42005-08-22 09:15:23 +00002417 MSICOMPONENT *comp;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002418 DWORD progress = 0;
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002419 DWORD total = 0;
Aric Stewart8e233e92005-03-01 11:45:19 +00002420 static const WCHAR q1[]=
2421 {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00002422 '`','R','e','g','i','s','t','r','y','`',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00002423 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002424 MSIQUERY * view;
Mike McCormack1da28582005-08-22 14:09:17 +00002425 MSIFEATURE *feature;
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002426 MSIFILE *file;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002427
Mike McCormackf3f12ab2005-09-21 10:20:03 +00002428 TRACE("InstallValidate\n");
Aric Stewart7d3e5972004-07-04 00:36:58 +00002429
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002430 rc = MSI_DatabaseOpenViewW(package->db, q1, &view);
Mike McCormackf3f12ab2005-09-21 10:20:03 +00002431 if (rc == ERROR_SUCCESS)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002432 {
Mike McCormackf3f12ab2005-09-21 10:20:03 +00002433 MSI_IterateRecords( view, &progress, NULL, package );
2434 msiobj_release( &view->hdr );
2435 total += progress * REG_PROGRESS_VALUE;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002436 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002437
Mike McCormack38d67a42005-08-22 09:15:23 +00002438 LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
Mike McCormack38d67a42005-08-22 09:15:23 +00002439 total += COMPONENT_PROGRESS_VALUE;
Mike McCormackf3f12ab2005-09-21 10:20:03 +00002440
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002441 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002442 total += file->FileSize;
Mike McCormackf3f12ab2005-09-21 10:20:03 +00002443
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002444 ui_progress(package,0,total,0,0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002445
Mike McCormack1da28582005-08-22 14:09:17 +00002446 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartb39d8fc2005-05-13 13:56:39 +00002447 {
Aric Stewartb39d8fc2005-05-13 13:56:39 +00002448 TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n",
2449 debugstr_w(feature->Feature), feature->Installed, feature->Action,
2450 feature->ActionRequest);
2451 }
2452
Aric Stewart7d3e5972004-07-04 00:36:58 +00002453 return ERROR_SUCCESS;
2454}
2455
Aric Stewartc79f4e22005-06-22 18:03:08 +00002456static UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param)
2457{
2458 MSIPACKAGE* package = (MSIPACKAGE*)param;
2459 LPCWSTR cond = NULL;
2460 LPCWSTR message = NULL;
2461 static const WCHAR title[]=
2462 {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0};
2463
2464 cond = MSI_RecordGetString(row,1);
2465
2466 if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
2467 {
2468 LPWSTR deformated;
2469 message = MSI_RecordGetString(row,2);
2470 deformat_string(package,message,&deformated);
2471 MessageBoxW(NULL,deformated,title,MB_OK);
Mike McCormackee034ba2005-09-20 11:59:14 +00002472 msi_free(deformated);
Aric Stewartc79f4e22005-06-22 18:03:08 +00002473 return ERROR_FUNCTION_FAILED;
2474 }
2475
2476 return ERROR_SUCCESS;
2477}
2478
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002479static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
Aric Stewart5b936ca2004-07-06 18:47:09 +00002480{
2481 UINT rc;
Mike McCormackf3c8b832004-07-19 19:35:05 +00002482 MSIQUERY * view = NULL;
Aric Stewart8e233e92005-03-01 11:45:19 +00002483 static const WCHAR ExecSeqQuery[] =
2484 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00002485 '`','L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','`',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00002486
Aric Stewart5b936ca2004-07-06 18:47:09 +00002487 TRACE("Checking launch conditions\n");
Aric Stewart7d3e5972004-07-04 00:36:58 +00002488
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002489 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart5b936ca2004-07-06 18:47:09 +00002490 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002491 return ERROR_SUCCESS;
Aric Stewart5b936ca2004-07-06 18:47:09 +00002492
Aric Stewartc79f4e22005-06-22 18:03:08 +00002493 rc = MSI_IterateRecords(view, NULL, ITERATE_LaunchConditions, package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002494 msiobj_release(&view->hdr);
Aric Stewartc79f4e22005-06-22 18:03:08 +00002495
Aric Stewart5b936ca2004-07-06 18:47:09 +00002496 return rc;
2497}
Aric Stewart7d3e5972004-07-04 00:36:58 +00002498
Mike McCormack38d67a42005-08-22 09:15:23 +00002499static LPWSTR resolve_keypath( MSIPACKAGE* package, MSICOMPONENT *cmp )
Aric Stewartb942e182004-07-06 18:50:02 +00002500{
Aric Stewartb942e182004-07-06 18:50:02 +00002501
Mike McCormackefcc1ec2005-09-12 12:07:15 +00002502 if (!cmp->KeyPath)
2503 return resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);
2504
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002505 if (cmp->Attributes & msidbComponentAttributesRegistryKeyPath)
Aric Stewartb942e182004-07-06 18:50:02 +00002506 {
Aric Stewart6269f002005-01-17 13:40:39 +00002507 MSIRECORD * row = 0;
Mike McCormack0b352c72005-06-02 10:29:57 +00002508 UINT root,len;
Aric Stewart09b0aba2005-06-09 20:30:59 +00002509 LPWSTR deformated,buffer,deformated_name;
2510 LPCWSTR key,name;
Aric Stewart8e233e92005-03-01 11:45:19 +00002511 static const WCHAR ExecSeqQuery[] =
2512 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00002513 '`','R','e','g','i','s','t','r','y','`',' ',
2514 'W','H','E','R','E',' ', '`','R','e','g','i','s','t','r','y','`',
2515 ' ','=',' ' ,'\'','%','s','\'',0 };
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002516 static const WCHAR fmt[]={'%','0','2','i',':','\\','%','s','\\',0};
Aric Stewart8e233e92005-03-01 11:45:19 +00002517 static const WCHAR fmt2[]=
2518 {'%','0','2','i',':','\\','%','s','\\','%','s',0};
Aric Stewart6269f002005-01-17 13:40:39 +00002519
Mike McCormack0b352c72005-06-02 10:29:57 +00002520 row = MSI_QueryGetRecord(package->db, ExecSeqQuery,cmp->KeyPath);
2521 if (!row)
Aric Stewart6269f002005-01-17 13:40:39 +00002522 return NULL;
2523
Aric Stewart6269f002005-01-17 13:40:39 +00002524 root = MSI_RecordGetInteger(row,2);
Aric Stewart09b0aba2005-06-09 20:30:59 +00002525 key = MSI_RecordGetString(row, 3);
2526 name = MSI_RecordGetString(row, 4);
Aric Stewart6269f002005-01-17 13:40:39 +00002527 deformat_string(package, key , &deformated);
2528 deformat_string(package, name, &deformated_name);
2529
Ulrich Czekallae15e5172005-03-08 16:44:51 +00002530 len = strlenW(deformated) + 6;
Aric Stewart6269f002005-01-17 13:40:39 +00002531 if (deformated_name)
2532 len+=strlenW(deformated_name);
2533
Mike McCormackee034ba2005-09-20 11:59:14 +00002534 buffer = msi_alloc( len *sizeof(WCHAR));
Aric Stewart6269f002005-01-17 13:40:39 +00002535
2536 if (deformated_name)
2537 sprintfW(buffer,fmt2,root,deformated,deformated_name);
2538 else
2539 sprintfW(buffer,fmt,root,deformated);
2540
Mike McCormackee034ba2005-09-20 11:59:14 +00002541 msi_free(deformated);
2542 msi_free(deformated_name);
Aric Stewart6269f002005-01-17 13:40:39 +00002543 msiobj_release(&row->hdr);
Aric Stewart6269f002005-01-17 13:40:39 +00002544
2545 return buffer;
2546 }
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002547 else if (cmp->Attributes & msidbComponentAttributesODBCDataSource)
Aric Stewart6269f002005-01-17 13:40:39 +00002548 {
2549 FIXME("UNIMPLEMENTED keypath as ODBC Source\n");
Aric Stewartfa384f62004-12-22 18:46:17 +00002550 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00002551 }
2552 else
2553 {
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002554 MSIFILE *file = get_loaded_file( package, cmp->KeyPath );
Aric Stewartfcb20c52004-07-06 18:51:16 +00002555
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002556 if (file)
2557 return strdupW( file->TargetPath );
Aric Stewartb942e182004-07-06 18:50:02 +00002558 }
Aric Stewartfa384f62004-12-22 18:46:17 +00002559 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00002560}
2561
Stefan Huehnerac6f5622005-06-20 14:18:03 +00002562static HKEY openSharedDLLsKey(void)
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002563{
2564 HKEY hkey=0;
Aric Stewart8e233e92005-03-01 11:45:19 +00002565 static const WCHAR path[] =
2566 {'S','o','f','t','w','a','r','e','\\',
2567 'M','i','c','r','o','s','o','f','t','\\',
2568 'W','i','n','d','o','w','s','\\',
2569 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2570 'S','h','a','r','e','d','D','L','L','s',0};
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002571
2572 RegCreateKeyW(HKEY_LOCAL_MACHINE,path,&hkey);
2573 return hkey;
2574}
2575
2576static UINT ACTION_GetSharedDLLsCount(LPCWSTR dll)
2577{
2578 HKEY hkey;
2579 DWORD count=0;
2580 DWORD type;
2581 DWORD sz = sizeof(count);
2582 DWORD rc;
2583
2584 hkey = openSharedDLLsKey();
2585 rc = RegQueryValueExW(hkey, dll, NULL, &type, (LPBYTE)&count, &sz);
2586 if (rc != ERROR_SUCCESS)
2587 count = 0;
2588 RegCloseKey(hkey);
2589 return count;
2590}
2591
2592static UINT ACTION_WriteSharedDLLsCount(LPCWSTR path, UINT count)
2593{
2594 HKEY hkey;
2595
2596 hkey = openSharedDLLsKey();
2597 if (count > 0)
Mike McCormack4db02cd2005-09-15 14:58:38 +00002598 msi_reg_set_val_dword( hkey, path, count );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002599 else
2600 RegDeleteValueW(hkey,path);
2601 RegCloseKey(hkey);
2602 return count;
2603}
2604
2605/*
2606 * Return TRUE if the count should be written out and FALSE if not
2607 */
Mike McCormack38d67a42005-08-22 09:15:23 +00002608static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002609{
Mike McCormack1da28582005-08-22 14:09:17 +00002610 MSIFEATURE *feature;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002611 INT count = 0;
2612 BOOL write = FALSE;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002613
2614 /* only refcount DLLs */
Mike McCormackefcc1ec2005-09-12 12:07:15 +00002615 if (comp->KeyPath == NULL ||
Mike McCormack38d67a42005-08-22 09:15:23 +00002616 comp->Attributes & msidbComponentAttributesRegistryKeyPath ||
2617 comp->Attributes & msidbComponentAttributesODBCDataSource)
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002618 write = FALSE;
2619 else
2620 {
Mike McCormack38d67a42005-08-22 09:15:23 +00002621 count = ACTION_GetSharedDLLsCount( comp->FullKeypath);
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002622 write = (count > 0);
2623
Mike McCormack38d67a42005-08-22 09:15:23 +00002624 if (comp->Attributes & msidbComponentAttributesSharedDllRefCount)
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002625 write = TRUE;
2626 }
2627
2628 /* increment counts */
Mike McCormack1da28582005-08-22 14:09:17 +00002629 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002630 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00002631 ComponentList *cl;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002632
Mike McCormack1da28582005-08-22 14:09:17 +00002633 if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ))
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002634 continue;
2635
Mike McCormack1da28582005-08-22 14:09:17 +00002636 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002637 {
Mike McCormack38d67a42005-08-22 09:15:23 +00002638 if ( cl->component == comp )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002639 count++;
2640 }
2641 }
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002642
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002643 /* decrement counts */
Mike McCormack1da28582005-08-22 14:09:17 +00002644 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002645 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00002646 ComponentList *cl;
2647
Mike McCormack1da28582005-08-22 14:09:17 +00002648 if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ABSENT ))
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002649 continue;
2650
Mike McCormack1da28582005-08-22 14:09:17 +00002651 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002652 {
Mike McCormack38d67a42005-08-22 09:15:23 +00002653 if ( cl->component == comp )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002654 count--;
2655 }
2656 }
2657
2658 /* ref count all the files in the component */
2659 if (write)
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002660 {
2661 MSIFILE *file;
2662
2663 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002664 {
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002665 if (file->Component == comp)
2666 ACTION_WriteSharedDLLsCount( file->TargetPath, count );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002667 }
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002668 }
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002669
2670 /* add a count for permenent */
Mike McCormack38d67a42005-08-22 09:15:23 +00002671 if (comp->Attributes & msidbComponentAttributesPermanent)
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002672 count ++;
2673
Mike McCormack38d67a42005-08-22 09:15:23 +00002674 comp->RefCount = count;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002675
2676 if (write)
Mike McCormack38d67a42005-08-22 09:15:23 +00002677 ACTION_WriteSharedDLLsCount( comp->FullKeypath, comp->RefCount );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002678}
2679
Aric Stewart2cf222f2004-07-06 19:00:23 +00002680/*
2681 * Ok further analysis makes me think that this work is
2682 * actually done in the PublishComponents and PublishFeatures
Mike McCormack3ece2462004-07-09 19:33:25 +00002683 * step, and not here. It appears like the keypath and all that is
2684 * resolved in this step, however actually written in the Publish steps.
Alexandre Julliard77b12762004-07-09 19:43:29 +00002685 * But we will leave it here for now because it is unclear
Aric Stewart2cf222f2004-07-06 19:00:23 +00002686 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002687static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
Aric Stewartb942e182004-07-06 18:50:02 +00002688{
Aric Stewart68b07492005-01-25 11:05:37 +00002689 WCHAR squished_pc[GUID_SIZE];
2690 WCHAR squished_cc[GUID_SIZE];
Aric Stewartb942e182004-07-06 18:50:02 +00002691 UINT rc;
Mike McCormack38d67a42005-08-22 09:15:23 +00002692 MSICOMPONENT *comp;
Aric Stewart68b07492005-01-25 11:05:37 +00002693 HKEY hkey=0,hkey2=0;
Aric Stewartb942e182004-07-06 18:50:02 +00002694
Aric Stewartb942e182004-07-06 18:50:02 +00002695 /* writes the Component and Features values to the registry */
Aric Stewartb942e182004-07-06 18:50:02 +00002696
Aric Stewart68b07492005-01-25 11:05:37 +00002697 rc = MSIREG_OpenComponents(&hkey);
Aric Stewartb942e182004-07-06 18:50:02 +00002698 if (rc != ERROR_SUCCESS)
Mike McCormackfe8cd382006-03-09 14:21:37 +09002699 return rc;
2700
Aric Stewartadaef112005-07-07 20:27:06 +00002701 squash_guid(package->ProductCode,squished_pc);
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002702 ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
Mike McCormack38d67a42005-08-22 09:15:23 +00002703
2704 LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
Aric Stewartb942e182004-07-06 18:50:02 +00002705 {
Mike McCormackfe8cd382006-03-09 14:21:37 +09002706 MSIRECORD * uirow;
2707
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002708 ui_progress(package,2,0,0,0);
Mike McCormackfe8cd382006-03-09 14:21:37 +09002709 if (!comp->ComponentId)
2710 continue;
Aric Stewartb942e182004-07-06 18:50:02 +00002711
Mike McCormackfe8cd382006-03-09 14:21:37 +09002712 squash_guid(comp->ComponentId,squished_cc);
Aric Stewartb942e182004-07-06 18:50:02 +00002713
Mike McCormackfe8cd382006-03-09 14:21:37 +09002714 msi_free(comp->FullKeypath);
2715 comp->FullKeypath = resolve_keypath( package, comp );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002716
Mike McCormackfe8cd382006-03-09 14:21:37 +09002717 /* do the refcounting */
2718 ACTION_RefCountComponent( package, comp );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002719
Mike McCormackfe8cd382006-03-09 14:21:37 +09002720 TRACE("Component %s (%s), Keypath=%s, RefCount=%i\n",
Mike McCormack38d67a42005-08-22 09:15:23 +00002721 debugstr_w(comp->Component),
Aric Stewartc5a14432005-05-18 17:46:12 +00002722 debugstr_w(squished_cc),
Mike McCormackfe8cd382006-03-09 14:21:37 +09002723 debugstr_w(comp->FullKeypath),
Mike McCormack38d67a42005-08-22 09:15:23 +00002724 comp->RefCount);
Mike McCormackfe8cd382006-03-09 14:21:37 +09002725 /*
2726 * Write the keypath out if the component is to be registered
2727 * and delete the key if the component is to be deregistered
2728 */
2729 if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
2730 {
2731 rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
2732 if (rc != ERROR_SUCCESS)
2733 continue;
2734
2735 if (!comp->FullKeypath)
2736 continue;
2737
2738 msi_reg_set_val_str( hkey2, squished_pc, comp->FullKeypath );
2739
2740 if (comp->Attributes & msidbComponentAttributesPermanent)
Aric Stewartfa384f62004-12-22 18:46:17 +00002741 {
Mike McCormackfe8cd382006-03-09 14:21:37 +09002742 static const WCHAR szPermKey[] =
2743 { '0','0','0','0','0','0','0','0','0','0','0','0',
2744 '0','0','0','0','0','0','0','0','0','0','0','0',
2745 '0','0','0','0','0','0','0','0',0 };
Aric Stewartb39d8fc2005-05-13 13:56:39 +00002746
Mike McCormackfe8cd382006-03-09 14:21:37 +09002747 msi_reg_set_val_str( hkey2, szPermKey, comp->FullKeypath );
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002748 }
Aric Stewartb39d8fc2005-05-13 13:56:39 +00002749
Mike McCormackfe8cd382006-03-09 14:21:37 +09002750 RegCloseKey(hkey2);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00002751
Mike McCormackfe8cd382006-03-09 14:21:37 +09002752 /* UI stuff */
2753 uirow = MSI_CreateRecord(3);
2754 MSI_RecordSetStringW(uirow,1,package->ProductCode);
2755 MSI_RecordSetStringW(uirow,2,comp->ComponentId);
2756 MSI_RecordSetStringW(uirow,3,comp->FullKeypath);
2757 ui_actiondata(package,szProcessComponents,uirow);
2758 msiobj_release( &uirow->hdr );
2759 }
2760 else if (ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ABSENT))
2761 {
2762 DWORD res;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00002763
Mike McCormackfe8cd382006-03-09 14:21:37 +09002764 rc = RegOpenKeyW(hkey,squished_cc,&hkey2);
2765 if (rc != ERROR_SUCCESS)
2766 continue;
2767
2768 RegDeleteValueW(hkey2,squished_pc);
2769
2770 /* if the key is empty delete it */
2771 res = RegEnumKeyExW(hkey2,0,NULL,0,0,NULL,0,NULL);
2772 RegCloseKey(hkey2);
2773 if (res == ERROR_NO_MORE_ITEMS)
2774 RegDeleteKeyW(hkey,squished_cc);
2775
2776 /* UI stuff */
2777 uirow = MSI_CreateRecord(2);
2778 MSI_RecordSetStringW(uirow,1,package->ProductCode);
2779 MSI_RecordSetStringW(uirow,2,comp->ComponentId);
2780 ui_actiondata(package,szProcessComponents,uirow);
2781 msiobj_release( &uirow->hdr );
Aric Stewartb942e182004-07-06 18:50:02 +00002782 }
2783 }
Aric Stewartb942e182004-07-06 18:50:02 +00002784 RegCloseKey(hkey);
2785 return rc;
2786}
2787
Aric Stewart6e821732005-03-30 10:19:08 +00002788typedef struct {
2789 CLSID clsid;
2790 LPWSTR source;
2791
2792 LPWSTR path;
2793 ITypeLib *ptLib;
2794} typelib_struct;
2795
Mike McCormackf9acfe62005-06-07 20:29:51 +00002796static BOOL CALLBACK Typelib_EnumResNameProc( HMODULE hModule, LPCWSTR lpszType,
Aric Stewart6e821732005-03-30 10:19:08 +00002797 LPWSTR lpszName, LONG_PTR lParam)
2798{
2799 TLIBATTR *attr;
2800 typelib_struct *tl_struct = (typelib_struct*) lParam;
2801 static const WCHAR fmt[] = {'%','s','\\','%','i',0};
2802 int sz;
2803 HRESULT res;
2804
2805 if (!IS_INTRESOURCE(lpszName))
2806 {
2807 ERR("Not Int Resource Name %s\n",debugstr_w(lpszName));
2808 return TRUE;
2809 }
2810
2811 sz = strlenW(tl_struct->source)+4;
2812 sz *= sizeof(WCHAR);
2813
Mike McCormack2acf8002006-05-25 11:41:39 +09002814 if ((INT_PTR)lpszName == 1)
Aric Stewartca8c4e42005-06-02 15:13:57 +00002815 tl_struct->path = strdupW(tl_struct->source);
2816 else
2817 {
Mike McCormackee034ba2005-09-20 11:59:14 +00002818 tl_struct->path = msi_alloc(sz);
Aric Stewartca8c4e42005-06-02 15:13:57 +00002819 sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName);
2820 }
Aric Stewart6e821732005-03-30 10:19:08 +00002821
2822 TRACE("trying %s\n", debugstr_w(tl_struct->path));
2823 res = LoadTypeLib(tl_struct->path,&tl_struct->ptLib);
2824 if (!SUCCEEDED(res))
2825 {
Mike McCormackee034ba2005-09-20 11:59:14 +00002826 msi_free(tl_struct->path);
Aric Stewart6e821732005-03-30 10:19:08 +00002827 tl_struct->path = NULL;
2828
2829 return TRUE;
2830 }
2831
2832 ITypeLib_GetLibAttr(tl_struct->ptLib, &attr);
2833 if (IsEqualGUID(&(tl_struct->clsid),&(attr->guid)))
2834 {
2835 ITypeLib_ReleaseTLibAttr(tl_struct->ptLib, attr);
2836 return FALSE;
2837 }
2838
Mike McCormackee034ba2005-09-20 11:59:14 +00002839 msi_free(tl_struct->path);
Aric Stewart6e821732005-03-30 10:19:08 +00002840 tl_struct->path = NULL;
2841
2842 ITypeLib_ReleaseTLibAttr(tl_struct->ptLib, attr);
2843 ITypeLib_Release(tl_struct->ptLib);
2844
2845 return TRUE;
2846}
2847
Aric Stewart234dc4b2005-06-22 18:27:34 +00002848static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param)
2849{
2850 MSIPACKAGE* package = (MSIPACKAGE*)param;
2851 LPCWSTR component;
Mike McCormack38d67a42005-08-22 09:15:23 +00002852 MSICOMPONENT *comp;
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002853 MSIFILE *file;
Aric Stewart234dc4b2005-06-22 18:27:34 +00002854 typelib_struct tl_struct;
2855 HMODULE module;
2856 static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0};
2857
2858 component = MSI_RecordGetString(row,3);
Mike McCormack38d67a42005-08-22 09:15:23 +00002859 comp = get_loaded_component(package,component);
2860 if (!comp)
Aric Stewart234dc4b2005-06-22 18:27:34 +00002861 return ERROR_SUCCESS;
2862
Mike McCormackd693f462005-10-29 11:36:48 +00002863 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
Aric Stewart234dc4b2005-06-22 18:27:34 +00002864 {
2865 TRACE("Skipping typelib reg due to disabled component\n");
2866
Mike McCormack38d67a42005-08-22 09:15:23 +00002867 comp->Action = comp->Installed;
Aric Stewart234dc4b2005-06-22 18:27:34 +00002868
2869 return ERROR_SUCCESS;
2870 }
2871
Mike McCormack38d67a42005-08-22 09:15:23 +00002872 comp->Action = INSTALLSTATE_LOCAL;
Aric Stewart234dc4b2005-06-22 18:27:34 +00002873
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002874 file = get_loaded_file( package, comp->KeyPath );
2875 if (!file)
Aric Stewart234dc4b2005-06-22 18:27:34 +00002876 return ERROR_SUCCESS;
2877
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002878 module = LoadLibraryExW( file->TargetPath, NULL, LOAD_LIBRARY_AS_DATAFILE );
Mike McCormack51c66182005-10-27 12:36:12 +00002879 if (module)
Aric Stewart234dc4b2005-06-22 18:27:34 +00002880 {
Mike McCormack51c66182005-10-27 12:36:12 +00002881 LPCWSTR guid;
2882 guid = MSI_RecordGetString(row,1);
2883 CLSIDFromString((LPWSTR)guid, &tl_struct.clsid);
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002884 tl_struct.source = strdupW( file->TargetPath );
Aric Stewart234dc4b2005-06-22 18:27:34 +00002885 tl_struct.path = NULL;
2886
2887 EnumResourceNamesW(module, szTYPELIB, Typelib_EnumResNameProc,
2888 (LONG_PTR)&tl_struct);
2889
Mike McCormack51c66182005-10-27 12:36:12 +00002890 if (tl_struct.path)
Aric Stewart234dc4b2005-06-22 18:27:34 +00002891 {
2892 LPWSTR help = NULL;
2893 LPCWSTR helpid;
2894 HRESULT res;
2895
2896 helpid = MSI_RecordGetString(row,6);
2897
2898 if (helpid)
2899 help = resolve_folder(package,helpid,FALSE,FALSE,NULL);
2900 res = RegisterTypeLib(tl_struct.ptLib,tl_struct.path,help);
Mike McCormackee034ba2005-09-20 11:59:14 +00002901 msi_free(help);
Aric Stewart234dc4b2005-06-22 18:27:34 +00002902
2903 if (!SUCCEEDED(res))
2904 ERR("Failed to register type library %s\n",
2905 debugstr_w(tl_struct.path));
2906 else
2907 {
2908 ui_actiondata(package,szRegisterTypeLibraries,row);
2909
2910 TRACE("Registered %s\n", debugstr_w(tl_struct.path));
2911 }
2912
2913 ITypeLib_Release(tl_struct.ptLib);
Mike McCormackee034ba2005-09-20 11:59:14 +00002914 msi_free(tl_struct.path);
Aric Stewart234dc4b2005-06-22 18:27:34 +00002915 }
2916 else
2917 ERR("Failed to load type library %s\n",
2918 debugstr_w(tl_struct.source));
2919
2920 FreeLibrary(module);
Mike McCormackee034ba2005-09-20 11:59:14 +00002921 msi_free(tl_struct.source);
Aric Stewart234dc4b2005-06-22 18:27:34 +00002922 }
2923 else
Mike McCormacke18f8ab2005-08-23 10:03:17 +00002924 ERR("Could not load file! %s\n", debugstr_w(file->TargetPath));
Aric Stewart234dc4b2005-06-22 18:27:34 +00002925
2926 return ERROR_SUCCESS;
2927}
2928
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002929static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
Aric Stewartfcb20c52004-07-06 18:51:16 +00002930{
2931 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00002932 * OK this is a bit confusing.. I am given a _Component key and I believe
Aric Stewartfcb20c52004-07-06 18:51:16 +00002933 * that the file that is being registered as a type library is the "key file
Mike McCormackc90c7812004-07-09 22:58:27 +00002934 * of that component" which I interpret to mean "The file in the KeyPath of
2935 * that component".
Aric Stewartfcb20c52004-07-06 18:51:16 +00002936 */
2937 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002938 MSIQUERY * view;
Aric Stewart8e233e92005-03-01 11:45:19 +00002939 static const WCHAR Query[] =
2940 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00002941 '`','T','y','p','e','L','i','b','`',0};
Aric Stewartfcb20c52004-07-06 18:51:16 +00002942
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002943 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewartfcb20c52004-07-06 18:51:16 +00002944 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002945 return ERROR_SUCCESS;
Aric Stewartfcb20c52004-07-06 18:51:16 +00002946
Aric Stewart234dc4b2005-06-22 18:27:34 +00002947 rc = MSI_IterateRecords(view, NULL, ITERATE_RegisterTypeLibraries, package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002948 msiobj_release(&view->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00002949 return rc;
Aric Stewartfcb20c52004-07-06 18:51:16 +00002950}
2951
Aric Stewart9adacf62005-06-24 11:58:21 +00002952static UINT ITERATE_CreateShortcuts(MSIRECORD *row, LPVOID param)
Aric Stewart2cf222f2004-07-06 19:00:23 +00002953{
Aric Stewart9adacf62005-06-24 11:58:21 +00002954 MSIPACKAGE *package = (MSIPACKAGE*)param;
Mike McCormack477bce32006-01-16 20:38:28 +01002955 LPWSTR target_file, target_folder, filename;
Robert Shearman4ac85672006-02-22 16:31:00 +00002956 LPCWSTR buffer, extension;
Mike McCormack38d67a42005-08-22 09:15:23 +00002957 MSICOMPONENT *comp;
Aric Stewart9adacf62005-06-24 11:58:21 +00002958 static const WCHAR szlnk[]={'.','l','n','k',0};
Mike McCormack20c57462006-05-24 17:41:04 +09002959 IShellLinkW *sl = NULL;
2960 IPersistFile *pf = NULL;
Aric Stewart2cf222f2004-07-06 19:00:23 +00002961 HRESULT res;
2962
Aric Stewart9adacf62005-06-24 11:58:21 +00002963 buffer = MSI_RecordGetString(row,4);
Mike McCormack38d67a42005-08-22 09:15:23 +00002964 comp = get_loaded_component(package,buffer);
2965 if (!comp)
Aric Stewart9adacf62005-06-24 11:58:21 +00002966 return ERROR_SUCCESS;
2967
Mike McCormackd693f462005-10-29 11:36:48 +00002968 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ))
Aric Stewart9adacf62005-06-24 11:58:21 +00002969 {
2970 TRACE("Skipping shortcut creation due to disabled component\n");
2971
Mike McCormack38d67a42005-08-22 09:15:23 +00002972 comp->Action = comp->Installed;
Aric Stewart9adacf62005-06-24 11:58:21 +00002973
2974 return ERROR_SUCCESS;
2975 }
2976
Mike McCormack38d67a42005-08-22 09:15:23 +00002977 comp->Action = INSTALLSTATE_LOCAL;
Aric Stewart9adacf62005-06-24 11:58:21 +00002978
2979 ui_actiondata(package,szCreateShortcuts,row);
2980
2981 res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
2982 &IID_IShellLinkW, (LPVOID *) &sl );
2983
Mike McCormack20c57462006-05-24 17:41:04 +09002984 if (FAILED( res ))
Aric Stewart9adacf62005-06-24 11:58:21 +00002985 {
Mike McCormack20c57462006-05-24 17:41:04 +09002986 ERR("CLSID_ShellLink not available\n");
2987 goto err;
Aric Stewart9adacf62005-06-24 11:58:21 +00002988 }
2989
2990 res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
Mike McCormack20c57462006-05-24 17:41:04 +09002991 if (FAILED( res ))
Aric Stewart9adacf62005-06-24 11:58:21 +00002992 {
Mike McCormack20c57462006-05-24 17:41:04 +09002993 ERR("QueryInterface(IID_IPersistFile) failed\n");
2994 goto err;
Aric Stewart9adacf62005-06-24 11:58:21 +00002995 }
2996
2997 buffer = MSI_RecordGetString(row,2);
2998 target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);
2999
3000 /* may be needed because of a bug somehwere else */
3001 create_full_pathW(target_folder);
3002
Mike McCormack477bce32006-01-16 20:38:28 +01003003 filename = msi_dup_record_field( row, 3 );
Aric Stewart9adacf62005-06-24 11:58:21 +00003004 reduce_to_longfilename(filename);
Robert Shearman4ac85672006-02-22 16:31:00 +00003005
3006 extension = strchrW(filename,'.');
3007 if (!extension || strcmpiW(extension,szlnk))
3008 {
3009 int len = strlenW(filename);
3010 filename = msi_realloc(filename, len * sizeof(WCHAR) + sizeof(szlnk));
3011 memcpy(filename + len, szlnk, sizeof(szlnk));
3012 }
Aric Stewart9adacf62005-06-24 11:58:21 +00003013 target_file = build_directory_name(2, target_folder, filename);
Mike McCormackee034ba2005-09-20 11:59:14 +00003014 msi_free(target_folder);
Mike McCormack477bce32006-01-16 20:38:28 +01003015 msi_free(filename);
Aric Stewart9adacf62005-06-24 11:58:21 +00003016
3017 buffer = MSI_RecordGetString(row,5);
3018 if (strchrW(buffer,'['))
3019 {
3020 LPWSTR deformated;
3021 deformat_string(package,buffer,&deformated);
3022 IShellLinkW_SetPath(sl,deformated);
Mike McCormackee034ba2005-09-20 11:59:14 +00003023 msi_free(deformated);
Aric Stewart9adacf62005-06-24 11:58:21 +00003024 }
3025 else
3026 {
Aric Stewart9adacf62005-06-24 11:58:21 +00003027 FIXME("poorly handled shortcut format, advertised shortcut\n");
Mike McCormack566c69e2005-09-22 10:49:17 +00003028 IShellLinkW_SetPath(sl,comp->FullKeypath);
Aric Stewart9adacf62005-06-24 11:58:21 +00003029 }
3030
3031 if (!MSI_RecordIsNull(row,6))
3032 {
3033 LPWSTR deformated;
3034 buffer = MSI_RecordGetString(row,6);
3035 deformat_string(package,buffer,&deformated);
3036 IShellLinkW_SetArguments(sl,deformated);
Mike McCormackee034ba2005-09-20 11:59:14 +00003037 msi_free(deformated);
Aric Stewart9adacf62005-06-24 11:58:21 +00003038 }
3039
3040 if (!MSI_RecordIsNull(row,7))
3041 {
3042 buffer = MSI_RecordGetString(row,7);
3043 IShellLinkW_SetDescription(sl,buffer);
3044 }
3045
3046 if (!MSI_RecordIsNull(row,8))
3047 IShellLinkW_SetHotkey(sl,MSI_RecordGetInteger(row,8));
3048
3049 if (!MSI_RecordIsNull(row,9))
3050 {
Mike McCormack75658d72005-09-22 10:33:57 +00003051 LPWSTR Path;
Aric Stewart9adacf62005-06-24 11:58:21 +00003052 INT index;
3053
3054 buffer = MSI_RecordGetString(row,9);
3055
Mike McCormack75658d72005-09-22 10:33:57 +00003056 Path = build_icon_path(package,buffer);
Aric Stewart9adacf62005-06-24 11:58:21 +00003057 index = MSI_RecordGetInteger(row,10);
3058
Robert Shearmanab378802006-08-03 20:24:10 +01003059 /* no value means 0 */
3060 if (index == MSI_NULL_INTEGER)
3061 index = 0;
3062
Aric Stewart9adacf62005-06-24 11:58:21 +00003063 IShellLinkW_SetIconLocation(sl,Path,index);
Mike McCormackee034ba2005-09-20 11:59:14 +00003064 msi_free(Path);
Aric Stewart9adacf62005-06-24 11:58:21 +00003065 }
3066
3067 if (!MSI_RecordIsNull(row,11))
3068 IShellLinkW_SetShowCmd(sl,MSI_RecordGetInteger(row,11));
3069
3070 if (!MSI_RecordIsNull(row,12))
3071 {
3072 LPWSTR Path;
3073 buffer = MSI_RecordGetString(row,12);
3074 Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
Mike McCormack43f7f3e2006-07-27 23:18:15 +09003075 if (Path)
3076 IShellLinkW_SetWorkingDirectory(sl,Path);
Mike McCormackee034ba2005-09-20 11:59:14 +00003077 msi_free(Path);
Aric Stewart9adacf62005-06-24 11:58:21 +00003078 }
3079
3080 TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
3081 IPersistFile_Save(pf,target_file,FALSE);
3082
Mike McCormackee034ba2005-09-20 11:59:14 +00003083 msi_free(target_file);
Aric Stewart9adacf62005-06-24 11:58:21 +00003084
Mike McCormack20c57462006-05-24 17:41:04 +09003085err:
3086 if (pf)
3087 IPersistFile_Release( pf );
3088 if (sl)
3089 IShellLinkW_Release( sl );
Aric Stewart9adacf62005-06-24 11:58:21 +00003090
3091 return ERROR_SUCCESS;
3092}
3093
3094static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
3095{
3096 UINT rc;
3097 HRESULT res;
3098 MSIQUERY * view;
3099 static const WCHAR Query[] =
3100 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
3101 '`','S','h','o','r','t','c','u','t','`',0};
3102
Aric Stewart9adacf62005-06-24 11:58:21 +00003103 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
3104 if (rc != ERROR_SUCCESS)
3105 return ERROR_SUCCESS;
3106
Aric Stewart2cf222f2004-07-06 19:00:23 +00003107 res = CoInitialize( NULL );
3108 if (FAILED (res))
3109 {
3110 ERR("CoInitialize failed\n");
3111 return ERROR_FUNCTION_FAILED;
3112 }
3113
Aric Stewart9adacf62005-06-24 11:58:21 +00003114 rc = MSI_IterateRecords(view, NULL, ITERATE_CreateShortcuts, package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003115 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00003116
Aric Stewart2cf222f2004-07-06 19:00:23 +00003117 CoUninitialize();
3118
3119 return rc;
3120}
3121
Aric Stewart916ef942005-06-22 18:42:19 +00003122static UINT ITERATE_PublishProduct(MSIRECORD *row, LPVOID param)
3123{
3124 MSIPACKAGE* package = (MSIPACKAGE*)param;
3125 HANDLE the_file;
Mike McCormack75658d72005-09-22 10:33:57 +00003126 LPWSTR FilePath;
3127 LPCWSTR FileName;
Aric Stewart916ef942005-06-22 18:42:19 +00003128 CHAR buffer[1024];
3129 DWORD sz;
3130 UINT rc;
Robert Shearmand2e48e02006-01-23 17:29:50 +01003131 MSIRECORD *uirow;
Aric Stewart916ef942005-06-22 18:42:19 +00003132
3133 FileName = MSI_RecordGetString(row,1);
3134 if (!FileName)
3135 {
3136 ERR("Unable to get FileName\n");
3137 return ERROR_SUCCESS;
3138 }
3139
Mike McCormack75658d72005-09-22 10:33:57 +00003140 FilePath = build_icon_path(package,FileName);
Aric Stewart916ef942005-06-22 18:42:19 +00003141
3142 TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
3143
3144 the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
3145 FILE_ATTRIBUTE_NORMAL, NULL);
3146
3147 if (the_file == INVALID_HANDLE_VALUE)
3148 {
3149 ERR("Unable to create file %s\n",debugstr_w(FilePath));
Mike McCormackee034ba2005-09-20 11:59:14 +00003150 msi_free(FilePath);
Aric Stewart916ef942005-06-22 18:42:19 +00003151 return ERROR_SUCCESS;
3152 }
3153
3154 do
3155 {
3156 DWORD write;
3157 sz = 1024;
3158 rc = MSI_RecordReadStream(row,2,buffer,&sz);
3159 if (rc != ERROR_SUCCESS)
3160 {
3161 ERR("Failed to get stream\n");
3162 CloseHandle(the_file);
3163 DeleteFileW(FilePath);
3164 break;
3165 }
3166 WriteFile(the_file,buffer,sz,&write,NULL);
3167 } while (sz == 1024);
3168
Mike McCormackee034ba2005-09-20 11:59:14 +00003169 msi_free(FilePath);
Aric Stewart916ef942005-06-22 18:42:19 +00003170
3171 CloseHandle(the_file);
Robert Shearmand2e48e02006-01-23 17:29:50 +01003172
3173 uirow = MSI_CreateRecord(1);
3174 MSI_RecordSetStringW(uirow,1,FileName);
3175 ui_actiondata(package,szPublishProduct,uirow);
3176 msiobj_release( &uirow->hdr );
3177
Aric Stewart916ef942005-06-22 18:42:19 +00003178 return ERROR_SUCCESS;
3179}
Aric Stewart2cf222f2004-07-06 19:00:23 +00003180
3181/*
3182 * 99% of the work done here is only done for
3183 * advertised installs. However this is where the
3184 * Icon table is processed and written out
Francois Gouget817c5202004-07-16 19:15:40 +00003185 * so that is what I am going to do here.
Aric Stewart2cf222f2004-07-06 19:00:23 +00003186 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003187static UINT ACTION_PublishProduct(MSIPACKAGE *package)
Aric Stewart2cf222f2004-07-06 19:00:23 +00003188{
3189 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003190 MSIQUERY * view;
Aric Stewart8e233e92005-03-01 11:45:19 +00003191 static const WCHAR Query[]=
3192 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00003193 '`','I','c','o','n','`',0};
Aric Stewart6269f002005-01-17 13:40:39 +00003194 /* for registry stuff */
Aric Stewart68b07492005-01-25 11:05:37 +00003195 HKEY hkey=0;
3196 HKEY hukey=0;
Aric Stewart6957e4a2005-06-08 19:16:45 +00003197 static const WCHAR szProductLanguage[] =
3198 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
Aric Stewart6957e4a2005-06-08 19:16:45 +00003199 static const WCHAR szARPProductIcon[] =
3200 {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0};
Aric Stewartc28bb542005-06-09 15:49:11 +00003201 static const WCHAR szProductVersion[] =
3202 {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
Aric Stewart6957e4a2005-06-08 19:16:45 +00003203 DWORD langid;
Aric Stewart6269f002005-01-17 13:40:39 +00003204 LPWSTR buffer;
3205 DWORD size;
Aric Stewart68b07492005-01-25 11:05:37 +00003206 MSIHANDLE hDb, hSumInfo;
Aric Stewart2cf222f2004-07-06 19:00:23 +00003207
Aric Stewart916ef942005-06-22 18:42:19 +00003208 /* write out icon files */
3209
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003210 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart916ef942005-06-22 18:42:19 +00003211 if (rc == ERROR_SUCCESS)
Aric Stewart2cf222f2004-07-06 19:00:23 +00003212 {
Aric Stewart916ef942005-06-22 18:42:19 +00003213 MSI_IterateRecords(view, NULL, ITERATE_PublishProduct, package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003214 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00003215 }
3216
Francois Gougetda8b3dd2005-01-26 21:09:04 +00003217 /* ok there is a lot more done here but i need to figure out what */
Aric Stewart916ef942005-06-22 18:42:19 +00003218
Aric Stewartadaef112005-07-07 20:27:06 +00003219 rc = MSIREG_OpenProductsKey(package->ProductCode,&hkey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00003220 if (rc != ERROR_SUCCESS)
3221 goto end;
3222
Aric Stewartadaef112005-07-07 20:27:06 +00003223 rc = MSIREG_OpenUserProductsKey(package->ProductCode,&hukey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00003224 if (rc != ERROR_SUCCESS)
3225 goto end;
3226
Aric Stewart6269f002005-01-17 13:40:39 +00003227
Mike McCormack062ad502005-09-15 15:04:08 +00003228 buffer = msi_dup_property( package, INSTALLPROPERTY_PRODUCTNAMEW );
Mike McCormack4db02cd2005-09-15 14:58:38 +00003229 msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTNAMEW, buffer );
Mike McCormackee034ba2005-09-20 11:59:14 +00003230 msi_free(buffer);
Aric Stewart6957e4a2005-06-08 19:16:45 +00003231
Mike McCormack74f0de92005-09-29 10:32:39 +00003232 langid = msi_get_property_int( package, szProductLanguage, 0 );
Mike McCormack4db02cd2005-09-15 14:58:38 +00003233 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
Aric Stewart6957e4a2005-06-08 19:16:45 +00003234
Mike McCormack062ad502005-09-15 15:04:08 +00003235 buffer = msi_dup_property( package, szARPProductIcon );
Aric Stewart6957e4a2005-06-08 19:16:45 +00003236 if (buffer)
3237 {
Mike McCormack75658d72005-09-22 10:33:57 +00003238 LPWSTR path = build_icon_path(package,buffer);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003239 msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTICONW, path );
Mike McCormack75658d72005-09-22 10:33:57 +00003240 msi_free( path );
Aric Stewart6957e4a2005-06-08 19:16:45 +00003241 }
Mike McCormackee034ba2005-09-20 11:59:14 +00003242 msi_free(buffer);
Aric Stewartc28bb542005-06-09 15:49:11 +00003243
Mike McCormack062ad502005-09-15 15:04:08 +00003244 buffer = msi_dup_property( package, szProductVersion );
Aric Stewartc28bb542005-06-09 15:49:11 +00003245 if (buffer)
3246 {
Mike McCormack230af9d2006-07-14 15:19:08 +09003247 DWORD verdword = msi_version_str_to_dword(buffer);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003248 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
Aric Stewartc28bb542005-06-09 15:49:11 +00003249 }
Mike McCormackee034ba2005-09-20 11:59:14 +00003250 msi_free(buffer);
Aric Stewart6957e4a2005-06-08 19:16:45 +00003251
Mike McCormackb7270b82005-12-31 13:18:11 +01003252 /* FIXME: Need to write more keys to the user registry */
Aric Stewart68b07492005-01-25 11:05:37 +00003253
Aric Stewart7e7b8cf2005-02-18 20:00:34 +00003254 hDb= alloc_msihandle( &package->db->hdr );
Dan Kegel337e1e22006-08-28 09:44:35 -07003255 if (!hDb) {
3256 rc = ERROR_NOT_ENOUGH_MEMORY;
3257 goto end;
3258 }
Aric Stewart68b07492005-01-25 11:05:37 +00003259 rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo);
Aric Stewart7e7b8cf2005-02-18 20:00:34 +00003260 MsiCloseHandle(hDb);
Aric Stewart68b07492005-01-25 11:05:37 +00003261 if (rc == ERROR_SUCCESS)
3262 {
3263 WCHAR guidbuffer[0x200];
3264 size = 0x200;
Aric Stewart7e7b8cf2005-02-18 20:00:34 +00003265 rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL,
Aric Stewart68b07492005-01-25 11:05:37 +00003266 guidbuffer, &size);
3267 if (rc == ERROR_SUCCESS)
3268 {
3269 WCHAR squashed[GUID_SIZE];
3270 /* for now we only care about the first guid */
3271 LPWSTR ptr = strchrW(guidbuffer,';');
3272 if (ptr) *ptr = 0;
3273 squash_guid(guidbuffer,squashed);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003274 msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, squashed );
Aric Stewart68b07492005-01-25 11:05:37 +00003275 }
3276 else
3277 {
Francois Gouget0edbaf72005-11-10 12:14:56 +00003278 ERR("Unable to query Revision_Number...\n");
Aric Stewart68b07492005-01-25 11:05:37 +00003279 rc = ERROR_SUCCESS;
3280 }
3281 MsiCloseHandle(hSumInfo);
3282 }
3283 else
3284 {
3285 ERR("Unable to open Summary Information\n");
3286 rc = ERROR_SUCCESS;
3287 }
Aric Stewart2cae30b2005-01-19 19:07:40 +00003288
Aric Stewart6269f002005-01-17 13:40:39 +00003289end:
3290
Aric Stewart6269f002005-01-17 13:40:39 +00003291 RegCloseKey(hkey);
Aric Stewart6269f002005-01-17 13:40:39 +00003292 RegCloseKey(hukey);
3293
Aric Stewart2cf222f2004-07-06 19:00:23 +00003294 return rc;
Aric Stewart2cf222f2004-07-06 19:00:23 +00003295}
3296
Aric Stewartaded32f2005-06-23 09:46:31 +00003297static UINT ITERATE_WriteIniValues(MSIRECORD *row, LPVOID param)
3298{
3299 MSIPACKAGE *package = (MSIPACKAGE*)param;
3300 LPCWSTR component,section,key,value,identifier,filename,dirproperty;
3301 LPWSTR deformated_section, deformated_key, deformated_value;
3302 LPWSTR folder, fullname = NULL;
3303 MSIRECORD * uirow;
Mike McCormack38d67a42005-08-22 09:15:23 +00003304 INT action;
3305 MSICOMPONENT *comp;
Aric Stewartaded32f2005-06-23 09:46:31 +00003306 static const WCHAR szWindowsFolder[] =
3307 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
3308
3309 component = MSI_RecordGetString(row, 8);
Mike McCormack38d67a42005-08-22 09:15:23 +00003310 comp = get_loaded_component(package,component);
Aric Stewartaded32f2005-06-23 09:46:31 +00003311
Mike McCormackd693f462005-10-29 11:36:48 +00003312 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL))
Aric Stewartaded32f2005-06-23 09:46:31 +00003313 {
3314 TRACE("Skipping ini file due to disabled component %s\n",
3315 debugstr_w(component));
3316
Mike McCormack38d67a42005-08-22 09:15:23 +00003317 comp->Action = comp->Installed;
Aric Stewartaded32f2005-06-23 09:46:31 +00003318
3319 return ERROR_SUCCESS;
3320 }
3321
Mike McCormack38d67a42005-08-22 09:15:23 +00003322 comp->Action = INSTALLSTATE_LOCAL;
Aric Stewartaded32f2005-06-23 09:46:31 +00003323
3324 identifier = MSI_RecordGetString(row,1);
3325 filename = MSI_RecordGetString(row,2);
3326 dirproperty = MSI_RecordGetString(row,3);
3327 section = MSI_RecordGetString(row,4);
3328 key = MSI_RecordGetString(row,5);
3329 value = MSI_RecordGetString(row,6);
3330 action = MSI_RecordGetInteger(row,7);
3331
3332 deformat_string(package,section,&deformated_section);
3333 deformat_string(package,key,&deformated_key);
3334 deformat_string(package,value,&deformated_value);
3335
3336 if (dirproperty)
3337 {
3338 folder = resolve_folder(package, dirproperty, FALSE, FALSE, NULL);
3339 if (!folder)
Mike McCormack062ad502005-09-15 15:04:08 +00003340 folder = msi_dup_property( package, dirproperty );
Aric Stewartaded32f2005-06-23 09:46:31 +00003341 }
3342 else
Mike McCormack062ad502005-09-15 15:04:08 +00003343 folder = msi_dup_property( package, szWindowsFolder );
Aric Stewartaded32f2005-06-23 09:46:31 +00003344
3345 if (!folder)
3346 {
3347 ERR("Unable to resolve folder! (%s)\n",debugstr_w(dirproperty));
3348 goto cleanup;
3349 }
3350
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003351 fullname = build_directory_name(2, folder, filename);
Aric Stewartaded32f2005-06-23 09:46:31 +00003352
3353 if (action == 0)
3354 {
3355 TRACE("Adding value %s to section %s in %s\n",
3356 debugstr_w(deformated_key), debugstr_w(deformated_section),
3357 debugstr_w(fullname));
3358 WritePrivateProfileStringW(deformated_section, deformated_key,
3359 deformated_value, fullname);
3360 }
3361 else if (action == 1)
3362 {
3363 WCHAR returned[10];
3364 GetPrivateProfileStringW(deformated_section, deformated_key, NULL,
3365 returned, 10, fullname);
3366 if (returned[0] == 0)
3367 {
3368 TRACE("Adding value %s to section %s in %s\n",
3369 debugstr_w(deformated_key), debugstr_w(deformated_section),
3370 debugstr_w(fullname));
3371
3372 WritePrivateProfileStringW(deformated_section, deformated_key,
3373 deformated_value, fullname);
3374 }
3375 }
3376 else if (action == 3)
3377 FIXME("Append to existing section not yet implemented\n");
3378
3379 uirow = MSI_CreateRecord(4);
3380 MSI_RecordSetStringW(uirow,1,identifier);
3381 MSI_RecordSetStringW(uirow,2,deformated_section);
3382 MSI_RecordSetStringW(uirow,3,deformated_key);
3383 MSI_RecordSetStringW(uirow,4,deformated_value);
3384 ui_actiondata(package,szWriteIniValues,uirow);
3385 msiobj_release( &uirow->hdr );
3386cleanup:
Mike McCormackee034ba2005-09-20 11:59:14 +00003387 msi_free(fullname);
3388 msi_free(folder);
3389 msi_free(deformated_key);
3390 msi_free(deformated_value);
3391 msi_free(deformated_section);
Aric Stewartaded32f2005-06-23 09:46:31 +00003392 return ERROR_SUCCESS;
3393}
3394
Aric Stewart516a9c72005-01-14 15:59:26 +00003395static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
3396{
3397 UINT rc;
3398 MSIQUERY * view;
Aric Stewart8e233e92005-03-01 11:45:19 +00003399 static const WCHAR ExecSeqQuery[] =
3400 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00003401 '`','I','n','i','F','i','l','e','`',0};
Aric Stewart516a9c72005-01-14 15:59:26 +00003402
3403 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
3404 if (rc != ERROR_SUCCESS)
3405 {
3406 TRACE("no IniFile table\n");
3407 return ERROR_SUCCESS;
3408 }
3409
Aric Stewartaded32f2005-06-23 09:46:31 +00003410 rc = MSI_IterateRecords(view, NULL, ITERATE_WriteIniValues, package);
Aric Stewart516a9c72005-01-14 15:59:26 +00003411 msiobj_release(&view->hdr);
3412 return rc;
3413}
3414
Aric Stewart854bfc42005-06-24 11:33:02 +00003415static UINT ITERATE_SelfRegModules(MSIRECORD *row, LPVOID param)
Aric Stewart6269f002005-01-17 13:40:39 +00003416{
Aric Stewart854bfc42005-06-24 11:33:02 +00003417 MSIPACKAGE *package = (MSIPACKAGE*)param;
3418 LPCWSTR filename;
3419 LPWSTR FullName;
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003420 MSIFILE *file;
Aric Stewart854bfc42005-06-24 11:33:02 +00003421 DWORD len;
Aric Stewart8e233e92005-03-01 11:45:19 +00003422 static const WCHAR ExeStr[] =
Aric Stewartc5a14432005-05-18 17:46:12 +00003423 {'r','e','g','s','v','r','3','2','.','e','x','e',' ','\"',0};
3424 static const WCHAR close[] = {'\"',0};
Aric Stewart2cae30b2005-01-19 19:07:40 +00003425 STARTUPINFOW si;
3426 PROCESS_INFORMATION info;
3427 BOOL brc;
Robert Shearmand2e48e02006-01-23 17:29:50 +01003428 MSIRECORD *uirow;
3429 LPWSTR uipath, p;
Aric Stewart2cae30b2005-01-19 19:07:40 +00003430
3431 memset(&si,0,sizeof(STARTUPINFOW));
3432
Aric Stewart854bfc42005-06-24 11:33:02 +00003433 filename = MSI_RecordGetString(row,1);
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003434 file = get_loaded_file( package, filename );
Aric Stewart854bfc42005-06-24 11:33:02 +00003435
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003436 if (!file)
Aric Stewart854bfc42005-06-24 11:33:02 +00003437 {
3438 ERR("Unable to find file id %s\n",debugstr_w(filename));
3439 return ERROR_SUCCESS;
3440 }
3441
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003442 len = strlenW(ExeStr) + strlenW( file->TargetPath ) + 2;
Aric Stewart854bfc42005-06-24 11:33:02 +00003443
Mike McCormackee034ba2005-09-20 11:59:14 +00003444 FullName = msi_alloc(len*sizeof(WCHAR));
Aric Stewart854bfc42005-06-24 11:33:02 +00003445 strcpyW(FullName,ExeStr);
Mike McCormacke18f8ab2005-08-23 10:03:17 +00003446 strcatW( FullName, file->TargetPath );
Aric Stewart854bfc42005-06-24 11:33:02 +00003447 strcatW(FullName,close);
3448
3449 TRACE("Registering %s\n",debugstr_w(FullName));
3450 brc = CreateProcessW(NULL, FullName, NULL, NULL, FALSE, 0, NULL, c_colon,
3451 &si, &info);
3452
3453 if (brc)
3454 msi_dialog_check_messages(info.hProcess);
3455
Mike McCormackee034ba2005-09-20 11:59:14 +00003456 msi_free(FullName);
Robert Shearmand2e48e02006-01-23 17:29:50 +01003457
3458 /* the UI chunk */
3459 uirow = MSI_CreateRecord( 2 );
3460 uipath = strdupW( file->TargetPath );
3461 p = strrchrW(uipath,'\\');
3462 if (p)
3463 p[1]=0;
3464 MSI_RecordSetStringW( uirow, 1, &p[2] );
3465 MSI_RecordSetStringW( uirow, 2, uipath);
3466 ui_actiondata( package, szSelfRegModules, uirow);
3467 msiobj_release( &uirow->hdr );
3468 msi_free( uipath );
3469 /* FIXME: call ui_progress? */
3470
Aric Stewart854bfc42005-06-24 11:33:02 +00003471 return ERROR_SUCCESS;
3472}
3473
3474static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
3475{
3476 UINT rc;
3477 MSIQUERY * view;
3478 static const WCHAR ExecSeqQuery[] =
3479 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
3480 '`','S','e','l','f','R','e','g','`',0};
3481
Aric Stewart6269f002005-01-17 13:40:39 +00003482 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
3483 if (rc != ERROR_SUCCESS)
3484 {
3485 TRACE("no SelfReg table\n");
3486 return ERROR_SUCCESS;
3487 }
3488
Aric Stewart854bfc42005-06-24 11:33:02 +00003489 MSI_IterateRecords(view, NULL, ITERATE_SelfRegModules, package);
Aric Stewart6269f002005-01-17 13:40:39 +00003490 msiobj_release(&view->hdr);
Aric Stewart854bfc42005-06-24 11:33:02 +00003491
3492 return ERROR_SUCCESS;
Aric Stewart6269f002005-01-17 13:40:39 +00003493}
3494
3495static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
3496{
Mike McCormack1da28582005-08-22 14:09:17 +00003497 MSIFEATURE *feature;
Aric Stewart6269f002005-01-17 13:40:39 +00003498 UINT rc;
Aric Stewart68b07492005-01-25 11:05:37 +00003499 HKEY hkey=0;
3500 HKEY hukey=0;
Aric Stewart68b07492005-01-25 11:05:37 +00003501
Aric Stewartadaef112005-07-07 20:27:06 +00003502 rc = MSIREG_OpenFeaturesKey(package->ProductCode,&hkey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00003503 if (rc != ERROR_SUCCESS)
3504 goto end;
3505
Aric Stewartadaef112005-07-07 20:27:06 +00003506 rc = MSIREG_OpenUserFeaturesKey(package->ProductCode,&hukey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00003507 if (rc != ERROR_SUCCESS)
3508 goto end;
3509
3510 /* here the guids are base 85 encoded */
Mike McCormack1da28582005-08-22 14:09:17 +00003511 LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
Aric Stewart6269f002005-01-17 13:40:39 +00003512 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00003513 ComponentList *cl;
Aric Stewart6269f002005-01-17 13:40:39 +00003514 LPWSTR data = NULL;
3515 GUID clsid;
Aric Stewart6269f002005-01-17 13:40:39 +00003516 INT size;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003517 BOOL absent = FALSE;
Robert Shearmand2e48e02006-01-23 17:29:50 +01003518 MSIRECORD *uirow;
Aric Stewart6269f002005-01-17 13:40:39 +00003519
Mike McCormack1da28582005-08-22 14:09:17 +00003520 if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ) &&
3521 !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_SOURCE ) &&
3522 !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003523 absent = TRUE;
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00003524
Mike McCormack3f2d5d72005-08-19 10:03:11 +00003525 size = 1;
Mike McCormack1da28582005-08-22 14:09:17 +00003526 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Mike McCormack3f2d5d72005-08-19 10:03:11 +00003527 {
3528 size += 21;
3529 }
Mike McCormack79ca56c2005-09-13 10:37:37 +00003530 if (feature->Feature_Parent)
Mike McCormack1da28582005-08-22 14:09:17 +00003531 size += strlenW( feature->Feature_Parent )+2;
Aric Stewart6269f002005-01-17 13:40:39 +00003532
Mike McCormackee034ba2005-09-20 11:59:14 +00003533 data = msi_alloc(size * sizeof(WCHAR));
Aric Stewart6269f002005-01-17 13:40:39 +00003534
3535 data[0] = 0;
Mike McCormack1da28582005-08-22 14:09:17 +00003536 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
Aric Stewart6269f002005-01-17 13:40:39 +00003537 {
Mike McCormack38d67a42005-08-22 09:15:23 +00003538 MSICOMPONENT* component = cl->component;
Aric Stewart6269f002005-01-17 13:40:39 +00003539 WCHAR buf[21];
Mike McCormack3f2d5d72005-08-19 10:03:11 +00003540
Mike McCormack3a940112006-04-19 02:29:03 +09003541 buf[0] = 0;
Mike McCormackefcc1ec2005-09-12 12:07:15 +00003542 if (component->ComponentId)
Aric Stewartc5a14432005-05-18 17:46:12 +00003543 {
Mike McCormack3f2d5d72005-08-19 10:03:11 +00003544 TRACE("From %s\n",debugstr_w(component->ComponentId));
3545 CLSIDFromString(component->ComponentId, &clsid);
Aric Stewartc5a14432005-05-18 17:46:12 +00003546 encode_base85_guid(&clsid,buf);
3547 TRACE("to %s\n",debugstr_w(buf));
3548 strcatW(data,buf);
3549 }
Aric Stewart6269f002005-01-17 13:40:39 +00003550 }
Mike McCormack79ca56c2005-09-13 10:37:37 +00003551 if (feature->Feature_Parent)
Aric Stewart6269f002005-01-17 13:40:39 +00003552 {
3553 static const WCHAR sep[] = {'\2',0};
3554 strcatW(data,sep);
Mike McCormack1da28582005-08-22 14:09:17 +00003555 strcatW(data,feature->Feature_Parent);
Aric Stewart6269f002005-01-17 13:40:39 +00003556 }
3557
Mike McCormack4db02cd2005-09-15 14:58:38 +00003558 msi_reg_set_val_str( hkey, feature->Feature, data );
Mike McCormackee034ba2005-09-20 11:59:14 +00003559 msi_free(data);
Aric Stewart6269f002005-01-17 13:40:39 +00003560
Mike McCormack79ca56c2005-09-13 10:37:37 +00003561 size = 0;
3562 if (feature->Feature_Parent)
3563 size = strlenW(feature->Feature_Parent)*sizeof(WCHAR);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003564 if (!absent)
3565 {
Mike McCormack1da28582005-08-22 14:09:17 +00003566 RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
3567 (LPBYTE)feature->Feature_Parent,size);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003568 }
3569 else
3570 {
Mike McCormack79ca56c2005-09-13 10:37:37 +00003571 size += 2*sizeof(WCHAR);
Mike McCormackee034ba2005-09-20 11:59:14 +00003572 data = msi_alloc(size);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003573 data[0] = 0x6;
Mike McCormack79ca56c2005-09-13 10:37:37 +00003574 data[1] = 0;
3575 if (feature->Feature_Parent)
3576 strcpyW( &data[1], feature->Feature_Parent );
Mike McCormack1da28582005-08-22 14:09:17 +00003577 RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
Mike McCormack16466af2005-07-06 10:33:30 +00003578 (LPBYTE)data,size);
Mike McCormackee034ba2005-09-20 11:59:14 +00003579 msi_free(data);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003580 }
Robert Shearmand2e48e02006-01-23 17:29:50 +01003581
3582 /* the UI chunk */
3583 uirow = MSI_CreateRecord( 1 );
3584 MSI_RecordSetStringW( uirow, 1, feature->Feature );
3585 ui_actiondata( package, szPublishFeatures, uirow);
3586 msiobj_release( &uirow->hdr );
3587 /* FIXME: call ui_progress? */
Aric Stewart6269f002005-01-17 13:40:39 +00003588 }
3589
Aric Stewart6269f002005-01-17 13:40:39 +00003590end:
Aric Stewart6269f002005-01-17 13:40:39 +00003591 RegCloseKey(hkey);
3592 RegCloseKey(hukey);
3593 return rc;
3594}
3595
Mike McCormack5f830692006-09-08 16:20:46 +09003596static UINT msi_get_local_package_name( LPWSTR path )
Mike McCormack61f24a42005-09-30 10:32:41 +00003597{
Mike McCormack5f830692006-09-08 16:20:46 +09003598 static const WCHAR szInstaller[] = {
3599 '\\','I','n','s','t','a','l','l','e','r','\\',0};
3600 static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
3601 DWORD time, len, i;
3602 HANDLE handle;
Mike McCormack61f24a42005-09-30 10:32:41 +00003603
Mike McCormack5f830692006-09-08 16:20:46 +09003604 time = GetTickCount();
3605 GetWindowsDirectoryW( path, MAX_PATH );
3606 lstrcatW( path, szInstaller );
3607 CreateDirectoryW( path, NULL );
3608
3609 len = lstrlenW(path);
3610 for (i=0; i<0x10000; i++)
Mike McCormack61f24a42005-09-30 10:32:41 +00003611 {
Mike McCormack5f830692006-09-08 16:20:46 +09003612 snprintfW( &path[len], MAX_PATH - len, fmt, (time+i)&0xffff );
3613 handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
3614 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
Mike McCormack61f24a42005-09-30 10:32:41 +00003615 if (handle != INVALID_HANDLE_VALUE)
3616 {
3617 CloseHandle(handle);
3618 break;
3619 }
3620 if (GetLastError() != ERROR_FILE_EXISTS &&
3621 GetLastError() != ERROR_SHARING_VIOLATION)
Mike McCormack5f830692006-09-08 16:20:46 +09003622 return ERROR_FUNCTION_FAILED;
3623 }
Mike McCormack61f24a42005-09-30 10:32:41 +00003624
Mike McCormack5f830692006-09-08 16:20:46 +09003625 return ERROR_SUCCESS;
3626}
3627
3628static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey )
3629{
3630 static const WCHAR szOriginalDatabase[] =
3631 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
3632 WCHAR packagefile[MAX_PATH];
3633 LPWSTR msiFilePath;
3634 UINT r;
3635
3636 r = msi_get_local_package_name( packagefile );
3637 if (r != ERROR_SUCCESS)
3638 return r;
Mike McCormack61f24a42005-09-30 10:32:41 +00003639
3640 TRACE("Copying to local package %s\n",debugstr_w(packagefile));
3641
3642 msiFilePath = msi_dup_property( package, szOriginalDatabase );
3643 r = CopyFileW( msiFilePath, packagefile, FALSE);
3644 msi_free( msiFilePath );
3645
3646 if (!r)
3647 {
Mike McCormackf1d46462006-10-05 13:41:22 +09003648 ERR("Unable to copy package (%s -> %s) (error %d)\n",
Mike McCormack61f24a42005-09-30 10:32:41 +00003649 debugstr_w(msiFilePath), debugstr_w(packagefile), GetLastError());
3650 return ERROR_FUNCTION_FAILED;
3651 }
3652
3653 /* FIXME: maybe set this key in ACTION_RegisterProduct instead */
3654 msi_reg_set_val_str( hkey, INSTALLPROPERTY_LOCALPACKAGEW, packagefile );
3655 return ERROR_SUCCESS;
3656}
3657
Mike McCormackba293ee2005-10-27 12:08:16 +00003658static UINT msi_write_uninstall_property_vals( MSIPACKAGE *package, HKEY hkey )
3659{
3660 LPWSTR prop, val, key;
3661 static const LPCSTR propval[] = {
3662 "ARPAUTHORIZEDCDFPREFIX", "AuthorizedCDFPrefix",
3663 "ARPCONTACT", "Contact",
3664 "ARPCOMMENTS", "Comments",
3665 "ProductName", "DisplayName",
3666 "ProductVersion", "DisplayVersion",
3667 "ARPHELPLINK", "HelpLink",
3668 "ARPHELPTELEPHONE", "HelpTelephone",
3669 "ARPINSTALLLOCATION", "InstallLocation",
3670 "SourceDir", "InstallSource",
3671 "Manufacturer", "Publisher",
3672 "ARPREADME", "Readme",
3673 "ARPSIZE", "Size",
3674 "ARPURLINFOABOUT", "URLInfoAbout",
3675 "ARPURLUPDATEINFO", "URLUpdateInfo",
3676 NULL,
3677 };
3678 const LPCSTR *p = propval;
3679
3680 while( *p )
3681 {
3682 prop = strdupAtoW( *p++ );
3683 key = strdupAtoW( *p++ );
3684 val = msi_dup_property( package, prop );
3685 msi_reg_set_val_str( hkey, key, val );
3686 msi_free(val);
3687 msi_free(key);
3688 msi_free(prop);
3689 }
3690 return ERROR_SUCCESS;
3691}
3692
Aric Stewart2cae30b2005-01-19 19:07:40 +00003693static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
3694{
Aric Stewart68b07492005-01-25 11:05:37 +00003695 HKEY hkey=0;
Aric Stewarte9db87b2005-06-17 21:25:41 +00003696 LPWSTR buffer = NULL;
Mike McCormackba293ee2005-10-27 12:08:16 +00003697 UINT rc;
Mike McCormack74f0de92005-09-29 10:32:39 +00003698 DWORD size, langid;
Mike McCormack4db02cd2005-09-15 14:58:38 +00003699 static const WCHAR szWindowsInstaller[] =
Mike McCormackba293ee2005-10-27 12:08:16 +00003700 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
Aric Stewart36a01502005-06-08 19:07:52 +00003701 static const WCHAR szUpgradeCode[] =
3702 {'U','p','g','r','a','d','e','C','o','d','e',0};
Aric Stewarte9db87b2005-06-17 21:25:41 +00003703 static const WCHAR modpath_fmt[] =
Mike McCormackba293ee2005-10-27 12:08:16 +00003704 {'M','s','i','E','x','e','c','.','e','x','e',' ',
3705 '/','I','[','P','r','o','d','u','c','t','C','o','d','e',']',0};
Aric Stewarte9db87b2005-06-17 21:25:41 +00003706 static const WCHAR szModifyPath[] =
3707 {'M','o','d','i','f','y','P','a','t','h',0};
3708 static const WCHAR szUninstallString[] =
3709 {'U','n','i','n','s','t','a','l','l','S','t','r','i','n','g',0};
3710 static const WCHAR szEstimatedSize[] =
3711 {'E','s','t','i','m','a','t','e','d','S','i','z','e',0};
Aric Stewarte9db87b2005-06-17 21:25:41 +00003712 static const WCHAR szProductLanguage[] =
3713 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
3714 static const WCHAR szProductVersion[] =
3715 {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0};
Aric Stewarte9db87b2005-06-17 21:25:41 +00003716
3717 SYSTEMTIME systime;
3718 static const WCHAR date_fmt[] = {'%','i','%','i','%','i',0};
Aric Stewart36a01502005-06-08 19:07:52 +00003719 LPWSTR upgrade_code;
Mike McCormackba293ee2005-10-27 12:08:16 +00003720 WCHAR szDate[9];
Aric Stewart2cae30b2005-01-19 19:07:40 +00003721
Aric Stewartadaef112005-07-07 20:27:06 +00003722 rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003723 if (rc != ERROR_SUCCESS)
Mike McCormackba293ee2005-10-27 12:08:16 +00003724 return rc;
Aric Stewart2cae30b2005-01-19 19:07:40 +00003725
3726 /* dump all the info i can grab */
Mike McCormackb7270b82005-12-31 13:18:11 +01003727 /* FIXME: Flesh out more information */
Aric Stewart2cae30b2005-01-19 19:07:40 +00003728
Mike McCormackba293ee2005-10-27 12:08:16 +00003729 msi_write_uninstall_property_vals( package, hkey );
Aric Stewart2cae30b2005-01-19 19:07:40 +00003730
Mike McCormack4db02cd2005-09-15 14:58:38 +00003731 msi_reg_set_val_dword( hkey, szWindowsInstaller, 1 );
Aric Stewart2cae30b2005-01-19 19:07:40 +00003732
Mike McCormack61f24a42005-09-30 10:32:41 +00003733 msi_make_package_local( package, hkey );
Aric Stewart36a01502005-06-08 19:07:52 +00003734
Aric Stewarte9db87b2005-06-17 21:25:41 +00003735 /* do ModifyPath and UninstallString */
3736 size = deformat_string(package,modpath_fmt,&buffer);
Mike McCormack16466af2005-07-06 10:33:30 +00003737 RegSetValueExW(hkey,szModifyPath,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
3738 RegSetValueExW(hkey,szUninstallString,0,REG_EXPAND_SZ,(LPBYTE)buffer,size);
Mike McCormackee034ba2005-09-20 11:59:14 +00003739 msi_free(buffer);
Aric Stewarte9db87b2005-06-17 21:25:41 +00003740
Mike McCormackb7270b82005-12-31 13:18:11 +01003741 /* FIXME: Write real Estimated Size when we have it */
Mike McCormack4db02cd2005-09-15 14:58:38 +00003742 msi_reg_set_val_dword( hkey, szEstimatedSize, 0 );
Aric Stewarte9db87b2005-06-17 21:25:41 +00003743
3744 GetLocalTime(&systime);
Mike McCormackba293ee2005-10-27 12:08:16 +00003745 sprintfW(szDate,date_fmt,systime.wYear,systime.wMonth,systime.wDay);
3746 msi_reg_set_val_str( hkey, INSTALLPROPERTY_INSTALLDATEW, szDate );
Aric Stewarte9db87b2005-06-17 21:25:41 +00003747
Mike McCormack74f0de92005-09-29 10:32:39 +00003748 langid = msi_get_property_int( package, szProductLanguage, 0 );
3749 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_LANGUAGEW, langid );
Aric Stewarte9db87b2005-06-17 21:25:41 +00003750
Mike McCormack062ad502005-09-15 15:04:08 +00003751 buffer = msi_dup_property( package, szProductVersion );
Aric Stewarte9db87b2005-06-17 21:25:41 +00003752 if (buffer)
3753 {
Mike McCormack230af9d2006-07-14 15:19:08 +09003754 DWORD verdword = msi_version_str_to_dword(buffer);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003755
3756 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONW, verdword );
3757 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMAJORW, verdword>>24 );
3758 msi_reg_set_val_dword( hkey, INSTALLPROPERTY_VERSIONMINORW, (verdword>>16)&0x00FF );
Aric Stewarte9db87b2005-06-17 21:25:41 +00003759 }
Mike McCormackee034ba2005-09-20 11:59:14 +00003760 msi_free(buffer);
Aric Stewarte9db87b2005-06-17 21:25:41 +00003761
Aric Stewart36a01502005-06-08 19:07:52 +00003762 /* Handle Upgrade Codes */
Mike McCormack062ad502005-09-15 15:04:08 +00003763 upgrade_code = msi_dup_property( package, szUpgradeCode );
Aric Stewart36a01502005-06-08 19:07:52 +00003764 if (upgrade_code)
3765 {
3766 HKEY hkey2;
3767 WCHAR squashed[33];
3768 MSIREG_OpenUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
Aric Stewartadaef112005-07-07 20:27:06 +00003769 squash_guid(package->ProductCode,squashed);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003770 msi_reg_set_val_str( hkey2, squashed, NULL );
Aric Stewart36a01502005-06-08 19:07:52 +00003771 RegCloseKey(hkey2);
3772 MSIREG_OpenUserUpgradeCodesKey(upgrade_code, &hkey2, TRUE);
Aric Stewartadaef112005-07-07 20:27:06 +00003773 squash_guid(package->ProductCode,squashed);
Mike McCormack4db02cd2005-09-15 14:58:38 +00003774 msi_reg_set_val_str( hkey2, squashed, NULL );
Aric Stewart36a01502005-06-08 19:07:52 +00003775 RegCloseKey(hkey2);
3776
Mike McCormackee034ba2005-09-20 11:59:14 +00003777 msi_free(upgrade_code);
Aric Stewart36a01502005-06-08 19:07:52 +00003778 }
Aric Stewart2cae30b2005-01-19 19:07:40 +00003779
Aric Stewart2cae30b2005-01-19 19:07:40 +00003780 RegCloseKey(hkey);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003781
Robert Shearmand2e48e02006-01-23 17:29:50 +01003782 /* FIXME: call ui_actiondata */
3783
Aric Stewart2cae30b2005-01-19 19:07:40 +00003784 return ERROR_SUCCESS;
3785}
3786
3787static UINT ACTION_InstallExecute(MSIPACKAGE *package)
3788{
Mike McCormacka977b2c2005-11-03 09:56:29 +00003789 return execute_script(package,INSTALL_SCRIPT);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003790}
3791
3792static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
3793{
Aric Stewart9cd707d2005-05-27 19:24:22 +00003794 UINT rc;
3795
Aric Stewart9cd707d2005-05-27 19:24:22 +00003796 /* turn off scheduleing */
3797 package->script->CurrentlyScripting= FALSE;
3798
Aric Stewart54c67dd2005-01-25 20:17:09 +00003799 /* first do the same as an InstallExecute */
Aric Stewart9cd707d2005-05-27 19:24:22 +00003800 rc = ACTION_InstallExecute(package);
3801 if (rc != ERROR_SUCCESS)
3802 return rc;
Aric Stewart54c67dd2005-01-25 20:17:09 +00003803
3804 /* then handle Commit Actions */
Aric Stewart9cd707d2005-05-27 19:24:22 +00003805 rc = execute_script(package,COMMIT_SCRIPT);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003806
Aric Stewart9cd707d2005-05-27 19:24:22 +00003807 return rc;
Aric Stewart2cae30b2005-01-19 19:07:40 +00003808}
3809
3810static UINT ACTION_ForceReboot(MSIPACKAGE *package)
3811{
3812 static const WCHAR RunOnce[] = {
3813 'S','o','f','t','w','a','r','e','\\',
3814 'M','i','c','r','o','s','o','f','t','\\',
3815 'W','i','n','d','o','w','s','\\',
3816 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
Mike McCormack09b82642005-02-22 19:31:45 +00003817 'R','u','n','O','n','c','e',0};
Aric Stewart2cae30b2005-01-19 19:07:40 +00003818 static const WCHAR InstallRunOnce[] = {
3819 'S','o','f','t','w','a','r','e','\\',
3820 'M','i','c','r','o','s','o','f','t','\\',
3821 'W','i','n','d','o','w','s','\\',
3822 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3823 'I','n','s','t','a','l','l','e','r','\\',
Mike McCormack09b82642005-02-22 19:31:45 +00003824 'R','u','n','O','n','c','e','E','n','t','r','i','e','s',0};
Aric Stewart2cae30b2005-01-19 19:07:40 +00003825
3826 static const WCHAR msiexec_fmt[] = {
Juan Lang014ad3b2005-03-01 10:41:52 +00003827 '%','s',
Aric Stewart2cae30b2005-01-19 19:07:40 +00003828 '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ',
3829 '\"','%','s','\"',0};
3830 static const WCHAR install_fmt[] = {
3831 '/','I',' ','\"','%','s','\"',' ',
3832 'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
3833 'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
Juan Lang014ad3b2005-03-01 10:41:52 +00003834 WCHAR buffer[256], sysdir[MAX_PATH];
Aric Stewartadaef112005-07-07 20:27:06 +00003835 HKEY hkey;
Mike McCormack4db02cd2005-09-15 14:58:38 +00003836 WCHAR squished_pc[100];
Aric Stewart2cae30b2005-01-19 19:07:40 +00003837
Aric Stewartadaef112005-07-07 20:27:06 +00003838 squash_guid(package->ProductCode,squished_pc);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003839
Juan Lang014ad3b2005-03-01 10:41:52 +00003840 GetSystemDirectoryW(sysdir, sizeof(sysdir)/sizeof(sysdir[0]));
Aric Stewart2cae30b2005-01-19 19:07:40 +00003841 RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
Juan Lang014ad3b2005-03-01 10:41:52 +00003842 snprintfW(buffer,sizeof(buffer)/sizeof(buffer[0]),msiexec_fmt,sysdir,
3843 squished_pc);
Aric Stewart2cae30b2005-01-19 19:07:40 +00003844
Mike McCormack4db02cd2005-09-15 14:58:38 +00003845 msi_reg_set_val_str( hkey, squished_pc, buffer );
Aric Stewart2cae30b2005-01-19 19:07:40 +00003846 RegCloseKey(hkey);
3847
3848 TRACE("Reboot command %s\n",debugstr_w(buffer));
3849
3850 RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
Aric Stewartadaef112005-07-07 20:27:06 +00003851 sprintfW(buffer,install_fmt,package->ProductCode,squished_pc);
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00003852
Mike McCormack4db02cd2005-09-15 14:58:38 +00003853 msi_reg_set_val_str( hkey, squished_pc, buffer );
Aric Stewart2cae30b2005-01-19 19:07:40 +00003854 RegCloseKey(hkey);
3855
Aric Stewart68b07492005-01-25 11:05:37 +00003856 return ERROR_INSTALL_SUSPEND;
Aric Stewart2cae30b2005-01-19 19:07:40 +00003857}
3858
James Hawkins563a50a2006-10-09 00:05:04 -07003859static UINT ACTION_ResolveSource(MSIPACKAGE* package)
Aric Stewart90c57392005-01-31 16:23:12 +00003860{
James Hawkinsc5075432006-10-10 13:39:50 -07003861 DWORD attrib, len;
3862 LPWSTR ptr, source;
Aric Stewart94d68182005-08-15 20:50:06 +00003863 UINT rc;
James Hawkinsc5075432006-10-10 13:39:50 -07003864
Aric Stewart90c57392005-01-31 16:23:12 +00003865 /*
3866 * we are currently doing what should be done here in the top level Install
3867 * however for Adminastrative and uninstalls this step will be needed
3868 */
Aric Stewart94d68182005-08-15 20:50:06 +00003869 if (!package->PackagePath)
3870 return ERROR_SUCCESS;
3871
James Hawkinsc5075432006-10-10 13:39:50 -07003872 ptr = strrchrW(package->PackagePath, '\\');
3873 if (!ptr)
3874 return ERROR_SUCCESS;
3875
3876 len = ptr - package->PackagePath + 2;
3877 source = msi_alloc(len * sizeof(WCHAR));
3878 lstrcpynW(source, package->PackagePath, len);
3879
3880 MSI_SetPropertyW(package, cszSourceDir, source);
3881 MSI_SetPropertyW(package, cszSOURCEDIR, source);
3882
3883 msi_free(source);
3884
Aric Stewart94d68182005-08-15 20:50:06 +00003885 attrib = GetFileAttributesW(package->PackagePath);
3886 if (attrib == INVALID_FILE_ATTRIBUTES)
3887 {
3888 LPWSTR prompt;
3889 LPWSTR msg;
3890 DWORD size = 0;
3891
3892 rc = MsiSourceListGetInfoW(package->ProductCode, NULL,
3893 MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
3894 INSTALLPROPERTY_DISKPROMPTW,NULL,&size);
3895 if (rc == ERROR_MORE_DATA)
3896 {
Mike McCormackee034ba2005-09-20 11:59:14 +00003897 prompt = msi_alloc(size * sizeof(WCHAR));
Aric Stewart94d68182005-08-15 20:50:06 +00003898 MsiSourceListGetInfoW(package->ProductCode, NULL,
3899 MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT,
3900 INSTALLPROPERTY_DISKPROMPTW,prompt,&size);
3901 }
3902 else
3903 prompt = strdupW(package->PackagePath);
3904
3905 msg = generate_error_string(package,1302,1,prompt);
3906 while(attrib == INVALID_FILE_ATTRIBUTES)
3907 {
3908 rc = MessageBoxW(NULL,msg,NULL,MB_OKCANCEL);
3909 if (rc == IDCANCEL)
3910 {
3911 rc = ERROR_INSTALL_USEREXIT;
3912 break;
3913 }
3914 attrib = GetFileAttributesW(package->PackagePath);
3915 }
Mike McCormackee034ba2005-09-20 11:59:14 +00003916 msi_free(prompt);
Aric Stewart94d68182005-08-15 20:50:06 +00003917 rc = ERROR_SUCCESS;
3918 }
3919 else
3920 return ERROR_SUCCESS;
3921
3922 return rc;
Aric Stewart90c57392005-01-31 16:23:12 +00003923}
3924
Aric Stewartc7e88e02005-02-10 17:09:44 +00003925static UINT ACTION_RegisterUser(MSIPACKAGE *package)
3926{
Aric Stewartc7e88e02005-02-10 17:09:44 +00003927 HKEY hkey=0;
3928 LPWSTR buffer;
Aric Stewartc7e88e02005-02-10 17:09:44 +00003929 LPWSTR productid;
3930 UINT rc,i;
Aric Stewartc7e88e02005-02-10 17:09:44 +00003931
3932 static const WCHAR szPropKeys[][80] =
3933 {
Aric Stewart8e233e92005-03-01 11:45:19 +00003934 {'P','r','o','d','u','c','t','I','D',0},
3935 {'U','S','E','R','N','A','M','E',0},
3936 {'C','O','M','P','A','N','Y','N','A','M','E',0},
3937 {0},
Aric Stewartc7e88e02005-02-10 17:09:44 +00003938 };
3939
3940 static const WCHAR szRegKeys[][80] =
3941 {
Aric Stewart8e233e92005-03-01 11:45:19 +00003942 {'P','r','o','d','u','c','t','I','D',0},
3943 {'R','e','g','O','w','n','e','r',0},
3944 {'R','e','g','C','o','m','p','a','n','y',0},
3945 {0},
Aric Stewartc7e88e02005-02-10 17:09:44 +00003946 };
3947
Mike McCormack062ad502005-09-15 15:04:08 +00003948 productid = msi_dup_property( package, INSTALLPROPERTY_PRODUCTIDW );
Aric Stewartc7e88e02005-02-10 17:09:44 +00003949 if (!productid)
3950 return ERROR_SUCCESS;
3951
Aric Stewartadaef112005-07-07 20:27:06 +00003952 rc = MSIREG_OpenUninstallKey(package->ProductCode,&hkey,TRUE);
Aric Stewartc7e88e02005-02-10 17:09:44 +00003953 if (rc != ERROR_SUCCESS)
3954 goto end;
3955
Mike McCormack67189f92005-09-16 18:45:19 +00003956 for( i = 0; szPropKeys[i][0]; i++ )
Aric Stewartc7e88e02005-02-10 17:09:44 +00003957 {
Mike McCormack062ad502005-09-15 15:04:08 +00003958 buffer = msi_dup_property( package, szPropKeys[i] );
Mike McCormack4db02cd2005-09-15 14:58:38 +00003959 msi_reg_set_val_str( hkey, szRegKeys[i], buffer );
Mike McCormackee034ba2005-09-20 11:59:14 +00003960 msi_free( buffer );
Aric Stewartc7e88e02005-02-10 17:09:44 +00003961 }
3962
3963end:
Mike McCormackee034ba2005-09-20 11:59:14 +00003964 msi_free(productid);
Aric Stewartc7e88e02005-02-10 17:09:44 +00003965 RegCloseKey(hkey);
3966
Robert Shearmand2e48e02006-01-23 17:29:50 +01003967 /* FIXME: call ui_actiondata */
3968
Aric Stewartc7e88e02005-02-10 17:09:44 +00003969 return ERROR_SUCCESS;
3970}
3971
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00003972
3973static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
3974{
3975 UINT rc;
Aric Stewart25f1e752005-06-24 12:14:52 +00003976
Aric Stewartc9802932005-06-30 20:45:43 +00003977 package->script->InWhatSequence |= SEQUENCE_EXEC;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003978 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewartb6bc6aa2005-02-24 12:47:43 +00003979 return rc;
3980}
3981
Aric Stewart0af24872005-02-25 14:00:09 +00003982
Aric Stewart072c5e52005-04-20 12:50:05 +00003983static UINT ITERATE_PublishComponent(MSIRECORD *rec, LPVOID param)
3984{
3985 MSIPACKAGE *package = (MSIPACKAGE*)param;
Aric Stewart09b0aba2005-06-09 20:30:59 +00003986 LPCWSTR compgroupid=NULL;
3987 LPCWSTR feature=NULL;
3988 LPCWSTR text = NULL;
3989 LPCWSTR qualifier = NULL;
3990 LPCWSTR component = NULL;
Aric Stewart6f43c182005-05-26 12:24:28 +00003991 LPWSTR advertise = NULL;
3992 LPWSTR output = NULL;
Aric Stewart072c5e52005-04-20 12:50:05 +00003993 HKEY hkey;
3994 UINT rc = ERROR_SUCCESS;
Mike McCormack38d67a42005-08-22 09:15:23 +00003995 MSICOMPONENT *comp;
Aric Stewart072c5e52005-04-20 12:50:05 +00003996 DWORD sz = 0;
Robert Shearmand2e48e02006-01-23 17:29:50 +01003997 MSIRECORD *uirow;
Aric Stewartb39d8fc2005-05-13 13:56:39 +00003998
Aric Stewart09b0aba2005-06-09 20:30:59 +00003999 component = MSI_RecordGetString(rec,3);
Mike McCormack38d67a42005-08-22 09:15:23 +00004000 comp = get_loaded_component(package,component);
Aric Stewartb39d8fc2005-05-13 13:56:39 +00004001
Mike McCormackd693f462005-10-29 11:36:48 +00004002 if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ) &&
4003 !ACTION_VerifyComponentForAction( comp, INSTALLSTATE_SOURCE ) &&
4004 !ACTION_VerifyComponentForAction( comp, INSTALLSTATE_ADVERTISED ))
Aric Stewartb39d8fc2005-05-13 13:56:39 +00004005 {
4006 TRACE("Skipping: Component %s not scheduled for install\n",
4007 debugstr_w(component));
Aric Stewart6f43c182005-05-26 12:24:28 +00004008
Aric Stewartb39d8fc2005-05-13 13:56:39 +00004009 return ERROR_SUCCESS;
4010 }
Aric Stewart072c5e52005-04-20 12:50:05 +00004011
Aric Stewart09b0aba2005-06-09 20:30:59 +00004012 compgroupid = MSI_RecordGetString(rec,1);
Robert Shearmand2e48e02006-01-23 17:29:50 +01004013 qualifier = MSI_RecordGetString(rec,2);
Aric Stewart072c5e52005-04-20 12:50:05 +00004014
4015 rc = MSIREG_OpenUserComponentsKey(compgroupid, &hkey, TRUE);
4016 if (rc != ERROR_SUCCESS)
4017 goto end;
4018
Aric Stewart09b0aba2005-06-09 20:30:59 +00004019 text = MSI_RecordGetString(rec,4);
Aric Stewart09b0aba2005-06-09 20:30:59 +00004020 feature = MSI_RecordGetString(rec,5);
Aric Stewart072c5e52005-04-20 12:50:05 +00004021
Mike McCormack38d67a42005-08-22 09:15:23 +00004022 advertise = create_component_advertise_string(package, comp, feature);
Aric Stewart072c5e52005-04-20 12:50:05 +00004023
Aric Stewart6f43c182005-05-26 12:24:28 +00004024 sz = strlenW(advertise);
4025
Aric Stewart072c5e52005-04-20 12:50:05 +00004026 if (text)
4027 sz += lstrlenW(text);
Aric Stewart072c5e52005-04-20 12:50:05 +00004028
4029 sz+=3;
4030 sz *= sizeof(WCHAR);
4031
Mike McCormack3a940112006-04-19 02:29:03 +09004032 output = msi_alloc_zero(sz);
Aric Stewart6f43c182005-05-26 12:24:28 +00004033 strcpyW(output,advertise);
Mike McCormack470f23d2005-09-22 10:56:26 +00004034 msi_free(advertise);
Aric Stewart072c5e52005-04-20 12:50:05 +00004035
4036 if (text)
4037 strcatW(output,text);
4038
Mike McCormack4db02cd2005-09-15 14:58:38 +00004039 msi_reg_set_val_multi_str( hkey, qualifier, output );
Aric Stewart072c5e52005-04-20 12:50:05 +00004040
4041end:
4042 RegCloseKey(hkey);
Mike McCormackee034ba2005-09-20 11:59:14 +00004043 msi_free(output);
Robert Shearmand2e48e02006-01-23 17:29:50 +01004044
4045 /* the UI chunk */
4046 uirow = MSI_CreateRecord( 2 );
4047 MSI_RecordSetStringW( uirow, 1, compgroupid );
4048 MSI_RecordSetStringW( uirow, 2, qualifier);
4049 ui_actiondata( package, szPublishComponents, uirow);
4050 msiobj_release( &uirow->hdr );
4051 /* FIXME: call ui_progress? */
4052
Aric Stewart072c5e52005-04-20 12:50:05 +00004053 return rc;
4054}
4055
4056/*
4057 * At present I am ignorning the advertised components part of this and only
4058 * focusing on the qualified component sets
4059 */
4060static UINT ACTION_PublishComponents(MSIPACKAGE *package)
4061{
4062 UINT rc;
4063 MSIQUERY * view;
4064 static const WCHAR ExecSeqQuery[] =
4065 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
Aric Stewart98e38082005-05-20 09:40:42 +00004066 '`','P','u','b','l','i','s','h',
4067 'C','o','m','p','o','n','e','n','t','`',0};
Aric Stewart072c5e52005-04-20 12:50:05 +00004068
4069 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
4070 if (rc != ERROR_SUCCESS)
4071 return ERROR_SUCCESS;
4072
4073 rc = MSI_IterateRecords(view, NULL, ITERATE_PublishComponent, package);
4074 msiobj_release(&view->hdr);
4075
4076 return rc;
4077}
Mike McCormack202166c2005-09-23 10:09:18 +00004078
James Hawkins9bc12ad2006-10-19 15:49:54 -07004079static UINT ITERATE_InstallService(MSIRECORD *rec, LPVOID param)
4080{
4081 MSIPACKAGE *package = (MSIPACKAGE*)param;
4082 MSIRECORD *row;
4083 MSIFILE *file;
4084 SC_HANDLE hscm, service = NULL;
4085 LPCWSTR name, disp, comp, depends, pass;
4086 LPCWSTR load_order, serv_name, key;
4087 DWORD serv_type, start_type;
4088 DWORD err_control;
4089
4090 static const WCHAR query[] =
4091 {'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ',
4092 '`','C','o','m','p','o','n','e','n','t','`',' ',
4093 'W','H','E','R','E',' ',
4094 '`','C','o','m','p','o','n','e','n','t','`',' ',
4095 '=','\'','%','s','\'',0};
4096
4097 hscm = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASEW, GENERIC_WRITE);
4098 if (!hscm)
4099 {
4100 ERR("Failed to open the SC Manager!\n");
4101 goto done;
4102 }
4103
4104 start_type = MSI_RecordGetInteger(rec, 5);
4105 if (start_type == SERVICE_BOOT_START || start_type == SERVICE_SYSTEM_START)
4106 goto done;
4107
4108 depends = MSI_RecordGetString(rec, 8);
4109 if (depends && *depends)
4110 FIXME("Dependency list unhandled!\n");
4111
4112 name = MSI_RecordGetString(rec, 2);
4113 disp = MSI_RecordGetString(rec, 3);
4114 serv_type = MSI_RecordGetInteger(rec, 4);
4115 err_control = MSI_RecordGetInteger(rec, 6);
4116 load_order = MSI_RecordGetString(rec, 7);
4117 serv_name = MSI_RecordGetString(rec, 9);
4118 pass = MSI_RecordGetString(rec, 10);
4119 comp = MSI_RecordGetString(rec, 12);
4120
4121 /* fetch the service path */
4122 row = MSI_QueryGetRecord(package->db, query, comp);
4123 if (!row)
4124 {
4125 ERR("Control query failed!\n");
4126 goto done;
4127 }
4128
4129 key = MSI_RecordGetString(row, 6);
4130 msiobj_release(&row->hdr);
4131
4132 file = get_loaded_file(package, key);
4133 if (!file)
4134 {
4135 ERR("Failed to load the service file\n");
4136 goto done;
4137 }
4138
4139 service = CreateServiceW(hscm, name, disp, GENERIC_ALL, serv_type,
4140 start_type, err_control, file->TargetPath,
4141 load_order, NULL, NULL, serv_name, pass);
4142 if (!service)
4143 {
4144 if (GetLastError() != ERROR_SERVICE_EXISTS)
4145 ERR("Failed to create service %s: %d\n", debugstr_w(name), GetLastError());
4146 }
4147
4148done:
4149 CloseServiceHandle(service);
4150 CloseServiceHandle(hscm);
4151
4152 return ERROR_SUCCESS;
4153}
4154
4155static UINT ACTION_InstallServices( MSIPACKAGE *package )
4156{
4157 UINT rc;
4158 MSIQUERY * view;
4159 static const WCHAR ExecSeqQuery[] =
4160 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
4161 'S','e','r','v','i','c','e','I','n','s','t','a','l','l',0};
4162
4163 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
4164 if (rc != ERROR_SUCCESS)
4165 return ERROR_SUCCESS;
4166
4167 rc = MSI_IterateRecords(view, NULL, ITERATE_InstallService, package);
4168 msiobj_release(&view->hdr);
4169
4170 return rc;
4171}
4172
Mike McCormack2586a092005-09-26 09:56:18 +00004173static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
4174 LPCSTR action, LPCWSTR table )
Mike McCormack567f0312005-09-23 11:06:57 +00004175{
4176 static const WCHAR query[] = {
Mike McCormack2586a092005-09-26 09:56:18 +00004177 'S','E','L','E','C','T',' ','*',' ',
4178 'F','R','O','M',' ','`','%','s','`',0 };
Mike McCormack567f0312005-09-23 11:06:57 +00004179 MSIQUERY *view = NULL;
4180 DWORD count = 0;
Mike McCormack2586a092005-09-26 09:56:18 +00004181 UINT r;
Mike McCormack567f0312005-09-23 11:06:57 +00004182
Mike McCormack2586a092005-09-26 09:56:18 +00004183 r = MSI_OpenQuery( package->db, &view, query, table );
4184 if (r == ERROR_SUCCESS)
Mike McCormack567f0312005-09-23 11:06:57 +00004185 {
Mike McCormack2586a092005-09-26 09:56:18 +00004186 r = MSI_IterateRecords(view, &count, NULL, package);
Mike McCormack567f0312005-09-23 11:06:57 +00004187 msiobj_release(&view->hdr);
4188 }
4189
Mike McCormack2586a092005-09-26 09:56:18 +00004190 if (count)
Mike McCormackf1d46462006-10-05 13:41:22 +09004191 FIXME("%s -> %u ignored %s table values\n",
Mike McCormack2586a092005-09-26 09:56:18 +00004192 action, count, debugstr_w(table));
4193
Mike McCormack567f0312005-09-23 11:06:57 +00004194 return ERROR_SUCCESS;
4195}
Mike McCormack94fbe092005-09-23 17:21:10 +00004196
Mike McCormack55942702005-10-30 19:23:28 +00004197static UINT ACTION_AllocateRegistrySpace( MSIPACKAGE *package )
4198{
4199 TRACE("%p\n", package);
4200 return ERROR_SUCCESS;
4201}
4202
Mike McCormack2586a092005-09-26 09:56:18 +00004203static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
Mike McCormack94fbe092005-09-23 17:21:10 +00004204{
Mike McCormack2586a092005-09-26 09:56:18 +00004205 static const WCHAR table[] =
4206 {'R','e','m','o','v','e','I','n','i','F','i','l','e',0 };
4207 return msi_unimplemented_action_stub( package, "RemoveIniValues", table );
Mike McCormack94fbe092005-09-23 17:21:10 +00004208}
Mike McCormackb9a3a7a2005-09-25 15:14:03 +00004209
Mike McCormack2586a092005-09-26 09:56:18 +00004210static UINT ACTION_MoveFiles( MSIPACKAGE *package )
Mike McCormackb9a3a7a2005-09-25 15:14:03 +00004211{
Mike McCormack2586a092005-09-26 09:56:18 +00004212 static const WCHAR table[] = { 'M','o','v','e','F','i','l','e',0 };
4213 return msi_unimplemented_action_stub( package, "MoveFiles", table );
4214}
4215
4216static UINT ACTION_PatchFiles( MSIPACKAGE *package )
4217{
4218 static const WCHAR table[] = { 'P','a','t','c','h',0 };
4219 return msi_unimplemented_action_stub( package, "PatchFiles", table );
4220}
4221
4222static UINT ACTION_BindImage( MSIPACKAGE *package )
4223{
4224 static const WCHAR table[] = { 'B','i','n','d','I','m','a','g','e',0 };
4225 return msi_unimplemented_action_stub( package, "BindImage", table );
4226}
4227
4228static UINT ACTION_IsolateComponents( MSIPACKAGE *package )
4229{
4230 static const WCHAR table[] = {
Mike McCormackb9a3a7a2005-09-25 15:14:03 +00004231 'I','s','o','l','a','t','e','C','o','m','p','o','n','e','n','t',0 };
Mike McCormack2586a092005-09-26 09:56:18 +00004232 return msi_unimplemented_action_stub( package, "IsolateComponents", table );
4233}
Mike McCormackb9a3a7a2005-09-25 15:14:03 +00004234
Mike McCormack2586a092005-09-26 09:56:18 +00004235static UINT ACTION_MigrateFeatureStates( MSIPACKAGE *package )
4236{
4237 static const WCHAR table[] = { 'U','p','g','r','a','d','e',0 };
4238 return msi_unimplemented_action_stub( package, "MigrateFeatureStates", table );
4239}
4240
4241static UINT ACTION_SelfUnregModules( MSIPACKAGE *package )
4242{
4243 static const WCHAR table[] = { 'S','e','l','f','R','e','g',0 };
4244 return msi_unimplemented_action_stub( package, "SelfUnregModules", table );
4245}
4246
Mike McCormack2586a092005-09-26 09:56:18 +00004247static UINT ACTION_StartServices( MSIPACKAGE *package )
4248{
4249 static const WCHAR table[] = {
4250 'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
4251 return msi_unimplemented_action_stub( package, "StartServices", table );
4252}
4253
4254static UINT ACTION_StopServices( MSIPACKAGE *package )
4255{
4256 static const WCHAR table[] = {
4257 'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
4258 return msi_unimplemented_action_stub( package, "StopServices", table );
4259}
4260
4261static UINT ACTION_DeleteServices( MSIPACKAGE *package )
4262{
4263 static const WCHAR table[] = {
4264 'S','e','r','v','i','c','e','C','o','n','t','r','o','l',0 };
4265 return msi_unimplemented_action_stub( package, "DeleteServices", table );
Mike McCormackb9a3a7a2005-09-25 15:14:03 +00004266}
Mike McCormack3b955152005-09-28 18:10:44 +00004267
4268static UINT ACTION_WriteEnvironmentStrings( MSIPACKAGE *package )
4269{
4270 static const WCHAR table[] = {
4271 'E','n','v','i','r','o','n','m','e','n','t',0 };
4272 return msi_unimplemented_action_stub( package, "WriteEnvironmentStrings", table );
4273}
4274
4275static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
4276{
4277 static const WCHAR table[] = {
4278 'E','n','v','i','r','o','n','m','e','n','t',0 };
4279 return msi_unimplemented_action_stub( package, "RemoveEnvironmentStrings", table );
4280}
4281
4282static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
4283{
4284 static const WCHAR table[] = {
4285 'M','s','i','A','s','s','e','m','b','l','y',0 };
4286 return msi_unimplemented_action_stub( package, "MsiPublishAssemblies", table );
4287}
4288
4289static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
4290{
4291 static const WCHAR table[] = {
4292 'M','s','i','A','s','s','e','m','b','l','y',0 };
4293 return msi_unimplemented_action_stub( package, "MsiUnpublishAssemblies", table );
4294}
4295
4296static UINT ACTION_UnregisterFonts( MSIPACKAGE *package )
4297{
4298 static const WCHAR table[] = { 'F','o','n','t',0 };
4299 return msi_unimplemented_action_stub( package, "UnregisterFonts", table );
4300}
4301
Mike McCormackf24a9e22005-12-31 13:14:23 +01004302static UINT ACTION_CCPSearch( MSIPACKAGE *package )
4303{
4304 static const WCHAR table[] = { 'C','C','P','S','e','a','r','c','h',0 };
4305 return msi_unimplemented_action_stub( package, "CCPSearch", table );
4306}
4307
4308static UINT ACTION_RMCCPSearch( MSIPACKAGE *package )
4309{
4310 static const WCHAR table[] = { 'C','C','P','S','e','a','r','c','h',0 };
4311 return msi_unimplemented_action_stub( package, "RMCCPSearch", table );
4312}
4313
Mike McCormack88603662006-03-22 23:01:56 +09004314static UINT ACTION_RegisterComPlus( MSIPACKAGE *package )
4315{
4316 static const WCHAR table[] = { 'C','o','m','p','l','u','s',0 };
4317 return msi_unimplemented_action_stub( package, "RegisterComPlus", table );
4318}
4319
4320static UINT ACTION_UnregisterComPlus( MSIPACKAGE *package )
4321{
4322 static const WCHAR table[] = { 'C','o','m','p','l','u','s',0 };
4323 return msi_unimplemented_action_stub( package, "UnregisterComPlus", table );
4324}
4325
Mike McCormack3b955152005-09-28 18:10:44 +00004326static struct _actions StandardActions[] = {
Mike McCormack55942702005-10-30 19:23:28 +00004327 { szAllocateRegistrySpace, ACTION_AllocateRegistrySpace },
Mike McCormack3b955152005-09-28 18:10:44 +00004328 { szAppSearch, ACTION_AppSearch },
4329 { szBindImage, ACTION_BindImage },
Mike McCormackf24a9e22005-12-31 13:14:23 +01004330 { szCCPSearch, ACTION_CCPSearch},
Mike McCormack3b955152005-09-28 18:10:44 +00004331 { szCostFinalize, ACTION_CostFinalize },
4332 { szCostInitialize, ACTION_CostInitialize },
4333 { szCreateFolders, ACTION_CreateFolders },
4334 { szCreateShortcuts, ACTION_CreateShortcuts },
4335 { szDeleteServices, ACTION_DeleteServices },
4336 { szDisableRollback, NULL},
4337 { szDuplicateFiles, ACTION_DuplicateFiles },
4338 { szExecuteAction, ACTION_ExecuteAction },
4339 { szFileCost, ACTION_FileCost },
4340 { szFindRelatedProducts, ACTION_FindRelatedProducts },
4341 { szForceReboot, ACTION_ForceReboot },
4342 { szInstallAdminPackage, NULL},
4343 { szInstallExecute, ACTION_InstallExecute },
4344 { szInstallExecuteAgain, ACTION_InstallExecute },
4345 { szInstallFiles, ACTION_InstallFiles},
4346 { szInstallFinalize, ACTION_InstallFinalize },
4347 { szInstallInitialize, ACTION_InstallInitialize },
4348 { szInstallSFPCatalogFile, NULL},
4349 { szInstallValidate, ACTION_InstallValidate },
4350 { szIsolateComponents, ACTION_IsolateComponents },
4351 { szLaunchConditions, ACTION_LaunchConditions },
4352 { szMigrateFeatureStates, ACTION_MigrateFeatureStates },
4353 { szMoveFiles, ACTION_MoveFiles },
4354 { szMsiPublishAssemblies, ACTION_MsiPublishAssemblies },
4355 { szMsiUnpublishAssemblies, ACTION_MsiUnpublishAssemblies },
4356 { szInstallODBC, NULL},
4357 { szInstallServices, ACTION_InstallServices },
4358 { szPatchFiles, ACTION_PatchFiles },
4359 { szProcessComponents, ACTION_ProcessComponents },
4360 { szPublishComponents, ACTION_PublishComponents },
4361 { szPublishFeatures, ACTION_PublishFeatures },
4362 { szPublishProduct, ACTION_PublishProduct },
4363 { szRegisterClassInfo, ACTION_RegisterClassInfo },
Mike McCormack88603662006-03-22 23:01:56 +09004364 { szRegisterComPlus, ACTION_RegisterComPlus},
Mike McCormack3b955152005-09-28 18:10:44 +00004365 { szRegisterExtensionInfo, ACTION_RegisterExtensionInfo },
4366 { szRegisterFonts, ACTION_RegisterFonts },
4367 { szRegisterMIMEInfo, ACTION_RegisterMIMEInfo },
4368 { szRegisterProduct, ACTION_RegisterProduct },
4369 { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo },
4370 { szRegisterTypeLibraries, ACTION_RegisterTypeLibraries },
4371 { szRegisterUser, ACTION_RegisterUser},
4372 { szRemoveDuplicateFiles, NULL},
4373 { szRemoveEnvironmentStrings, ACTION_RemoveEnvironmentStrings },
4374 { szRemoveExistingProducts, NULL},
Mike McCormackfd4a2002005-11-02 11:42:56 +00004375 { szRemoveFiles, ACTION_RemoveFiles},
Mike McCormack3b955152005-09-28 18:10:44 +00004376 { szRemoveFolders, NULL},
4377 { szRemoveIniValues, ACTION_RemoveIniValues },
4378 { szRemoveODBC, NULL},
4379 { szRemoveRegistryValues, NULL},
4380 { szRemoveShortcuts, NULL},
4381 { szResolveSource, ACTION_ResolveSource},
Mike McCormackf24a9e22005-12-31 13:14:23 +01004382 { szRMCCPSearch, ACTION_RMCCPSearch},
Mike McCormack3b955152005-09-28 18:10:44 +00004383 { szScheduleReboot, NULL},
4384 { szSelfRegModules, ACTION_SelfRegModules },
4385 { szSelfUnregModules, ACTION_SelfUnregModules },
4386 { szSetODBCFolders, NULL},
4387 { szStartServices, ACTION_StartServices },
4388 { szStopServices, ACTION_StopServices },
4389 { szUnpublishComponents, NULL},
4390 { szUnpublishFeatures, NULL},
4391 { szUnregisterClassInfo, NULL},
Mike McCormack88603662006-03-22 23:01:56 +09004392 { szUnregisterComPlus, ACTION_UnregisterComPlus},
Mike McCormack3b955152005-09-28 18:10:44 +00004393 { szUnregisterExtensionInfo, NULL},
4394 { szUnregisterFonts, ACTION_UnregisterFonts },
4395 { szUnregisterMIMEInfo, NULL},
4396 { szUnregisterProgIdInfo, NULL},
4397 { szUnregisterTypeLibraries, NULL},
4398 { szValidateProductID, NULL},
4399 { szWriteEnvironmentStrings, ACTION_WriteEnvironmentStrings },
4400 { szWriteIniValues, ACTION_WriteIniValues },
4401 { szWriteRegistryValues, ACTION_WriteRegistryValues},
4402 { NULL, NULL},
4403};