mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / msi / install.c
blob88b3ff518e2c740e2c0f002f999e7fa7ac6128d7
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/heap.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
43 /***********************************************************************
44 * MsiDoActionA (MSI.@)
46 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
48 LPWSTR szwAction;
49 UINT ret;
51 TRACE("%s\n", debugstr_a(szAction));
53 szwAction = strdupAtoW(szAction);
54 if (szAction && !szwAction)
55 return ERROR_FUNCTION_FAILED;
57 ret = MsiDoActionW( hInstall, szwAction );
58 msi_free( szwAction );
59 return ret;
62 /***********************************************************************
63 * MsiDoActionW (MSI.@)
65 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
67 MSIPACKAGE *package;
68 UINT ret;
70 TRACE("%s\n",debugstr_w(szAction));
72 if (!szAction)
73 return ERROR_INVALID_PARAMETER;
75 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
76 if (!package)
78 MSIHANDLE remote;
80 if (!(remote = msi_get_remote(hInstall)))
81 return ERROR_INVALID_HANDLE;
83 return remote_DoAction(remote, szAction);
86 ret = ACTION_PerformAction( package, szAction, SCRIPT_NONE );
87 msiobj_release( &package->hdr );
89 return ret;
92 /***********************************************************************
93 * MsiSequenceA (MSI.@)
95 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
97 LPWSTR szwTable;
98 UINT ret;
100 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
102 szwTable = strdupAtoW(szTable);
103 if (szTable && !szwTable)
104 return ERROR_FUNCTION_FAILED;
106 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
107 msi_free( szwTable );
108 return ret;
111 /***********************************************************************
112 * MsiSequenceW (MSI.@)
114 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
116 MSIPACKAGE *package;
117 UINT ret;
119 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
121 if (!szTable)
122 return ERROR_INVALID_PARAMETER;
124 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
125 if (!package)
127 MSIHANDLE remote;
129 if (!(remote = msi_get_remote(hInstall)))
130 return ERROR_INVALID_HANDLE;
132 return remote_Sequence(remote, szTable, iSequenceMode);
134 ret = MSI_Sequence( package, szTable );
135 msiobj_release( &package->hdr );
136 return ret;
139 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
141 UINT r = ERROR_SUCCESS;
143 if (awbuf->str.w && !sz)
144 return ERROR_INVALID_PARAMETER;
145 if (!sz)
146 return ERROR_SUCCESS;
148 if (len < 0) len = strlenW( str );
150 if (awbuf->unicode && awbuf->str.w)
152 memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
153 if (*sz && len >= *sz)
154 awbuf->str.w[*sz - 1] = 0;
156 else
158 int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
159 if (lenA) lenA--;
160 WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
161 if (awbuf->str.a && *sz && lenA >= *sz)
162 awbuf->str.a[*sz - 1] = 0;
163 len = lenA;
165 if (awbuf->str.w && len >= *sz)
166 r = ERROR_MORE_DATA;
167 *sz = len;
168 return r;
171 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
173 MSIFOLDER *folder = msi_get_loaded_folder( package, name );
175 if (!folder) return NULL;
176 if (!folder->ResolvedTarget)
178 MSIFOLDER *parent = folder;
179 while (parent->Parent && strcmpW( parent->Parent, parent->Directory ))
181 parent = msi_get_loaded_folder( package, parent->Parent );
183 msi_resolve_target_folder( package, parent->Directory, TRUE );
185 return folder->ResolvedTarget;
188 /***********************************************************************
189 * MsiGetTargetPath (internal)
191 static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
192 awstring *szPathBuf, LPDWORD pcchPathBuf )
194 MSIPACKAGE *package;
195 const WCHAR *path;
196 UINT r = ERROR_FUNCTION_FAILED;
198 if (!szFolder)
199 return ERROR_INVALID_PARAMETER;
201 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
202 if (!package)
204 LPWSTR value = NULL;
205 MSIHANDLE remote;
207 if (!(remote = msi_get_remote(hInstall)))
208 return ERROR_INVALID_HANDLE;
210 r = remote_GetTargetPath(remote, szFolder, &value);
211 if (r != ERROR_SUCCESS)
212 return r;
214 r = msi_strcpy_to_awstring(value, -1, szPathBuf, pcchPathBuf);
216 midl_user_free(value);
217 return r;
220 path = msi_get_target_folder( package, szFolder );
221 msiobj_release( &package->hdr );
223 if (!path)
224 return ERROR_DIRECTORY;
226 return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
229 /***********************************************************************
230 * MsiGetTargetPathA (MSI.@)
232 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
233 LPSTR szPathBuf, LPDWORD pcchPathBuf )
235 LPWSTR szwFolder;
236 awstring path;
237 UINT r;
239 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
241 szwFolder = strdupAtoW(szFolder);
242 if (szFolder && !szwFolder)
243 return ERROR_FUNCTION_FAILED;
245 path.unicode = FALSE;
246 path.str.a = szPathBuf;
248 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
250 msi_free( szwFolder );
252 return r;
255 /***********************************************************************
256 * MsiGetTargetPathW (MSI.@)
258 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
259 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
261 awstring path;
263 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
265 path.unicode = TRUE;
266 path.str.w = szPathBuf;
268 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
271 static WCHAR *get_source_root( MSIPACKAGE *package )
273 msi_set_sourcedir_props( package, FALSE );
274 return msi_dup_property( package->db, szSourceDir );
277 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
279 MSIFOLDER *f;
280 LPWSTR p, path = NULL, parent;
282 TRACE("working to resolve %s\n", debugstr_w(name));
284 if (!strcmpW( name, szSourceDir )) name = szTargetDir;
285 if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
287 /* special resolving for root dir */
288 if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
290 f->ResolvedSource = get_source_root( package );
292 if (folder) *folder = f;
293 if (f->ResolvedSource)
295 path = strdupW( f->ResolvedSource );
296 TRACE(" already resolved to %s\n", debugstr_w(path));
297 return path;
299 if (!f->Parent) return path;
300 parent = f->Parent;
301 TRACE(" ! parent is %s\n", debugstr_w(parent));
303 p = msi_resolve_source_folder( package, parent, NULL );
305 if (package->WordCount & msidbSumInfoSourceTypeCompressed)
306 path = get_source_root( package );
307 else if (package->WordCount & msidbSumInfoSourceTypeSFN)
308 path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
309 else
310 path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
312 TRACE("-> %s\n", debugstr_w(path));
313 f->ResolvedSource = strdupW( path );
314 msi_free( p );
316 return path;
319 /***********************************************************************
320 * MSI_GetSourcePath (internal)
322 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
323 awstring *szPathBuf, LPDWORD pcchPathBuf )
325 MSIPACKAGE *package;
326 LPWSTR path;
327 UINT r = ERROR_FUNCTION_FAILED;
329 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
331 if (!szFolder)
332 return ERROR_INVALID_PARAMETER;
334 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
335 if (!package)
337 LPWSTR value = NULL;
338 MSIHANDLE remote;
340 if (!(remote = msi_get_remote(hInstall)))
341 return ERROR_INVALID_HANDLE;
343 r = remote_GetSourcePath(remote, szFolder, &value);
344 if (r != ERROR_SUCCESS)
345 return r;
347 r = msi_strcpy_to_awstring(value, -1, szPathBuf, pcchPathBuf);
349 midl_user_free(value);
350 return r;
353 if (szPathBuf->str.w && !pcchPathBuf )
355 msiobj_release( &package->hdr );
356 return ERROR_INVALID_PARAMETER;
359 path = msi_resolve_source_folder( package, szFolder, NULL );
360 msiobj_release( &package->hdr );
362 TRACE("path = %s\n", debugstr_w(path));
363 if (!path)
364 return ERROR_DIRECTORY;
366 r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
367 msi_free( path );
368 return r;
371 /***********************************************************************
372 * MsiGetSourcePathA (MSI.@)
374 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
375 LPSTR szPathBuf, LPDWORD pcchPathBuf )
377 LPWSTR folder;
378 awstring str;
379 UINT r;
381 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
383 str.unicode = FALSE;
384 str.str.a = szPathBuf;
386 folder = strdupAtoW( szFolder );
387 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
388 msi_free( folder );
390 return r;
393 /***********************************************************************
394 * MsiGetSourcePathW (MSI.@)
396 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
397 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
399 awstring str;
401 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
403 str.unicode = TRUE;
404 str.str.w = szPathBuf;
406 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
409 /***********************************************************************
410 * MsiSetTargetPathA (MSI.@)
412 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
413 LPCSTR szFolderPath )
415 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
416 UINT rc = ERROR_OUTOFMEMORY;
418 if ( !szFolder || !szFolderPath )
419 return ERROR_INVALID_PARAMETER;
421 szwFolder = strdupAtoW(szFolder);
422 szwFolderPath = strdupAtoW(szFolderPath);
423 if (!szwFolder || !szwFolderPath)
424 goto end;
426 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
428 end:
429 msi_free(szwFolder);
430 msi_free(szwFolderPath);
432 return rc;
435 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
437 FolderList *fl;
438 MSIFOLDER *child;
439 WCHAR *target_path;
441 if (!(target_path = msi_normalize_path( path ))) return;
442 if (strcmpW( target_path, folder->ResolvedTarget ))
444 msi_free( folder->ResolvedTarget );
445 folder->ResolvedTarget = target_path;
446 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
448 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
450 child = fl->folder;
451 msi_resolve_target_folder( package, child->Directory, FALSE );
454 else msi_free( target_path );
457 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
459 DWORD attrib;
460 MSIFOLDER *folder;
461 MSIFILE *file;
463 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
465 attrib = GetFileAttributesW(szFolderPath);
466 /* native MSI tests writeability by making temporary files at each drive */
467 if (attrib != INVALID_FILE_ATTRIBUTES &&
468 (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
470 return ERROR_FUNCTION_FAILED;
472 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
474 set_target_path( package, folder, szFolderPath );
476 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
478 const WCHAR *dir;
479 MSICOMPONENT *comp = file->Component;
481 if (!comp->Enabled || msi_is_global_assembly( comp )) continue;
483 dir = msi_get_target_folder( package, comp->Directory );
484 msi_free( file->TargetPath );
485 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
487 return ERROR_SUCCESS;
490 /***********************************************************************
491 * MsiSetTargetPathW (MSI.@)
493 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
494 LPCWSTR szFolderPath)
496 MSIPACKAGE *package;
497 UINT ret;
499 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
501 if ( !szFolder || !szFolderPath )
502 return ERROR_INVALID_PARAMETER;
504 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
505 if (!package)
507 MSIHANDLE remote;
509 if (!(remote = msi_get_remote(hInstall)))
510 return ERROR_INVALID_HANDLE;
512 return remote_SetTargetPath(remote, szFolder, szFolderPath);
515 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
516 msiobj_release( &package->hdr );
517 return ret;
520 /***********************************************************************
521 * MsiGetMode (MSI.@)
523 * Returns an internal installer state (if it is running in a mode iRunMode)
525 * PARAMS
526 * hInstall [I] Handle to the installation
527 * hRunMode [I] Checking run mode
528 * MSIRUNMODE_ADMIN Administrative mode
529 * MSIRUNMODE_ADVERTISE Advertisement mode
530 * MSIRUNMODE_MAINTENANCE Maintenance mode
531 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
532 * MSIRUNMODE_LOGENABLED Log file is writing
533 * MSIRUNMODE_OPERATIONS Operations in progress??
534 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
535 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
536 * MSIRUNMODE_CABINET Files from cabinet are installed
537 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
538 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
539 * MSIRUNMODE_RESERVED11 Reserved
540 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
541 * MSIRUNMODE_ZAWENABLED Demand installation is supported
542 * MSIRUNMODE_RESERVED14 Reserved
543 * MSIRUNMODE_RESERVED15 Reserved
544 * MSIRUNMODE_SCHEDULED called from install script
545 * MSIRUNMODE_ROLLBACK called from rollback script
546 * MSIRUNMODE_COMMIT called from commit script
548 * RETURNS
549 * In the state: TRUE
550 * Not in the state: FALSE
553 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
555 MSIPACKAGE *package;
556 BOOL r = FALSE;
558 TRACE("%d %d\n", hInstall, iRunMode);
560 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
561 if (!package)
563 MSIHANDLE remote;
564 BOOL ret;
565 HRESULT hr;
567 if (!(remote = msi_get_remote(hInstall)))
568 return FALSE;
570 hr = remote_GetMode(remote, iRunMode, &ret);
572 if (hr == S_OK)
573 return ret;
575 return FALSE;
578 switch (iRunMode)
580 case MSIRUNMODE_ADMIN:
581 FIXME("no support for administrative installs\n");
582 break;
584 case MSIRUNMODE_ADVERTISE:
585 FIXME("no support for advertised installs\n");
586 break;
588 case MSIRUNMODE_WINDOWS9X:
589 if (GetVersion() & 0x80000000)
590 r = TRUE;
591 break;
593 case MSIRUNMODE_OPERATIONS:
594 case MSIRUNMODE_RESERVED11:
595 case MSIRUNMODE_RESERVED14:
596 case MSIRUNMODE_RESERVED15:
597 break;
599 case MSIRUNMODE_SCHEDULED:
600 r = package->scheduled_action_running;
601 break;
603 case MSIRUNMODE_ROLLBACK:
604 r = package->rollback_action_running;
605 break;
607 case MSIRUNMODE_COMMIT:
608 r = package->commit_action_running;
609 break;
611 case MSIRUNMODE_MAINTENANCE:
612 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
613 break;
615 case MSIRUNMODE_ROLLBACKENABLED:
616 r = msi_get_property_int( package->db, szRollbackDisabled, 0 ) == 0;
617 break;
619 case MSIRUNMODE_REBOOTATEND:
620 r = package->need_reboot_at_end;
621 break;
623 case MSIRUNMODE_REBOOTNOW:
624 r = package->need_reboot_now;
625 break;
627 case MSIRUNMODE_LOGENABLED:
628 r = (package->log_file != INVALID_HANDLE_VALUE);
629 break;
631 default:
632 FIXME("unimplemented run mode: %d\n", iRunMode);
633 r = TRUE;
636 msiobj_release( &package->hdr );
637 return r;
640 /***********************************************************************
641 * MsiSetMode (MSI.@)
643 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
645 MSIPACKAGE *package;
646 UINT r;
648 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
650 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
651 if (!package)
653 MSIHANDLE remote;
654 HRESULT hr;
656 if (!(remote = msi_get_remote(hInstall)))
657 return FALSE;
659 hr = remote_SetMode(remote, iRunMode, fState);
661 if (FAILED(hr))
663 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
664 return HRESULT_CODE(hr);
666 return ERROR_FUNCTION_FAILED;
669 return ERROR_SUCCESS;
672 switch (iRunMode)
674 case MSIRUNMODE_REBOOTATEND:
675 package->need_reboot_at_end = (fState != 0);
676 r = ERROR_SUCCESS;
677 break;
679 case MSIRUNMODE_REBOOTNOW:
680 package->need_reboot_now = (fState != 0);
681 r = ERROR_SUCCESS;
682 break;
684 default:
685 r = ERROR_ACCESS_DENIED;
688 msiobj_release( &package->hdr );
689 return r;
692 /***********************************************************************
693 * MsiSetFeatureStateA (MSI.@)
695 * According to the docs, when this is called it immediately recalculates
696 * all the component states as well
698 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
699 INSTALLSTATE iState)
701 LPWSTR szwFeature = NULL;
702 UINT rc;
704 szwFeature = strdupAtoW(szFeature);
706 if (!szwFeature)
707 return ERROR_FUNCTION_FAILED;
709 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
711 msi_free(szwFeature);
713 return rc;
716 /* update component state based on a feature change */
717 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
719 INSTALLSTATE newstate;
720 ComponentList *cl;
722 newstate = feature->ActionRequest;
723 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
725 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
727 MSICOMPONENT *component = cl->component;
729 if (!component->Enabled) continue;
731 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
732 newstate, debugstr_w(component->Component), component->Installed,
733 component->Action, component->ActionRequest);
735 if (newstate == INSTALLSTATE_LOCAL)
737 component->Action = INSTALLSTATE_LOCAL;
738 component->ActionRequest = INSTALLSTATE_LOCAL;
740 else
742 ComponentList *clist;
743 MSIFEATURE *f;
745 component->hasLocalFeature = FALSE;
747 component->Action = newstate;
748 component->ActionRequest = newstate;
749 /* if any other feature wants it local we need to set it local */
750 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
752 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
753 f->ActionRequest != INSTALLSTATE_SOURCE )
755 continue;
757 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
759 if (clist->component == component &&
760 (f->ActionRequest == INSTALLSTATE_LOCAL ||
761 f->ActionRequest == INSTALLSTATE_SOURCE))
763 TRACE("Saved by %s\n", debugstr_w(f->Feature));
764 component->hasLocalFeature = TRUE;
766 if (component->Attributes & msidbComponentAttributesOptional)
768 if (f->Attributes & msidbFeatureAttributesFavorSource)
770 component->Action = INSTALLSTATE_SOURCE;
771 component->ActionRequest = INSTALLSTATE_SOURCE;
773 else
775 component->Action = INSTALLSTATE_LOCAL;
776 component->ActionRequest = INSTALLSTATE_LOCAL;
779 else if (component->Attributes & msidbComponentAttributesSourceOnly)
781 component->Action = INSTALLSTATE_SOURCE;
782 component->ActionRequest = INSTALLSTATE_SOURCE;
784 else
786 component->Action = INSTALLSTATE_LOCAL;
787 component->ActionRequest = INSTALLSTATE_LOCAL;
793 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
794 newstate, debugstr_w(component->Component), component->Installed,
795 component->Action, component->ActionRequest);
799 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
801 UINT rc = ERROR_SUCCESS;
802 MSIFEATURE *feature, *child;
804 TRACE("%s %i\n", debugstr_w(szFeature), iState);
806 feature = msi_get_loaded_feature( package, szFeature );
807 if (!feature)
808 return ERROR_UNKNOWN_FEATURE;
810 if (iState == INSTALLSTATE_ADVERTISED &&
811 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
812 return ERROR_FUNCTION_FAILED;
814 feature->ActionRequest = iState;
816 ACTION_UpdateComponentStates( package, feature );
818 /* update all the features that are children of this feature */
819 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
821 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
822 MSI_SetFeatureStateW(package, child->Feature, iState);
825 return rc;
828 /***********************************************************************
829 * MsiSetFeatureStateW (MSI.@)
831 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
832 INSTALLSTATE iState)
834 MSIPACKAGE* package;
835 UINT rc = ERROR_SUCCESS;
837 TRACE("%s %i\n",debugstr_w(szFeature), iState);
839 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
840 if (!package)
842 MSIHANDLE remote;
843 HRESULT hr;
844 BSTR feature;
846 if (!(remote = msi_get_remote(hInstall)))
847 return ERROR_INVALID_HANDLE;
849 feature = SysAllocString(szFeature);
850 if (!feature)
851 return ERROR_OUTOFMEMORY;
853 hr = remote_SetFeatureState(remote, feature, iState);
855 SysFreeString(feature);
857 if (FAILED(hr))
859 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
860 return HRESULT_CODE(hr);
862 return ERROR_FUNCTION_FAILED;
865 return ERROR_SUCCESS;
868 rc = MSI_SetFeatureStateW(package,szFeature,iState);
870 msiobj_release( &package->hdr );
871 return rc;
874 /***********************************************************************
875 * MsiSetFeatureAttributesA (MSI.@)
877 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
879 UINT r;
880 WCHAR *featureW = NULL;
882 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
884 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
886 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
887 msi_free( featureW );
888 return r;
891 static DWORD unmap_feature_attributes( DWORD attrs )
893 DWORD ret = 0;
895 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
896 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
897 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
898 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
899 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
900 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
901 return ret;
904 /***********************************************************************
905 * MsiSetFeatureAttributesW (MSI.@)
907 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
909 MSIPACKAGE *package;
910 MSIFEATURE *feature;
911 WCHAR *costing;
913 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
915 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
917 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
918 return ERROR_INVALID_HANDLE;
920 costing = msi_dup_property( package->db, szCostingComplete );
921 if (!costing || !strcmpW( costing, szOne ))
923 msi_free( costing );
924 msiobj_release( &package->hdr );
925 return ERROR_FUNCTION_FAILED;
927 msi_free( costing );
928 if (!(feature = msi_get_loaded_feature( package, name )))
930 msiobj_release( &package->hdr );
931 return ERROR_UNKNOWN_FEATURE;
933 feature->Attributes = unmap_feature_attributes( attrs );
934 msiobj_release( &package->hdr );
935 return ERROR_SUCCESS;
938 /***********************************************************************
939 * MsiGetFeatureStateA (MSI.@)
941 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
942 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
944 LPWSTR szwFeature = NULL;
945 UINT rc;
947 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
949 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
950 msi_free( szwFeature);
951 return rc;
954 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
955 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
957 MSIFEATURE *feature;
959 feature = msi_get_loaded_feature(package,szFeature);
960 if (!feature)
961 return ERROR_UNKNOWN_FEATURE;
963 if (piInstalled)
964 *piInstalled = feature->Installed;
966 if (piAction)
967 *piAction = feature->ActionRequest;
969 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
971 return ERROR_SUCCESS;
974 /***********************************************************************
975 * MsiGetFeatureStateW (MSI.@)
977 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
978 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
980 MSIPACKAGE* package;
981 UINT ret;
983 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
985 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
986 if (!package)
988 MSIHANDLE remote;
989 HRESULT hr;
990 BSTR feature;
992 if (!(remote = msi_get_remote(hInstall)))
993 return ERROR_INVALID_HANDLE;
995 feature = SysAllocString(szFeature);
996 if (!feature)
997 return ERROR_OUTOFMEMORY;
999 hr = remote_GetFeatureState(remote, feature, piInstalled, piAction);
1001 SysFreeString(feature);
1003 if (FAILED(hr))
1005 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1006 return HRESULT_CODE(hr);
1008 return ERROR_FUNCTION_FAILED;
1011 return ERROR_SUCCESS;
1014 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1015 msiobj_release( &package->hdr );
1016 return ret;
1019 /***********************************************************************
1020 * MsiGetFeatureCostA (MSI.@)
1022 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1023 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1025 LPWSTR szwFeature = NULL;
1026 UINT rc;
1028 szwFeature = strdupAtoW(szFeature);
1030 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1032 msi_free(szwFeature);
1034 return rc;
1037 static INT feature_cost( MSIFEATURE *feature )
1039 INT cost = 0;
1040 ComponentList *cl;
1042 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
1044 cost += cl->component->Cost;
1046 return cost;
1049 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1050 INSTALLSTATE state, LPINT cost )
1052 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1054 *cost = 0;
1055 switch (tree)
1057 case MSICOSTTREE_CHILDREN:
1059 MSIFEATURE *child;
1061 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1063 if (child->ActionRequest == state)
1064 *cost += feature_cost( child );
1066 break;
1068 case MSICOSTTREE_PARENTS:
1070 const WCHAR *feature_parent = feature->Feature_Parent;
1071 for (;;)
1073 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1074 if (!parent)
1075 break;
1077 if (parent->ActionRequest == state)
1078 *cost += feature_cost( parent );
1080 feature_parent = parent->Feature_Parent;
1082 break;
1084 case MSICOSTTREE_SELFONLY:
1085 if (feature->ActionRequest == state)
1086 *cost = feature_cost( feature );
1087 break;
1089 default:
1090 WARN("unhandled cost tree %u\n", tree);
1091 break;
1094 *cost /= 512;
1095 return ERROR_SUCCESS;
1098 /***********************************************************************
1099 * MsiGetFeatureCostW (MSI.@)
1101 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1102 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1104 MSIPACKAGE *package;
1105 MSIFEATURE *feature;
1106 UINT ret;
1108 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1109 iCostTree, iState, piCost);
1111 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1112 if (!package)
1114 MSIHANDLE remote;
1115 HRESULT hr;
1116 BSTR feature;
1118 if (!(remote = msi_get_remote(hInstall)))
1119 return ERROR_INVALID_HANDLE;
1121 feature = SysAllocString(szFeature);
1122 if (!feature)
1123 return ERROR_OUTOFMEMORY;
1125 hr = remote_GetFeatureCost(remote, feature, iCostTree, iState, piCost);
1127 SysFreeString(feature);
1129 if (FAILED(hr))
1131 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1132 return HRESULT_CODE(hr);
1134 return ERROR_FUNCTION_FAILED;
1137 return ERROR_SUCCESS;
1140 feature = msi_get_loaded_feature(package, szFeature);
1142 if (feature)
1143 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1144 else
1145 ret = ERROR_UNKNOWN_FEATURE;
1147 msiobj_release( &package->hdr );
1148 return ret;
1151 /***********************************************************************
1152 * MsiGetFeatureInfoA (MSI.@)
1154 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1155 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1157 UINT r;
1158 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1160 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1161 title_len, help, help_len);
1163 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1165 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1167 msi_free( featureW );
1168 return ERROR_OUTOFMEMORY;
1170 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1172 msi_free( featureW );
1173 msi_free( titleW );
1174 return ERROR_OUTOFMEMORY;
1176 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1177 if (r == ERROR_SUCCESS)
1179 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1180 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1182 msi_free( titleW );
1183 msi_free( helpW );
1184 msi_free( featureW );
1185 return r;
1188 static DWORD map_feature_attributes( DWORD attrs )
1190 DWORD ret = 0;
1192 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1193 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1194 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1195 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1196 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1197 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1198 return ret;
1201 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1202 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1204 UINT r = ERROR_SUCCESS;
1205 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1206 int len;
1208 if (!feature) return ERROR_UNKNOWN_FEATURE;
1209 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1210 if (title_len)
1212 if (feature->Title) len = strlenW( feature->Title );
1213 else len = 0;
1214 if (*title_len <= len)
1216 *title_len = len;
1217 if (title) r = ERROR_MORE_DATA;
1219 else if (title)
1221 if (feature->Title) strcpyW( title, feature->Title );
1222 else *title = 0;
1223 *title_len = len;
1226 if (help_len)
1228 if (feature->Description) len = strlenW( feature->Description );
1229 else len = 0;
1230 if (*help_len <= len)
1232 *help_len = len;
1233 if (help) r = ERROR_MORE_DATA;
1235 else if (help)
1237 if (feature->Description) strcpyW( help, feature->Description );
1238 else *help = 0;
1239 *help_len = len;
1242 return r;
1245 /***********************************************************************
1246 * MsiGetFeatureInfoW (MSI.@)
1248 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1249 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1251 UINT r;
1252 MSIPACKAGE *package;
1254 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1255 title_len, help, help_len);
1257 if (!feature) return ERROR_INVALID_PARAMETER;
1259 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1260 return ERROR_INVALID_HANDLE;
1262 /* features may not have been loaded yet */
1263 msi_load_all_components( package );
1264 msi_load_all_features( package );
1266 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1267 msiobj_release( &package->hdr );
1268 return r;
1271 /***********************************************************************
1272 * MsiSetComponentStateA (MSI.@)
1274 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1275 INSTALLSTATE iState)
1277 UINT rc;
1278 LPWSTR szwComponent = strdupAtoW(szComponent);
1280 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1282 msi_free(szwComponent);
1284 return rc;
1287 /***********************************************************************
1288 * MsiGetComponentStateA (MSI.@)
1290 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1291 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1293 LPWSTR szwComponent= NULL;
1294 UINT rc;
1296 szwComponent= strdupAtoW(szComponent);
1298 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1300 msi_free( szwComponent);
1302 return rc;
1305 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1306 INSTALLSTATE iState)
1308 MSICOMPONENT *comp;
1310 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1312 comp = msi_get_loaded_component(package, szComponent);
1313 if (!comp)
1314 return ERROR_UNKNOWN_COMPONENT;
1316 if (comp->Enabled)
1317 comp->Action = iState;
1319 return ERROR_SUCCESS;
1322 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1323 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1325 MSICOMPONENT *comp;
1327 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1328 piInstalled, piAction);
1330 comp = msi_get_loaded_component(package,szComponent);
1331 if (!comp)
1332 return ERROR_UNKNOWN_COMPONENT;
1334 if (piInstalled)
1336 if (comp->Enabled)
1337 *piInstalled = comp->Installed;
1338 else
1339 *piInstalled = INSTALLSTATE_UNKNOWN;
1342 if (piAction)
1344 if (comp->Enabled)
1345 *piAction = comp->Action;
1346 else
1347 *piAction = INSTALLSTATE_UNKNOWN;
1350 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1351 return ERROR_SUCCESS;
1354 /***********************************************************************
1355 * MsiSetComponentStateW (MSI.@)
1357 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1358 INSTALLSTATE iState)
1360 MSIPACKAGE* package;
1361 UINT ret;
1363 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1364 if (!package)
1366 MSIHANDLE remote;
1367 HRESULT hr;
1368 BSTR component;
1370 if (!(remote = msi_get_remote(hInstall)))
1371 return ERROR_INVALID_HANDLE;
1373 component = SysAllocString(szComponent);
1374 if (!component)
1375 return ERROR_OUTOFMEMORY;
1377 hr = remote_SetComponentState(remote, component, iState);
1379 SysFreeString(component);
1381 if (FAILED(hr))
1383 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1384 return HRESULT_CODE(hr);
1386 return ERROR_FUNCTION_FAILED;
1389 return ERROR_SUCCESS;
1392 ret = MSI_SetComponentStateW(package, szComponent, iState);
1393 msiobj_release(&package->hdr);
1394 return ret;
1397 /***********************************************************************
1398 * MsiGetComponentStateW (MSI.@)
1400 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1401 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1403 MSIPACKAGE* package;
1404 UINT ret;
1406 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1407 piInstalled, piAction);
1409 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1410 if (!package)
1412 MSIHANDLE remote;
1413 HRESULT hr;
1414 BSTR component;
1416 if (!(remote = msi_get_remote(hInstall)))
1417 return ERROR_INVALID_HANDLE;
1419 component = SysAllocString(szComponent);
1420 if (!component)
1421 return ERROR_OUTOFMEMORY;
1423 hr = remote_GetComponentState(remote, component, piInstalled, piAction);
1425 SysFreeString(component);
1427 if (FAILED(hr))
1429 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1430 return HRESULT_CODE(hr);
1432 return ERROR_FUNCTION_FAILED;
1435 return ERROR_SUCCESS;
1438 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1439 msiobj_release( &package->hdr );
1440 return ret;
1443 /***********************************************************************
1444 * MsiGetLanguage (MSI.@)
1446 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1448 MSIPACKAGE* package;
1449 LANGID langid;
1451 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1452 if (!package)
1454 MSIHANDLE remote;
1455 HRESULT hr;
1456 LANGID lang;
1458 if (!(remote = msi_get_remote(hInstall)))
1459 return ERROR_INVALID_HANDLE;
1461 hr = remote_GetLanguage(remote, &lang);
1463 if (SUCCEEDED(hr))
1464 return lang;
1466 return 0;
1469 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1470 msiobj_release( &package->hdr );
1471 return langid;
1474 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1476 static const WCHAR fmt[] = { '%','d',0 };
1477 WCHAR level[6];
1478 int len;
1479 UINT r;
1481 TRACE("%p %i\n", package, iInstallLevel);
1483 if (iInstallLevel > 32767)
1484 return ERROR_INVALID_PARAMETER;
1486 if (iInstallLevel < 1)
1487 return MSI_SetFeatureStates( package );
1489 len = sprintfW( level, fmt, iInstallLevel );
1490 r = msi_set_property( package->db, szInstallLevel, level, len );
1491 if ( r == ERROR_SUCCESS )
1492 r = MSI_SetFeatureStates( package );
1494 return r;
1497 /***********************************************************************
1498 * MsiSetInstallLevel (MSI.@)
1500 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1502 MSIPACKAGE* package;
1503 UINT r;
1505 TRACE("%d %i\n", hInstall, iInstallLevel);
1507 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1508 if (!package)
1510 MSIHANDLE remote;
1511 HRESULT hr;
1513 if (!(remote = msi_get_remote(hInstall)))
1514 return ERROR_INVALID_HANDLE;
1516 hr = remote_SetInstallLevel(remote, iInstallLevel);
1518 if (FAILED(hr))
1520 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1521 return HRESULT_CODE(hr);
1523 return ERROR_FUNCTION_FAILED;
1526 return ERROR_SUCCESS;
1529 r = MSI_SetInstallLevel( package, iInstallLevel );
1531 msiobj_release( &package->hdr );
1533 return r;
1536 /***********************************************************************
1537 * MsiGetFeatureValidStatesW (MSI.@)
1539 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1540 LPDWORD pInstallState)
1542 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1543 FIXME("%d %s %p stub returning %d\n",
1544 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1546 return ERROR_SUCCESS;
1549 /***********************************************************************
1550 * MsiGetFeatureValidStatesA (MSI.@)
1552 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1553 LPDWORD pInstallState)
1555 UINT ret;
1556 LPWSTR szwFeature = strdupAtoW(szFeature);
1558 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1560 msi_free(szwFeature);
1562 return ret;