msi: Make MsiGetMode() RPC-compatible.
[wine.git] / dlls / msi / install.c
blob3ac151d36c8039b2c92305cb4fd0865351ebd69b
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;
565 if (!(remote = msi_get_remote(hInstall)))
566 return FALSE;
568 return remote_GetMode(remote, iRunMode);
571 switch (iRunMode)
573 case MSIRUNMODE_ADMIN:
574 FIXME("no support for administrative installs\n");
575 break;
577 case MSIRUNMODE_ADVERTISE:
578 FIXME("no support for advertised installs\n");
579 break;
581 case MSIRUNMODE_WINDOWS9X:
582 if (GetVersion() & 0x80000000)
583 r = TRUE;
584 break;
586 case MSIRUNMODE_OPERATIONS:
587 case MSIRUNMODE_RESERVED11:
588 case MSIRUNMODE_RESERVED14:
589 case MSIRUNMODE_RESERVED15:
590 break;
592 case MSIRUNMODE_SCHEDULED:
593 r = package->scheduled_action_running;
594 break;
596 case MSIRUNMODE_ROLLBACK:
597 r = package->rollback_action_running;
598 break;
600 case MSIRUNMODE_COMMIT:
601 r = package->commit_action_running;
602 break;
604 case MSIRUNMODE_MAINTENANCE:
605 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
606 break;
608 case MSIRUNMODE_ROLLBACKENABLED:
609 r = msi_get_property_int( package->db, szRollbackDisabled, 0 ) == 0;
610 break;
612 case MSIRUNMODE_REBOOTATEND:
613 r = package->need_reboot_at_end;
614 break;
616 case MSIRUNMODE_REBOOTNOW:
617 r = package->need_reboot_now;
618 break;
620 case MSIRUNMODE_LOGENABLED:
621 r = (package->log_file != INVALID_HANDLE_VALUE);
622 break;
624 default:
625 FIXME("unimplemented run mode: %d\n", iRunMode);
626 r = TRUE;
629 msiobj_release( &package->hdr );
630 return r;
633 /***********************************************************************
634 * MsiSetMode (MSI.@)
636 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
638 MSIPACKAGE *package;
639 UINT r;
641 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
643 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
644 if (!package)
646 MSIHANDLE remote;
647 HRESULT hr;
649 if (!(remote = msi_get_remote(hInstall)))
650 return FALSE;
652 hr = remote_SetMode(remote, iRunMode, fState);
654 if (FAILED(hr))
656 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
657 return HRESULT_CODE(hr);
659 return ERROR_FUNCTION_FAILED;
662 return ERROR_SUCCESS;
665 switch (iRunMode)
667 case MSIRUNMODE_REBOOTATEND:
668 package->need_reboot_at_end = (fState != 0);
669 r = ERROR_SUCCESS;
670 break;
672 case MSIRUNMODE_REBOOTNOW:
673 package->need_reboot_now = (fState != 0);
674 r = ERROR_SUCCESS;
675 break;
677 default:
678 r = ERROR_ACCESS_DENIED;
681 msiobj_release( &package->hdr );
682 return r;
685 /***********************************************************************
686 * MsiSetFeatureStateA (MSI.@)
688 * According to the docs, when this is called it immediately recalculates
689 * all the component states as well
691 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
692 INSTALLSTATE iState)
694 LPWSTR szwFeature = NULL;
695 UINT rc;
697 szwFeature = strdupAtoW(szFeature);
699 if (!szwFeature)
700 return ERROR_FUNCTION_FAILED;
702 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
704 msi_free(szwFeature);
706 return rc;
709 /* update component state based on a feature change */
710 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
712 INSTALLSTATE newstate;
713 ComponentList *cl;
715 newstate = feature->ActionRequest;
716 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
718 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
720 MSICOMPONENT *component = cl->component;
722 if (!component->Enabled) continue;
724 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
725 newstate, debugstr_w(component->Component), component->Installed,
726 component->Action, component->ActionRequest);
728 if (newstate == INSTALLSTATE_LOCAL)
730 component->Action = INSTALLSTATE_LOCAL;
731 component->ActionRequest = INSTALLSTATE_LOCAL;
733 else
735 ComponentList *clist;
736 MSIFEATURE *f;
738 component->hasLocalFeature = FALSE;
740 component->Action = newstate;
741 component->ActionRequest = newstate;
742 /* if any other feature wants it local we need to set it local */
743 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
745 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
746 f->ActionRequest != INSTALLSTATE_SOURCE )
748 continue;
750 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
752 if (clist->component == component &&
753 (f->ActionRequest == INSTALLSTATE_LOCAL ||
754 f->ActionRequest == INSTALLSTATE_SOURCE))
756 TRACE("Saved by %s\n", debugstr_w(f->Feature));
757 component->hasLocalFeature = TRUE;
759 if (component->Attributes & msidbComponentAttributesOptional)
761 if (f->Attributes & msidbFeatureAttributesFavorSource)
763 component->Action = INSTALLSTATE_SOURCE;
764 component->ActionRequest = INSTALLSTATE_SOURCE;
766 else
768 component->Action = INSTALLSTATE_LOCAL;
769 component->ActionRequest = INSTALLSTATE_LOCAL;
772 else if (component->Attributes & msidbComponentAttributesSourceOnly)
774 component->Action = INSTALLSTATE_SOURCE;
775 component->ActionRequest = INSTALLSTATE_SOURCE;
777 else
779 component->Action = INSTALLSTATE_LOCAL;
780 component->ActionRequest = INSTALLSTATE_LOCAL;
786 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
787 newstate, debugstr_w(component->Component), component->Installed,
788 component->Action, component->ActionRequest);
792 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
794 UINT rc = ERROR_SUCCESS;
795 MSIFEATURE *feature, *child;
797 TRACE("%s %i\n", debugstr_w(szFeature), iState);
799 feature = msi_get_loaded_feature( package, szFeature );
800 if (!feature)
801 return ERROR_UNKNOWN_FEATURE;
803 if (iState == INSTALLSTATE_ADVERTISED &&
804 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
805 return ERROR_FUNCTION_FAILED;
807 feature->ActionRequest = iState;
809 ACTION_UpdateComponentStates( package, feature );
811 /* update all the features that are children of this feature */
812 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
814 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
815 MSI_SetFeatureStateW(package, child->Feature, iState);
818 return rc;
821 /***********************************************************************
822 * MsiSetFeatureStateW (MSI.@)
824 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
825 INSTALLSTATE iState)
827 MSIPACKAGE* package;
828 UINT rc = ERROR_SUCCESS;
830 TRACE("%s %i\n",debugstr_w(szFeature), iState);
832 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
833 if (!package)
835 MSIHANDLE remote;
836 HRESULT hr;
837 BSTR feature;
839 if (!(remote = msi_get_remote(hInstall)))
840 return ERROR_INVALID_HANDLE;
842 feature = SysAllocString(szFeature);
843 if (!feature)
844 return ERROR_OUTOFMEMORY;
846 hr = remote_SetFeatureState(remote, feature, iState);
848 SysFreeString(feature);
850 if (FAILED(hr))
852 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
853 return HRESULT_CODE(hr);
855 return ERROR_FUNCTION_FAILED;
858 return ERROR_SUCCESS;
861 rc = MSI_SetFeatureStateW(package,szFeature,iState);
863 msiobj_release( &package->hdr );
864 return rc;
867 /***********************************************************************
868 * MsiSetFeatureAttributesA (MSI.@)
870 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
872 UINT r;
873 WCHAR *featureW = NULL;
875 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
877 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
879 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
880 msi_free( featureW );
881 return r;
884 static DWORD unmap_feature_attributes( DWORD attrs )
886 DWORD ret = 0;
888 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
889 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
890 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
891 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
892 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
893 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
894 return ret;
897 /***********************************************************************
898 * MsiSetFeatureAttributesW (MSI.@)
900 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
902 MSIPACKAGE *package;
903 MSIFEATURE *feature;
904 WCHAR *costing;
906 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
908 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
910 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
911 return ERROR_INVALID_HANDLE;
913 costing = msi_dup_property( package->db, szCostingComplete );
914 if (!costing || !strcmpW( costing, szOne ))
916 msi_free( costing );
917 msiobj_release( &package->hdr );
918 return ERROR_FUNCTION_FAILED;
920 msi_free( costing );
921 if (!(feature = msi_get_loaded_feature( package, name )))
923 msiobj_release( &package->hdr );
924 return ERROR_UNKNOWN_FEATURE;
926 feature->Attributes = unmap_feature_attributes( attrs );
927 msiobj_release( &package->hdr );
928 return ERROR_SUCCESS;
931 /***********************************************************************
932 * MsiGetFeatureStateA (MSI.@)
934 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
935 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
937 LPWSTR szwFeature = NULL;
938 UINT rc;
940 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
942 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
943 msi_free( szwFeature);
944 return rc;
947 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
948 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
950 MSIFEATURE *feature;
952 feature = msi_get_loaded_feature(package,szFeature);
953 if (!feature)
954 return ERROR_UNKNOWN_FEATURE;
956 if (piInstalled)
957 *piInstalled = feature->Installed;
959 if (piAction)
960 *piAction = feature->ActionRequest;
962 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
964 return ERROR_SUCCESS;
967 /***********************************************************************
968 * MsiGetFeatureStateW (MSI.@)
970 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
971 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
973 MSIPACKAGE* package;
974 UINT ret;
976 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
978 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
979 if (!package)
981 MSIHANDLE remote;
982 HRESULT hr;
983 BSTR feature;
985 if (!(remote = msi_get_remote(hInstall)))
986 return ERROR_INVALID_HANDLE;
988 feature = SysAllocString(szFeature);
989 if (!feature)
990 return ERROR_OUTOFMEMORY;
992 hr = remote_GetFeatureState(remote, feature, piInstalled, piAction);
994 SysFreeString(feature);
996 if (FAILED(hr))
998 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
999 return HRESULT_CODE(hr);
1001 return ERROR_FUNCTION_FAILED;
1004 return ERROR_SUCCESS;
1007 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1008 msiobj_release( &package->hdr );
1009 return ret;
1012 /***********************************************************************
1013 * MsiGetFeatureCostA (MSI.@)
1015 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1016 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1018 LPWSTR szwFeature = NULL;
1019 UINT rc;
1021 szwFeature = strdupAtoW(szFeature);
1023 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1025 msi_free(szwFeature);
1027 return rc;
1030 static INT feature_cost( MSIFEATURE *feature )
1032 INT cost = 0;
1033 ComponentList *cl;
1035 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
1037 cost += cl->component->Cost;
1039 return cost;
1042 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1043 INSTALLSTATE state, LPINT cost )
1045 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1047 *cost = 0;
1048 switch (tree)
1050 case MSICOSTTREE_CHILDREN:
1052 MSIFEATURE *child;
1054 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1056 if (child->ActionRequest == state)
1057 *cost += feature_cost( child );
1059 break;
1061 case MSICOSTTREE_PARENTS:
1063 const WCHAR *feature_parent = feature->Feature_Parent;
1064 for (;;)
1066 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1067 if (!parent)
1068 break;
1070 if (parent->ActionRequest == state)
1071 *cost += feature_cost( parent );
1073 feature_parent = parent->Feature_Parent;
1075 break;
1077 case MSICOSTTREE_SELFONLY:
1078 if (feature->ActionRequest == state)
1079 *cost = feature_cost( feature );
1080 break;
1082 default:
1083 WARN("unhandled cost tree %u\n", tree);
1084 break;
1087 *cost /= 512;
1088 return ERROR_SUCCESS;
1091 /***********************************************************************
1092 * MsiGetFeatureCostW (MSI.@)
1094 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1095 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1097 MSIPACKAGE *package;
1098 MSIFEATURE *feature;
1099 UINT ret;
1101 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1102 iCostTree, iState, piCost);
1104 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1105 if (!package)
1107 MSIHANDLE remote;
1108 HRESULT hr;
1109 BSTR feature;
1111 if (!(remote = msi_get_remote(hInstall)))
1112 return ERROR_INVALID_HANDLE;
1114 feature = SysAllocString(szFeature);
1115 if (!feature)
1116 return ERROR_OUTOFMEMORY;
1118 hr = remote_GetFeatureCost(remote, feature, iCostTree, iState, piCost);
1120 SysFreeString(feature);
1122 if (FAILED(hr))
1124 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1125 return HRESULT_CODE(hr);
1127 return ERROR_FUNCTION_FAILED;
1130 return ERROR_SUCCESS;
1133 feature = msi_get_loaded_feature(package, szFeature);
1135 if (feature)
1136 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1137 else
1138 ret = ERROR_UNKNOWN_FEATURE;
1140 msiobj_release( &package->hdr );
1141 return ret;
1144 /***********************************************************************
1145 * MsiGetFeatureInfoA (MSI.@)
1147 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1148 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1150 UINT r;
1151 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1153 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1154 title_len, help, help_len);
1156 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1158 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1160 msi_free( featureW );
1161 return ERROR_OUTOFMEMORY;
1163 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1165 msi_free( featureW );
1166 msi_free( titleW );
1167 return ERROR_OUTOFMEMORY;
1169 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1170 if (r == ERROR_SUCCESS)
1172 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1173 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1175 msi_free( titleW );
1176 msi_free( helpW );
1177 msi_free( featureW );
1178 return r;
1181 static DWORD map_feature_attributes( DWORD attrs )
1183 DWORD ret = 0;
1185 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1186 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1187 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1188 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1189 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1190 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1191 return ret;
1194 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1195 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1197 UINT r = ERROR_SUCCESS;
1198 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1199 int len;
1201 if (!feature) return ERROR_UNKNOWN_FEATURE;
1202 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1203 if (title_len)
1205 if (feature->Title) len = strlenW( feature->Title );
1206 else len = 0;
1207 if (*title_len <= len)
1209 *title_len = len;
1210 if (title) r = ERROR_MORE_DATA;
1212 else if (title)
1214 if (feature->Title) strcpyW( title, feature->Title );
1215 else *title = 0;
1216 *title_len = len;
1219 if (help_len)
1221 if (feature->Description) len = strlenW( feature->Description );
1222 else len = 0;
1223 if (*help_len <= len)
1225 *help_len = len;
1226 if (help) r = ERROR_MORE_DATA;
1228 else if (help)
1230 if (feature->Description) strcpyW( help, feature->Description );
1231 else *help = 0;
1232 *help_len = len;
1235 return r;
1238 /***********************************************************************
1239 * MsiGetFeatureInfoW (MSI.@)
1241 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1242 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1244 UINT r;
1245 MSIPACKAGE *package;
1247 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1248 title_len, help, help_len);
1250 if (!feature) return ERROR_INVALID_PARAMETER;
1252 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1253 return ERROR_INVALID_HANDLE;
1255 /* features may not have been loaded yet */
1256 msi_load_all_components( package );
1257 msi_load_all_features( package );
1259 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1260 msiobj_release( &package->hdr );
1261 return r;
1264 /***********************************************************************
1265 * MsiSetComponentStateA (MSI.@)
1267 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1268 INSTALLSTATE iState)
1270 UINT rc;
1271 LPWSTR szwComponent = strdupAtoW(szComponent);
1273 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1275 msi_free(szwComponent);
1277 return rc;
1280 /***********************************************************************
1281 * MsiGetComponentStateA (MSI.@)
1283 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1284 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1286 LPWSTR szwComponent= NULL;
1287 UINT rc;
1289 szwComponent= strdupAtoW(szComponent);
1291 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1293 msi_free( szwComponent);
1295 return rc;
1298 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1299 INSTALLSTATE iState)
1301 MSICOMPONENT *comp;
1303 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1305 comp = msi_get_loaded_component(package, szComponent);
1306 if (!comp)
1307 return ERROR_UNKNOWN_COMPONENT;
1309 if (comp->Enabled)
1310 comp->Action = iState;
1312 return ERROR_SUCCESS;
1315 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1316 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1318 MSICOMPONENT *comp;
1320 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1321 piInstalled, piAction);
1323 comp = msi_get_loaded_component(package,szComponent);
1324 if (!comp)
1325 return ERROR_UNKNOWN_COMPONENT;
1327 if (piInstalled)
1329 if (comp->Enabled)
1330 *piInstalled = comp->Installed;
1331 else
1332 *piInstalled = INSTALLSTATE_UNKNOWN;
1335 if (piAction)
1337 if (comp->Enabled)
1338 *piAction = comp->Action;
1339 else
1340 *piAction = INSTALLSTATE_UNKNOWN;
1343 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1344 return ERROR_SUCCESS;
1347 /***********************************************************************
1348 * MsiSetComponentStateW (MSI.@)
1350 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1351 INSTALLSTATE iState)
1353 MSIPACKAGE* package;
1354 UINT ret;
1356 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1357 if (!package)
1359 MSIHANDLE remote;
1360 HRESULT hr;
1361 BSTR component;
1363 if (!(remote = msi_get_remote(hInstall)))
1364 return ERROR_INVALID_HANDLE;
1366 component = SysAllocString(szComponent);
1367 if (!component)
1368 return ERROR_OUTOFMEMORY;
1370 hr = remote_SetComponentState(remote, component, iState);
1372 SysFreeString(component);
1374 if (FAILED(hr))
1376 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1377 return HRESULT_CODE(hr);
1379 return ERROR_FUNCTION_FAILED;
1382 return ERROR_SUCCESS;
1385 ret = MSI_SetComponentStateW(package, szComponent, iState);
1386 msiobj_release(&package->hdr);
1387 return ret;
1390 /***********************************************************************
1391 * MsiGetComponentStateW (MSI.@)
1393 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1394 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1396 MSIPACKAGE* package;
1397 UINT ret;
1399 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1400 piInstalled, piAction);
1402 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1403 if (!package)
1405 MSIHANDLE remote;
1406 HRESULT hr;
1407 BSTR component;
1409 if (!(remote = msi_get_remote(hInstall)))
1410 return ERROR_INVALID_HANDLE;
1412 component = SysAllocString(szComponent);
1413 if (!component)
1414 return ERROR_OUTOFMEMORY;
1416 hr = remote_GetComponentState(remote, component, piInstalled, piAction);
1418 SysFreeString(component);
1420 if (FAILED(hr))
1422 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1423 return HRESULT_CODE(hr);
1425 return ERROR_FUNCTION_FAILED;
1428 return ERROR_SUCCESS;
1431 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1432 msiobj_release( &package->hdr );
1433 return ret;
1436 /***********************************************************************
1437 * MsiGetLanguage (MSI.@)
1439 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1441 MSIPACKAGE* package;
1442 LANGID langid;
1444 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1445 if (!package)
1447 MSIHANDLE remote;
1448 HRESULT hr;
1449 LANGID lang;
1451 if (!(remote = msi_get_remote(hInstall)))
1452 return ERROR_INVALID_HANDLE;
1454 hr = remote_GetLanguage(remote, &lang);
1456 if (SUCCEEDED(hr))
1457 return lang;
1459 return 0;
1462 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1463 msiobj_release( &package->hdr );
1464 return langid;
1467 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1469 static const WCHAR fmt[] = { '%','d',0 };
1470 WCHAR level[6];
1471 int len;
1472 UINT r;
1474 TRACE("%p %i\n", package, iInstallLevel);
1476 if (iInstallLevel > 32767)
1477 return ERROR_INVALID_PARAMETER;
1479 if (iInstallLevel < 1)
1480 return MSI_SetFeatureStates( package );
1482 len = sprintfW( level, fmt, iInstallLevel );
1483 r = msi_set_property( package->db, szInstallLevel, level, len );
1484 if ( r == ERROR_SUCCESS )
1485 r = MSI_SetFeatureStates( package );
1487 return r;
1490 /***********************************************************************
1491 * MsiSetInstallLevel (MSI.@)
1493 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1495 MSIPACKAGE* package;
1496 UINT r;
1498 TRACE("%d %i\n", hInstall, iInstallLevel);
1500 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1501 if (!package)
1503 MSIHANDLE remote;
1504 HRESULT hr;
1506 if (!(remote = msi_get_remote(hInstall)))
1507 return ERROR_INVALID_HANDLE;
1509 hr = remote_SetInstallLevel(remote, iInstallLevel);
1511 if (FAILED(hr))
1513 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1514 return HRESULT_CODE(hr);
1516 return ERROR_FUNCTION_FAILED;
1519 return ERROR_SUCCESS;
1522 r = MSI_SetInstallLevel( package, iInstallLevel );
1524 msiobj_release( &package->hdr );
1526 return r;
1529 /***********************************************************************
1530 * MsiGetFeatureValidStatesW (MSI.@)
1532 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1533 LPDWORD pInstallState)
1535 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1536 FIXME("%d %s %p stub returning %d\n",
1537 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1539 return ERROR_SUCCESS;
1542 /***********************************************************************
1543 * MsiGetFeatureValidStatesA (MSI.@)
1545 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1546 LPDWORD pInstallState)
1548 UINT ret;
1549 LPWSTR szwFeature = strdupAtoW(szFeature);
1551 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1553 msi_free(szwFeature);
1555 return ret;