xref: /reactos/dll/win32/msi/install.c (revision f4be6dc3)
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /* Msi top level apis directly related to installs */
22 
23 #define COBJMACROS
24 
25 #include <stdarg.h>
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "msi.h"
31 #include "msidefs.h"
32 #include "objbase.h"
33 #include "oleauto.h"
34 
35 #include "msipriv.h"
36 #include "winemsi_s.h"
37 #include "wine/debug.h"
38 #include "wine/exception.h"
39 
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
41 
42 /***********************************************************************
43  * MsiDoActionA       (MSI.@)
44  */
MsiDoActionA(MSIHANDLE hInstall,LPCSTR szAction)45 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
46 {
47     LPWSTR szwAction;
48     UINT ret;
49 
50     TRACE("%s\n", debugstr_a(szAction));
51 
52     szwAction = strdupAtoW(szAction);
53     if (szAction && !szwAction)
54         return ERROR_FUNCTION_FAILED;
55 
56     ret = MsiDoActionW( hInstall, szwAction );
57     free( szwAction );
58     return ret;
59 }
60 
61 /***********************************************************************
62  * MsiDoActionW       (MSI.@)
63  */
MsiDoActionW(MSIHANDLE hInstall,LPCWSTR szAction)64 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
65 {
66     MSIPACKAGE *package;
67     UINT ret;
68 
69     TRACE("%s\n",debugstr_w(szAction));
70 
71     if (!szAction)
72         return ERROR_INVALID_PARAMETER;
73 
74     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
75     if (!package)
76     {
77         MSIHANDLE remote;
78 
79         if (!(remote = msi_get_remote(hInstall)))
80             return ERROR_INVALID_HANDLE;
81 
82         __TRY
83         {
84             ret = remote_DoAction(remote, szAction);
85         }
86         __EXCEPT(rpc_filter)
87         {
88             ret = GetExceptionCode();
89         }
90         __ENDTRY
91 
92         return ret;
93     }
94 
95     ret = ACTION_PerformAction(package, szAction);
96     msiobj_release( &package->hdr );
97 
98     return ret;
99 }
100 
101 /***********************************************************************
102  * MsiSequenceA       (MSI.@)
103  */
MsiSequenceA(MSIHANDLE hInstall,LPCSTR szTable,INT iSequenceMode)104 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
105 {
106     LPWSTR szwTable;
107     UINT ret;
108 
109     TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
110 
111     szwTable = strdupAtoW(szTable);
112     if (szTable && !szwTable)
113         return ERROR_FUNCTION_FAILED;
114 
115     ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
116     free( szwTable );
117     return ret;
118 }
119 
120 /***********************************************************************
121  * MsiSequenceW       (MSI.@)
122  */
MsiSequenceW(MSIHANDLE hInstall,LPCWSTR szTable,INT iSequenceMode)123 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
124 {
125     MSIPACKAGE *package;
126     UINT ret;
127 
128     TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
129 
130     if (!szTable)
131         return ERROR_INVALID_PARAMETER;
132 
133     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
134     if (!package)
135     {
136         MSIHANDLE remote;
137 
138         if (!(remote = msi_get_remote(hInstall)))
139             return ERROR_INVALID_HANDLE;
140 
141         __TRY
142         {
143             ret = remote_Sequence(remote, szTable, iSequenceMode);
144         }
145         __EXCEPT(rpc_filter)
146         {
147             ret = GetExceptionCode();
148         }
149         __ENDTRY
150 
151         return ret;
152     }
153     ret = MSI_Sequence( package, szTable );
154     msiobj_release( &package->hdr );
155     return ret;
156 }
157 
msi_strcpy_to_awstring(const WCHAR * str,int len,awstring * awbuf,DWORD * sz)158 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
159 {
160     UINT r = ERROR_SUCCESS;
161 
162     if (awbuf->str.w && !sz)
163         return ERROR_INVALID_PARAMETER;
164     if (!sz)
165         return ERROR_SUCCESS;
166 
167     if (len < 0) len = lstrlenW( str );
168 
169     if (awbuf->unicode && awbuf->str.w)
170     {
171         memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
172         if (*sz && len >= *sz)
173             awbuf->str.w[*sz - 1] = 0;
174     }
175     else
176     {
177         int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
178         if (lenA) lenA--;
179         WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
180         if (awbuf->str.a && *sz && lenA >= *sz)
181             awbuf->str.a[*sz - 1] = 0;
182         len = lenA;
183     }
184     if (awbuf->str.w && len >= *sz)
185         r = ERROR_MORE_DATA;
186     *sz = len;
187     return r;
188 }
189 
msi_strncpyWtoA(const WCHAR * str,int lenW,char * buf,DWORD * sz,BOOL remote)190 UINT msi_strncpyWtoA(const WCHAR *str, int lenW, char *buf, DWORD *sz, BOOL remote)
191 {
192     UINT r = ERROR_SUCCESS;
193     DWORD lenA;
194 
195     if (!sz)
196         return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
197 
198     if (lenW < 0) lenW = lstrlenW(str);
199     lenA = WideCharToMultiByte(CP_ACP, 0, str, lenW + 1, NULL, 0, NULL, NULL);
200     WideCharToMultiByte(CP_ACP, 0, str, lenW + 1, buf, *sz, NULL, NULL);
201     lenA--;
202     if (buf && lenA >= *sz)
203     {
204         if (*sz) buf[*sz - 1] = 0;
205         r = ERROR_MORE_DATA;
206     }
207     if (remote && lenA >= *sz)
208         lenA *= 2;
209     *sz = lenA;
210     return r;
211 }
212 
msi_strncpyW(const WCHAR * str,int len,WCHAR * buf,DWORD * sz)213 UINT msi_strncpyW(const WCHAR *str, int len, WCHAR *buf, DWORD *sz)
214 {
215     UINT r = ERROR_SUCCESS;
216 
217     if (!sz)
218         return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
219 
220     if (len < 0) len = lstrlenW(str);
221     if (buf)
222         memcpy(buf, str, min(len + 1, *sz) * sizeof(WCHAR));
223     if (buf && len >= *sz)
224     {
225         if (*sz) buf[*sz - 1] = 0;
226         r = ERROR_MORE_DATA;
227     }
228     *sz = len;
229     return r;
230 }
231 
msi_get_target_folder(MSIPACKAGE * package,const WCHAR * name)232 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
233 {
234     MSIFOLDER *folder = msi_get_loaded_folder( package, name );
235 
236     if (!folder) return NULL;
237     if (!folder->ResolvedTarget)
238     {
239         MSIFOLDER *parent = folder;
240         while (parent->Parent && wcscmp( parent->Parent, parent->Directory ))
241         {
242             parent = msi_get_loaded_folder( package, parent->Parent );
243         }
244         msi_resolve_target_folder( package, parent->Directory, TRUE );
245     }
246     return folder->ResolvedTarget;
247 }
248 
249 /***********************************************************************
250  * MsiGetTargetPathA        (MSI.@)
251  */
MsiGetTargetPathA(MSIHANDLE hinst,const char * folder,char * buf,DWORD * sz)252 UINT WINAPI MsiGetTargetPathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
253 {
254     MSIPACKAGE *package;
255     const WCHAR *path;
256     WCHAR *folderW;
257     UINT r;
258 
259     TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
260 
261     if (!folder)
262         return ERROR_INVALID_PARAMETER;
263 
264     if (!(folderW = strdupAtoW(folder)))
265         return ERROR_OUTOFMEMORY;
266 
267     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
268     if (!package)
269     {
270         WCHAR *path = NULL;
271         MSIHANDLE remote;
272 
273         if (!(remote = msi_get_remote(hinst)))
274         {
275             free(folderW);
276             return ERROR_INVALID_HANDLE;
277         }
278 
279         __TRY
280         {
281             r = remote_GetTargetPath(remote, folderW, &path);
282         }
283         __EXCEPT(rpc_filter)
284         {
285             r = GetExceptionCode();
286         }
287         __ENDTRY
288 
289         if (!r)
290             r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
291 
292         midl_user_free(path);
293         free(folderW);
294         return r;
295     }
296 
297     path = msi_get_target_folder(package, folderW);
298     if (path)
299         r = msi_strncpyWtoA(path, -1, buf, sz, FALSE);
300     else
301         r = ERROR_DIRECTORY;
302 
303     free(folderW);
304     msiobj_release(&package->hdr);
305     return r;
306 }
307 
308 /***********************************************************************
309  * MsiGetTargetPathW        (MSI.@)
310  */
MsiGetTargetPathW(MSIHANDLE hinst,const WCHAR * folder,WCHAR * buf,DWORD * sz)311 UINT WINAPI MsiGetTargetPathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
312 {
313     MSIPACKAGE *package;
314     const WCHAR *path;
315     UINT r;
316 
317     TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
318 
319     if (!folder)
320         return ERROR_INVALID_PARAMETER;
321 
322     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
323     if (!package)
324     {
325         WCHAR *path = NULL;
326         MSIHANDLE remote;
327 
328         if (!(remote = msi_get_remote(hinst)))
329             return ERROR_INVALID_HANDLE;
330 
331         __TRY
332         {
333             r = remote_GetTargetPath(remote, folder, &path);
334         }
335         __EXCEPT(rpc_filter)
336         {
337             r = GetExceptionCode();
338         }
339         __ENDTRY
340 
341         if (!r)
342             r = msi_strncpyW(path, -1, buf, sz);
343 
344         midl_user_free(path);
345         return r;
346     }
347 
348     path = msi_get_target_folder(package, folder);
349     if (path)
350         r = msi_strncpyW(path, -1, buf, sz);
351     else
352         r = ERROR_DIRECTORY;
353 
354     msiobj_release(&package->hdr);
355     return r;
356 }
357 
get_source_root(MSIPACKAGE * package)358 static WCHAR *get_source_root( MSIPACKAGE *package )
359 {
360     msi_set_sourcedir_props( package, FALSE );
361     return msi_dup_property( package->db, L"SourceDir" );
362 }
363 
msi_resolve_source_folder(MSIPACKAGE * package,const WCHAR * name,MSIFOLDER ** folder)364 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
365 {
366     MSIFOLDER *f;
367     LPWSTR p, path = NULL, parent;
368 
369     TRACE("working to resolve %s\n", debugstr_w(name));
370 
371     if (!wcscmp( name, L"SourceDir" )) name = L"TARGETDIR";
372     if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
373 
374     /* special resolving for root dir */
375     if (!wcscmp( name, L"TARGETDIR" ) && !f->ResolvedSource)
376     {
377         f->ResolvedSource = get_source_root( package );
378     }
379     if (folder) *folder = f;
380     if (f->ResolvedSource)
381     {
382         path = wcsdup( f->ResolvedSource );
383         TRACE("   already resolved to %s\n", debugstr_w(path));
384         return path;
385     }
386     if (!f->Parent) return path;
387     parent = f->Parent;
388     TRACE(" ! parent is %s\n", debugstr_w(parent));
389 
390     p = msi_resolve_source_folder( package, parent, NULL );
391 
392     if (package->WordCount & msidbSumInfoSourceTypeCompressed)
393         path = get_source_root( package );
394     else if (package->WordCount & msidbSumInfoSourceTypeSFN)
395         path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
396     else
397         path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
398 
399     TRACE("-> %s\n", debugstr_w(path));
400     f->ResolvedSource = wcsdup( path );
401     free( p );
402 
403     return path;
404 }
405 
406 /***********************************************************************
407  * MsiGetSourcePathA     (MSI.@)
408  */
MsiGetSourcePathA(MSIHANDLE hinst,const char * folder,char * buf,DWORD * sz)409 UINT WINAPI MsiGetSourcePathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
410 {
411     MSIPACKAGE *package;
412     WCHAR *path, *folderW;
413     UINT r;
414 
415     TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
416 
417     if (!folder)
418         return ERROR_INVALID_PARAMETER;
419 
420     if (!(folderW = strdupAtoW(folder)))
421         return ERROR_OUTOFMEMORY;
422 
423     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
424     if (!package)
425     {
426         WCHAR *path = NULL;
427         MSIHANDLE remote;
428 
429         if (!(remote = msi_get_remote(hinst)))
430         {
431             free(folderW);
432             return ERROR_INVALID_HANDLE;
433         }
434 
435         __TRY
436         {
437             r = remote_GetSourcePath(remote, folderW, &path);
438         }
439         __EXCEPT(rpc_filter)
440         {
441             r = GetExceptionCode();
442         }
443         __ENDTRY
444 
445         if (!r)
446             r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
447 
448         midl_user_free(path);
449         free(folderW);
450         return r;
451     }
452 
453     path = msi_resolve_source_folder(package, folderW, NULL);
454     if (path)
455         r = msi_strncpyWtoA(path, -1, buf, sz, FALSE);
456     else
457         r = ERROR_DIRECTORY;
458 
459     free(path);
460     free(folderW);
461     msiobj_release(&package->hdr);
462     return r;
463 }
464 
465 /***********************************************************************
466  * MsiGetSourcePathW     (MSI.@)
467  */
MsiGetSourcePathW(MSIHANDLE hinst,const WCHAR * folder,WCHAR * buf,DWORD * sz)468 UINT WINAPI MsiGetSourcePathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
469 {
470     MSIPACKAGE *package;
471     WCHAR *path;
472     UINT r;
473 
474     TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
475 
476     if (!folder)
477         return ERROR_INVALID_PARAMETER;
478 
479     package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
480     if (!package)
481     {
482         WCHAR *path = NULL;
483         MSIHANDLE remote;
484 
485         if (!(remote = msi_get_remote(hinst)))
486             return ERROR_INVALID_HANDLE;
487 
488         __TRY
489         {
490             r = remote_GetSourcePath(remote, folder, &path);
491         }
492         __EXCEPT(rpc_filter)
493         {
494             r = GetExceptionCode();
495         }
496         __ENDTRY
497 
498         if (!r)
499             r = msi_strncpyW(path, -1, buf, sz);
500 
501         midl_user_free(path);
502         return r;
503     }
504 
505     path = msi_resolve_source_folder(package, folder, NULL);
506     if (path)
507         r = msi_strncpyW(path, -1, buf, sz);
508     else
509         r = ERROR_DIRECTORY;
510 
511     free(path);
512     msiobj_release(&package->hdr);
513     return r;
514 }
515 
516 /***********************************************************************
517  * MsiSetTargetPathA  (MSI.@)
518  */
MsiSetTargetPathA(MSIHANDLE hInstall,LPCSTR szFolder,LPCSTR szFolderPath)519 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
520                                LPCSTR szFolderPath )
521 {
522     LPWSTR szwFolder = NULL, szwFolderPath = NULL;
523     UINT rc = ERROR_OUTOFMEMORY;
524 
525     if ( !szFolder || !szFolderPath )
526         return ERROR_INVALID_PARAMETER;
527 
528     szwFolder = strdupAtoW(szFolder);
529     szwFolderPath = strdupAtoW(szFolderPath);
530     if (!szwFolder || !szwFolderPath)
531         goto end;
532 
533     rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
534 
535 end:
536     free(szwFolder);
537     free(szwFolderPath);
538 
539     return rc;
540 }
541 
set_target_path(MSIPACKAGE * package,MSIFOLDER * folder,const WCHAR * path)542 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
543 {
544     FolderList *fl;
545     MSIFOLDER *child;
546     WCHAR *target_path;
547 
548     if (!(target_path = msi_normalize_path( path ))) return;
549     if (wcscmp( target_path, folder->ResolvedTarget ))
550     {
551         free( folder->ResolvedTarget );
552         folder->ResolvedTarget = target_path;
553         msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
554 
555         LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
556         {
557             child = fl->folder;
558             msi_resolve_target_folder( package, child->Directory, FALSE );
559         }
560     }
561     else free( target_path );
562 }
563 
MSI_SetTargetPathW(MSIPACKAGE * package,LPCWSTR szFolder,LPCWSTR szFolderPath)564 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
565 {
566     DWORD attrib;
567     MSIFOLDER *folder;
568     MSIFILE *file;
569 
570     TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
571 
572     attrib = msi_get_file_attributes( package, szFolderPath );
573     /* native MSI tests writeability by making temporary files at each drive */
574     if (attrib != INVALID_FILE_ATTRIBUTES &&
575         (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
576     {
577         return ERROR_FUNCTION_FAILED;
578     }
579     if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
580 
581     set_target_path( package, folder, szFolderPath );
582 
583     LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
584     {
585         const WCHAR *dir;
586         MSICOMPONENT *comp = file->Component;
587 
588         if (!comp->Enabled || msi_is_global_assembly( comp )) continue;
589 
590         dir = msi_get_target_folder( package, comp->Directory );
591         free( file->TargetPath );
592         file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
593     }
594     return ERROR_SUCCESS;
595 }
596 
597 /***********************************************************************
598  * MsiSetTargetPathW  (MSI.@)
599  */
MsiSetTargetPathW(MSIHANDLE hInstall,LPCWSTR szFolder,LPCWSTR szFolderPath)600 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
601                              LPCWSTR szFolderPath)
602 {
603     MSIPACKAGE *package;
604     UINT ret;
605 
606     TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
607 
608     if ( !szFolder || !szFolderPath )
609         return ERROR_INVALID_PARAMETER;
610 
611     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
612     if (!package)
613     {
614         MSIHANDLE remote;
615 
616         if (!(remote = msi_get_remote(hInstall)))
617             return ERROR_INVALID_HANDLE;
618 
619         __TRY
620         {
621             ret = remote_SetTargetPath(remote, szFolder, szFolderPath);
622         }
623         __EXCEPT(rpc_filter)
624         {
625             ret = GetExceptionCode();
626         }
627         __ENDTRY
628 
629         return ret;
630     }
631 
632     ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
633     msiobj_release( &package->hdr );
634     return ret;
635 }
636 
637 /***********************************************************************
638  *           MsiGetMode    (MSI.@)
639  *
640  * Returns an internal installer state (if it is running in a mode iRunMode)
641  *
642  * PARAMS
643  *   hInstall    [I]  Handle to the installation
644  *   hRunMode    [I]  Checking run mode
645  *        MSIRUNMODE_ADMIN             Administrative mode
646  *        MSIRUNMODE_ADVERTISE         Advertisement mode
647  *        MSIRUNMODE_MAINTENANCE       Maintenance mode
648  *        MSIRUNMODE_ROLLBACKENABLED   Rollback is enabled
649  *        MSIRUNMODE_LOGENABLED        Log file is writing
650  *        MSIRUNMODE_OPERATIONS        Operations in progress??
651  *        MSIRUNMODE_REBOOTATEND       We need to reboot after installation completed
652  *        MSIRUNMODE_REBOOTNOW         We need to reboot to continue the installation
653  *        MSIRUNMODE_CABINET           Files from cabinet are installed
654  *        MSIRUNMODE_SOURCESHORTNAMES  Long names in source files is suppressed
655  *        MSIRUNMODE_TARGETSHORTNAMES  Long names in destination files is suppressed
656  *        MSIRUNMODE_RESERVED11        Reserved
657  *        MSIRUNMODE_WINDOWS9X         Running under Windows95/98
658  *        MSIRUNMODE_ZAWENABLED        Demand installation is supported
659  *        MSIRUNMODE_RESERVED14        Reserved
660  *        MSIRUNMODE_RESERVED15        Reserved
661  *        MSIRUNMODE_SCHEDULED         called from install script
662  *        MSIRUNMODE_ROLLBACK          called from rollback script
663  *        MSIRUNMODE_COMMIT            called from commit script
664  *
665  * RETURNS
666  *    In the state: TRUE
667  *    Not in the state: FALSE
668  *
669  */
MsiGetMode(MSIHANDLE hInstall,MSIRUNMODE iRunMode)670 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
671 {
672     MSIPACKAGE *package;
673     BOOL r = FALSE;
674 
675     TRACE( "%lu, %d\n", hInstall, iRunMode );
676 
677     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
678     if (!package)
679     {
680         MSIHANDLE remote;
681 
682         if (!(remote = msi_get_remote(hInstall)))
683             return FALSE;
684 
685         __TRY
686         {
687             r = remote_GetMode(remote, iRunMode);
688         }
689         __EXCEPT(rpc_filter)
690         {
691             r = FALSE;
692         }
693         __ENDTRY
694 
695         return r;
696     }
697 
698     switch (iRunMode)
699     {
700     case MSIRUNMODE_ADMIN:
701         FIXME("no support for administrative installs\n");
702         break;
703 
704     case MSIRUNMODE_ADVERTISE:
705         FIXME("no support for advertised installs\n");
706         break;
707 
708     case MSIRUNMODE_WINDOWS9X:
709         if (GetVersion() & 0x80000000)
710             r = TRUE;
711         break;
712 
713     case MSIRUNMODE_OPERATIONS:
714     case MSIRUNMODE_RESERVED11:
715     case MSIRUNMODE_RESERVED14:
716     case MSIRUNMODE_RESERVED15:
717         break;
718 
719     case MSIRUNMODE_SCHEDULED:
720         r = package->scheduled_action_running;
721         break;
722 
723     case MSIRUNMODE_ROLLBACK:
724         r = package->rollback_action_running;
725         break;
726 
727     case MSIRUNMODE_COMMIT:
728         r = package->commit_action_running;
729         break;
730 
731     case MSIRUNMODE_MAINTENANCE:
732         r = msi_get_property_int( package->db, L"Installed", 0 ) != 0;
733         break;
734 
735     case MSIRUNMODE_ROLLBACKENABLED:
736         r = msi_get_property_int( package->db, L"RollbackDisabled", 0 ) == 0;
737         break;
738 
739     case MSIRUNMODE_REBOOTATEND:
740         r = package->need_reboot_at_end;
741         break;
742 
743     case MSIRUNMODE_REBOOTNOW:
744         r = package->need_reboot_now;
745         break;
746 
747     case MSIRUNMODE_LOGENABLED:
748         r = (package->log_file != INVALID_HANDLE_VALUE);
749         break;
750 
751     default:
752         FIXME("unimplemented run mode: %d\n", iRunMode);
753         r = TRUE;
754     }
755 
756     msiobj_release( &package->hdr );
757     return r;
758 }
759 
760 /***********************************************************************
761  *           MsiSetMode    (MSI.@)
762  */
MsiSetMode(MSIHANDLE hInstall,MSIRUNMODE iRunMode,BOOL fState)763 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
764 {
765     MSIPACKAGE *package;
766     UINT r;
767 
768     TRACE( "%lu, %d, %d\n", hInstall, iRunMode, fState );
769 
770     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
771     if (!package)
772     {
773         MSIHANDLE remote;
774 
775         if (!(remote = msi_get_remote(hInstall)))
776             return FALSE;
777 
778         __TRY
779         {
780             r = remote_SetMode(remote, iRunMode, fState);
781         }
782         __EXCEPT(rpc_filter)
783         {
784             r = GetExceptionCode();
785         }
786         __ENDTRY
787 
788         return r;
789     }
790 
791     switch (iRunMode)
792     {
793     case MSIRUNMODE_REBOOTATEND:
794         package->need_reboot_at_end = (fState != 0);
795         r = ERROR_SUCCESS;
796         break;
797 
798     case MSIRUNMODE_REBOOTNOW:
799         package->need_reboot_now = (fState != 0);
800         r = ERROR_SUCCESS;
801         break;
802 
803     default:
804         r = ERROR_ACCESS_DENIED;
805     }
806 
807     msiobj_release( &package->hdr );
808     return r;
809 }
810 
811 /***********************************************************************
812  * MsiSetFeatureStateA (MSI.@)
813  *
814  * According to the docs, when this is called it immediately recalculates
815  * all the component states as well
816  */
MsiSetFeatureStateA(MSIHANDLE hInstall,LPCSTR szFeature,INSTALLSTATE iState)817 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
818                                 INSTALLSTATE iState)
819 {
820     LPWSTR szwFeature = NULL;
821     UINT rc;
822 
823     szwFeature = strdupAtoW(szFeature);
824 
825     rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
826 
827     free(szwFeature);
828 
829     return rc;
830 }
831 
832 /* update component state based on a feature change */
ACTION_UpdateComponentStates(MSIPACKAGE * package,MSIFEATURE * feature)833 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
834 {
835     INSTALLSTATE newstate;
836     ComponentList *cl;
837 
838     newstate = feature->ActionRequest;
839     if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
840 
841     LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
842     {
843         MSICOMPONENT *component = cl->component;
844 
845         if (!component->Enabled) continue;
846 
847         TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
848             newstate, debugstr_w(component->Component), component->Installed,
849             component->Action, component->ActionRequest);
850 
851         if (newstate == INSTALLSTATE_LOCAL)
852         {
853             component->Action = INSTALLSTATE_LOCAL;
854             component->ActionRequest = INSTALLSTATE_LOCAL;
855         }
856         else
857         {
858             ComponentList *clist;
859             MSIFEATURE *f;
860 
861             component->hasLocalFeature = FALSE;
862 
863             component->Action = newstate;
864             component->ActionRequest = newstate;
865             /* if any other feature wants it local we need to set it local */
866             LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
867             {
868                 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
869                      f->ActionRequest != INSTALLSTATE_SOURCE )
870                 {
871                     continue;
872                 }
873                 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
874                 {
875                     if (clist->component == component &&
876                         (f->ActionRequest == INSTALLSTATE_LOCAL ||
877                          f->ActionRequest == INSTALLSTATE_SOURCE))
878                     {
879                         TRACE("Saved by %s\n", debugstr_w(f->Feature));
880                         component->hasLocalFeature = TRUE;
881 
882                         if (component->Attributes & msidbComponentAttributesOptional)
883                         {
884                             if (f->Attributes & msidbFeatureAttributesFavorSource)
885                             {
886                                 component->Action = INSTALLSTATE_SOURCE;
887                                 component->ActionRequest = INSTALLSTATE_SOURCE;
888                             }
889                             else
890                             {
891                                 component->Action = INSTALLSTATE_LOCAL;
892                                 component->ActionRequest = INSTALLSTATE_LOCAL;
893                             }
894                         }
895                         else if (component->Attributes & msidbComponentAttributesSourceOnly)
896                         {
897                             component->Action = INSTALLSTATE_SOURCE;
898                             component->ActionRequest = INSTALLSTATE_SOURCE;
899                         }
900                         else
901                         {
902                             component->Action = INSTALLSTATE_LOCAL;
903                             component->ActionRequest = INSTALLSTATE_LOCAL;
904                         }
905                     }
906                 }
907             }
908         }
909         TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
910             newstate, debugstr_w(component->Component), component->Installed,
911             component->Action, component->ActionRequest);
912     }
913 }
914 
MSI_SetFeatureStateW(MSIPACKAGE * package,LPCWSTR szFeature,INSTALLSTATE iState)915 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
916 {
917     UINT rc = ERROR_SUCCESS;
918     MSIFEATURE *feature, *child;
919 
920     TRACE("%s %i\n", debugstr_w(szFeature), iState);
921 
922     feature = msi_get_loaded_feature( package, szFeature );
923     if (!feature)
924         return ERROR_UNKNOWN_FEATURE;
925 
926     if (iState == INSTALLSTATE_ADVERTISED &&
927         feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
928         return ERROR_FUNCTION_FAILED;
929 
930     feature->ActionRequest = iState;
931 
932     ACTION_UpdateComponentStates( package, feature );
933 
934     /* update all the features that are children of this feature */
935     LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
936     {
937         if (child->Feature_Parent && !wcscmp( szFeature, child->Feature_Parent ))
938             MSI_SetFeatureStateW(package, child->Feature, iState);
939     }
940 
941     return rc;
942 }
943 
944 /***********************************************************************
945  * MsiSetFeatureStateW (MSI.@)
946  */
MsiSetFeatureStateW(MSIHANDLE hInstall,LPCWSTR szFeature,INSTALLSTATE iState)947 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
948                                 INSTALLSTATE iState)
949 {
950     MSIPACKAGE* package;
951     UINT rc = ERROR_SUCCESS;
952 
953     TRACE("%s %i\n",debugstr_w(szFeature), iState);
954 
955     if (!szFeature)
956         return ERROR_UNKNOWN_FEATURE;
957 
958     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
959     if (!package)
960     {
961         MSIHANDLE remote;
962 
963         if (!(remote = msi_get_remote(hInstall)))
964             return ERROR_INVALID_HANDLE;
965 
966         __TRY
967         {
968             rc = remote_SetFeatureState(remote, szFeature, iState);
969         }
970         __EXCEPT(rpc_filter)
971         {
972             rc = GetExceptionCode();
973         }
974         __ENDTRY
975 
976         return rc;
977     }
978 
979     rc = MSI_SetFeatureStateW(package,szFeature,iState);
980 
981     msiobj_release( &package->hdr );
982     return rc;
983 }
984 
985 /***********************************************************************
986 * MsiSetFeatureAttributesA   (MSI.@)
987 */
MsiSetFeatureAttributesA(MSIHANDLE handle,LPCSTR feature,DWORD attrs)988 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
989 {
990     UINT r;
991     WCHAR *featureW = NULL;
992 
993     TRACE( "%lu, %s, %#lx\n", handle, debugstr_a(feature), attrs );
994 
995     if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
996 
997     r = MsiSetFeatureAttributesW( handle, featureW, attrs );
998     free( featureW );
999     return r;
1000 }
1001 
unmap_feature_attributes(DWORD attrs)1002 static DWORD unmap_feature_attributes( DWORD attrs )
1003 {
1004     DWORD ret = 0;
1005 
1006     if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL)             ret = msidbFeatureAttributesFavorLocal;
1007     if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE)            ret |= msidbFeatureAttributesFavorSource;
1008     if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT)           ret |= msidbFeatureAttributesFollowParent;
1009     if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE)         ret |= msidbFeatureAttributesFavorAdvertise;
1010     if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE)      ret |= msidbFeatureAttributesDisallowAdvertise;
1011     if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
1012     return ret;
1013 }
1014 
1015 /***********************************************************************
1016 * MsiSetFeatureAttributesW   (MSI.@)
1017 */
MsiSetFeatureAttributesW(MSIHANDLE handle,LPCWSTR name,DWORD attrs)1018 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
1019 {
1020     MSIPACKAGE *package;
1021     MSIFEATURE *feature;
1022     WCHAR *costing;
1023 
1024     TRACE( "%lu, %s, %#lx\n", handle, debugstr_w(name), attrs );
1025 
1026     if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
1027 
1028     if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1029         return ERROR_INVALID_HANDLE;
1030 
1031     costing = msi_dup_property( package->db, L"CostingComplete" );
1032     if (!costing || !wcscmp( costing, L"1" ))
1033     {
1034         free( costing );
1035         msiobj_release( &package->hdr );
1036         return ERROR_FUNCTION_FAILED;
1037     }
1038     free( costing );
1039     if (!(feature = msi_get_loaded_feature( package, name )))
1040     {
1041         msiobj_release( &package->hdr );
1042         return ERROR_UNKNOWN_FEATURE;
1043     }
1044     feature->Attributes = unmap_feature_attributes( attrs );
1045     msiobj_release( &package->hdr );
1046     return ERROR_SUCCESS;
1047 }
1048 
1049 /***********************************************************************
1050 * MsiGetFeatureStateA   (MSI.@)
1051 */
MsiGetFeatureStateA(MSIHANDLE hInstall,LPCSTR szFeature,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1052 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
1053                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1054 {
1055     LPWSTR szwFeature = NULL;
1056     UINT rc;
1057 
1058     if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
1059 
1060     rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
1061     free(szwFeature);
1062     return rc;
1063 }
1064 
MSI_GetFeatureStateW(MSIPACKAGE * package,LPCWSTR szFeature,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1065 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
1066                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1067 {
1068     MSIFEATURE *feature;
1069 
1070     feature = msi_get_loaded_feature(package,szFeature);
1071     if (!feature)
1072         return ERROR_UNKNOWN_FEATURE;
1073 
1074     if (piInstalled)
1075         *piInstalled = feature->Installed;
1076 
1077     if (piAction)
1078         *piAction = feature->ActionRequest;
1079 
1080     TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
1081 
1082     return ERROR_SUCCESS;
1083 }
1084 
1085 /***********************************************************************
1086 * MsiGetFeatureStateW   (MSI.@)
1087 */
MsiGetFeatureStateW(MSIHANDLE hInstall,const WCHAR * szFeature,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1088 UINT WINAPI MsiGetFeatureStateW( MSIHANDLE hInstall, const WCHAR *szFeature, INSTALLSTATE *piInstalled,
1089                                  INSTALLSTATE *piAction )
1090 {
1091     MSIPACKAGE* package;
1092     UINT ret;
1093 
1094     TRACE( "%lu, %s, %p, %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction );
1095 
1096     if (!szFeature)
1097         return ERROR_UNKNOWN_FEATURE;
1098 
1099     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1100     if (!package)
1101     {
1102         MSIHANDLE remote;
1103 
1104         if (!(remote = msi_get_remote(hInstall)))
1105             return ERROR_INVALID_HANDLE;
1106 
1107         __TRY
1108         {
1109             ret = remote_GetFeatureState(remote, szFeature, piInstalled, piAction);
1110         }
1111         __EXCEPT(rpc_filter)
1112         {
1113             ret = GetExceptionCode();
1114         }
1115         __ENDTRY
1116 
1117         return ret;
1118     }
1119 
1120     ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1121     msiobj_release( &package->hdr );
1122     return ret;
1123 }
1124 
1125 /***********************************************************************
1126 * MsiGetFeatureCostA   (MSI.@)
1127 */
MsiGetFeatureCostA(MSIHANDLE hInstall,LPCSTR szFeature,MSICOSTTREE iCostTree,INSTALLSTATE iState,LPINT piCost)1128 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1129                   MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1130 {
1131     LPWSTR szwFeature = NULL;
1132     UINT rc;
1133 
1134     szwFeature = strdupAtoW(szFeature);
1135 
1136     rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1137 
1138     free(szwFeature);
1139 
1140     return rc;
1141 }
1142 
feature_cost(MSIFEATURE * feature)1143 static INT feature_cost( MSIFEATURE *feature )
1144 {
1145     INT cost = 0;
1146     ComponentList *cl;
1147 
1148     LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
1149     {
1150         cost += cl->component->cost;
1151     }
1152     return cost;
1153 }
1154 
MSI_GetFeatureCost(MSIPACKAGE * package,MSIFEATURE * feature,MSICOSTTREE tree,INSTALLSTATE state,LPINT cost)1155 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1156                          INSTALLSTATE state, LPINT cost )
1157 {
1158     TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1159 
1160     *cost = 0;
1161     switch (tree)
1162     {
1163     case MSICOSTTREE_CHILDREN:
1164     {
1165         MSIFEATURE *child;
1166 
1167         LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1168         {
1169             if (child->ActionRequest == state)
1170                 *cost += feature_cost( child );
1171         }
1172         break;
1173     }
1174     case MSICOSTTREE_PARENTS:
1175     {
1176         const WCHAR *feature_parent = feature->Feature_Parent;
1177         for (;;)
1178         {
1179             MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1180             if (!parent)
1181                 break;
1182 
1183             if (parent->ActionRequest == state)
1184                 *cost += feature_cost( parent );
1185 
1186             feature_parent = parent->Feature_Parent;
1187         }
1188         break;
1189     }
1190     case MSICOSTTREE_SELFONLY:
1191         if (feature->ActionRequest == state)
1192             *cost = feature_cost( feature );
1193         break;
1194 
1195     default:
1196         WARN("unhandled cost tree %u\n", tree);
1197         break;
1198     }
1199 
1200     return ERROR_SUCCESS;
1201 }
1202 
1203 /***********************************************************************
1204 * MsiGetFeatureCostW   (MSI.@)
1205 */
MsiGetFeatureCostW(MSIHANDLE hInstall,const WCHAR * szFeature,MSICOSTTREE iCostTree,INSTALLSTATE iState,INT * piCost)1206 UINT WINAPI MsiGetFeatureCostW( MSIHANDLE hInstall, const WCHAR *szFeature, MSICOSTTREE iCostTree,
1207                                 INSTALLSTATE iState, INT *piCost )
1208 {
1209     MSIPACKAGE *package;
1210     MSIFEATURE *feature;
1211     UINT ret;
1212 
1213     TRACE( "%lu, %s, %d, %d, %p\n", hInstall, debugstr_w(szFeature), iCostTree, iState, piCost );
1214 
1215     if (!szFeature)
1216         return ERROR_INVALID_PARAMETER;
1217 
1218     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1219     if (!package)
1220     {
1221         MSIHANDLE remote;
1222 
1223         if (!(remote = msi_get_remote(hInstall)))
1224             return ERROR_INVALID_HANDLE;
1225 
1226         __TRY
1227         {
1228             ret = remote_GetFeatureCost(remote, szFeature, iCostTree, iState, piCost);
1229         }
1230         __EXCEPT(rpc_filter)
1231         {
1232             ret = GetExceptionCode();
1233         }
1234         __ENDTRY
1235 
1236         return ret;
1237     }
1238 
1239     if (!piCost)
1240     {
1241         msiobj_release( &package->hdr );
1242         return ERROR_INVALID_PARAMETER;
1243     }
1244 
1245     feature = msi_get_loaded_feature(package, szFeature);
1246 
1247     if (feature)
1248         ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1249     else
1250         ret = ERROR_UNKNOWN_FEATURE;
1251 
1252     msiobj_release( &package->hdr );
1253     return ret;
1254 }
1255 
1256 /***********************************************************************
1257 * MsiGetFeatureInfoA   (MSI.@)
1258 */
MsiGetFeatureInfoA(MSIHANDLE handle,const char * feature,DWORD * attrs,char * title,DWORD * title_len,char * help,DWORD * help_len)1259 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, const char *feature, DWORD *attrs,
1260                                 char *title, DWORD *title_len, char *help, DWORD *help_len )
1261 {
1262     UINT r;
1263     WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1264 
1265     TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1266            title_len, help, help_len );
1267 
1268     if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1269 
1270     if (title && title_len && !(titleW = malloc( *title_len * sizeof(WCHAR) )))
1271     {
1272         free( featureW );
1273         return ERROR_OUTOFMEMORY;
1274     }
1275     if (help && help_len && !(helpW = malloc( *help_len * sizeof(WCHAR) )))
1276     {
1277         free( featureW );
1278         free( titleW );
1279         return ERROR_OUTOFMEMORY;
1280     }
1281     r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1282     if (r == ERROR_SUCCESS)
1283     {
1284         if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1285         if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1286     }
1287     free( titleW );
1288     free( helpW );
1289     free( featureW );
1290     return r;
1291 }
1292 
map_feature_attributes(DWORD attrs)1293 static DWORD map_feature_attributes( DWORD attrs )
1294 {
1295     DWORD ret = 0;
1296 
1297     if (attrs == msidbFeatureAttributesFavorLocal)            ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1298     if (attrs & msidbFeatureAttributesFavorSource)            ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1299     if (attrs & msidbFeatureAttributesFollowParent)           ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1300     if (attrs & msidbFeatureAttributesFavorAdvertise)         ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1301     if (attrs & msidbFeatureAttributesDisallowAdvertise)      ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1302     if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1303     return ret;
1304 }
1305 
MSI_GetFeatureInfo(MSIPACKAGE * package,LPCWSTR name,LPDWORD attrs,LPWSTR title,LPDWORD title_len,LPWSTR help,LPDWORD help_len)1306 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1307                                 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1308 {
1309     UINT r = ERROR_SUCCESS;
1310     MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1311     int len;
1312 
1313     if (!feature) return ERROR_UNKNOWN_FEATURE;
1314     if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1315     if (title_len)
1316     {
1317         if (feature->Title) len = lstrlenW( feature->Title );
1318         else len = 0;
1319         if (*title_len <= len)
1320         {
1321             *title_len = len;
1322             if (title) r = ERROR_MORE_DATA;
1323         }
1324         else if (title)
1325         {
1326             if (feature->Title) lstrcpyW( title, feature->Title );
1327             else *title = 0;
1328             *title_len = len;
1329         }
1330     }
1331     if (help_len)
1332     {
1333         if (feature->Description) len = lstrlenW( feature->Description );
1334         else len = 0;
1335         if (*help_len <= len)
1336         {
1337             *help_len = len;
1338             if (help) r = ERROR_MORE_DATA;
1339         }
1340         else if (help)
1341         {
1342             if (feature->Description) lstrcpyW( help, feature->Description );
1343             else *help = 0;
1344             *help_len = len;
1345         }
1346     }
1347     return r;
1348 }
1349 
1350 /***********************************************************************
1351 * MsiGetFeatureInfoW   (MSI.@)
1352 */
MsiGetFeatureInfoW(MSIHANDLE handle,const WCHAR * feature,DWORD * attrs,WCHAR * title,DWORD * title_len,WCHAR * help,DWORD * help_len)1353 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, const WCHAR *feature, DWORD *attrs,
1354                                 WCHAR *title, DWORD *title_len, WCHAR *help, DWORD *help_len )
1355 {
1356     UINT r;
1357     MSIPACKAGE *package;
1358 
1359     TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1360            title_len, help, help_len );
1361 
1362     if (!feature) return ERROR_INVALID_PARAMETER;
1363 
1364     if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1365         return ERROR_INVALID_HANDLE;
1366 
1367     /* features may not have been loaded yet */
1368     msi_load_all_components( package );
1369     msi_load_all_features( package );
1370 
1371     r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1372     msiobj_release( &package->hdr );
1373     return r;
1374 }
1375 
1376 /***********************************************************************
1377  * MsiSetComponentStateA (MSI.@)
1378  */
MsiSetComponentStateA(MSIHANDLE hInstall,LPCSTR szComponent,INSTALLSTATE iState)1379 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1380                                   INSTALLSTATE iState)
1381 {
1382     UINT rc;
1383     LPWSTR szwComponent = strdupAtoW(szComponent);
1384 
1385     rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1386 
1387     free(szwComponent);
1388 
1389     return rc;
1390 }
1391 
1392 /***********************************************************************
1393  * MsiGetComponentStateA (MSI.@)
1394  */
MsiGetComponentStateA(MSIHANDLE hInstall,LPCSTR szComponent,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1395 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1396                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1397 {
1398     LPWSTR szwComponent= NULL;
1399     UINT rc;
1400 
1401     szwComponent= strdupAtoW(szComponent);
1402 
1403     rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1404 
1405     free(szwComponent);
1406 
1407     return rc;
1408 }
1409 
MSI_SetComponentStateW(MSIPACKAGE * package,LPCWSTR szComponent,INSTALLSTATE iState)1410 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1411                                    INSTALLSTATE iState)
1412 {
1413     MSICOMPONENT *comp;
1414 
1415     TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1416 
1417     comp = msi_get_loaded_component(package, szComponent);
1418     if (!comp)
1419         return ERROR_UNKNOWN_COMPONENT;
1420 
1421     if (comp->Enabled)
1422         comp->Action = iState;
1423 
1424     return ERROR_SUCCESS;
1425 }
1426 
MSI_GetComponentStateW(MSIPACKAGE * package,LPCWSTR szComponent,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1427 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1428                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1429 {
1430     MSICOMPONENT *comp;
1431 
1432     TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1433            piInstalled, piAction);
1434 
1435     comp = msi_get_loaded_component(package,szComponent);
1436     if (!comp)
1437         return ERROR_UNKNOWN_COMPONENT;
1438 
1439     if (piInstalled)
1440     {
1441         if (comp->Enabled)
1442             *piInstalled = comp->Installed;
1443         else
1444             *piInstalled = INSTALLSTATE_UNKNOWN;
1445     }
1446 
1447     if (piAction)
1448     {
1449         if (comp->Enabled)
1450             *piAction = comp->Action;
1451         else
1452             *piAction = INSTALLSTATE_UNKNOWN;
1453     }
1454 
1455     TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1456     return ERROR_SUCCESS;
1457 }
1458 
1459 /***********************************************************************
1460  * MsiSetComponentStateW (MSI.@)
1461  */
MsiSetComponentStateW(MSIHANDLE hInstall,LPCWSTR szComponent,INSTALLSTATE iState)1462 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1463                                   INSTALLSTATE iState)
1464 {
1465     MSIPACKAGE* package;
1466     UINT ret;
1467 
1468     if (!szComponent)
1469         return ERROR_UNKNOWN_COMPONENT;
1470 
1471     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1472     if (!package)
1473     {
1474         MSIHANDLE remote;
1475 
1476         if (!(remote = msi_get_remote(hInstall)))
1477             return ERROR_INVALID_HANDLE;
1478 
1479         __TRY
1480         {
1481             ret = remote_SetComponentState(remote, szComponent, iState);
1482         }
1483         __EXCEPT(rpc_filter)
1484         {
1485             ret = GetExceptionCode();
1486         }
1487         __ENDTRY
1488 
1489         return ret;
1490     }
1491 
1492     ret = MSI_SetComponentStateW(package, szComponent, iState);
1493     msiobj_release(&package->hdr);
1494     return ret;
1495 }
1496 
1497 /***********************************************************************
1498  * MsiGetComponentStateW (MSI.@)
1499  */
MsiGetComponentStateW(MSIHANDLE hInstall,const WCHAR * szComponent,INSTALLSTATE * piInstalled,INSTALLSTATE * piAction)1500 UINT WINAPI MsiGetComponentStateW( MSIHANDLE hInstall, const WCHAR *szComponent, INSTALLSTATE *piInstalled,
1501                                    INSTALLSTATE *piAction )
1502 {
1503     MSIPACKAGE* package;
1504     UINT ret;
1505 
1506     TRACE( "%lu, %s, %p, %p\n", hInstall, debugstr_w(szComponent), piInstalled, piAction );
1507 
1508     if (!szComponent)
1509         return ERROR_UNKNOWN_COMPONENT;
1510 
1511     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1512     if (!package)
1513     {
1514         MSIHANDLE remote;
1515 
1516         if (!(remote = msi_get_remote(hInstall)))
1517             return ERROR_INVALID_HANDLE;
1518 
1519         __TRY
1520         {
1521             ret = remote_GetComponentState(remote, szComponent, piInstalled, piAction);
1522         }
1523         __EXCEPT(rpc_filter)
1524         {
1525             ret = GetExceptionCode();
1526         }
1527         __ENDTRY
1528 
1529         return ret;
1530     }
1531 
1532     ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1533     msiobj_release( &package->hdr );
1534     return ret;
1535 }
1536 
1537 /***********************************************************************
1538  * MsiGetLanguage (MSI.@)
1539  */
MsiGetLanguage(MSIHANDLE hInstall)1540 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1541 {
1542     MSIPACKAGE* package;
1543     LANGID langid;
1544 
1545     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1546     if (!package)
1547     {
1548         MSIHANDLE remote;
1549 
1550         if (!(remote = msi_get_remote(hInstall)))
1551             return ERROR_INVALID_HANDLE;
1552 
1553         __TRY
1554         {
1555             langid = remote_GetLanguage(remote);
1556         }
1557         __EXCEPT(rpc_filter)
1558         {
1559             langid = 0;
1560         }
1561         __ENDTRY
1562 
1563         return langid;
1564     }
1565 
1566     langid = msi_get_property_int( package->db, L"ProductLanguage", 0 );
1567     msiobj_release( &package->hdr );
1568     return langid;
1569 }
1570 
MSI_SetInstallLevel(MSIPACKAGE * package,int iInstallLevel)1571 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1572 {
1573     WCHAR level[6];
1574     int len;
1575     UINT r;
1576 
1577     TRACE("%p %i\n", package, iInstallLevel);
1578 
1579     if (iInstallLevel > 32767)
1580         return ERROR_INVALID_PARAMETER;
1581 
1582     if (iInstallLevel < 1)
1583         return MSI_SetFeatureStates( package );
1584 
1585     len = swprintf( level, ARRAY_SIZE(level), L"%d", iInstallLevel );
1586     r = msi_set_property( package->db, L"INSTALLLEVEL", level, len );
1587     if ( r == ERROR_SUCCESS )
1588         r = MSI_SetFeatureStates( package );
1589 
1590     return r;
1591 }
1592 
1593 /***********************************************************************
1594  * MsiSetInstallLevel (MSI.@)
1595  */
MsiSetInstallLevel(MSIHANDLE hInstall,int iInstallLevel)1596 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1597 {
1598     MSIPACKAGE* package;
1599     UINT r;
1600 
1601     TRACE( "%lu %d\n", hInstall, iInstallLevel );
1602 
1603     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1604     if (!package)
1605     {
1606         MSIHANDLE remote;
1607 
1608         if (!(remote = msi_get_remote(hInstall)))
1609             return ERROR_INVALID_HANDLE;
1610 
1611         __TRY
1612         {
1613             r = remote_SetInstallLevel(remote, iInstallLevel);
1614         }
1615         __EXCEPT(rpc_filter)
1616         {
1617             r = GetExceptionCode();
1618         }
1619         __ENDTRY
1620 
1621         return r;
1622     }
1623 
1624     r = MSI_SetInstallLevel( package, iInstallLevel );
1625 
1626     msiobj_release( &package->hdr );
1627 
1628     return r;
1629 }
1630 
1631 /***********************************************************************
1632  * MsiGetFeatureValidStatesW (MSI.@)
1633  */
MsiGetFeatureValidStatesW(MSIHANDLE hInstall,const WCHAR * szFeature,DWORD * pInstallState)1634 UINT WINAPI MsiGetFeatureValidStatesW( MSIHANDLE hInstall, const WCHAR *szFeature, DWORD *pInstallState )
1635 {
1636     if (pInstallState) *pInstallState = 1 << INSTALLSTATE_LOCAL;
1637     FIXME( "%lu, %s, %p stub returning %lu\n", hInstall, debugstr_w(szFeature), pInstallState,
1638            pInstallState ? *pInstallState : 0 );
1639     return ERROR_SUCCESS;
1640 }
1641 
1642 /***********************************************************************
1643  * MsiGetFeatureValidStatesA (MSI.@)
1644  */
MsiGetFeatureValidStatesA(MSIHANDLE hInstall,const char * szFeature,DWORD * pInstallState)1645 UINT WINAPI MsiGetFeatureValidStatesA( MSIHANDLE hInstall, const char *szFeature, DWORD *pInstallState )
1646 {
1647     UINT ret;
1648     WCHAR *szwFeature = strdupAtoW(szFeature);
1649     ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1650     free(szwFeature);
1651     return ret;
1652 }
1653