include: Be consistent in naming regarding MSF's block.
[wine.git] / dlls / msi / install.c
blob609a3016eaa4c3d701dab8ec70cedee6d5de1ed2
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 Aric Stewart for CodeWeavers
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.
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.
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
21 /* Msi top level apis directly related to installs */
23 #define COBJMACROS
25 #include <stdarg.h>
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"
35 #include "msipriv.h"
36 #include "winemsi.h"
37 #include "wine/debug.h"
38 #include "wine/exception.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42 /***********************************************************************
43 * MsiDoActionA (MSI.@)
45 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
47 LPWSTR szwAction;
48 UINT ret;
50 TRACE("%s\n", debugstr_a(szAction));
52 szwAction = strdupAtoW(szAction);
53 if (szAction && !szwAction)
54 return ERROR_FUNCTION_FAILED;
56 ret = MsiDoActionW( hInstall, szwAction );
57 free( szwAction );
58 return ret;
61 /***********************************************************************
62 * MsiDoActionW (MSI.@)
64 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
66 MSIPACKAGE *package;
67 UINT ret;
69 TRACE("%s\n",debugstr_w(szAction));
71 if (!szAction)
72 return ERROR_INVALID_PARAMETER;
74 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
75 if (!package)
77 MSIHANDLE remote;
79 if (!(remote = msi_get_remote(hInstall)))
80 return ERROR_INVALID_HANDLE;
82 __TRY
84 ret = remote_DoAction(remote, szAction);
86 __EXCEPT(rpc_filter)
88 ret = GetExceptionCode();
90 __ENDTRY
92 return ret;
95 ret = ACTION_PerformAction(package, szAction);
96 msiobj_release( &package->hdr );
98 return ret;
101 /***********************************************************************
102 * MsiSequenceA (MSI.@)
104 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
106 LPWSTR szwTable;
107 UINT ret;
109 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
111 szwTable = strdupAtoW(szTable);
112 if (szTable && !szwTable)
113 return ERROR_FUNCTION_FAILED;
115 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
116 free( szwTable );
117 return ret;
120 /***********************************************************************
121 * MsiSequenceW (MSI.@)
123 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
125 MSIPACKAGE *package;
126 UINT ret;
128 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
130 if (!szTable)
131 return ERROR_INVALID_PARAMETER;
133 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
134 if (!package)
136 MSIHANDLE remote;
138 if (!(remote = msi_get_remote(hInstall)))
139 return ERROR_INVALID_HANDLE;
141 __TRY
143 ret = remote_Sequence(remote, szTable, iSequenceMode);
145 __EXCEPT(rpc_filter)
147 ret = GetExceptionCode();
149 __ENDTRY
151 return ret;
153 ret = MSI_Sequence( package, szTable );
154 msiobj_release( &package->hdr );
155 return ret;
158 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
160 UINT r = ERROR_SUCCESS;
162 if (awbuf->str.w && !sz)
163 return ERROR_INVALID_PARAMETER;
164 if (!sz)
165 return ERROR_SUCCESS;
167 if (len < 0) len = lstrlenW( str );
169 if (awbuf->unicode && awbuf->str.w)
171 memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
172 if (*sz && len >= *sz)
173 awbuf->str.w[*sz - 1] = 0;
175 else
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;
184 if (awbuf->str.w && len >= *sz)
185 r = ERROR_MORE_DATA;
186 *sz = len;
187 return r;
190 UINT msi_strncpyWtoA(const WCHAR *str, int lenW, char *buf, DWORD *sz, BOOL remote)
192 UINT r = ERROR_SUCCESS;
193 DWORD lenA;
195 if (!sz)
196 return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
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)
204 if (*sz) buf[*sz - 1] = 0;
205 r = ERROR_MORE_DATA;
207 if (remote && lenA >= *sz)
208 lenA *= 2;
209 *sz = lenA;
210 return r;
213 UINT msi_strncpyW(const WCHAR *str, int len, WCHAR *buf, DWORD *sz)
215 UINT r = ERROR_SUCCESS;
217 if (!sz)
218 return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
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)
225 if (*sz) buf[*sz - 1] = 0;
226 r = ERROR_MORE_DATA;
228 *sz = len;
229 return r;
232 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
234 MSIFOLDER *folder = msi_get_loaded_folder( package, name );
236 if (!folder) return NULL;
237 if (!folder->ResolvedTarget)
239 MSIFOLDER *parent = folder;
240 while (parent->Parent && wcscmp( parent->Parent, parent->Directory ))
242 parent = msi_get_loaded_folder( package, parent->Parent );
244 msi_resolve_target_folder( package, parent->Directory, TRUE );
246 return folder->ResolvedTarget;
249 /***********************************************************************
250 * MsiGetTargetPathA (MSI.@)
252 UINT WINAPI MsiGetTargetPathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
254 MSIPACKAGE *package;
255 const WCHAR *path;
256 WCHAR *folderW;
257 UINT r;
259 TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
261 if (!folder)
262 return ERROR_INVALID_PARAMETER;
264 if (!(folderW = strdupAtoW(folder)))
265 return ERROR_OUTOFMEMORY;
267 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
268 if (!package)
270 WCHAR *path = NULL;
271 MSIHANDLE remote;
273 if (!(remote = msi_get_remote(hinst)))
275 free(folderW);
276 return ERROR_INVALID_HANDLE;
279 __TRY
281 r = remote_GetTargetPath(remote, folderW, &path);
283 __EXCEPT(rpc_filter)
285 r = GetExceptionCode();
287 __ENDTRY
289 if (!r)
290 r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
292 midl_user_free(path);
293 free(folderW);
294 return r;
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;
303 free(folderW);
304 msiobj_release(&package->hdr);
305 return r;
308 /***********************************************************************
309 * MsiGetTargetPathW (MSI.@)
311 UINT WINAPI MsiGetTargetPathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
313 MSIPACKAGE *package;
314 const WCHAR *path;
315 UINT r;
317 TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
319 if (!folder)
320 return ERROR_INVALID_PARAMETER;
322 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
323 if (!package)
325 WCHAR *path = NULL;
326 MSIHANDLE remote;
328 if (!(remote = msi_get_remote(hinst)))
329 return ERROR_INVALID_HANDLE;
331 __TRY
333 r = remote_GetTargetPath(remote, folder, &path);
335 __EXCEPT(rpc_filter)
337 r = GetExceptionCode();
339 __ENDTRY
341 if (!r)
342 r = msi_strncpyW(path, -1, buf, sz);
344 midl_user_free(path);
345 return r;
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;
354 msiobj_release(&package->hdr);
355 return r;
358 static WCHAR *get_source_root( MSIPACKAGE *package )
360 msi_set_sourcedir_props( package, FALSE );
361 return msi_dup_property( package->db, L"SourceDir" );
364 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
366 MSIFOLDER *f;
367 LPWSTR p, path = NULL, parent;
369 TRACE("working to resolve %s\n", debugstr_w(name));
371 if (!wcscmp( name, L"SourceDir" )) name = L"TARGETDIR";
372 if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
374 /* special resolving for root dir */
375 if (!wcscmp( name, L"TARGETDIR" ) && !f->ResolvedSource)
377 f->ResolvedSource = get_source_root( package );
379 if (folder) *folder = f;
380 if (f->ResolvedSource)
382 path = wcsdup( f->ResolvedSource );
383 TRACE(" already resolved to %s\n", debugstr_w(path));
384 return path;
386 if (!f->Parent) return path;
387 parent = f->Parent;
388 TRACE(" ! parent is %s\n", debugstr_w(parent));
390 p = msi_resolve_source_folder( package, parent, NULL );
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 );
399 TRACE("-> %s\n", debugstr_w(path));
400 f->ResolvedSource = wcsdup( path );
401 free( p );
403 return path;
406 /***********************************************************************
407 * MsiGetSourcePathA (MSI.@)
409 UINT WINAPI MsiGetSourcePathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
411 MSIPACKAGE *package;
412 WCHAR *path, *folderW;
413 UINT r;
415 TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
417 if (!folder)
418 return ERROR_INVALID_PARAMETER;
420 if (!(folderW = strdupAtoW(folder)))
421 return ERROR_OUTOFMEMORY;
423 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
424 if (!package)
426 WCHAR *path = NULL;
427 MSIHANDLE remote;
429 if (!(remote = msi_get_remote(hinst)))
431 free(folderW);
432 return ERROR_INVALID_HANDLE;
435 __TRY
437 r = remote_GetSourcePath(remote, folderW, &path);
439 __EXCEPT(rpc_filter)
441 r = GetExceptionCode();
443 __ENDTRY
445 if (!r)
446 r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
448 midl_user_free(path);
449 free(folderW);
450 return r;
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;
459 free(path);
460 free(folderW);
461 msiobj_release(&package->hdr);
462 return r;
465 /***********************************************************************
466 * MsiGetSourcePathW (MSI.@)
468 UINT WINAPI MsiGetSourcePathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
470 MSIPACKAGE *package;
471 WCHAR *path;
472 UINT r;
474 TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
476 if (!folder)
477 return ERROR_INVALID_PARAMETER;
479 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
480 if (!package)
482 WCHAR *path = NULL;
483 MSIHANDLE remote;
485 if (!(remote = msi_get_remote(hinst)))
486 return ERROR_INVALID_HANDLE;
488 __TRY
490 r = remote_GetSourcePath(remote, folder, &path);
492 __EXCEPT(rpc_filter)
494 r = GetExceptionCode();
496 __ENDTRY
498 if (!r)
499 r = msi_strncpyW(path, -1, buf, sz);
501 midl_user_free(path);
502 return r;
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;
511 free(path);
512 msiobj_release(&package->hdr);
513 return r;
516 /***********************************************************************
517 * MsiSetTargetPathA (MSI.@)
519 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
520 LPCSTR szFolderPath )
522 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
523 UINT rc = ERROR_OUTOFMEMORY;
525 if ( !szFolder || !szFolderPath )
526 return ERROR_INVALID_PARAMETER;
528 szwFolder = strdupAtoW(szFolder);
529 szwFolderPath = strdupAtoW(szFolderPath);
530 if (!szwFolder || !szwFolderPath)
531 goto end;
533 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
535 end:
536 free(szwFolder);
537 free(szwFolderPath);
539 return rc;
542 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
544 FolderList *fl;
545 MSIFOLDER *child;
546 WCHAR *target_path;
548 if (!(target_path = msi_normalize_path( path ))) return;
549 if (wcscmp( target_path, folder->ResolvedTarget ))
551 free( folder->ResolvedTarget );
552 folder->ResolvedTarget = target_path;
553 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
555 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
557 child = fl->folder;
558 msi_resolve_target_folder( package, child->Directory, FALSE );
561 else free( target_path );
564 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
566 DWORD attrib;
567 MSIFOLDER *folder;
568 MSIFILE *file;
570 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
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))
577 return ERROR_FUNCTION_FAILED;
579 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
581 set_target_path( package, folder, szFolderPath );
583 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
585 const WCHAR *dir;
586 MSICOMPONENT *comp = file->Component;
588 if (!comp->Enabled || msi_is_global_assembly( comp )) continue;
590 dir = msi_get_target_folder( package, comp->Directory );
591 free( file->TargetPath );
592 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
594 return ERROR_SUCCESS;
597 /***********************************************************************
598 * MsiSetTargetPathW (MSI.@)
600 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
601 LPCWSTR szFolderPath)
603 MSIPACKAGE *package;
604 UINT ret;
606 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
608 if ( !szFolder || !szFolderPath )
609 return ERROR_INVALID_PARAMETER;
611 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
612 if (!package)
614 MSIHANDLE remote;
616 if (!(remote = msi_get_remote(hInstall)))
617 return ERROR_INVALID_HANDLE;
619 __TRY
621 ret = remote_SetTargetPath(remote, szFolder, szFolderPath);
623 __EXCEPT(rpc_filter)
625 ret = GetExceptionCode();
627 __ENDTRY
629 return ret;
632 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
633 msiobj_release( &package->hdr );
634 return ret;
637 /***********************************************************************
638 * MsiGetMode (MSI.@)
640 * Returns an internal installer state (if it is running in a mode iRunMode)
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
665 * RETURNS
666 * In the state: TRUE
667 * Not in the state: FALSE
670 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
672 MSIPACKAGE *package;
673 BOOL r = FALSE;
675 TRACE( "%lu, %d\n", hInstall, iRunMode );
677 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
678 if (!package)
680 MSIHANDLE remote;
682 if (!(remote = msi_get_remote(hInstall)))
683 return FALSE;
685 __TRY
687 r = remote_GetMode(remote, iRunMode);
689 __EXCEPT(rpc_filter)
691 r = FALSE;
693 __ENDTRY
695 return r;
698 switch (iRunMode)
700 case MSIRUNMODE_ADMIN:
701 FIXME("no support for administrative installs\n");
702 break;
704 case MSIRUNMODE_ADVERTISE:
705 FIXME("no support for advertised installs\n");
706 break;
708 case MSIRUNMODE_WINDOWS9X:
709 if (GetVersion() & 0x80000000)
710 r = TRUE;
711 break;
713 case MSIRUNMODE_OPERATIONS:
714 case MSIRUNMODE_RESERVED11:
715 case MSIRUNMODE_RESERVED14:
716 case MSIRUNMODE_RESERVED15:
717 break;
719 case MSIRUNMODE_SCHEDULED:
720 r = package->scheduled_action_running;
721 break;
723 case MSIRUNMODE_ROLLBACK:
724 r = package->rollback_action_running;
725 break;
727 case MSIRUNMODE_COMMIT:
728 r = package->commit_action_running;
729 break;
731 case MSIRUNMODE_MAINTENANCE:
732 r = msi_get_property_int( package->db, L"Installed", 0 ) != 0;
733 break;
735 case MSIRUNMODE_ROLLBACKENABLED:
736 r = msi_get_property_int( package->db, L"RollbackDisabled", 0 ) == 0;
737 break;
739 case MSIRUNMODE_REBOOTATEND:
740 r = package->need_reboot_at_end;
741 break;
743 case MSIRUNMODE_REBOOTNOW:
744 r = package->need_reboot_now;
745 break;
747 case MSIRUNMODE_LOGENABLED:
748 r = (package->log_file != INVALID_HANDLE_VALUE);
749 break;
751 default:
752 FIXME("unimplemented run mode: %d\n", iRunMode);
753 r = TRUE;
756 msiobj_release( &package->hdr );
757 return r;
760 /***********************************************************************
761 * MsiSetMode (MSI.@)
763 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
765 MSIPACKAGE *package;
766 UINT r;
768 TRACE( "%lu, %d, %d\n", hInstall, iRunMode, fState );
770 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
771 if (!package)
773 MSIHANDLE remote;
775 if (!(remote = msi_get_remote(hInstall)))
776 return FALSE;
778 __TRY
780 r = remote_SetMode(remote, iRunMode, fState);
782 __EXCEPT(rpc_filter)
784 r = GetExceptionCode();
786 __ENDTRY
788 return r;
791 switch (iRunMode)
793 case MSIRUNMODE_REBOOTATEND:
794 package->need_reboot_at_end = (fState != 0);
795 r = ERROR_SUCCESS;
796 break;
798 case MSIRUNMODE_REBOOTNOW:
799 package->need_reboot_now = (fState != 0);
800 r = ERROR_SUCCESS;
801 break;
803 default:
804 r = ERROR_ACCESS_DENIED;
807 msiobj_release( &package->hdr );
808 return r;
811 /***********************************************************************
812 * MsiSetFeatureStateA (MSI.@)
814 * According to the docs, when this is called it immediately recalculates
815 * all the component states as well
817 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
818 INSTALLSTATE iState)
820 LPWSTR szwFeature = NULL;
821 UINT rc;
823 szwFeature = strdupAtoW(szFeature);
825 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
827 free(szwFeature);
829 return rc;
832 /* update component state based on a feature change */
833 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
835 INSTALLSTATE newstate;
836 ComponentList *cl;
838 newstate = feature->ActionRequest;
839 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
841 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
843 MSICOMPONENT *component = cl->component;
845 if (!component->Enabled) continue;
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);
851 if (newstate == INSTALLSTATE_LOCAL)
853 component->Action = INSTALLSTATE_LOCAL;
854 component->ActionRequest = INSTALLSTATE_LOCAL;
856 else
858 ComponentList *clist;
859 MSIFEATURE *f;
861 component->hasLocalFeature = FALSE;
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)
868 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
869 f->ActionRequest != INSTALLSTATE_SOURCE )
871 continue;
873 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
875 if (clist->component == component &&
876 (f->ActionRequest == INSTALLSTATE_LOCAL ||
877 f->ActionRequest == INSTALLSTATE_SOURCE))
879 TRACE("Saved by %s\n", debugstr_w(f->Feature));
880 component->hasLocalFeature = TRUE;
882 if (component->Attributes & msidbComponentAttributesOptional)
884 if (f->Attributes & msidbFeatureAttributesFavorSource)
886 component->Action = INSTALLSTATE_SOURCE;
887 component->ActionRequest = INSTALLSTATE_SOURCE;
889 else
891 component->Action = INSTALLSTATE_LOCAL;
892 component->ActionRequest = INSTALLSTATE_LOCAL;
895 else if (component->Attributes & msidbComponentAttributesSourceOnly)
897 component->Action = INSTALLSTATE_SOURCE;
898 component->ActionRequest = INSTALLSTATE_SOURCE;
900 else
902 component->Action = INSTALLSTATE_LOCAL;
903 component->ActionRequest = INSTALLSTATE_LOCAL;
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);
915 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
917 UINT rc = ERROR_SUCCESS;
918 MSIFEATURE *feature, *child;
920 TRACE("%s %i\n", debugstr_w(szFeature), iState);
922 feature = msi_get_loaded_feature( package, szFeature );
923 if (!feature)
924 return ERROR_UNKNOWN_FEATURE;
926 if (iState == INSTALLSTATE_ADVERTISED &&
927 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
928 return ERROR_FUNCTION_FAILED;
930 feature->ActionRequest = iState;
932 ACTION_UpdateComponentStates( package, feature );
934 /* update all the features that are children of this feature */
935 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
937 if (child->Feature_Parent && !wcscmp( szFeature, child->Feature_Parent ))
938 MSI_SetFeatureStateW(package, child->Feature, iState);
941 return rc;
944 /***********************************************************************
945 * MsiSetFeatureStateW (MSI.@)
947 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
948 INSTALLSTATE iState)
950 MSIPACKAGE* package;
951 UINT rc = ERROR_SUCCESS;
953 TRACE("%s %i\n",debugstr_w(szFeature), iState);
955 if (!szFeature)
956 return ERROR_UNKNOWN_FEATURE;
958 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
959 if (!package)
961 MSIHANDLE remote;
963 if (!(remote = msi_get_remote(hInstall)))
964 return ERROR_INVALID_HANDLE;
966 __TRY
968 rc = remote_SetFeatureState(remote, szFeature, iState);
970 __EXCEPT(rpc_filter)
972 rc = GetExceptionCode();
974 __ENDTRY
976 return rc;
979 rc = MSI_SetFeatureStateW(package,szFeature,iState);
981 msiobj_release( &package->hdr );
982 return rc;
985 /***********************************************************************
986 * MsiSetFeatureAttributesA (MSI.@)
988 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
990 UINT r;
991 WCHAR *featureW = NULL;
993 TRACE( "%lu, %s, %#lx\n", handle, debugstr_a(feature), attrs );
995 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
997 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
998 free( featureW );
999 return r;
1002 static DWORD unmap_feature_attributes( DWORD attrs )
1004 DWORD ret = 0;
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;
1015 /***********************************************************************
1016 * MsiSetFeatureAttributesW (MSI.@)
1018 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
1020 MSIPACKAGE *package;
1021 MSIFEATURE *feature;
1022 WCHAR *costing;
1024 TRACE( "%lu, %s, %#lx\n", handle, debugstr_w(name), attrs );
1026 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
1028 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1029 return ERROR_INVALID_HANDLE;
1031 costing = msi_dup_property( package->db, L"CostingComplete" );
1032 if (!costing || !wcscmp( costing, L"1" ))
1034 free( costing );
1035 msiobj_release( &package->hdr );
1036 return ERROR_FUNCTION_FAILED;
1038 free( costing );
1039 if (!(feature = msi_get_loaded_feature( package, name )))
1041 msiobj_release( &package->hdr );
1042 return ERROR_UNKNOWN_FEATURE;
1044 feature->Attributes = unmap_feature_attributes( attrs );
1045 msiobj_release( &package->hdr );
1046 return ERROR_SUCCESS;
1049 /***********************************************************************
1050 * MsiGetFeatureStateA (MSI.@)
1052 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
1053 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1055 LPWSTR szwFeature = NULL;
1056 UINT rc;
1058 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
1060 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
1061 free(szwFeature);
1062 return rc;
1065 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
1066 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1068 MSIFEATURE *feature;
1070 feature = msi_get_loaded_feature(package,szFeature);
1071 if (!feature)
1072 return ERROR_UNKNOWN_FEATURE;
1074 if (piInstalled)
1075 *piInstalled = feature->Installed;
1077 if (piAction)
1078 *piAction = feature->ActionRequest;
1080 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
1082 return ERROR_SUCCESS;
1085 /***********************************************************************
1086 * MsiGetFeatureStateW (MSI.@)
1088 UINT WINAPI MsiGetFeatureStateW( MSIHANDLE hInstall, const WCHAR *szFeature, INSTALLSTATE *piInstalled,
1089 INSTALLSTATE *piAction )
1091 MSIPACKAGE* package;
1092 UINT ret;
1094 TRACE( "%lu, %s, %p, %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction );
1096 if (!szFeature)
1097 return ERROR_UNKNOWN_FEATURE;
1099 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1100 if (!package)
1102 MSIHANDLE remote;
1104 if (!(remote = msi_get_remote(hInstall)))
1105 return ERROR_INVALID_HANDLE;
1107 __TRY
1109 ret = remote_GetFeatureState(remote, szFeature, piInstalled, piAction);
1111 __EXCEPT(rpc_filter)
1113 ret = GetExceptionCode();
1115 __ENDTRY
1117 return ret;
1120 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1121 msiobj_release( &package->hdr );
1122 return ret;
1125 /***********************************************************************
1126 * MsiGetFeatureCostA (MSI.@)
1128 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1129 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1131 LPWSTR szwFeature = NULL;
1132 UINT rc;
1134 szwFeature = strdupAtoW(szFeature);
1136 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1138 free(szwFeature);
1140 return rc;
1143 static INT feature_cost( MSIFEATURE *feature )
1145 INT cost = 0;
1146 ComponentList *cl;
1148 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
1150 cost += cl->component->Cost;
1152 return cost;
1155 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1156 INSTALLSTATE state, LPINT cost )
1158 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1160 *cost = 0;
1161 switch (tree)
1163 case MSICOSTTREE_CHILDREN:
1165 MSIFEATURE *child;
1167 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1169 if (child->ActionRequest == state)
1170 *cost += feature_cost( child );
1172 break;
1174 case MSICOSTTREE_PARENTS:
1176 const WCHAR *feature_parent = feature->Feature_Parent;
1177 for (;;)
1179 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1180 if (!parent)
1181 break;
1183 if (parent->ActionRequest == state)
1184 *cost += feature_cost( parent );
1186 feature_parent = parent->Feature_Parent;
1188 break;
1190 case MSICOSTTREE_SELFONLY:
1191 if (feature->ActionRequest == state)
1192 *cost = feature_cost( feature );
1193 break;
1195 default:
1196 WARN("unhandled cost tree %u\n", tree);
1197 break;
1200 *cost /= 512;
1201 return ERROR_SUCCESS;
1204 /***********************************************************************
1205 * MsiGetFeatureCostW (MSI.@)
1207 UINT WINAPI MsiGetFeatureCostW( MSIHANDLE hInstall, const WCHAR *szFeature, MSICOSTTREE iCostTree,
1208 INSTALLSTATE iState, INT *piCost )
1210 MSIPACKAGE *package;
1211 MSIFEATURE *feature;
1212 UINT ret;
1214 TRACE( "%lu, %s, %d, %d, %p\n", hInstall, debugstr_w(szFeature), iCostTree, iState, piCost );
1216 if (!szFeature)
1217 return ERROR_INVALID_PARAMETER;
1219 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1220 if (!package)
1222 MSIHANDLE remote;
1224 if (!(remote = msi_get_remote(hInstall)))
1225 return ERROR_INVALID_HANDLE;
1227 __TRY
1229 ret = remote_GetFeatureCost(remote, szFeature, iCostTree, iState, piCost);
1231 __EXCEPT(rpc_filter)
1233 ret = GetExceptionCode();
1235 __ENDTRY
1237 return ret;
1240 if (!piCost)
1242 msiobj_release( &package->hdr );
1243 return ERROR_INVALID_PARAMETER;
1246 feature = msi_get_loaded_feature(package, szFeature);
1248 if (feature)
1249 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1250 else
1251 ret = ERROR_UNKNOWN_FEATURE;
1253 msiobj_release( &package->hdr );
1254 return ret;
1257 /***********************************************************************
1258 * MsiGetFeatureInfoA (MSI.@)
1260 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, const char *feature, DWORD *attrs,
1261 char *title, DWORD *title_len, char *help, DWORD *help_len )
1263 UINT r;
1264 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1266 TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1267 title_len, help, help_len );
1269 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1271 if (title && title_len && !(titleW = malloc( *title_len * sizeof(WCHAR) )))
1273 free( featureW );
1274 return ERROR_OUTOFMEMORY;
1276 if (help && help_len && !(helpW = malloc( *help_len * sizeof(WCHAR) )))
1278 free( featureW );
1279 free( titleW );
1280 return ERROR_OUTOFMEMORY;
1282 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1283 if (r == ERROR_SUCCESS)
1285 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1286 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1288 free( titleW );
1289 free( helpW );
1290 free( featureW );
1291 return r;
1294 static DWORD map_feature_attributes( DWORD attrs )
1296 DWORD ret = 0;
1298 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1299 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1300 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1301 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1302 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1303 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1304 return ret;
1307 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1308 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1310 UINT r = ERROR_SUCCESS;
1311 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1312 int len;
1314 if (!feature) return ERROR_UNKNOWN_FEATURE;
1315 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1316 if (title_len)
1318 if (feature->Title) len = lstrlenW( feature->Title );
1319 else len = 0;
1320 if (*title_len <= len)
1322 *title_len = len;
1323 if (title) r = ERROR_MORE_DATA;
1325 else if (title)
1327 if (feature->Title) lstrcpyW( title, feature->Title );
1328 else *title = 0;
1329 *title_len = len;
1332 if (help_len)
1334 if (feature->Description) len = lstrlenW( feature->Description );
1335 else len = 0;
1336 if (*help_len <= len)
1338 *help_len = len;
1339 if (help) r = ERROR_MORE_DATA;
1341 else if (help)
1343 if (feature->Description) lstrcpyW( help, feature->Description );
1344 else *help = 0;
1345 *help_len = len;
1348 return r;
1351 /***********************************************************************
1352 * MsiGetFeatureInfoW (MSI.@)
1354 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, const WCHAR *feature, DWORD *attrs,
1355 WCHAR *title, DWORD *title_len, WCHAR *help, DWORD *help_len )
1357 UINT r;
1358 MSIPACKAGE *package;
1360 TRACE( "%lu, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1361 title_len, help, help_len );
1363 if (!feature) return ERROR_INVALID_PARAMETER;
1365 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1366 return ERROR_INVALID_HANDLE;
1368 /* features may not have been loaded yet */
1369 msi_load_all_components( package );
1370 msi_load_all_features( package );
1372 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1373 msiobj_release( &package->hdr );
1374 return r;
1377 /***********************************************************************
1378 * MsiSetComponentStateA (MSI.@)
1380 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1381 INSTALLSTATE iState)
1383 UINT rc;
1384 LPWSTR szwComponent = strdupAtoW(szComponent);
1386 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1388 free(szwComponent);
1390 return rc;
1393 /***********************************************************************
1394 * MsiGetComponentStateA (MSI.@)
1396 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1397 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1399 LPWSTR szwComponent= NULL;
1400 UINT rc;
1402 szwComponent= strdupAtoW(szComponent);
1404 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1406 free(szwComponent);
1408 return rc;
1411 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1412 INSTALLSTATE iState)
1414 MSICOMPONENT *comp;
1416 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1418 comp = msi_get_loaded_component(package, szComponent);
1419 if (!comp)
1420 return ERROR_UNKNOWN_COMPONENT;
1422 if (comp->Enabled)
1423 comp->Action = iState;
1425 return ERROR_SUCCESS;
1428 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1429 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1431 MSICOMPONENT *comp;
1433 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1434 piInstalled, piAction);
1436 comp = msi_get_loaded_component(package,szComponent);
1437 if (!comp)
1438 return ERROR_UNKNOWN_COMPONENT;
1440 if (piInstalled)
1442 if (comp->Enabled)
1443 *piInstalled = comp->Installed;
1444 else
1445 *piInstalled = INSTALLSTATE_UNKNOWN;
1448 if (piAction)
1450 if (comp->Enabled)
1451 *piAction = comp->Action;
1452 else
1453 *piAction = INSTALLSTATE_UNKNOWN;
1456 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1457 return ERROR_SUCCESS;
1460 /***********************************************************************
1461 * MsiSetComponentStateW (MSI.@)
1463 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1464 INSTALLSTATE iState)
1466 MSIPACKAGE* package;
1467 UINT ret;
1469 if (!szComponent)
1470 return ERROR_UNKNOWN_COMPONENT;
1472 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1473 if (!package)
1475 MSIHANDLE remote;
1477 if (!(remote = msi_get_remote(hInstall)))
1478 return ERROR_INVALID_HANDLE;
1480 __TRY
1482 ret = remote_SetComponentState(remote, szComponent, iState);
1484 __EXCEPT(rpc_filter)
1486 ret = GetExceptionCode();
1488 __ENDTRY
1490 return ret;
1493 ret = MSI_SetComponentStateW(package, szComponent, iState);
1494 msiobj_release(&package->hdr);
1495 return ret;
1498 /***********************************************************************
1499 * MsiGetComponentStateW (MSI.@)
1501 UINT WINAPI MsiGetComponentStateW( MSIHANDLE hInstall, const WCHAR *szComponent, INSTALLSTATE *piInstalled,
1502 INSTALLSTATE *piAction )
1504 MSIPACKAGE* package;
1505 UINT ret;
1507 TRACE( "%lu, %s, %p, %p\n", hInstall, debugstr_w(szComponent), piInstalled, piAction );
1509 if (!szComponent)
1510 return ERROR_UNKNOWN_COMPONENT;
1512 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1513 if (!package)
1515 MSIHANDLE remote;
1517 if (!(remote = msi_get_remote(hInstall)))
1518 return ERROR_INVALID_HANDLE;
1520 __TRY
1522 ret = remote_GetComponentState(remote, szComponent, piInstalled, piAction);
1524 __EXCEPT(rpc_filter)
1526 ret = GetExceptionCode();
1528 __ENDTRY
1530 return ret;
1533 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1534 msiobj_release( &package->hdr );
1535 return ret;
1538 /***********************************************************************
1539 * MsiGetLanguage (MSI.@)
1541 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1543 MSIPACKAGE* package;
1544 LANGID langid;
1546 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1547 if (!package)
1549 MSIHANDLE remote;
1551 if (!(remote = msi_get_remote(hInstall)))
1552 return ERROR_INVALID_HANDLE;
1554 __TRY
1556 langid = remote_GetLanguage(remote);
1558 __EXCEPT(rpc_filter)
1560 langid = 0;
1562 __ENDTRY
1564 return langid;
1567 langid = msi_get_property_int( package->db, L"ProductLanguage", 0 );
1568 msiobj_release( &package->hdr );
1569 return langid;
1572 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1574 WCHAR level[6];
1575 int len;
1576 UINT r;
1578 TRACE("%p %i\n", package, iInstallLevel);
1580 if (iInstallLevel > 32767)
1581 return ERROR_INVALID_PARAMETER;
1583 if (iInstallLevel < 1)
1584 return MSI_SetFeatureStates( package );
1586 len = swprintf( level, ARRAY_SIZE(level), L"%d", iInstallLevel );
1587 r = msi_set_property( package->db, L"INSTALLLEVEL", level, len );
1588 if ( r == ERROR_SUCCESS )
1589 r = MSI_SetFeatureStates( package );
1591 return r;
1594 /***********************************************************************
1595 * MsiSetInstallLevel (MSI.@)
1597 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1599 MSIPACKAGE* package;
1600 UINT r;
1602 TRACE( "%lu %d\n", hInstall, iInstallLevel );
1604 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1605 if (!package)
1607 MSIHANDLE remote;
1609 if (!(remote = msi_get_remote(hInstall)))
1610 return ERROR_INVALID_HANDLE;
1612 __TRY
1614 r = remote_SetInstallLevel(remote, iInstallLevel);
1616 __EXCEPT(rpc_filter)
1618 r = GetExceptionCode();
1620 __ENDTRY
1622 return r;
1625 r = MSI_SetInstallLevel( package, iInstallLevel );
1627 msiobj_release( &package->hdr );
1629 return r;
1632 /***********************************************************************
1633 * MsiGetFeatureValidStatesW (MSI.@)
1635 UINT WINAPI MsiGetFeatureValidStatesW( MSIHANDLE hInstall, const WCHAR *szFeature, DWORD *pInstallState )
1637 if (pInstallState) *pInstallState = 1 << INSTALLSTATE_LOCAL;
1638 FIXME( "%lu, %s, %p stub returning %lu\n", hInstall, debugstr_w(szFeature), pInstallState,
1639 pInstallState ? *pInstallState : 0 );
1640 return ERROR_SUCCESS;
1643 /***********************************************************************
1644 * MsiGetFeatureValidStatesA (MSI.@)
1646 UINT WINAPI MsiGetFeatureValidStatesA( MSIHANDLE hInstall, const char *szFeature, DWORD *pInstallState )
1648 UINT ret;
1649 WCHAR *szwFeature = strdupAtoW(szFeature);
1650 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1651 free(szwFeature);
1652 return ret;