blob: b6eef69b41e88c852482d60723a1413fbd0dd9d0 [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 Stewart401bd3f2004-06-28 20:34:35 +000051
52#define CUSTOM_ACTION_TYPE_MASK 0x3F
53
Aric Stewart401bd3f2004-06-28 20:34:35 +000054WINE_DEFAULT_DEBUG_CHANNEL(msi);
55
Aric Stewartbdb29552004-07-04 00:32:48 +000056typedef struct tagMSIFEATURE
57{
58 WCHAR Feature[96];
59 WCHAR Feature_Parent[96];
60 WCHAR Title[0x100];
61 WCHAR Description[0x100];
62 INT Display;
63 INT Level;
64 WCHAR Directory[96];
65 INT Attributes;
66
67 INSTALLSTATE State;
Aric Stewarta3149f82004-07-09 19:38:40 +000068 BOOL Enabled;
Aric Stewartbdb29552004-07-04 00:32:48 +000069 INT ComponentCount;
Aric Stewartec688fb2004-07-04 00:35:52 +000070 INT Components[1024]; /* yes hardcoded limit.... I am bad */
71 INT Cost;
Aric Stewartbdb29552004-07-04 00:32:48 +000072} MSIFEATURE;
73
74typedef struct tagMSICOMPONENT
75{
76 WCHAR Component[96];
77 WCHAR ComponentId[96];
78 WCHAR Directory[96];
79 INT Attributes;
80 WCHAR Condition[0x100];
81 WCHAR KeyPath[96];
82
83 INSTALLSTATE State;
Aric Stewart7d3e5972004-07-04 00:36:58 +000084 BOOL FeatureState;
Aric Stewartbdb29552004-07-04 00:32:48 +000085 BOOL Enabled;
Aric Stewartec688fb2004-07-04 00:35:52 +000086 INT Cost;
Mike McCormack24e9a342004-07-06 18:56:12 +000087} MSICOMPONENT;
Aric Stewartbdb29552004-07-04 00:32:48 +000088
89typedef struct tagMSIFOLDER
90{
Mike McCormackba8200b2004-12-22 15:25:30 +000091 LPWSTR Directory;
92 LPWSTR TargetDefault;
93 LPWSTR SourceDefault;
Aric Stewartbdb29552004-07-04 00:32:48 +000094
Mike McCormackba8200b2004-12-22 15:25:30 +000095 LPWSTR ResolvedTarget;
96 LPWSTR ResolvedSource;
97 LPWSTR Property; /* initially set property */
Aric Stewartbdb29552004-07-04 00:32:48 +000098 INT ParentIndex;
99 INT State;
100 /* 0 = uninitialized */
101 /* 1 = existing */
102 /* 2 = created remove if empty */
103 /* 3 = created persist if empty */
Aric Stewartec688fb2004-07-04 00:35:52 +0000104 INT Cost;
105 INT Space;
Aric Stewartbdb29552004-07-04 00:32:48 +0000106}MSIFOLDER;
107
Aric Stewartec688fb2004-07-04 00:35:52 +0000108typedef struct tagMSIFILE
109{
Mike McCormack9db0e072004-12-22 15:05:07 +0000110 LPWSTR File;
Aric Stewartec688fb2004-07-04 00:35:52 +0000111 INT ComponentIndex;
Mike McCormack9db0e072004-12-22 15:05:07 +0000112 LPWSTR FileName;
Aric Stewartec688fb2004-07-04 00:35:52 +0000113 INT FileSize;
Mike McCormack9db0e072004-12-22 15:05:07 +0000114 LPWSTR Version;
115 LPWSTR Language;
Aric Stewartec688fb2004-07-04 00:35:52 +0000116 INT Attributes;
117 INT Sequence;
118
119 INT State;
120 /* 0 = uninitialize */
121 /* 1 = not present */
122 /* 2 = present but replace */
123 /* 3 = present do not replace */
124 /* 4 = Installed */
Aric Stewartfa384f62004-12-22 18:46:17 +0000125 LPWSTR SourcePath;
Mike McCormackba8200b2004-12-22 15:25:30 +0000126 LPWSTR TargetPath;
Aric Stewartec688fb2004-07-04 00:35:52 +0000127 BOOL Temporary;
128}MSIFILE;
129
Aric Stewart401bd3f2004-06-28 20:34:35 +0000130/*
131 * Prototypes
132 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000133static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
134static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000135
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000136UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
Aric Stewart5b936ca2004-07-06 18:47:09 +0000137
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000138static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
139static UINT ACTION_CostInitialize(MSIPACKAGE *package);
140static UINT ACTION_CreateFolders(MSIPACKAGE *package);
141static UINT ACTION_CostFinalize(MSIPACKAGE *package);
142static UINT ACTION_FileCost(MSIPACKAGE *package);
143static UINT ACTION_InstallFiles(MSIPACKAGE *package);
144static UINT ACTION_DuplicateFiles(MSIPACKAGE *package);
145static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package);
146static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action);
147static UINT ACTION_InstallInitialize(MSIPACKAGE *package);
148static UINT ACTION_InstallValidate(MSIPACKAGE *package);
149static UINT ACTION_ProcessComponents(MSIPACKAGE *package);
150static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package);
151static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
152static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
153static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
154static UINT ACTION_PublishProduct(MSIPACKAGE *package);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000155
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000156static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source,
Aric Stewartc75201f2004-06-29 04:04:13 +0000157 const LPWSTR target, const INT type);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000158static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source,
Aric Stewartc75201f2004-06-29 04:04:13 +0000159 const LPWSTR target, const INT type);
Aric Stewart1282d7a2004-11-03 22:16:53 +0000160static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
161 const LPWSTR target, const INT type);
162static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,
163 const LPWSTR target, const INT type);
164static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
165 const LPWSTR target, const INT type);
Aric Stewartc75201f2004-06-29 04:04:13 +0000166
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000167static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);
Mike McCormackba8200b2004-12-22 15:25:30 +0000168static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
Aric Stewartbdb29552004-07-04 00:32:48 +0000169 BOOL source, BOOL set_prop, MSIFOLDER **folder);
170
Mike McCormack4604e662004-08-06 17:30:20 +0000171static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
Aric Stewartec688fb2004-07-04 00:35:52 +0000172
Aric Stewart401bd3f2004-06-28 20:34:35 +0000173/*
174 * consts and values used
175 */
176static const WCHAR cszSourceDir[] = {'S','o','u','r','c','e','D','i','r',0};
177static const WCHAR cszRootDrive[] = {'R','O','O','T','D','R','I','V','E',0};
178static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
Aric Stewartbdb29552004-07-04 00:32:48 +0000179static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
180static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
Aric Stewarteb0e0df2004-06-30 19:38:36 +0000181static const WCHAR c_collen[] = {'C',':','\\',0};
182
Aric Stewart401bd3f2004-06-28 20:34:35 +0000183static const WCHAR cszlsb[]={'[',0};
184static const WCHAR cszrsb[]={']',0};
185static const WCHAR cszbs[]={'\\',0};
186
Aric Stewartd2c395a2004-07-06 18:48:15 +0000187const static WCHAR szCreateFolders[] =
188 {'C','r','e','a','t','e','F','o','l','d','e','r','s',0};
189const static WCHAR szCostFinalize[] =
190 {'C','o','s','t','F','i','n','a','l','i','z','e',0};
191const static WCHAR szInstallFiles[] =
192 {'I','n','s','t','a','l','l','F','i','l','e','s',0};
193const static WCHAR szDuplicateFiles[] =
194 {'D','u','p','l','i','c','a','t','e','F','i','l','e','s',0};
195const static WCHAR szWriteRegistryValues[] =
196{'W','r','i','t','e','R','e','g','i','s','t','r','y','V','a','l','u','e','s',0};
197const static WCHAR szCostInitialize[] =
198 {'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0};
199const static WCHAR szFileCost[] = {'F','i','l','e','C','o','s','t',0};
200const static WCHAR szInstallInitialize[] =
201 {'I','n','s','t','a','l','l','I','n','i','t','i','a','l','i','z','e',0};
202const static WCHAR szInstallValidate[] =
203 {'I','n','s','t','a','l','l','V','a','l','i','d','a','t','e',0};
204const static WCHAR szLaunchConditions[] =
205 {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
Aric Stewartb942e182004-07-06 18:50:02 +0000206const static WCHAR szProcessComponents[] =
207 {'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 +0000208const static WCHAR szRegisterTypeLibraries[] =
209{'R','e','g','i','s','t','e','r','T','y','p','e','L','i','b','r','a','r',
210'i','e','s',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +0000211const static WCHAR szRegisterClassInfo[] =
212{'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
213const static WCHAR szRegisterProgIdInfo[] =
214{'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 +0000215const static WCHAR szCreateShortcuts[] =
216{'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
217const static WCHAR szPublishProduct[] =
218{'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +0000219
220/********************************************************
221 * helper functions to get around current HACKS and such
222 ********************************************************/
Aric Stewartec688fb2004-07-04 00:35:52 +0000223inline static void reduce_to_longfilename(WCHAR* filename)
224{
Mike McCormack9db0e072004-12-22 15:05:07 +0000225 LPWSTR p = strchrW(filename,'|');
226 if (p)
227 memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR));
Aric Stewartec688fb2004-07-04 00:35:52 +0000228}
229
Aric Stewartc75201f2004-06-29 04:04:13 +0000230inline static char *strdupWtoA( const WCHAR *str )
231{
232 char *ret = NULL;
233 if (str)
234 {
235 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL
236);
237 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
238 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
239 }
240 return ret;
241}
Aric Stewart401bd3f2004-06-28 20:34:35 +0000242
Aric Stewarta3149f82004-07-09 19:38:40 +0000243inline static WCHAR *strdupAtoW( const char *str )
244{
245 WCHAR *ret = NULL;
246 if (str)
247 {
248 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
249 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
250 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
251 }
252 return ret;
253}
254
Aric Stewartfa384f62004-12-22 18:46:17 +0000255static LPWSTR dupstrW(LPCWSTR src)
256{
257 LPWSTR dest;
258 if (!src) return NULL;
259 dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR));
260 strcpyW(dest, src);
261 return dest;
262}
263
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000264inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index)
Aric Stewart7231a432004-07-09 19:26:30 +0000265{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000266 UINT rc;
Aric Stewart7231a432004-07-09 19:26:30 +0000267 DWORD sz;
268 LPWSTR ret;
269
270 sz = 0;
Aric Stewartfa384f62004-12-22 18:46:17 +0000271 if (MSI_RecordIsNull(row,index))
Aric Stewart7231a432004-07-09 19:26:30 +0000272 return NULL;
273
Aric Stewartfa384f62004-12-22 18:46:17 +0000274 rc = MSI_RecordGetStringW(row,index,NULL,&sz);
275
276 /* having an empty string is different than NULL */
277 if (sz == 0)
278 {
279 ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR));
280 ret[0] = 0;
281 return ret;
282 }
283
Aric Stewart7231a432004-07-09 19:26:30 +0000284 sz ++;
285 ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000286 rc = MSI_RecordGetStringW(row,index,ret,&sz);
Mike McCormack9db0e072004-12-22 15:05:07 +0000287 if (rc!=ERROR_SUCCESS)
288 {
Aric Stewartfa384f62004-12-22 18:46:17 +0000289 ERR("Unable to load dynamic string\n");
Mike McCormack9db0e072004-12-22 15:05:07 +0000290 HeapFree(GetProcessHeap(), 0, ret);
291 ret = NULL;
292 }
Aric Stewart7231a432004-07-09 19:26:30 +0000293 return ret;
294}
295
Aric Stewartfa384f62004-12-22 18:46:17 +0000296inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop,
297 UINT* rc)
Mike McCormackba8200b2004-12-22 15:25:30 +0000298{
299 DWORD sz = 0;
300 LPWSTR str;
301 UINT r;
302
303 r = MSI_GetPropertyW(package, prop, NULL, &sz);
Aric Stewart25955702004-12-22 17:13:26 +0000304 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
Aric Stewartfa384f62004-12-22 18:46:17 +0000305 {
306 if (rc)
307 *rc = r;
Mike McCormackba8200b2004-12-22 15:25:30 +0000308 return NULL;
Aric Stewartfa384f62004-12-22 18:46:17 +0000309 }
Mike McCormackba8200b2004-12-22 15:25:30 +0000310 sz++;
311 str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR));
312 r = MSI_GetPropertyW(package, prop, str, &sz);
313 if (r != ERROR_SUCCESS)
314 {
315 HeapFree(GetProcessHeap(),0,str);
316 str = NULL;
317 }
Aric Stewartfa384f62004-12-22 18:46:17 +0000318 if (rc)
319 *rc = r;
Mike McCormackba8200b2004-12-22 15:25:30 +0000320 return str;
321}
322
Aric Stewartec688fb2004-07-04 00:35:52 +0000323inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component )
Aric Stewartbdb29552004-07-04 00:32:48 +0000324{
Mike McCormack4604e662004-08-06 17:30:20 +0000325 int rc = -1;
326 DWORD i;
Aric Stewartbdb29552004-07-04 00:32:48 +0000327
328 for (i = 0; i < package->loaded_components; i++)
329 {
330 if (strcmpW(Component,package->components[i].Component)==0)
331 {
332 rc = i;
333 break;
334 }
335 }
336 return rc;
337}
338
Aric Stewart7d3e5972004-07-04 00:36:58 +0000339inline static int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
340{
Mike McCormack4604e662004-08-06 17:30:20 +0000341 int rc = -1;
342 DWORD i;
Aric Stewart7d3e5972004-07-04 00:36:58 +0000343
344 for (i = 0; i < package->loaded_features; i++)
345 {
346 if (strcmpW(Feature,package->features[i].Feature)==0)
347 {
348 rc = i;
349 break;
350 }
351 }
352 return rc;
353}
354
Aric Stewartfcb20c52004-07-06 18:51:16 +0000355inline static int get_loaded_file(MSIPACKAGE* package, LPCWSTR file)
356{
Mike McCormack4604e662004-08-06 17:30:20 +0000357 int rc = -1;
358 DWORD i;
Aric Stewartfcb20c52004-07-06 18:51:16 +0000359
360 for (i = 0; i < package->loaded_files; i++)
361 {
362 if (strcmpW(file,package->files[i].File)==0)
363 {
364 rc = i;
365 break;
366 }
367 }
368 return rc;
369}
370
Mike McCormack9db0e072004-12-22 15:05:07 +0000371
Mike McCormack4604e662004-08-06 17:30:20 +0000372static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path)
Aric Stewartec688fb2004-07-04 00:35:52 +0000373{
Mike McCormack4604e662004-08-06 17:30:20 +0000374 DWORD i;
375 DWORD index;
Aric Stewartec688fb2004-07-04 00:35:52 +0000376
Aric Stewartec688fb2004-07-04 00:35:52 +0000377 if (!package)
378 return -2;
379
380 for (i=0; i < package->loaded_files; i++)
381 if (strcmpW(package->files[i].File,name)==0)
382 return -1;
383
384 index = package->loaded_files;
385 package->loaded_files++;
386 if (package->loaded_files== 1)
387 package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
388 else
389 package->files = HeapReAlloc(GetProcessHeap(),0,
390 package->files , package->loaded_files * sizeof(MSIFILE));
391
392 memset(&package->files[index],0,sizeof(MSIFILE));
393
Aric Stewartfa384f62004-12-22 18:46:17 +0000394 package->files[index].File = dupstrW(name);
395 package->files[index].TargetPath = dupstrW(path);
Aric Stewartec688fb2004-07-04 00:35:52 +0000396 package->files[index].Temporary = TRUE;
397
398 TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File));
399
400 return 0;
401}
402
403void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package)
404{
Mike McCormack4604e662004-08-06 17:30:20 +0000405 DWORD i;
Aric Stewartec688fb2004-07-04 00:35:52 +0000406
407 if (!package)
408 return;
409
410 for (i = 0; i < package->loaded_files; i++)
411 {
412 if (package->files[i].Temporary)
413 DeleteFileW(package->files[i].TargetPath);
414
415 }
416}
417
Mike McCormack9db0e072004-12-22 15:05:07 +0000418static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
419{
420 LPWSTR szQuery;
421 LPCWSTR p;
422 UINT sz, rc;
423 va_list va;
424
425 /* figure out how much space we need to allocate */
426 va_start(va, fmt);
427 sz = strlenW(fmt) + 1;
428 p = fmt;
429 while (*p)
430 {
431 p = strchrW(p, '%');
432 if (!p)
433 break;
434 p++;
435 switch (*p)
436 {
437 case 's': /* a string */
438 sz += strlenW(va_arg(va,LPCWSTR));
439 break;
440 case 'd':
441 case 'i': /* an integer -2147483648 seems to be longest */
442 sz += 3*sizeof(int);
443 (void)va_arg(va,int);
444 break;
445 case '%': /* a single % - leave it alone */
446 break;
447 default:
448 FIXME("Unhandled character type %c\n",*p);
449 }
450 p++;
451 }
452 va_end(va);
453
454 /* construct the string */
455 szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
456 va_start(va, fmt);
457 vsnprintfW(szQuery, sz, fmt, va);
458 va_end(va);
459
460 /* perform the query */
461 rc = MSI_DatabaseOpenViewW(db, szQuery, view);
462 HeapFree(GetProcessHeap(), 0, szQuery);
463 return rc;
464}
465
Aric Stewartfa384f62004-12-22 18:46:17 +0000466static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d )
467{
468 MSIRECORD * row;
469
470 row = MSI_CreateRecord(4);
471 MSI_RecordSetInteger(row,1,a);
472 MSI_RecordSetInteger(row,2,b);
473 MSI_RecordSetInteger(row,3,c);
474 MSI_RecordSetInteger(row,4,d);
475 MSI_ProcessMessage(package, INSTALLMESSAGE_PROGRESS, row);
476 msiobj_release(&row->hdr);
477}
478
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000479static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * record)
Aric Stewartd2c395a2004-07-06 18:48:15 +0000480{
481 static const WCHAR Query_t[] =
482{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o',
483'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',
484' ','\'','%','s','\'',0};
485 WCHAR message[1024];
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 LPWSTR ptr;
490
Mike McCormack9db0e072004-12-22 15:05:07 +0000491 if (!package->LastAction || strcmpW(package->LastAction,action))
Aric Stewartd2c395a2004-07-06 18:48:15 +0000492 {
Mike McCormack9db0e072004-12-22 15:05:07 +0000493 rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000494 if (rc != ERROR_SUCCESS)
495 return;
Mike McCormack9db0e072004-12-22 15:05:07 +0000496
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000497 rc = MSI_ViewExecute(view, 0);
Aric Stewart7231a432004-07-09 19:26:30 +0000498 if (rc != ERROR_SUCCESS)
499 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000500 MSI_ViewClose(view);
501 return;
502 }
503 rc = MSI_ViewFetch(view,&row);
504 if (rc != ERROR_SUCCESS)
505 {
506 MSI_ViewClose(view);
Aric Stewart7231a432004-07-09 19:26:30 +0000507 return;
508 }
Aric Stewartd2c395a2004-07-06 18:48:15 +0000509
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000510 if (MSI_RecordIsNull(row,3))
Aric Stewart7231a432004-07-09 19:26:30 +0000511 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000512 msiobj_release(&row->hdr);
513 MSI_ViewClose(view);
514 msiobj_release(&view->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000515 return;
516 }
517
Mike McCormack9db0e072004-12-22 15:05:07 +0000518 /* update the cached actionformat */
519 if (package->ActionFormat)
520 HeapFree(GetProcessHeap(),0,package->ActionFormat);
521 package->ActionFormat = load_dynamic_stringW(row,3);
Aric Stewart7231a432004-07-09 19:26:30 +0000522
Mike McCormack9db0e072004-12-22 15:05:07 +0000523 if (package->LastAction)
Aric Stewartfa384f62004-12-22 18:46:17 +0000524 HeapFree(GetProcessHeap(),0,package->LastAction);
525 package->LastAction = dupstrW(action);
Mike McCormack9db0e072004-12-22 15:05:07 +0000526
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000527 msiobj_release(&row->hdr);
528 MSI_ViewClose(view);
529 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000530 }
Aric Stewartd2c395a2004-07-06 18:48:15 +0000531
532 message[0]=0;
Mike McCormack9db0e072004-12-22 15:05:07 +0000533 ptr = package->ActionFormat;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000534 while (*ptr)
535 {
536 LPWSTR ptr2;
537 LPWSTR data=NULL;
538 WCHAR tmp[1023];
539 INT field;
540
541 ptr2 = strchrW(ptr,'[');
542 if (ptr2)
543 {
544 strncpyW(tmp,ptr,ptr2-ptr);
545 tmp[ptr2-ptr]=0;
546 strcatW(message,tmp);
547 ptr2++;
548 field = atoiW(ptr2);
Aric Stewart7231a432004-07-09 19:26:30 +0000549 data = load_dynamic_stringW(record,field);
550 if (data)
551 {
552 strcatW(message,data);
553 HeapFree(GetProcessHeap(),0,data);
554 }
Aric Stewartd2c395a2004-07-06 18:48:15 +0000555 ptr=strchrW(ptr2,']');
556 ptr++;
557 }
558 else
559 {
560 strcatW(message,ptr);
561 break;
562 }
563 }
564
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000565 row = MSI_CreateRecord(1);
566 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000567
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000568 MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, row);
569 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000570}
571
572
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000573static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action)
Aric Stewartd2c395a2004-07-06 18:48:15 +0000574{
575 static const WCHAR template_s[]=
576{'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ','%','s','.',0};
577 static const WCHAR format[] =
578{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
579 static const WCHAR Query_t[] =
580{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','c','t','i','o',
581'n','T','e','x','t',' ','w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',
582' ','\'','%','s','\'',0};
583 WCHAR message[1024];
584 WCHAR timet[0x100];
585 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000586 MSIQUERY * view;
587 MSIRECORD * row = 0;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000588 WCHAR *ActionText=NULL;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000589
590 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
591
Mike McCormack9db0e072004-12-22 15:05:07 +0000592 rc = ACTION_OpenQuery(package->db, &view, Query_t, action);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000593 if (rc != ERROR_SUCCESS)
594 return;
595 rc = MSI_ViewExecute(view, 0);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000596 if (rc != ERROR_SUCCESS)
597 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000598 MSI_ViewClose(view);
599 msiobj_release(&view->hdr);
600 return;
601 }
602 rc = MSI_ViewFetch(view,&row);
603 if (rc != ERROR_SUCCESS)
604 {
605 MSI_ViewClose(view);
606 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000607 return;
608 }
609
Aric Stewart7231a432004-07-09 19:26:30 +0000610 ActionText = load_dynamic_stringW(row,2);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000611 msiobj_release(&row->hdr);
612 MSI_ViewClose(view);
613 msiobj_release(&view->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000614
615 sprintfW(message,template_s,timet,action,ActionText);
616
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000617 row = MSI_CreateRecord(1);
618 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000619
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000620 MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row);
621 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000622 HeapFree(GetProcessHeap(),0,ActionText);
623}
624
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000625static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start,
Aric Stewartd2c395a2004-07-06 18:48:15 +0000626 UINT rc)
627{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000628 MSIRECORD * row;
Aric Stewartd2c395a2004-07-06 18:48:15 +0000629 static const WCHAR template_s[]=
630{'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ','%','s',
631'.',0};
632 static const WCHAR template_e[]=
633{'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ','%','s',
634'.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ','%','i','.',0};
635 static const WCHAR format[] =
636{'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
637 WCHAR message[1024];
638 WCHAR timet[0x100];
639
640 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
641 if (start)
642 sprintfW(message,template_s,timet,action);
643 else
644 sprintfW(message,template_e,timet,action,rc);
645
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000646 row = MSI_CreateRecord(1);
647 MSI_RecordSetStringW(row,1,message);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000648
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000649 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row);
650 msiobj_release(&row->hdr);
Aric Stewartd2c395a2004-07-06 18:48:15 +0000651}
652
Aric Stewartfa384f62004-12-22 18:46:17 +0000653/*
654 * build_directory_name()
655 *
656 * This function is to save messing round with directory names
657 * It handles adding backslashes between path segments,
658 * and can add \ at the end of the directory name if told to.
659 *
660 * It takes a variable number of arguments.
661 * It always allocates a new string for the result, so make sure
662 * to free the return value when finished with it.
663 *
664 * The first arg is the number of path segments that follow.
665 * The arguments following count are a list of path segments.
666 * A path segment may be NULL.
667 *
668 * Path segments will be added with a \ seperating them.
669 * A \ will not be added after the last segment, however if the
670 * last segment is NULL, then the last character will be a \
671 *
672 */
673static LPWSTR build_directory_name(DWORD count, ...)
674{
675 DWORD sz = 1, i;
676 LPWSTR dir;
677 va_list va;
678
679 va_start(va,count);
680 for(i=0; i<count; i++)
681 {
682 LPCWSTR str = va_arg(va,LPCWSTR);
683 if (str)
684 sz += strlenW(str) + 1;
685 }
686 va_end(va);
687
688 dir = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
689 dir[0]=0;
690
691 va_start(va,count);
692 for(i=0; i<count; i++)
693 {
694 LPCWSTR str = va_arg(va,LPCWSTR);
695 if (!str)
696 continue;
697 strcatW(dir, str);
698 if( ((i+1)!=count) && dir[strlenW(dir)-1]!='\\')
699 strcatW(dir, cszbs);
700 }
701 return dir;
702}
703
704
Aric Stewart401bd3f2004-06-28 20:34:35 +0000705/****************************************************
706 * TOP level entry points
707 *****************************************************/
708
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000709UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
Aric Stewart401bd3f2004-06-28 20:34:35 +0000710 LPCWSTR szCommandLine)
711{
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000712 DWORD sz;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000713 WCHAR buffer[10];
Aric Stewart401bd3f2004-06-28 20:34:35 +0000714 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000715 static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +0000716
Aric Stewarte95136b2004-06-29 03:44:01 +0000717 if (szPackagePath)
718 {
Mike McCormackba8200b2004-12-22 15:25:30 +0000719 LPWSTR p, check, path;
Aric Stewarte95136b2004-06-29 03:44:01 +0000720
Aric Stewartfa384f62004-12-22 18:46:17 +0000721 path = dupstrW(szPackagePath);
Mike McCormackba8200b2004-12-22 15:25:30 +0000722 p = strrchrW(path,'\\');
Aric Stewarte95136b2004-06-29 03:44:01 +0000723 if (p)
724 {
725 p++;
726 *p=0;
727 }
728
Aric Stewartfa384f62004-12-22 18:46:17 +0000729 check = load_dynamic_property(package, cszSourceDir,NULL);
Aric Stewartd0c971a2004-12-22 18:15:50 +0000730 if (!check)
Mike McCormackba8200b2004-12-22 15:25:30 +0000731 MSI_SetPropertyW(package, cszSourceDir, path);
Aric Stewartfa384f62004-12-22 18:46:17 +0000732 else
Mike McCormackba8200b2004-12-22 15:25:30 +0000733 HeapFree(GetProcessHeap(), 0, check);
Aric Stewartfa384f62004-12-22 18:46:17 +0000734
Mike McCormackba8200b2004-12-22 15:25:30 +0000735 HeapFree(GetProcessHeap(), 0, path);
Aric Stewarte95136b2004-06-29 03:44:01 +0000736 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000737
Aric Stewart36eee232004-07-04 00:07:13 +0000738 if (szCommandLine)
739 {
740 LPWSTR ptr,ptr2;
741 ptr = (LPWSTR)szCommandLine;
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000742
Aric Stewart36eee232004-07-04 00:07:13 +0000743 while (*ptr)
744 {
Aric Stewart36eee232004-07-04 00:07:13 +0000745 WCHAR prop[0x100];
746 WCHAR val[0x100];
747
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000748 TRACE("Looking at %s\n",debugstr_w(ptr));
749
Aric Stewart36eee232004-07-04 00:07:13 +0000750 ptr2 = strchrW(ptr,'=');
751 if (ptr2)
752 {
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000753 BOOL quote=FALSE;
Aric Stewart36eee232004-07-04 00:07:13 +0000754 DWORD len = 0;
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000755
756 while (*ptr == ' ') ptr++;
Aric Stewart36eee232004-07-04 00:07:13 +0000757 strncpyW(prop,ptr,ptr2-ptr);
758 prop[ptr2-ptr]=0;
759 ptr2++;
760
761 ptr = ptr2;
Aric Stewarte2d4ea82004-07-04 00:33:45 +0000762 while (*ptr && (quote || (!quote && *ptr!=' ')))
Aric Stewart36eee232004-07-04 00:07:13 +0000763 {
764 if (*ptr == '"')
765 quote = !quote;
766 ptr++;
767 len++;
768 }
769
770 if (*ptr2=='"')
771 {
772 ptr2++;
773 len -= 2;
774 }
775 strncpyW(val,ptr2,len);
776 val[len]=0;
777
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000778 if (strlenW(prop) > 0)
779 {
Aric Stewartfa384f62004-12-22 18:46:17 +0000780 TRACE("Found commandline property (%s) = (%s)\n",
781 debugstr_w(prop), debugstr_w(val));
Hans Leidekkerba848ac2004-07-12 20:43:09 +0000782 MSI_SetPropertyW(package,prop,val);
783 }
784 }
785 ptr++;
Aric Stewart36eee232004-07-04 00:07:13 +0000786 }
787 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000788
789 sz = 10;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000790 if (MSI_GetPropertyW(package,szUILevel,buffer,&sz) == ERROR_SUCCESS)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000791 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000792 if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000793 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000794 rc = ACTION_ProcessUISequence(package);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000795 if (rc == ERROR_SUCCESS)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000796 rc = ACTION_ProcessExecSequence(package,TRUE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000797 }
798 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000799 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000800 }
801 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000802 rc = ACTION_ProcessExecSequence(package,FALSE);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000803
804 return rc;
805}
806
807
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000808static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000809{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000810 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000811 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000812 static const WCHAR ExecSeqQuery[] = {
813 's','e','l','e','c','t',' ','*',' ',
814 'f','r','o','m',' ',
815 'I','n','s','t','a','l','l','E','x','e','c','u','t','e',
816 'S','e','q','u','e','n','c','e',' ',
817 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ',
818 '>',' ','%','i',' ','o','r','d','e','r',' ',
819 'b','y',' ','S','e','q','u','e','n','c','e',0 };
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000820 MSIRECORD * row = 0;
821 static const WCHAR IVQuery[] = {
822 's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ',
823 'f','r','o','m',' ','I','n','s','t','a','l','l',
824 'E','x','e','c','u','t','e','S','e','q','u','e','n','c','e',' ',
825 'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ',
826 '`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`',
827 0};
Mike McCormack9db0e072004-12-22 15:05:07 +0000828 INT seq = 0;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000829
Mike McCormack9db0e072004-12-22 15:05:07 +0000830 /* get the sequence number */
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000831 if (UIran)
832 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000833 rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view);
834 if (rc != ERROR_SUCCESS)
835 return rc;
836 rc = MSI_ViewExecute(view, 0);
837 if (rc != ERROR_SUCCESS)
838 {
839 MSI_ViewClose(view);
840 msiobj_release(&view->hdr);
841 return rc;
842 }
843 rc = MSI_ViewFetch(view,&row);
844 if (rc != ERROR_SUCCESS)
845 {
846 MSI_ViewClose(view);
847 msiobj_release(&view->hdr);
848 return rc;
849 }
850 seq = MSI_RecordGetInteger(row,1);
851 msiobj_release(&row->hdr);
852 MSI_ViewClose(view);
853 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000854 }
Mike McCormack9db0e072004-12-22 15:05:07 +0000855
856 rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000857 if (rc == ERROR_SUCCESS)
858 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000859 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000860
861 if (rc != ERROR_SUCCESS)
862 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000863 MSI_ViewClose(view);
864 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000865 goto end;
866 }
867
Mike McCormack9db0e072004-12-22 15:05:07 +0000868 TRACE("Running the actions\n");
Aric Stewart401bd3f2004-06-28 20:34:35 +0000869
870 while (1)
871 {
872 WCHAR buffer[0x100];
873 DWORD sz = 0x100;
Aric Stewart401bd3f2004-06-28 20:34:35 +0000874
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000875 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000876 if (rc != ERROR_SUCCESS)
877 {
878 rc = ERROR_SUCCESS;
879 break;
880 }
881
882 /* check conditions */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000883 if (!MSI_RecordIsNull(row,2))
Aric Stewart401bd3f2004-06-28 20:34:35 +0000884 {
Aric Stewart7231a432004-07-09 19:26:30 +0000885 LPWSTR cond = NULL;
886 cond = load_dynamic_stringW(row,2);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000887
Aric Stewart7231a432004-07-09 19:26:30 +0000888 if (cond)
Aric Stewart401bd3f2004-06-28 20:34:35 +0000889 {
Aric Stewart7231a432004-07-09 19:26:30 +0000890 /* this is a hack to skip errors in the condition code */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000891 if (MSI_EvaluateConditionW(package, cond) ==
Aric Stewart7231a432004-07-09 19:26:30 +0000892 MSICONDITION_FALSE)
893 {
894 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000895 msiobj_release(&row->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000896 continue;
897 }
898 else
899 HeapFree(GetProcessHeap(),0,cond);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000900 }
Aric Stewart401bd3f2004-06-28 20:34:35 +0000901 }
902
903 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000904 rc = MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000905 if (rc != ERROR_SUCCESS)
906 {
907 ERR("Error is %x\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000908 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000909 break;
910 }
911
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000912 rc = ACTION_PerformAction(package,buffer);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000913
Aric Stewart1282d7a2004-11-03 22:16:53 +0000914 if (rc == ERROR_FUNCTION_NOT_CALLED)
915 rc = ERROR_SUCCESS;
916
Aric Stewart401bd3f2004-06-28 20:34:35 +0000917 if (rc != ERROR_SUCCESS)
918 {
919 ERR("Execution halted due to error (%i)\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000920 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000921 break;
922 }
923
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000924 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000925 }
926
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000927 MSI_ViewClose(view);
928 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +0000929 }
930
931end:
Aric Stewart401bd3f2004-06-28 20:34:35 +0000932 return rc;
933}
934
935
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000936static UINT ACTION_ProcessUISequence(MSIPACKAGE *package)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000937{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000938 MSIQUERY * view;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000939 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000940 static const WCHAR ExecSeqQuery [] = {
941 's','e','l','e','c','t',' ','*',' ',
942 'f','r','o','m',' ','I','n','s','t','a','l','l',
943 'U','I','S','e','q','u','e','n','c','e',' ',
944 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', '>',' ','0',' ',
945 'o','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e',0};
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000946
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000947 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000948
949 if (rc == ERROR_SUCCESS)
950 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000951 rc = MSI_ViewExecute(view, 0);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000952
953 if (rc != ERROR_SUCCESS)
954 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000955 MSI_ViewClose(view);
956 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000957 goto end;
958 }
959
960 TRACE("Running the actions \n");
961
962 while (1)
963 {
964 WCHAR buffer[0x100];
965 DWORD sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000966 MSIRECORD * row = 0;
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000967
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000968 rc = MSI_ViewFetch(view,&row);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000969 if (rc != ERROR_SUCCESS)
970 {
971 rc = ERROR_SUCCESS;
972 break;
973 }
974
975 /* check conditions */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000976 if (!MSI_RecordIsNull(row,2))
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000977 {
Aric Stewart7231a432004-07-09 19:26:30 +0000978 LPWSTR cond = NULL;
979 cond = load_dynamic_stringW(row,2);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000980
Aric Stewart7231a432004-07-09 19:26:30 +0000981 if (cond)
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000982 {
Aric Stewart7231a432004-07-09 19:26:30 +0000983 /* this is a hack to skip errors in the condition code */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000984 if (MSI_EvaluateConditionW(package, cond) ==
Aric Stewart7231a432004-07-09 19:26:30 +0000985 MSICONDITION_FALSE)
986 {
987 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000988 msiobj_release(&row->hdr);
Aric Stewart7231a432004-07-09 19:26:30 +0000989 continue;
990 }
991 else
992 HeapFree(GetProcessHeap(),0,cond);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000993 }
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000994 }
995
996 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +0000997 rc = MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewarted7c4bc2004-07-04 00:26:54 +0000998 if (rc != ERROR_SUCCESS)
999 {
1000 ERR("Error is %x\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001001 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001002 break;
1003 }
1004
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001005 rc = ACTION_PerformAction(package,buffer);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001006
Aric Stewart1282d7a2004-11-03 22:16:53 +00001007 if (rc == ERROR_FUNCTION_NOT_CALLED)
1008 rc = ERROR_SUCCESS;
1009
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001010 if (rc != ERROR_SUCCESS)
1011 {
1012 ERR("Execution halted due to error (%i)\n",rc);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001013 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001014 break;
1015 }
1016
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001017 msiobj_release(&row->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001018 }
1019
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001020 MSI_ViewClose(view);
1021 msiobj_release(&view->hdr);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00001022 }
1023
1024end:
1025 return rc;
1026}
1027
Aric Stewart401bd3f2004-06-28 20:34:35 +00001028/********************************************************
1029 * ACTION helper functions and functions that perform the actions
1030 *******************************************************/
1031
1032/*
1033 * Alot of actions are really important even if they don't do anything
1034 * explicit.. Lots of properties are set at the beginning of the installation
Mike McCormack6e2bca32004-07-04 00:25:00 +00001035 * CostFinalize does a bunch of work to translated the directories and such
Aric Stewart401bd3f2004-06-28 20:34:35 +00001036 *
Mike McCormack6e2bca32004-07-04 00:25:00 +00001037 * But until I get write access to the database that is hard, so I am going to
Aric Stewart401bd3f2004-06-28 20:34:35 +00001038 * hack it to see if I can get something to run.
1039 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001040UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001041{
Aric Stewartd2c395a2004-07-06 18:48:15 +00001042 UINT rc = ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001043
1044 TRACE("Performing action (%s)\n",debugstr_w(action));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001045 ui_actioninfo(package, action, TRUE, 0);
1046 ui_actionstart(package, action);
1047 ui_progress(package,2,1,0,0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001048
Mike McCormack24e9a342004-07-06 18:56:12 +00001049 /* pre install, setup and configuration block */
Aric Stewart5b936ca2004-07-06 18:47:09 +00001050 if (strcmpW(action,szLaunchConditions)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001051 rc = ACTION_LaunchConditions(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001052 else if (strcmpW(action,szCostInitialize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001053 rc = ACTION_CostInitialize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001054 else if (strcmpW(action,szFileCost)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001055 rc = ACTION_FileCost(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001056 else if (strcmpW(action,szCostFinalize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001057 rc = ACTION_CostFinalize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001058 else if (strcmpW(action,szInstallValidate)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001059 rc = ACTION_InstallValidate(package);
Aric Stewart7d3e5972004-07-04 00:36:58 +00001060
1061 /* install block */
Aric Stewartb942e182004-07-06 18:50:02 +00001062 else if (strcmpW(action,szProcessComponents)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001063 rc = ACTION_ProcessComponents(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001064 else if (strcmpW(action,szInstallInitialize)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001065 rc = ACTION_InstallInitialize(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001066 else if (strcmpW(action,szCreateFolders)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001067 rc = ACTION_CreateFolders(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001068 else if (strcmpW(action,szInstallFiles)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001069 rc = ACTION_InstallFiles(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001070 else if (strcmpW(action,szDuplicateFiles)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001071 rc = ACTION_DuplicateFiles(package);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001072 else if (strcmpW(action,szWriteRegistryValues)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001073 rc = ACTION_WriteRegistryValues(package);
Aric Stewartfcb20c52004-07-06 18:51:16 +00001074 else if (strcmpW(action,szRegisterTypeLibraries)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001075 rc = ACTION_RegisterTypeLibraries(package);
Aric Stewart8f0a7612004-07-06 18:53:11 +00001076 else if (strcmpW(action,szRegisterClassInfo)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001077 rc = ACTION_RegisterClassInfo(package);
Aric Stewart8f0a7612004-07-06 18:53:11 +00001078 else if (strcmpW(action,szRegisterProgIdInfo)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001079 rc = ACTION_RegisterProgIdInfo(package);
Aric Stewart2cf222f2004-07-06 19:00:23 +00001080 else if (strcmpW(action,szCreateShortcuts)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001081 rc = ACTION_CreateShortcuts(package);
Aric Stewart2cf222f2004-07-06 19:00:23 +00001082 else if (strcmpW(action,szPublishProduct)==0)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001083 rc = ACTION_PublishProduct(package);
Aric Stewart7d3e5972004-07-04 00:36:58 +00001084
Aric Stewart401bd3f2004-06-28 20:34:35 +00001085 /*
Mike McCormack3ece2462004-07-09 19:33:25 +00001086 Called during iTunes but unimplemented and seem important
Aric Stewartc75201f2004-06-29 04:04:13 +00001087
Aric Stewartc75201f2004-06-29 04:04:13 +00001088 ResolveSource (sets SourceDir)
Aric Stewartc75201f2004-06-29 04:04:13 +00001089 RegisterProduct
Aric Stewartc75201f2004-06-29 04:04:13 +00001090 InstallFinalize
Aric Stewart401bd3f2004-06-28 20:34:35 +00001091 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001092 else if ((rc = ACTION_CustomAction(package,action)) != ERROR_SUCCESS)
Aric Stewartd2c395a2004-07-06 18:48:15 +00001093 {
Aric Stewartec688fb2004-07-04 00:35:52 +00001094 FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001095 rc = ERROR_FUNCTION_NOT_CALLED;
Aric Stewartd2c395a2004-07-06 18:48:15 +00001096 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00001097
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001098 ui_actioninfo(package, action, FALSE, rc);
Aric Stewartd2c395a2004-07-06 18:48:15 +00001099 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001100}
1101
1102
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001103static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001104{
Aric Stewartd2c395a2004-07-06 18:48:15 +00001105 UINT rc = ERROR_SUCCESS;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001106 MSIQUERY * view;
1107 MSIRECORD * row = 0;
Mike McCormack9db0e072004-12-22 15:05:07 +00001108 static const WCHAR ExecSeqQuery[] =
Aric Stewart401bd3f2004-06-28 20:34:35 +00001109 {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o'
Mike McCormack9db0e072004-12-22 15:05:07 +00001110 ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i'
1111 ,'o','n','`',' ','=',' ','`','%','s','`',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00001112 UINT type;
Aric Stewart7231a432004-07-09 19:26:30 +00001113 LPWSTR source;
1114 LPWSTR target;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001115 WCHAR *deformated=NULL;
1116
Mike McCormack9db0e072004-12-22 15:05:07 +00001117 rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001118 if (rc != ERROR_SUCCESS)
1119 return rc;
1120
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001121 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001122 if (rc != ERROR_SUCCESS)
1123 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001124 MSI_ViewClose(view);
1125 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001126 return rc;
1127 }
1128
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001129 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001130 if (rc != ERROR_SUCCESS)
1131 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001132 MSI_ViewClose(view);
1133 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001134 return rc;
1135 }
1136
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001137 type = MSI_RecordGetInteger(row,2);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001138
Aric Stewart7231a432004-07-09 19:26:30 +00001139 source = load_dynamic_stringW(row,3);
1140 target = load_dynamic_stringW(row,4);
Aric Stewartc75201f2004-06-29 04:04:13 +00001141
1142 TRACE("Handling custom action %s (%x %s %s)\n",debugstr_w(action),type,
1143 debugstr_w(source), debugstr_w(target));
1144
Mike McCormack6e2bca32004-07-04 00:25:00 +00001145 /* we are ignoring ALOT of flags and important synchronization stuff */
Aric Stewart401bd3f2004-06-28 20:34:35 +00001146 switch (type & CUSTOM_ACTION_TYPE_MASK)
1147 {
Aric Stewartc75201f2004-06-29 04:04:13 +00001148 case 1: /* DLL file stored in a Binary table stream */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001149 rc = HANDLE_CustomType1(package,source,target,type);
Aric Stewartc75201f2004-06-29 04:04:13 +00001150 break;
Mike McCormack24e9a342004-07-06 18:56:12 +00001151 case 2: /* EXE file stored in a Binary table strem */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001152 rc = HANDLE_CustomType2(package,source,target,type);
Aric Stewartc75201f2004-06-29 04:04:13 +00001153 break;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001154 case 18: /*EXE file installed with package */
1155 rc = HANDLE_CustomType18(package,source,target,type);
1156 break;
1157 case 50: /*EXE file specified by a property value */
1158 rc = HANDLE_CustomType50(package,source,target,type);
1159 break;
1160 case 34: /*EXE to be run in specified directory */
1161 rc = HANDLE_CustomType34(package,source,target,type);
1162 break;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001163 case 35: /* Directory set with formatted text. */
1164 case 51: /* Property set with formatted text. */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001165 deformat_string(package,target,&deformated);
1166 rc = MSI_SetPropertyW(package,source,deformated);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001167 HeapFree(GetProcessHeap(),0,deformated);
1168 break;
1169 default:
Aric Stewartec688fb2004-07-04 00:35:52 +00001170 FIXME("UNHANDLED ACTION TYPE %i (%s %s)\n",
Aric Stewartc75201f2004-06-29 04:04:13 +00001171 type & CUSTOM_ACTION_TYPE_MASK, debugstr_w(source),
1172 debugstr_w(target));
Aric Stewart401bd3f2004-06-28 20:34:35 +00001173 }
1174
Aric Stewart7231a432004-07-09 19:26:30 +00001175 HeapFree(GetProcessHeap(),0,source);
1176 HeapFree(GetProcessHeap(),0,target);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001177 msiobj_release(&row->hdr);
1178 MSI_ViewClose(view);
1179 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001180 return rc;
1181}
1182
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001183static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source,
Aric Stewartc75201f2004-06-29 04:04:13 +00001184 LPWSTR tmp_file)
1185{
Aric Stewartc75201f2004-06-29 04:04:13 +00001186 DWORD sz=MAX_PATH;
1187
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001188 if (MSI_GetPropertyW(package, cszTempFolder, tmp_file, &sz)
Aric Stewartbdb29552004-07-04 00:32:48 +00001189 != ERROR_SUCCESS)
Aric Stewartc75201f2004-06-29 04:04:13 +00001190 GetTempPathW(MAX_PATH,tmp_file);
1191
1192 strcatW(tmp_file,source);
1193
1194 if (GetFileAttributesW(tmp_file) != INVALID_FILE_ATTRIBUTES)
1195 {
1196 TRACE("File already exists\n");
1197 return ERROR_SUCCESS;
1198 }
1199 else
1200 {
1201 /* write out the file */
1202 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001203 MSIQUERY * view;
1204 MSIRECORD * row = 0;
Mike McCormack9db0e072004-12-22 15:05:07 +00001205 static const WCHAR fmt[] =
Aric Stewartc75201f2004-06-29 04:04:13 +00001206 {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i'
Mike McCormack9db0e072004-12-22 15:05:07 +00001207,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0};
Aric Stewartc75201f2004-06-29 04:04:13 +00001208 HANDLE the_file;
1209 CHAR buffer[1024];
1210
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001211 if (track_tempfile(package, source, tmp_file)!=0)
Aric Stewartec688fb2004-07-04 00:35:52 +00001212 FIXME("File Name in temp tracking collision\n");
1213
Aric Stewartc75201f2004-06-29 04:04:13 +00001214 the_file = CreateFileW(tmp_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1215 FILE_ATTRIBUTE_NORMAL, NULL);
1216
1217 if (the_file == INVALID_HANDLE_VALUE)
1218 return ERROR_FUNCTION_FAILED;
1219
Mike McCormack9db0e072004-12-22 15:05:07 +00001220 rc = ACTION_OpenQuery(package->db, &view, fmt, source);
Aric Stewartc75201f2004-06-29 04:04:13 +00001221 if (rc != ERROR_SUCCESS)
1222 return rc;
1223
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001224 rc = MSI_ViewExecute(view, 0);
Aric Stewartc75201f2004-06-29 04:04:13 +00001225 if (rc != ERROR_SUCCESS)
1226 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001227 MSI_ViewClose(view);
1228 msiobj_release(&view->hdr);
Aric Stewartc75201f2004-06-29 04:04:13 +00001229 return rc;
1230 }
1231
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001232 rc = MSI_ViewFetch(view,&row);
Aric Stewartc75201f2004-06-29 04:04:13 +00001233 if (rc != ERROR_SUCCESS)
1234 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001235 MSI_ViewClose(view);
1236 msiobj_release(&view->hdr);
Aric Stewartc75201f2004-06-29 04:04:13 +00001237 return rc;
1238 }
1239
1240 do
1241 {
1242 DWORD write;
1243 sz = 1024;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001244 rc = MSI_RecordReadStream(row,2,buffer,&sz);
Aric Stewartc75201f2004-06-29 04:04:13 +00001245 if (rc != ERROR_SUCCESS)
1246 {
1247 ERR("Failed to get stream\n");
1248 CloseHandle(the_file);
1249 DeleteFileW(tmp_file);
1250 break;
1251 }
1252 WriteFile(the_file,buffer,sz,&write,NULL);
1253 } while (sz == 1024);
1254
1255 CloseHandle(the_file);
1256
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001257 msiobj_release(&row->hdr);
1258 MSI_ViewClose(view);
1259 msiobj_release(&view->hdr);
Aric Stewartc75201f2004-06-29 04:04:13 +00001260 }
1261
1262 return ERROR_SUCCESS;
1263}
1264
Aric Stewart6a787c72004-07-30 00:00:25 +00001265typedef UINT __stdcall CustomEntry(MSIHANDLE);
Aric Stewart7231a432004-07-09 19:26:30 +00001266typedef struct
1267{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001268 MSIPACKAGE *package;
Aric Stewart7231a432004-07-09 19:26:30 +00001269 WCHAR target[MAX_PATH];
1270 WCHAR source[MAX_PATH];
1271} thread_struct;
1272
Aric Stewarta3149f82004-07-09 19:38:40 +00001273#if 0
Aric Stewart7231a432004-07-09 19:26:30 +00001274static DWORD WINAPI DllThread(LPVOID info)
1275{
1276 HANDLE DLL;
1277 LPSTR proc;
1278 thread_struct *stuff;
1279 CustomEntry *fn;
1280
1281 stuff = (thread_struct*)info;
1282
Francois Gouget817c5202004-07-16 19:15:40 +00001283 TRACE("Asynchronous start (%s, %s) \n", debugstr_w(stuff->source),
Aric Stewart7231a432004-07-09 19:26:30 +00001284 debugstr_w(stuff->target));
1285
1286 DLL = LoadLibraryW(stuff->source);
1287 if (DLL)
1288 {
1289 proc = strdupWtoA( stuff->target );
1290 fn = (CustomEntry*)GetProcAddress(DLL,proc);
1291 if (fn)
1292 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001293 MSIHANDLE hPackage;
1294 MSIPACKAGE *package = stuff->package;
1295
Aric Stewart7231a432004-07-09 19:26:30 +00001296 TRACE("Calling function\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001297 hPackage = msiobj_findhandle( &package->hdr );
1298 if( !hPackage )
1299 ERR("Handle for object %p not found\n", package );
1300 fn(hPackage);
1301 msiobj_release( &package->hdr );
Aric Stewart7231a432004-07-09 19:26:30 +00001302 }
1303 else
1304 ERR("Cannot load functon\n");
1305
1306 HeapFree(GetProcessHeap(),0,proc);
1307 FreeLibrary(DLL);
1308 }
1309 else
1310 ERR("Unable to load library\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001311 msiobj_release( &stuff->package->hdr );
1312 HeapFree( GetProcessHeap(), 0, info );
Aric Stewart7231a432004-07-09 19:26:30 +00001313 return 0;
1314}
Aric Stewarta3149f82004-07-09 19:38:40 +00001315#endif
Aric Stewartc75201f2004-06-29 04:04:13 +00001316
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001317static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source,
Aric Stewartc75201f2004-06-29 04:04:13 +00001318 const LPWSTR target, const INT type)
1319{
1320 WCHAR tmp_file[MAX_PATH];
1321 CustomEntry *fn;
1322 HANDLE DLL;
1323 LPSTR proc;
1324
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001325 store_binary_to_temp(package, source, tmp_file);
Aric Stewartc75201f2004-06-29 04:04:13 +00001326
1327 TRACE("Calling function %s from %s\n",debugstr_w(target),
1328 debugstr_w(tmp_file));
1329
Aric Stewart36eee232004-07-04 00:07:13 +00001330 if (!strchrW(tmp_file,'.'))
1331 {
1332 static const WCHAR dot[]={'.',0};
1333 strcatW(tmp_file,dot);
1334 }
Aric Stewart7231a432004-07-09 19:26:30 +00001335
1336 if (type & 0xc0)
1337 {
Aric Stewarta3149f82004-07-09 19:38:40 +00001338 /* DWORD ThreadId; */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001339 thread_struct *info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) );
1340
1341 /* msiobj_addref( &package->hdr ); */
1342 info->package = package;
1343 strcpyW(info->target,target);
1344 strcpyW(info->source,tmp_file);
Francois Gouget817c5202004-07-16 19:15:40 +00001345 TRACE("Start Asynchronous execution\n");
Aric Stewarta3149f82004-07-09 19:38:40 +00001346 FIXME("DATABASE NOT THREADSAFE... not starting\n");
1347 /* CreateThread(NULL,0,DllThread,(LPVOID)&info,0,&ThreadId); */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001348 /* FIXME: release the package if the CreateThread fails */
1349 HeapFree( GetProcessHeap(), 0, info );
Aric Stewart7231a432004-07-09 19:26:30 +00001350 return ERROR_SUCCESS;
1351 }
Aric Stewart36eee232004-07-04 00:07:13 +00001352
Aric Stewartc75201f2004-06-29 04:04:13 +00001353 DLL = LoadLibraryW(tmp_file);
1354 if (DLL)
1355 {
1356 proc = strdupWtoA( target );
1357 fn = (CustomEntry*)GetProcAddress(DLL,proc);
1358 if (fn)
1359 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001360 MSIHANDLE hPackage;
1361
Aric Stewartc75201f2004-06-29 04:04:13 +00001362 TRACE("Calling function\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001363 hPackage = msiobj_findhandle( &package->hdr );
1364 if( !hPackage )
1365 ERR("Handle for object %p not found\n", package );
Aric Stewartc75201f2004-06-29 04:04:13 +00001366 fn(hPackage);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001367 msiobj_release( &package->hdr );
Aric Stewartc75201f2004-06-29 04:04:13 +00001368 }
1369 else
1370 ERR("Cannot load functon\n");
1371
1372 HeapFree(GetProcessHeap(),0,proc);
1373 FreeLibrary(DLL);
1374 }
1375 else
1376 ERR("Unable to load library\n");
1377
1378 return ERROR_SUCCESS;
1379}
1380
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001381static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source,
Aric Stewartc75201f2004-06-29 04:04:13 +00001382 const LPWSTR target, const INT type)
1383{
Aric Stewartfa384f62004-12-22 18:46:17 +00001384 WCHAR tmp_file[MAX_PATH];
Aric Stewartc75201f2004-06-29 04:04:13 +00001385 STARTUPINFOW si;
1386 PROCESS_INFORMATION info;
1387 BOOL rc;
Aric Stewartfa384f62004-12-22 18:46:17 +00001388 INT len;
Aric Stewartc75201f2004-06-29 04:04:13 +00001389 WCHAR *deformated;
Aric Stewartfa384f62004-12-22 18:46:17 +00001390 WCHAR *cmd;
Aric Stewartc75201f2004-06-29 04:04:13 +00001391 static const WCHAR spc[] = {' ',0};
1392
1393 memset(&si,0,sizeof(STARTUPINFOW));
Aric Stewartc75201f2004-06-29 04:04:13 +00001394
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001395 store_binary_to_temp(package, source, tmp_file);
Aric Stewartc75201f2004-06-29 04:04:13 +00001396
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001397 deformat_string(package,target,&deformated);
Aric Stewartfa384f62004-12-22 18:46:17 +00001398
1399 len = strlenW(tmp_file) + strlenW(deformated) + 2;
1400
1401 cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len);
1402
1403 strcpyW(cmd,tmp_file);
1404 strcatW(cmd,spc);
1405 strcatW(cmd,deformated);
Aric Stewartc75201f2004-06-29 04:04:13 +00001406
1407 HeapFree(GetProcessHeap(),0,deformated);
1408
Aric Stewartfa384f62004-12-22 18:46:17 +00001409 TRACE("executing exe %s \n",debugstr_w(cmd));
Aric Stewartc75201f2004-06-29 04:04:13 +00001410
Aric Stewartfa384f62004-12-22 18:46:17 +00001411 rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
Aric Stewartc75201f2004-06-29 04:04:13 +00001412 c_collen, &si, &info);
1413
Aric Stewartfa384f62004-12-22 18:46:17 +00001414 HeapFree(GetProcessHeap(),0,cmd);
1415
Aric Stewartc75201f2004-06-29 04:04:13 +00001416 if ( !rc )
1417 {
1418 ERR("Unable to execute command\n");
1419 return ERROR_SUCCESS;
1420 }
1421
1422 if (!(type & 0xc0))
1423 WaitForSingleObject(info.hProcess,INFINITE);
1424
Aric Stewart1282d7a2004-11-03 22:16:53 +00001425 CloseHandle( info.hProcess );
1426 CloseHandle( info.hThread );
1427 return ERROR_SUCCESS;
1428}
1429
1430static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source,
1431 const LPWSTR target, const INT type)
1432{
Aric Stewart1282d7a2004-11-03 22:16:53 +00001433 STARTUPINFOW si;
1434 PROCESS_INFORMATION info;
1435 BOOL rc;
1436 WCHAR *deformated;
Aric Stewartfa384f62004-12-22 18:46:17 +00001437 WCHAR *cmd;
1438 INT len;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001439 static const WCHAR spc[] = {' ',0};
1440 int index;
1441
1442 memset(&si,0,sizeof(STARTUPINFOW));
1443
1444 index = get_loaded_file(package,source);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001445
Aric Stewartfa384f62004-12-22 18:46:17 +00001446 len = strlenW(package->files[index].TargetPath);
1447
Aric Stewart1282d7a2004-11-03 22:16:53 +00001448 deformat_string(package,target,&deformated);
Aric Stewartfa384f62004-12-22 18:46:17 +00001449 len += strlenW(deformated);
1450 len += 2;
1451
1452 cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR));
1453
1454 strcpyW(cmd, package->files[index].TargetPath);
1455 strcatW(cmd, spc);
1456 strcatW(cmd, deformated);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001457
1458 HeapFree(GetProcessHeap(),0,deformated);
1459
Aric Stewartfa384f62004-12-22 18:46:17 +00001460 TRACE("executing exe %s \n",debugstr_w(cmd));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001461
Aric Stewartfa384f62004-12-22 18:46:17 +00001462 rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
Aric Stewart1282d7a2004-11-03 22:16:53 +00001463 c_collen, &si, &info);
1464
Aric Stewartfa384f62004-12-22 18:46:17 +00001465 HeapFree(GetProcessHeap(),0,cmd);
1466
Aric Stewart1282d7a2004-11-03 22:16:53 +00001467 if ( !rc )
1468 {
1469 ERR("Unable to execute command\n");
1470 return ERROR_SUCCESS;
1471 }
1472
1473 if (!(type & 0xc0))
1474 WaitForSingleObject(info.hProcess,INFINITE);
1475
1476 CloseHandle( info.hProcess );
1477 CloseHandle( info.hThread );
1478 return ERROR_SUCCESS;
1479}
1480
1481static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source,
1482 const LPWSTR target, const INT type)
1483{
Aric Stewart1282d7a2004-11-03 22:16:53 +00001484 STARTUPINFOW si;
1485 PROCESS_INFORMATION info;
Aric Stewartfa384f62004-12-22 18:46:17 +00001486 WCHAR *prop;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001487 BOOL rc;
1488 WCHAR *deformated;
Aric Stewartfa384f62004-12-22 18:46:17 +00001489 WCHAR *cmd;
1490 INT len;
1491 UINT prc;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001492 static const WCHAR spc[] = {' ',0};
Aric Stewart1282d7a2004-11-03 22:16:53 +00001493
1494 memset(&si,0,sizeof(STARTUPINFOW));
Aric Stewartfa384f62004-12-22 18:46:17 +00001495 memset(&info,0,sizeof(PROCESS_INFORMATION));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001496
Aric Stewartfa384f62004-12-22 18:46:17 +00001497 prop = load_dynamic_property(package,source,&prc);
1498 if (!prop)
1499 return prc;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001500
Aric Stewart1282d7a2004-11-03 22:16:53 +00001501 deformat_string(package,target,&deformated);
Aric Stewartfa384f62004-12-22 18:46:17 +00001502 len = strlenW(prop) + strlenW(deformated) + 2;
1503 cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len);
1504
1505 strcpyW(cmd,prop);
1506 strcatW(cmd,spc);
1507 strcatW(cmd,deformated);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001508
1509 HeapFree(GetProcessHeap(),0,deformated);
1510
Aric Stewartfa384f62004-12-22 18:46:17 +00001511 TRACE("executing exe %s \n",debugstr_w(cmd));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001512
Aric Stewartfa384f62004-12-22 18:46:17 +00001513 rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
Aric Stewart1282d7a2004-11-03 22:16:53 +00001514 c_collen, &si, &info);
1515
Aric Stewartfa384f62004-12-22 18:46:17 +00001516 HeapFree(GetProcessHeap(),0,cmd);
1517
Aric Stewart1282d7a2004-11-03 22:16:53 +00001518 if ( !rc )
1519 {
1520 ERR("Unable to execute command\n");
1521 return ERROR_SUCCESS;
1522 }
1523
1524 if (!(type & 0xc0))
1525 WaitForSingleObject(info.hProcess,INFINITE);
1526
1527 CloseHandle( info.hProcess );
1528 CloseHandle( info.hThread );
1529 return ERROR_SUCCESS;
1530}
1531
1532static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source,
1533 const LPWSTR target, const INT type)
1534{
Mike McCormackba8200b2004-12-22 15:25:30 +00001535 LPWSTR filename, deformated;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001536 STARTUPINFOW si;
1537 PROCESS_INFORMATION info;
1538 BOOL rc;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001539
1540 memset(&si,0,sizeof(STARTUPINFOW));
1541
Mike McCormackba8200b2004-12-22 15:25:30 +00001542 filename = resolve_folder(package, source, FALSE, FALSE, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00001543
Mike McCormackba8200b2004-12-22 15:25:30 +00001544 if (!filename)
1545 return ERROR_FUNCTION_FAILED;
Aric Stewart1282d7a2004-11-03 22:16:53 +00001546
1547 SetCurrentDirectoryW(filename);
Mike McCormackba8200b2004-12-22 15:25:30 +00001548 HeapFree(GetProcessHeap(),0,filename);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001549
1550 deformat_string(package,target,&deformated);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001551
Mike McCormackba8200b2004-12-22 15:25:30 +00001552 TRACE("executing exe %s \n",debugstr_w(deformated));
Aric Stewart1282d7a2004-11-03 22:16:53 +00001553
Mike McCormackba8200b2004-12-22 15:25:30 +00001554 rc = CreateProcessW(NULL, deformated, NULL, NULL, FALSE, 0, NULL,
Aric Stewart1282d7a2004-11-03 22:16:53 +00001555 c_collen, &si, &info);
Mike McCormackba8200b2004-12-22 15:25:30 +00001556 HeapFree(GetProcessHeap(),0,deformated);
Aric Stewart1282d7a2004-11-03 22:16:53 +00001557
1558 if ( !rc )
1559 {
1560 ERR("Unable to execute command\n");
1561 return ERROR_SUCCESS;
1562 }
1563
1564 if (!(type & 0xc0))
1565 WaitForSingleObject(info.hProcess,INFINITE);
1566
1567 CloseHandle( info.hProcess );
1568 CloseHandle( info.hThread );
Aric Stewartc75201f2004-06-29 04:04:13 +00001569 return ERROR_SUCCESS;
1570}
Aric Stewart401bd3f2004-06-28 20:34:35 +00001571
1572/***********************************************************************
1573 * create_full_pathW
1574 *
1575 * Recursively create all directories in the path.
1576 *
1577 * shamelessly stolen from setupapi/queue.c
1578 */
1579static BOOL create_full_pathW(const WCHAR *path)
1580{
1581 BOOL ret = TRUE;
1582 int len;
1583 WCHAR *new_path;
1584
1585 new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) *
Aric Stewartfa384f62004-12-22 18:46:17 +00001586 sizeof(WCHAR));
1587
Aric Stewart401bd3f2004-06-28 20:34:35 +00001588 strcpyW(new_path, path);
1589
1590 while((len = strlenW(new_path)) && new_path[len - 1] == '\\')
1591 new_path[len - 1] = 0;
1592
1593 while(!CreateDirectoryW(new_path, NULL))
1594 {
1595 WCHAR *slash;
1596 DWORD last_error = GetLastError();
1597 if(last_error == ERROR_ALREADY_EXISTS)
1598 break;
1599
1600 if(last_error != ERROR_PATH_NOT_FOUND)
1601 {
1602 ret = FALSE;
1603 break;
1604 }
1605
1606 if(!(slash = strrchrW(new_path, '\\')))
1607 {
1608 ret = FALSE;
1609 break;
1610 }
1611
1612 len = slash - new_path;
1613 new_path[len] = 0;
1614 if(!create_full_pathW(new_path))
1615 {
1616 ret = FALSE;
1617 break;
1618 }
1619 new_path[len] = '\\';
1620 }
1621
1622 HeapFree(GetProcessHeap(), 0, new_path);
1623 return ret;
1624}
1625
1626/*
1627 * Also we cannot enable/disable components either, so for now I am just going
Mike McCormack6e2bca32004-07-04 00:25:00 +00001628 * to do all the directories for all the components.
Aric Stewart401bd3f2004-06-28 20:34:35 +00001629 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001630static UINT ACTION_CreateFolders(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001631{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001632 static const WCHAR ExecSeqQuery[] = {
1633 's','e','l','e','c','t',' ','D','i','r','e','c','t','o','r','y','_',' ',
1634 'f','r','o','m',' ','C','r','e','a','t','e','F','o','l','d','e','r',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00001635 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001636 MSIQUERY *view;
Aric Stewartbdb29552004-07-04 00:32:48 +00001637 MSIFOLDER *folder;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001638
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001639 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view );
Aric Stewart401bd3f2004-06-28 20:34:35 +00001640 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00001641 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001642
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001643 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001644 if (rc != ERROR_SUCCESS)
1645 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001646 MSI_ViewClose(view);
1647 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001648 return rc;
1649 }
1650
1651 while (1)
1652 {
1653 WCHAR dir[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00001654 LPWSTR full_path;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001655 DWORD sz;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001656 MSIRECORD *row = NULL, *uirow;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001657
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001658 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001659 if (rc != ERROR_SUCCESS)
1660 {
1661 rc = ERROR_SUCCESS;
1662 break;
1663 }
1664
1665 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001666 rc = MSI_RecordGetStringW(row,1,dir,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001667
1668 if (rc!= ERROR_SUCCESS)
1669 {
1670 ERR("Unable to get folder id \n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001671 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001672 continue;
1673 }
1674
Aric Stewarte95136b2004-06-29 03:44:01 +00001675 sz = MAX_PATH;
Mike McCormackba8200b2004-12-22 15:25:30 +00001676 full_path = resolve_folder(package,dir,FALSE,FALSE,&folder);
1677 if (!full_path)
Aric Stewart401bd3f2004-06-28 20:34:35 +00001678 {
1679 ERR("Unable to resolve folder id %s\n",debugstr_w(dir));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001680 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001681 continue;
1682 }
1683
1684 TRACE("Folder is %s\n",debugstr_w(full_path));
Aric Stewartec688fb2004-07-04 00:35:52 +00001685
Aric Stewartd2c395a2004-07-06 18:48:15 +00001686 /* UI stuff */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001687 uirow = MSI_CreateRecord(1);
1688 MSI_RecordSetStringW(uirow,1,full_path);
1689 ui_actiondata(package,szCreateFolders,uirow);
1690 msiobj_release( &uirow->hdr );
Aric Stewartd2c395a2004-07-06 18:48:15 +00001691
Aric Stewartbdb29552004-07-04 00:32:48 +00001692 if (folder->State == 0)
1693 create_full_pathW(full_path);
1694
1695 folder->State = 3;
Aric Stewart401bd3f2004-06-28 20:34:35 +00001696
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001697 msiobj_release(&row->hdr);
Mike McCormackba8200b2004-12-22 15:25:30 +00001698 HeapFree(GetProcessHeap(),0,full_path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001699 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001700 MSI_ViewClose(view);
1701 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00001702
1703 return rc;
1704}
1705
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001706static int load_component(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartbdb29552004-07-04 00:32:48 +00001707{
1708 int index = package->loaded_components;
1709 DWORD sz;
1710
1711 /* fill in the data */
1712
1713 package->loaded_components++;
1714 if (package->loaded_components == 1)
1715 package->components = HeapAlloc(GetProcessHeap(),0,
1716 sizeof(MSICOMPONENT));
1717 else
1718 package->components = HeapReAlloc(GetProcessHeap(),0,
1719 package->components, package->loaded_components *
1720 sizeof(MSICOMPONENT));
1721
1722 memset(&package->components[index],0,sizeof(MSICOMPONENT));
1723
1724 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001725 MSI_RecordGetStringW(row,1,package->components[index].Component,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001726
1727 TRACE("Loading Component %s\n",
1728 debugstr_w(package->components[index].Component));
1729
1730 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001731 if (!MSI_RecordIsNull(row,2))
1732 MSI_RecordGetStringW(row,2,package->components[index].ComponentId,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001733
1734 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001735 MSI_RecordGetStringW(row,3,package->components[index].Directory,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001736
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001737 package->components[index].Attributes = MSI_RecordGetInteger(row,4);
Aric Stewartbdb29552004-07-04 00:32:48 +00001738
1739 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001740 MSI_RecordGetStringW(row,5,package->components[index].Condition,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001741
1742 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001743 MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001744
1745 package->components[index].State = INSTALLSTATE_UNKNOWN;
1746 package->components[index].Enabled = TRUE;
Aric Stewart7d3e5972004-07-04 00:36:58 +00001747 package->components[index].FeatureState= FALSE;
Aric Stewartbdb29552004-07-04 00:32:48 +00001748
1749 return index;
1750}
1751
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001752static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartbdb29552004-07-04 00:32:48 +00001753{
1754 int index = package->loaded_features;
1755 DWORD sz;
1756 static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p',
Mike McCormack9db0e072004-12-22 15:05:07 +00001757 'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e',
1758 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e',
1759 'a','t','u','r','e','_','=','\'','%','s','\'',0};
Aric Stewartbdb29552004-07-04 00:32:48 +00001760 static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R',
Mike McCormack9db0e072004-12-22 15:05:07 +00001761 'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C',
1762 'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001763 MSIQUERY * view;
1764 MSIQUERY * view2;
1765 MSIRECORD * row2;
1766 MSIRECORD * row3;
1767 UINT rc;
Aric Stewartbdb29552004-07-04 00:32:48 +00001768
1769 /* fill in the data */
1770
1771 package->loaded_features ++;
1772 if (package->loaded_features == 1)
1773 package->features = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFEATURE));
1774 else
1775 package->features = HeapReAlloc(GetProcessHeap(),0,package->features,
1776 package->loaded_features * sizeof(MSIFEATURE));
1777
1778 memset(&package->features[index],0,sizeof(MSIFEATURE));
1779
1780 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001781 MSI_RecordGetStringW(row,1,package->features[index].Feature,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001782
1783 TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature));
1784
1785 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001786 if (!MSI_RecordIsNull(row,2))
1787 MSI_RecordGetStringW(row,2,package->features[index].Feature_Parent,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001788
1789 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001790 if (!MSI_RecordIsNull(row,3))
1791 MSI_RecordGetStringW(row,3,package->features[index].Title,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001792
1793 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001794 if (!MSI_RecordIsNull(row,4))
1795 MSI_RecordGetStringW(row,4,package->features[index].Description,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001796
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001797 if (!MSI_RecordIsNull(row,5))
1798 package->features[index].Display = MSI_RecordGetInteger(row,5);
Aric Stewartbdb29552004-07-04 00:32:48 +00001799
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001800 package->features[index].Level= MSI_RecordGetInteger(row,6);
Aric Stewartbdb29552004-07-04 00:32:48 +00001801
1802 sz = 96;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001803 if (!MSI_RecordIsNull(row,7))
1804 MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001805
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001806 package->features[index].Attributes= MSI_RecordGetInteger(row,8);
Aric Stewartbdb29552004-07-04 00:32:48 +00001807 package->features[index].State = INSTALLSTATE_UNKNOWN;
1808
1809 /* load feature components */
1810
Mike McCormack9db0e072004-12-22 15:05:07 +00001811 rc = ACTION_OpenQuery(package->db, &view, Query1, package->features[index].Feature);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001812 if (rc != ERROR_SUCCESS)
1813 return;
1814 rc = MSI_ViewExecute(view,0);
1815 if (rc != ERROR_SUCCESS)
1816 {
1817 MSI_ViewClose(view);
1818 msiobj_release(&view->hdr);
1819 return;
1820 }
Aric Stewartbdb29552004-07-04 00:32:48 +00001821 while (1)
1822 {
1823 DWORD sz = 0x100;
1824 WCHAR buffer[0x100];
1825 DWORD rc;
1826 INT c_indx;
1827 INT cnt = package->features[index].ComponentCount;
1828
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001829 rc = MSI_ViewFetch(view,&row2);
Aric Stewartbdb29552004-07-04 00:32:48 +00001830 if (rc != ERROR_SUCCESS)
1831 break;
1832
1833 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001834 MSI_RecordGetStringW(row2,1,buffer,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00001835
1836 /* check to see if the component is already loaded */
1837 c_indx = get_loaded_component(package,buffer);
1838 if (c_indx != -1)
1839 {
1840 TRACE("Component %s already loaded at %i\n", debugstr_w(buffer),
1841 c_indx);
1842 package->features[index].Components[cnt] = c_indx;
1843 package->features[index].ComponentCount ++;
1844 }
1845
Mike McCormack9db0e072004-12-22 15:05:07 +00001846 rc = ACTION_OpenQuery(package->db, &view2, Query2, buffer);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001847 if (rc != ERROR_SUCCESS)
1848 {
1849 msiobj_release( &row2->hdr );
1850 continue;
1851 }
1852 rc = MSI_ViewExecute(view2,0);
1853 if (rc != ERROR_SUCCESS)
1854 {
1855 msiobj_release( &row2->hdr );
1856 MSI_ViewClose(view2);
1857 msiobj_release( &view2->hdr );
1858 continue;
1859 }
Aric Stewartbdb29552004-07-04 00:32:48 +00001860 while (1)
1861 {
1862 DWORD rc;
1863
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001864 rc = MSI_ViewFetch(view2,&row3);
Aric Stewartbdb29552004-07-04 00:32:48 +00001865 if (rc != ERROR_SUCCESS)
1866 break;
1867 c_indx = load_component(package,row3);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001868 msiobj_release( &row3->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00001869
1870 package->features[index].Components[cnt] = c_indx;
1871 package->features[index].ComponentCount ++;
1872 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001873 MSI_ViewClose(view2);
1874 msiobj_release( &view2->hdr );
1875 msiobj_release( &row2->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00001876 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001877 MSI_ViewClose(view);
1878 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001879}
1880
1881/*
1882 * I am not doing any of the costing functionality yet.
1883 * Mostly looking at doing the Component and Feature loading
1884 *
1885 * The native MSI does ALOT of modification to tables here. Mostly adding alot
1886 * of temporary columns to the Feature and Component tables.
1887 *
Mike McCormack24e9a342004-07-06 18:56:12 +00001888 * note: native msi also tracks the short filename. but I am only going to
Aric Stewartbdb29552004-07-04 00:32:48 +00001889 * track the long ones. Also looking at this directory table
1890 * it appears that the directory table does not get the parents
1891 * resolved base on property only based on their entrys in the
1892 * directory table.
1893 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001894static UINT ACTION_CostInitialize(MSIPACKAGE *package)
Aric Stewartbdb29552004-07-04 00:32:48 +00001895{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001896 MSIQUERY * view;
1897 MSIRECORD * row;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001898 UINT rc;
1899 static const WCHAR Query_all[] = {
1900 'S','E','L','E','C','T',' ','*',' ',
1901 'F','R','O','M',' ','F','e','a','t','u','r','e',0};
1902 static const WCHAR szCosting[] = {
1903 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
1904 static const WCHAR szZero[] = { '0', 0 };
Aric Stewartbdb29552004-07-04 00:32:48 +00001905
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001906 MSI_SetPropertyW(package, szCosting, szZero);
1907 MSI_SetPropertyW(package, cszRootDrive , c_collen);
Aric Stewartbdb29552004-07-04 00:32:48 +00001908
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001909 rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view);
1910 if (rc != ERROR_SUCCESS)
1911 return rc;
1912 rc = MSI_ViewExecute(view,0);
1913 if (rc != ERROR_SUCCESS)
1914 {
1915 MSI_ViewClose(view);
1916 msiobj_release(&view->hdr);
1917 return rc;
1918 }
Aric Stewartec688fb2004-07-04 00:35:52 +00001919 while (1)
Aric Stewartbdb29552004-07-04 00:32:48 +00001920 {
Aric Stewartec688fb2004-07-04 00:35:52 +00001921 DWORD rc;
Aric Stewartbdb29552004-07-04 00:32:48 +00001922
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001923 rc = MSI_ViewFetch(view,&row);
Aric Stewartec688fb2004-07-04 00:35:52 +00001924 if (rc != ERROR_SUCCESS)
1925 break;
Aric Stewartbdb29552004-07-04 00:32:48 +00001926
Aric Stewartec688fb2004-07-04 00:35:52 +00001927 load_feature(package,row);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001928 msiobj_release(&row->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00001929 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001930 MSI_ViewClose(view);
1931 msiobj_release(&view->hdr);
Aric Stewartec688fb2004-07-04 00:35:52 +00001932
1933 return ERROR_SUCCESS;
1934}
1935
Mike McCormack4604e662004-08-06 17:30:20 +00001936static UINT load_file(MSIPACKAGE* package, MSIRECORD * row)
Aric Stewartec688fb2004-07-04 00:35:52 +00001937{
Mike McCormack4604e662004-08-06 17:30:20 +00001938 DWORD index = package->loaded_files;
1939 DWORD i;
Mike McCormack9db0e072004-12-22 15:05:07 +00001940 LPWSTR buffer;
Aric Stewartec688fb2004-07-04 00:35:52 +00001941
1942 /* fill in the data */
1943
1944 package->loaded_files++;
1945 if (package->loaded_files== 1)
1946 package->files = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFILE));
1947 else
1948 package->files = HeapReAlloc(GetProcessHeap(),0,
1949 package->files , package->loaded_files * sizeof(MSIFILE));
1950
1951 memset(&package->files[index],0,sizeof(MSIFILE));
Mike McCormack9db0e072004-12-22 15:05:07 +00001952
1953 package->files[index].File = load_dynamic_stringW(row, 1);
1954 buffer = load_dynamic_stringW(row, 2);
Aric Stewartec688fb2004-07-04 00:35:52 +00001955
1956 package->files[index].ComponentIndex = -1;
1957 for (i = 0; i < package->loaded_components; i++)
1958 if (strcmpW(package->components[i].Component,buffer)==0)
1959 {
1960 package->files[index].ComponentIndex = i;
1961 break;
1962 }
1963 if (package->files[index].ComponentIndex == -1)
1964 ERR("Unfound Component %s\n",debugstr_w(buffer));
Mike McCormack9db0e072004-12-22 15:05:07 +00001965 HeapFree(GetProcessHeap(), 0, buffer);
Aric Stewartec688fb2004-07-04 00:35:52 +00001966
Mike McCormack9db0e072004-12-22 15:05:07 +00001967 package->files[index].FileName = load_dynamic_stringW(row,3);
Aric Stewartec688fb2004-07-04 00:35:52 +00001968
1969 reduce_to_longfilename(package->files[index].FileName);
1970
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001971 package->files[index].FileSize = MSI_RecordGetInteger(row,4);
Mike McCormack9db0e072004-12-22 15:05:07 +00001972 package->files[index].Version = load_dynamic_stringW(row, 5);
1973 package->files[index].Language = load_dynamic_stringW(row, 6);
1974 package->files[index].Attributes= MSI_RecordGetInteger(row,7);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001975 package->files[index].Sequence= MSI_RecordGetInteger(row,8);
Aric Stewartec688fb2004-07-04 00:35:52 +00001976
1977 package->files[index].Temporary = FALSE;
1978 package->files[index].State = 0;
1979
1980 TRACE("File Loaded (%s)\n",debugstr_w(package->files[index].File));
1981
1982 return ERROR_SUCCESS;
1983}
1984
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001985static UINT ACTION_FileCost(MSIPACKAGE *package)
Aric Stewartec688fb2004-07-04 00:35:52 +00001986{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001987 MSIQUERY * view;
1988 MSIRECORD * row;
Aric Stewartec688fb2004-07-04 00:35:52 +00001989 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001990 static const WCHAR Query[] = {
1991 'S','E','L','E','C','T',' ','*',' ',
1992 'F','R','O','M',' ','F','i','l','e',' ',
1993 'O','r','d','e','r',' ','b','y',' ','S','e','q','u','e','n','c','e', 0};
Aric Stewartec688fb2004-07-04 00:35:52 +00001994
Aric Stewartec688fb2004-07-04 00:35:52 +00001995 if (!package)
1996 return ERROR_INVALID_HANDLE;
1997
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00001998 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewartec688fb2004-07-04 00:35:52 +00001999 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002000 return ERROR_SUCCESS;
Aric Stewartec688fb2004-07-04 00:35:52 +00002001
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002002 rc = MSI_ViewExecute(view, 0);
Aric Stewartec688fb2004-07-04 00:35:52 +00002003 if (rc != ERROR_SUCCESS)
2004 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002005 MSI_ViewClose(view);
2006 msiobj_release(&view->hdr);
Aric Stewart84837d92004-07-20 01:22:37 +00002007 return ERROR_SUCCESS;
Aric Stewartec688fb2004-07-04 00:35:52 +00002008 }
2009
2010 while (1)
2011 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002012 rc = MSI_ViewFetch(view,&row);
Aric Stewartec688fb2004-07-04 00:35:52 +00002013 if (rc != ERROR_SUCCESS)
2014 {
2015 rc = ERROR_SUCCESS;
2016 break;
2017 }
2018 load_file(package,row);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002019 msiobj_release(&row->hdr);
Aric Stewartec688fb2004-07-04 00:35:52 +00002020 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002021 MSI_ViewClose(view);
2022 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00002023
2024 return ERROR_SUCCESS;
2025}
2026
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002027static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
Aric Stewartbdb29552004-07-04 00:32:48 +00002028
2029{
Mike McCormackba8200b2004-12-22 15:25:30 +00002030 static const WCHAR Query[] =
2031 {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c',
2032 't','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t',
2033 'o','r','y','`',' ','=',' ','`','%','s','`',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00002034 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002035 MSIQUERY * view;
Mike McCormackba8200b2004-12-22 15:25:30 +00002036 LPWSTR targetdir, parent, srcdir;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002037 MSIRECORD * row = 0;
Mike McCormack4604e662004-08-06 17:30:20 +00002038 INT index = -1;
2039 DWORD i;
Aric Stewarte95136b2004-06-29 03:44:01 +00002040
Aric Stewartbdb29552004-07-04 00:32:48 +00002041 TRACE("Looking for dir %s\n",debugstr_w(dir));
Aric Stewart401bd3f2004-06-28 20:34:35 +00002042
Aric Stewartbdb29552004-07-04 00:32:48 +00002043 for (i = 0; i < package->loaded_folders; i++)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002044 {
Aric Stewartbdb29552004-07-04 00:32:48 +00002045 if (strcmpW(package->folders[i].Directory,dir)==0)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002046 {
Mike McCormack4604e662004-08-06 17:30:20 +00002047 TRACE(" %s retuning on index %lu\n",debugstr_w(dir),i);
Aric Stewartbdb29552004-07-04 00:32:48 +00002048 return i;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002049 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002050 }
2051
Aric Stewartbdb29552004-07-04 00:32:48 +00002052 TRACE("Working to load %s\n",debugstr_w(dir));
2053
Mike McCormackba8200b2004-12-22 15:25:30 +00002054 index = package->loaded_folders++;
2055 if (package->loaded_folders==1)
Aric Stewartbdb29552004-07-04 00:32:48 +00002056 package->folders = HeapAlloc(GetProcessHeap(),0,
2057 sizeof(MSIFOLDER));
2058 else
2059 package->folders= HeapReAlloc(GetProcessHeap(),0,
2060 package->folders, package->loaded_folders*
2061 sizeof(MSIFOLDER));
2062
2063 memset(&package->folders[index],0,sizeof(MSIFOLDER));
2064
Aric Stewartfa384f62004-12-22 18:46:17 +00002065 package->folders[index].Directory = dupstrW(dir);
Aric Stewartbdb29552004-07-04 00:32:48 +00002066
Mike McCormackba8200b2004-12-22 15:25:30 +00002067 rc = ACTION_OpenQuery(package->db, &view, Query, dir);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002068 if (rc != ERROR_SUCCESS)
Aric Stewartbdb29552004-07-04 00:32:48 +00002069 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002070
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002071 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002072 if (rc != ERROR_SUCCESS)
2073 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002074 MSI_ViewClose(view);
2075 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00002076 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002077 }
2078
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002079 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002080 if (rc != ERROR_SUCCESS)
2081 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002082 MSI_ViewClose(view);
2083 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00002084 return -1;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002085 }
2086
Mike McCormackba8200b2004-12-22 15:25:30 +00002087 targetdir = load_dynamic_stringW(row,3);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002088
2089 /* split src and target dir */
2090 if (strchrW(targetdir,':'))
2091 {
2092 srcdir=strchrW(targetdir,':');
2093 *srcdir=0;
2094 srcdir ++;
2095 }
2096 else
2097 srcdir=NULL;
2098
2099 /* for now only pick long filename versions */
2100 if (strchrW(targetdir,'|'))
2101 {
2102 targetdir = strchrW(targetdir,'|');
2103 *targetdir = 0;
2104 targetdir ++;
2105 }
2106 if (srcdir && strchrW(srcdir,'|'))
2107 {
2108 srcdir= strchrW(srcdir,'|');
2109 *srcdir= 0;
2110 srcdir ++;
2111 }
2112
2113 /* now check for root dirs */
2114 if (targetdir[0] == '.' && targetdir[1] == 0)
2115 targetdir = NULL;
2116
2117 if (srcdir && srcdir[0] == '.' && srcdir[1] == 0)
2118 srcdir = NULL;
2119
Mike McCormackba8200b2004-12-22 15:25:30 +00002120 if (targetdir)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002121 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002122 TRACE(" TargetDefault = %s\n",debugstr_w(targetdir));
Aric Stewartfa384f62004-12-22 18:46:17 +00002123 if (package->folders[index].TargetDefault)
2124 HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault);
2125 package->folders[index].TargetDefault = dupstrW(targetdir);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002126 }
2127
Mike McCormackba8200b2004-12-22 15:25:30 +00002128 if (srcdir)
Aric Stewartfa384f62004-12-22 18:46:17 +00002129 package->folders[index].SourceDefault = dupstrW(srcdir);
Mike McCormackba8200b2004-12-22 15:25:30 +00002130 else if (targetdir)
Aric Stewartfa384f62004-12-22 18:46:17 +00002131 package->folders[index].SourceDefault = dupstrW(targetdir);
Mike McCormackba8200b2004-12-22 15:25:30 +00002132 HeapFree(GetProcessHeap(), 0, targetdir);
2133
2134 parent = load_dynamic_stringW(row,2);
2135 if (parent)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002136 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002137 i = load_folder(package,parent);
Aric Stewartbdb29552004-07-04 00:32:48 +00002138 package->folders[index].ParentIndex = i;
2139 TRACE("Parent is index %i... %s %s\n",
2140 package->folders[index].ParentIndex,
Mike McCormackba8200b2004-12-22 15:25:30 +00002141 debugstr_w(package->folders[package->folders[index].ParentIndex].Directory),
Aric Stewartbdb29552004-07-04 00:32:48 +00002142 debugstr_w(parent));
2143 }
2144 else
2145 package->folders[index].ParentIndex = -2;
Mike McCormackba8200b2004-12-22 15:25:30 +00002146 HeapFree(GetProcessHeap(), 0, parent);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002147
Aric Stewartfa384f62004-12-22 18:46:17 +00002148 package->folders[index].Property = load_dynamic_property(package, dir,NULL);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002149
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002150 msiobj_release(&row->hdr);
2151 MSI_ViewClose(view);
2152 msiobj_release(&view->hdr);
Aric Stewartbdb29552004-07-04 00:32:48 +00002153 TRACE(" %s retuning on index %i\n",debugstr_w(dir),index);
2154 return index;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002155}
2156
Mike McCormackba8200b2004-12-22 15:25:30 +00002157
2158static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
Aric Stewartbdb29552004-07-04 00:32:48 +00002159 BOOL source, BOOL set_prop, MSIFOLDER **folder)
Aric Stewarte95136b2004-06-29 03:44:01 +00002160{
Mike McCormack4604e662004-08-06 17:30:20 +00002161 DWORD i;
Mike McCormackba8200b2004-12-22 15:25:30 +00002162 LPWSTR p, path = NULL;
Aric Stewart36eee232004-07-04 00:07:13 +00002163
Aric Stewartbdb29552004-07-04 00:32:48 +00002164 TRACE("Working to resolve %s\n",debugstr_w(name));
Aric Stewart36eee232004-07-04 00:07:13 +00002165
Aric Stewartbdb29552004-07-04 00:32:48 +00002166 /* special resolving for Target and Source root dir */
2167 if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0)
Aric Stewart36eee232004-07-04 00:07:13 +00002168 {
Aric Stewartbdb29552004-07-04 00:32:48 +00002169 if (!source)
Aric Stewart36eee232004-07-04 00:07:13 +00002170 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002171 path = load_dynamic_property(package,cszTargetDir,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00002172 if (!path)
Aric Stewart36eee232004-07-04 00:07:13 +00002173 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002174 path = load_dynamic_property(package,cszRootDrive,NULL);
Aric Stewartbdb29552004-07-04 00:32:48 +00002175 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002176 MSI_SetPropertyW(package,cszTargetDir,path);
Aric Stewart36eee232004-07-04 00:07:13 +00002177 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002178 if (folder)
2179 *folder = &(package->folders[0]);
Mike McCormackba8200b2004-12-22 15:25:30 +00002180 return path;
Aric Stewart36eee232004-07-04 00:07:13 +00002181 }
2182 else
2183 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002184 path = load_dynamic_property(package,cszSourceDir,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00002185 if (!path)
Aric Stewart36eee232004-07-04 00:07:13 +00002186 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002187 path = load_dynamic_property(package,cszDatabase,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00002188 if (path)
Aric Stewart36eee232004-07-04 00:07:13 +00002189 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002190 p = strrchrW(path,'\\');
2191 if (p)
2192 *p++ = 0;
Aric Stewart36eee232004-07-04 00:07:13 +00002193 }
Aric Stewart36eee232004-07-04 00:07:13 +00002194 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002195 if (folder)
2196 *folder = &(package->folders[0]);
Mike McCormackba8200b2004-12-22 15:25:30 +00002197 return path;
Aric Stewart36eee232004-07-04 00:07:13 +00002198 }
2199 }
Aric Stewartbdb29552004-07-04 00:32:48 +00002200
Aric Stewart7d3e5972004-07-04 00:36:58 +00002201 for (i = 0; i < package->loaded_folders; i++)
2202 {
2203 if (strcmpW(package->folders[i].Directory,name)==0)
2204 break;
2205 }
2206
2207 if (i >= package->loaded_folders)
Mike McCormackba8200b2004-12-22 15:25:30 +00002208 return NULL;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002209
2210 if (folder)
2211 *folder = &(package->folders[i]);
2212
Mike McCormackba8200b2004-12-22 15:25:30 +00002213 if (!source && package->folders[i].ResolvedTarget)
Aric Stewartbdb29552004-07-04 00:32:48 +00002214 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002215 path = dupstrW(package->folders[i].ResolvedTarget);
Aric Stewartbdb29552004-07-04 00:32:48 +00002216 TRACE(" already resolved to %s\n",debugstr_w(path));
Mike McCormackba8200b2004-12-22 15:25:30 +00002217 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00002218 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002219 else if (source && package->folders[i].ResolvedSource)
Aric Stewartbdb29552004-07-04 00:32:48 +00002220 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002221 path = dupstrW(package->folders[i].ResolvedSource);
Mike McCormackba8200b2004-12-22 15:25:30 +00002222 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00002223 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002224 else if (!source && package->folders[i].Property)
Aric Stewartbdb29552004-07-04 00:32:48 +00002225 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002226 path = dupstrW(package->folders[i].Property);
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002227 TRACE(" internally set to %s\n",debugstr_w(path));
2228 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002229 MSI_SetPropertyW(package,name,path);
Mike McCormackba8200b2004-12-22 15:25:30 +00002230 return path;
Aric Stewartbdb29552004-07-04 00:32:48 +00002231 }
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002232
Aric Stewartbdb29552004-07-04 00:32:48 +00002233 if (package->folders[i].ParentIndex >= 0)
2234 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002235 LPWSTR parent = package->folders[package->folders[i].ParentIndex].Directory;
Aric Stewartbdb29552004-07-04 00:32:48 +00002236
Mike McCormackba8200b2004-12-22 15:25:30 +00002237 TRACE(" ! Parent is %s\n", debugstr_w(parent));
Robert Shearmandce07c42004-09-17 18:11:14 +00002238
Mike McCormackba8200b2004-12-22 15:25:30 +00002239 p = resolve_folder(package, parent, source, set_prop, NULL);
Aric Stewart1ab0e412004-07-06 18:42:56 +00002240 if (!source)
Aric Stewartbdb29552004-07-04 00:32:48 +00002241 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002242 TRACE(" TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault));
2243 path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00002244 package->folders[i].ResolvedTarget = dupstrW(path);
Aric Stewartbdb29552004-07-04 00:32:48 +00002245 TRACE(" resolved into %s\n",debugstr_w(path));
2246 if (set_prop)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002247 MSI_SetPropertyW(package,name,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00002248 }
Aric Stewart1ab0e412004-07-06 18:42:56 +00002249 else
Aric Stewartbdb29552004-07-04 00:32:48 +00002250 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002251 path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00002252 package->folders[i].ResolvedSource = dupstrW(path);
Aric Stewartbdb29552004-07-04 00:32:48 +00002253 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002254 HeapFree(GetProcessHeap(),0,p);
Aric Stewartbdb29552004-07-04 00:32:48 +00002255 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002256 return path;
Aric Stewarte95136b2004-06-29 03:44:01 +00002257}
2258
Aric Stewart401bd3f2004-06-28 20:34:35 +00002259/*
2260 * Alot is done in this function aside from just the costing.
Mike McCormack6e2bca32004-07-04 00:25:00 +00002261 * The costing needs to be implemented at some point but for now I am going
Aric Stewart401bd3f2004-06-28 20:34:35 +00002262 * to focus on the directory building
2263 *
Aric Stewart401bd3f2004-06-28 20:34:35 +00002264 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002265static UINT ACTION_CostFinalize(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002266{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002267 static const WCHAR ExecSeqQuery[] = {
2268 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
2269 'D','i','r','e','c','t','o','r','y',0};
2270 static const WCHAR ConditionQuery[] = {
2271 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
2272 'C','o','n','d','i','t','i','o','n',0};
2273 static const WCHAR szCosting[] = {
2274 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
2275 static const WCHAR szOne[] = { '1', 0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00002276 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002277 MSIQUERY * view;
Mike McCormack4604e662004-08-06 17:30:20 +00002278 DWORD i;
Aric Stewarte95136b2004-06-29 03:44:01 +00002279
Aric Stewart401bd3f2004-06-28 20:34:35 +00002280 TRACE("Building Directory properties\n");
2281
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002282 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00002283 if (rc == ERROR_SUCCESS)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002284 {
Aric Stewart84837d92004-07-20 01:22:37 +00002285 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002286 if (rc != ERROR_SUCCESS)
2287 {
Aric Stewart84837d92004-07-20 01:22:37 +00002288 MSI_ViewClose(view);
2289 msiobj_release(&view->hdr);
2290 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002291 }
2292
Aric Stewart84837d92004-07-20 01:22:37 +00002293 while (1)
2294 {
2295 WCHAR name[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00002296 LPWSTR path;
Aric Stewart84837d92004-07-20 01:22:37 +00002297 MSIRECORD * row = 0;
2298 DWORD sz;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002299
Aric Stewart84837d92004-07-20 01:22:37 +00002300 rc = MSI_ViewFetch(view,&row);
2301 if (rc != ERROR_SUCCESS)
2302 {
2303 rc = ERROR_SUCCESS;
2304 break;
2305 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002306
Aric Stewart84837d92004-07-20 01:22:37 +00002307 sz=0x100;
2308 MSI_RecordGetStringW(row,1,name,&sz);
2309
2310 /* This helper function now does ALL the work */
2311 TRACE("Dir %s ...\n",debugstr_w(name));
2312 load_folder(package,name);
Mike McCormackba8200b2004-12-22 15:25:30 +00002313 path = resolve_folder(package,name,FALSE,TRUE,NULL);
Aric Stewart84837d92004-07-20 01:22:37 +00002314 TRACE("resolves to %s\n",debugstr_w(path));
Mike McCormackba8200b2004-12-22 15:25:30 +00002315 HeapFree( GetProcessHeap(), 0, path);
Aric Stewart84837d92004-07-20 01:22:37 +00002316
2317 msiobj_release(&row->hdr);
2318 }
2319 MSI_ViewClose(view);
2320 msiobj_release(&view->hdr);
2321 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002322
Aric Stewartec688fb2004-07-04 00:35:52 +00002323 TRACE("File calculations %i files\n",package->loaded_files);
2324
2325 for (i = 0; i < package->loaded_files; i++)
2326 {
2327 MSICOMPONENT* comp = NULL;
2328 MSIFILE* file= NULL;
2329
2330 file = &package->files[i];
2331 if (file->ComponentIndex >= 0)
2332 comp = &package->components[file->ComponentIndex];
2333
Aric Stewartfa384f62004-12-22 18:46:17 +00002334 if (file->Temporary == TRUE)
2335 continue;
2336
Aric Stewartec688fb2004-07-04 00:35:52 +00002337 if (comp)
2338 {
Mike McCormackba8200b2004-12-22 15:25:30 +00002339 LPWSTR p;
2340
Aric Stewartec688fb2004-07-04 00:35:52 +00002341 /* calculate target */
Mike McCormackba8200b2004-12-22 15:25:30 +00002342 p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00002343
2344 if (file->TargetPath)
2345 HeapFree(GetProcessHeap(),0,file->TargetPath);
2346
2347 TRACE("file %s is named %s\n",
2348 debugstr_w(file->File),debugstr_w(file->FileName));
2349
Mike McCormackba8200b2004-12-22 15:25:30 +00002350 file->TargetPath = build_directory_name(2, p, file->FileName);
Aric Stewartec688fb2004-07-04 00:35:52 +00002351
Aric Stewartfa384f62004-12-22 18:46:17 +00002352 HeapFree(GetProcessHeap(),0,p);
2353
Aric Stewartec688fb2004-07-04 00:35:52 +00002354 TRACE("file %s resolves to %s\n",
2355 debugstr_w(file->File),debugstr_w(file->TargetPath));
Aric Stewartfa384f62004-12-22 18:46:17 +00002356
Aric Stewartec688fb2004-07-04 00:35:52 +00002357 if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
2358 {
2359 file->State = 1;
2360 comp->Cost += file->FileSize;
2361 }
2362 else
2363 {
2364 if (file->Version[0])
2365 {
2366 DWORD handle;
2367 DWORD versize;
2368 UINT sz;
2369 LPVOID version;
Aric Stewart120009e2004-10-08 23:35:35 +00002370 static const WCHAR name[] =
2371 {'\\',0};
2372 static const WCHAR name_fmt[] =
2373 {'%','u','.','%','u','.','%','u','.','%','u',0};
Aric Stewartec688fb2004-07-04 00:35:52 +00002374 WCHAR filever[0x100];
Aric Stewart120009e2004-10-08 23:35:35 +00002375 VS_FIXEDFILEINFO *lpVer;
Aric Stewartec688fb2004-07-04 00:35:52 +00002376
Aric Stewart120009e2004-10-08 23:35:35 +00002377 FIXME("Version comparison.. \n");
Aric Stewartec688fb2004-07-04 00:35:52 +00002378 versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
2379 version = HeapAlloc(GetProcessHeap(),0,versize);
2380 GetFileVersionInfoW(file->TargetPath, 0, versize, version);
Aric Stewart120009e2004-10-08 23:35:35 +00002381
2382 VerQueryValueW(version, name, (LPVOID*)&lpVer, &sz);
2383
2384 sprintfW(filever,name_fmt,
2385 HIWORD(lpVer->dwFileVersionMS),
2386 LOWORD(lpVer->dwFileVersionMS),
2387 HIWORD(lpVer->dwFileVersionLS),
2388 LOWORD(lpVer->dwFileVersionLS));
2389
2390 TRACE("new %s old %s\n", debugstr_w(file->Version),
2391 debugstr_w(filever));
2392 if (strcmpiW(filever,file->Version)<0)
Aric Stewartec688fb2004-07-04 00:35:52 +00002393 {
2394 file->State = 2;
2395 FIXME("cost should be diff in size\n");
2396 comp->Cost += file->FileSize;
2397 }
2398 else
2399 file->State = 3;
Aric Stewart120009e2004-10-08 23:35:35 +00002400 HeapFree(GetProcessHeap(),0,version);
Aric Stewartec688fb2004-07-04 00:35:52 +00002401 }
2402 else
2403 file->State = 3;
2404 }
2405 }
2406 }
2407
Aric Stewart7d3e5972004-07-04 00:36:58 +00002408 TRACE("Evaluating Condition Table\n");
Aric Stewart2e9b5f72004-07-04 00:31:17 +00002409
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002410 rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view);
Aric Stewart84837d92004-07-20 01:22:37 +00002411 if (rc == ERROR_SUCCESS)
2412 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002413 rc = MSI_ViewExecute(view, 0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002414 if (rc != ERROR_SUCCESS)
2415 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002416 MSI_ViewClose(view);
2417 msiobj_release(&view->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002418 return rc;
2419 }
2420
2421 while (1)
2422 {
2423 WCHAR Feature[0x100];
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002424 MSIRECORD * row = 0;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002425 DWORD sz;
2426 int feature_index;
2427
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002428 rc = MSI_ViewFetch(view,&row);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002429
2430 if (rc != ERROR_SUCCESS)
2431 {
2432 rc = ERROR_SUCCESS;
2433 break;
2434 }
2435
2436 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002437 MSI_RecordGetStringW(row,1,Feature,&sz);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002438
2439 feature_index = get_loaded_feature(package,Feature);
2440 if (feature_index < 0)
2441 ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature));
2442 else
2443 {
Aric Stewart7231a432004-07-09 19:26:30 +00002444 LPWSTR Condition;
2445 Condition = load_dynamic_stringW(row,3);
2446
Aric Stewart84837d92004-07-20 01:22:37 +00002447 if (MSI_EvaluateConditionW(package,Condition) ==
2448 MSICONDITION_TRUE)
Aric Stewart7d3e5972004-07-04 00:36:58 +00002449 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002450 int level = MSI_RecordGetInteger(row,2);
Aric Stewart84837d92004-07-20 01:22:37 +00002451 TRACE("Reseting feature %s to level %i\n",
2452 debugstr_w(Feature), level);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002453 package->features[feature_index].Level = level;
2454 }
Aric Stewart7231a432004-07-09 19:26:30 +00002455 HeapFree(GetProcessHeap(),0,Condition);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002456 }
2457
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002458 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002459 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002460 MSI_ViewClose(view);
2461 msiobj_release(&view->hdr);
Aric Stewart84837d92004-07-20 01:22:37 +00002462 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00002463
2464 TRACE("Enabling or Disabling Components\n");
2465 for (i = 0; i < package->loaded_components; i++)
2466 {
2467 if (package->components[i].Condition[0])
2468 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002469 if (MSI_EvaluateConditionW(package,
Aric Stewart7d3e5972004-07-04 00:36:58 +00002470 package->components[i].Condition) == MSICONDITION_FALSE)
2471 {
2472 TRACE("Disabling component %s\n",
2473 debugstr_w(package->components[i].Component));
2474 package->components[i].Enabled = FALSE;
2475 }
2476 }
2477 }
2478
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002479 MSI_SetPropertyW(package,szCosting,szOne);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002480 return ERROR_SUCCESS;
2481}
2482
2483/*
2484 * This is a helper function for handling embedded cabinet media
2485 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002486static UINT writeout_cabinet_stream(MSIPACKAGE *package, WCHAR* stream_name,
Aric Stewart401bd3f2004-06-28 20:34:35 +00002487 WCHAR* source)
2488{
2489 UINT rc;
2490 USHORT* data;
2491 UINT size;
2492 DWORD write;
2493 HANDLE the_file;
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002494 WCHAR tmp[MAX_PATH];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002495
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002496 rc = read_raw_stream_data(package->db,stream_name,&data,&size);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002497 if (rc != ERROR_SUCCESS)
2498 return rc;
2499
Aric Stewartbdb29552004-07-04 00:32:48 +00002500 write = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002501 if (MSI_GetPropertyW(package, cszTempFolder, tmp, &write))
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002502 GetTempPathW(MAX_PATH,tmp);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002503
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002504 GetTempFileNameW(tmp,stream_name,0,source);
2505
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002506 track_tempfile(package,strrchrW(source,'\\'), source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002507 the_file = CreateFileW(source, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2508 FILE_ATTRIBUTE_NORMAL, NULL);
2509
2510 if (the_file == INVALID_HANDLE_VALUE)
2511 {
2512 rc = ERROR_FUNCTION_FAILED;
2513 goto end;
2514 }
2515
2516 WriteFile(the_file,data,size,&write,NULL);
2517 CloseHandle(the_file);
2518 TRACE("wrote %li bytes to %s\n",write,debugstr_w(source));
2519end:
2520 HeapFree(GetProcessHeap(),0,data);
2521 return rc;
2522}
2523
Aric Stewart401bd3f2004-06-28 20:34:35 +00002524
Robert Shearman3d7299b2004-09-10 22:29:49 +00002525/* Support functions for FDI functions */
2526
2527static void * cabinet_alloc(ULONG cb)
2528{
2529 return HeapAlloc(GetProcessHeap(), 0, cb);
2530}
2531
2532static void cabinet_free(void *pv)
2533{
2534 HeapFree(GetProcessHeap(), 0, pv);
2535}
2536
2537static INT_PTR cabinet_open(char *pszFile, int oflag, int pmode)
2538{
2539 DWORD dwAccess = 0;
2540 DWORD dwShareMode = 0;
2541 DWORD dwCreateDisposition = OPEN_EXISTING;
2542 switch (oflag & _O_ACCMODE)
2543 {
2544 case _O_RDONLY:
2545 dwAccess = GENERIC_READ;
2546 dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
2547 break;
2548 case _O_WRONLY:
2549 dwAccess = GENERIC_WRITE;
2550 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
2551 break;
2552 case _O_RDWR:
2553 dwAccess = GENERIC_READ | GENERIC_WRITE;
2554 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
2555 break;
2556 }
2557 if ((oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
2558 dwCreateDisposition = CREATE_NEW;
2559 else if (oflag & _O_CREAT)
2560 dwCreateDisposition = CREATE_ALWAYS;
2561 return (INT_PTR)CreateFileA(pszFile, dwAccess, dwShareMode, NULL, dwCreateDisposition, 0, NULL);
2562}
2563
2564static UINT cabinet_read(INT_PTR hf, void *pv, UINT cb)
2565{
2566 DWORD dwRead;
2567 if (ReadFile((HANDLE)hf, pv, cb, &dwRead, NULL))
2568 return dwRead;
2569 return 0;
2570}
2571
2572static UINT cabinet_write(INT_PTR hf, void *pv, UINT cb)
2573{
2574 DWORD dwWritten;
2575 if (WriteFile((HANDLE)hf, pv, cb, &dwWritten, NULL))
2576 return dwWritten;
2577 return 0;
2578}
2579
2580static int cabinet_close(INT_PTR hf)
2581{
2582 return CloseHandle((HANDLE)hf) ? 0 : -1;
2583}
2584
2585static long cabinet_seek(INT_PTR hf, long dist, int seektype)
2586{
2587 /* flags are compatible and so are passed straight through */
2588 return SetFilePointer((HANDLE)hf, dist, NULL, seektype);
2589}
2590
2591static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
2592{
2593 /* FIXME: try to do more processing in this function */
2594 switch (fdint)
2595 {
2596 case fdintCOPY_FILE:
2597 {
2598 ULONG len = strlen((char*)pfdin->pv) + strlen(pfdin->psz1);
2599 char *file = cabinet_alloc((len+1)*sizeof(char));
2600
2601 strcpy(file, (char*)pfdin->pv);
2602 strcat(file, pfdin->psz1);
2603
2604 TRACE("file: %s\n", debugstr_a(file));
2605
2606 return cabinet_open(file, _O_WRONLY | _O_CREAT, 0);
2607 }
2608 case fdintCLOSE_FILE_INFO:
2609 {
2610 FILETIME ft;
2611 FILETIME ftLocal;
2612 if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
2613 return -1;
2614 if (!LocalFileTimeToFileTime(&ft, &ftLocal))
2615 return -1;
2616 if (!SetFileTime((HANDLE)pfdin->hf, &ftLocal, 0, &ftLocal))
2617 return -1;
2618
2619 cabinet_close(pfdin->hf);
2620 return 1;
2621 }
2622 default:
2623 return 0;
2624 }
2625}
2626
Aric Stewart401bd3f2004-06-28 20:34:35 +00002627/***********************************************************************
2628 * extract_cabinet_file
2629 *
Robert Shearman3d7299b2004-09-10 22:29:49 +00002630 * Extract files from a cab file.
Aric Stewart401bd3f2004-06-28 20:34:35 +00002631 */
Aric Stewart36eee232004-07-04 00:07:13 +00002632static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path)
2633{
Robert Shearman3d7299b2004-09-10 22:29:49 +00002634 HFDI hfdi;
2635 ERF erf;
2636 BOOL ret;
2637 char *cabinet;
2638 char *cab_path;
2639
Aric Stewarte2d4ea82004-07-04 00:33:45 +00002640 TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));
Robert Shearman3d7299b2004-09-10 22:29:49 +00002641
2642 hfdi = FDICreate(cabinet_alloc,
2643 cabinet_free,
2644 cabinet_open,
2645 cabinet_read,
2646 cabinet_write,
2647 cabinet_close,
2648 cabinet_seek,
2649 0,
2650 &erf);
2651 if (!hfdi)
2652 {
2653 ERR("FDICreate failed\n");
2654 return FALSE;
2655 }
2656
2657 if (!(cabinet = strdupWtoA( source )))
2658 {
2659 FDIDestroy(hfdi);
2660 return FALSE;
2661 }
2662 if (!(cab_path = strdupWtoA( path )))
2663 {
2664 FDIDestroy(hfdi);
2665 HeapFree(GetProcessHeap(), 0, cabinet);
2666 return FALSE;
2667 }
2668
2669 ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, cab_path);
2670
2671 if (!ret)
2672 ERR("FDICopy failed\n");
2673
2674 FDIDestroy(hfdi);
2675
2676 HeapFree(GetProcessHeap(), 0, cabinet);
2677 HeapFree(GetProcessHeap(), 0, cab_path);
2678
2679 return ret;
Aric Stewart36eee232004-07-04 00:07:13 +00002680}
2681
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002682static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence,
Aric Stewart401bd3f2004-06-28 20:34:35 +00002683 WCHAR* path)
2684{
2685 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002686 MSIQUERY * view;
2687 MSIRECORD * row = 0;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002688 WCHAR source[MAX_PATH];
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002689 static const WCHAR ExecSeqQuery[] = {
2690 's','e','l','e','c','t',' ','*',' ',
2691 'f','r','o','m',' ','M','e','d','i','a',' ',
2692 'w','h','e','r','e',' ','L','a','s','t','S','e','q','u','e','n','c','e',' ','>','=',' ','%','i',' ',
2693 'o','r','d','e','r',' ','b','y',' ','L','a','s','t','S','e','q','u','e','n','c','e',0};
2694 WCHAR Query[1024];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002695 WCHAR cab[0x100];
2696 DWORD sz=0x100;
2697 INT seq;
Mike McCormack4604e662004-08-06 17:30:20 +00002698 static UINT last_sequence = 0;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002699
2700 if (sequence <= last_sequence)
2701 {
Mike McCormack4604e662004-08-06 17:30:20 +00002702 TRACE("Media already ready (%u, %u)\n",sequence,last_sequence);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002703 return ERROR_SUCCESS;
2704 }
2705
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002706 sprintfW(Query,ExecSeqQuery,sequence);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002707
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002708 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002709 if (rc != ERROR_SUCCESS)
2710 return rc;
2711
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002712 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002713 if (rc != ERROR_SUCCESS)
2714 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002715 MSI_ViewClose(view);
2716 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002717 return rc;
2718 }
2719
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002720 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002721 if (rc != ERROR_SUCCESS)
2722 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002723 MSI_ViewClose(view);
2724 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002725 return rc;
2726 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002727 seq = MSI_RecordGetInteger(row,2);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002728 last_sequence = seq;
2729
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002730 if (!MSI_RecordIsNull(row,4))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002731 {
2732 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002733 MSI_RecordGetStringW(row,4,cab,&sz);
Aric Stewartbdb29552004-07-04 00:32:48 +00002734 TRACE("Source is CAB %s\n",debugstr_w(cab));
Aric Stewart401bd3f2004-06-28 20:34:35 +00002735 /* the stream does not contain the # character */
2736 if (cab[0]=='#')
2737 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002738 writeout_cabinet_stream(package,&cab[1],source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002739 strcpyW(path,source);
2740 *(strrchrW(path,'\\')+1)=0;
2741 }
2742 else
2743 {
Aric Stewart7231a432004-07-09 19:26:30 +00002744 sz = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002745 if (MSI_GetPropertyW(package, cszSourceDir, source, &sz))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002746 {
2747 ERR("No Source dir defined \n");
2748 rc = ERROR_FUNCTION_FAILED;
2749 }
2750 else
2751 {
2752 strcpyW(path,source);
2753 strcatW(source,cab);
Aric Stewartbdb29552004-07-04 00:32:48 +00002754 /* extract the cab file into a folder in the temp folder */
2755 sz = MAX_PATH;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002756 if (MSI_GetPropertyW(package, cszTempFolder,path, &sz)
Aric Stewartbdb29552004-07-04 00:32:48 +00002757 != ERROR_SUCCESS)
2758 GetTempPathW(MAX_PATH,path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002759 }
2760 }
2761 rc = !extract_cabinet_file(source,path);
2762 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002763 msiobj_release(&row->hdr);
2764 MSI_ViewClose(view);
2765 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002766 return rc;
2767}
2768
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002769inline static UINT create_component_directory ( MSIPACKAGE* package, INT component)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002770{
2771 UINT rc;
Aric Stewartbdb29552004-07-04 00:32:48 +00002772 MSIFOLDER *folder;
Mike McCormackba8200b2004-12-22 15:25:30 +00002773 LPWSTR install_path;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002774
Mike McCormackba8200b2004-12-22 15:25:30 +00002775 install_path = resolve_folder(package, package->components[component].Directory,
2776 FALSE, FALSE, &folder);
2777 if (!install_path)
2778 return ERROR_FUNCTION_FAILED;
Aric Stewartbdb29552004-07-04 00:32:48 +00002779
2780 /* create the path */
2781 if (folder->State == 0)
2782 {
2783 create_full_pathW(install_path);
2784 folder->State = 2;
2785 }
Mike McCormackba8200b2004-12-22 15:25:30 +00002786 HeapFree(GetProcessHeap(), 0, install_path);
Aric Stewartbdb29552004-07-04 00:32:48 +00002787
Aric Stewart401bd3f2004-06-28 20:34:35 +00002788 return rc;
2789}
2790
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002791static UINT ACTION_InstallFiles(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002792{
Aric Stewartec688fb2004-07-04 00:35:52 +00002793 UINT rc = ERROR_SUCCESS;
Mike McCormack4604e662004-08-06 17:30:20 +00002794 DWORD index;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002795 MSIRECORD * uirow;
Aric Stewartd2c395a2004-07-06 18:48:15 +00002796 WCHAR uipath[MAX_PATH];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002797
Aric Stewartec688fb2004-07-04 00:35:52 +00002798 if (!package)
2799 return ERROR_INVALID_HANDLE;
2800
Aric Stewartd2c395a2004-07-06 18:48:15 +00002801 /* increment progress bar each time action data is sent */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002802 ui_progress(package,1,1,1,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002803
Aric Stewartec688fb2004-07-04 00:35:52 +00002804 for (index = 0; index < package->loaded_files; index++)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002805 {
Aric Stewart401bd3f2004-06-28 20:34:35 +00002806 WCHAR path_to_source[MAX_PATH];
Aric Stewartec688fb2004-07-04 00:35:52 +00002807 MSIFILE *file;
2808
2809 file = &package->files[index];
Aric Stewart401bd3f2004-06-28 20:34:35 +00002810
Aric Stewart7d3e5972004-07-04 00:36:58 +00002811 if (file->Temporary)
2812 continue;
2813
2814 if (!package->components[file->ComponentIndex].Enabled ||
2815 !package->components[file->ComponentIndex].FeatureState)
2816 {
2817 TRACE("File %s is not scheduled for install\n",
2818 debugstr_w(file->File));
2819 continue;
2820 }
2821
Aric Stewartec688fb2004-07-04 00:35:52 +00002822 if ((file->State == 1) || (file->State == 2))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002823 {
Aric Stewartec688fb2004-07-04 00:35:52 +00002824 TRACE("Installing %s\n",debugstr_w(file->File));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002825 rc = ready_media_for_file(package,file->Sequence,path_to_source);
Aric Stewartec688fb2004-07-04 00:35:52 +00002826 /*
2827 * WARNING!
2828 * our file table could change here because a new temp file
2829 * may have been created
2830 */
2831 file = &package->files[index];
2832 if (rc != ERROR_SUCCESS)
2833 {
2834 ERR("Unable to ready media\n");
2835 rc = ERROR_FUNCTION_FAILED;
2836 break;
2837 }
2838
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002839 create_component_directory( package, file->ComponentIndex);
Aric Stewartec688fb2004-07-04 00:35:52 +00002840
2841 strcpyW(file->SourcePath, path_to_source);
2842 strcatW(file->SourcePath, file->File);
2843
2844 TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
2845 debugstr_w(file->TargetPath));
2846
Aric Stewartd2c395a2004-07-06 18:48:15 +00002847 /* the UI chunk */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002848 uirow=MSI_CreateRecord(9);
2849 MSI_RecordSetStringW(uirow,1,file->File);
Aric Stewartd2c395a2004-07-06 18:48:15 +00002850 strcpyW(uipath,file->TargetPath);
2851 *(strrchrW(uipath,'\\')+1)=0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002852 MSI_RecordSetStringW(uirow,9,uipath);
2853 MSI_RecordSetInteger(uirow,6,file->FileSize);
2854 ui_actiondata(package,szInstallFiles,uirow);
2855 msiobj_release( &uirow->hdr );
Aric Stewartd2c395a2004-07-06 18:48:15 +00002856
Robert Shearman3d7299b2004-09-10 22:29:49 +00002857 if (!MoveFileW(file->SourcePath,file->TargetPath))
Aric Stewartb942e182004-07-06 18:50:02 +00002858 {
Robert Shearman3d7299b2004-09-10 22:29:49 +00002859 rc = GetLastError();
Aric Stewart120009e2004-10-08 23:35:35 +00002860 ERR("Unable to move file (%s -> %s) (error %d)\n",
2861 debugstr_w(file->SourcePath), debugstr_w(file->TargetPath),
2862 rc);
2863 if (rc == ERROR_ALREADY_EXISTS && file->State == 2)
2864 {
2865 CopyFileW(file->SourcePath,file->TargetPath,FALSE);
2866 DeleteFileW(file->SourcePath);
2867 rc = 0;
2868 }
2869 else
2870 break;
Aric Stewartb942e182004-07-06 18:50:02 +00002871 }
Aric Stewartec688fb2004-07-04 00:35:52 +00002872 else
2873 file->State = 4;
Robert Shearman3d7299b2004-09-10 22:29:49 +00002874
2875 ui_progress(package,2,0,0,0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002876 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002877 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002878
2879 return rc;
2880}
2881
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002882inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key,
Aric Stewartfa384f62004-12-22 18:46:17 +00002883 LPWSTR* file_source)
Aric Stewartec688fb2004-07-04 00:35:52 +00002884{
Mike McCormack4604e662004-08-06 17:30:20 +00002885 DWORD index;
Aric Stewartec688fb2004-07-04 00:35:52 +00002886
Aric Stewartec688fb2004-07-04 00:35:52 +00002887 if (!package)
2888 return ERROR_INVALID_HANDLE;
2889
2890 for (index = 0; index < package->loaded_files; index ++)
2891 {
2892 if (strcmpW(file_key,package->files[index].File)==0)
2893 {
Aric Stewart7d3e5972004-07-04 00:36:58 +00002894 if (package->files[index].State >= 3)
2895 {
Aric Stewartfa384f62004-12-22 18:46:17 +00002896 *file_source = dupstrW(package->files[index].TargetPath);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002897 return ERROR_SUCCESS;
2898 }
2899 else
2900 return ERROR_FILE_NOT_FOUND;
Aric Stewartec688fb2004-07-04 00:35:52 +00002901 }
2902 }
2903
2904 return ERROR_FUNCTION_FAILED;
2905}
2906
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002907static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00002908{
2909 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002910 MSIQUERY * view;
2911 MSIRECORD * row = 0;
2912 static const WCHAR ExecSeqQuery[] = {
2913 's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ',
2914 'D','u','p','l','i','c','a','t','e','F','i','l','e',0};
Aric Stewart401bd3f2004-06-28 20:34:35 +00002915
Aric Stewart7d3e5972004-07-04 00:36:58 +00002916 if (!package)
2917 return ERROR_INVALID_HANDLE;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002918
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002919 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002920 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00002921 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002922
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002923 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002924 if (rc != ERROR_SUCCESS)
2925 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002926 MSI_ViewClose(view);
2927 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002928 return rc;
2929 }
2930
2931 while (1)
2932 {
2933 WCHAR file_key[0x100];
Aric Stewartfa384f62004-12-22 18:46:17 +00002934 WCHAR *file_source = NULL;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002935 WCHAR dest_name[0x100];
Mike McCormackba8200b2004-12-22 15:25:30 +00002936 LPWSTR dest_path, dest;
Aric Stewart7d3e5972004-07-04 00:36:58 +00002937 WCHAR component[0x100];
2938 INT component_index;
Aric Stewart401bd3f2004-06-28 20:34:35 +00002939
2940 DWORD sz=0x100;
2941
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002942 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002943 if (rc != ERROR_SUCCESS)
2944 {
2945 rc = ERROR_SUCCESS;
2946 break;
2947 }
2948
2949 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002950 rc = MSI_RecordGetStringW(row,2,component,&sz);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002951 if (rc != ERROR_SUCCESS)
2952 {
2953 ERR("Unable to get component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002954 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002955 break;
2956 }
2957
2958 component_index = get_loaded_component(package,component);
2959 if (!package->components[component_index].Enabled ||
2960 !package->components[component_index].FeatureState)
2961 {
2962 TRACE("Skipping copy due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002963 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00002964 continue;
2965 }
2966
2967 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002968 rc = MSI_RecordGetStringW(row,3,file_key,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002969 if (rc != ERROR_SUCCESS)
2970 {
2971 ERR("Unable to get file key\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002972 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002973 break;
2974 }
2975
Aric Stewartfa384f62004-12-22 18:46:17 +00002976 rc = get_file_target(package,file_key,&file_source);
Aric Stewartec688fb2004-07-04 00:35:52 +00002977
Aric Stewart401bd3f2004-06-28 20:34:35 +00002978 if (rc != ERROR_SUCCESS)
2979 {
2980 ERR("Original file unknown %s\n",debugstr_w(file_key));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002981 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00002982 if (file_source)
2983 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002984 break;
2985 }
2986
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002987 if (MSI_RecordIsNull(row,4))
Aric Stewartec688fb2004-07-04 00:35:52 +00002988 {
Aric Stewart401bd3f2004-06-28 20:34:35 +00002989 strcpyW(dest_name,strrchrW(file_source,'\\')+1);
Aric Stewartec688fb2004-07-04 00:35:52 +00002990 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00002991 else
2992 {
2993 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002994 MSI_RecordGetStringW(row,4,dest_name,&sz);
Aric Stewart401bd3f2004-06-28 20:34:35 +00002995 reduce_to_longfilename(dest_name);
2996 }
2997
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00002998 if (MSI_RecordIsNull(row,5))
Aric Stewart401bd3f2004-06-28 20:34:35 +00002999 {
Mike McCormackba8200b2004-12-22 15:25:30 +00003000 LPWSTR p;
Aric Stewartfa384f62004-12-22 18:46:17 +00003001 dest_path = dupstrW(file_source);
Mike McCormackba8200b2004-12-22 15:25:30 +00003002 p = strrchrW(dest_path,'\\');
3003 if (p)
3004 *p=0;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003005 }
3006 else
3007 {
3008 WCHAR destkey[0x100];
3009 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003010 MSI_RecordGetStringW(row,5,destkey,&sz);
Aric Stewarte95136b2004-06-29 03:44:01 +00003011 sz = 0x100;
Mike McCormackba8200b2004-12-22 15:25:30 +00003012 dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL);
3013 if (!dest_path)
Aric Stewart401bd3f2004-06-28 20:34:35 +00003014 {
3015 ERR("Unable to get destination folder\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003016 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00003017 if (file_source)
3018 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003019 break;
3020 }
3021 }
3022
Mike McCormackba8200b2004-12-22 15:25:30 +00003023 dest = build_directory_name(2, dest_path, dest_name);
3024 HeapFree(GetProcessHeap(), 0, dest_path);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003025
3026 TRACE("Duplicating file %s to %s\n",debugstr_w(file_source),
Aric Stewartfa384f62004-12-22 18:46:17 +00003027 debugstr_w(dest));
Aric Stewart401bd3f2004-06-28 20:34:35 +00003028
Aric Stewartfa384f62004-12-22 18:46:17 +00003029 if (strcmpW(file_source,dest))
3030 rc = !CopyFileW(file_source,dest,TRUE);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003031 else
3032 rc = ERROR_SUCCESS;
3033
3034 if (rc != ERROR_SUCCESS)
3035 ERR("Failed to copy file\n");
Aric Stewartec688fb2004-07-04 00:35:52 +00003036
3037 FIXME("We should track these duplicate files as well\n");
3038
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003039 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00003040 HeapFree(GetProcessHeap(),0,dest);
3041 HeapFree(GetProcessHeap(),0,file_source);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003042 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003043 MSI_ViewClose(view);
3044 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003045 return rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003046}
3047
3048
Mike McCormack6e2bca32004-07-04 00:25:00 +00003049/* OK this value is "interpretted" and then formatted based on the
Aric Stewart6e160f12004-06-29 04:07:22 +00003050 first few characters */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003051static LPSTR parse_value(MSIPACKAGE *package, WCHAR *value, DWORD *type,
Aric Stewart401bd3f2004-06-28 20:34:35 +00003052 DWORD *size)
3053{
3054 LPSTR data = NULL;
Aric Stewart6e160f12004-06-29 04:07:22 +00003055 if (value[0]=='#' && value[1]!='#' && value[1]!='%')
Aric Stewart401bd3f2004-06-28 20:34:35 +00003056 {
Aric Stewart6e160f12004-06-29 04:07:22 +00003057 if (value[1]=='x')
3058 {
3059 LPWSTR ptr;
3060 CHAR byte[5];
3061 LPWSTR deformated;
3062 int count;
3063
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003064 deformat_string(package, &value[2], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00003065
3066 /* binary value type */
3067 ptr = deformated;
3068 *type=REG_BINARY;
3069 *size = strlenW(ptr)/2;
3070 data = HeapAlloc(GetProcessHeap(),0,*size);
3071
3072 byte[0] = '0';
3073 byte[1] = 'x';
3074 byte[4] = 0;
3075 count = 0;
3076 while (*ptr)
3077 {
3078 byte[2]= *ptr;
3079 ptr++;
3080 byte[3]= *ptr;
3081 ptr++;
3082 data[count] = (BYTE)strtol(byte,NULL,0);
3083 count ++;
3084 }
3085 HeapFree(GetProcessHeap(),0,deformated);
3086
3087 TRACE("Data %li bytes(%i)\n",*size,count);
3088 }
3089 else
3090 {
3091 LPWSTR deformated;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003092 deformat_string(package, &value[1], &deformated);
Aric Stewart6e160f12004-06-29 04:07:22 +00003093
3094 *type=REG_DWORD;
3095 *size = sizeof(DWORD);
3096 data = HeapAlloc(GetProcessHeap(),0,*size);
3097 *(LPDWORD)data = atoiW(deformated);
3098 TRACE("DWORD %i\n",*data);
3099
3100 HeapFree(GetProcessHeap(),0,deformated);
3101 }
Aric Stewart401bd3f2004-06-28 20:34:35 +00003102 }
3103 else
3104 {
3105 WCHAR *ptr;
Aric Stewart6e160f12004-06-29 04:07:22 +00003106 *type=REG_SZ;
3107
Aric Stewart401bd3f2004-06-28 20:34:35 +00003108 if (value[0]=='#')
Aric Stewart6e160f12004-06-29 04:07:22 +00003109 {
3110 if (value[1]=='%')
3111 {
3112 ptr = &value[2];
3113 *type=REG_EXPAND_SZ;
3114 }
3115 else
3116 ptr = &value[1];
3117 }
3118 else
Aric Stewart401bd3f2004-06-28 20:34:35 +00003119 ptr=value;
3120
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003121 *size = deformat_string(package, ptr,(LPWSTR*)&data);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003122 }
3123 return data;
3124}
3125
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003126static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
Aric Stewart401bd3f2004-06-28 20:34:35 +00003127{
3128 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003129 MSIQUERY * view;
3130 MSIRECORD * row = 0;
3131 static const WCHAR ExecSeqQuery[] = {
3132 's','e','l','e','c','t',' ','*',' ',
3133 'f','r','o','m',' ','R','e','g','i','s','t','r','y',0 };
Aric Stewart401bd3f2004-06-28 20:34:35 +00003134
Aric Stewart7d3e5972004-07-04 00:36:58 +00003135 if (!package)
3136 return ERROR_INVALID_HANDLE;
3137
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003138 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003139 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003140 return ERROR_SUCCESS;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003141
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003142 rc = MSI_ViewExecute(view, 0);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003143 if (rc != ERROR_SUCCESS)
3144 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003145 MSI_ViewClose(view);
3146 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003147 return rc;
3148 }
3149
Aric Stewartd2c395a2004-07-06 18:48:15 +00003150 /* increment progress bar each time action data is sent */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003151 ui_progress(package,1,1,1,0);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003152
Aric Stewart401bd3f2004-06-28 20:34:35 +00003153 while (1)
3154 {
Aric Stewartd2c395a2004-07-06 18:48:15 +00003155 static const WCHAR szHCR[] =
3156{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T','\\',0};
3157 static const WCHAR szHCU[] =
3158{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',0};
3159 static const WCHAR szHLM[] =
3160{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',
3161'\\',0};
3162 static const WCHAR szHU[] =
3163{'H','K','E','Y','_','U','S','E','R','S','\\',0};
3164
Aric Stewart401bd3f2004-06-28 20:34:35 +00003165 LPSTR value_data = NULL;
3166 HKEY root_key, hkey;
3167 DWORD type,size;
Mike McCormack9db0e072004-12-22 15:05:07 +00003168 LPWSTR value, key, name, component;
3169 LPCWSTR szRoot;
Aric Stewart7d3e5972004-07-04 00:36:58 +00003170 INT component_index;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003171 MSIRECORD * uirow;
Mike McCormack9db0e072004-12-22 15:05:07 +00003172 LPWSTR uikey;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003173 INT root;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003174
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003175 rc = MSI_ViewFetch(view,&row);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003176 if (rc != ERROR_SUCCESS)
3177 {
3178 rc = ERROR_SUCCESS;
3179 break;
3180 }
3181
Mike McCormack9db0e072004-12-22 15:05:07 +00003182 value = NULL;
3183 key = NULL;
3184 uikey = NULL;
3185 name = NULL;
3186
3187 component = load_dynamic_stringW(row, 6);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003188 component_index = get_loaded_component(package,component);
3189
3190 if (!package->components[component_index].Enabled ||
3191 !package->components[component_index].FeatureState)
3192 {
3193 TRACE("Skipping write due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003194 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00003195 goto next;
Aric Stewart7d3e5972004-07-04 00:36:58 +00003196 }
3197
Aric Stewart401bd3f2004-06-28 20:34:35 +00003198 /* null values have special meanings during uninstalls and such */
3199
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003200 if(MSI_RecordIsNull(row,5))
Aric Stewart401bd3f2004-06-28 20:34:35 +00003201 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003202 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00003203 goto next;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003204 }
3205
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003206 root = MSI_RecordGetInteger(row,2);
Mike McCormack9db0e072004-12-22 15:05:07 +00003207 key = load_dynamic_stringW(row, 3);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003208
Mike McCormack9db0e072004-12-22 15:05:07 +00003209 name = load_dynamic_stringW(row, 4);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003210
Aric Stewart401bd3f2004-06-28 20:34:35 +00003211 /* get the root key */
3212 switch (root)
3213 {
Aric Stewartd2c395a2004-07-06 18:48:15 +00003214 case 0: root_key = HKEY_CLASSES_ROOT;
Mike McCormack9db0e072004-12-22 15:05:07 +00003215 szRoot = szHCR;
3216 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00003217 case 1: root_key = HKEY_CURRENT_USER;
Mike McCormack9db0e072004-12-22 15:05:07 +00003218 szRoot = szHCU;
3219 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00003220 case 2: root_key = HKEY_LOCAL_MACHINE;
Mike McCormack9db0e072004-12-22 15:05:07 +00003221 szRoot = szHLM;
3222 break;
Aric Stewartd2c395a2004-07-06 18:48:15 +00003223 case 3: root_key = HKEY_USERS;
Mike McCormack9db0e072004-12-22 15:05:07 +00003224 szRoot = szHU;
3225 break;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003226 default:
3227 ERR("Unknown root %i\n",root);
3228 root_key=NULL;
Mike McCormack9db0e072004-12-22 15:05:07 +00003229 szRoot = NULL;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003230 break;
3231 }
3232 if (!root_key)
3233 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003234 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00003235 goto next;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003236 }
3237
Mike McCormack9db0e072004-12-22 15:05:07 +00003238 size = strlenW(key) + strlenW(szRoot) + 1;
3239 uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
3240 strcpyW(uikey,szRoot);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003241 strcatW(uikey,key);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003242 if (RegCreateKeyW( root_key, key, &hkey))
3243 {
3244 ERR("Could not create key %s\n",debugstr_w(key));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003245 msiobj_release(&row->hdr);
Mike McCormack9db0e072004-12-22 15:05:07 +00003246 goto next;
Aric Stewart6e160f12004-06-29 04:07:22 +00003247 }
3248
Aric Stewart7231a432004-07-09 19:26:30 +00003249 value = load_dynamic_stringW(row,5);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003250 value_data = parse_value(package, value, &type, &size);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003251
3252 if (value_data)
3253 {
3254 TRACE("Setting value %s\n",debugstr_w(name));
3255 RegSetValueExW(hkey, name, 0, type, value_data, size);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003256
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003257 uirow = MSI_CreateRecord(3);
3258 MSI_RecordSetStringW(uirow,2,name);
3259 MSI_RecordSetStringW(uirow,1,uikey);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003260
3261 if (type == REG_SZ)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003262 MSI_RecordSetStringW(uirow,3,(LPWSTR)value_data);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003263 else
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003264 MSI_RecordSetStringW(uirow,3,value);
Aric Stewartd2c395a2004-07-06 18:48:15 +00003265
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003266 ui_actiondata(package,szWriteRegistryValues,uirow);
3267 ui_progress(package,2,0,0,0);
3268 msiobj_release( &uirow->hdr );
Aric Stewartd2c395a2004-07-06 18:48:15 +00003269
Aric Stewart401bd3f2004-06-28 20:34:35 +00003270 HeapFree(GetProcessHeap(),0,value_data);
3271 }
Aric Stewartd2c395a2004-07-06 18:48:15 +00003272 HeapFree(GetProcessHeap(),0,value);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003273
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003274 msiobj_release(&row->hdr);
Aric Stewartb942e182004-07-06 18:50:02 +00003275 RegCloseKey(hkey);
Mike McCormack9db0e072004-12-22 15:05:07 +00003276next:
3277 if (uikey)
3278 HeapFree(GetProcessHeap(),0,uikey);
3279 if (key)
3280 HeapFree(GetProcessHeap(),0,key);
3281 if (name)
3282 HeapFree(GetProcessHeap(),0,name);
3283 if (component)
3284 HeapFree(GetProcessHeap(),0,component);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003285 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003286 MSI_ViewClose(view);
3287 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003288 return rc;
3289}
3290
3291/*
3292 * This helper function should probably go alot of places
Aric Stewart6e160f12004-06-29 04:07:22 +00003293 *
Mike McCormack6e2bca32004-07-04 00:25:00 +00003294 * Thinking about this, maybe this should become yet another Bison file
Aric Stewart401bd3f2004-06-28 20:34:35 +00003295 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003296static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data)
Aric Stewart401bd3f2004-06-28 20:34:35 +00003297{
3298 WCHAR* mark=NULL;
3299 DWORD size=0;
3300 DWORD chunk=0;
3301 WCHAR key[0x100];
Aric Stewart7231a432004-07-09 19:26:30 +00003302 LPWSTR value;
Aric Stewarte95136b2004-06-29 03:44:01 +00003303 DWORD sz;
Aric Stewart7231a432004-07-09 19:26:30 +00003304 UINT rc;
Aric Stewart401bd3f2004-06-28 20:34:35 +00003305
3306 /* scan for special characters */
3307 if (!strchrW(ptr,'[') || (strchrW(ptr,'[') && !strchrW(ptr,']')))
3308 {
3309 /* not formatted */
3310 size = (strlenW(ptr)+1) * sizeof(WCHAR);
3311 *data = HeapAlloc(GetProcessHeap(),0,size);
3312 strcpyW(*data,ptr);
3313 return size;
3314 }
3315
3316 /* formatted string located */
3317 mark = strchrW(ptr,'[');
3318 if (mark != ptr)
3319 {
3320 INT cnt = (mark - ptr);
3321 TRACE("%i (%i) characters before marker\n",cnt,(mark-ptr));
3322 size = cnt * sizeof(WCHAR);
3323 size += sizeof(WCHAR);
3324 *data = HeapAlloc(GetProcessHeap(),0,size);
3325 strncpyW(*data,ptr,cnt);
3326 (*data)[cnt]=0;
3327 }
3328 else
3329 {
3330 size = sizeof(WCHAR);
3331 *data = HeapAlloc(GetProcessHeap(),0,size);
3332 (*data)[0]=0;
3333 }
3334 mark++;
3335 strcpyW(key,mark);
3336 *strchrW(key,']')=0;
3337 mark = strchrW(mark,']');
3338 mark++;
3339 TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
Aric Stewart7231a432004-07-09 19:26:30 +00003340 sz = 0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003341 rc = MSI_GetPropertyW(package, key, NULL, &sz);
Aric Stewart7231a432004-07-09 19:26:30 +00003342 if ((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA))
Aric Stewart401bd3f2004-06-28 20:34:35 +00003343 {
3344 LPWSTR newdata;
Aric Stewart7231a432004-07-09 19:26:30 +00003345
3346 sz++;
3347 value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003348 MSI_GetPropertyW(package, key, value, &sz);
Aric Stewart7231a432004-07-09 19:26:30 +00003349
Aric Stewart401bd3f2004-06-28 20:34:35 +00003350 chunk = (strlenW(value)+1) * sizeof(WCHAR);
3351 size+=chunk;
3352 newdata = HeapReAlloc(GetProcessHeap(),0,*data,size);
3353 *data = newdata;
3354 strcatW(*data,value);
3355 }
3356 TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
3357 if (*mark!=0)
3358 {
3359 LPWSTR newdata;
3360 chunk = (strlenW(mark)+1) * sizeof(WCHAR);
3361 size+=chunk;
3362 newdata = HeapReAlloc(GetProcessHeap(),0,*data,size);
3363 *data = newdata;
3364 strcatW(*data,mark);
3365 }
3366 (*data)[strlenW(*data)]=0;
3367 TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
3368
Mike McCormack6e2bca32004-07-04 00:25:00 +00003369 /* recursively do this to clean up */
Aric Stewart401bd3f2004-06-28 20:34:35 +00003370 mark = HeapAlloc(GetProcessHeap(),0,size);
3371 strcpyW(mark,*data);
3372 TRACE("String at this point %s\n",debugstr_w(mark));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003373 size = deformat_string(package,mark,data);
Aric Stewart401bd3f2004-06-28 20:34:35 +00003374 HeapFree(GetProcessHeap(),0,mark);
3375 return size;
3376}
3377
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003378static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00003379{
Mike McCormackba8200b2004-12-22 15:25:30 +00003380 LPWSTR level;
Aric Stewart7d3e5972004-07-04 00:36:58 +00003381 INT install_level;
Mike McCormack4604e662004-08-06 17:30:20 +00003382 DWORD i;
3383 INT j;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003384 LPWSTR override = NULL;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003385 static const WCHAR all[]={'A','L','L',0};
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003386 static const WCHAR szlevel[] = {
3387 'I','N','S','T','A','L','L','L','E','V','E','L',0};
3388 static const WCHAR szAddLocal[] = {
3389 'A','D','D','L','O','C','A','L',0};
Aric Stewart5b936ca2004-07-06 18:47:09 +00003390
Aric Stewart7d3e5972004-07-04 00:36:58 +00003391 /* I do not know if this is where it should happen.. but */
3392
3393 TRACE("Checking Install Level\n");
Aric Stewart7d3e5972004-07-04 00:36:58 +00003394
Aric Stewartfa384f62004-12-22 18:46:17 +00003395 level = load_dynamic_property(package,szlevel,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00003396 if (level)
3397 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003398 install_level = atoiW(level);
Mike McCormackba8200b2004-12-22 15:25:30 +00003399 HeapFree(GetProcessHeap(), 0, level);
3400 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00003401 else
3402 install_level = 1;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003403
Aric Stewartfa384f62004-12-22 18:46:17 +00003404 override = load_dynamic_property(package,szAddLocal,NULL);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003405
Aric Stewart7d3e5972004-07-04 00:36:58 +00003406 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00003407 * Components FeatureState defaults to FALSE. The idea is we want to
Aric Stewart7d3e5972004-07-04 00:36:58 +00003408 * enable the component is ANY feature that uses it is enabled to install
3409 */
3410 for(i = 0; i < package->loaded_features; i++)
3411 {
3412 BOOL feature_state= ((package->features[i].Level > 0) &&
3413 (package->features[i].Level <= install_level));
Aric Stewart5b936ca2004-07-06 18:47:09 +00003414
3415 if (override && (strcmpiW(override,all)==0 ||
3416 strstrW(override,package->features[i].Feature)))
3417 {
3418 TRACE("Override of install level found\n");
3419 feature_state = TRUE;
Aric Stewarta3149f82004-07-09 19:38:40 +00003420 package->features[i].Enabled = feature_state;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003421 }
3422
Aric Stewart7d3e5972004-07-04 00:36:58 +00003423 TRACE("Feature %s has a state of %i\n",
3424 debugstr_w(package->features[i].Feature), feature_state);
3425 for( j = 0; j < package->features[i].ComponentCount; j++)
3426 {
3427 package->components[package->features[i].Components[j]].FeatureState
3428 |= feature_state;
3429 }
3430 }
Mike McCormackba8200b2004-12-22 15:25:30 +00003431 if (override)
Aric Stewart5b936ca2004-07-06 18:47:09 +00003432 HeapFree(GetProcessHeap(),0,override);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003433 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00003434 * So basically we ONLY want to install a component if its Enabled AND
Aric Stewart7d3e5972004-07-04 00:36:58 +00003435 * FeatureState are both TRUE
3436 */
3437 return ERROR_SUCCESS;
3438}
3439
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003440static UINT ACTION_InstallValidate(MSIPACKAGE *package)
Aric Stewart7d3e5972004-07-04 00:36:58 +00003441{
3442 DWORD progress = 0;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003443 static const WCHAR q1[]={
3444 'S','E','L','E','C','T',' ','*',' ',
3445 'F','R','O','M',' ','R','e','g','i','s','t','r','y',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00003446 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003447 MSIQUERY * view;
3448 MSIRECORD * row = 0;
Aric Stewart7d3e5972004-07-04 00:36:58 +00003449
3450 TRACE(" InstallValidate \n");
3451
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003452 rc = MSI_DatabaseOpenViewW(package->db, q1, &view);
3453 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003454 return ERROR_SUCCESS;
3455
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003456 rc = MSI_ViewExecute(view, 0);
3457 if (rc != ERROR_SUCCESS)
3458 {
3459 MSI_ViewClose(view);
3460 msiobj_release(&view->hdr);
3461 return rc;
3462 }
Aric Stewart7d3e5972004-07-04 00:36:58 +00003463 while (1)
3464 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003465 rc = MSI_ViewFetch(view,&row);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003466 if (rc != ERROR_SUCCESS)
3467 {
3468 rc = ERROR_SUCCESS;
3469 break;
3470 }
3471 progress +=1;
3472
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003473 msiobj_release(&row->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003474 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003475 MSI_ViewClose(view);
3476 msiobj_release(&view->hdr);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003477
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003478 ui_progress(package,0,progress+package->loaded_files,0,0);
Aric Stewart7d3e5972004-07-04 00:36:58 +00003479
3480 return ERROR_SUCCESS;
3481}
3482
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003483static UINT ACTION_LaunchConditions(MSIPACKAGE *package)
Aric Stewart5b936ca2004-07-06 18:47:09 +00003484{
3485 UINT rc;
Mike McCormackf3c8b832004-07-19 19:35:05 +00003486 MSIQUERY * view = NULL;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003487 MSIRECORD * row = 0;
3488 static const WCHAR ExecSeqQuery[] = {
3489 'S','E','L','E','C','T',' ','*',' ',
3490 '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 +00003491 static const WCHAR title[]=
3492 {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0};
Aric Stewart7d3e5972004-07-04 00:36:58 +00003493
Aric Stewart5b936ca2004-07-06 18:47:09 +00003494 TRACE("Checking launch conditions\n");
Aric Stewart7d3e5972004-07-04 00:36:58 +00003495
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003496 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003497 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003498 return ERROR_SUCCESS;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003499
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003500 rc = MSI_ViewExecute(view, 0);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003501 if (rc != ERROR_SUCCESS)
3502 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003503 MSI_ViewClose(view);
3504 msiobj_release(&view->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003505 return rc;
3506 }
3507
3508 rc = ERROR_SUCCESS;
3509 while (rc == ERROR_SUCCESS)
3510 {
3511 LPWSTR cond = NULL;
3512 LPWSTR message = NULL;
Aric Stewart5b936ca2004-07-06 18:47:09 +00003513
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003514 rc = MSI_ViewFetch(view,&row);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003515 if (rc != ERROR_SUCCESS)
3516 {
3517 rc = ERROR_SUCCESS;
3518 break;
3519 }
3520
Aric Stewart7231a432004-07-09 19:26:30 +00003521 cond = load_dynamic_stringW(row,1);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003522
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003523 if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
Aric Stewart5b936ca2004-07-06 18:47:09 +00003524 {
Aric Stewart7231a432004-07-09 19:26:30 +00003525 message = load_dynamic_stringW(row,2);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003526 MessageBoxW(NULL,message,title,MB_OK);
3527 HeapFree(GetProcessHeap(),0,message);
3528 rc = ERROR_FUNCTION_FAILED;
3529 }
3530 HeapFree(GetProcessHeap(),0,cond);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003531 msiobj_release(&row->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003532 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003533 MSI_ViewClose(view);
3534 msiobj_release(&view->hdr);
Aric Stewart5b936ca2004-07-06 18:47:09 +00003535 return rc;
3536}
Aric Stewart7d3e5972004-07-04 00:36:58 +00003537
Aric Stewartfa384f62004-12-22 18:46:17 +00003538static LPWSTR resolve_keypath( MSIPACKAGE* package, INT
3539 component_index)
Aric Stewartb942e182004-07-06 18:50:02 +00003540{
3541 MSICOMPONENT* cmp = &package->components[component_index];
3542
3543 if (cmp->KeyPath[0]==0)
3544 {
Mike McCormackba8200b2004-12-22 15:25:30 +00003545 LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);
Aric Stewartfa384f62004-12-22 18:46:17 +00003546 return p;
Aric Stewartb942e182004-07-06 18:50:02 +00003547 }
3548 if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20))
3549 {
3550 FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n");
Aric Stewartfa384f62004-12-22 18:46:17 +00003551 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00003552 }
3553 else
3554 {
3555 int j;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003556 j = get_loaded_file(package,cmp->KeyPath);
3557
3558 if (j>=0)
Aric Stewartfa384f62004-12-22 18:46:17 +00003559 {
3560 LPWSTR p = dupstrW(package->files[j].TargetPath);
3561 return p;
3562 }
Aric Stewartb942e182004-07-06 18:50:02 +00003563 }
Aric Stewartfa384f62004-12-22 18:46:17 +00003564 return NULL;
Aric Stewartb942e182004-07-06 18:50:02 +00003565}
3566
Aric Stewart2cf222f2004-07-06 19:00:23 +00003567/*
3568 * Ok further analysis makes me think that this work is
3569 * actually done in the PublishComponents and PublishFeatures
Mike McCormack3ece2462004-07-09 19:33:25 +00003570 * step, and not here. It appears like the keypath and all that is
3571 * resolved in this step, however actually written in the Publish steps.
Alexandre Julliard77b12762004-07-09 19:43:29 +00003572 * But we will leave it here for now because it is unclear
Aric Stewart2cf222f2004-07-06 19:00:23 +00003573 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003574static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
Aric Stewartb942e182004-07-06 18:50:02 +00003575{
Mike McCormackba8200b2004-12-22 15:25:30 +00003576 LPWSTR productcode;
Aric Stewartb942e182004-07-06 18:50:02 +00003577 WCHAR squished_pc[0x100];
3578 WCHAR squished_cc[0x100];
Aric Stewartb942e182004-07-06 18:50:02 +00003579 UINT rc;
Mike McCormack4604e662004-08-06 17:30:20 +00003580 DWORD i;
Aric Stewartb942e182004-07-06 18:50:02 +00003581 HKEY hkey=0,hkey2=0,hkey3=0;
3582 static const WCHAR szProductCode[]=
Mike McCormackba8200b2004-12-22 15:25:30 +00003583 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewartb942e182004-07-06 18:50:02 +00003584 static const WCHAR szInstaller[] = {
Mike McCormackba8200b2004-12-22 15:25:30 +00003585 'S','o','f','t','w','a','r','e','\\',
3586 'M','i','c','r','o','s','o','f','t','\\',
3587 'W','i','n','d','o','w','s','\\',
3588 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3589 'I','n','s','t','a','l','l','e','r',0 };
Aric Stewartb942e182004-07-06 18:50:02 +00003590 static const WCHAR szFeatures[] = {
Mike McCormackba8200b2004-12-22 15:25:30 +00003591 'F','e','a','t','u','r','e','s',0 };
Aric Stewartb942e182004-07-06 18:50:02 +00003592 static const WCHAR szComponents[] = {
Mike McCormackba8200b2004-12-22 15:25:30 +00003593 'C','o','m','p','o','n','e','n','t','s',0 };
Aric Stewartb942e182004-07-06 18:50:02 +00003594
Aric Stewartb942e182004-07-06 18:50:02 +00003595 if (!package)
3596 return ERROR_INVALID_HANDLE;
3597
3598 /* writes the Component and Features values to the registry */
Aric Stewartfa384f62004-12-22 18:46:17 +00003599 productcode = load_dynamic_property(package,szProductCode,&rc);
Mike McCormackba8200b2004-12-22 15:25:30 +00003600 if (!productcode)
Aric Stewartfa384f62004-12-22 18:46:17 +00003601 return rc;
Aric Stewartb942e182004-07-06 18:50:02 +00003602
3603 squash_guid(productcode,squished_pc);
3604 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);
3605 if (rc != ERROR_SUCCESS)
3606 goto end;
3607
3608 rc = RegCreateKeyW(hkey,szFeatures,&hkey2);
3609 if (rc != ERROR_SUCCESS)
3610 goto end;
3611
3612 rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
3613 if (rc != ERROR_SUCCESS)
3614 goto end;
3615
Alexandre Julliard77b12762004-07-09 19:43:29 +00003616 /* here the guids are base 85 encoded */
Aric Stewartb942e182004-07-06 18:50:02 +00003617 for (i = 0; i < package->loaded_features; i++)
Alexandre Julliard77b12762004-07-09 19:43:29 +00003618 {
3619 LPWSTR data = NULL;
3620 GUID clsid;
3621 int j;
3622 INT size;
3623
3624 size = package->features[i].ComponentCount*21*sizeof(WCHAR);
3625 data = HeapAlloc(GetProcessHeap(), 0, size);
3626
3627 data[0] = 0;
3628 for (j = 0; j < package->features[i].ComponentCount; j++)
3629 {
3630 WCHAR buf[21];
3631 TRACE("From %s\n",debugstr_w(package->components
3632 [package->features[i].Components[j]].ComponentId));
3633 CLSIDFromString(package->components
3634 [package->features[i].Components[j]].ComponentId,
3635 &clsid);
3636 encode_base85_guid(&clsid,buf);
3637 TRACE("to %s\n",debugstr_w(buf));
3638 strcatW(data,buf);
3639 }
3640
3641 size = strlenW(data)*sizeof(WCHAR);
3642 RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ,
3643 (LPSTR)data,size);
3644 HeapFree(GetProcessHeap(),0,data);
3645 }
Aric Stewartb942e182004-07-06 18:50:02 +00003646
3647 RegCloseKey(hkey3);
3648 RegCloseKey(hkey2);
3649
3650 rc = RegCreateKeyW(hkey,szComponents,&hkey2);
3651 if (rc != ERROR_SUCCESS)
3652 goto end;
3653
3654 for (i = 0; i < package->loaded_components; i++)
3655 {
3656 if (package->components[i].ComponentId[0]!=0)
3657 {
Aric Stewartfa384f62004-12-22 18:46:17 +00003658 WCHAR *keypath = NULL;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003659 MSIRECORD * uirow;
Aric Stewartb942e182004-07-06 18:50:02 +00003660
3661 squash_guid(package->components[i].ComponentId,squished_cc);
3662 rc = RegCreateKeyW(hkey2,squished_cc,&hkey3);
3663 if (rc != ERROR_SUCCESS)
3664 continue;
3665
Aric Stewartfa384f62004-12-22 18:46:17 +00003666 keypath = resolve_keypath(package,i);
3667 if (keypath)
3668 {
3669 RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath,
Aric Stewartb942e182004-07-06 18:50:02 +00003670 (strlenW(keypath)+1)*sizeof(WCHAR));
Aric Stewartfa384f62004-12-22 18:46:17 +00003671 RegCloseKey(hkey3);
Aric Stewartb942e182004-07-06 18:50:02 +00003672
Aric Stewartfa384f62004-12-22 18:46:17 +00003673 /* UI stuff */
3674 uirow = MSI_CreateRecord(3);
3675 MSI_RecordSetStringW(uirow,1,productcode);
3676 MSI_RecordSetStringW(uirow,2,package->components[i].
3677 ComponentId);
3678 MSI_RecordSetStringW(uirow,3,keypath);
3679 ui_actiondata(package,szProcessComponents,uirow);
3680 msiobj_release( &uirow->hdr );
3681 HeapFree(GetProcessHeap(),0,keypath);
3682 }
Aric Stewartb942e182004-07-06 18:50:02 +00003683 }
3684 }
3685end:
Mike McCormackba8200b2004-12-22 15:25:30 +00003686 HeapFree(GetProcessHeap(), 0, productcode);
Aric Stewartb942e182004-07-06 18:50:02 +00003687 RegCloseKey(hkey2);
3688 RegCloseKey(hkey);
3689 return rc;
3690}
3691
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003692static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
Aric Stewartfcb20c52004-07-06 18:51:16 +00003693{
3694 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00003695 * OK this is a bit confusing.. I am given a _Component key and I believe
Aric Stewartfcb20c52004-07-06 18:51:16 +00003696 * that the file that is being registered as a type library is the "key file
Mike McCormackc90c7812004-07-09 22:58:27 +00003697 * of that component" which I interpret to mean "The file in the KeyPath of
3698 * that component".
Aric Stewartfcb20c52004-07-06 18:51:16 +00003699 */
3700 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003701 MSIQUERY * view;
3702 MSIRECORD * row = 0;
3703 static const WCHAR Query[] = {
3704 'S','E','L','E','C','T',' ','*',' ',
3705 'f','r','o','m',' ','T','y','p','e','L','i','b',0};
Aric Stewartfcb20c52004-07-06 18:51:16 +00003706 ITypeLib *ptLib;
3707 HRESULT res;
3708
Aric Stewartfcb20c52004-07-06 18:51:16 +00003709 if (!package)
3710 return ERROR_INVALID_HANDLE;
3711
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003712 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003713 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003714 return ERROR_SUCCESS;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003715
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003716 rc = MSI_ViewExecute(view, 0);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003717 if (rc != ERROR_SUCCESS)
3718 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003719 MSI_ViewClose(view);
3720 msiobj_release(&view->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003721 return rc;
3722 }
3723
3724 while (1)
3725 {
3726 WCHAR component[0x100];
3727 DWORD sz;
3728 INT index;
3729
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003730 rc = MSI_ViewFetch(view,&row);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003731 if (rc != ERROR_SUCCESS)
3732 {
3733 rc = ERROR_SUCCESS;
3734 break;
3735 }
3736
3737 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003738 MSI_RecordGetStringW(row,3,component,&sz);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003739
3740 index = get_loaded_component(package,component);
3741 if (index < 0)
3742 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003743 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003744 continue;
3745 }
3746
3747 if (!package->components[index].Enabled ||
3748 !package->components[index].FeatureState)
3749 {
3750 TRACE("Skipping typelib reg due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003751 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003752 continue;
3753 }
3754
3755 index = get_loaded_file(package,package->components[index].KeyPath);
3756
3757 if (index < 0)
3758 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003759 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003760 continue;
3761 }
3762
3763 res = LoadTypeLib(package->files[index].TargetPath,&ptLib);
3764 if (SUCCEEDED(res))
3765 {
Mike McCormackba8200b2004-12-22 15:25:30 +00003766 LPWSTR help;
Aric Stewartfcb20c52004-07-06 18:51:16 +00003767 WCHAR helpid[0x100];
3768
3769 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003770 MSI_RecordGetStringW(row,6,helpid,&sz);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003771
Mike McCormackba8200b2004-12-22 15:25:30 +00003772 help = resolve_folder(package,helpid,FALSE,FALSE,NULL);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003773 res = RegisterTypeLib(ptLib,package->files[index].TargetPath,help);
Mike McCormackba8200b2004-12-22 15:25:30 +00003774 HeapFree(GetProcessHeap(),0,help);
3775
Aric Stewartfcb20c52004-07-06 18:51:16 +00003776 if (!SUCCEEDED(res))
3777 ERR("Failed to register type library %s\n",
3778 debugstr_w(package->files[index].TargetPath));
3779 else
3780 {
Mike McCormackc90c7812004-07-09 22:58:27 +00003781 /* Yes the row has more fields than I need, but #1 is
3782 correct and the only one I need. Why make a new row? */
Aric Stewartfcb20c52004-07-06 18:51:16 +00003783
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003784 ui_actiondata(package,szRegisterTypeLibraries,row);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003785
3786 TRACE("Registered %s\n",
3787 debugstr_w(package->files[index].TargetPath));
3788 }
3789
3790 if (ptLib)
3791 ITypeLib_Release(ptLib);
3792 }
3793 else
3794 ERR("Failed to load type library %s\n",
3795 debugstr_w(package->files[index].TargetPath));
3796
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003797 msiobj_release(&row->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003798 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003799 MSI_ViewClose(view);
3800 msiobj_release(&view->hdr);
Aric Stewartfcb20c52004-07-06 18:51:16 +00003801 return rc;
3802
3803}
3804
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003805static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app )
Aric Stewart8f0a7612004-07-06 18:53:11 +00003806{
3807 static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
3808 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003809 MSIQUERY * view;
3810 MSIRECORD * row = 0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003811 static const WCHAR ExecSeqQuery[] =
Mike McCormack9db0e072004-12-22 15:05:07 +00003812 {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I'
3813 ,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003814 HKEY hkey2,hkey3;
3815 LPWSTR buffer=0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003816
Aric Stewart8f0a7612004-07-06 18:53:11 +00003817 if (!package)
3818 return ERROR_INVALID_HANDLE;
3819
Mike McCormackba8200b2004-12-22 15:25:30 +00003820 rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003821 if (rc != ERROR_SUCCESS)
3822 return rc;
3823
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003824 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003825 if (rc != ERROR_SUCCESS)
3826 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003827 MSI_ViewClose(view);
3828 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003829 return rc;
3830 }
3831
3832 RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
3833 RegCreateKeyW(hkey2,clsid,&hkey3);
3834 RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
3835 (strlenW(app)+1)*sizeof(WCHAR));
3836
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003837 rc = MSI_ViewFetch(view,&row);
3838 if (rc != ERROR_SUCCESS)
3839 {
3840 MSI_ViewClose(view);
3841 msiobj_release(&view->hdr);
3842 return rc;
3843 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003844
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003845 if (!MSI_RecordIsNull(row,2))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003846 {
3847 LPWSTR deformated=0;
3848 UINT size;
3849 static const WCHAR szRemoteServerName[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003850 {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
Aric Stewart7231a432004-07-09 19:26:30 +00003851 buffer = load_dynamic_stringW(row,2);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003852 size = deformat_string(package,buffer,&deformated);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003853 RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated,
3854 size);
3855 HeapFree(GetProcessHeap(),0,deformated);
3856 HeapFree(GetProcessHeap(),0,buffer);
3857 }
3858
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003859 if (!MSI_RecordIsNull(row,3))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003860 {
3861 static const WCHAR szLocalService[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003862 {'L','o','c','a','l','S','e','r','v','i','c','e',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003863 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003864 buffer = load_dynamic_stringW(row,3);
3865 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003866 RegSetValueExW(hkey3,szLocalService,0,REG_SZ,(LPVOID)buffer,size);
3867 HeapFree(GetProcessHeap(),0,buffer);
3868 }
3869
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003870 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003871 {
3872 static const WCHAR szService[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003873 {'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 +00003874 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003875 buffer = load_dynamic_stringW(row,4);
3876 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003877 RegSetValueExW(hkey3,szService,0,REG_SZ,(LPVOID)buffer,size);
3878 HeapFree(GetProcessHeap(),0,buffer);
3879 }
3880
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003881 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003882 {
3883 static const WCHAR szDLL[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003884 {'D','l','l','S','u','r','r','o','g','a','t','e',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003885 UINT size;
Aric Stewart7231a432004-07-09 19:26:30 +00003886 buffer = load_dynamic_stringW(row,5);
3887 size = (strlenW(buffer)+1) * sizeof(WCHAR);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003888 RegSetValueExW(hkey3,szDLL,0,REG_SZ,(LPVOID)buffer,size);
3889 HeapFree(GetProcessHeap(),0,buffer);
3890 }
3891
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003892 if (!MSI_RecordIsNull(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003893 {
3894 static const WCHAR szActivate[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003895 {'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 +00003896 static const WCHAR szY[] = {'Y',0};
3897
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003898 if (MSI_RecordGetInteger(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003899 RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
3900 }
3901
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003902 if (!MSI_RecordIsNull(row,7))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003903 {
3904 static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
3905 static const WCHAR szUser[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00003906 {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003907
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003908 if (MSI_RecordGetInteger(row,7))
Aric Stewart8f0a7612004-07-06 18:53:11 +00003909 RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34);
3910 }
3911
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003912 msiobj_release(&row->hdr);
3913 MSI_ViewClose(view);
3914 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003915 RegCloseKey(hkey3);
3916 RegCloseKey(hkey2);
3917 return rc;
3918}
3919
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003920static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
Aric Stewart8f0a7612004-07-06 18:53:11 +00003921{
3922 /*
Francois Gouget817c5202004-07-16 19:15:40 +00003923 * Again I am assuming the words, "Whose key file represents" when referring
Mike McCormackc90c7812004-07-09 22:58:27 +00003924 * to a Component as to meaning that Components KeyPath file
Aric Stewart8f0a7612004-07-06 18:53:11 +00003925 *
3926 * Also there is a very strong connection between ClassInfo and ProgID
Mike McCormack3ece2462004-07-09 19:33:25 +00003927 * that I am mostly glossing over.
3928 * What would be more propper is to load the ClassInfo and the ProgID info
Aric Stewart8f0a7612004-07-06 18:53:11 +00003929 * into memory data structures and then be able to enable and disable them
3930 * based on component.
3931 */
3932
3933 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003934 MSIQUERY * view;
3935 MSIRECORD * row = 0;
3936 static const WCHAR ExecSeqQuery[] = {
3937 'S','E','L','E','C','T',' ','*',' ',
3938 'f','r','o','m',' ','C','l','a','s','s',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00003939 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
3940 static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
3941 static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
3942 HKEY hkey,hkey2,hkey3;
3943
Aric Stewart8f0a7612004-07-06 18:53:11 +00003944 if (!package)
3945 return ERROR_INVALID_HANDLE;
3946
3947 rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
3948 if (rc != ERROR_SUCCESS)
3949 return ERROR_FUNCTION_FAILED;
3950
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003951 rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003952 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00003953 {
3954 rc = ERROR_SUCCESS;
Aric Stewart8f0a7612004-07-06 18:53:11 +00003955 goto end;
Aric Stewart84837d92004-07-20 01:22:37 +00003956 }
Aric Stewart8f0a7612004-07-06 18:53:11 +00003957
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003958 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003959 if (rc != ERROR_SUCCESS)
3960 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003961 MSI_ViewClose(view);
3962 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003963 goto end;
3964 }
3965
3966 while (1)
3967 {
3968 WCHAR clsid[0x100];
3969 WCHAR buffer[0x100];
3970 WCHAR desc[0x100];
3971 DWORD sz;
3972 INT index;
3973
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003974 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003975 if (rc != ERROR_SUCCESS)
3976 {
3977 rc = ERROR_SUCCESS;
3978 break;
3979 }
3980
3981 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003982 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003983
3984 index = get_loaded_component(package,buffer);
3985
3986 if (index < 0)
3987 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003988 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003989 continue;
3990 }
3991
3992 if (!package->components[index].Enabled ||
3993 !package->components[index].FeatureState)
3994 {
3995 TRACE("Skipping class reg due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00003996 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00003997 continue;
3998 }
3999
4000 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004001 MSI_RecordGetStringW(row,1,clsid,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004002 RegCreateKeyW(hkey,clsid,&hkey2);
4003
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004004 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004005 {
4006 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004007 MSI_RecordGetStringW(row,5,desc,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004008
4009 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)desc,
4010 (strlenW(desc)+1)*sizeof(WCHAR));
4011 }
4012 else
4013 desc[0]=0;
4014
4015 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004016 MSI_RecordGetStringW(row,2,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004017
4018 RegCreateKeyW(hkey2,buffer,&hkey3);
4019
4020 index = get_loaded_file(package,package->components[index].KeyPath);
4021 RegSetValueExW(hkey3,NULL,0,REG_SZ,
4022 (LPVOID)package->files[index].TargetPath,
4023 (strlenW(package->files[index].TargetPath)+1)
4024 *sizeof(WCHAR));
4025
4026 RegCloseKey(hkey3);
4027
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004028 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004029 {
4030 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004031 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004032
4033 RegCreateKeyW(hkey2,szProgID,&hkey3);
4034
4035 RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)buffer,
4036 (strlenW(buffer)+1)*sizeof(WCHAR));
4037
4038 RegCloseKey(hkey3);
4039 }
4040
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004041 if (!MSI_RecordIsNull(row,6))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004042 {
4043 sz=0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004044 MSI_RecordGetStringW(row,6,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004045
4046 RegSetValueExW(hkey2,szAppID,0,REG_SZ,(LPVOID)buffer,
4047 (strlenW(buffer)+1)*sizeof(WCHAR));
4048
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004049 register_appid(package,buffer,desc);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004050 }
4051
4052 RegCloseKey(hkey2);
4053
4054 FIXME("Process the rest of the fields >7\n");
4055
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004056 ui_actiondata(package,szRegisterClassInfo,row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004057
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004058 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004059 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004060 MSI_ViewClose(view);
4061 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004062
4063end:
4064 RegCloseKey(hkey);
4065 return rc;
4066}
4067
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004068static UINT register_progid_base(MSIRECORD * row, LPWSTR clsid)
Aric Stewart8f0a7612004-07-06 18:53:11 +00004069{
4070 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
4071 HKEY hkey,hkey2;
Aric Stewart7231a432004-07-09 19:26:30 +00004072 WCHAR buffer[0x100];
Aric Stewart8f0a7612004-07-06 18:53:11 +00004073 DWORD sz;
4074
4075
Aric Stewart7231a432004-07-09 19:26:30 +00004076 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004077 MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004078 RegCreateKeyW(HKEY_CLASSES_ROOT,buffer,&hkey);
4079
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004080 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004081 {
Aric Stewart7231a432004-07-09 19:26:30 +00004082 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004083 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004084 RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
4085 sizeof(WCHAR));
4086 }
4087
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004088 if (!MSI_RecordIsNull(row,3))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004089 {
Aric Stewart7231a432004-07-09 19:26:30 +00004090 sz = 0x100;
Aric Stewart8f0a7612004-07-06 18:53:11 +00004091
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004092 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004093 RegCreateKeyW(hkey,szCLSID,&hkey2);
4094 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)buffer, (strlenW(buffer)+1) *
4095 sizeof(WCHAR));
4096
4097 if (clsid)
4098 strcpyW(clsid,buffer);
4099
4100 RegCloseKey(hkey2);
4101 }
4102 else
4103 {
4104 FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
4105 return ERROR_FUNCTION_FAILED;
4106 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004107 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004108 FIXME ("UNHANDLED icon in Progid\n");
4109 return ERROR_SUCCESS;
4110}
4111
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004112static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004113
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004114static UINT register_parent_progid(MSIPACKAGE *package, LPCWSTR parent,
Aric Stewart8f0a7612004-07-06 18:53:11 +00004115 LPWSTR clsid)
4116{
4117 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004118 MSIQUERY * view;
4119 MSIRECORD * row = 0;
Aric Stewart8f0a7612004-07-06 18:53:11 +00004120 static const WCHAR Query_t[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00004121 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g'
4122 ,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`'
4123 ,'%','s','`',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00004124
Aric Stewart8f0a7612004-07-06 18:53:11 +00004125 if (!package)
4126 return ERROR_INVALID_HANDLE;
4127
Mike McCormackba8200b2004-12-22 15:25:30 +00004128 rc = ACTION_OpenQuery(package->db, &view, Query_t, parent);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004129 if (rc != ERROR_SUCCESS)
4130 return rc;
4131
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004132 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004133 if (rc != ERROR_SUCCESS)
4134 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004135 MSI_ViewClose(view);
4136 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004137 return rc;
4138 }
4139
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004140 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004141 if (rc != ERROR_SUCCESS)
4142 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004143 MSI_ViewClose(view);
4144 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004145 return rc;
4146 }
4147
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004148 register_progid(package,row,clsid);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004149
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004150 msiobj_release(&row->hdr);
4151 MSI_ViewClose(view);
4152 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004153 return rc;
4154}
4155
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004156static UINT register_progid(MSIPACKAGE *package, MSIRECORD * row, LPWSTR clsid)
Aric Stewart8f0a7612004-07-06 18:53:11 +00004157{
4158 UINT rc = ERROR_SUCCESS;
4159
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004160 if (MSI_RecordIsNull(row,2))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004161 rc = register_progid_base(row,clsid);
4162 else
4163 {
4164 WCHAR buffer[0x1000];
Aric Stewartd906ef02004-10-22 22:06:31 +00004165 DWORD sz, disp;
Aric Stewart8f0a7612004-07-06 18:53:11 +00004166 HKEY hkey,hkey2;
4167 static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
4168
Aric Stewartd906ef02004-10-22 22:06:31 +00004169 /* check if already registered */
Aric Stewart7231a432004-07-09 19:26:30 +00004170 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004171 MSI_RecordGetStringW(row,1,buffer,&sz);
Aric Stewartd906ef02004-10-22 22:06:31 +00004172 RegCreateKeyExW(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0,
4173 KEY_ALL_ACCESS, NULL, &hkey, &disp );
4174 if (disp == REG_OPENED_EXISTING_KEY)
4175 {
4176 TRACE("Key already registered\n");
4177 RegCloseKey(hkey);
4178 return rc;
4179 }
4180 /* clsid is same as parent */
Aric Stewart8f0a7612004-07-06 18:53:11 +00004181 RegCreateKeyW(hkey,szCLSID,&hkey2);
4182 RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
4183 sizeof(WCHAR));
4184
4185 RegCloseKey(hkey2);
Aric Stewartd906ef02004-10-22 22:06:31 +00004186
4187 sz = 0x100;
4188 MSI_RecordGetStringW(row,2,buffer,&sz);
4189 rc = register_parent_progid(package,buffer,clsid);
4190
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004191 if (!MSI_RecordIsNull(row,4))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004192 {
Aric Stewart7231a432004-07-09 19:26:30 +00004193 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004194 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004195 RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)buffer,
4196 (strlenW(buffer)+1) * sizeof(WCHAR));
4197 }
4198
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004199 if (!MSI_RecordIsNull(row,5))
Aric Stewart8f0a7612004-07-06 18:53:11 +00004200 FIXME ("UNHANDLED icon in Progid\n");
4201
4202 RegCloseKey(hkey);
4203 }
4204 return rc;
4205}
4206
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004207static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
Aric Stewart8f0a7612004-07-06 18:53:11 +00004208{
4209 /*
Mike McCormackc90c7812004-07-09 22:58:27 +00004210 * Sigh, here I am just brute force registering all progids
Francois Gouget817c5202004-07-16 19:15:40 +00004211 * this needs to be linked to the Classes that have been registered
Aric Stewart8f0a7612004-07-06 18:53:11 +00004212 * but the easiest way to do that is to load all these stuff into
4213 * memory for easy checking.
4214 *
Mike McCormackc90c7812004-07-09 22:58:27 +00004215 * Gives me something to continue to work toward.
Aric Stewart8f0a7612004-07-06 18:53:11 +00004216 */
4217 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004218 MSIQUERY * view;
4219 MSIRECORD * row = 0;
4220 static const WCHAR Query[] = {
4221 'S','E','L','E','C','T',' ','*',' ',
4222 'F','R','O','M',' ','P','r','o','g','I','d',0};
Aric Stewart8f0a7612004-07-06 18:53:11 +00004223
Aric Stewart8f0a7612004-07-06 18:53:11 +00004224 if (!package)
4225 return ERROR_INVALID_HANDLE;
4226
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004227 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004228 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00004229 return ERROR_SUCCESS;
Aric Stewart8f0a7612004-07-06 18:53:11 +00004230
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004231 rc = MSI_ViewExecute(view, 0);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004232 if (rc != ERROR_SUCCESS)
4233 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004234 MSI_ViewClose(view);
4235 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004236 return rc;
4237 }
4238
4239 while (1)
4240 {
4241 WCHAR clsid[0x1000];
4242
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004243 rc = MSI_ViewFetch(view,&row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004244 if (rc != ERROR_SUCCESS)
4245 {
4246 rc = ERROR_SUCCESS;
4247 break;
4248 }
4249
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004250 register_progid(package,row,clsid);
4251 ui_actiondata(package,szRegisterProgIdInfo,row);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004252
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004253 msiobj_release(&row->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004254 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004255 MSI_ViewClose(view);
4256 msiobj_release(&view->hdr);
Aric Stewart8f0a7612004-07-06 18:53:11 +00004257 return rc;
4258}
4259
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004260static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
Aric Stewartfa384f62004-12-22 18:46:17 +00004261 LPWSTR *FilePath)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004262{
Mike McCormackba8200b2004-12-22 15:25:30 +00004263 LPWSTR ProductCode;
4264 LPWSTR SystemFolder;
Aric Stewartfa384f62004-12-22 18:46:17 +00004265 LPWSTR dest;
4266 UINT rc;
4267
Aric Stewart2cf222f2004-07-06 19:00:23 +00004268 static const WCHAR szInstaller[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00004269 {'I','n','s','t','a','l','l','e','r','\\',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004270 static const WCHAR szProductCode[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00004271 {'P','r','o','d','u','c','t','C','o','d','e',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004272 static const WCHAR szFolder[] =
Mike McCormackba8200b2004-12-22 15:25:30 +00004273 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004274
Aric Stewartfa384f62004-12-22 18:46:17 +00004275 ProductCode = load_dynamic_property(package,szProductCode,&rc);
Mike McCormackba8200b2004-12-22 15:25:30 +00004276 if (!ProductCode)
Aric Stewartfa384f62004-12-22 18:46:17 +00004277 return rc;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004278
Aric Stewartfa384f62004-12-22 18:46:17 +00004279 SystemFolder = load_dynamic_property(package,szFolder,NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00004280
Aric Stewartfa384f62004-12-22 18:46:17 +00004281 dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004282
Aric Stewartfa384f62004-12-22 18:46:17 +00004283 create_full_pathW(dest);
4284
4285 *FilePath = build_directory_name(2, dest, icon_name);
4286
Mike McCormackba8200b2004-12-22 15:25:30 +00004287 HeapFree(GetProcessHeap(),0,SystemFolder);
4288 HeapFree(GetProcessHeap(),0,ProductCode);
Aric Stewartfa384f62004-12-22 18:46:17 +00004289 HeapFree(GetProcessHeap(),0,dest);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004290 return ERROR_SUCCESS;
4291}
4292
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004293static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004294{
4295 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004296 MSIQUERY * view;
4297 MSIRECORD * row = 0;
4298 static const WCHAR Query[] = {
4299 'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ',
4300 'S','h','o','r','t','c','u','t',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004301 IShellLinkW *sl;
4302 IPersistFile *pf;
4303 HRESULT res;
4304
Aric Stewart2cf222f2004-07-06 19:00:23 +00004305 if (!package)
4306 return ERROR_INVALID_HANDLE;
4307
4308 res = CoInitialize( NULL );
4309 if (FAILED (res))
4310 {
4311 ERR("CoInitialize failed\n");
4312 return ERROR_FUNCTION_FAILED;
4313 }
4314
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004315 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004316 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00004317 return ERROR_SUCCESS;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004318
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004319 rc = MSI_ViewExecute(view, 0);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004320 if (rc != ERROR_SUCCESS)
4321 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004322 MSI_ViewClose(view);
4323 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004324 return rc;
4325 }
4326
4327 while (1)
4328 {
Mike McCormackba8200b2004-12-22 15:25:30 +00004329 LPWSTR target_file, target_folder;
Aric Stewart7231a432004-07-09 19:26:30 +00004330 WCHAR buffer[0x100];
Aric Stewart2cf222f2004-07-06 19:00:23 +00004331 DWORD sz;
4332 DWORD index;
4333 static const WCHAR szlnk[]={'.','l','n','k',0};
4334
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004335 rc = MSI_ViewFetch(view,&row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004336 if (rc != ERROR_SUCCESS)
4337 {
4338 rc = ERROR_SUCCESS;
4339 break;
4340 }
4341
Aric Stewart7231a432004-07-09 19:26:30 +00004342 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004343 MSI_RecordGetStringW(row,4,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004344
4345 index = get_loaded_component(package,buffer);
4346
4347 if (index < 0)
4348 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004349 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004350 continue;
4351 }
4352
4353 if (!package->components[index].Enabled ||
4354 !package->components[index].FeatureState)
4355 {
4356 TRACE("Skipping shortcut creation due to disabled component\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004357 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004358 continue;
4359 }
4360
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004361 ui_actiondata(package,szCreateShortcuts,row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004362
4363 res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
4364 &IID_IShellLinkW, (LPVOID *) &sl );
4365
4366 if (FAILED(res))
4367 {
4368 ERR("Is IID_IShellLink\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004369 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004370 continue;
4371 }
4372
4373 res = IShellLinkW_QueryInterface( sl, &IID_IPersistFile,(LPVOID*) &pf );
4374 if( FAILED( res ) )
4375 {
4376 ERR("Is IID_IPersistFile\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004377 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004378 continue;
4379 }
4380
Aric Stewart7231a432004-07-09 19:26:30 +00004381 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004382 MSI_RecordGetStringW(row,2,buffer,&sz);
Mike McCormackba8200b2004-12-22 15:25:30 +00004383 target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004384
Aric Stewart7231a432004-07-09 19:26:30 +00004385 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004386 MSI_RecordGetStringW(row,3,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004387 reduce_to_longfilename(buffer);
Mike McCormackba8200b2004-12-22 15:25:30 +00004388 if (!strchrW(buffer,'.'))
4389 strcatW(buffer,szlnk);
4390 target_file = build_directory_name(2, target_folder, buffer);
4391 HeapFree(GetProcessHeap(),0,target_folder);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004392
Aric Stewart7231a432004-07-09 19:26:30 +00004393 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004394 MSI_RecordGetStringW(row,5,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004395 if (strchrW(buffer,'['))
4396 {
4397 LPWSTR deformated;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004398 deformat_string(package,buffer,&deformated);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004399 IShellLinkW_SetPath(sl,deformated);
4400 HeapFree(GetProcessHeap(),0,deformated);
4401 }
4402 else
4403 {
4404 FIXME("UNHANDLED shortcut format, advertised shortcut\n");
4405 IPersistFile_Release( pf );
4406 IShellLinkW_Release( sl );
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004407 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004408 continue;
4409 }
4410
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004411 if (!MSI_RecordIsNull(row,6))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004412 {
4413 LPWSTR deformated;
Aric Stewart7231a432004-07-09 19:26:30 +00004414 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004415 MSI_RecordGetStringW(row,6,buffer,&sz);
4416 deformat_string(package,buffer,&deformated);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004417 IShellLinkW_SetArguments(sl,deformated);
4418 HeapFree(GetProcessHeap(),0,deformated);
4419 }
4420
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004421 if (!MSI_RecordIsNull(row,7))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004422 {
4423 LPWSTR deformated;
Aric Stewart7231a432004-07-09 19:26:30 +00004424 deformated = load_dynamic_stringW(row,7);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004425 IShellLinkW_SetDescription(sl,deformated);
4426 HeapFree(GetProcessHeap(),0,deformated);
4427 }
4428
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004429 if (!MSI_RecordIsNull(row,8))
4430 IShellLinkW_SetHotkey(sl,MSI_RecordGetInteger(row,8));
Aric Stewart2cf222f2004-07-06 19:00:23 +00004431
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004432 if (!MSI_RecordIsNull(row,9))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004433 {
Aric Stewartfa384f62004-12-22 18:46:17 +00004434 WCHAR *Path = NULL;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004435 INT index;
4436
Aric Stewart7231a432004-07-09 19:26:30 +00004437 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004438 MSI_RecordGetStringW(row,9,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004439
Aric Stewartfa384f62004-12-22 18:46:17 +00004440 build_icon_path(package,buffer,&Path);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004441 index = MSI_RecordGetInteger(row,10);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004442
4443 IShellLinkW_SetIconLocation(sl,Path,index);
Aric Stewartfa384f62004-12-22 18:46:17 +00004444 HeapFree(GetProcessHeap(),0,Path);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004445 }
4446
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004447 if (!MSI_RecordIsNull(row,11))
4448 IShellLinkW_SetShowCmd(sl,MSI_RecordGetInteger(row,11));
Aric Stewart2cf222f2004-07-06 19:00:23 +00004449
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004450 if (!MSI_RecordIsNull(row,12))
Aric Stewart2cf222f2004-07-06 19:00:23 +00004451 {
Mike McCormackba8200b2004-12-22 15:25:30 +00004452 LPWSTR Path;
Aric Stewart7231a432004-07-09 19:26:30 +00004453 sz = 0x100;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004454 MSI_RecordGetStringW(row,12,buffer,&sz);
Mike McCormackba8200b2004-12-22 15:25:30 +00004455 Path = resolve_folder(package, buffer, FALSE, FALSE, NULL);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004456 IShellLinkW_SetWorkingDirectory(sl,Path);
Mike McCormackba8200b2004-12-22 15:25:30 +00004457 HeapFree(GetProcessHeap(), 0, Path);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004458 }
4459
4460 TRACE("Writing shortcut to %s\n",debugstr_w(target_file));
4461 IPersistFile_Save(pf,target_file,FALSE);
Aric Stewartfa384f62004-12-22 18:46:17 +00004462
4463 HeapFree(GetProcessHeap(),0,target_file);
4464
Aric Stewart2cf222f2004-07-06 19:00:23 +00004465 IPersistFile_Release( pf );
4466 IShellLinkW_Release( sl );
4467
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004468 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004469 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004470 MSI_ViewClose(view);
4471 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004472
4473
4474 CoUninitialize();
4475
4476 return rc;
4477}
4478
4479
4480/*
4481 * 99% of the work done here is only done for
4482 * advertised installs. However this is where the
4483 * Icon table is processed and written out
Francois Gouget817c5202004-07-16 19:15:40 +00004484 * so that is what I am going to do here.
Aric Stewart2cf222f2004-07-06 19:00:23 +00004485 */
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004486static UINT ACTION_PublishProduct(MSIPACKAGE *package)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004487{
4488 UINT rc;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004489 MSIQUERY * view;
4490 MSIRECORD * row = 0;
4491 static const WCHAR Query[]={
4492 'S','E','L','E','C','T',' ','*',' ',
4493 'f','r','o','m',' ','I','c','o','n',0};
Aric Stewart2cf222f2004-07-06 19:00:23 +00004494 DWORD sz;
4495
Aric Stewart2cf222f2004-07-06 19:00:23 +00004496 if (!package)
4497 return ERROR_INVALID_HANDLE;
4498
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004499 rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004500 if (rc != ERROR_SUCCESS)
Aric Stewart84837d92004-07-20 01:22:37 +00004501 return ERROR_SUCCESS;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004502
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004503 rc = MSI_ViewExecute(view, 0);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004504 if (rc != ERROR_SUCCESS)
4505 {
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004506 MSI_ViewClose(view);
4507 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004508 return rc;
4509 }
4510
4511 while (1)
4512 {
4513 HANDLE the_file;
Aric Stewartfa384f62004-12-22 18:46:17 +00004514 WCHAR *FilePath=NULL;
4515 WCHAR *FileName=NULL;
Aric Stewart2cf222f2004-07-06 19:00:23 +00004516 CHAR buffer[1024];
4517
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004518 rc = MSI_ViewFetch(view,&row);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004519 if (rc != ERROR_SUCCESS)
4520 {
4521 rc = ERROR_SUCCESS;
4522 break;
4523 }
4524
Aric Stewartfa384f62004-12-22 18:46:17 +00004525 FileName = load_dynamic_stringW(row,1);
4526 if (!FileName)
Aric Stewart2cf222f2004-07-06 19:00:23 +00004527 {
4528 ERR("Unable to get FileName\n");
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004529 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004530 continue;
4531 }
4532
Aric Stewartfa384f62004-12-22 18:46:17 +00004533 build_icon_path(package,FileName,&FilePath);
4534
4535 HeapFree(GetProcessHeap(),0,FileName);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004536
4537 TRACE("Creating icon file at %s\n",debugstr_w(FilePath));
4538
4539 the_file = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
4540 FILE_ATTRIBUTE_NORMAL, NULL);
4541
4542 if (the_file == INVALID_HANDLE_VALUE)
4543 {
4544 ERR("Unable to create file %s\n",debugstr_w(FilePath));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004545 msiobj_release(&row->hdr);
Aric Stewartfa384f62004-12-22 18:46:17 +00004546 HeapFree(GetProcessHeap(),0,FilePath);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004547 continue;
4548 }
4549
4550 do
4551 {
4552 DWORD write;
4553 sz = 1024;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004554 rc = MSI_RecordReadStream(row,2,buffer,&sz);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004555 if (rc != ERROR_SUCCESS)
4556 {
4557 ERR("Failed to get stream\n");
4558 CloseHandle(the_file);
4559 DeleteFileW(FilePath);
4560 break;
4561 }
4562 WriteFile(the_file,buffer,sz,&write,NULL);
4563 } while (sz == 1024);
4564
Aric Stewartfa384f62004-12-22 18:46:17 +00004565 HeapFree(GetProcessHeap(),0,FilePath);
4566
Aric Stewart2cf222f2004-07-06 19:00:23 +00004567 CloseHandle(the_file);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004568 msiobj_release(&row->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004569 }
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004570 MSI_ViewClose(view);
4571 msiobj_release(&view->hdr);
Aric Stewart2cf222f2004-07-06 19:00:23 +00004572 return rc;
4573
4574}
4575
Mike McCormack3ece2462004-07-09 19:33:25 +00004576/* Msi functions that seem appropriate here */
Aric Stewarte95136b2004-06-29 03:44:01 +00004577UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
4578{
4579 LPWSTR szwAction;
Aric Stewarta3149f82004-07-09 19:38:40 +00004580 UINT rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00004581
4582 TRACE(" exteral attempt at action %s\n",szAction);
4583
4584 if (!szAction)
4585 return ERROR_FUNCTION_FAILED;
4586 if (hInstall == 0)
4587 return ERROR_FUNCTION_FAILED;
4588
Aric Stewarta3149f82004-07-09 19:38:40 +00004589 szwAction = strdupAtoW(szAction);
Aric Stewarte95136b2004-06-29 03:44:01 +00004590
4591 if (!szwAction)
4592 return ERROR_FUNCTION_FAILED;
4593
Aric Stewarte95136b2004-06-29 03:44:01 +00004594
4595 rc = MsiDoActionW(hInstall, szwAction);
4596 HeapFree(GetProcessHeap(),0,szwAction);
4597 return rc;
4598}
4599
4600UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
4601{
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004602 MSIPACKAGE *package;
4603 UINT ret = ERROR_INVALID_HANDLE;
4604
Mike McCormack3ece2462004-07-09 19:33:25 +00004605 TRACE(" external attempt at action %s \n",debugstr_w(szAction));
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004606
4607 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4608 if( package )
4609 {
4610 ret = ACTION_PerformAction(package,szAction);
4611 msiobj_release( &package->hdr );
4612 }
4613 return ret;
Aric Stewarte95136b2004-06-29 03:44:01 +00004614}
4615
4616UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
4617 LPSTR szPathBuf, DWORD* pcchPathBuf)
4618{
4619 LPWSTR szwFolder;
4620 LPWSTR szwPathBuf;
Aric Stewarta3149f82004-07-09 19:38:40 +00004621 UINT rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00004622
4623 TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
4624
4625 if (!szFolder)
4626 return ERROR_FUNCTION_FAILED;
4627 if (hInstall == 0)
4628 return ERROR_FUNCTION_FAILED;
4629
Aric Stewarta3149f82004-07-09 19:38:40 +00004630 szwFolder = strdupAtoW(szFolder);
Aric Stewarte95136b2004-06-29 03:44:01 +00004631
4632 if (!szwFolder)
4633 return ERROR_FUNCTION_FAILED;
4634
4635 szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
4636
Aric Stewarte95136b2004-06-29 03:44:01 +00004637 rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
4638
4639 WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
4640 *pcchPathBuf, NULL, NULL );
4641
4642 HeapFree(GetProcessHeap(),0,szwFolder);
4643 HeapFree(GetProcessHeap(),0,szwPathBuf);
4644
4645 return rc;
4646}
4647
4648UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
4649 szPathBuf, DWORD* pcchPathBuf)
4650{
Mike McCormackba8200b2004-12-22 15:25:30 +00004651 LPWSTR path;
4652 UINT rc = ERROR_FUNCTION_FAILED;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004653 MSIPACKAGE *package;
Aric Stewartbdb29552004-07-04 00:32:48 +00004654
Aric Stewarte95136b2004-06-29 03:44:01 +00004655 TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
Aric Stewartbdb29552004-07-04 00:32:48 +00004656
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004657 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
Mike McCormackba8200b2004-12-22 15:25:30 +00004658 if (!package)
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004659 return ERROR_INVALID_HANDLE;
Mike McCormackba8200b2004-12-22 15:25:30 +00004660 path = resolve_folder(package, szFolder, FALSE, FALSE, NULL);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004661 msiobj_release( &package->hdr );
Aric Stewartbdb29552004-07-04 00:32:48 +00004662
Mike McCormackba8200b2004-12-22 15:25:30 +00004663 if (path && (strlenW(path) > *pcchPathBuf))
Aric Stewartbdb29552004-07-04 00:32:48 +00004664 {
4665 *pcchPathBuf = strlenW(path)+1;
Mike McCormackba8200b2004-12-22 15:25:30 +00004666 rc = ERROR_MORE_DATA;
Aric Stewartbdb29552004-07-04 00:32:48 +00004667 }
Aric Stewartfa384f62004-12-22 18:46:17 +00004668 else if (path)
Aric Stewartbdb29552004-07-04 00:32:48 +00004669 {
4670 *pcchPathBuf = strlenW(path)+1;
4671 strcpyW(szPathBuf,path);
4672 TRACE("Returning Path %s\n",debugstr_w(path));
Aric Stewartfa384f62004-12-22 18:46:17 +00004673 rc = ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00004674 }
Mike McCormackba8200b2004-12-22 15:25:30 +00004675 HeapFree(GetProcessHeap(),0,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00004676
4677 return rc;
Aric Stewarte95136b2004-06-29 03:44:01 +00004678}
Aric Stewart401bd3f2004-06-28 20:34:35 +00004679
4680
Aric Stewart6e160f12004-06-29 04:07:22 +00004681UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
4682 LPSTR szPathBuf, DWORD* pcchPathBuf)
4683{
4684 LPWSTR szwFolder;
4685 LPWSTR szwPathBuf;
Aric Stewarta3149f82004-07-09 19:38:40 +00004686 UINT rc;
Aric Stewart6e160f12004-06-29 04:07:22 +00004687
4688 TRACE("getting source %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
4689
4690 if (!szFolder)
4691 return ERROR_FUNCTION_FAILED;
4692 if (hInstall == 0)
4693 return ERROR_FUNCTION_FAILED;
4694
Aric Stewarta3149f82004-07-09 19:38:40 +00004695 szwFolder = strdupAtoW(szFolder);
Aric Stewart6e160f12004-06-29 04:07:22 +00004696 if (!szwFolder)
4697 return ERROR_FUNCTION_FAILED;
4698
4699 szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
4700
Aric Stewart6e160f12004-06-29 04:07:22 +00004701 rc = MsiGetSourcePathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
4702
4703 WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
4704 *pcchPathBuf, NULL, NULL );
4705
4706 HeapFree(GetProcessHeap(),0,szwFolder);
4707 HeapFree(GetProcessHeap(),0,szwPathBuf);
4708
4709 return rc;
4710}
4711
4712UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
4713 szPathBuf, DWORD* pcchPathBuf)
4714{
Mike McCormackba8200b2004-12-22 15:25:30 +00004715 LPWSTR path;
4716 UINT rc = ERROR_FUNCTION_FAILED;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004717 MSIPACKAGE *package;
Aric Stewart6e160f12004-06-29 04:07:22 +00004718
4719 TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004720
4721 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4722 if( !package )
4723 return ERROR_INVALID_HANDLE;
Mike McCormackba8200b2004-12-22 15:25:30 +00004724 path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004725 msiobj_release( &package->hdr );
Aric Stewart6e160f12004-06-29 04:07:22 +00004726
Mike McCormackba8200b2004-12-22 15:25:30 +00004727 if (path && strlenW(path) > *pcchPathBuf)
Aric Stewart6e160f12004-06-29 04:07:22 +00004728 {
Aric Stewartbdb29552004-07-04 00:32:48 +00004729 *pcchPathBuf = strlenW(path)+1;
Aric Stewartfa384f62004-12-22 18:46:17 +00004730 rc = ERROR_MORE_DATA;
Aric Stewart6e160f12004-06-29 04:07:22 +00004731 }
Aric Stewartfa384f62004-12-22 18:46:17 +00004732 else if (path)
Aric Stewartbdb29552004-07-04 00:32:48 +00004733 {
4734 *pcchPathBuf = strlenW(path)+1;
4735 strcpyW(szPathBuf,path);
4736 TRACE("Returning Path %s\n",debugstr_w(path));
Aric Stewartfa384f62004-12-22 18:46:17 +00004737 rc = ERROR_SUCCESS;
Aric Stewartbdb29552004-07-04 00:32:48 +00004738 }
Aric Stewartfa384f62004-12-22 18:46:17 +00004739 HeapFree(GetProcessHeap(),0,path);
Aric Stewartbdb29552004-07-04 00:32:48 +00004740
Aric Stewart6e160f12004-06-29 04:07:22 +00004741 return rc;
4742}
4743
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004744
4745UINT WINAPI MsiSetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder,
4746 LPCSTR szFolderPath)
4747{
4748 LPWSTR szwFolder;
4749 LPWSTR szwFolderPath;
Aric Stewarta3149f82004-07-09 19:38:40 +00004750 UINT rc;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004751
4752 if (!szFolder)
4753 return ERROR_FUNCTION_FAILED;
4754 if (hInstall == 0)
4755 return ERROR_FUNCTION_FAILED;
4756
Aric Stewarta3149f82004-07-09 19:38:40 +00004757 szwFolder = strdupAtoW(szFolder);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004758 if (!szwFolder)
4759 return ERROR_FUNCTION_FAILED;
4760
Aric Stewarta3149f82004-07-09 19:38:40 +00004761 szwFolderPath = strdupAtoW(szFolderPath);
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004762 if (!szwFolderPath)
4763 {
4764 HeapFree(GetProcessHeap(),0,szwFolder);
4765 return ERROR_FUNCTION_FAILED;
4766 }
4767
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004768 rc = MsiSetTargetPathW(hInstall, szwFolder, szwFolderPath);
4769
4770 HeapFree(GetProcessHeap(),0,szwFolder);
4771 HeapFree(GetProcessHeap(),0,szwFolderPath);
4772
4773 return rc;
4774}
4775
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004776UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004777 LPCWSTR szFolderPath)
4778{
Mike McCormack4604e662004-08-06 17:30:20 +00004779 DWORD i;
Mike McCormackba8200b2004-12-22 15:25:30 +00004780 LPWSTR path = NULL;
Aric Stewarte2d4ea82004-07-04 00:33:45 +00004781 MSIFOLDER *folder;
Aric Stewartbdb29552004-07-04 00:32:48 +00004782
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004783 TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
4784
4785 if (package==NULL)
4786 return ERROR_INVALID_HANDLE;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004787
Aric Stewartbdb29552004-07-04 00:32:48 +00004788 if (szFolderPath[0]==0)
4789 return ERROR_FUNCTION_FAILED;
4790
Aric Stewarte2d4ea82004-07-04 00:33:45 +00004791 if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES)
4792 return ERROR_FUNCTION_FAILED;
4793
Mike McCormackba8200b2004-12-22 15:25:30 +00004794 path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
4795 if (!path)
Aric Stewarte2d4ea82004-07-04 00:33:45 +00004796 return ERROR_INVALID_PARAMETER;
Mike McCormackba8200b2004-12-22 15:25:30 +00004797 HeapFree(GetProcessHeap(),0,path);
Aric Stewarte2d4ea82004-07-04 00:33:45 +00004798
4799 strcpyW(folder->Property,szFolderPath);
Aric Stewartbdb29552004-07-04 00:32:48 +00004800
4801 for (i = 0; i < package->loaded_folders; i++)
Mike McCormackba8200b2004-12-22 15:25:30 +00004802 package->folders[i].ResolvedTarget=NULL;
Aric Stewartbdb29552004-07-04 00:32:48 +00004803
Aric Stewartbdb29552004-07-04 00:32:48 +00004804 for (i = 0; i < package->loaded_folders; i++)
Mike McCormackba8200b2004-12-22 15:25:30 +00004805 {
4806 path = resolve_folder(package, package->folders[i].Directory, FALSE,
Aric Stewartbdb29552004-07-04 00:32:48 +00004807 TRUE, NULL);
Mike McCormackba8200b2004-12-22 15:25:30 +00004808 HeapFree(GetProcessHeap(),0,path);
4809 }
Aric Stewartbdb29552004-07-04 00:32:48 +00004810
4811 return ERROR_SUCCESS;
Aric Stewarted7c4bc2004-07-04 00:26:54 +00004812}
4813
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004814UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
4815 LPCWSTR szFolderPath)
4816{
4817 MSIPACKAGE *package;
4818 UINT ret;
4819
4820 TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
4821
4822 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4823 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
4824 msiobj_release( &package->hdr );
4825 return ret;
4826}
4827
Vitaly Lipatov5c4116b2004-12-16 14:29:25 +00004828/***********************************************************************
4829 * MsiGetMode (MSI.@)
4830 *
4831 * Returns an internal installer state (if it is running in a mode iRunMode)
4832 *
4833 * PARAMS
4834 * hInstall [I] Handle to the installation
4835 * hRunMode [I] Checking run mode
4836 * MSIRUNMODE_ADMIN Administrative mode
4837 * MSIRUNMODE_ADVERTISE Advertisement mode
4838 * MSIRUNMODE_MAINTENANCE Maintenance mode
4839 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
4840 * MSIRUNMODE_LOGENABLED Log file is writing
4841 * MSIRUNMODE_OPERATIONS Operations in progress??
4842 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
4843 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
4844 * MSIRUNMODE_CABINET Files from cabinet are installed
4845 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is supressed
4846 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is supressed
4847 * MSIRUNMODE_RESERVED11 Reserved
4848 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
4849 * MSIRUNMODE_ZAWENABLED Demand installation is supported
4850 * MSIRUNMODE_RESERVED14 Reserved
4851 * MSIRUNMODE_RESERVED15 Reserved
4852 * MSIRUNMODE_SCHEDULED called from install script
4853 * MSIRUNMODE_ROLLBACK called from rollback script
4854 * MSIRUNMODE_COMMIT called from commit script
4855 *
4856 * RETURNS
4857 * In the state: TRUE
4858 * Not in the state: FALSE
4859 *
4860 */
4861
4862BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
Aric Stewart6e160f12004-06-29 04:07:22 +00004863{
Vitaly Lipatov5c4116b2004-12-16 14:29:25 +00004864 FIXME("STUB (iRunMode=%i)\n",iRunMode);
4865 return TRUE;
Aric Stewart6e160f12004-06-29 04:07:22 +00004866}
4867
Aric Stewarta3149f82004-07-09 19:38:40 +00004868/*
Aric Stewartd906ef02004-10-22 22:06:31 +00004869 * According to the docs, when this is called it immediately recalculates
4870 * all the component states as well
Aric Stewarta3149f82004-07-09 19:38:40 +00004871 */
4872UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
4873 INSTALLSTATE iState)
4874{
4875 LPWSTR szwFeature = NULL;
4876 UINT rc;
4877
4878 szwFeature = strdupAtoW(szFeature);
4879
4880 if (!szwFeature)
4881 return ERROR_FUNCTION_FAILED;
4882
4883 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
4884
4885 HeapFree(GetProcessHeap(),0,szwFeature);
4886
4887 return rc;
4888}
4889
4890UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
4891 INSTALLSTATE iState)
4892{
4893 MSIPACKAGE* package;
4894 INT index;
4895
4896 TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
4897
4898 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4899 if (!package)
4900 return ERROR_INVALID_HANDLE;
4901
4902 index = get_loaded_feature(package,szFeature);
4903 if (index < 0)
4904 return ERROR_UNKNOWN_FEATURE;
4905
4906 package->features[index].State = iState;
4907
4908 return ERROR_SUCCESS;
4909}
4910
4911UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
4912 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
4913{
4914 LPWSTR szwFeature = NULL;
4915 UINT rc;
4916
4917 szwFeature = strdupAtoW(szFeature);
4918
4919 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
4920
4921 HeapFree( GetProcessHeap(), 0 , szwFeature);
4922
4923 return rc;
4924}
4925
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004926UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
Aric Stewarta3149f82004-07-09 19:38:40 +00004927 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
4928{
Aric Stewarta3149f82004-07-09 19:38:40 +00004929 INT index;
4930
Aric Stewarta3149f82004-07-09 19:38:40 +00004931 index = get_loaded_feature(package,szFeature);
4932 if (index < 0)
4933 return ERROR_UNKNOWN_FEATURE;
4934
4935 if (piInstalled)
4936 *piInstalled = package->features[index].State;
4937
4938 if (piAction)
4939 {
4940 if (package->features[index].Enabled)
4941 *piAction = INSTALLSTATE_LOCAL;
4942 else
4943 *piAction = INSTALLSTATE_UNKNOWN;
4944 }
4945
4946 return ERROR_SUCCESS;
4947}
4948
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004949UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
4950 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
4951{
4952 MSIPACKAGE* package;
4953 UINT ret;
4954
4955 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
4956piAction);
4957
4958 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
4959 if (!package)
4960 return ERROR_INVALID_HANDLE;
4961 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
4962 msiobj_release( &package->hdr );
4963 return ret;
4964}
4965
Aric Stewarta3149f82004-07-09 19:38:40 +00004966UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
4967 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
4968{
4969 LPWSTR szwComponent= NULL;
4970 UINT rc;
4971
4972 szwComponent= strdupAtoW(szComponent);
4973
4974 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
4975
4976 HeapFree( GetProcessHeap(), 0 , szwComponent);
4977
4978 return rc;
4979}
4980
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004981UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
Aric Stewarta3149f82004-07-09 19:38:40 +00004982 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
4983{
Aric Stewarta3149f82004-07-09 19:38:40 +00004984 INT index;
4985
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00004986 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
Aric Stewarta3149f82004-07-09 19:38:40 +00004987piAction);
4988
Aric Stewarta3149f82004-07-09 19:38:40 +00004989 index = get_loaded_component(package,szComponent);
4990 if (index < 0)
4991 return ERROR_UNKNOWN_COMPONENT;
4992
4993 if (piInstalled)
4994 *piInstalled = package->components[index].State;
4995
4996 if (piAction)
4997 {
4998 if (package->components[index].Enabled &&
4999 package->components[index].FeatureState)
5000 *piAction = INSTALLSTATE_LOCAL;
5001 else
5002 *piAction = INSTALLSTATE_UNKNOWN;
5003 }
5004
5005 return ERROR_SUCCESS;
5006}
5007
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005008UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
5009 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
Aric Stewart401bd3f2004-06-28 20:34:35 +00005010{
Aric Stewart8f0a7612004-07-06 18:53:11 +00005011 MSIPACKAGE* package;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005012 UINT ret;
Aric Stewart401bd3f2004-06-28 20:34:35 +00005013
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005014 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
5015 piInstalled, piAction);
5016
5017 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
Aric Stewart8f0a7612004-07-06 18:53:11 +00005018 if (!package)
5019 return ERROR_INVALID_HANDLE;
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005020 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
5021 msiobj_release( &package->hdr );
5022 return ret;
5023}
Aric Stewart8f0a7612004-07-06 18:53:11 +00005024
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005025#if 0
5026static UINT ACTION_Template(MSIPACKAGE *package)
5027{
5028 UINT rc;
5029 MSIQUERY * view;
5030 MSIRECORD * row = 0;
5031 static const WCHAR ExecSeqQuery[] = {0};
Aric Stewarteb0e0df2004-06-30 19:38:36 +00005032
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005033 rc = MsiDatabaseOpenViewW(package->db, ExecSeqQuery, &view);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005034 if (rc != ERROR_SUCCESS)
5035 return rc;
5036
5037 rc = MsiViewExecute(view, 0);
5038 if (rc != ERROR_SUCCESS)
5039 {
5040 MsiViewClose(view);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005041 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005042 return rc;
5043 }
5044
5045 while (1)
5046 {
5047 rc = MsiViewFetch(view,&row);
5048 if (rc != ERROR_SUCCESS)
5049 {
5050 rc = ERROR_SUCCESS;
5051 break;
5052 }
5053
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005054 msiobj_release(&row->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005055 }
5056 MsiViewClose(view);
Alexandre Julliarda7a6f5f2004-07-09 22:25:34 +00005057 msiobj_release(&view->hdr);
Aric Stewart401bd3f2004-06-28 20:34:35 +00005058 return rc;
5059}
5060#endif