blob: d0953c34f297ea3ea3c07e9038abd89b35c8cd9d [file] [log] [blame]
Aric Stewart401bd3f2004-06-28 20:34:35 +00001/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2004 Aric Stewart for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
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>
30#include <stdio.h>
31
Francois Gouget486d0202004-10-07 03:06:48 +000032#define COBJMACROS
33
Aric Stewart401bd3f2004-06-28 20:34:35 +000034#include "windef.h"
35#include "winbase.h"
36#include "winerror.h"
37#include "winreg.h"
38#include "wine/debug.h"
Robert Shearman3d7299b2004-09-10 22:29:49 +000039#include "fdi.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000040#include "msi.h"
41#include "msiquery.h"
Robert Shearman3d7299b2004-09-10 22:29:49 +000042#include "msvcrt/fcntl.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000043#include "objbase.h"
44#include "objidl.h"
45#include "msipriv.h"
46#include "winnls.h"
47#include "winuser.h"
48#include "shlobj.h"
49#include "wine/unicode.h"
Aric Stewartec688fb2004-07-04 00:35:52 +000050#include "ver.h"
Aric Stewart54c67dd2005-01-25 20:17:09 +000051#include "action.h"
Aric Stewart401bd3f2004-06-28 20:34:35 +000052
Aric Stewartbd1bbc12005-01-03 20:00:13 +000053#define REG_PROGRESS_VALUE 13200
54#define COMPONENT_PROGRESS_VALUE 24000
Aric Stewart401bd3f2004-06-28 20:34:35 +000055
Aric Stewart401bd3f2004-06-28 20:34:35 +000056WINE_DEFAULT_DEBUG_CHANNEL(msi);
57
58/*
59 * Prototypes
60 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +000061static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
62static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
Aric Stewarted7c4bc2004-07-04 00:26:54 +000063
Aric Stewart09d35c32004-12-27 19:00:26 +000064static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +000065UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
Aric Stewart5b936ca2004-07-06 18:47:09 +000066
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +000067static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
68static UINT ACTION_CostInitialize(MSIPACKAGE *package);
69static UINT ACTION_CreateFolders(MSIPACKAGE *package);
70static UINT ACTION_CostFinalize(MSIPACKAGE *package);
71static UINT ACTION_FileCost(MSIPACKAGE *package);
72static UINT ACTION_InstallFiles(MSIPACKAGE *package);
73static UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
74static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +000075static UINT ACTION_InstallInitialize(MSIPACKAGE *package);
76static UINT ACTION_InstallValidate(MSIPACKAGE *package);
77static UINT ACTION_ProcessComponents(MSIPACKAGE *package);
78static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package);
79static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
80static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
81static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
82static UINT ACTION_PublishProduct(MSIPACKAGE *package);
Aric Stewart516a9c72005-01-14 15:59:26 +000083static UINT ACTION_WriteIniValues(MSIPACKAGE *package);
Aric Stewart6269f002005-01-17 13:40:39 +000084static UINT ACTION_SelfRegModules(MSIPACKAGE *package);
85static UINT ACTION_PublishFeatures(MSIPACKAGE *package);
Aric Stewart2cae30b2005-01-19 19:07:40 +000086static UINT ACTION_RegisterProduct(MSIPACKAGE *package);
87static UINT ACTION_InstallExecute(MSIPACKAGE *package);
88static UINT ACTION_InstallFinalize(MSIPACKAGE *package);
89static UINT ACTION_ForceReboot(MSIPACKAGE *package);
Aric Stewart401bd3f2004-06-28 20:34:35 +000090
Aric Stewartc75201f2004-06-29 04:04:13 +000091
Aric Stewart6269f002005-01-17 13:40:39 +000092static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
93 LPWSTR *FilePath);
Aric Stewartec688fb2004-07-04 00:35:52 +000094
Aric Stewart401bd3f2004-06-28 20:34:35 +000095/*
96 * consts and values used
97 */
98static const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
99static const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
100static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
Aric Stewartbdb29552004-07-04 00:32:48 +0000101static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
102static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
Aric Stewarteb0e0df2004-06-30 19:38:36 +0000103static const WCHAR c_collen[] = {'C',':','\\',0};
104
Aric Stewart401bd3f2004-06-28 20:34:35 +0000105static const WCHAR cszbs[]={'\\',0};
106
Aric Stewartd2c395a2004-07-06 18:48:15 +0000107const static WCHAR szCreateFolders[] =
108 {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
109const static WCHAR szCostFinalize[] =
110 {'C','o','s','t','F','i','n','a','l','i','z','e',0};
111const static WCHAR szInstallFiles[] =
112 {'I','n','s','t','a','l','l','F','i','l','e','s',0};
113const static WCHAR szDuplicateFiles[] =
114 {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
115const static WCHAR szWriteRegistryValues[] =
116{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
117const static WCHAR szCostInitialize[] =
118 {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
119const static WCHAR szFileCost[] = {'F','i','l','e','C','o','s','t',0};
120const static WCHAR szInstallInitialize[] =
121 {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
122const static WCHAR szInstallValidate[] =
123 {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
124const static WCHAR szLaunchConditions[] =
125 {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
Aric Stewartb942e182004-07-06 18:50:02 +0000126const static WCHAR szProcessComponents[] =
127 {'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0};
Aric Stewartfcb20c52004-07-06 18:51:16 +0000128const static WCHAR szRegisterTypeLibraries[] =
129{'R','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r',
130'i','e','s',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +0000131const static WCHAR szRegisterClassInfo[] =
132{'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
133const static WCHAR szRegisterProgIdInfo[] =
134{'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +0000135const static WCHAR szCreateShortcuts[] =
136{'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
137const static WCHAR szPublishProduct[] =
138{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
Aric Stewart516a9c72005-01-14 15:59:26 +0000139const static WCHAR szWriteIniValues[] =
140{'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
Aric Stewart6269f002005-01-17 13:40:39 +0000141const static WCHAR szSelfRegModules[] =
142{'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0};
143const static WCHAR szPublishFeatures[] =
144{'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
Aric Stewart2cae30b2005-01-19 19:07:40 +0000145const static WCHAR szRegisterProduct[] =
146{'R','e','g','i','s','t','e','r','P','r','o','d','u','c','t',0};
147const static WCHAR szInstallExecute[] =
148{'I','n','s','t','a','l','l','E','x','e','c','u','t','e',0};
149const static WCHAR szInstallExecuteAgain[] =
150{'I','n','s','t','a','l','l','E','x','e','c','u','t','e','A','g','a','i','n',0};
151const static WCHAR szInstallFinalize[] =
152{'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
153const static WCHAR szForceReboot[] =
154{'F','o','r','c','e','R','e','b','o','o','t',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +0000155
156/********************************************************
157 * helper functions to get around current HACKS and such
158 ********************************************************/
Aric Stewartec688fb2004-07-04 00:35:52 +0000159inline static void reduce_to_longfilename(WCHAR* filename)
160{
Mike McCormack9db0e072004-12-22 15:05:07 +0000161 LPWSTR p = strchrW(filename,'|');
162 if (p)
163 memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
Aric Stewartec688fb2004-07-04 00:35:52 +0000164}
165
Aric Stewart54c67dd2005-01-25 20:17:09 +0000166WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)
Aric Stewart7231a432004-07-09 19:26:30 +0000167{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000168 UINT rc;
Aric Stewart7231a432004-07-09 19:26:30 +0000169 DWORD sz;
170 LPWSTR ret;
171
172 sz = 0;
Aric Stewartfa384f62004-12-22 18:46:17 +0000173 if (MSI_RecordIsNull(row,index))
Aric Stewart7231a432004-07-09 19:26:30 +0000174 return NULL;
175
Aric Stewartfa384f62004-12-22 18:46:17 +0000176 rc = MSI_RecordGetStringW(row,index,NULL,&sz);
177
178 /* having an empty string is different than NULL */
179 if (sz == 0)
180 {
181 ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));
182 ret[0] = 0;
183 return ret;
184 }
185
Aric Stewart7231a432004-07-09 19:26:30 +0000186 sz ++;
187 ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000188 rc = MSI_RecordGetStringW(row,index,ret,&sz);
Mike McCormack9db0e072004-12-22 15:05:07 +0000189 if (rc!=ERROR_SUCCESS)
190 {
Aric Stewartfa384f62004-12-22 18:46:17 +0000191 ERR("Unable to load dynamic string\n");
Mike McCormack9db0e072004-12-22 15:05:07 +0000192 HeapFree(GetProcessHeap(), 0, ret);
193 ret = NULL;
194 }
Aric Stewart7231a432004-07-09 19:26:30 +0000195 return ret;
196}
197
Aric Stewart54c67dd2005-01-25 20:17:09 +0000198LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc)
Mike McCormackba8200b2004-12-22 15:25:30 +0000199{
200 DWORD sz = 0;
201 LPWSTR str;
202 UINT r;
203
204 r = MSI_GetPropertyW(package, prop, NULL, &sz);
Aric Stewart25955702004-12-22 17:13:26 +0000205 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
Aric Stewartfa384f62004-12-22 18:46:17 +0000206 {
207 if (rc)
208 *rc = r;
Mike McCormackba8200b2004-12-22 15:25:30 +0000209 return NULL;
Aric Stewartfa384f62004-12-22 18:46:17 +0000210 }
Mike McCormackba8200b2004-12-22 15:25:30 +0000211 sz++;
212 str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
213 r = MSI_GetPropertyW(package, prop, str, &sz);
214 if (r != ERROR_SUCCESS)
215 {
216 HeapFree(GetProcessHeap(),0,str);
217 str = NULL;
218 }
Aric Stewartfa384f62004-12-22 18:46:17 +0000219 if (rc)
220 *rc = r;
Mike McCormackba8200b2004-12-22 15:25:30 +0000221 return str;
222}
223
Aric Stewart54c67dd2005-01-25 20:17:09 +0000224int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
Aric Stewartbdb29552004-07-04 00:32:48 +0000225{
Mike McCormack4604e662004-08-06 17:30:20 +0000226 int rc = -1;
227 DWORD i;
Aric Stewartbdb29552004-07-04 00:32:48 +0000228
229 for (i = 0; i < package->loaded_components; i++)
230 {
231 if (strcmpW(Component,package->components[i].Component)==0)
232 {
233 rc = i;
234 break;
235 }
236 }
237 return rc;
238}
239
Aric Stewart54c67dd2005-01-25 20:17:09 +0000240int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
Aric Stewart7d3e5972004-07-04 00:36:58 +0000241{
Mike McCormack4604e662004-08-06 17:30:20 +0000242 int rc = -1;
243 DWORD i;
Aric Stewart7d3e5972004-07-04 00:36:58 +0000244
245 for (i = 0; i < package->loaded_features; i++)
246 {
247 if (strcmpW(Feature,package->features[i].Feature)==0)
248 {
249 rc = i;
250 break;
251 }
252 }
253 return rc;
254}
255
Aric Stewart54c67dd2005-01-25 20:17:09 +0000256int get_loaded_file(MSIPACKAGE* package, LPCWSTR file)
Aric Stewartfcb20c52004-07-06 18:51:16 +0000257{
Mike McCormack4604e662004-08-06 17:30:20 +0000258 int rc = -1;
259 DWORD i;
Aric Stewartfcb20c52004-07-06 18:51:16 +0000260
261 for (i = 0; i < package->loaded_files; i++)
262 {
263 if (strcmpW(file,package->files[i].File)==0)
264 {
265 rc = i;
266 break;
267 }
268 }
269 return rc;
270}
271
Aric Stewart54c67dd2005-01-25 20:17:09 +0000272int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)
Aric Stewartec688fb2004-07-04 00:35:52 +0000273{
Mike McCormack4604e662004-08-06 17:30:20 +0000274 DWORD i;
275 DWORD index;
Aric Stewartec688fb2004-07-04 00:35:52 +0000276
Aric Stewartec688fb2004-07-04 00:35:52 +0000277 if (!package)
278 return -2;
279
280 for (i=0; i < package->loaded_files; i++)
281 if (strcmpW(package->files[i].File,name)==0)
282 return -1;
283
284 index = package->loaded_files;
285 package->loaded_files++;
286 if (package->loaded_files== 1)
287 package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
288 else
289 package->files = HeapReAlloc(GetProcessHeap(),0,
290 package->files , package->loaded_files * sizeof(MSIFILE));
291
292 memset(&package->files[index],0,sizeof(MSIFILE));
293
Aric Stewartfa384f62004-12-22 18:46:17 +0000294 package->files[index].File = dupstrW(name);
295 package->files[index].TargetPath = dupstrW(path);
Aric Stewartec688fb2004-07-04 00:35:52 +0000296 package->files[index].Temporary = TRUE;
297
298 TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));
299
300 return 0;
301}
302
Aric Stewart54c67dd2005-01-25 20:17:09 +0000303static void remove_tracked_tempfiles(MSIPACKAGE* package)
Aric Stewartec688fb2004-07-04 00:35:52 +0000304{
Mike McCormack4604e662004-08-06 17:30:20 +0000305 DWORD i;
Aric Stewartec688fb2004-07-04 00:35:52 +0000306
307 if (!package)
308 return;
309
310 for (i = 0; i < package->loaded_files; i++)
311 {
312 if (package->files[i].Temporary)
Aric Stewartfbdd7092004-12-27 19:06:22 +0000313 {
314 TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath));
Aric Stewartec688fb2004-07-04 00:35:52 +0000315 DeleteFileW(package->files[i].TargetPath);
Aric Stewartfbdd7092004-12-27 19:06:22 +0000316 }
Aric Stewartec688fb2004-07-04 00:35:52 +0000317
318 }
319}
320
Aric Stewart54c67dd2005-01-25 20:17:09 +0000321/* wrapper to resist a need for a full rewrite right now */
322DWORD deformat_string(MSIPACKAGE *package, LPCWSTR ptr, WCHAR** data )
323{
324 if (ptr)
325 {
326 MSIRECORD *rec = MSI_CreateRecord(1);
327 DWORD size = 0;
328 WCHAR size_buf[2] = {' ',0};
329
330 MSI_RecordSetStringW(rec,0,ptr);
331 MSI_FormatRecordW(package,rec,size_buf,&size);
332 if (size > 0)
333 {
334 size++;
335 *data = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
336 MSI_FormatRecordW(package,rec,*data,&size);
337 return sizeof(WCHAR)*size;
338 }
339 }
340
341 *data = NULL;
342 return 0;
343}
344
Aric Stewart51cf7d12005-01-03 14:29:09 +0000345/* Called when the package is being closed */
Aric Stewart54c67dd2005-01-25 20:17:09 +0000346void ACTION_free_package_structures( MSIPACKAGE* package)
Aric Stewart51cf7d12005-01-03 14:29:09 +0000347{
348 INT i;
349
350 TRACE("Freeing package action data\n");
351
Aric Stewart54c67dd2005-01-25 20:17:09 +0000352 remove_tracked_tempfiles(package);
353
Aric Stewart51cf7d12005-01-03 14:29:09 +0000354 /* No dynamic buffers in features */
355 if (package->features && package->loaded_features > 0)
356 HeapFree(GetProcessHeap(),0,package->features);
357
358 for (i = 0; i < package->loaded_folders; i++)
359 {
360 HeapFree(GetProcessHeap(),0,package->folders[i].Directory);
361 HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault);
362 HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault);
363 HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
364 HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource);
365 HeapFree(GetProcessHeap(),0,package->folders[i].Property);
366 }
367 if (package->folders && package->loaded_folders > 0)
368 HeapFree(GetProcessHeap(),0,package->folders);
369
370 /* no dynamic buffers in components */
371 if (package->components && package->loaded_components > 0)
372 HeapFree(GetProcessHeap(),0,package->components);
373
374 for (i = 0; i < package->loaded_files; i++)
375 {
376 HeapFree(GetProcessHeap(),0,package->files[i].File);
377 HeapFree(GetProcessHeap(),0,package->files[i].FileName);
378 HeapFree(GetProcessHeap(),0,package->files[i].Version);
379 HeapFree(GetProcessHeap(),0,package->files[i].Language);
380 HeapFree(GetProcessHeap(),0,package->files[i].SourcePath);
381 HeapFree(GetProcessHeap(),0,package->files[i].TargetPath);
382 }
383
384 if (package->files && package->loaded_files > 0)
385 HeapFree(GetProcessHeap(),0,package->files);
Aric Stewart2cae30b2005-01-19 19:07:40 +0000386
387 for (i = 0; i < package->DeferredActionCount; i++)
388 HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
389 HeapFree(GetProcessHeap(),0,package->DeferredAction);
390
391 for (i = 0; i < package->CommitActionCount; i++)
392 HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
393 HeapFree(GetProcessHeap(),0,package->CommitAction);
394
395 HeapFree(GetProcessHeap(),0,package->PackagePath);
Aric Stewart51cf7d12005-01-03 14:29:09 +0000396}
397
Aric Stewartfa384f62004-12-22 18:46:17 +0000398static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
399{
400 MSIRECORD * row;
401
402 row = MSI_CreateRecord(4);
403 MSI_RecordSetInteger(row,1,a);
404 MSI_RecordSetInteger(row,2,b);
405 MSI_RecordSetInteger(row,3,c);
406 MSI_RecordSetInteger(row,4,d);
407 MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row);
408 msiobj_release(&row->hdr);
409}
410
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000411static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
Aric Stewartd2c395a2004-07-06 18:48:15 +0000412{
413 static const WCHAR Query_t[] =
414{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o',
415'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',
416' ','\'','%','s','\'',0};
417 WCHAR message[1024];
418 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000419 MSIQUERY * view;
420 MSIRECORD * row = 0;
Aric Stewart54c67dd2005-01-25 20:17:09 +0000421 DWORD size;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000422
Mike McCormack9db0e072004-12-22 15:05:07 +0000423 if (!package->LastAction || strcmpW(package->LastAction,action))
Aric Stewartd2c395a2004-07-06 18:48:15 +0000424 {
Mike McCormack0c238852005-01-21 16:19:11 +0000425 rc = MSI_OpenQuery(package->db, &view, Query_t, action);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000426 if (rc != ERROR_SUCCESS)
427 return;
Mike McCormack9db0e072004-12-22 15:05:07 +0000428
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000429 rc = MSI_ViewExecute(view, 0);
Aric Stewart7231a432004-07-09 19:26:30 +0000430 if (rc != ERROR_SUCCESS)
431 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000432 MSI_ViewClose(view);
433 return;
434 }
435 rc = MSI_ViewFetch(view,&row);
436 if (rc != ERROR_SUCCESS)
437 {
438 MSI_ViewClose(view);
Aric Stewart7231a432004-07-09 19:26:30 +0000439 return;
440 }
Aric Stewartd2c395a2004-07-06 18:48:15 +0000441
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000442 if (MSI_RecordIsNull(row,3))
Aric Stewart7231a432004-07-09 19:26:30 +0000443 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000444 msiobj_release(&row->hdr);
445 MSI_ViewClose(view);
446 msiobj_release(&view->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000447 return;
448 }
449
Mike McCormack9db0e072004-12-22 15:05:07 +0000450 /* update the cached actionformat */
Michael Stefaniucb9374072005-01-20 10:36:35 +0000451 HeapFree(GetProcessHeap(),0,package->ActionFormat);
Mike McCormack9db0e072004-12-22 15:05:07 +0000452 package->ActionFormat = load_dynamic_stringW(row,3);
Aric Stewart7231a432004-07-09 19:26:30 +0000453
Michael Stefaniucb9374072005-01-20 10:36:35 +0000454 HeapFree(GetProcessHeap(),0,package->LastAction);
Aric Stewartfa384f62004-12-22 18:46:17 +0000455 package->LastAction = dupstrW(action);
Mike McCormack9db0e072004-12-22 15:05:07 +0000456
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000457 msiobj_release(&row->hdr);
458 MSI_ViewClose(view);
459 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000460 }
Aric Stewartd2c395a2004-07-06 18:48:15 +0000461
Aric Stewart54c67dd2005-01-25 20:17:09 +0000462 MSI_RecordSetStringW(record,0,package->ActionFormat);
463 size = 1024;
464 MSI_FormatRecordW(package,record,message,&size);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000465
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000466 row = MSI_CreateRecord(1);
467 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000468
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000469 MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
470 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000471}
472
473
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000474static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
Aric Stewartd2c395a2004-07-06 18:48:15 +0000475{
476 static const WCHAR template_s[]=
477{'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ','%','s','.',0};
478 static const WCHAR format[] =
479{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
480 static const WCHAR Query_t[] =
481{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o',
482'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',
483' ','\'','%','s','\'',0};
484 WCHAR message[1024];
485 WCHAR timet[0x100];
486 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000487 MSIQUERY * view;
488 MSIRECORD * row = 0;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000489 WCHAR *ActionText=NULL;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000490
491 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
492
Mike McCormack0c238852005-01-21 16:19:11 +0000493 rc = MSI_OpenQuery(package->db, &view, Query_t, action);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000494 if (rc != ERROR_SUCCESS)
495 return;
496 rc = MSI_ViewExecute(view, 0);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000497 if (rc != ERROR_SUCCESS)
498 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000499 MSI_ViewClose(view);
500 msiobj_release(&view->hdr);
501 return;
502 }
503 rc = MSI_ViewFetch(view,&row);
504 if (rc != ERROR_SUCCESS)
505 {
506 MSI_ViewClose(view);
507 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000508 return;
509 }
510
Aric Stewart7231a432004-07-09 19:26:30 +0000511 ActionText = load_dynamic_stringW(row,2);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000512 msiobj_release(&row->hdr);
513 MSI_ViewClose(view);
514 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000515
516 sprintfW(message,template_s,timet,action,ActionText);
517
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000518 row = MSI_CreateRecord(1);
519 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000520
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000521 MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
522 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000523 HeapFree(GetProcessHeap(),0,ActionText);
524}
525
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000526static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
Aric Stewartd2c395a2004-07-06 18:48:15 +0000527 UINT rc)
528{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000529 MSIRECORD * row;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000530 static const WCHAR template_s[]=
531{'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ','%','s',
532'.',0};
533 static const WCHAR template_e[]=
534{'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ','%','s',
535'.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ','%','i','.',0};
536 static const WCHAR format[] =
537{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
538 WCHAR message[1024];
539 WCHAR timet[0x100];
540
541 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
542 if (start)
543 sprintfW(message,template_s,timet,action);
544 else
545 sprintfW(message,template_e,timet,action,rc);
546
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000547 row = MSI_CreateRecord(1);
548 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000549
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000550 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row);
551 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000552}
553
Aric Stewartfa384f62004-12-22 18:46:17 +0000554/*
555 * build_directory_name()
556 *
557 * This function is to save messing round with directory names
558 * It handles adding backslashes between path segments,
559 * and can add \ at the end of the directory name if told to.
560 *
561 * It takes a variable number of arguments.
562 * It always allocates a new string for the result, so make sure
563 * to free the return value when finished with it.
564 *
565 * The first arg is the number of path segments that follow.
566 * The arguments following count are a list of path segments.
567 * A path segment may be NULL.
568 *
Francois Gouget87b09062005-01-10 13:29:24 +0000569 * Path segments will be added with a \ separating them.
Aric Stewartfa384f62004-12-22 18:46:17 +0000570 * A \ will not be added after the last segment, however if the
571 * last segment is NULL, then the last character will be a \
572 *
573 */
574static LPWSTR build_directory_name(DWORD count, ...)
575{
576 DWORD sz = 1, i;
577 LPWSTR dir;
578 va_list va;
579
580 va_start(va,count);
581 for(i=0; i<count; i++)
582 {
583 LPCWSTR str = va_arg(va,LPCWSTR);
584 if (str)
585 sz += strlenW(str) + 1;
586 }
587 va_end(va);
588
589 dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
590 dir[0]=0;
591
592 va_start(va,count);
593 for(i=0; i<count; i++)
594 {
595 LPCWSTR str = va_arg(va,LPCWSTR);
596 if (!str)
597 continue;
598 strcatW(dir, str);
599 if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
600 strcatW(dir, cszbs);
601 }
602 return dir;
603}
604
605
Aric Stewart401bd3f2004-06-28 20:34:35 +0000606/****************************************************
607 * TOP level entry points
608 *****************************************************/
609
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000610UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
Aric Stewart401bd3f2004-06-28 20:34:35 +0000611 LPCWSTR szCommandLine)
612{
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000613 DWORD sz;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000614 WCHAR buffer[10];
Aric Stewart401bd3f2004-06-28 20:34:35 +0000615 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000616 static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
Aric Stewart6269f002005-01-17 13:40:39 +0000617 static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
618 static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
619
620 MSI_SetPropertyW(package, szAction, szInstall);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000621
Aric Stewarte95136b2004-06-29 03:44:01 +0000622 if (szPackagePath)
623 {
Mike McCormackba8200b2004-12-22 15:25:30 +0000624 LPWSTR p, check, path;
Aric Stewarte95136b2004-06-29 03:44:01 +0000625
Aric Stewart2cae30b2005-01-19 19:07:40 +0000626 package->PackagePath = dupstrW(szPackagePath);
Aric Stewartfa384f62004-12-22 18:46:17 +0000627 path = dupstrW(szPackagePath);
Mike McCormackba8200b2004-12-22 15:25:30 +0000628 p = strrchrW(path,'\\');
Aric Stewarte95136b2004-06-29 03:44:01 +0000629 if (p)
630 {
631 p++;
632 *p=0;
633 }
634
Aric Stewartfa384f62004-12-22 18:46:17 +0000635 check = load_dynamic_property(package, cszSourceDir,NULL);
Aric Stewartd0c971a2004-12-22 18:15:50 +0000636 if (!check)
Mike McCormackba8200b2004-12-22 15:25:30 +0000637 MSI_SetPropertyW(package, cszSourceDir, path);
Aric Stewartfa384f62004-12-22 18:46:17 +0000638 else
Mike McCormackba8200b2004-12-22 15:25:30 +0000639 HeapFree(GetProcessHeap(), 0, check);
Aric Stewartfa384f62004-12-22 18:46:17 +0000640
Mike McCormackba8200b2004-12-22 15:25:30 +0000641 HeapFree(GetProcessHeap(), 0, path);
Aric Stewarte95136b2004-06-29 03:44:01 +0000642 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000643
Aric Stewart36eee232004-07-04 00:07:13 +0000644 if (szCommandLine)
645 {
646 LPWSTR ptr,ptr2;
647 ptr = (LPWSTR)szCommandLine;
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000648
Aric Stewart36eee232004-07-04 00:07:13 +0000649 while (*ptr)
650 {
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000651 WCHAR *prop = NULL;
652 WCHAR *val = NULL;
Aric Stewart36eee232004-07-04 00:07:13 +0000653
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000654 TRACE("Looking at %s\n",debugstr_w(ptr));
655
Aric Stewart36eee232004-07-04 00:07:13 +0000656 ptr2 = strchrW(ptr,'=');
657 if (ptr2)
658 {
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000659 BOOL quote=FALSE;
Aric Stewart36eee232004-07-04 00:07:13 +0000660 DWORD len = 0;
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000661
662 while (*ptr == ' ') ptr++;
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000663 len = ptr2-ptr;
664 prop = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
665 strncpyW(prop,ptr,len);
666 prop[len]=0;
Aric Stewart36eee232004-07-04 00:07:13 +0000667 ptr2++;
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000668
669 len = 0;
Aric Stewart36eee232004-07-04 00:07:13 +0000670 ptr = ptr2;
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000671 while (*ptr && (quote || (!quote && *ptr!=' ')))
Aric Stewart36eee232004-07-04 00:07:13 +0000672 {
673 if (*ptr == '"')
674 quote = !quote;
675 ptr++;
676 len++;
677 }
678
679 if (*ptr2=='"')
680 {
681 ptr2++;
682 len -= 2;
683 }
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000684 val = HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
Aric Stewart36eee232004-07-04 00:07:13 +0000685 strncpyW(val,ptr2,len);
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000686 val[len] = 0;
Aric Stewart36eee232004-07-04 00:07:13 +0000687
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000688 if (strlenW(prop) > 0)
689 {
Aric Stewartfa384f62004-12-22 18:46:17 +0000690 TRACE("Found commandline property (%s) = (%s)\n",
691 debugstr_w(prop), debugstr_w(val));
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000692 MSI_SetPropertyW(package,prop,val);
693 }
Aric Stewart2ad3ff82004-12-27 18:50:00 +0000694 HeapFree(GetProcessHeap(),0,val);
695 HeapFree(GetProcessHeap(),0,prop);
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000696 }
697 ptr++;
Aric Stewart36eee232004-07-04 00:07:13 +0000698 }
699 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000700
701 sz = 10;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000702 if (MSI_GetPropertyW(package,szUILevel,buffer,&sz) == ERROR_SUCCESS)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000703 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000704 if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000705 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000706 rc = ACTION_ProcessUISequence(package);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000707 if (rc == ERROR_SUCCESS)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000708 rc = ACTION_ProcessExecSequence(package,TRUE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000709 }
710 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000711 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000712 }
713 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000714 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000715
Aric Stewart09d35c32004-12-27 19:00:26 +0000716 /* process the ending type action */
717 if (rc == ERROR_SUCCESS)
718 rc = ACTION_PerformActionSequence(package,-1);
719 else if (rc == ERROR_FUNCTION_FAILED)
720 rc = ACTION_PerformActionSequence(package,-3);
Aric Stewart54c67dd2005-01-25 20:17:09 +0000721
722 /* finish up running custom actions */
723 ACTION_FinishCustomActions(package);
Aric Stewart09d35c32004-12-27 19:00:26 +0000724
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000725 return rc;
726}
727
Aric Stewart09d35c32004-12-27 19:00:26 +0000728static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq)
729{
730 MSIQUERY * view;
731 UINT rc;
732 WCHAR buffer[0x100];
733 DWORD sz = 0x100;
734 MSIRECORD * row = 0;
735 static const WCHAR ExecSeqQuery[] = {
736 's','e','l','e','c','t',' ','*',' ',
737 'f','r','o','m',' ',
738 'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
739 'S','e','q','u','e','n','c','e',' ',
740 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
741 '=',' ','%','i',0};
742
Mike McCormack0c238852005-01-21 16:19:11 +0000743 rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq);
Aric Stewart09d35c32004-12-27 19:00:26 +0000744
745 if (rc == ERROR_SUCCESS)
746 {
747 rc = MSI_ViewExecute(view, 0);
748
749 if (rc != ERROR_SUCCESS)
750 {
751 MSI_ViewClose(view);
752 msiobj_release(&view->hdr);
753 goto end;
754 }
755
756 TRACE("Running the actions\n");
757
758 rc = MSI_ViewFetch(view,&row);
759 if (rc != ERROR_SUCCESS)
760 {
761 rc = ERROR_SUCCESS;
762 goto end;
763 }
764
765 /* check conditions */
766 if (!MSI_RecordIsNull(row,2))
767 {
768 LPWSTR cond = NULL;
769 cond = load_dynamic_stringW(row,2);
770
771 if (cond)
772 {
773 /* this is a hack to skip errors in the condition code */
774 if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
775 {
776 HeapFree(GetProcessHeap(),0,cond);
777 msiobj_release(&row->hdr);
778 goto end;
779 }
780 else
781 HeapFree(GetProcessHeap(),0,cond);
782 }
783 }
784
785 sz=0x100;
786 rc = MSI_RecordGetStringW(row,1,buffer,&sz);
787 if (rc != ERROR_SUCCESS)
788 {
789 ERR("Error is %x\n",rc);
790 msiobj_release(&row->hdr);
791 goto end;
792 }
793
794 rc = ACTION_PerformAction(package,buffer);
795 msiobj_release(&row->hdr);
796end:
797 MSI_ViewClose(view);
798 msiobj_release(&view->hdr);
799 }
800 else
801 rc = ERROR_SUCCESS;
802
803 return rc;
804}
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000805
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000806static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000807{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000808 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000809 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000810 static const WCHAR ExecSeqQuery[] = {
811 's','e','l','e','c','t',' ','*',' ',
812 'f','r','o','m',' ',
813 'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
814 'S','e','q','u','e','n','c','e',' ',
815 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
816 '>',' ','%','i',' ','o','r','d','e','r',' ',
817 'b','y',' ','S','e','q','u','e','n','c','e',0 };
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000818 MSIRECORD * row = 0;
819 static const WCHAR IVQuery[] = {
820 's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ',
821 'f','r','o','m',' ','I','n','s','t','a','l','l',
822 'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e',' ',
823 'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ',
824 '`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`',
825 0};
Mike McCormack9db0e072004-12-22 15:05:07 +0000826 INT seq = 0;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000827
Mike McCormack9db0e072004-12-22 15:05:07 +0000828 /* get the sequence number */
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000829 if (UIran)
830 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000831 rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);
832 if (rc != ERROR_SUCCESS)
833 return rc;
834 rc = MSI_ViewExecute(view, 0);
835 if (rc != ERROR_SUCCESS)
836 {
837 MSI_ViewClose(view);
838 msiobj_release(&view->hdr);
839 return rc;
840 }
841 rc = MSI_ViewFetch(view,&row);
842 if (rc != ERROR_SUCCESS)
843 {
844 MSI_ViewClose(view);
845 msiobj_release(&view->hdr);
846 return rc;
847 }
848 seq = MSI_RecordGetInteger(row,1);
849 msiobj_release(&row->hdr);
850 MSI_ViewClose(view);
851 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000852 }
Mike McCormack9db0e072004-12-22 15:05:07 +0000853
Mike McCormack0c238852005-01-21 16:19:11 +0000854 rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, seq);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000855 if (rc == ERROR_SUCCESS)
856 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000857 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000858
859 if (rc != ERROR_SUCCESS)
860 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000861 MSI_ViewClose(view);
862 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000863 goto end;
864 }
865
Mike McCormack9db0e072004-12-22 15:05:07 +0000866 TRACE("Running the actions\n");
Aric Stewart401bd3f2004-06-28 20:34:35 +0000867
868 while (1)
869 {
870 WCHAR buffer[0x100];
871 DWORD sz = 0x100;
Aric Stewart401bd3f2004-06-28 20:34:35 +0000872
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000873 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000874 if (rc != ERROR_SUCCESS)
875 {
876 rc = ERROR_SUCCESS;
877 break;
878 }
879
880 /* check conditions */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000881 if (!MSI_RecordIsNull(row,2))
Aric Stewart401bd3f2004-06-28 20:34:35 +0000882 {
Aric Stewart7231a432004-07-09 19:26:30 +0000883 LPWSTR cond = NULL;
884 cond = load_dynamic_stringW(row,2);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000885
Aric Stewart7231a432004-07-09 19:26:30 +0000886 if (cond)
Aric Stewart401bd3f2004-06-28 20:34:35 +0000887 {
Aric Stewart7231a432004-07-09 19:26:30 +0000888 /* this is a hack to skip errors in the condition code */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000889 if (MSI_EvaluateConditionW(package, cond) ==
Aric Stewart7231a432004-07-09 19:26:30 +0000890 MSICONDITION_FALSE)
891 {
892 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000893 msiobj_release(&row->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000894 continue;
895 }
896 else
897 HeapFree(GetProcessHeap(),0,cond);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000898 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000899 }
900
901 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000902 rc = MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000903 if (rc != ERROR_SUCCESS)
904 {
905 ERR("Error is %x\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000906 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000907 break;
908 }
909
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000910 rc = ACTION_PerformAction(package,buffer);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000911
Aric Stewart1282d7a2004-11-03 22:16:53 +0000912 if (rc == ERROR_FUNCTION_NOT_CALLED)
913 rc = ERROR_SUCCESS;
914
Aric Stewart401bd3f2004-06-28 20:34:35 +0000915 if (rc != ERROR_SUCCESS)
916 {
917 ERR("Execution halted due to error (%i)\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000918 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000919 break;
920 }
921
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000922 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000923 }
924
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000925 MSI_ViewClose(view);
926 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000927 }
928
929end:
Aric Stewart401bd3f2004-06-28 20:34:35 +0000930 return rc;
931}
932
933
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000934static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000935{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000936 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000937 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000938 static const WCHAR ExecSeqQuery [] = {
939 's','e','l','e','c','t',' ','*',' ',
940 'f','r','o','m',' ','I','n','s','t','a','l','l',
941 'U','I','S','e','q','u','e','n','c','e',' ',
942 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', '>',' ','0',' ',
943 'o','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e',0};
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000944
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000945 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000946
947 if (rc == ERROR_SUCCESS)
948 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000949 rc = MSI_ViewExecute(view, 0);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000950
951 if (rc != ERROR_SUCCESS)
952 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000953 MSI_ViewClose(view);
954 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000955 goto end;
956 }
957
958 TRACE("Running the actions \n");
959
960 while (1)
961 {
962 WCHAR buffer[0x100];
963 DWORD sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000964 MSIRECORD * row = 0;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000965
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000966 rc = MSI_ViewFetch(view,&row);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000967 if (rc != ERROR_SUCCESS)
968 {
969 rc = ERROR_SUCCESS;
970 break;
971 }
972
973 /* check conditions */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000974 if (!MSI_RecordIsNull(row,2))
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000975 {
Aric Stewart7231a432004-07-09 19:26:30 +0000976 LPWSTR cond = NULL;
977 cond = load_dynamic_stringW(row,2);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000978
Aric Stewart7231a432004-07-09 19:26:30 +0000979 if (cond)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000980 {
Aric Stewart7231a432004-07-09 19:26:30 +0000981 /* this is a hack to skip errors in the condition code */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000982 if (MSI_EvaluateConditionW(package, cond) ==
Aric Stewart7231a432004-07-09 19:26:30 +0000983 MSICONDITION_FALSE)
984 {
985 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000986 msiobj_release(&row->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000987 continue;
988 }
989 else
990 HeapFree(GetProcessHeap(),0,cond);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000991 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000992 }
993
994 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000995 rc = MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000996 if (rc != ERROR_SUCCESS)
997 {
998 ERR("Error is %x\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000999 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001000 break;
1001 }
1002
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001003 rc = ACTION_PerformAction(package,buffer);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001004
Aric Stewart1282d7a2004-11-03 22:16:53 +00001005 if (rc == ERROR_FUNCTION_NOT_CALLED)
1006 rc = ERROR_SUCCESS;
1007
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001008 if (rc != ERROR_SUCCESS)
1009 {
1010 ERR("Execution halted due to error (%i)\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001011 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001012 break;
1013 }
1014
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001015 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001016 }
1017
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001018 MSI_ViewClose(view);
1019 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001020 }
1021
1022end:
1023 return rc;
1024}
1025
Aric Stewart401bd3f2004-06-28 20:34:35 +00001026/********************************************************
1027 * ACTION helper functions and functions that perform the actions
1028 *******************************************************/
1029
1030/*
1031 * Alot of actions are really important even if they don't do anything
1032 * explicit.. Lots of properties are set at the beginning of the installation
Mike McCormack6e2bca32004-07-04 00:25:00 +00001033 * CostFinalize does a bunch of work to translated the directories and such
Aric Stewart401bd3f2004-06-28 20:34:35 +00001034 *
Mike McCormack6e2bca32004-07-04 00:25:00 +00001035 * But until I get write access to the database that is hard, so I am going to
Aric Stewart401bd3f2004-06-28 20:34:35 +00001036 * hack it to see if I can get something to run.
1037 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001038UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001039{
Aric Stewartd2c395a2004-07-06 18:48:15 +00001040 UINT rc = ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001041
1042 TRACE("Performing action (%s)\n",debugstr_w(action));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001043 ui_actioninfo(package, action, TRUE, 0);
1044 ui_actionstart(package, action);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001045
Mike McCormack24e9a342004-07-06 18:56:12 +00001046 /* pre install, setup and configuration block */
Aric Stewart5b936ca2004-07-06 18:47:09 +00001047 if (strcmpW(action,szLaunchConditions)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001048 rc = ACTION_LaunchConditions(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001049 else if (strcmpW(action,szCostInitialize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001050 rc = ACTION_CostInitialize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001051 else if (strcmpW(action,szFileCost)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001052 rc = ACTION_FileCost(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001053 else if (strcmpW(action,szCostFinalize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001054 rc = ACTION_CostFinalize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001055 else if (strcmpW(action,szInstallValidate)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001056 rc = ACTION_InstallValidate(package);
Aric Stewart7d3e5972004-07-04 00:36:58 +00001057
1058 /* install block */
Aric Stewartb942e182004-07-06 18:50:02 +00001059 else if (strcmpW(action,szProcessComponents)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001060 rc = ACTION_ProcessComponents(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001061 else if (strcmpW(action,szInstallInitialize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001062 rc = ACTION_InstallInitialize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001063 else if (strcmpW(action,szCreateFolders)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001064 rc = ACTION_CreateFolders(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001065 else if (strcmpW(action,szInstallFiles)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001066 rc = ACTION_InstallFiles(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001067 else if (strcmpW(action,szDuplicateFiles)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001068 rc = ACTION_DuplicateFiles(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001069 else if (strcmpW(action,szWriteRegistryValues)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001070 rc = ACTION_WriteRegistryValues(package);
Aric Stewartfcb20c52004-07-06 18:51:16 +00001071 else if (strcmpW(action,szRegisterTypeLibraries)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001072 rc = ACTION_RegisterTypeLibraries(package);
Aric Stewart8f0a7612004-07-06 18:53:11 +00001073 else if (strcmpW(action,szRegisterClassInfo)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001074 rc = ACTION_RegisterClassInfo(package);
Aric Stewart8f0a7612004-07-06 18:53:11 +00001075 else if (strcmpW(action,szRegisterProgIdInfo)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001076 rc = ACTION_RegisterProgIdInfo(package);
Aric Stewart2cf222f2004-07-06 19:00:23 +00001077 else if (strcmpW(action,szCreateShortcuts)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001078 rc = ACTION_CreateShortcuts(package);
Aric Stewart2cf222f2004-07-06 19:00:23 +00001079 else if (strcmpW(action,szPublishProduct)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001080 rc = ACTION_PublishProduct(package);
Aric Stewart516a9c72005-01-14 15:59:26 +00001081 else if (strcmpW(action,szWriteIniValues)==0)
1082 rc = ACTION_WriteIniValues(package);
Aric Stewart6269f002005-01-17 13:40:39 +00001083 else if (strcmpW(action,szSelfRegModules)==0)
1084 rc = ACTION_SelfRegModules(package);
1085 else if (strcmpW(action,szPublishFeatures)==0)
1086 rc = ACTION_PublishFeatures(package);
Aric Stewart2cae30b2005-01-19 19:07:40 +00001087 else if (strcmpW(action,szRegisterProduct)==0)
1088 rc = ACTION_RegisterProduct(package);
1089 else if (strcmpW(action,szInstallExecute)==0)
1090 rc = ACTION_InstallExecute(package);
1091 else if (strcmpW(action,szInstallExecuteAgain)==0)
1092 rc = ACTION_InstallExecute(package);
1093 else if (strcmpW(action,szInstallFinalize)==0)
1094 rc = ACTION_InstallFinalize(package);
1095 else if (strcmpW(action,szForceReboot)==0)
1096 rc = ACTION_ForceReboot(package);
Aric Stewart7d3e5972004-07-04 00:36:58 +00001097
Aric Stewart401bd3f2004-06-28 20:34:35 +00001098 /*
Mike McCormack3ece2462004-07-09 19:33:25 +00001099 Called during iTunes but unimplemented and seem important
Aric Stewartc75201f2004-06-29 04:04:13 +00001100
Aric Stewartc75201f2004-06-29 04:04:13 +00001101 ResolveSource (sets SourceDir)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001102 */
Aric Stewart2cae30b2005-01-19 19:07:40 +00001103 else if ((rc = ACTION_CustomAction(package,action,FALSE)) != ERROR_SUCCESS)
Aric Stewartd2c395a2004-07-06 18:48:15 +00001104 {
Aric Stewartec688fb2004-07-04 00:35:52 +00001105 FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001106 rc = ERROR_FUNCTION_NOT_CALLED;
Aric Stewartd2c395a2004-07-06 18:48:15 +00001107 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001108
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001109 ui_actioninfo(package, action, FALSE, rc);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001110 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001111}
1112
Aric Stewart401bd3f2004-06-28 20:34:35 +00001113/***********************************************************************
1114 * create_full_pathW
1115 *
1116 * Recursively create all directories in the path.
1117 *
1118 * shamelessly stolen from setupapi/queue.c
1119 */
1120static BOOL create_full_pathW(const WCHAR *path)
1121{
1122 BOOL ret = TRUE;
1123 int len;
1124 WCHAR *new_path;
1125
1126 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) *
Aric Stewartfa384f62004-12-22 18:46:17 +00001127 sizeof(WCHAR));
1128
Aric Stewart401bd3f2004-06-28 20:34:35 +00001129 strcpyW(new_path, path);
1130
1131 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
1132 new_path[len - 1] = 0;
1133
1134 while(!CreateDirectoryW(new_path, NULL))
1135 {
Mike McCormackac6a4132005-01-04 20:36:12 +00001136 WCHAR *slash;
1137 DWORD last_error = GetLastError();
1138 if(last_error == ERROR_ALREADY_EXISTS)
1139 break;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001140
Mike McCormackac6a4132005-01-04 20:36:12 +00001141 if(last_error != ERROR_PATH_NOT_FOUND)
1142 {
1143 ret = FALSE;
1144 break;
1145 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001146
Mike McCormackac6a4132005-01-04 20:36:12 +00001147 if(!(slash = strrchrW(new_path, '\\')))
1148 {
1149 ret = FALSE;
1150 break;
1151 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001152
Mike McCormackac6a4132005-01-04 20:36:12 +00001153 len = slash - new_path;
1154 new_path[len] = 0;
1155 if(!create_full_pathW(new_path))
1156 {
1157 ret = FALSE;
1158 break;
1159 }
1160 new_path[len] = '\\';
Aric Stewart401bd3f2004-06-28 20:34:35 +00001161 }
1162
1163 HeapFree(GetProcessHeap(), 0, new_path);
1164 return ret;
1165}
1166
1167/*
1168 * Also we cannot enable/disable components either, so for now I am just going
Mike McCormack6e2bca32004-07-04 00:25:00 +00001169 * to do all the directories for all the components.
Aric Stewart401bd3f2004-06-28 20:34:35 +00001170 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001171static UINT ACTION_CreateFolders(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001172{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001173 static const WCHAR ExecSeqQuery[] = {
1174 's','e','l','e','c','t',' ','D','i','r','e','c','t','o','r','y','_',' ',
1175 'f','r','o','m',' ','C','r','e','a','t','e','F','o','l','d','e','r',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00001176 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001177 MSIQUERY *view;
Aric Stewartbdb29552004-07-04 00:32:48 +00001178 MSIFOLDER *folder;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001179
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001180 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001181 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00001182 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001183
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001184 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001185 if (rc != ERROR_SUCCESS)
1186 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001187 MSI_ViewClose(view);
1188 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001189 return rc;
1190 }
1191
1192 while (1)
1193 {
1194 WCHAR dir[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00001195 LPWSTR full_path;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001196 DWORD sz;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001197 MSIRECORD *row = NULL, *uirow;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001198
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001199 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001200 if (rc != ERROR_SUCCESS)
1201 {
1202 rc = ERROR_SUCCESS;
1203 break;
1204 }
1205
1206 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001207 rc = MSI_RecordGetStringW(row,1,dir,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001208
1209 if (rc!= ERROR_SUCCESS)
1210 {
1211 ERR("Unable to get folder id \n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001212 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001213 continue;
1214 }
1215
Aric Stewarte95136b2004-06-29 03:44:01 +00001216 sz = MAX_PATH;
Mike McCormackba8200b2004-12-22 15:25:30 +00001217 full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);
1218 if (!full_path)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001219 {
1220 ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001221 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001222 continue;
1223 }
1224
1225 TRACE("Folder is %s\n",debugstr_w(full_path));
Aric Stewartec688fb2004-07-04 00:35:52 +00001226
Aric Stewartd2c395a2004-07-06 18:48:15 +00001227 /* UI stuff */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001228 uirow = MSI_CreateRecord(1);
1229 MSI_RecordSetStringW(uirow,1,full_path);
1230 ui_actiondata(package,szCreateFolders,uirow);
1231 msiobj_release( &uirow->hdr );
Aric Stewartd2c395a2004-07-06 18:48:15 +00001232
Aric Stewartbdb29552004-07-04 00:32:48 +00001233 if (folder->State == 0)
1234 create_full_pathW(full_path);
1235
1236 folder->State = 3;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001237
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001238 msiobj_release(&row->hdr);
Mike McCormackba8200b2004-12-22 15:25:30 +00001239 HeapFree(GetProcessHeap(),0,full_path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001240 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001241 MSI_ViewClose(view);
1242 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001243
1244 return rc;
1245}
1246
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001247static int load_component(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartbdb29552004-07-04 00:32:48 +00001248{
1249 int index = package->loaded_components;
1250 DWORD sz;
1251
1252 /* fill in the data */
1253
1254 package->loaded_components++;
1255 if (package->loaded_components == 1)
1256 package->components = HeapAlloc(GetProcessHeap(),0,
1257 sizeof(MSICOMPONENT));
1258 else
1259 package->components = HeapReAlloc(GetProcessHeap(),0,
1260 package->components, package->loaded_components *
1261 sizeof(MSICOMPONENT));
1262
1263 memset(&package->components[index],0,sizeof(MSICOMPONENT));
1264
1265 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001266 MSI_RecordGetStringW(row,1,package->components[index].Component,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001267
1268 TRACE("Loading Component %s\n",
1269 debugstr_w(package->components[index].Component));
1270
1271 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001272 if (!MSI_RecordIsNull(row,2))
1273 MSI_RecordGetStringW(row,2,package->components[index].ComponentId,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001274
1275 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001276 MSI_RecordGetStringW(row,3,package->components[index].Directory,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001277
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001278 package->components[index].Attributes = MSI_RecordGetInteger(row,4);
Aric Stewartbdb29552004-07-04 00:32:48 +00001279
1280 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001281 MSI_RecordGetStringW(row,5,package->components[index].Condition,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001282
1283 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001284 MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001285
Aric Stewartfbdd7092004-12-27 19:06:22 +00001286 package->components[index].Installed = INSTALLSTATE_ABSENT;
1287 package->components[index].Action = INSTALLSTATE_UNKNOWN;
1288 package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN;
1289
Aric Stewartbdb29552004-07-04 00:32:48 +00001290 package->components[index].Enabled = TRUE;
1291
1292 return index;
1293}
1294
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001295static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartbdb29552004-07-04 00:32:48 +00001296{
1297 int index = package->loaded_features;
1298 DWORD sz;
1299 static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p',
Mike McCormack9db0e072004-12-22 15:05:07 +00001300 'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e',
1301 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e',
1302 'a','t','u','r','e','_','=','\'','%','s','\'',0};
Aric Stewartbdb29552004-07-04 00:32:48 +00001303 static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R',
Mike McCormack9db0e072004-12-22 15:05:07 +00001304 'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C',
1305 'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001306 MSIQUERY * view;
1307 MSIQUERY * view2;
1308 MSIRECORD * row2;
1309 MSIRECORD * row3;
1310 UINT rc;
Aric Stewartbdb29552004-07-04 00:32:48 +00001311
1312 /* fill in the data */
1313
1314 package->loaded_features ++;
1315 if (package->loaded_features == 1)
1316 package->features = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFEATURE));
1317 else
1318 package->features = HeapReAlloc(GetProcessHeap(),0,package->features,
1319 package->loaded_features * sizeof(MSIFEATURE));
1320
1321 memset(&package->features[index],0,sizeof(MSIFEATURE));
1322
1323 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001324 MSI_RecordGetStringW(row,1,package->features[index].Feature,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001325
1326 TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature));
1327
1328 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001329 if (!MSI_RecordIsNull(row,2))
1330 MSI_RecordGetStringW(row,2,package->features[index].Feature_Parent,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001331
1332 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001333 if (!MSI_RecordIsNull(row,3))
1334 MSI_RecordGetStringW(row,3,package->features[index].Title,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001335
1336 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001337 if (!MSI_RecordIsNull(row,4))
1338 MSI_RecordGetStringW(row,4,package->features[index].Description,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001339
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001340 if (!MSI_RecordIsNull(row,5))
1341 package->features[index].Display = MSI_RecordGetInteger(row,5);
Aric Stewartbdb29552004-07-04 00:32:48 +00001342
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001343 package->features[index].Level= MSI_RecordGetInteger(row,6);
Aric Stewartbdb29552004-07-04 00:32:48 +00001344
1345 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001346 if (!MSI_RecordIsNull(row,7))
1347 MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001348
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001349 package->features[index].Attributes= MSI_RecordGetInteger(row,8);
Aric Stewartfbdd7092004-12-27 19:06:22 +00001350
1351 package->features[index].Installed = INSTALLSTATE_ABSENT;
1352 package->features[index].Action = INSTALLSTATE_UNKNOWN;
1353 package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;
Aric Stewartbdb29552004-07-04 00:32:48 +00001354
1355 /* load feature components */
1356
Mike McCormack0c238852005-01-21 16:19:11 +00001357 rc = MSI_OpenQuery(package->db, &view, Query1, package->features[index].Feature);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001358 if (rc != ERROR_SUCCESS)
1359 return;
1360 rc = MSI_ViewExecute(view,0);
1361 if (rc != ERROR_SUCCESS)
1362 {
1363 MSI_ViewClose(view);
1364 msiobj_release(&view->hdr);
1365 return;
1366 }
Aric Stewartbdb29552004-07-04 00:32:48 +00001367 while (1)
1368 {
1369 DWORD sz = 0x100;
1370 WCHAR buffer[0x100];
1371 DWORD rc;
1372 INT c_indx;
1373 INT cnt = package->features[index].ComponentCount;
1374
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001375 rc = MSI_ViewFetch(view,&row2);
Aric Stewartbdb29552004-07-04 00:32:48 +00001376 if (rc != ERROR_SUCCESS)
1377 break;
1378
1379 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001380 MSI_RecordGetStringW(row2,1,buffer,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001381
1382 /* check to see if the component is already loaded */
1383 c_indx = get_loaded_component(package,buffer);
1384 if (c_indx != -1)
1385 {
1386 TRACE("Component %s already loaded at %i\n", debugstr_w(buffer),
1387 c_indx);
1388 package->features[index].Components[cnt] = c_indx;
1389 package->features[index].ComponentCount ++;
Aric Stewartea32fb92004-12-27 19:09:16 +00001390 continue;
Aric Stewartbdb29552004-07-04 00:32:48 +00001391 }
1392
Mike McCormack0c238852005-01-21 16:19:11 +00001393 rc = MSI_OpenQuery(package->db, &view2, Query2, buffer);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001394 if (rc != ERROR_SUCCESS)
1395 {
1396 msiobj_release( &row2->hdr );
1397 continue;
1398 }
1399 rc = MSI_ViewExecute(view2,0);
1400 if (rc != ERROR_SUCCESS)
1401 {
1402 msiobj_release( &row2->hdr );
1403 MSI_ViewClose(view2);
1404 msiobj_release( &view2->hdr );
1405 continue;
1406 }
Aric Stewartbdb29552004-07-04 00:32:48 +00001407 while (1)
1408 {
1409 DWORD rc;
1410
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001411 rc = MSI_ViewFetch(view2,&row3);
Aric Stewartbdb29552004-07-04 00:32:48 +00001412 if (rc != ERROR_SUCCESS)
1413 break;
1414 c_indx = load_component(package,row3);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001415 msiobj_release( &row3->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00001416
1417 package->features[index].Components[cnt] = c_indx;
1418 package->features[index].ComponentCount ++;
Aric Stewartea32fb92004-12-27 19:09:16 +00001419 TRACE("Loaded new component to index %i\n",c_indx);
Aric Stewartbdb29552004-07-04 00:32:48 +00001420 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001421 MSI_ViewClose(view2);
1422 msiobj_release( &view2->hdr );
1423 msiobj_release( &row2->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00001424 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001425 MSI_ViewClose(view);
1426 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001427}
1428
1429/*
1430 * I am not doing any of the costing functionality yet.
1431 * Mostly looking at doing the Component and Feature loading
1432 *
1433 * The native MSI does ALOT of modification to tables here. Mostly adding alot
1434 * of temporary columns to the Feature and Component tables.
1435 *
Mike McCormack24e9a342004-07-06 18:56:12 +00001436 * note: native msi also tracks the short filename. but I am only going to
Aric Stewartbdb29552004-07-04 00:32:48 +00001437 * track the long ones. Also looking at this directory table
1438 * it appears that the directory table does not get the parents
1439 * resolved base on property only based on their entrys in the
1440 * directory table.
1441 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001442static UINT ACTION_CostInitialize(MSIPACKAGE *package)
Aric Stewartbdb29552004-07-04 00:32:48 +00001443{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001444 MSIQUERY * view;
1445 MSIRECORD * row;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001446 UINT rc;
1447 static const WCHAR Query_all[] = {
1448 'S','E','L','E','C','T',' ','*',' ',
1449 'F','R','O','M',' ','F','e','a','t','u','r','e',0};
1450 static const WCHAR szCosting[] = {
1451 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
1452 static const WCHAR szZero[] = { '0', 0 };
Aric Stewartbdb29552004-07-04 00:32:48 +00001453
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001454 MSI_SetPropertyW(package, szCosting, szZero);
1455 MSI_SetPropertyW(package, cszRootDrive , c_collen);
Aric Stewartbdb29552004-07-04 00:32:48 +00001456
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001457 rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view);
1458 if (rc != ERROR_SUCCESS)
1459 return rc;
1460 rc = MSI_ViewExecute(view,0);
1461 if (rc != ERROR_SUCCESS)
1462 {
1463 MSI_ViewClose(view);
1464 msiobj_release(&view->hdr);
1465 return rc;
1466 }
Aric Stewartec688fb2004-07-04 00:35:52 +00001467 while (1)
Aric Stewartbdb29552004-07-04 00:32:48 +00001468 {
Aric Stewartec688fb2004-07-04 00:35:52 +00001469 DWORD rc;
Aric Stewartbdb29552004-07-04 00:32:48 +00001470
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001471 rc = MSI_ViewFetch(view,&row);
Aric Stewartec688fb2004-07-04 00:35:52 +00001472 if (rc != ERROR_SUCCESS)
1473 break;
Aric Stewartbdb29552004-07-04 00:32:48 +00001474
Aric Stewartec688fb2004-07-04 00:35:52 +00001475 load_feature(package,row);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001476 msiobj_release(&row->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001477 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001478 MSI_ViewClose(view);
1479 msiobj_release(&view->hdr);
Aric Stewartec688fb2004-07-04 00:35:52 +00001480
1481 return ERROR_SUCCESS;
1482}
1483
Mike McCormack4604e662004-08-06 17:30:20 +00001484static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartec688fb2004-07-04 00:35:52 +00001485{
Mike McCormack4604e662004-08-06 17:30:20 +00001486 DWORD index = package->loaded_files;
1487 DWORD i;
Mike McCormack9db0e072004-12-22 15:05:07 +00001488 LPWSTR buffer;
Aric Stewartec688fb2004-07-04 00:35:52 +00001489
1490 /* fill in the data */
1491
1492 package->loaded_files++;
1493 if (package->loaded_files== 1)
1494 package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
1495 else
1496 package->files = HeapReAlloc(GetProcessHeap(),0,
1497 package->files , package->loaded_files * sizeof(MSIFILE));
1498
1499 memset(&package->files[index],0,sizeof(MSIFILE));
Mike McCormack9db0e072004-12-22 15:05:07 +00001500
1501 package->files[index].File = load_dynamic_stringW(row, 1);
1502 buffer = load_dynamic_stringW(row, 2);
Aric Stewartec688fb2004-07-04 00:35:52 +00001503
1504 package->files[index].ComponentIndex = -1;
1505 for (i = 0; i < package->loaded_components; i++)
1506 if (strcmpW(package->components[i].Component,buffer)==0)
1507 {
1508 package->files[index].ComponentIndex = i;
1509 break;
1510 }
1511 if (package->files[index].ComponentIndex == -1)
1512 ERR("Unfound Component %s\n",debugstr_w(buffer));
Mike McCormack9db0e072004-12-22 15:05:07 +00001513 HeapFree(GetProcessHeap(), 0, buffer);
Aric Stewartec688fb2004-07-04 00:35:52 +00001514
Mike McCormack9db0e072004-12-22 15:05:07 +00001515 package->files[index].FileName = load_dynamic_stringW(row,3);
Aric Stewartec688fb2004-07-04 00:35:52 +00001516
1517 reduce_to_longfilename(package->files[index].FileName);
1518
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001519 package->files[index].FileSize = MSI_RecordGetInteger(row,4);
Mike McCormack9db0e072004-12-22 15:05:07 +00001520 package->files[index].Version = load_dynamic_stringW(row, 5);
1521 package->files[index].Language = load_dynamic_stringW(row, 6);
1522 package->files[index].Attributes= MSI_RecordGetInteger(row,7);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001523 package->files[index].Sequence= MSI_RecordGetInteger(row,8);
Aric Stewartec688fb2004-07-04 00:35:52 +00001524
1525 package->files[index].Temporary = FALSE;
1526 package->files[index].State = 0;
1527
1528 TRACE("File Loaded (%s)\n",debugstr_w(package->files[index].File));
1529
1530 return ERROR_SUCCESS;
1531}
1532
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001533static UINT ACTION_FileCost(MSIPACKAGE *package)
Aric Stewartec688fb2004-07-04 00:35:52 +00001534{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001535 MSIQUERY * view;
1536 MSIRECORD * row;
Aric Stewartec688fb2004-07-04 00:35:52 +00001537 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001538 static const WCHAR Query[] = {
1539 'S','E','L','E','C','T',' ','*',' ',
1540 'F','R','O','M',' ','F','i','l','e',' ',
1541 'O','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e', 0};
Aric Stewartec688fb2004-07-04 00:35:52 +00001542
Aric Stewartec688fb2004-07-04 00:35:52 +00001543 if (!package)
1544 return ERROR_INVALID_HANDLE;
1545
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001546 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewartec688fb2004-07-04 00:35:52 +00001547 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00001548 return ERROR_SUCCESS;
Aric Stewartec688fb2004-07-04 00:35:52 +00001549
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001550 rc = MSI_ViewExecute(view, 0);
Aric Stewartec688fb2004-07-04 00:35:52 +00001551 if (rc != ERROR_SUCCESS)
1552 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001553 MSI_ViewClose(view);
1554 msiobj_release(&view->hdr);
Aric Stewart84837d92004-07-20 01:22:37 +00001555 return ERROR_SUCCESS;
Aric Stewartec688fb2004-07-04 00:35:52 +00001556 }
1557
1558 while (1)
1559 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001560 rc = MSI_ViewFetch(view,&row);
Aric Stewartec688fb2004-07-04 00:35:52 +00001561 if (rc != ERROR_SUCCESS)
1562 {
1563 rc = ERROR_SUCCESS;
1564 break;
1565 }
1566 load_file(package,row);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001567 msiobj_release(&row->hdr);
Aric Stewartec688fb2004-07-04 00:35:52 +00001568 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001569 MSI_ViewClose(view);
1570 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001571
1572 return ERROR_SUCCESS;
1573}
1574
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001575static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
Aric Stewartbdb29552004-07-04 00:32:48 +00001576
1577{
Mike McCormackba8200b2004-12-22 15:25:30 +00001578 static const WCHAR Query[] =
1579 {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c',
1580 't','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t',
1581 'o','r','y','`',' ','=',' ','`','%','s','`',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00001582 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001583 MSIQUERY * view;
Mike McCormackba8200b2004-12-22 15:25:30 +00001584 LPWSTR targetdir, parent, srcdir;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001585 MSIRECORD * row = 0;
Mike McCormack4604e662004-08-06 17:30:20 +00001586 INT index = -1;
1587 DWORD i;
Aric Stewarte95136b2004-06-29 03:44:01 +00001588
Aric Stewartbdb29552004-07-04 00:32:48 +00001589 TRACE("Looking for dir %s\n",debugstr_w(dir));
Aric Stewart401bd3f2004-06-28 20:34:35 +00001590
Aric Stewartbdb29552004-07-04 00:32:48 +00001591 for (i = 0; i < package->loaded_folders; i++)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001592 {
Aric Stewartbdb29552004-07-04 00:32:48 +00001593 if (strcmpW(package->folders[i].Directory,dir)==0)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001594 {
Mike McCormack4604e662004-08-06 17:30:20 +00001595 TRACE(" %s retuning on index %lu\n",debugstr_w(dir),i);
Aric Stewartbdb29552004-07-04 00:32:48 +00001596 return i;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001597 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001598 }
1599
Aric Stewartbdb29552004-07-04 00:32:48 +00001600 TRACE("Working to load %s\n",debugstr_w(dir));
1601
Mike McCormackba8200b2004-12-22 15:25:30 +00001602 index = package->loaded_folders++;
1603 if (package->loaded_folders==1)
Aric Stewartbdb29552004-07-04 00:32:48 +00001604 package->folders = HeapAlloc(GetProcessHeap(),0,
1605 sizeof(MSIFOLDER));
1606 else
1607 package->folders= HeapReAlloc(GetProcessHeap(),0,
1608 package->folders, package->loaded_folders*
1609 sizeof(MSIFOLDER));
1610
1611 memset(&package->folders[index],0,sizeof(MSIFOLDER));
1612
Aric Stewartfa384f62004-12-22 18:46:17 +00001613 package->folders[index].Directory = dupstrW(dir);
Aric Stewartbdb29552004-07-04 00:32:48 +00001614
Mike McCormack0c238852005-01-21 16:19:11 +00001615 rc = MSI_OpenQuery(package->db, &view, Query, dir);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001616 if (rc != ERROR_SUCCESS)
Aric Stewartbdb29552004-07-04 00:32:48 +00001617 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001618
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001619 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001620 if (rc != ERROR_SUCCESS)
1621 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001622 MSI_ViewClose(view);
1623 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001624 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001625 }
1626
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001627 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001628 if (rc != ERROR_SUCCESS)
1629 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001630 MSI_ViewClose(view);
1631 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001632 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001633 }
1634
Mike McCormackba8200b2004-12-22 15:25:30 +00001635 targetdir = load_dynamic_stringW(row,3);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001636
1637 /* split src and target dir */
1638 if (strchrW(targetdir,':'))
1639 {
1640 srcdir=strchrW(targetdir,':');
1641 *srcdir=0;
1642 srcdir ++;
1643 }
1644 else
1645 srcdir=NULL;
1646
1647 /* for now only pick long filename versions */
1648 if (strchrW(targetdir,'|'))
1649 {
1650 targetdir = strchrW(targetdir,'|');
1651 *targetdir = 0;
1652 targetdir ++;
1653 }
1654 if (srcdir && strchrW(srcdir,'|'))
1655 {
1656 srcdir= strchrW(srcdir,'|');
1657 *srcdir= 0;
1658 srcdir ++;
1659 }
1660
1661 /* now check for root dirs */
1662 if (targetdir[0] == '.' && targetdir[1] == 0)
1663 targetdir = NULL;
1664
1665 if (srcdir && srcdir[0] == '.' && srcdir[1] == 0)
1666 srcdir = NULL;
1667
Mike McCormackba8200b2004-12-22 15:25:30 +00001668 if (targetdir)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001669 {
Mike McCormackba8200b2004-12-22 15:25:30 +00001670 TRACE(" TargetDefault = %s\n",debugstr_w(targetdir));
Michael Stefaniucb9374072005-01-20 10:36:35 +00001671 HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault);
Aric Stewartfa384f62004-12-22 18:46:17 +00001672 package->folders[index].TargetDefault = dupstrW(targetdir);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001673 }
1674
Mike McCormackba8200b2004-12-22 15:25:30 +00001675 if (srcdir)
Aric Stewartfa384f62004-12-22 18:46:17 +00001676 package->folders[index].SourceDefault = dupstrW(srcdir);
Mike McCormackba8200b2004-12-22 15:25:30 +00001677 else if (targetdir)
Aric Stewartfa384f62004-12-22 18:46:17 +00001678 package->folders[index].SourceDefault = dupstrW(targetdir);
Mike McCormackba8200b2004-12-22 15:25:30 +00001679 HeapFree(GetProcessHeap(), 0, targetdir);
1680
1681 parent = load_dynamic_stringW(row,2);
1682 if (parent)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001683 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001684 i = load_folder(package,parent);
Aric Stewartbdb29552004-07-04 00:32:48 +00001685 package->folders[index].ParentIndex = i;
1686 TRACE("Parent is index %i... %s %s\n",
1687 package->folders[index].ParentIndex,
Mike McCormackba8200b2004-12-22 15:25:30 +00001688 debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),
Aric Stewartbdb29552004-07-04 00:32:48 +00001689 debugstr_w(parent));
1690 }
1691 else
1692 package->folders[index].ParentIndex = -2;
Mike McCormackba8200b2004-12-22 15:25:30 +00001693 HeapFree(GetProcessHeap(), 0, parent);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001694
Aric Stewartfa384f62004-12-22 18:46:17 +00001695 package->folders[index].Property = load_dynamic_property(package, dir,NULL);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001696
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001697 msiobj_release(&row->hdr);
1698 MSI_ViewClose(view);
1699 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001700 TRACE(" %s retuning on index %i\n",debugstr_w(dir),index);
1701 return index;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001702}
1703
Mike McCormackba8200b2004-12-22 15:25:30 +00001704
Aric Stewart54c67dd2005-01-25 20:17:09 +00001705LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
1706 BOOL set_prop, MSIFOLDER **folder)
Aric Stewarte95136b2004-06-29 03:44:01 +00001707{
Mike McCormack4604e662004-08-06 17:30:20 +00001708 DWORD i;
Mike McCormackba8200b2004-12-22 15:25:30 +00001709 LPWSTR p, path = NULL;
Aric Stewart36eee232004-07-04 00:07:13 +00001710
Aric Stewartbdb29552004-07-04 00:32:48 +00001711 TRACE("Working to resolve %s\n",debugstr_w(name));
Aric Stewart36eee232004-07-04 00:07:13 +00001712
Aric Stewartbdb29552004-07-04 00:32:48 +00001713 /* special resolving for Target and Source root dir */
1714 if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
Aric Stewart36eee232004-07-04 00:07:13 +00001715 {
Aric Stewartbdb29552004-07-04 00:32:48 +00001716 if (!source)
Aric Stewart36eee232004-07-04 00:07:13 +00001717 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001718 path = load_dynamic_property(package,cszTargetDir,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00001719 if (!path)
Aric Stewart36eee232004-07-04 00:07:13 +00001720 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001721 path = load_dynamic_property(package,cszRootDrive,NULL);
Aric Stewartbdb29552004-07-04 00:32:48 +00001722 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001723 MSI_SetPropertyW(package,cszTargetDir,path);
Aric Stewart36eee232004-07-04 00:07:13 +00001724 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00001725 if (folder)
Aric Stewart4e553432005-01-04 20:47:20 +00001726 {
1727 for (i = 0; i < package->loaded_folders; i++)
1728 {
1729 if (strcmpW(package->folders[i].Directory,name)==0)
1730 break;
1731 }
1732 *folder = &(package->folders[i]);
1733 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001734 return path;
Aric Stewart36eee232004-07-04 00:07:13 +00001735 }
1736 else
1737 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001738 path = load_dynamic_property(package,cszSourceDir,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00001739 if (!path)
Aric Stewart36eee232004-07-04 00:07:13 +00001740 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001741 path = load_dynamic_property(package,cszDatabase,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00001742 if (path)
Aric Stewart36eee232004-07-04 00:07:13 +00001743 {
Mike McCormackba8200b2004-12-22 15:25:30 +00001744 p = strrchrW(path,'\\');
1745 if (p)
Aric Stewart454422d2004-12-23 11:20:50 +00001746 *(p+1) = 0;
Aric Stewart36eee232004-07-04 00:07:13 +00001747 }
Aric Stewart36eee232004-07-04 00:07:13 +00001748 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00001749 if (folder)
Aric Stewart4e553432005-01-04 20:47:20 +00001750 {
1751 for (i = 0; i < package->loaded_folders; i++)
1752 {
1753 if (strcmpW(package->folders[i].Directory,name)==0)
1754 break;
1755 }
1756 *folder = &(package->folders[i]);
1757 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001758 return path;
Aric Stewart36eee232004-07-04 00:07:13 +00001759 }
1760 }
Aric Stewartbdb29552004-07-04 00:32:48 +00001761
Aric Stewart7d3e5972004-07-04 00:36:58 +00001762 for (i = 0; i < package->loaded_folders; i++)
1763 {
1764 if (strcmpW(package->folders[i].Directory,name)==0)
1765 break;
1766 }
1767
1768 if (i >= package->loaded_folders)
Mike McCormackba8200b2004-12-22 15:25:30 +00001769 return NULL;
Aric Stewart7d3e5972004-07-04 00:36:58 +00001770
1771 if (folder)
1772 *folder = &(package->folders[i]);
1773
Mike McCormackba8200b2004-12-22 15:25:30 +00001774 if (!source && package->folders[i].ResolvedTarget)
Aric Stewartbdb29552004-07-04 00:32:48 +00001775 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001776 path = dupstrW(package->folders[i].ResolvedTarget);
Aric Stewartbdb29552004-07-04 00:32:48 +00001777 TRACE(" already resolved to %s\n",debugstr_w(path));
Mike McCormackba8200b2004-12-22 15:25:30 +00001778 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00001779 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001780 else if (source && package->folders[i].ResolvedSource)
Aric Stewartbdb29552004-07-04 00:32:48 +00001781 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001782 path = dupstrW(package->folders[i].ResolvedSource);
Mike McCormackba8200b2004-12-22 15:25:30 +00001783 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00001784 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001785 else if (!source && package->folders[i].Property)
Aric Stewartbdb29552004-07-04 00:32:48 +00001786 {
Aric Stewartfa384f62004-12-22 18:46:17 +00001787 path = dupstrW(package->folders[i].Property);
Aric Stewarte2d4ea82004-07-04 00:33:45 +00001788 TRACE(" internally set to %s\n",debugstr_w(path));
1789 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001790 MSI_SetPropertyW(package,name,path);
Mike McCormackba8200b2004-12-22 15:25:30 +00001791 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00001792 }
Aric Stewarte2d4ea82004-07-04 00:33:45 +00001793
Aric Stewartbdb29552004-07-04 00:32:48 +00001794 if (package->folders[i].ParentIndex >= 0)
1795 {
Mike McCormackba8200b2004-12-22 15:25:30 +00001796 LPWSTR parent = package->folders[package->folders[i].ParentIndex].Directory;
Aric Stewartbdb29552004-07-04 00:32:48 +00001797
Mike McCormackba8200b2004-12-22 15:25:30 +00001798 TRACE(" ! Parent is %s\n", debugstr_w(parent));
Robert Shearmandce07c42004-09-17 18:11:14 +00001799
Mike McCormackba8200b2004-12-22 15:25:30 +00001800 p = resolve_folder(package, parent, source, set_prop, NULL);
Aric Stewart1ab0e412004-07-06 18:42:56 +00001801 if (!source)
Aric Stewartbdb29552004-07-04 00:32:48 +00001802 {
Mike McCormackba8200b2004-12-22 15:25:30 +00001803 TRACE(" TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault));
1804 path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00001805 package->folders[i].ResolvedTarget = dupstrW(path);
Aric Stewartbdb29552004-07-04 00:32:48 +00001806 TRACE(" resolved into %s\n",debugstr_w(path));
1807 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001808 MSI_SetPropertyW(package,name,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00001809 }
Aric Stewart1ab0e412004-07-06 18:42:56 +00001810 else
Aric Stewartbdb29552004-07-04 00:32:48 +00001811 {
Mike McCormackba8200b2004-12-22 15:25:30 +00001812 path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00001813 package->folders[i].ResolvedSource = dupstrW(path);
Aric Stewartbdb29552004-07-04 00:32:48 +00001814 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001815 HeapFree(GetProcessHeap(),0,p);
Aric Stewartbdb29552004-07-04 00:32:48 +00001816 }
Mike McCormackba8200b2004-12-22 15:25:30 +00001817 return path;
Aric Stewarte95136b2004-06-29 03:44:01 +00001818}
1819
Aric Stewartae1aa322004-12-27 19:02:59 +00001820static UINT SetFeatureStates(MSIPACKAGE *package)
1821{
1822 LPWSTR level;
1823 INT install_level;
1824 DWORD i;
1825 INT j;
1826 LPWSTR override = NULL;
1827 static const WCHAR all[]={'A','L','L',0};
1828 static const WCHAR szlevel[] = {
1829 'I','N','S','T','A','L','L','L','E','V','E','L',0};
1830 static const WCHAR szAddLocal[] = {
1831 'A','D','D','L','O','C','A','L',0};
1832
1833 /* I do not know if this is where it should happen.. but */
1834
1835 TRACE("Checking Install Level\n");
1836
1837 level = load_dynamic_property(package,szlevel,NULL);
1838 if (level)
1839 {
1840 install_level = atoiW(level);
1841 HeapFree(GetProcessHeap(), 0, level);
1842 }
1843 else
1844 install_level = 1;
1845
Aric Stewartfbdd7092004-12-27 19:06:22 +00001846 /* ok hereis the rub
1847 * ADDLOCAL and its friend OVERRIDE INSTALLLEVLE
1848 * I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is
1849 * itnored for all the features. seems strange, epsecially since it is not
1850 * documented anywhere, but it is how it works.
Aric Stewartae1aa322004-12-27 19:02:59 +00001851 */
Aric Stewartfbdd7092004-12-27 19:06:22 +00001852
1853 override = load_dynamic_property(package,szAddLocal,NULL);
1854
1855 if (override)
Aric Stewartae1aa322004-12-27 19:02:59 +00001856 {
Aric Stewartfbdd7092004-12-27 19:06:22 +00001857 for(i = 0; i < package->loaded_features; i++)
1858 {
Aric Stewartd900b532004-12-27 19:12:35 +00001859 if (strcmpiW(override,all)==0)
Aric Stewartfbdd7092004-12-27 19:06:22 +00001860 {
1861 package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
1862 package->features[i].Action = INSTALLSTATE_LOCAL;
1863 }
Aric Stewartd900b532004-12-27 19:12:35 +00001864 else
1865 {
1866 LPWSTR ptr = override;
1867 LPWSTR ptr2 = strchrW(override,',');
1868
1869 while (ptr)
1870 {
1871 if ((ptr2 &&
1872 strncmpW(ptr,package->features[i].Feature, ptr2-ptr)==0)
1873 || (!ptr2 &&
1874 strcmpW(ptr,package->features[i].Feature)==0))
1875 {
1876 package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
1877 package->features[i].Action = INSTALLSTATE_LOCAL;
1878 break;
1879 }
1880 if (ptr2)
1881 {
1882 ptr=ptr2+1;
1883 ptr2 = strchrW(ptr,',');
1884 }
1885 else
1886 break;
1887 }
1888 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001889 }
1890 HeapFree(GetProcessHeap(),0,override);
1891 }
1892 else
1893 {
1894 for(i = 0; i < package->loaded_features; i++)
1895 {
1896 BOOL feature_state= ((package->features[i].Level > 0) &&
Aric Stewartae1aa322004-12-27 19:02:59 +00001897 (package->features[i].Level <= install_level));
1898
Aric Stewartfbdd7092004-12-27 19:06:22 +00001899 if (feature_state)
1900 {
1901 package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
1902 package->features[i].Action = INSTALLSTATE_LOCAL;
1903 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001904 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001905 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001906
Aric Stewartfbdd7092004-12-27 19:06:22 +00001907 /*
1908 * now we want to enable or disable components base on feature
1909 */
1910
1911 for(i = 0; i < package->loaded_features; i++)
1912 {
1913 MSIFEATURE* feature = &package->features[i];
1914 TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n",
1915 debugstr_w(feature->Feature), feature->Installed, feature->Action,
1916 feature->ActionRequest);
1917
1918 for( j = 0; j < feature->ComponentCount; j++)
Aric Stewartae1aa322004-12-27 19:02:59 +00001919 {
Aric Stewartfbdd7092004-12-27 19:06:22 +00001920 MSICOMPONENT* component = &package->components[
1921 feature->Components[j]];
1922
1923 if (!component->Enabled)
1924 {
1925 component->Action = INSTALLSTATE_ABSENT;
1926 component->ActionRequest = INSTALLSTATE_ABSENT;
1927 }
1928 else
1929 {
1930 if (feature->Action == INSTALLSTATE_LOCAL)
1931 component->Action = INSTALLSTATE_LOCAL;
1932 if (feature->ActionRequest == INSTALLSTATE_LOCAL)
1933 component->ActionRequest = INSTALLSTATE_LOCAL;
1934 }
Aric Stewartae1aa322004-12-27 19:02:59 +00001935 }
1936 }
Aric Stewartfbdd7092004-12-27 19:06:22 +00001937
1938 for(i = 0; i < package->loaded_components; i++)
1939 {
1940 MSICOMPONENT* component= &package->components[i];
1941
1942 TRACE("Result: Component %s (Installed %i, Action %i, Request %i)\n",
1943 debugstr_w(component->Component), component->Installed,
1944 component->Action, component->ActionRequest);
1945 }
1946
1947
Aric Stewartae1aa322004-12-27 19:02:59 +00001948 return ERROR_SUCCESS;
1949}
1950
Aric Stewart401bd3f2004-06-28 20:34:35 +00001951/*
1952 * Alot is done in this function aside from just the costing.
Mike McCormack6e2bca32004-07-04 00:25:00 +00001953 * The costing needs to be implemented at some point but for now I am going
Aric Stewart401bd3f2004-06-28 20:34:35 +00001954 * to focus on the directory building
1955 *
Aric Stewart401bd3f2004-06-28 20:34:35 +00001956 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001957static UINT ACTION_CostFinalize(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001958{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001959 static const WCHAR ExecSeqQuery[] = {
1960 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
1961 'D','i','r','e','c','t','o','r','y',0};
1962 static const WCHAR ConditionQuery[] = {
1963 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
1964 'C','o','n','d','i','t','i','o','n',0};
1965 static const WCHAR szCosting[] = {
1966 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
Aric Stewart8cc14a92004-12-27 18:56:30 +00001967 static const WCHAR szlevel[] = {
1968 'I','N','S','T','A','L','L','L','E','V','E','L',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001969 static const WCHAR szOne[] = { '1', 0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00001970 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001971 MSIQUERY * view;
Mike McCormack4604e662004-08-06 17:30:20 +00001972 DWORD i;
Aric Stewart8cc14a92004-12-27 18:56:30 +00001973 LPWSTR level;
Aric Stewarte95136b2004-06-29 03:44:01 +00001974
Aric Stewart401bd3f2004-06-28 20:34:35 +00001975 TRACE("Building Directory properties\n");
1976
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001977 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00001978 if (rc == ERROR_SUCCESS)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001979 {
Aric Stewart84837d92004-07-20 01:22:37 +00001980 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001981 if (rc != ERROR_SUCCESS)
1982 {
Aric Stewart84837d92004-07-20 01:22:37 +00001983 MSI_ViewClose(view);
1984 msiobj_release(&view->hdr);
1985 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001986 }
1987
Aric Stewart84837d92004-07-20 01:22:37 +00001988 while (1)
1989 {
1990 WCHAR name[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00001991 LPWSTR path;
Aric Stewart84837d92004-07-20 01:22:37 +00001992 MSIRECORD * row = 0;
1993 DWORD sz;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001994
Aric Stewart84837d92004-07-20 01:22:37 +00001995 rc = MSI_ViewFetch(view,&row);
1996 if (rc != ERROR_SUCCESS)
1997 {
1998 rc = ERROR_SUCCESS;
1999 break;
2000 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002001
Aric Stewart84837d92004-07-20 01:22:37 +00002002 sz=0x100;
2003 MSI_RecordGetStringW(row,1,name,&sz);
2004
2005 /* This helper function now does ALL the work */
2006 TRACE("Dir %s ...\n",debugstr_w(name));
2007 load_folder(package,name);
Mike McCormackba8200b2004-12-22 15:25:30 +00002008 path = resolve_folder(package,name,FALSE,TRUE,NULL);
Aric Stewart84837d92004-07-20 01:22:37 +00002009 TRACE("resolves to %s\n",debugstr_w(path));
Mike McCormackba8200b2004-12-22 15:25:30 +00002010 HeapFree( GetProcessHeap(), 0, path);
Aric Stewart84837d92004-07-20 01:22:37 +00002011
2012 msiobj_release(&row->hdr);
2013 }
2014 MSI_ViewClose(view);
2015 msiobj_release(&view->hdr);
2016 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002017
Aric Stewartec688fb2004-07-04 00:35:52 +00002018 TRACE("File calculations %i files\n",package->loaded_files);
2019
2020 for (i = 0; i < package->loaded_files; i++)
2021 {
2022 MSICOMPONENT* comp = NULL;
2023 MSIFILE* file= NULL;
2024
2025 file = &package->files[i];
2026 if (file->ComponentIndex >= 0)
2027 comp = &package->components[file->ComponentIndex];
2028
Aric Stewartfa384f62004-12-22 18:46:17 +00002029 if (file->Temporary == TRUE)
2030 continue;
2031
Aric Stewartec688fb2004-07-04 00:35:52 +00002032 if (comp)
2033 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002034 LPWSTR p;
2035
Aric Stewartec688fb2004-07-04 00:35:52 +00002036 /* calculate target */
Mike McCormackba8200b2004-12-22 15:25:30 +00002037 p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00002038
Michael Stefaniucb9374072005-01-20 10:36:35 +00002039 HeapFree(GetProcessHeap(),0,file->TargetPath);
Aric Stewartfa384f62004-12-22 18:46:17 +00002040
2041 TRACE("file %s is named %s\n",
2042 debugstr_w(file->File),debugstr_w(file->FileName));
2043
Mike McCormackba8200b2004-12-22 15:25:30 +00002044 file->TargetPath = build_directory_name(2, p, file->FileName);
Aric Stewartec688fb2004-07-04 00:35:52 +00002045
Aric Stewartfa384f62004-12-22 18:46:17 +00002046 HeapFree(GetProcessHeap(),0,p);
2047
Aric Stewartec688fb2004-07-04 00:35:52 +00002048 TRACE("file %s resolves to %s\n",
2049 debugstr_w(file->File),debugstr_w(file->TargetPath));
Aric Stewartfa384f62004-12-22 18:46:17 +00002050
Aric Stewartec688fb2004-07-04 00:35:52 +00002051 if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
2052 {
2053 file->State = 1;
2054 comp->Cost += file->FileSize;
2055 }
2056 else
2057 {
Aric Stewart2ad3ff82004-12-27 18:50:00 +00002058 if (file->Version)
Aric Stewartec688fb2004-07-04 00:35:52 +00002059 {
2060 DWORD handle;
2061 DWORD versize;
2062 UINT sz;
2063 LPVOID version;
Aric Stewart120009e2004-10-08 23:35:35 +00002064 static const WCHAR name[] =
2065 {'\\',0};
2066 static const WCHAR name_fmt[] =
2067 {'%','u','.','%','u','.','%','u','.','%','u',0};
Aric Stewartec688fb2004-07-04 00:35:52 +00002068 WCHAR filever[0x100];
Aric Stewart120009e2004-10-08 23:35:35 +00002069 VS_FIXEDFILEINFO *lpVer;
Aric Stewartec688fb2004-07-04 00:35:52 +00002070
Aric Stewart6269f002005-01-17 13:40:39 +00002071 TRACE("Version comparison.. \n");
Aric Stewartec688fb2004-07-04 00:35:52 +00002072 versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
2073 version = HeapAlloc(GetProcessHeap(),0,versize);
2074 GetFileVersionInfoW(file->TargetPath, 0, versize, version);
Aric Stewart120009e2004-10-08 23:35:35 +00002075
2076 VerQueryValueW(version, name, (LPVOID*)&lpVer, &sz);
2077
2078 sprintfW(filever,name_fmt,
2079 HIWORD(lpVer->dwFileVersionMS),
2080 LOWORD(lpVer->dwFileVersionMS),
2081 HIWORD(lpVer->dwFileVersionLS),
2082 LOWORD(lpVer->dwFileVersionLS));
2083
2084 TRACE("new %s old %s\n", debugstr_w(file->Version),
2085 debugstr_w(filever));
2086 if (strcmpiW(filever,file->Version)<0)
Aric Stewartec688fb2004-07-04 00:35:52 +00002087 {
2088 file->State = 2;
2089 FIXME("cost should be diff in size\n");
2090 comp->Cost += file->FileSize;
2091 }
2092 else
2093 file->State = 3;
Aric Stewart120009e2004-10-08 23:35:35 +00002094 HeapFree(GetProcessHeap(),0,version);
Aric Stewartec688fb2004-07-04 00:35:52 +00002095 }
2096 else
2097 file->State = 3;
2098 }
2099 }
2100 }
2101
Aric Stewart7d3e5972004-07-04 00:36:58 +00002102 TRACE("Evaluating Condition Table\n");
Aric Stewart2e9b5f72004-07-04 00:31:17 +00002103
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002104 rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00002105 if (rc == ERROR_SUCCESS)
2106 {
Mike McCormackac6a4132005-01-04 20:36:12 +00002107 rc = MSI_ViewExecute(view, 0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002108 if (rc != ERROR_SUCCESS)
2109 {
Mike McCormackac6a4132005-01-04 20:36:12 +00002110 MSI_ViewClose(view);
2111 msiobj_release(&view->hdr);
2112 return rc;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002113 }
Mike McCormackac6a4132005-01-04 20:36:12 +00002114
2115 while (1)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002116 {
Mike McCormackac6a4132005-01-04 20:36:12 +00002117 WCHAR Feature[0x100];
2118 MSIRECORD * row = 0;
2119 DWORD sz;
2120 int feature_index;
2121
2122 rc = MSI_ViewFetch(view,&row);
2123
2124 if (rc != ERROR_SUCCESS)
2125 {
2126 rc = ERROR_SUCCESS;
2127 break;
2128 }
2129
2130 sz = 0x100;
2131 MSI_RecordGetStringW(row,1,Feature,&sz);
2132
2133 feature_index = get_loaded_feature(package,Feature);
2134 if (feature_index < 0)
2135 ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));
2136 else
2137 {
2138 LPWSTR Condition;
2139 Condition = load_dynamic_stringW(row,3);
Aric Stewart7231a432004-07-09 19:26:30 +00002140
Aric Stewart84837d92004-07-20 01:22:37 +00002141 if (MSI_EvaluateConditionW(package,Condition) ==
2142 MSICONDITION_TRUE)
Mike McCormackac6a4132005-01-04 20:36:12 +00002143 {
2144 int level = MSI_RecordGetInteger(row,2);
Aric Stewart84837d92004-07-20 01:22:37 +00002145 TRACE("Reseting feature %s to level %i\n",
2146 debugstr_w(Feature), level);
Mike McCormackac6a4132005-01-04 20:36:12 +00002147 package->features[feature_index].Level = level;
2148 }
2149 HeapFree(GetProcessHeap(),0,Condition);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002150 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002151
Mike McCormackac6a4132005-01-04 20:36:12 +00002152 msiobj_release(&row->hdr);
2153 }
2154 MSI_ViewClose(view);
2155 msiobj_release(&view->hdr);
Aric Stewart84837d92004-07-20 01:22:37 +00002156 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002157
2158 TRACE("Enabling or Disabling Components\n");
2159 for (i = 0; i < package->loaded_components; i++)
2160 {
2161 if (package->components[i].Condition[0])
2162 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002163 if (MSI_EvaluateConditionW(package,
Aric Stewart7d3e5972004-07-04 00:36:58 +00002164 package->components[i].Condition) == MSICONDITION_FALSE)
2165 {
2166 TRACE("Disabling component %s\n",
2167 debugstr_w(package->components[i].Component));
2168 package->components[i].Enabled = FALSE;
2169 }
2170 }
2171 }
2172
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002173 MSI_SetPropertyW(package,szCosting,szOne);
Aric Stewart8cc14a92004-12-27 18:56:30 +00002174 /* set default run level if not set */
2175 level = load_dynamic_property(package,szlevel,NULL);
2176 if (!level)
2177 MSI_SetPropertyW(package,szlevel, szOne);
2178 else
2179 HeapFree(GetProcessHeap(),0,level);
Aric Stewartae1aa322004-12-27 19:02:59 +00002180
2181 return SetFeatureStates(package);
2182
Aric Stewart401bd3f2004-06-28 20:34:35 +00002183}
2184
2185/*
2186 * This is a helper function for handling embedded cabinet media
2187 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002188static UINT writeout_cabinet_stream(MSIPACKAGE *package, WCHAR* stream_name,
Aric Stewart401bd3f2004-06-28 20:34:35 +00002189 WCHAR* source)
2190{
2191 UINT rc;
2192 USHORT* data;
2193 UINT size;
2194 DWORD write;
2195 HANDLE the_file;
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002196 WCHAR tmp[MAX_PATH];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002197
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002198 rc = read_raw_stream_data(package->db,stream_name,&data,&size);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002199 if (rc != ERROR_SUCCESS)
2200 return rc;
2201
Aric Stewartbdb29552004-07-04 00:32:48 +00002202 write = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002203 if (MSI_GetPropertyW(package, cszTempFolder, tmp, &write))
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002204 GetTempPathW(MAX_PATH,tmp);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002205
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002206 GetTempFileNameW(tmp,stream_name,0,source);
2207
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002208 track_tempfile(package,strrchrW(source,'\\'), source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002209 the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2210 FILE_ATTRIBUTE_NORMAL, NULL);
2211
2212 if (the_file == INVALID_HANDLE_VALUE)
2213 {
2214 rc = ERROR_FUNCTION_FAILED;
2215 goto end;
2216 }
2217
2218 WriteFile(the_file,data,size,&write,NULL);
2219 CloseHandle(the_file);
2220 TRACE("wrote %li bytes to %s\n",write,debugstr_w(source));
2221end:
2222 HeapFree(GetProcessHeap(),0,data);
2223 return rc;
2224}
2225
Aric Stewart401bd3f2004-06-28 20:34:35 +00002226
Robert Shearman3d7299b2004-09-10 22:29:49 +00002227/* Support functions for FDI functions */
Aric Stewartfbdd7092004-12-27 19:06:22 +00002228typedef struct
2229{
2230 MSIPACKAGE* package;
2231 LPCSTR cab_path;
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002232 LPCSTR file_name;
Aric Stewartfbdd7092004-12-27 19:06:22 +00002233} CabData;
Robert Shearman3d7299b2004-09-10 22:29:49 +00002234
2235static void * cabinet_alloc(ULONG cb)
2236{
2237 return HeapAlloc(GetProcessHeap(), 0, cb);
2238}
2239
2240static void cabinet_free(void *pv)
2241{
2242 HeapFree(GetProcessHeap(), 0, pv);
2243}
2244
2245static INT_PTR cabinet_open(char *pszFile, int oflag, int pmode)
2246{
2247 DWORD dwAccess = 0;
2248 DWORD dwShareMode = 0;
2249 DWORD dwCreateDisposition = OPEN_EXISTING;
2250 switch (oflag & _O_ACCMODE)
2251 {
2252 case _O_RDONLY:
2253 dwAccess = GENERIC_READ;
2254 dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
2255 break;
2256 case _O_WRONLY:
2257 dwAccess = GENERIC_WRITE;
2258 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
2259 break;
2260 case _O_RDWR:
2261 dwAccess = GENERIC_READ | GENERIC_WRITE;
2262 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
2263 break;
2264 }
2265 if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
2266 dwCreateDisposition = CREATE_NEW;
2267 else if (oflag & _O_CREAT)
2268 dwCreateDisposition = CREATE_ALWAYS;
2269 return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, dwCreateDisposition, 0, NULL);
2270}
2271
2272static UINT cabinet_read(INT_PTR hf, void *pv, UINT cb)
2273{
2274 DWORD dwRead;
2275 if (ReadFile((HANDLE)hf, pv, cb, &dwRead, NULL))
2276 return dwRead;
2277 return 0;
2278}
2279
2280static UINT cabinet_write(INT_PTR hf, void *pv, UINT cb)
2281{
2282 DWORD dwWritten;
2283 if (WriteFile((HANDLE)hf, pv, cb, &dwWritten, NULL))
2284 return dwWritten;
2285 return 0;
2286}
2287
2288static int cabinet_close(INT_PTR hf)
2289{
2290 return CloseHandle((HANDLE)hf) ? 0 : -1;
2291}
2292
2293static long cabinet_seek(INT_PTR hf, long dist, int seektype)
2294{
2295 /* flags are compatible and so are passed straight through */
2296 return SetFilePointer((HANDLE)hf, dist, NULL, seektype);
2297}
2298
2299static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
2300{
2301 /* FIXME: try to do more processing in this function */
2302 switch (fdint)
2303 {
2304 case fdintCOPY_FILE:
2305 {
Aric Stewartfbdd7092004-12-27 19:06:22 +00002306 CabData *data = (CabData*) pfdin->pv;
2307 ULONG len = strlen(data->cab_path) + strlen(pfdin->psz1);
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002308 char *file;
Robert Shearman3d7299b2004-09-10 22:29:49 +00002309
Aric Stewartfbdd7092004-12-27 19:06:22 +00002310 LPWSTR trackname;
2311 LPWSTR trackpath;
2312 LPWSTR tracknametmp;
2313 static const WCHAR tmpprefix[] = {'C','A','B','T','M','P','_',0};
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002314
2315 if (data->file_name && strcmp(data->file_name,pfdin->psz1))
2316 return 0;
Aric Stewartfbdd7092004-12-27 19:06:22 +00002317
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002318 file = cabinet_alloc((len+1)*sizeof(char));
Aric Stewartfbdd7092004-12-27 19:06:22 +00002319 strcpy(file, data->cab_path);
Robert Shearman3d7299b2004-09-10 22:29:49 +00002320 strcat(file, pfdin->psz1);
2321
2322 TRACE("file: %s\n", debugstr_a(file));
2323
Aric Stewartfbdd7092004-12-27 19:06:22 +00002324 /* track this file so it can be deleted if not installed */
2325 trackpath=strdupAtoW(file);
2326 tracknametmp=strdupAtoW(strrchr(file,'\\')+1);
2327 trackname = HeapAlloc(GetProcessHeap(),0,(strlenW(tracknametmp) +
2328 strlenW(tmpprefix)+1) * sizeof(WCHAR));
2329
2330 strcpyW(trackname,tmpprefix);
2331 strcatW(trackname,tracknametmp);
2332
2333 track_tempfile(data->package, trackname, trackpath);
2334
2335 HeapFree(GetProcessHeap(),0,trackpath);
2336 HeapFree(GetProcessHeap(),0,trackname);
2337 HeapFree(GetProcessHeap(),0,tracknametmp);
2338
Robert Shearman3d7299b2004-09-10 22:29:49 +00002339 return cabinet_open(file, _O_WRONLY | _O_CREAT, 0);
2340 }
2341 case fdintCLOSE_FILE_INFO:
2342 {
2343 FILETIME ft;
2344 FILETIME ftLocal;
2345 if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
2346 return -1;
2347 if (!LocalFileTimeToFileTime(&ft, &ftLocal))
2348 return -1;
2349 if (!SetFileTime((HANDLE)pfdin->hf, &ftLocal, 0, &ftLocal))
2350 return -1;
2351
2352 cabinet_close(pfdin->hf);
2353 return 1;
2354 }
2355 default:
2356 return 0;
2357 }
2358}
2359
Aric Stewart401bd3f2004-06-28 20:34:35 +00002360/***********************************************************************
2361 * extract_cabinet_file
2362 *
Robert Shearman3d7299b2004-09-10 22:29:49 +00002363 * Extract files from a cab file.
Aric Stewart401bd3f2004-06-28 20:34:35 +00002364 */
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002365static BOOL extract_a_cabinet_file(MSIPACKAGE* package, const WCHAR* source,
2366 const WCHAR* path, const WCHAR* file)
Aric Stewart36eee232004-07-04 00:07:13 +00002367{
Robert Shearman3d7299b2004-09-10 22:29:49 +00002368 HFDI hfdi;
2369 ERF erf;
2370 BOOL ret;
2371 char *cabinet;
2372 char *cab_path;
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002373 char *file_name;
Aric Stewartfbdd7092004-12-27 19:06:22 +00002374 CabData data;
Robert Shearman3d7299b2004-09-10 22:29:49 +00002375
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002376 TRACE("Extracting %s (%s) to %s\n",debugstr_w(source),
2377 debugstr_w(file), debugstr_w(path));
Robert Shearman3d7299b2004-09-10 22:29:49 +00002378
2379 hfdi = FDICreate(cabinet_alloc,
2380 cabinet_free,
2381 cabinet_open,
2382 cabinet_read,
2383 cabinet_write,
2384 cabinet_close,
2385 cabinet_seek,
2386 0,
2387 &erf);
2388 if (!hfdi)
2389 {
2390 ERR("FDICreate failed\n");
2391 return FALSE;
2392 }
2393
2394 if (!(cabinet = strdupWtoA( source )))
2395 {
2396 FDIDestroy(hfdi);
2397 return FALSE;
2398 }
2399 if (!(cab_path = strdupWtoA( path )))
2400 {
2401 FDIDestroy(hfdi);
2402 HeapFree(GetProcessHeap(), 0, cabinet);
2403 return FALSE;
2404 }
2405
Aric Stewartfbdd7092004-12-27 19:06:22 +00002406 data.package = package;
2407 data.cab_path = cab_path;
Aric Stewart54c67dd2005-01-25 20:17:09 +00002408 if (file)
2409 file_name = strdupWtoA(file);
2410 else
2411 file_name = NULL;
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002412 data.file_name = file_name;
Aric Stewartfbdd7092004-12-27 19:06:22 +00002413
2414 ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data);
Robert Shearman3d7299b2004-09-10 22:29:49 +00002415
2416 if (!ret)
2417 ERR("FDICopy failed\n");
2418
2419 FDIDestroy(hfdi);
2420
2421 HeapFree(GetProcessHeap(), 0, cabinet);
2422 HeapFree(GetProcessHeap(), 0, cab_path);
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002423 HeapFree(GetProcessHeap(), 0, file_name);
Robert Shearman3d7299b2004-09-10 22:29:49 +00002424
2425 return ret;
Aric Stewart36eee232004-07-04 00:07:13 +00002426}
2427
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002428static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence,
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002429 WCHAR* path, WCHAR* file)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002430{
2431 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002432 MSIQUERY * view;
2433 MSIRECORD * row = 0;
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002434 static WCHAR source[MAX_PATH];
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002435 static const WCHAR ExecSeqQuery[] = {
2436 's','e','l','e','c','t',' ','*',' ',
2437 'f','r','o','m',' ','M','e','d','i','a',' ',
2438 'w','h','e','r','e',' ','L','a','s','t','S','e','q','u','e','n','c','e',' ','>','=',' ','%','i',' ',
2439 'o','r','d','e','r',' ','b','y',' ','L','a','s','t','S','e','q','u','e','n','c','e',0};
2440 WCHAR Query[1024];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002441 WCHAR cab[0x100];
2442 DWORD sz=0x100;
2443 INT seq;
Mike McCormack4604e662004-08-06 17:30:20 +00002444 static UINT last_sequence = 0;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002445
2446 if (sequence <= last_sequence)
2447 {
Mike McCormack4604e662004-08-06 17:30:20 +00002448 TRACE("Media already ready (%u, %u)\n",sequence,last_sequence);
Aric Stewart54c67dd2005-01-25 20:17:09 +00002449 /*extract_a_cabinet_file(package, source,path,file); */
Aric Stewart401bd3f2004-06-28 20:34:35 +00002450 return ERROR_SUCCESS;
2451 }
2452
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002453 sprintfW(Query,ExecSeqQuery,sequence);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002454
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002455 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002456 if (rc != ERROR_SUCCESS)
2457 return rc;
2458
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002459 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002460 if (rc != ERROR_SUCCESS)
2461 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002462 MSI_ViewClose(view);
2463 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002464 return rc;
2465 }
2466
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002467 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002468 if (rc != ERROR_SUCCESS)
2469 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002470 MSI_ViewClose(view);
2471 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002472 return rc;
2473 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002474 seq = MSI_RecordGetInteger(row,2);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002475 last_sequence = seq;
2476
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002477 if (!MSI_RecordIsNull(row,4))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002478 {
2479 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002480 MSI_RecordGetStringW(row,4,cab,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00002481 TRACE("Source is CAB %s\n",debugstr_w(cab));
Aric Stewart401bd3f2004-06-28 20:34:35 +00002482 /* the stream does not contain the # character */
2483 if (cab[0]=='#')
2484 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002485 writeout_cabinet_stream(package,&cab[1],source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002486 strcpyW(path,source);
2487 *(strrchrW(path,'\\')+1)=0;
2488 }
2489 else
2490 {
Aric Stewart7231a432004-07-09 19:26:30 +00002491 sz = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002492 if (MSI_GetPropertyW(package, cszSourceDir, source, &sz))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002493 {
2494 ERR("No Source dir defined \n");
2495 rc = ERROR_FUNCTION_FAILED;
2496 }
2497 else
2498 {
2499 strcpyW(path,source);
2500 strcatW(source,cab);
Aric Stewartbdb29552004-07-04 00:32:48 +00002501 /* extract the cab file into a folder in the temp folder */
2502 sz = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002503 if (MSI_GetPropertyW(package, cszTempFolder,path, &sz)
Aric Stewartbdb29552004-07-04 00:32:48 +00002504 != ERROR_SUCCESS)
2505 GetTempPathW(MAX_PATH,path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002506 }
2507 }
Aric Stewart54c67dd2005-01-25 20:17:09 +00002508 rc = !extract_a_cabinet_file(package, source,path,NULL);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002509 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002510 msiobj_release(&row->hdr);
2511 MSI_ViewClose(view);
2512 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002513 return rc;
2514}
2515
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002516inline static UINT create_component_directory ( MSIPACKAGE* package, INT component)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002517{
Marcus Meissnerb7f67812005-01-14 16:50:39 +00002518 UINT rc = ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00002519 MSIFOLDER *folder;
Mike McCormackba8200b2004-12-22 15:25:30 +00002520 LPWSTR install_path;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002521
Mike McCormackba8200b2004-12-22 15:25:30 +00002522 install_path = resolve_folder(package, package->components[component].Directory,
2523 FALSE, FALSE, &folder);
2524 if (!install_path)
2525 return ERROR_FUNCTION_FAILED;
Aric Stewartbdb29552004-07-04 00:32:48 +00002526
2527 /* create the path */
2528 if (folder->State == 0)
2529 {
2530 create_full_pathW(install_path);
2531 folder->State = 2;
2532 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002533 HeapFree(GetProcessHeap(), 0, install_path);
Aric Stewartbdb29552004-07-04 00:32:48 +00002534
Aric Stewart401bd3f2004-06-28 20:34:35 +00002535 return rc;
2536}
2537
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002538static UINT ACTION_InstallFiles(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002539{
Aric Stewartec688fb2004-07-04 00:35:52 +00002540 UINT rc = ERROR_SUCCESS;
Mike McCormack4604e662004-08-06 17:30:20 +00002541 DWORD index;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002542 MSIRECORD * uirow;
Aric Stewartd2c395a2004-07-06 18:48:15 +00002543 WCHAR uipath[MAX_PATH];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002544
Aric Stewartec688fb2004-07-04 00:35:52 +00002545 if (!package)
2546 return ERROR_INVALID_HANDLE;
2547
Aric Stewartd2c395a2004-07-06 18:48:15 +00002548 /* increment progress bar each time action data is sent */
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002549 ui_progress(package,1,1,0,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002550
Aric Stewartec688fb2004-07-04 00:35:52 +00002551 for (index = 0; index < package->loaded_files; index++)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002552 {
Aric Stewart401bd3f2004-06-28 20:34:35 +00002553 WCHAR path_to_source[MAX_PATH];
Aric Stewartec688fb2004-07-04 00:35:52 +00002554 MSIFILE *file;
2555
2556 file = &package->files[index];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002557
Aric Stewart7d3e5972004-07-04 00:36:58 +00002558 if (file->Temporary)
2559 continue;
2560
Aric Stewartfbdd7092004-12-27 19:06:22 +00002561 if (package->components[file->ComponentIndex].ActionRequest !=
2562 INSTALLSTATE_LOCAL)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002563 {
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002564 ui_progress(package,2,file->FileSize,0,0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002565 TRACE("File %s is not scheduled for install\n",
2566 debugstr_w(file->File));
Aric Stewartfbdd7092004-12-27 19:06:22 +00002567
Aric Stewart7d3e5972004-07-04 00:36:58 +00002568 continue;
2569 }
2570
Aric Stewartec688fb2004-07-04 00:35:52 +00002571 if ((file->State == 1) || (file->State == 2))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002572 {
Aric Stewart1416b102005-01-06 19:34:16 +00002573 LPWSTR p;
2574 INT len;
2575 MSICOMPONENT* comp = NULL;
2576
Aric Stewartec688fb2004-07-04 00:35:52 +00002577 TRACE("Installing %s\n",debugstr_w(file->File));
Aric Stewartdef5cbf2005-01-04 20:42:58 +00002578 rc = ready_media_for_file(package,file->Sequence,path_to_source,
2579 file->File);
Aric Stewartec688fb2004-07-04 00:35:52 +00002580 /*
2581 * WARNING!
2582 * our file table could change here because a new temp file
2583 * may have been created
2584 */
2585 file = &package->files[index];
2586 if (rc != ERROR_SUCCESS)
2587 {
2588 ERR("Unable to ready media\n");
2589 rc = ERROR_FUNCTION_FAILED;
2590 break;
2591 }
2592
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002593 create_component_directory( package, file->ComponentIndex);
Aric Stewartec688fb2004-07-04 00:35:52 +00002594
Aric Stewart1416b102005-01-06 19:34:16 +00002595 /* recalculate file paths because things may have changed */
2596
2597 if (file->ComponentIndex >= 0)
2598 comp = &package->components[file->ComponentIndex];
2599
2600 p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
Michael Stefaniucb9374072005-01-20 10:36:35 +00002601 HeapFree(GetProcessHeap(),0,file->TargetPath);
Aric Stewart1416b102005-01-06 19:34:16 +00002602
2603 file->TargetPath = build_directory_name(2, p, file->FileName);
2604
2605 len = strlenW(path_to_source) + strlenW(file->File) + 2;
2606 file->SourcePath = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
Aric Stewartec688fb2004-07-04 00:35:52 +00002607 strcpyW(file->SourcePath, path_to_source);
2608 strcatW(file->SourcePath, file->File);
2609
2610 TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
2611 debugstr_w(file->TargetPath));
2612
Aric Stewartd2c395a2004-07-06 18:48:15 +00002613 /* the UI chunk */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002614 uirow=MSI_CreateRecord(9);
2615 MSI_RecordSetStringW(uirow,1,file->File);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002616 strcpyW(uipath,file->TargetPath);
2617 *(strrchrW(uipath,'\\')+1)=0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002618 MSI_RecordSetStringW(uirow,9,uipath);
2619 MSI_RecordSetInteger(uirow,6,file->FileSize);
2620 ui_actiondata(package,szInstallFiles,uirow);
2621 msiobj_release( &uirow->hdr );
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002622 ui_progress(package,2,file->FileSize,0,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002623
Robert Shearman3d7299b2004-09-10 22:29:49 +00002624 if (!MoveFileW(file->SourcePath,file->TargetPath))
Aric Stewartb942e182004-07-06 18:50:02 +00002625 {
Robert Shearman3d7299b2004-09-10 22:29:49 +00002626 rc = GetLastError();
Aric Stewart120009e2004-10-08 23:35:35 +00002627 ERR("Unable to move file (%s -> %s) (error %d)\n",
2628 debugstr_w(file->SourcePath), debugstr_w(file->TargetPath),
2629 rc);
2630 if (rc == ERROR_ALREADY_EXISTS && file->State == 2)
2631 {
2632 CopyFileW(file->SourcePath,file->TargetPath,FALSE);
2633 DeleteFileW(file->SourcePath);
2634 rc = 0;
2635 }
Aric Stewart3c949ef2004-12-27 17:09:40 +00002636 else if (rc == ERROR_FILE_NOT_FOUND)
2637 {
2638 ERR("Source File Not Found! Continueing\n");
2639 rc = 0;
2640 }
Aric Stewart120009e2004-10-08 23:35:35 +00002641 else
Aric Stewart2ad3ff82004-12-27 18:50:00 +00002642 {
2643 ERR("Ignoring Error and continuing...\n");
2644 rc = 0;
2645 }
Aric Stewartb942e182004-07-06 18:50:02 +00002646 }
Aric Stewartec688fb2004-07-04 00:35:52 +00002647 else
2648 file->State = 4;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002649 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002650 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002651
2652 return rc;
2653}
2654
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002655inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key,
Aric Stewartfa384f62004-12-22 18:46:17 +00002656 LPWSTR* file_source)
Aric Stewartec688fb2004-07-04 00:35:52 +00002657{
Mike McCormack4604e662004-08-06 17:30:20 +00002658 DWORD index;
Aric Stewartec688fb2004-07-04 00:35:52 +00002659
Aric Stewartec688fb2004-07-04 00:35:52 +00002660 if (!package)
2661 return ERROR_INVALID_HANDLE;
2662
2663 for (index = 0; index < package->loaded_files; index ++)
2664 {
2665 if (strcmpW(file_key,package->files[index].File)==0)
2666 {
Aric Stewart2cae30b2005-01-19 19:07:40 +00002667 if (package->files[index].State >= 2)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002668 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002669 *file_source = dupstrW(package->files[index].TargetPath);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002670 return ERROR_SUCCESS;
2671 }
2672 else
2673 return ERROR_FILE_NOT_FOUND;
Aric Stewartec688fb2004-07-04 00:35:52 +00002674 }
2675 }
2676
2677 return ERROR_FUNCTION_FAILED;
2678}
2679
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002680static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002681{
2682 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002683 MSIQUERY * view;
2684 MSIRECORD * row = 0;
2685 static const WCHAR ExecSeqQuery[] = {
2686 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
2687 'D','u','p','l','i','c','a','t','e','F','i','l','e',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00002688
Aric Stewart7d3e5972004-07-04 00:36:58 +00002689 if (!package)
2690 return ERROR_INVALID_HANDLE;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002691
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002692 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002693 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002694 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002695
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002696 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002697 if (rc != ERROR_SUCCESS)
2698 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002699 MSI_ViewClose(view);
2700 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002701 return rc;
2702 }
2703
2704 while (1)
2705 {
2706 WCHAR file_key[0x100];
Aric Stewartfa384f62004-12-22 18:46:17 +00002707 WCHAR *file_source = NULL;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002708 WCHAR dest_name[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00002709 LPWSTR dest_path, dest;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002710 WCHAR component[0x100];
2711 INT component_index;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002712
2713 DWORD sz=0x100;
2714
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002715 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002716 if (rc != ERROR_SUCCESS)
2717 {
2718 rc = ERROR_SUCCESS;
2719 break;
2720 }
2721
2722 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002723 rc = MSI_RecordGetStringW(row,2,component,&sz);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002724 if (rc != ERROR_SUCCESS)
2725 {
2726 ERR("Unable to get component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002727 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002728 break;
2729 }
2730
2731 component_index = get_loaded_component(package,component);
Aric Stewartfbdd7092004-12-27 19:06:22 +00002732 if (package->components[component_index].ActionRequest !=
2733 INSTALLSTATE_LOCAL)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002734 {
2735 TRACE("Skipping copy due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002736 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002737 continue;
2738 }
2739
2740 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002741 rc = MSI_RecordGetStringW(row,3,file_key,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002742 if (rc != ERROR_SUCCESS)
2743 {
2744 ERR("Unable to get file key\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002745 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002746 break;
2747 }
2748
Aric Stewartfa384f62004-12-22 18:46:17 +00002749 rc = get_file_target(package,file_key,&file_source);
Aric Stewartec688fb2004-07-04 00:35:52 +00002750
Aric Stewart401bd3f2004-06-28 20:34:35 +00002751 if (rc != ERROR_SUCCESS)
2752 {
2753 ERR("Original file unknown %s\n",debugstr_w(file_key));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002754 msiobj_release(&row->hdr);
Michael Stefaniucb9374072005-01-20 10:36:35 +00002755 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart2cae30b2005-01-19 19:07:40 +00002756 continue;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002757 }
2758
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002759 if (MSI_RecordIsNull(row,4))
Aric Stewartec688fb2004-07-04 00:35:52 +00002760 {
Aric Stewart401bd3f2004-06-28 20:34:35 +00002761 strcpyW(dest_name,strrchrW(file_source,'\\')+1);
Aric Stewartec688fb2004-07-04 00:35:52 +00002762 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002763 else
2764 {
2765 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002766 MSI_RecordGetStringW(row,4,dest_name,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002767 reduce_to_longfilename(dest_name);
2768 }
2769
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002770 if (MSI_RecordIsNull(row,5))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002771 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002772 LPWSTR p;
Aric Stewartfa384f62004-12-22 18:46:17 +00002773 dest_path = dupstrW(file_source);
Mike McCormackba8200b2004-12-22 15:25:30 +00002774 p = strrchrW(dest_path,'\\');
2775 if (p)
2776 *p=0;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002777 }
2778 else
2779 {
2780 WCHAR destkey[0x100];
2781 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002782 MSI_RecordGetStringW(row,5,destkey,&sz);
Aric Stewarte95136b2004-06-29 03:44:01 +00002783 sz = 0x100;
Mike McCormackba8200b2004-12-22 15:25:30 +00002784 dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL);
2785 if (!dest_path)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002786 {
2787 ERR("Unable to get destination folder\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002788 msiobj_release(&row->hdr);
Michael Stefaniucb9374072005-01-20 10:36:35 +00002789 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002790 break;
2791 }
2792 }
2793
Mike McCormackba8200b2004-12-22 15:25:30 +00002794 dest = build_directory_name(2, dest_path, dest_name);
2795 HeapFree(GetProcessHeap(), 0, dest_path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002796
2797 TRACE("Duplicating file %s to %s\n",debugstr_w(file_source),
Aric Stewartfa384f62004-12-22 18:46:17 +00002798 debugstr_w(dest));
Aric Stewart401bd3f2004-06-28 20:34:35 +00002799
Aric Stewartfa384f62004-12-22 18:46:17 +00002800 if (strcmpW(file_source,dest))
2801 rc = !CopyFileW(file_source,dest,TRUE);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002802 else
2803 rc = ERROR_SUCCESS;
2804
2805 if (rc != ERROR_SUCCESS)
2806 ERR("Failed to copy file\n");
Aric Stewartec688fb2004-07-04 00:35:52 +00002807
2808 FIXME("We should track these duplicate files as well\n");
2809
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002810 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00002811 HeapFree(GetProcessHeap(),0,dest);
2812 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002813 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002814 MSI_ViewClose(view);
2815 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002816 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002817}
2818
2819
Mike McCormack6e2bca32004-07-04 00:25:00 +00002820/* OK this value is "interpretted" and then formatted based on the
Aric Stewart6e160f12004-06-29 04:07:22 +00002821 first few characters */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002822static LPSTR parse_value(MSIPACKAGE *package, WCHAR *value, DWORD *type,
Aric Stewart401bd3f2004-06-28 20:34:35 +00002823 DWORD *size)
2824{
2825 LPSTR data = NULL;
Aric Stewart6e160f12004-06-29 04:07:22 +00002826 if (value[0]=='#' && value[1]!='#' && value[1]!='%')
Aric Stewart401bd3f2004-06-28 20:34:35 +00002827 {
Aric Stewart6e160f12004-06-29 04:07:22 +00002828 if (value[1]=='x')
2829 {
2830 LPWSTR ptr;
2831 CHAR byte[5];
2832 LPWSTR deformated;
2833 int count;
2834
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002835 deformat_string(package, &value[2], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002836
2837 /* binary value type */
2838 ptr = deformated;
2839 *type=REG_BINARY;
2840 *size = strlenW(ptr)/2;
2841 data = HeapAlloc(GetProcessHeap(),0,*size);
2842
2843 byte[0] = '0';
2844 byte[1] = 'x';
2845 byte[4] = 0;
2846 count = 0;
2847 while (*ptr)
2848 {
2849 byte[2]= *ptr;
2850 ptr++;
2851 byte[3]= *ptr;
2852 ptr++;
2853 data[count] = (BYTE)strtol(byte,NULL,0);
2854 count ++;
2855 }
2856 HeapFree(GetProcessHeap(),0,deformated);
2857
2858 TRACE("Data %li bytes(%i)\n",*size,count);
2859 }
2860 else
2861 {
2862 LPWSTR deformated;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002863 deformat_string(package, &value[1], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00002864
2865 *type=REG_DWORD;
2866 *size = sizeof(DWORD);
2867 data = HeapAlloc(GetProcessHeap(),0,*size);
2868 *(LPDWORD)data = atoiW(deformated);
2869 TRACE("DWORD %i\n",*data);
2870
2871 HeapFree(GetProcessHeap(),0,deformated);
2872 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002873 }
2874 else
2875 {
Aric Stewart54c67dd2005-01-25 20:17:09 +00002876 static const WCHAR szMulti[] = {'[','~',']',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00002877 WCHAR *ptr;
Aric Stewart6e160f12004-06-29 04:07:22 +00002878 *type=REG_SZ;
2879
Aric Stewart401bd3f2004-06-28 20:34:35 +00002880 if (value[0]=='#')
Aric Stewart6e160f12004-06-29 04:07:22 +00002881 {
2882 if (value[1]=='%')
2883 {
2884 ptr = &value[2];
2885 *type=REG_EXPAND_SZ;
2886 }
2887 else
2888 ptr = &value[1];
2889 }
2890 else
Aric Stewart401bd3f2004-06-28 20:34:35 +00002891 ptr=value;
2892
Aric Stewart54c67dd2005-01-25 20:17:09 +00002893 if (strstrW(value,szMulti))
2894 *type = REG_MULTI_SZ;
2895
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002896 *size = deformat_string(package, ptr,(LPWSTR*)&data);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002897 }
2898 return data;
2899}
2900
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002901static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002902{
2903 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002904 MSIQUERY * view;
2905 MSIRECORD * row = 0;
2906 static const WCHAR ExecSeqQuery[] = {
2907 's','e','l','e','c','t',' ','*',' ',
2908 'f','r','o','m',' ','R','e','g','i','s','t','r','y',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00002909
Aric Stewart7d3e5972004-07-04 00:36:58 +00002910 if (!package)
2911 return ERROR_INVALID_HANDLE;
2912
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002913 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002914 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002915 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002916
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002917 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002918 if (rc != ERROR_SUCCESS)
2919 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002920 MSI_ViewClose(view);
2921 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002922 return rc;
2923 }
2924
Aric Stewartd2c395a2004-07-06 18:48:15 +00002925 /* increment progress bar each time action data is sent */
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002926 ui_progress(package,1,REG_PROGRESS_VALUE,1,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002927
Aric Stewart401bd3f2004-06-28 20:34:35 +00002928 while (1)
2929 {
Aric Stewartd2c395a2004-07-06 18:48:15 +00002930 static const WCHAR szHCR[] =
2931{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T','\\',0};
2932 static const WCHAR szHCU[] =
2933{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',0};
2934 static const WCHAR szHLM[] =
2935{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',
2936'\\',0};
2937 static const WCHAR szHU[] =
2938{'H','K','E','Y','_','U','S','E','R','S','\\',0};
2939
Aric Stewart401bd3f2004-06-28 20:34:35 +00002940 LPSTR value_data = NULL;
2941 HKEY root_key, hkey;
2942 DWORD type,size;
Aric Stewart1416b102005-01-06 19:34:16 +00002943 LPWSTR value, key, name, component, deformated;
Mike McCormack9db0e072004-12-22 15:05:07 +00002944 LPCWSTR szRoot;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002945 INT component_index;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002946 MSIRECORD * uirow;
Mike McCormack9db0e072004-12-22 15:05:07 +00002947 LPWSTR uikey;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002948 INT root;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002949
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002950 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002951 if (rc != ERROR_SUCCESS)
2952 {
2953 rc = ERROR_SUCCESS;
2954 break;
2955 }
Aric Stewartbd1bbc12005-01-03 20:00:13 +00002956 ui_progress(package,2,0,0,0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002957
Mike McCormack9db0e072004-12-22 15:05:07 +00002958 value = NULL;
2959 key = NULL;
2960 uikey = NULL;
2961 name = NULL;
2962
2963 component = load_dynamic_stringW(row, 6);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002964 component_index = get_loaded_component(package,component);
2965
Aric Stewartfbdd7092004-12-27 19:06:22 +00002966 if (package->components[component_index].ActionRequest !=
2967 INSTALLSTATE_LOCAL)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002968 {
2969 TRACE("Skipping write due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002970 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00002971 goto next;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002972 }
2973
Aric Stewart401bd3f2004-06-28 20:34:35 +00002974 /* null values have special meanings during uninstalls and such */
2975
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002976 if(MSI_RecordIsNull(row,5))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002977 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002978 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00002979 goto next;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002980 }
2981
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002982 root = MSI_RecordGetInteger(row,2);
Mike McCormack9db0e072004-12-22 15:05:07 +00002983 key = load_dynamic_stringW(row, 3);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002984
Mike McCormack9db0e072004-12-22 15:05:07 +00002985 name = load_dynamic_stringW(row, 4);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002986
Aric Stewart401bd3f2004-06-28 20:34:35 +00002987 /* get the root key */
2988 switch (root)
2989 {
Aric Stewartd2c395a2004-07-06 18:48:15 +00002990 case 0: root_key = HKEY_CLASSES_ROOT;
Mike McCormack9db0e072004-12-22 15:05:07 +00002991 szRoot = szHCR;
2992 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00002993 case 1: root_key = HKEY_CURRENT_USER;
Mike McCormack9db0e072004-12-22 15:05:07 +00002994 szRoot = szHCU;
2995 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00002996 case 2: root_key = HKEY_LOCAL_MACHINE;
Mike McCormack9db0e072004-12-22 15:05:07 +00002997 szRoot = szHLM;
2998 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00002999 case 3: root_key = HKEY_USERS;
Mike McCormack9db0e072004-12-22 15:05:07 +00003000 szRoot = szHU;
3001 break;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003002 default:
3003 ERR("Unknown root %i\n",root);
3004 root_key=NULL;
Mike McCormack9db0e072004-12-22 15:05:07 +00003005 szRoot = NULL;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003006 break;
3007 }
3008 if (!root_key)
3009 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003010 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00003011 goto next;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003012 }
3013
Aric Stewart1416b102005-01-06 19:34:16 +00003014 deformat_string(package, key , &deformated);
3015 size = strlenW(deformated) + strlenW(szRoot) + 1;
Mike McCormack9db0e072004-12-22 15:05:07 +00003016 uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
3017 strcpyW(uikey,szRoot);
Aric Stewart1416b102005-01-06 19:34:16 +00003018 strcatW(uikey,deformated);
3019
3020 if (RegCreateKeyW( root_key, deformated, &hkey))
Aric Stewart401bd3f2004-06-28 20:34:35 +00003021 {
Aric Stewart1416b102005-01-06 19:34:16 +00003022 ERR("Could not create key %s\n",debugstr_w(deformated));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003023 msiobj_release(&row->hdr);
Aric Stewart1416b102005-01-06 19:34:16 +00003024 HeapFree(GetProcessHeap(),0,deformated);
Mike McCormack9db0e072004-12-22 15:05:07 +00003025 goto next;
Aric Stewart6e160f12004-06-29 04:07:22 +00003026 }
Aric Stewart1416b102005-01-06 19:34:16 +00003027 HeapFree(GetProcessHeap(),0,deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00003028
Aric Stewart7231a432004-07-09 19:26:30 +00003029 value = load_dynamic_stringW(row,5);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003030 value_data = parse_value(package, value, &type, &size);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003031
Aric Stewart1416b102005-01-06 19:34:16 +00003032 deformat_string(package, name, &deformated);
3033
Aric Stewart401bd3f2004-06-28 20:34:35 +00003034 if (value_data)
3035 {
Aric Stewart1416b102005-01-06 19:34:16 +00003036 TRACE("Setting value %s\n",debugstr_w(deformated));
3037 RegSetValueExW(hkey, deformated, 0, type, value_data, size);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003038
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003039 uirow = MSI_CreateRecord(3);
Aric Stewart1416b102005-01-06 19:34:16 +00003040 MSI_RecordSetStringW(uirow,2,deformated);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003041 MSI_RecordSetStringW(uirow,1,uikey);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003042
3043 if (type == REG_SZ)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003044 MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003045 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003046 MSI_RecordSetStringW(uirow,3,value);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003047
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003048 ui_actiondata(package,szWriteRegistryValues,uirow);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003049 msiobj_release( &uirow->hdr );
Aric Stewartd2c395a2004-07-06 18:48:15 +00003050
Aric Stewart401bd3f2004-06-28 20:34:35 +00003051 HeapFree(GetProcessHeap(),0,value_data);
3052 }
Aric Stewartd2c395a2004-07-06 18:48:15 +00003053 HeapFree(GetProcessHeap(),0,value);
Aric Stewart1416b102005-01-06 19:34:16 +00003054 HeapFree(GetProcessHeap(),0,deformated);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003055
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003056 msiobj_release(&row->hdr);
Aric Stewartb942e182004-07-06 18:50:02 +00003057 RegCloseKey(hkey);
Mike McCormack9db0e072004-12-22 15:05:07 +00003058next:
Michael Stefaniucb9374072005-01-20 10:36:35 +00003059 HeapFree(GetProcessHeap(),0,uikey);
3060 HeapFree(GetProcessHeap(),0,key);
3061 HeapFree(GetProcessHeap(),0,name);
3062 HeapFree(GetProcessHeap(),0,component);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003063 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003064 MSI_ViewClose(view);
3065 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003066 return rc;
3067}
3068
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003069static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00003070{
Aric Stewart7d3e5972004-07-04 00:36:58 +00003071 return ERROR_SUCCESS;
3072}
3073
Aric Stewartae1aa322004-12-27 19:02:59 +00003074
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003075static UINT ACTION_InstallValidate(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00003076{
3077 DWORD progress = 0;
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003078 DWORD total = 0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003079 static const WCHAR q1[]={
3080 'S','E','L','E','C','T',' ','*',' ',
3081 'F','R','O','M',' ','R','e','g','i','s','t','r','y',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00003082 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003083 MSIQUERY * view;
3084 MSIRECORD * row = 0;
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003085 int i;
Aric Stewart7d3e5972004-07-04 00:36:58 +00003086
3087 TRACE(" InstallValidate \n");
3088
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003089 rc = MSI_DatabaseOpenViewW(package->db, q1, &view);
3090 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003091 return ERROR_SUCCESS;
3092
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003093 rc = MSI_ViewExecute(view, 0);
3094 if (rc != ERROR_SUCCESS)
3095 {
3096 MSI_ViewClose(view);
3097 msiobj_release(&view->hdr);
3098 return rc;
3099 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00003100 while (1)
3101 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003102 rc = MSI_ViewFetch(view,&row);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003103 if (rc != ERROR_SUCCESS)
3104 {
3105 rc = ERROR_SUCCESS;
3106 break;
3107 }
3108 progress +=1;
3109
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003110 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003111 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003112 MSI_ViewClose(view);
3113 msiobj_release(&view->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003114
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003115 total = total + progress * REG_PROGRESS_VALUE;
3116 total = total + package->loaded_components * COMPONENT_PROGRESS_VALUE;
3117 for (i=0; i < package->loaded_files; i++)
3118 total += package->files[i].FileSize;
3119 ui_progress(package,0,total,0,0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003120
3121 return ERROR_SUCCESS;
3122}
3123
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003124static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
Aric Stewart5b936ca2004-07-06 18:47:09 +00003125{
3126 UINT rc;
Mike McCormackf3c8b832004-07-19 19:35:05 +00003127 MSIQUERY * view = NULL;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003128 MSIRECORD * row = 0;
3129 static const WCHAR ExecSeqQuery[] = {
3130 'S','E','L','E','C','T',' ','*',' ',
3131 'f','r','o','m',' ','L','a','u','n','c','h','C','o','n','d','i','t','i','o','n',0};
Aric Stewart5b936ca2004-07-06 18:47:09 +00003132 static const WCHAR title[]=
3133 {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00003134
Aric Stewart5b936ca2004-07-06 18:47:09 +00003135 TRACE("Checking launch conditions\n");
Aric Stewart7d3e5972004-07-04 00:36:58 +00003136
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003137 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003138 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003139 return ERROR_SUCCESS;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003140
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003141 rc = MSI_ViewExecute(view, 0);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003142 if (rc != ERROR_SUCCESS)
3143 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003144 MSI_ViewClose(view);
3145 msiobj_release(&view->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003146 return rc;
3147 }
3148
3149 rc = ERROR_SUCCESS;
3150 while (rc == ERROR_SUCCESS)
3151 {
3152 LPWSTR cond = NULL;
3153 LPWSTR message = NULL;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003154
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003155 rc = MSI_ViewFetch(view,&row);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003156 if (rc != ERROR_SUCCESS)
3157 {
3158 rc = ERROR_SUCCESS;
3159 break;
3160 }
3161
Aric Stewart7231a432004-07-09 19:26:30 +00003162 cond = load_dynamic_stringW(row,1);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003163
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003164 if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
Aric Stewart5b936ca2004-07-06 18:47:09 +00003165 {
Aric Stewart6269f002005-01-17 13:40:39 +00003166 LPWSTR deformated;
Aric Stewart7231a432004-07-09 19:26:30 +00003167 message = load_dynamic_stringW(row,2);
Aric Stewart6269f002005-01-17 13:40:39 +00003168 deformat_string(package,message,&deformated);
3169 MessageBoxW(NULL,deformated,title,MB_OK);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003170 HeapFree(GetProcessHeap(),0,message);
Aric Stewart6269f002005-01-17 13:40:39 +00003171 HeapFree(GetProcessHeap(),0,deformated);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003172 rc = ERROR_FUNCTION_FAILED;
3173 }
3174 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003175 msiobj_release(&row->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003176 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003177 MSI_ViewClose(view);
3178 msiobj_release(&view->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003179 return rc;
3180}
Aric Stewart7d3e5972004-07-04 00:36:58 +00003181
Aric Stewartfa384f62004-12-22 18:46:17 +00003182static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
3183 component_index)
Aric Stewartb942e182004-07-06 18:50:02 +00003184{
3185 MSICOMPONENT* cmp = &package->components[component_index];
3186
3187 if (cmp->KeyPath[0]==0)
3188 {
Mike McCormackba8200b2004-12-22 15:25:30 +00003189 LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00003190 return p;
Aric Stewartb942e182004-07-06 18:50:02 +00003191 }
Aric Stewart6269f002005-01-17 13:40:39 +00003192 if (cmp->Attributes & 0x4)
Aric Stewartb942e182004-07-06 18:50:02 +00003193 {
Aric Stewart6269f002005-01-17 13:40:39 +00003194 MSIQUERY * view;
3195 MSIRECORD * row = 0;
3196 UINT rc,root,len;
3197 LPWSTR key,deformated,buffer,name,deformated_name;
3198 static const WCHAR ExecSeqQuery[] = {
3199 's','e','l','e','c','t',' ','*',' ',
3200 'f','r','o','m',' ','R','e','g','i','s','t','r','y',' ',
3201'w','h','e','r','e',' ','R','e','g','i','s','t','r','y',' ','=',' '
3202,'`','%','s','`',0 };
3203 static const WCHAR fmt[]={'%','0','2','i',':','%','s',0};
3204 static const WCHAR fmt2[]={'%','0','2','i',':','%','s','\\','%','s',0};
3205
Mike McCormack0c238852005-01-21 16:19:11 +00003206 rc = MSI_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath);
Aric Stewart6269f002005-01-17 13:40:39 +00003207
3208 if (rc!=ERROR_SUCCESS)
3209 return NULL;
3210
3211 rc = MSI_ViewExecute(view, 0);
3212 if (rc != ERROR_SUCCESS)
3213 {
3214 MSI_ViewClose(view);
3215 msiobj_release(&view->hdr);
3216 return NULL;
3217 }
3218
3219 rc = MSI_ViewFetch(view,&row);
3220 if (rc != ERROR_SUCCESS)
3221 {
3222 MSI_ViewClose(view);
3223 msiobj_release(&view->hdr);
3224 return NULL;
3225 }
3226
3227 root = MSI_RecordGetInteger(row,2);
3228 key = load_dynamic_stringW(row, 3);
3229 name = load_dynamic_stringW(row, 4);
3230 deformat_string(package, key , &deformated);
3231 deformat_string(package, name, &deformated_name);
3232
3233 len = strlenW(deformated) + 5;
3234 if (deformated_name)
3235 len+=strlenW(deformated_name);
3236
3237 buffer = HeapAlloc(GetProcessHeap(),0, len *sizeof(WCHAR));
3238
3239 if (deformated_name)
3240 sprintfW(buffer,fmt2,root,deformated,deformated_name);
3241 else
3242 sprintfW(buffer,fmt,root,deformated);
3243
3244 HeapFree(GetProcessHeap(),0,key);
3245 HeapFree(GetProcessHeap(),0,deformated);
3246 HeapFree(GetProcessHeap(),0,name);
3247 HeapFree(GetProcessHeap(),0,deformated_name);
3248 msiobj_release(&row->hdr);
3249 MSI_ViewClose(view);
3250 msiobj_release(&view->hdr);
3251
3252 return buffer;
3253 }
3254 else if (cmp->Attributes & 0x20)
3255 {
3256 FIXME("UNIMPLEMENTED keypath as ODBC Source\n");
Aric Stewartfa384f62004-12-22 18:46:17 +00003257 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00003258 }
3259 else
3260 {
3261 int j;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003262 j = get_loaded_file(package,cmp->KeyPath);
3263
3264 if (j>=0)
Aric Stewartfa384f62004-12-22 18:46:17 +00003265 {
3266 LPWSTR p = dupstrW(package->files[j].TargetPath);
3267 return p;
3268 }
Aric Stewartb942e182004-07-06 18:50:02 +00003269 }
Aric Stewartfa384f62004-12-22 18:46:17 +00003270 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00003271}
3272
Aric Stewart2cf222f2004-07-06 19:00:23 +00003273/*
3274 * Ok further analysis makes me think that this work is
3275 * actually done in the PublishComponents and PublishFeatures
Mike McCormack3ece2462004-07-09 19:33:25 +00003276 * step, and not here. It appears like the keypath and all that is
3277 * resolved in this step, however actually written in the Publish steps.
Alexandre Julliard77b12762004-07-09 19:43:29 +00003278 * But we will leave it here for now because it is unclear
Aric Stewart2cf222f2004-07-06 19:00:23 +00003279 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003280static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
Aric Stewartb942e182004-07-06 18:50:02 +00003281{
Mike McCormackba8200b2004-12-22 15:25:30 +00003282 LPWSTR productcode;
Aric Stewart68b07492005-01-25 11:05:37 +00003283 WCHAR squished_pc[GUID_SIZE];
3284 WCHAR squished_cc[GUID_SIZE];
Aric Stewartb942e182004-07-06 18:50:02 +00003285 UINT rc;
Mike McCormack4604e662004-08-06 17:30:20 +00003286 DWORD i;
Aric Stewart68b07492005-01-25 11:05:37 +00003287 HKEY hkey=0,hkey2=0;
Aric Stewartb942e182004-07-06 18:50:02 +00003288 static const WCHAR szProductCode[]=
Mike McCormackba8200b2004-12-22 15:25:30 +00003289 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewartb942e182004-07-06 18:50:02 +00003290
Aric Stewartb942e182004-07-06 18:50:02 +00003291 if (!package)
3292 return ERROR_INVALID_HANDLE;
3293
3294 /* writes the Component and Features values to the registry */
Aric Stewartfa384f62004-12-22 18:46:17 +00003295 productcode = load_dynamic_property(package,szProductCode,&rc);
Mike McCormackba8200b2004-12-22 15:25:30 +00003296 if (!productcode)
Aric Stewartfa384f62004-12-22 18:46:17 +00003297 return rc;
Aric Stewartb942e182004-07-06 18:50:02 +00003298
Aric Stewart68b07492005-01-25 11:05:37 +00003299 rc = MSIREG_OpenComponents(&hkey);
Aric Stewartb942e182004-07-06 18:50:02 +00003300 if (rc != ERROR_SUCCESS)
3301 goto end;
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003302
Aric Stewart68b07492005-01-25 11:05:37 +00003303 squash_guid(productcode,squished_pc);
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003304 ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0);
Aric Stewartb942e182004-07-06 18:50:02 +00003305 for (i = 0; i < package->loaded_components; i++)
3306 {
Aric Stewartbd1bbc12005-01-03 20:00:13 +00003307 ui_progress(package,2,0,0,0);
Aric Stewartb942e182004-07-06 18:50:02 +00003308 if (package->components[i].ComponentId[0]!=0)
3309 {
Aric Stewartfa384f62004-12-22 18:46:17 +00003310 WCHAR *keypath = NULL;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003311 MSIRECORD * uirow;
Aric Stewartb942e182004-07-06 18:50:02 +00003312
3313 squash_guid(package->components[i].ComponentId,squished_cc);
Aric Stewart68b07492005-01-25 11:05:37 +00003314 rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
Aric Stewartb942e182004-07-06 18:50:02 +00003315 if (rc != ERROR_SUCCESS)
3316 continue;
3317
Aric Stewartfa384f62004-12-22 18:46:17 +00003318 keypath = resolve_keypath(package,i);
3319 if (keypath)
3320 {
Aric Stewart68b07492005-01-25 11:05:37 +00003321 RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath,
Aric Stewartb942e182004-07-06 18:50:02 +00003322 (strlenW(keypath)+1)*sizeof(WCHAR));
Aric Stewart68b07492005-01-25 11:05:37 +00003323 RegCloseKey(hkey2);
Aric Stewartb942e182004-07-06 18:50:02 +00003324
Aric Stewartfa384f62004-12-22 18:46:17 +00003325 /* UI stuff */
3326 uirow = MSI_CreateRecord(3);
3327 MSI_RecordSetStringW(uirow,1,productcode);
3328 MSI_RecordSetStringW(uirow,2,package->components[i].
3329 ComponentId);
3330 MSI_RecordSetStringW(uirow,3,keypath);
3331 ui_actiondata(package,szProcessComponents,uirow);
3332 msiobj_release( &uirow->hdr );
3333 HeapFree(GetProcessHeap(),0,keypath);
3334 }
Aric Stewartb942e182004-07-06 18:50:02 +00003335 }
3336 }
3337end:
Mike McCormackba8200b2004-12-22 15:25:30 +00003338 HeapFree(GetProcessHeap(), 0, productcode);
Aric Stewartb942e182004-07-06 18:50:02 +00003339 RegCloseKey(hkey);
3340 return rc;
3341}
3342
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003343static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
Aric Stewartfcb20c52004-07-06 18:51:16 +00003344{
3345 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00003346 * OK this is a bit confusing.. I am given a _Component key and I believe
Aric Stewartfcb20c52004-07-06 18:51:16 +00003347 * that the file that is being registered as a type library is the "key file
Mike McCormackc90c7812004-07-09 22:58:27 +00003348 * of that component" which I interpret to mean "The file in the KeyPath of
3349 * that component".
Aric Stewartfcb20c52004-07-06 18:51:16 +00003350 */
3351 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003352 MSIQUERY * view;
3353 MSIRECORD * row = 0;
3354 static const WCHAR Query[] = {
3355 'S','E','L','E','C','T',' ','*',' ',
3356 'f','r','o','m',' ','T','y','p','e','L','i','b',0};
Aric Stewartfcb20c52004-07-06 18:51:16 +00003357 ITypeLib *ptLib;
3358 HRESULT res;
3359
Aric Stewartfcb20c52004-07-06 18:51:16 +00003360 if (!package)
3361 return ERROR_INVALID_HANDLE;
3362
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003363 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003364 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003365 return ERROR_SUCCESS;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003366
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003367 rc = MSI_ViewExecute(view, 0);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003368 if (rc != ERROR_SUCCESS)
3369 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003370 MSI_ViewClose(view);
3371 msiobj_release(&view->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003372 return rc;
3373 }
3374
3375 while (1)
3376 {
3377 WCHAR component[0x100];
3378 DWORD sz;
3379 INT index;
3380
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003381 rc = MSI_ViewFetch(view,&row);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003382 if (rc != ERROR_SUCCESS)
3383 {
3384 rc = ERROR_SUCCESS;
3385 break;
3386 }
3387
3388 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003389 MSI_RecordGetStringW(row,3,component,&sz);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003390
3391 index = get_loaded_component(package,component);
3392 if (index < 0)
3393 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003394 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003395 continue;
3396 }
3397
Aric Stewartfbdd7092004-12-27 19:06:22 +00003398 if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
Aric Stewartfcb20c52004-07-06 18:51:16 +00003399 {
3400 TRACE("Skipping typelib reg due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003401 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003402 continue;
3403 }
3404
3405 index = get_loaded_file(package,package->components[index].KeyPath);
3406
3407 if (index < 0)
3408 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003409 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003410 continue;
3411 }
3412
3413 res = LoadTypeLib(package->files[index].TargetPath,&ptLib);
3414 if (SUCCEEDED(res))
3415 {
Mike McCormackba8200b2004-12-22 15:25:30 +00003416 LPWSTR help;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003417 WCHAR helpid[0x100];
3418
3419 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003420 MSI_RecordGetStringW(row,6,helpid,&sz);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003421
Mike McCormackba8200b2004-12-22 15:25:30 +00003422 help = resolve_folder(package,helpid,FALSE,FALSE,NULL);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003423 res = RegisterTypeLib(ptLib,package->files[index].TargetPath,help);
Mike McCormackba8200b2004-12-22 15:25:30 +00003424 HeapFree(GetProcessHeap(),0,help);
3425
Aric Stewartfcb20c52004-07-06 18:51:16 +00003426 if (!SUCCEEDED(res))
3427 ERR("Failed to register type library %s\n",
3428 debugstr_w(package->files[index].TargetPath));
3429 else
3430 {
Mike McCormackc90c7812004-07-09 22:58:27 +00003431 /* Yes the row has more fields than I need, but #1 is
3432 correct and the only one I need. Why make a new row? */
Aric Stewartfcb20c52004-07-06 18:51:16 +00003433
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003434 ui_actiondata(package,szRegisterTypeLibraries,row);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003435
3436 TRACE("Registered %s\n",
3437 debugstr_w(package->files[index].TargetPath));
3438 }
3439
3440 if (ptLib)
3441 ITypeLib_Release(ptLib);
3442 }
3443 else
3444 ERR("Failed to load type library %s\n",
3445 debugstr_w(package->files[index].TargetPath));
3446
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003447 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003448 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003449 MSI_ViewClose(view);
3450 msiobj_release(&view->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003451 return rc;
3452
3453}
3454
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003455static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app )
Aric Stewart8f0a7612004-07-06 18:53:11 +00003456{
3457 static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
3458 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003459 MSIQUERY * view;
3460 MSIRECORD * row = 0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003461 static const WCHAR ExecSeqQuery[] =
Mike McCormack9db0e072004-12-22 15:05:07 +00003462 {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I'
3463 ,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003464 HKEY hkey2,hkey3;
3465 LPWSTR buffer=0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003466
Aric Stewart8f0a7612004-07-06 18:53:11 +00003467 if (!package)
3468 return ERROR_INVALID_HANDLE;
3469
Mike McCormack0c238852005-01-21 16:19:11 +00003470 rc = MSI_OpenQuery(package->db, &view, ExecSeqQuery, clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003471 if (rc != ERROR_SUCCESS)
3472 return rc;
3473
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003474 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003475 if (rc != ERROR_SUCCESS)
3476 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003477 MSI_ViewClose(view);
3478 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003479 return rc;
3480 }
3481
3482 RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
3483 RegCreateKeyW(hkey2,clsid,&hkey3);
3484 RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
3485 (strlenW(app)+1)*sizeof(WCHAR));
3486
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003487 rc = MSI_ViewFetch(view,&row);
3488 if (rc != ERROR_SUCCESS)
3489 {
3490 MSI_ViewClose(view);
3491 msiobj_release(&view->hdr);
3492 return rc;
3493 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003494
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003495 if (!MSI_RecordIsNull(row,2))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003496 {
3497 LPWSTR deformated=0;
3498 UINT size;
3499 static const WCHAR szRemoteServerName[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003500 {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
Aric Stewart7231a432004-07-09 19:26:30 +00003501 buffer = load_dynamic_stringW(row,2);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003502 size = deformat_string(package,buffer,&deformated);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003503 RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated,
3504 size);
3505 HeapFree(GetProcessHeap(),0,deformated);
3506 HeapFree(GetProcessHeap(),0,buffer);
3507 }
3508
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003509 if (!MSI_RecordIsNull(row,3))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003510 {
3511 static const WCHAR szLocalService[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003512 {'L','o','c','a','l','S','e','r','v','i','c','e',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003513 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003514 buffer = load_dynamic_stringW(row,3);
3515 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003516 RegSetValueExW(hkey3,szLocalService,0,REG_SZ,(LPVOID)buffer,size);
3517 HeapFree(GetProcessHeap(),0,buffer);
3518 }
3519
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003520 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003521 {
3522 static const WCHAR szService[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003523 {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003524 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003525 buffer = load_dynamic_stringW(row,4);
3526 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003527 RegSetValueExW(hkey3,szService,0,REG_SZ,(LPVOID)buffer,size);
3528 HeapFree(GetProcessHeap(),0,buffer);
3529 }
3530
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003531 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003532 {
3533 static const WCHAR szDLL[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003534 {'D','l','l','S','u','r','r','o','g','a','t','e',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003535 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003536 buffer = load_dynamic_stringW(row,5);
3537 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003538 RegSetValueExW(hkey3,szDLL,0,REG_SZ,(LPVOID)buffer,size);
3539 HeapFree(GetProcessHeap(),0,buffer);
3540 }
3541
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003542 if (!MSI_RecordIsNull(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003543 {
3544 static const WCHAR szActivate[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003545 {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003546 static const WCHAR szY[] = {'Y',0};
3547
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003548 if (MSI_RecordGetInteger(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003549 RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
3550 }
3551
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003552 if (!MSI_RecordIsNull(row,7))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003553 {
3554 static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
3555 static const WCHAR szUser[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003556 {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003557
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003558 if (MSI_RecordGetInteger(row,7))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003559 RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34);
3560 }
3561
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003562 msiobj_release(&row->hdr);
3563 MSI_ViewClose(view);
3564 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003565 RegCloseKey(hkey3);
3566 RegCloseKey(hkey2);
3567 return rc;
3568}
3569
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003570static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003571{
3572 /*
Francois Gouget817c5202004-07-16 19:15:40 +00003573 * Again I am assuming the words, "Whose key file represents" when referring
Mike McCormackc90c7812004-07-09 22:58:27 +00003574 * to a Component as to meaning that Components KeyPath file
Aric Stewart8f0a7612004-07-06 18:53:11 +00003575 *
3576 * Also there is a very strong connection between ClassInfo and ProgID
Mike McCormack3ece2462004-07-09 19:33:25 +00003577 * that I am mostly glossing over.
3578 * What would be more propper is to load the ClassInfo and the ProgID info
Aric Stewart8f0a7612004-07-06 18:53:11 +00003579 * into memory data structures and then be able to enable and disable them
3580 * based on component.
3581 */
3582
3583 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003584 MSIQUERY * view;
3585 MSIRECORD * row = 0;
3586 static const WCHAR ExecSeqQuery[] = {
3587 'S','E','L','E','C','T',' ','*',' ',
3588 'f','r','o','m',' ','C','l','a','s','s',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003589 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
3590 static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
3591 static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
3592 HKEY hkey,hkey2,hkey3;
3593
Aric Stewart8f0a7612004-07-06 18:53:11 +00003594 if (!package)
3595 return ERROR_INVALID_HANDLE;
3596
3597 rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
3598 if (rc != ERROR_SUCCESS)
3599 return ERROR_FUNCTION_FAILED;
3600
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003601 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003602 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003603 {
3604 rc = ERROR_SUCCESS;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003605 goto end;
Aric Stewart84837d92004-07-20 01:22:37 +00003606 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003607
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003608 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003609 if (rc != ERROR_SUCCESS)
3610 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003611 MSI_ViewClose(view);
3612 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003613 goto end;
3614 }
3615
3616 while (1)
3617 {
3618 WCHAR clsid[0x100];
3619 WCHAR buffer[0x100];
3620 WCHAR desc[0x100];
3621 DWORD sz;
3622 INT index;
3623
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003624 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003625 if (rc != ERROR_SUCCESS)
3626 {
3627 rc = ERROR_SUCCESS;
3628 break;
3629 }
3630
3631 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003632 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003633
3634 index = get_loaded_component(package,buffer);
3635
3636 if (index < 0)
3637 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003638 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003639 continue;
3640 }
3641
Aric Stewartfbdd7092004-12-27 19:06:22 +00003642 if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003643 {
3644 TRACE("Skipping class reg due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003645 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003646 continue;
3647 }
3648
3649 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003650 MSI_RecordGetStringW(row,1,clsid,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003651 RegCreateKeyW(hkey,clsid,&hkey2);
3652
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003653 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003654 {
3655 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003656 MSI_RecordGetStringW(row,5,desc,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003657
3658 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)desc,
3659 (strlenW(desc)+1)*sizeof(WCHAR));
3660 }
3661 else
3662 desc[0]=0;
3663
3664 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003665 MSI_RecordGetStringW(row,2,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003666
3667 RegCreateKeyW(hkey2,buffer,&hkey3);
3668
3669 index = get_loaded_file(package,package->components[index].KeyPath);
3670 RegSetValueExW(hkey3,NULL,0,REG_SZ,
3671 (LPVOID)package->files[index].TargetPath,
3672 (strlenW(package->files[index].TargetPath)+1)
3673 *sizeof(WCHAR));
3674
3675 RegCloseKey(hkey3);
3676
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003677 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003678 {
3679 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003680 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003681
3682 RegCreateKeyW(hkey2,szProgID,&hkey3);
3683
3684 RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)buffer,
3685 (strlenW(buffer)+1)*sizeof(WCHAR));
3686
3687 RegCloseKey(hkey3);
3688 }
3689
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003690 if (!MSI_RecordIsNull(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003691 {
3692 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003693 MSI_RecordGetStringW(row,6,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003694
3695 RegSetValueExW(hkey2,szAppID,0,REG_SZ,(LPVOID)buffer,
3696 (strlenW(buffer)+1)*sizeof(WCHAR));
3697
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003698 register_appid(package,buffer,desc);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003699 }
3700
3701 RegCloseKey(hkey2);
3702
3703 FIXME("Process the rest of the fields >7\n");
3704
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003705 ui_actiondata(package,szRegisterClassInfo,row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003706
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003707 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003708 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003709 MSI_ViewClose(view);
3710 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003711
3712end:
3713 RegCloseKey(hkey);
3714 return rc;
3715}
3716
Aric Stewart6269f002005-01-17 13:40:39 +00003717static UINT register_progid_base(MSIPACKAGE* package, MSIRECORD * row,
3718 LPWSTR clsid)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003719{
3720 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
Aric Stewart6269f002005-01-17 13:40:39 +00003721 static const WCHAR szDefaultIcon[] = {
3722 'D','e','f','a','u','l','t','I','c','o','n',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003723 HKEY hkey,hkey2;
Aric Stewart7231a432004-07-09 19:26:30 +00003724 WCHAR buffer[0x100];
Aric Stewart8f0a7612004-07-06 18:53:11 +00003725 DWORD sz;
3726
3727
Aric Stewart7231a432004-07-09 19:26:30 +00003728 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003729 MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003730 RegCreateKeyW(HKEY_CLASSES_ROOT,buffer,&hkey);
3731
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003732 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003733 {
Aric Stewart7231a432004-07-09 19:26:30 +00003734 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003735 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003736 RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
3737 sizeof(WCHAR));
3738 }
3739
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003740 if (!MSI_RecordIsNull(row,3))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003741 {
Aric Stewart7231a432004-07-09 19:26:30 +00003742 sz = 0x100;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003743
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003744 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003745 RegCreateKeyW(hkey,szCLSID,&hkey2);
3746 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
3747 sizeof(WCHAR));
3748
3749 if (clsid)
3750 strcpyW(clsid,buffer);
3751
3752 RegCloseKey(hkey2);
3753 }
3754 else
3755 {
3756 FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
3757 return ERROR_FUNCTION_FAILED;
3758 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003759 if (!MSI_RecordIsNull(row,5))
Aric Stewart6269f002005-01-17 13:40:39 +00003760 {
3761 INT index = MSI_RecordGetInteger(row,6);
3762 LPWSTR FileName = load_dynamic_stringW(row,5);
3763 LPWSTR FilePath,IconPath;
3764 static const WCHAR fmt[] = {'%','s',',','%','i',0};
3765
3766 RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
3767 build_icon_path(package,FileName,&FilePath);
3768
3769 IconPath = HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
3770 sizeof(WCHAR));
3771
3772 sprintfW(IconPath,fmt,FilePath,index);
3773 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)IconPath,
3774 (strlenW(IconPath)+1) * sizeof(WCHAR));
3775 HeapFree(GetProcessHeap(),0,FilePath);
3776 HeapFree(GetProcessHeap(),0,FileName);
3777 RegCloseKey(hkey2);
3778 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003779 return ERROR_SUCCESS;
3780}
3781
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003782static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003783
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003784static UINT register_parent_progid(MSIPACKAGE *package, LPCWSTR parent,
Aric Stewart8f0a7612004-07-06 18:53:11 +00003785 LPWSTR clsid)
3786{
3787 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003788 MSIQUERY * view;
3789 MSIRECORD * row = 0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003790 static const WCHAR Query_t[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003791 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g'
3792 ,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`'
3793 ,'%','s','`',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003794
Aric Stewart8f0a7612004-07-06 18:53:11 +00003795 if (!package)
3796 return ERROR_INVALID_HANDLE;
3797
Mike McCormack0c238852005-01-21 16:19:11 +00003798 rc = MSI_OpenQuery(package->db, &view, Query_t, parent);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003799 if (rc != ERROR_SUCCESS)
3800 return rc;
3801
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003802 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003803 if (rc != ERROR_SUCCESS)
3804 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003805 MSI_ViewClose(view);
3806 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003807 return rc;
3808 }
3809
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003810 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003811 if (rc != ERROR_SUCCESS)
3812 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003813 MSI_ViewClose(view);
3814 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003815 return rc;
3816 }
3817
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003818 register_progid(package,row,clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003819
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003820 msiobj_release(&row->hdr);
3821 MSI_ViewClose(view);
3822 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003823 return rc;
3824}
3825
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003826static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003827{
3828 UINT rc = ERROR_SUCCESS;
3829
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003830 if (MSI_RecordIsNull(row,2))
Aric Stewart6269f002005-01-17 13:40:39 +00003831 rc = register_progid_base(package,row,clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003832 else
3833 {
3834 WCHAR buffer[0x1000];
Aric Stewartd906ef02004-10-22 22:06:31 +00003835 DWORD sz, disp;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003836 HKEY hkey,hkey2;
3837 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
Aric Stewart6269f002005-01-17 13:40:39 +00003838 static const WCHAR szDefaultIcon[] = {
3839 'D','e','f','a','u','l','t','I','c','o','n',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003840
Aric Stewartd906ef02004-10-22 22:06:31 +00003841 /* check if already registered */
Aric Stewart7231a432004-07-09 19:26:30 +00003842 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003843 MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewartd906ef02004-10-22 22:06:31 +00003844 RegCreateKeyExW(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0,
3845 KEY_ALL_ACCESS, NULL, &hkey, &disp );
3846 if (disp == REG_OPENED_EXISTING_KEY)
3847 {
3848 TRACE("Key already registered\n");
3849 RegCloseKey(hkey);
3850 return rc;
3851 }
Aric Stewart6269f002005-01-17 13:40:39 +00003852
3853 sz = 0x100;
3854 MSI_RecordGetStringW(row,2,buffer,&sz);
3855 rc = register_parent_progid(package,buffer,clsid);
3856
Aric Stewartd906ef02004-10-22 22:06:31 +00003857 /* clsid is same as parent */
Aric Stewart8f0a7612004-07-06 18:53:11 +00003858 RegCreateKeyW(hkey,szCLSID,&hkey2);
3859 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
3860 sizeof(WCHAR));
3861
3862 RegCloseKey(hkey2);
Aric Stewartd906ef02004-10-22 22:06:31 +00003863
Aric Stewartd906ef02004-10-22 22:06:31 +00003864
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003865 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003866 {
Aric Stewart7231a432004-07-09 19:26:30 +00003867 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003868 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003869 RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer,
3870 (strlenW(buffer)+1) * sizeof(WCHAR));
3871 }
3872
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003873 if (!MSI_RecordIsNull(row,5))
Aric Stewart6269f002005-01-17 13:40:39 +00003874 {
3875 LPWSTR FileName = load_dynamic_stringW(row,5);
3876 LPWSTR FilePath;
3877 RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
3878 build_icon_path(package,FileName,&FilePath);
3879 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)FilePath,
3880 (strlenW(FilePath)+1) * sizeof(WCHAR));
3881 HeapFree(GetProcessHeap(),0,FilePath);
3882 HeapFree(GetProcessHeap(),0,FileName);
3883 RegCloseKey(hkey2);
3884 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003885
3886 RegCloseKey(hkey);
3887 }
3888 return rc;
3889}
3890
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003891static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003892{
3893 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00003894 * Sigh, here I am just brute force registering all progids
Francois Gouget817c5202004-07-16 19:15:40 +00003895 * this needs to be linked to the Classes that have been registered
Aric Stewart8f0a7612004-07-06 18:53:11 +00003896 * but the easiest way to do that is to load all these stuff into
3897 * memory for easy checking.
3898 *
Mike McCormackc90c7812004-07-09 22:58:27 +00003899 * Gives me something to continue to work toward.
Aric Stewart8f0a7612004-07-06 18:53:11 +00003900 */
3901 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003902 MSIQUERY * view;
3903 MSIRECORD * row = 0;
3904 static const WCHAR Query[] = {
3905 'S','E','L','E','C','T',' ','*',' ',
3906 'F','R','O','M',' ','P','r','o','g','I','d',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003907
Aric Stewart8f0a7612004-07-06 18:53:11 +00003908 if (!package)
3909 return ERROR_INVALID_HANDLE;
3910
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003911 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003912 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003913 return ERROR_SUCCESS;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003914
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003915 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003916 if (rc != ERROR_SUCCESS)
3917 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003918 MSI_ViewClose(view);
3919 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003920 return rc;
3921 }
3922
3923 while (1)
3924 {
3925 WCHAR clsid[0x1000];
3926
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003927 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003928 if (rc != ERROR_SUCCESS)
3929 {
3930 rc = ERROR_SUCCESS;
3931 break;
3932 }
3933
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003934 register_progid(package,row,clsid);
3935 ui_actiondata(package,szRegisterProgIdInfo,row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003936
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003937 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003938 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003939 MSI_ViewClose(view);
3940 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003941 return rc;
3942}
3943
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003944static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
Aric Stewartfa384f62004-12-22 18:46:17 +00003945 LPWSTR *FilePath)
Aric Stewart2cf222f2004-07-06 19:00:23 +00003946{
Mike McCormackba8200b2004-12-22 15:25:30 +00003947 LPWSTR ProductCode;
3948 LPWSTR SystemFolder;
Aric Stewartfa384f62004-12-22 18:46:17 +00003949 LPWSTR dest;
3950 UINT rc;
3951
Aric Stewart2cf222f2004-07-06 19:00:23 +00003952 static const WCHAR szInstaller[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003953 {'I','n','s','t','a','l','l','e','r','\\',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00003954 static const WCHAR szProductCode[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003955 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00003956 static const WCHAR szFolder[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003957 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00003958
Aric Stewartfa384f62004-12-22 18:46:17 +00003959 ProductCode = load_dynamic_property(package,szProductCode,&rc);
Mike McCormackba8200b2004-12-22 15:25:30 +00003960 if (!ProductCode)
Aric Stewartfa384f62004-12-22 18:46:17 +00003961 return rc;
Aric Stewart2cf222f2004-07-06 19:00:23 +00003962
Aric Stewartfa384f62004-12-22 18:46:17 +00003963 SystemFolder = load_dynamic_property(package,szFolder,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00003964
Aric Stewartfa384f62004-12-22 18:46:17 +00003965 dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode);
Aric Stewart2cf222f2004-07-06 19:00:23 +00003966
Aric Stewartfa384f62004-12-22 18:46:17 +00003967 create_full_pathW(dest);
3968
3969 *FilePath = build_directory_name(2, dest, icon_name);
3970
Mike McCormackba8200b2004-12-22 15:25:30 +00003971 HeapFree(GetProcessHeap(),0,SystemFolder);
3972 HeapFree(GetProcessHeap(),0,ProductCode);
Aric Stewartfa384f62004-12-22 18:46:17 +00003973 HeapFree(GetProcessHeap(),0,dest);
Aric Stewart2cf222f2004-07-06 19:00:23 +00003974 return ERROR_SUCCESS;
3975}
3976
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003977static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
Aric Stewart2cf222f2004-07-06 19:00:23 +00003978{
3979 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003980 MSIQUERY * view;
3981 MSIRECORD * row = 0;
3982 static const WCHAR Query[] = {
3983 'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ',
3984 'S','h','o','r','t','c','u','t',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00003985 IShellLinkW *sl;
3986 IPersistFile *pf;
3987 HRESULT res;
3988
Aric Stewart2cf222f2004-07-06 19:00:23 +00003989 if (!package)
3990 return ERROR_INVALID_HANDLE;
3991
3992 res = CoInitialize( NULL );
3993 if (FAILED (res))
3994 {
3995 ERR("CoInitialize failed\n");
3996 return ERROR_FUNCTION_FAILED;
3997 }
3998
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003999 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004000 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00004001 return ERROR_SUCCESS;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004002
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004003 rc = MSI_ViewExecute(view, 0);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004004 if (rc != ERROR_SUCCESS)
4005 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004006 MSI_ViewClose(view);
4007 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004008 return rc;
4009 }
4010
4011 while (1)
4012 {
Mike McCormackba8200b2004-12-22 15:25:30 +00004013 LPWSTR target_file, target_folder;
Aric Stewart7231a432004-07-09 19:26:30 +00004014 WCHAR buffer[0x100];
Aric Stewart2cf222f2004-07-06 19:00:23 +00004015 DWORD sz;
4016 DWORD index;
4017 static const WCHAR szlnk[]={'.','l','n','k',0};
4018
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004019 rc = MSI_ViewFetch(view,&row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004020 if (rc != ERROR_SUCCESS)
4021 {
4022 rc = ERROR_SUCCESS;
4023 break;
4024 }
4025
Aric Stewart7231a432004-07-09 19:26:30 +00004026 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004027 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004028
4029 index = get_loaded_component(package,buffer);
4030
4031 if (index < 0)
4032 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004033 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004034 continue;
4035 }
4036
Aric Stewartfbdd7092004-12-27 19:06:22 +00004037 if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004038 {
4039 TRACE("Skipping shortcut creation due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004040 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004041 continue;
4042 }
4043
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004044 ui_actiondata(package,szCreateShortcuts,row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004045
4046 res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
4047 &IID_IShellLinkW, (LPVOID *) &sl );
4048
4049 if (FAILED(res))
4050 {
4051 ERR("Is IID_IShellLink\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004052 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004053 continue;
4054 }
4055
4056 res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
4057 if( FAILED( res ) )
4058 {
4059 ERR("Is IID_IPersistFile\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004060 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004061 continue;
4062 }
4063
Aric Stewart7231a432004-07-09 19:26:30 +00004064 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004065 MSI_RecordGetStringW(row,2,buffer,&sz);
Mike McCormackba8200b2004-12-22 15:25:30 +00004066 target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004067
Aric Stewart8cc14a92004-12-27 18:56:30 +00004068 /* may be needed because of a bug somehwere else */
4069 create_full_pathW(target_folder);
4070
Aric Stewart7231a432004-07-09 19:26:30 +00004071 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004072 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004073 reduce_to_longfilename(buffer);
Aric Stewart00e1ecd2005-01-05 17:13:12 +00004074 if (!strchrW(buffer,'.') || strcmpiW(strchrW(buffer,'.'),szlnk))
Mike McCormackba8200b2004-12-22 15:25:30 +00004075 strcatW(buffer,szlnk);
4076 target_file = build_directory_name(2, target_folder, buffer);
4077 HeapFree(GetProcessHeap(),0,target_folder);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004078
Aric Stewart7231a432004-07-09 19:26:30 +00004079 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004080 MSI_RecordGetStringW(row,5,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004081 if (strchrW(buffer,'['))
4082 {
4083 LPWSTR deformated;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004084 deformat_string(package,buffer,&deformated);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004085 IShellLinkW_SetPath(sl,deformated);
4086 HeapFree(GetProcessHeap(),0,deformated);
4087 }
4088 else
4089 {
4090 FIXME("UNHANDLED shortcut format, advertised shortcut\n");
4091 IPersistFile_Release( pf );
4092 IShellLinkW_Release( sl );
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004093 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004094 continue;
4095 }
4096
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004097 if (!MSI_RecordIsNull(row,6))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004098 {
4099 LPWSTR deformated;
Aric Stewart7231a432004-07-09 19:26:30 +00004100 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004101 MSI_RecordGetStringW(row,6,buffer,&sz);
4102 deformat_string(package,buffer,&deformated);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004103 IShellLinkW_SetArguments(sl,deformated);
4104 HeapFree(GetProcessHeap(),0,deformated);
4105 }
4106
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004107 if (!MSI_RecordIsNull(row,7))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004108 {
4109 LPWSTR deformated;
Aric Stewart7231a432004-07-09 19:26:30 +00004110 deformated = load_dynamic_stringW(row,7);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004111 IShellLinkW_SetDescription(sl,deformated);
4112 HeapFree(GetProcessHeap(),0,deformated);
4113 }
4114
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004115 if (!MSI_RecordIsNull(row,8))
4116 IShellLinkW_SetHotkey(sl,MSI_RecordGetInteger(row,8));
Aric Stewart2cf222f2004-07-06 19:00:23 +00004117
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004118 if (!MSI_RecordIsNull(row,9))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004119 {
Aric Stewartfa384f62004-12-22 18:46:17 +00004120 WCHAR *Path = NULL;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004121 INT index;
4122
Aric Stewart7231a432004-07-09 19:26:30 +00004123 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004124 MSI_RecordGetStringW(row,9,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004125
Aric Stewartfa384f62004-12-22 18:46:17 +00004126 build_icon_path(package,buffer,&Path);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004127 index = MSI_RecordGetInteger(row,10);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004128
4129 IShellLinkW_SetIconLocation(sl,Path,index);
Aric Stewartfa384f62004-12-22 18:46:17 +00004130 HeapFree(GetProcessHeap(),0,Path);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004131 }
4132
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004133 if (!MSI_RecordIsNull(row,11))
4134 IShellLinkW_SetShowCmd(sl,MSI_RecordGetInteger(row,11));
Aric Stewart2cf222f2004-07-06 19:00:23 +00004135
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004136 if (!MSI_RecordIsNull(row,12))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004137 {
Mike McCormackba8200b2004-12-22 15:25:30 +00004138 LPWSTR Path;
Aric Stewart7231a432004-07-09 19:26:30 +00004139 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004140 MSI_RecordGetStringW(row,12,buffer,&sz);
Mike McCormackba8200b2004-12-22 15:25:30 +00004141 Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004142 IShellLinkW_SetWorkingDirectory(sl,Path);
Mike McCormackba8200b2004-12-22 15:25:30 +00004143 HeapFree(GetProcessHeap(), 0, Path);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004144 }
4145
4146 TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
4147 IPersistFile_Save(pf,target_file,FALSE);
Aric Stewartfa384f62004-12-22 18:46:17 +00004148
4149 HeapFree(GetProcessHeap(),0,target_file);
4150
Aric Stewart2cf222f2004-07-06 19:00:23 +00004151 IPersistFile_Release( pf );
4152 IShellLinkW_Release( sl );
4153
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004154 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004155 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004156 MSI_ViewClose(view);
4157 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004158
4159
4160 CoUninitialize();
4161
4162 return rc;
4163}
4164
4165
4166/*
4167 * 99% of the work done here is only done for
4168 * advertised installs. However this is where the
4169 * Icon table is processed and written out
Francois Gouget817c5202004-07-16 19:15:40 +00004170 * so that is what I am going to do here.
Aric Stewart2cf222f2004-07-06 19:00:23 +00004171 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004172static UINT ACTION_PublishProduct(MSIPACKAGE *package)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004173{
4174 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004175 MSIQUERY * view;
4176 MSIRECORD * row = 0;
4177 static const WCHAR Query[]={
4178 'S','E','L','E','C','T',' ','*',' ',
4179 'f','r','o','m',' ','I','c','o','n',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004180 DWORD sz;
Aric Stewart6269f002005-01-17 13:40:39 +00004181 /* for registry stuff */
4182 LPWSTR productcode;
Aric Stewart68b07492005-01-25 11:05:37 +00004183 HKEY hkey=0;
4184 HKEY hukey=0;
Aric Stewart6269f002005-01-17 13:40:39 +00004185 static const WCHAR szProductCode[]=
4186 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart6269f002005-01-17 13:40:39 +00004187 static const WCHAR szProductName[] = {
4188 'P','r','o','d','u','c','t','N','a','m','e',0};
Aric Stewart68b07492005-01-25 11:05:37 +00004189 static const WCHAR szPackageCode[] = {
4190 'P','a','c','k','a','g','e','C','o','d','e',0};
Aric Stewart6269f002005-01-17 13:40:39 +00004191 LPWSTR buffer;
4192 DWORD size;
Aric Stewart68b07492005-01-25 11:05:37 +00004193 MSIHANDLE hDb, hSumInfo;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004194
Aric Stewart2cf222f2004-07-06 19:00:23 +00004195 if (!package)
4196 return ERROR_INVALID_HANDLE;
4197
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004198 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004199 if (rc != ERROR_SUCCESS)
Aric Stewart2cae30b2005-01-19 19:07:40 +00004200 goto next;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004201
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004202 rc = MSI_ViewExecute(view, 0);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004203 if (rc != ERROR_SUCCESS)
4204 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004205 MSI_ViewClose(view);
4206 msiobj_release(&view->hdr);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004207 goto next;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004208 }
4209
4210 while (1)
4211 {
4212 HANDLE the_file;
Aric Stewartfa384f62004-12-22 18:46:17 +00004213 WCHAR *FilePath=NULL;
4214 WCHAR *FileName=NULL;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004215 CHAR buffer[1024];
4216
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004217 rc = MSI_ViewFetch(view,&row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004218 if (rc != ERROR_SUCCESS)
4219 {
4220 rc = ERROR_SUCCESS;
4221 break;
4222 }
4223
Aric Stewartfa384f62004-12-22 18:46:17 +00004224 FileName = load_dynamic_stringW(row,1);
4225 if (!FileName)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004226 {
4227 ERR("Unable to get FileName\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004228 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004229 continue;
4230 }
4231
Aric Stewartfa384f62004-12-22 18:46:17 +00004232 build_icon_path(package,FileName,&FilePath);
4233
4234 HeapFree(GetProcessHeap(),0,FileName);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004235
4236 TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
4237
4238 the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
4239 FILE_ATTRIBUTE_NORMAL, NULL);
4240
4241 if (the_file == INVALID_HANDLE_VALUE)
4242 {
4243 ERR("Unable to create file %s\n",debugstr_w(FilePath));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004244 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00004245 HeapFree(GetProcessHeap(),0,FilePath);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004246 continue;
4247 }
4248
4249 do
4250 {
4251 DWORD write;
4252 sz = 1024;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004253 rc = MSI_RecordReadStream(row,2,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004254 if (rc != ERROR_SUCCESS)
4255 {
4256 ERR("Failed to get stream\n");
4257 CloseHandle(the_file);
4258 DeleteFileW(FilePath);
4259 break;
4260 }
4261 WriteFile(the_file,buffer,sz,&write,NULL);
4262 } while (sz == 1024);
4263
Aric Stewartfa384f62004-12-22 18:46:17 +00004264 HeapFree(GetProcessHeap(),0,FilePath);
4265
Aric Stewart2cf222f2004-07-06 19:00:23 +00004266 CloseHandle(the_file);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004267 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004268 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004269 MSI_ViewClose(view);
4270 msiobj_release(&view->hdr);
Aric Stewart6269f002005-01-17 13:40:39 +00004271
Aric Stewart2cae30b2005-01-19 19:07:40 +00004272next:
Aric Stewart6269f002005-01-17 13:40:39 +00004273 /* ok there is alot more done here but i need to figure out what */
4274 productcode = load_dynamic_property(package,szProductCode,&rc);
4275 if (!productcode)
4276 return rc;
4277
Aric Stewart68b07492005-01-25 11:05:37 +00004278 rc = MSIREG_OpenProductsKey(productcode,&hkey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00004279 if (rc != ERROR_SUCCESS)
4280 goto end;
4281
Aric Stewart68b07492005-01-25 11:05:37 +00004282 rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00004283 if (rc != ERROR_SUCCESS)
4284 goto end;
4285
Aric Stewart6269f002005-01-17 13:40:39 +00004286
4287 buffer = load_dynamic_property(package,szProductName,NULL);
4288 size = strlenW(buffer)*sizeof(WCHAR);
Aric Stewart68b07492005-01-25 11:05:37 +00004289 RegSetValueExW(hukey,szProductName,0,REG_SZ, (LPSTR)buffer,size);
Aric Stewart6269f002005-01-17 13:40:39 +00004290 HeapFree(GetProcessHeap(),0,buffer);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004291 FIXME("Need to write more keys to the user registry\n");
Aric Stewart68b07492005-01-25 11:05:37 +00004292
4293 hDb= msiobj_findhandle( &package->db->hdr );
4294 rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo);
4295 if (rc == ERROR_SUCCESS)
4296 {
4297 WCHAR guidbuffer[0x200];
4298 size = 0x200;
4299 rc = MsiSummaryInfoGetPropertyW(hSumInfo, 8, NULL, NULL, NULL,
4300 guidbuffer, &size);
4301 if (rc == ERROR_SUCCESS)
4302 {
4303 WCHAR squashed[GUID_SIZE];
4304 /* for now we only care about the first guid */
4305 LPWSTR ptr = strchrW(guidbuffer,';');
4306 if (ptr) *ptr = 0;
4307 squash_guid(guidbuffer,squashed);
4308 size = strlenW(guidbuffer)*sizeof(WCHAR);
4309 RegSetValueExW(hukey,szPackageCode,0,REG_SZ, (LPSTR)guidbuffer,
4310 size);
4311
4312 }
4313 else
4314 {
4315 ERR("Unable to query Revision_Number... \n");
4316 rc = ERROR_SUCCESS;
4317 }
4318 MsiCloseHandle(hSumInfo);
4319 }
4320 else
4321 {
4322 ERR("Unable to open Summary Information\n");
4323 rc = ERROR_SUCCESS;
4324 }
Aric Stewart2cae30b2005-01-19 19:07:40 +00004325
Aric Stewart6269f002005-01-17 13:40:39 +00004326end:
4327
4328 HeapFree(GetProcessHeap(),0,productcode);
Aric Stewart6269f002005-01-17 13:40:39 +00004329 RegCloseKey(hkey);
Aric Stewart6269f002005-01-17 13:40:39 +00004330 RegCloseKey(hukey);
4331
Aric Stewart2cf222f2004-07-06 19:00:23 +00004332 return rc;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004333}
4334
Aric Stewart516a9c72005-01-14 15:59:26 +00004335static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
4336{
4337 UINT rc;
4338 MSIQUERY * view;
4339 MSIRECORD * row = 0;
4340 static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',
4341 ' ','f','r','o','m',' ','I','n','i','F','i','l','e',0};
4342 static const WCHAR szWindowsFolder[] =
4343 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
4344 static const WCHAR szbs[] = {'\\',0};
4345
4346 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
4347 if (rc != ERROR_SUCCESS)
4348 {
4349 TRACE("no IniFile table\n");
4350 return ERROR_SUCCESS;
4351 }
4352
4353 rc = MSI_ViewExecute(view, 0);
4354 if (rc != ERROR_SUCCESS)
4355 {
4356 MSI_ViewClose(view);
4357 msiobj_release(&view->hdr);
4358 return rc;
4359 }
4360
4361 while (1)
4362 {
4363 LPWSTR component,filename,dirproperty,section,key,value,identifier;
4364 LPWSTR deformated_section, deformated_key, deformated_value;
4365 LPWSTR folder, fullname = NULL;
4366 MSIRECORD * uirow;
4367 INT component_index,action;
4368
4369 rc = MSI_ViewFetch(view,&row);
4370 if (rc != ERROR_SUCCESS)
4371 {
4372 rc = ERROR_SUCCESS;
4373 break;
4374 }
4375
4376 component = load_dynamic_stringW(row, 8);
4377 component_index = get_loaded_component(package,component);
Michael Stefaniucb9374072005-01-20 10:36:35 +00004378 HeapFree(GetProcessHeap(),0,component);
Aric Stewart516a9c72005-01-14 15:59:26 +00004379
4380 if (package->components[component_index].ActionRequest !=
4381 INSTALLSTATE_LOCAL)
4382 {
4383 TRACE("Skipping ini file due to disabled component\n");
4384 msiobj_release(&row->hdr);
4385 continue;
4386 }
4387
4388 identifier = load_dynamic_stringW(row,1);
4389 filename = load_dynamic_stringW(row,2);
4390 dirproperty = load_dynamic_stringW(row,3);
4391 section = load_dynamic_stringW(row,4);
4392 key = load_dynamic_stringW(row,5);
4393 value = load_dynamic_stringW(row,6);
4394 action = MSI_RecordGetInteger(row,7);
4395
4396 deformat_string(package,section,&deformated_section);
4397 deformat_string(package,key,&deformated_key);
4398 deformat_string(package,value,&deformated_value);
4399
4400 if (dirproperty)
4401 {
4402 folder = resolve_folder(package, dirproperty, FALSE, FALSE, NULL);
4403 if (!folder)
4404 folder = load_dynamic_property(package,dirproperty,NULL);
4405 }
4406 else
4407 folder = load_dynamic_property(package, szWindowsFolder, NULL);
4408
4409 if (!folder)
4410 {
4411 ERR("Unable to resolve folder! (%s)\n",debugstr_w(dirproperty));
4412 goto cleanup;
4413 }
4414
4415
4416 fullname = HeapAlloc(GetProcessHeap(),0,
4417 (strlenW(folder)+strlenW(filename)+2)*sizeof(WCHAR));
4418
4419 strcpyW(fullname,folder);
4420 if (fullname[strlenW(folder)] != '\\')
4421 strcatW(fullname,szbs);
4422 strcatW(fullname,filename);
4423
4424 if (action == 0)
4425 {
4426 TRACE("Adding value %s to section %s in %s\n",
4427 debugstr_w(deformated_key), debugstr_w(deformated_section),
4428 debugstr_w(fullname));
4429 WritePrivateProfileStringW(deformated_section, deformated_key,
4430 deformated_value, fullname);
4431 }
4432 else if (action == 1)
4433 {
4434 WCHAR returned[10];
4435 GetPrivateProfileStringW(deformated_section, deformated_key, NULL,
4436 returned, 10, fullname);
4437 if (returned[0] == 0)
4438 {
4439 TRACE("Adding value %s to section %s in %s\n",
4440 debugstr_w(deformated_key), debugstr_w(deformated_section),
4441 debugstr_w(fullname));
4442
4443 WritePrivateProfileStringW(deformated_section, deformated_key,
4444 deformated_value, fullname);
4445 }
4446 }
4447 else if (action == 3)
4448 {
4449 FIXME("Append to existing section not yet implemented\n");
4450 }
4451
4452 uirow = MSI_CreateRecord(4);
4453 MSI_RecordSetStringW(uirow,1,identifier);
4454 MSI_RecordSetStringW(uirow,2,deformated_section);
4455 MSI_RecordSetStringW(uirow,3,deformated_key);
4456 MSI_RecordSetStringW(uirow,4,deformated_value);
4457 ui_actiondata(package,szWriteIniValues,uirow);
4458 msiobj_release( &uirow->hdr );
4459cleanup:
4460 HeapFree(GetProcessHeap(),0,identifier);
4461 HeapFree(GetProcessHeap(),0,fullname);
4462 HeapFree(GetProcessHeap(),0,filename);
4463 HeapFree(GetProcessHeap(),0,key);
4464 HeapFree(GetProcessHeap(),0,value);
4465 HeapFree(GetProcessHeap(),0,section);
4466 HeapFree(GetProcessHeap(),0,dirproperty);
4467 HeapFree(GetProcessHeap(),0,folder);
4468 HeapFree(GetProcessHeap(),0,deformated_key);
4469 HeapFree(GetProcessHeap(),0,deformated_value);
4470 HeapFree(GetProcessHeap(),0,deformated_section);
4471 msiobj_release(&row->hdr);
4472 }
4473 MSI_ViewClose(view);
4474 msiobj_release(&view->hdr);
4475 return rc;
4476}
4477
Aric Stewart6269f002005-01-17 13:40:39 +00004478static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
4479{
4480 UINT rc;
4481 MSIQUERY * view;
4482 MSIRECORD * row = 0;
4483 static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',' ',
4484'f','r','o','m',' ','S','e','l','f','R','e','g',0};
4485
Aric Stewart2cae30b2005-01-19 19:07:40 +00004486 static const WCHAR ExeStr[] = {
4487'r','e','g','s','v','r','3','2','.','e','x','e',' ','/','s',' ',0};
4488 STARTUPINFOW si;
4489 PROCESS_INFORMATION info;
4490 BOOL brc;
4491
4492 memset(&si,0,sizeof(STARTUPINFOW));
4493
Aric Stewart6269f002005-01-17 13:40:39 +00004494 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
4495 if (rc != ERROR_SUCCESS)
4496 {
4497 TRACE("no SelfReg table\n");
4498 return ERROR_SUCCESS;
4499 }
4500
4501 rc = MSI_ViewExecute(view, 0);
4502 if (rc != ERROR_SUCCESS)
4503 {
4504 MSI_ViewClose(view);
4505 msiobj_release(&view->hdr);
4506 return rc;
4507 }
4508
4509 while (1)
4510 {
4511 LPWSTR filename;
4512 INT index;
Aric Stewart2cae30b2005-01-19 19:07:40 +00004513 DWORD len;
Aric Stewart6269f002005-01-17 13:40:39 +00004514
4515 rc = MSI_ViewFetch(view,&row);
4516 if (rc != ERROR_SUCCESS)
4517 {
4518 rc = ERROR_SUCCESS;
4519 break;
4520 }
4521
4522 filename = load_dynamic_stringW(row,1);
4523 index = get_loaded_file(package,filename);
4524
4525 if (index < 0)
4526 {
4527 ERR("Unable to find file id %s\n",debugstr_w(filename));
4528 HeapFree(GetProcessHeap(),0,filename);
4529 msiobj_release(&row->hdr);
4530 continue;
4531 }
4532 HeapFree(GetProcessHeap(),0,filename);
4533
Aric Stewart2cae30b2005-01-19 19:07:40 +00004534 len = strlenW(ExeStr);
4535 len += strlenW(package->files[index].TargetPath);
4536 len +=2;
Aric Stewart6269f002005-01-17 13:40:39 +00004537
Aric Stewart2cae30b2005-01-19 19:07:40 +00004538 filename = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
4539 strcpyW(filename,ExeStr);
4540 strcatW(filename,package->files[index].TargetPath);
Aric Stewart6269f002005-01-17 13:40:39 +00004541
Aric Stewart2cae30b2005-01-19 19:07:40 +00004542 TRACE("Registering %s\n",debugstr_w(filename));
4543 brc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL,
4544 c_collen, &si, &info);
Aric Stewart6269f002005-01-17 13:40:39 +00004545
Aric Stewart2cae30b2005-01-19 19:07:40 +00004546 if (brc)
4547 WaitForSingleObject(info.hProcess,INFINITE);
4548
4549 HeapFree(GetProcessHeap(),0,filename);
Aric Stewart6269f002005-01-17 13:40:39 +00004550 msiobj_release(&row->hdr);
4551 }
4552 MSI_ViewClose(view);
4553 msiobj_release(&view->hdr);
4554 return rc;
4555}
4556
4557static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
4558{
4559 LPWSTR productcode;
Aric Stewart6269f002005-01-17 13:40:39 +00004560 UINT rc;
4561 DWORD i;
Aric Stewart68b07492005-01-25 11:05:37 +00004562 HKEY hkey=0;
4563 HKEY hukey=0;
Aric Stewart6269f002005-01-17 13:40:39 +00004564 static const WCHAR szProductCode[]=
4565 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart68b07492005-01-25 11:05:37 +00004566
Aric Stewart6269f002005-01-17 13:40:39 +00004567 if (!package)
4568 return ERROR_INVALID_HANDLE;
4569
4570 productcode = load_dynamic_property(package,szProductCode,&rc);
4571 if (!productcode)
4572 return rc;
4573
Aric Stewart68b07492005-01-25 11:05:37 +00004574 rc = MSIREG_OpenFeaturesKey(productcode,&hkey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00004575 if (rc != ERROR_SUCCESS)
4576 goto end;
4577
Aric Stewart68b07492005-01-25 11:05:37 +00004578 rc = MSIREG_OpenUserFeaturesKey(productcode,&hukey,TRUE);
Aric Stewart6269f002005-01-17 13:40:39 +00004579 if (rc != ERROR_SUCCESS)
4580 goto end;
4581
4582 /* here the guids are base 85 encoded */
4583 for (i = 0; i < package->loaded_features; i++)
4584 {
4585 LPWSTR data = NULL;
4586 GUID clsid;
4587 int j;
4588 INT size;
4589
4590 size = package->features[i].ComponentCount*21;
4591 size +=1;
4592 if (package->features[i].Feature_Parent[0])
4593 size += strlenW(package->features[i].Feature_Parent)+2;
4594
4595 data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
4596
4597 data[0] = 0;
4598 for (j = 0; j < package->features[i].ComponentCount; j++)
4599 {
4600 WCHAR buf[21];
4601 memset(buf,0,sizeof(buf));
4602 TRACE("From %s\n",debugstr_w(package->components
4603 [package->features[i].Components[j]].ComponentId));
4604 CLSIDFromString(package->components
4605 [package->features[i].Components[j]].ComponentId,
4606 &clsid);
4607 encode_base85_guid(&clsid,buf);
4608 TRACE("to %s\n",debugstr_w(buf));
4609 strcatW(data,buf);
4610 }
4611 if (package->features[i].Feature_Parent[0])
4612 {
4613 static const WCHAR sep[] = {'\2',0};
4614 strcatW(data,sep);
4615 strcatW(data,package->features[i].Feature_Parent);
4616 }
4617
Aric Stewart2cae30b2005-01-19 19:07:40 +00004618 size = (strlenW(data)+1)*sizeof(WCHAR);
Aric Stewart68b07492005-01-25 11:05:37 +00004619 RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ,
Aric Stewart6269f002005-01-17 13:40:39 +00004620 (LPSTR)data,size);
4621 HeapFree(GetProcessHeap(),0,data);
4622
4623 size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
Aric Stewart68b07492005-01-25 11:05:37 +00004624 RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
Aric Stewart6269f002005-01-17 13:40:39 +00004625 (LPSTR)package->features[i].Feature_Parent,size);
4626 }
4627
Aric Stewart6269f002005-01-17 13:40:39 +00004628end:
Aric Stewart6269f002005-01-17 13:40:39 +00004629 RegCloseKey(hkey);
4630 RegCloseKey(hukey);
Aric Stewart68b07492005-01-25 11:05:37 +00004631 HeapFree(GetProcessHeap(), 0, productcode);
Aric Stewart6269f002005-01-17 13:40:39 +00004632 return rc;
4633}
4634
Aric Stewart2cae30b2005-01-19 19:07:40 +00004635static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
4636{
Aric Stewart2cae30b2005-01-19 19:07:40 +00004637 static const WCHAR szProductCode[]=
4638 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart68b07492005-01-25 11:05:37 +00004639 HKEY hkey=0;
Aric Stewart2cae30b2005-01-19 19:07:40 +00004640 LPWSTR buffer;
4641 LPWSTR productcode;
4642 UINT rc,i;
4643 DWORD size;
4644 static WCHAR szNONE[] = {0};
4645 static const WCHAR szWindowsInstaler[] =
4646 {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0};
4647 static const WCHAR szPropKeys[][80] =
4648 {
4649{'A','R','P','A','U','T','H','O','R','I','Z','E','D','C','D','F','P','R','E','F','I','X',0},
4650{'A','R','P','C','O','N','T','A','C','T'},
4651{'A','R','P','C','O','M','M','E','N','T','S',0},
4652{'P','r','o','d','u','c','t','N','a','m','e',0},
4653{'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0},
4654{'A','R','P','H','E','L','P','L','I','N','K',0},
4655{'A','R','P','H','E','L','P','T','E','L','E','P','H','O','N','E',0},
4656{'A','R','P','I','N','S','T','A','L','L','L','O','C','A','T','I','O','N',0},
4657{'S','O','U','R','C','E','D','I','R',0},
4658{'M','a','n','u','f','a','c','t','u','r','e','r',0},
4659{'A','R','P','R','E','A','D','M','E',0},
4660{'A','R','P','S','I','Z','E',0},
4661{'A','R','P','U','R','L','I','N','F','O','A','B','O','U','T',0},
4662{'A','R','P','U','R','L','U','P','D','A','T','E','I','N','F','O',0},
4663{0},
4664 };
4665
4666 static const WCHAR szRegKeys[][80] =
4667 {
4668{'A','u','t','h','o','r','i','z','e','d','C','D','F','P','r','e','f','i','x',0},
4669{'C','o','n','t','a','c','t',0},
4670{'C','o','m','m','e','n','t','s',0},
4671{'D','i','s','p','l','a','y','N','a','m','e',0},
4672{'D','i','s','p','l','a','y','V','e','r','s','i','o','n',0},
4673{'H','e','l','p','L','i','n','k',0},
4674{'H','e','l','p','T','e','l','e','p','h','o','n','e',0},
4675{'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0},
4676{'I','n','s','t','a','l','l','S','o','u','r','c','e',0},
4677{'P','u','b','l','i','s','h','e','r',0},
4678{'R','e','a','d','m','e',0},
4679{'S','i','z','e',0},
4680{'U','R','L','I','n','f','o','A','b','o','u','t',0},
4681{'U','R','L','U','p','d','a','t','e','I','n','f','o',0},
4682{0},
4683 };
4684
4685 static const WCHAR path[] = {
4686 'C',':','\\','W','i','n','d','o','w','s','\\',
4687 'I','n','s','t','a','l','l','e','r','\\'};
4688 static const WCHAR fmt[] = {
4689 'C',':','\\','W','i','n','d','o','w','s','\\',
4690 'I','n','s','t','a','l','l','e','r','\\',
4691 '%','x','.','m','s','i',0};
4692 static const WCHAR szLocalPackage[]=
4693 {'L','o','c','a','l','P','a','c','k','a','g','e',0};
4694 WCHAR packagefile[MAX_PATH];
4695 INT num,start;
4696
4697 if (!package)
4698 return ERROR_INVALID_HANDLE;
4699
4700 productcode = load_dynamic_property(package,szProductCode,&rc);
4701 if (!productcode)
4702 return rc;
4703
Aric Stewart68b07492005-01-25 11:05:37 +00004704 rc = MSIREG_OpenUninstallKey(productcode,&hkey,TRUE);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004705 if (rc != ERROR_SUCCESS)
4706 goto end;
4707
4708 /* dump all the info i can grab */
4709 FIXME("Flesh out more information \n");
4710
4711 i = 0;
4712 while (szPropKeys[i][0]!=0)
4713 {
4714 buffer = load_dynamic_property(package,szPropKeys[i],&rc);
4715 if (rc != ERROR_SUCCESS)
4716 buffer = szNONE;
4717 size = strlenW(buffer)*sizeof(WCHAR);
Aric Stewart68b07492005-01-25 11:05:37 +00004718 RegSetValueExW(hkey,szRegKeys[i],0,REG_SZ,(LPSTR)buffer,size);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004719 i++;
4720 }
4721
4722 rc = 0x1;
4723 size = sizeof(rc);
Aric Stewart68b07492005-01-25 11:05:37 +00004724 RegSetValueExW(hkey,szWindowsInstaler,0,REG_DWORD,(LPSTR)&rc,size);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004725
4726 /* copy the package locally */
4727 num = GetTickCount() & 0xffff;
4728 if (!num)
4729 num = 1;
4730 start = num;
4731 sprintfW(packagefile,fmt,num);
4732 do
4733 {
4734 HANDLE handle = CreateFileW(packagefile,GENERIC_WRITE, 0, NULL,
4735 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
4736 if (handle != INVALID_HANDLE_VALUE)
4737 {
4738 CloseHandle(handle);
4739 break;
4740 }
4741 if (GetLastError() != ERROR_FILE_EXISTS &&
4742 GetLastError() != ERROR_SHARING_VIOLATION)
4743 break;
4744 if (!(++num & 0xffff)) num = 1;
4745 sprintfW(packagefile,fmt,num);
4746 } while (num != start);
4747
4748 create_full_pathW(path);
Aric Stewart54c67dd2005-01-25 20:17:09 +00004749 TRACE("Copying to local package %s\n",debugstr_w(packagefile));
Aric Stewart2cae30b2005-01-19 19:07:40 +00004750 CopyFileW(package->PackagePath,packagefile,FALSE);
Aric Stewart54c67dd2005-01-25 20:17:09 +00004751 size = strlenW(packagefile)*sizeof(WCHAR);
Aric Stewart68b07492005-01-25 11:05:37 +00004752 RegSetValueExW(hkey,szLocalPackage,0,REG_SZ,(LPSTR)packagefile,size);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004753
4754end:
4755 HeapFree(GetProcessHeap(),0,productcode);
4756 RegCloseKey(hkey);
Aric Stewart2cae30b2005-01-19 19:07:40 +00004757
4758 return ERROR_SUCCESS;
4759}
4760
4761static UINT ACTION_InstallExecute(MSIPACKAGE *package)
4762{
4763 int i;
4764 if (!package)
4765 return ERROR_INVALID_HANDLE;
4766
4767 for (i = 0; i < package->DeferredActionCount; i++)
4768 {
4769 LPWSTR action;
4770 action = package->DeferredAction[i];
4771 ui_actionstart(package, action);
4772 TRACE("Executing Action (%s)\n",debugstr_w(action));
4773 ACTION_CustomAction(package,action,TRUE);
4774 HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
4775 }
4776 HeapFree(GetProcessHeap(),0,package->DeferredAction);
4777
4778 package->DeferredActionCount = 0;
4779 package->DeferredAction = NULL;
4780
4781 return ERROR_SUCCESS;
4782}
4783
4784static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
4785{
4786 int i;
4787 if (!package)
4788 return ERROR_INVALID_HANDLE;
4789
Aric Stewart54c67dd2005-01-25 20:17:09 +00004790 /* first do the same as an InstallExecute */
4791 ACTION_InstallExecute(package);
4792
4793 /* then handle Commit Actions */
Aric Stewart2cae30b2005-01-19 19:07:40 +00004794 for (i = 0; i < package->CommitActionCount; i++)
4795 {
4796 LPWSTR action;
4797 action = package->CommitAction[i];
4798 ui_actionstart(package, action);
4799 TRACE("Executing Commit Action (%s)\n",debugstr_w(action));
4800 ACTION_CustomAction(package,action,TRUE);
4801 HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
4802 }
4803 HeapFree(GetProcessHeap(),0,package->CommitAction);
4804
4805 package->CommitActionCount = 0;
4806 package->CommitAction = NULL;
4807
4808 return ERROR_SUCCESS;
4809}
4810
4811static UINT ACTION_ForceReboot(MSIPACKAGE *package)
4812{
4813 static const WCHAR RunOnce[] = {
4814 'S','o','f','t','w','a','r','e','\\',
4815 'M','i','c','r','o','s','o','f','t','\\',
4816 'W','i','n','d','o','w','s','\\',
4817 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4818 'R','u','n','O','n','c','e'};
4819 static const WCHAR InstallRunOnce[] = {
4820 'S','o','f','t','w','a','r','e','\\',
4821 'M','i','c','r','o','s','o','f','t','\\',
4822 'W','i','n','d','o','w','s','\\',
4823 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4824 'I','n','s','t','a','l','l','e','r','\\',
4825 'R','u','n','O','n','c','e','E','n','t','r','i','e','s'};
4826
4827 static const WCHAR msiexec_fmt[] = {
4828 'C',':','\\','W','i','n','d','o','w','s','\\','S','y','s','t','e','m',
4829 '\\','M','s','i','E','x','e','c','.','e','x','e',' ','/','@',' ',
4830 '\"','%','s','\"',0};
4831 static const WCHAR install_fmt[] = {
4832 '/','I',' ','\"','%','s','\"',' ',
4833 'A','F','T','E','R','R','E','B','O','O','T','=','1',' ',
4834 'R','U','N','O','N','C','E','E','N','T','R','Y','=','\"','%','s','\"',0};
4835 WCHAR buffer[256];
Aric Stewart68b07492005-01-25 11:05:37 +00004836 HKEY hkey,hukey;
Aric Stewart2cae30b2005-01-19 19:07:40 +00004837 LPWSTR productcode;
4838 WCHAR squished_pc[100];
4839 INT rc;
4840 DWORD size;
4841 static const WCHAR szProductCode[]=
4842 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart68b07492005-01-25 11:05:37 +00004843 static const WCHAR szLUS[] = {
4844 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
4845 static const WCHAR szSourceList[] = {
4846 'S','o','u','r','c','e','L','i','s','t',0};
4847 static const WCHAR szPackageName[] = {
4848 'P','a','c','k','a','g','e','N','a','m','e',0};
Aric Stewart2cae30b2005-01-19 19:07:40 +00004849
4850 if (!package)
4851 return ERROR_INVALID_HANDLE;
4852
4853 productcode = load_dynamic_property(package,szProductCode,&rc);
4854 if (!productcode)
4855 return rc;
4856
4857 squash_guid(productcode,squished_pc);
4858
4859 RegCreateKeyW(HKEY_LOCAL_MACHINE,RunOnce,&hkey);
4860 sprintfW(buffer,msiexec_fmt,squished_pc);
4861
4862 size = strlenW(buffer)*sizeof(WCHAR);
4863 RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
4864 RegCloseKey(hkey);
4865
4866 TRACE("Reboot command %s\n",debugstr_w(buffer));
4867
4868 RegCreateKeyW(HKEY_LOCAL_MACHINE,InstallRunOnce,&hkey);
4869 sprintfW(buffer,install_fmt,productcode,squished_pc);
4870 RegSetValueExW(hkey,squished_pc,0,REG_SZ,(LPSTR)buffer,size);
4871 RegCloseKey(hkey);
4872
Aric Stewart68b07492005-01-25 11:05:37 +00004873 rc = MSIREG_OpenUserProductsKey(productcode,&hukey,TRUE);
4874 if (rc == ERROR_SUCCESS)
4875 {
4876 HKEY hukey2;
4877 LPWSTR buf;
4878 RegCreateKeyW(hukey, szSourceList, &hukey2);
4879 buf = load_dynamic_property(package,cszSourceDir,NULL);
4880 size = strlenW(buf)*sizeof(WCHAR);
4881 RegSetValueExW(hukey2,szLUS,0,REG_SZ,(LPSTR)buf,size);
4882 HeapFree(GetProcessHeap(),0,buf);
4883
4884 buf = strrchrW(package->PackagePath,'\\');
4885 if (buf)
4886 {
4887 buf++;
4888 size = strlenW(buf)*sizeof(WCHAR);
4889 RegSetValueExW(hukey2,szPackageName,0,REG_SZ,(LPSTR)buf,size);
4890 }
4891
4892 RegCloseKey(hukey2);
4893 }
Aric Stewart2cae30b2005-01-19 19:07:40 +00004894 HeapFree(GetProcessHeap(),0,productcode);
4895
Aric Stewart68b07492005-01-25 11:05:37 +00004896 return ERROR_INSTALL_SUSPEND;
Aric Stewart2cae30b2005-01-19 19:07:40 +00004897}
4898
Mike McCormack3ece2462004-07-09 19:33:25 +00004899/* Msi functions that seem appropriate here */
Aric Stewarte95136b2004-06-29 03:44:01 +00004900UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
4901{
4902 LPWSTR szwAction;
Aric Stewarta3149f82004-07-09 19:38:40 +00004903 UINT rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00004904
4905 TRACE(" exteral attempt at action %s\n",szAction);
4906
4907 if (!szAction)
4908 return ERROR_FUNCTION_FAILED;
4909 if (hInstall == 0)
4910 return ERROR_FUNCTION_FAILED;
4911
Aric Stewarta3149f82004-07-09 19:38:40 +00004912 szwAction = strdupAtoW(szAction);
Aric Stewarte95136b2004-06-29 03:44:01 +00004913
4914 if (!szwAction)
4915 return ERROR_FUNCTION_FAILED;
4916
Aric Stewarte95136b2004-06-29 03:44:01 +00004917
4918 rc = MsiDoActionW(hInstall, szwAction);
4919 HeapFree(GetProcessHeap(),0,szwAction);
4920 return rc;
4921}
4922
4923UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
4924{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004925 MSIPACKAGE *package;
4926 UINT ret = ERROR_INVALID_HANDLE;
4927
Mike McCormack3ece2462004-07-09 19:33:25 +00004928 TRACE(" external attempt at action %s \n",debugstr_w(szAction));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004929
4930 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4931 if( package )
4932 {
4933 ret = ACTION_PerformAction(package,szAction);
4934 msiobj_release( &package->hdr );
4935 }
4936 return ret;
Aric Stewarte95136b2004-06-29 03:44:01 +00004937}
4938
4939UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
4940 LPSTR szPathBuf, DWORD* pcchPathBuf)
4941{
4942 LPWSTR szwFolder;
4943 LPWSTR szwPathBuf;
Aric Stewarta3149f82004-07-09 19:38:40 +00004944 UINT rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00004945
4946 TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
4947
4948 if (!szFolder)
4949 return ERROR_FUNCTION_FAILED;
4950 if (hInstall == 0)
4951 return ERROR_FUNCTION_FAILED;
4952
Aric Stewarta3149f82004-07-09 19:38:40 +00004953 szwFolder = strdupAtoW(szFolder);
Aric Stewarte95136b2004-06-29 03:44:01 +00004954
4955 if (!szwFolder)
4956 return ERROR_FUNCTION_FAILED;
4957
4958 szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
4959
Aric Stewarte95136b2004-06-29 03:44:01 +00004960 rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
4961
4962 WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
4963 *pcchPathBuf, NULL, NULL );
4964
4965 HeapFree(GetProcessHeap(),0,szwFolder);
4966 HeapFree(GetProcessHeap(),0,szwPathBuf);
4967
4968 return rc;
4969}
4970
4971UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
4972 szPathBuf, DWORD* pcchPathBuf)
4973{
Mike McCormackba8200b2004-12-22 15:25:30 +00004974 LPWSTR path;
4975 UINT rc = ERROR_FUNCTION_FAILED;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004976 MSIPACKAGE *package;
Aric Stewartbdb29552004-07-04 00:32:48 +00004977
Aric Stewarte95136b2004-06-29 03:44:01 +00004978 TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
Aric Stewartbdb29552004-07-04 00:32:48 +00004979
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004980 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
Mike McCormackba8200b2004-12-22 15:25:30 +00004981 if (!package)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004982 return ERROR_INVALID_HANDLE;
Mike McCormackba8200b2004-12-22 15:25:30 +00004983 path = resolve_folder(package, szFolder, FALSE, FALSE, NULL);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004984 msiobj_release( &package->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00004985
Mike McCormackba8200b2004-12-22 15:25:30 +00004986 if (path && (strlenW(path) > *pcchPathBuf))
Aric Stewartbdb29552004-07-04 00:32:48 +00004987 {
4988 *pcchPathBuf = strlenW(path)+1;
Mike McCormackba8200b2004-12-22 15:25:30 +00004989 rc = ERROR_MORE_DATA;
Aric Stewartbdb29552004-07-04 00:32:48 +00004990 }
Aric Stewartfa384f62004-12-22 18:46:17 +00004991 else if (path)
Aric Stewartbdb29552004-07-04 00:32:48 +00004992 {
4993 *pcchPathBuf = strlenW(path)+1;
4994 strcpyW(szPathBuf,path);
4995 TRACE("Returning Path %s\n",debugstr_w(path));
Aric Stewartfa384f62004-12-22 18:46:17 +00004996 rc = ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00004997 }
Mike McCormackba8200b2004-12-22 15:25:30 +00004998 HeapFree(GetProcessHeap(),0,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00004999
5000 return rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00005001}
Aric Stewart401bd3f2004-06-28 20:34:35 +00005002
5003
Aric Stewart6e160f12004-06-29 04:07:22 +00005004UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
5005 LPSTR szPathBuf, DWORD* pcchPathBuf)
5006{
5007 LPWSTR szwFolder;
5008 LPWSTR szwPathBuf;
Aric Stewarta3149f82004-07-09 19:38:40 +00005009 UINT rc;
Aric Stewart6e160f12004-06-29 04:07:22 +00005010
5011 TRACE("getting source %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
5012
5013 if (!szFolder)
5014 return ERROR_FUNCTION_FAILED;
5015 if (hInstall == 0)
5016 return ERROR_FUNCTION_FAILED;
5017
Aric Stewarta3149f82004-07-09 19:38:40 +00005018 szwFolder = strdupAtoW(szFolder);
Aric Stewart6e160f12004-06-29 04:07:22 +00005019 if (!szwFolder)
5020 return ERROR_FUNCTION_FAILED;
5021
5022 szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
5023
Aric Stewart6e160f12004-06-29 04:07:22 +00005024 rc = MsiGetSourcePathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
5025
5026 WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
5027 *pcchPathBuf, NULL, NULL );
5028
5029 HeapFree(GetProcessHeap(),0,szwFolder);
5030 HeapFree(GetProcessHeap(),0,szwPathBuf);
5031
5032 return rc;
5033}
5034
5035UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
5036 szPathBuf, DWORD* pcchPathBuf)
5037{
Mike McCormackba8200b2004-12-22 15:25:30 +00005038 LPWSTR path;
5039 UINT rc = ERROR_FUNCTION_FAILED;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005040 MSIPACKAGE *package;
Aric Stewart6e160f12004-06-29 04:07:22 +00005041
5042 TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005043
5044 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
5045 if( !package )
5046 return ERROR_INVALID_HANDLE;
Mike McCormackba8200b2004-12-22 15:25:30 +00005047 path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005048 msiobj_release( &package->hdr );
Aric Stewart6e160f12004-06-29 04:07:22 +00005049
Mike McCormackba8200b2004-12-22 15:25:30 +00005050 if (path && strlenW(path) > *pcchPathBuf)
Aric Stewart6e160f12004-06-29 04:07:22 +00005051 {
Aric Stewartbdb29552004-07-04 00:32:48 +00005052 *pcchPathBuf = strlenW(path)+1;
Aric Stewartfa384f62004-12-22 18:46:17 +00005053 rc = ERROR_MORE_DATA;
Aric Stewart6e160f12004-06-29 04:07:22 +00005054 }
Aric Stewartfa384f62004-12-22 18:46:17 +00005055 else if (path)
Aric Stewartbdb29552004-07-04 00:32:48 +00005056 {
5057 *pcchPathBuf = strlenW(path)+1;
5058 strcpyW(szPathBuf,path);
5059 TRACE("Returning Path %s\n",debugstr_w(path));
Aric Stewartfa384f62004-12-22 18:46:17 +00005060 rc = ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00005061 }
Aric Stewartfa384f62004-12-22 18:46:17 +00005062 HeapFree(GetProcessHeap(),0,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00005063
Aric Stewart6e160f12004-06-29 04:07:22 +00005064 return rc;
5065}
5066
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005067
5068UINT WINAPI MsiSetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder,
5069 LPCSTR szFolderPath)
5070{
5071 LPWSTR szwFolder;
5072 LPWSTR szwFolderPath;
Aric Stewarta3149f82004-07-09 19:38:40 +00005073 UINT rc;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005074
5075 if (!szFolder)
5076 return ERROR_FUNCTION_FAILED;
5077 if (hInstall == 0)
5078 return ERROR_FUNCTION_FAILED;
5079
Aric Stewarta3149f82004-07-09 19:38:40 +00005080 szwFolder = strdupAtoW(szFolder);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005081 if (!szwFolder)
5082 return ERROR_FUNCTION_FAILED;
5083
Aric Stewarta3149f82004-07-09 19:38:40 +00005084 szwFolderPath = strdupAtoW(szFolderPath);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005085 if (!szwFolderPath)
5086 {
5087 HeapFree(GetProcessHeap(),0,szwFolder);
5088 return ERROR_FUNCTION_FAILED;
5089 }
5090
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005091 rc = MsiSetTargetPathW(hInstall, szwFolder, szwFolderPath);
5092
5093 HeapFree(GetProcessHeap(),0,szwFolder);
5094 HeapFree(GetProcessHeap(),0,szwFolderPath);
5095
5096 return rc;
5097}
5098
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005099UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005100 LPCWSTR szFolderPath)
5101{
Mike McCormack4604e662004-08-06 17:30:20 +00005102 DWORD i;
Mike McCormackba8200b2004-12-22 15:25:30 +00005103 LPWSTR path = NULL;
Aric Stewart4e553432005-01-04 20:47:20 +00005104 LPWSTR path2 = NULL;
Aric Stewart6296de32005-01-03 16:06:44 +00005105 INT len;
Aric Stewarte2d4ea82004-07-04 00:33:45 +00005106 MSIFOLDER *folder;
Aric Stewartbdb29552004-07-04 00:32:48 +00005107
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005108 TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
5109
5110 if (package==NULL)
5111 return ERROR_INVALID_HANDLE;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005112
Aric Stewartbdb29552004-07-04 00:32:48 +00005113 if (szFolderPath[0]==0)
5114 return ERROR_FUNCTION_FAILED;
5115
Aric Stewarte2d4ea82004-07-04 00:33:45 +00005116 if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES)
5117 return ERROR_FUNCTION_FAILED;
5118
Mike McCormackba8200b2004-12-22 15:25:30 +00005119 path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
Aric Stewart4e553432005-01-04 20:47:20 +00005120
Mike McCormackba8200b2004-12-22 15:25:30 +00005121 if (!path)
Aric Stewarte2d4ea82004-07-04 00:33:45 +00005122 return ERROR_INVALID_PARAMETER;
Aric Stewart4e553432005-01-04 20:47:20 +00005123
Michael Stefaniucb9374072005-01-20 10:36:35 +00005124 HeapFree(GetProcessHeap(),0,folder->Property);
Aric Stewarte2d4ea82004-07-04 00:33:45 +00005125
Aric Stewart6296de32005-01-03 16:06:44 +00005126 len = strlenW(szFolderPath);
5127
5128 if (szFolderPath[len-1]!='\\')
5129 {
5130 len +=2;
5131 folder->Property = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
5132 strcpyW(folder->Property,szFolderPath);
5133 strcatW(folder->Property,cszbs);
5134 }
5135 else
5136 folder->Property = dupstrW(szFolderPath);
Aric Stewartbdb29552004-07-04 00:32:48 +00005137
Aric Stewart4e553432005-01-04 20:47:20 +00005138 if (strcmpiW(path, szFolderPath) == 0)
Mike McCormackba8200b2004-12-22 15:25:30 +00005139 {
Aric Stewart4e553432005-01-04 20:47:20 +00005140 /*
5141 * Resolved Target has not really changed, so just
5142 * set this folder and do not recalculate everything.
5143 */
5144 HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);
5145 folder->ResolvedTarget = NULL;
5146 path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
5147 HeapFree(GetProcessHeap(),0,path2);
Mike McCormackba8200b2004-12-22 15:25:30 +00005148 }
Aric Stewart4e553432005-01-04 20:47:20 +00005149 else
5150 {
5151 for (i = 0; i < package->loaded_folders; i++)
5152 {
Michael Stefaniucb9374072005-01-20 10:36:35 +00005153 HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
Aric Stewart4e553432005-01-04 20:47:20 +00005154 package->folders[i].ResolvedTarget=NULL;
5155 }
5156
5157 for (i = 0; i < package->loaded_folders; i++)
5158 {
5159 path2=resolve_folder(package, package->folders[i].Directory, FALSE,
5160 TRUE, NULL);
5161 HeapFree(GetProcessHeap(),0,path2);
5162 }
5163 }
5164 HeapFree(GetProcessHeap(),0,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00005165
5166 return ERROR_SUCCESS;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00005167}
5168
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005169UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
5170 LPCWSTR szFolderPath)
5171{
5172 MSIPACKAGE *package;
5173 UINT ret;
5174
5175 TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
5176
5177 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
5178 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
5179 msiobj_release( &package->hdr );
5180 return ret;
5181}
5182
Vitaly Lipatov5c4116b2004-12-16 14:29:25 +00005183/***********************************************************************
5184 * MsiGetMode (MSI.@)
5185 *
5186 * Returns an internal installer state (if it is running in a mode iRunMode)
5187 *
5188 * PARAMS
5189 * hInstall [I] Handle to the installation
5190 * hRunMode [I] Checking run mode
5191 * MSIRUNMODE_ADMIN Administrative mode
5192 * MSIRUNMODE_ADVERTISE Advertisement mode
5193 * MSIRUNMODE_MAINTENANCE Maintenance mode
5194 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
5195 * MSIRUNMODE_LOGENABLED Log file is writing
5196 * MSIRUNMODE_OPERATIONS Operations in progress??
5197 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
5198 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
5199 * MSIRUNMODE_CABINET Files from cabinet are installed
5200 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is supressed
5201 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is supressed
5202 * MSIRUNMODE_RESERVED11 Reserved
5203 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
5204 * MSIRUNMODE_ZAWENABLED Demand installation is supported
5205 * MSIRUNMODE_RESERVED14 Reserved
5206 * MSIRUNMODE_RESERVED15 Reserved
5207 * MSIRUNMODE_SCHEDULED called from install script
5208 * MSIRUNMODE_ROLLBACK called from rollback script
5209 * MSIRUNMODE_COMMIT called from commit script
5210 *
5211 * RETURNS
5212 * In the state: TRUE
5213 * Not in the state: FALSE
5214 *
5215 */
5216
5217BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
Aric Stewart6e160f12004-06-29 04:07:22 +00005218{
Vitaly Lipatov5c4116b2004-12-16 14:29:25 +00005219 FIXME("STUB (iRunMode=%i)\n",iRunMode);
5220 return TRUE;
Aric Stewart6e160f12004-06-29 04:07:22 +00005221}
5222
Aric Stewarta3149f82004-07-09 19:38:40 +00005223/*
Aric Stewartd906ef02004-10-22 22:06:31 +00005224 * According to the docs, when this is called it immediately recalculates
5225 * all the component states as well
Aric Stewarta3149f82004-07-09 19:38:40 +00005226 */
5227UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
5228 INSTALLSTATE iState)
5229{
5230 LPWSTR szwFeature = NULL;
5231 UINT rc;
5232
5233 szwFeature = strdupAtoW(szFeature);
5234
5235 if (!szwFeature)
5236 return ERROR_FUNCTION_FAILED;
5237
5238 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
5239
5240 HeapFree(GetProcessHeap(),0,szwFeature);
5241
5242 return rc;
5243}
5244
5245UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
5246 INSTALLSTATE iState)
5247{
5248 MSIPACKAGE* package;
5249 INT index;
5250
5251 TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
5252
5253 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
5254 if (!package)
5255 return ERROR_INVALID_HANDLE;
5256
5257 index = get_loaded_feature(package,szFeature);
5258 if (index < 0)
5259 return ERROR_UNKNOWN_FEATURE;
5260
Aric Stewartfbdd7092004-12-27 19:06:22 +00005261 package->features[index].ActionRequest= iState;
Aric Stewarta3149f82004-07-09 19:38:40 +00005262
5263 return ERROR_SUCCESS;
5264}
5265
5266UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
5267 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
5268{
5269 LPWSTR szwFeature = NULL;
5270 UINT rc;
5271
5272 szwFeature = strdupAtoW(szFeature);
5273
5274 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
5275
5276 HeapFree( GetProcessHeap(), 0 , szwFeature);
5277
5278 return rc;
5279}
5280
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005281UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
Aric Stewarta3149f82004-07-09 19:38:40 +00005282 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
5283{
Aric Stewarta3149f82004-07-09 19:38:40 +00005284 INT index;
5285
Aric Stewarta3149f82004-07-09 19:38:40 +00005286 index = get_loaded_feature(package,szFeature);
5287 if (index < 0)
5288 return ERROR_UNKNOWN_FEATURE;
5289
5290 if (piInstalled)
Aric Stewartfbdd7092004-12-27 19:06:22 +00005291 *piInstalled = package->features[index].Installed;
Aric Stewarta3149f82004-07-09 19:38:40 +00005292
5293 if (piAction)
Aric Stewartfbdd7092004-12-27 19:06:22 +00005294 *piAction = package->features[index].Action;
5295
Aric Stewartae1aa322004-12-27 19:02:59 +00005296 TRACE("returning %i %i\n",*piInstalled,*piAction);
Aric Stewarta3149f82004-07-09 19:38:40 +00005297
5298 return ERROR_SUCCESS;
5299}
5300
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005301UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
5302 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
5303{
5304 MSIPACKAGE* package;
5305 UINT ret;
5306
5307 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
5308piAction);
5309
5310 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
5311 if (!package)
5312 return ERROR_INVALID_HANDLE;
5313 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
5314 msiobj_release( &package->hdr );
5315 return ret;
5316}
5317
Aric Stewarta3149f82004-07-09 19:38:40 +00005318UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
5319 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
5320{
5321 LPWSTR szwComponent= NULL;
5322 UINT rc;
5323
5324 szwComponent= strdupAtoW(szComponent);
5325
5326 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
5327
5328 HeapFree( GetProcessHeap(), 0 , szwComponent);
5329
5330 return rc;
5331}
5332
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005333UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
Aric Stewarta3149f82004-07-09 19:38:40 +00005334 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
5335{
Aric Stewarta3149f82004-07-09 19:38:40 +00005336 INT index;
5337
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005338 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
Aric Stewarta3149f82004-07-09 19:38:40 +00005339piAction);
5340
Aric Stewarta3149f82004-07-09 19:38:40 +00005341 index = get_loaded_component(package,szComponent);
5342 if (index < 0)
5343 return ERROR_UNKNOWN_COMPONENT;
5344
5345 if (piInstalled)
Aric Stewartfbdd7092004-12-27 19:06:22 +00005346 *piInstalled = package->components[index].Installed;
Aric Stewarta3149f82004-07-09 19:38:40 +00005347
5348 if (piAction)
Aric Stewartfbdd7092004-12-27 19:06:22 +00005349 *piInstalled = package->components[index].Action;
Aric Stewarta3149f82004-07-09 19:38:40 +00005350
5351 return ERROR_SUCCESS;
5352}
5353
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005354UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
5355 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
Aric Stewart401bd3f2004-06-28 20:34:35 +00005356{
Aric Stewart8f0a7612004-07-06 18:53:11 +00005357 MSIPACKAGE* package;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005358 UINT ret;
Aric Stewart401bd3f2004-06-28 20:34:35 +00005359
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005360 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
5361 piInstalled, piAction);
5362
5363 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
Aric Stewart8f0a7612004-07-06 18:53:11 +00005364 if (!package)
5365 return ERROR_INVALID_HANDLE;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005366 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
5367 msiobj_release( &package->hdr );
5368 return ret;
5369}
Aric Stewart8f0a7612004-07-06 18:53:11 +00005370
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005371#if 0
5372static UINT ACTION_Template(MSIPACKAGE *package)
5373{
5374 UINT rc;
5375 MSIQUERY * view;
5376 MSIRECORD * row = 0;
5377 static const WCHAR ExecSeqQuery[] = {0};
Aric Stewarteb0e0df2004-06-30 19:38:36 +00005378
Aric Stewart6269f002005-01-17 13:40:39 +00005379 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005380 if (rc != ERROR_SUCCESS)
5381 return rc;
5382
Aric Stewart6269f002005-01-17 13:40:39 +00005383 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005384 if (rc != ERROR_SUCCESS)
5385 {
Aric Stewart6269f002005-01-17 13:40:39 +00005386 MSI_ViewClose(view);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005387 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005388 return rc;
5389 }
5390
5391 while (1)
5392 {
Aric Stewart6269f002005-01-17 13:40:39 +00005393 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005394 if (rc != ERROR_SUCCESS)
5395 {
5396 rc = ERROR_SUCCESS;
5397 break;
5398 }
5399
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005400 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005401 }
Aric Stewart6269f002005-01-17 13:40:39 +00005402 MSI_ViewClose(view);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005403 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005404 return rc;
5405}
5406#endif