winepulse: Set pulse master volume to 0 when session is muted.
[wine.git] / dlls / msi / install.c
bloba3bfb53cffff86efdec6edd41ba147b0c8abf320
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/exception.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 __TRY
85 ret = remote_DoAction(remote, szAction);
87 __EXCEPT(rpc_filter)
89 ret = GetExceptionCode();
91 __ENDTRY
93 return ret;
96 ret = ACTION_PerformAction(package, szAction);
97 msiobj_release( &package->hdr );
99 return ret;
102 /***********************************************************************
103 * MsiSequenceA (MSI.@)
105 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
107 LPWSTR szwTable;
108 UINT ret;
110 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
112 szwTable = strdupAtoW(szTable);
113 if (szTable && !szwTable)
114 return ERROR_FUNCTION_FAILED;
116 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
117 msi_free( szwTable );
118 return ret;
121 /***********************************************************************
122 * MsiSequenceW (MSI.@)
124 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
126 MSIPACKAGE *package;
127 UINT ret;
129 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
131 if (!szTable)
132 return ERROR_INVALID_PARAMETER;
134 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
135 if (!package)
137 MSIHANDLE remote;
139 if (!(remote = msi_get_remote(hInstall)))
140 return ERROR_INVALID_HANDLE;
142 __TRY
144 ret = remote_Sequence(remote, szTable, iSequenceMode);
146 __EXCEPT(rpc_filter)
148 ret = GetExceptionCode();
150 __ENDTRY
152 return ret;
154 ret = MSI_Sequence( package, szTable );
155 msiobj_release( &package->hdr );
156 return ret;
159 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
161 UINT r = ERROR_SUCCESS;
163 if (awbuf->str.w && !sz)
164 return ERROR_INVALID_PARAMETER;
165 if (!sz)
166 return ERROR_SUCCESS;
168 if (len < 0) len = lstrlenW( str );
170 if (awbuf->unicode && awbuf->str.w)
172 memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
173 if (*sz && len >= *sz)
174 awbuf->str.w[*sz - 1] = 0;
176 else
178 int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
179 if (lenA) lenA--;
180 WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
181 if (awbuf->str.a && *sz && lenA >= *sz)
182 awbuf->str.a[*sz - 1] = 0;
183 len = lenA;
185 if (awbuf->str.w && len >= *sz)
186 r = ERROR_MORE_DATA;
187 *sz = len;
188 return r;
191 UINT msi_strncpyWtoA(const WCHAR *str, int lenW, char *buf, DWORD *sz, BOOL remote)
193 UINT r = ERROR_SUCCESS;
194 DWORD lenA;
196 if (!sz)
197 return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
199 if (lenW < 0) lenW = lstrlenW(str);
200 lenA = WideCharToMultiByte(CP_ACP, 0, str, lenW + 1, NULL, 0, NULL, NULL);
201 WideCharToMultiByte(CP_ACP, 0, str, lenW + 1, buf, *sz, NULL, NULL);
202 lenA--;
203 if (buf && lenA >= *sz)
205 if (*sz) buf[*sz - 1] = 0;
206 r = ERROR_MORE_DATA;
208 if (remote && lenA >= *sz)
209 lenA *= 2;
210 *sz = lenA;
211 return r;
214 UINT msi_strncpyW(const WCHAR *str, int len, WCHAR *buf, DWORD *sz)
216 UINT r = ERROR_SUCCESS;
218 if (!sz)
219 return buf ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
221 if (len < 0) len = lstrlenW(str);
222 if (buf)
223 memcpy(buf, str, min(len + 1, *sz) * sizeof(WCHAR));
224 if (buf && len >= *sz)
226 if (*sz) buf[*sz - 1] = 0;
227 r = ERROR_MORE_DATA;
229 *sz = len;
230 return r;
233 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
235 MSIFOLDER *folder = msi_get_loaded_folder( package, name );
237 if (!folder) return NULL;
238 if (!folder->ResolvedTarget)
240 MSIFOLDER *parent = folder;
241 while (parent->Parent && wcscmp( parent->Parent, parent->Directory ))
243 parent = msi_get_loaded_folder( package, parent->Parent );
245 msi_resolve_target_folder( package, parent->Directory, TRUE );
247 return folder->ResolvedTarget;
250 /***********************************************************************
251 * MsiGetTargetPathA (MSI.@)
253 UINT WINAPI MsiGetTargetPathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
255 MSIPACKAGE *package;
256 const WCHAR *path;
257 WCHAR *folderW;
258 UINT r;
260 TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
262 if (!folder)
263 return ERROR_INVALID_PARAMETER;
265 if (!(folderW = strdupAtoW(folder)))
266 return ERROR_OUTOFMEMORY;
268 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
269 if (!package)
271 WCHAR *path = NULL;
272 MSIHANDLE remote;
274 if (!(remote = msi_get_remote(hinst)))
276 heap_free(folderW);
277 return ERROR_INVALID_HANDLE;
280 __TRY
282 r = remote_GetTargetPath(remote, folderW, &path);
284 __EXCEPT(rpc_filter)
286 r = GetExceptionCode();
288 __ENDTRY
290 if (!r)
291 r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
293 midl_user_free(path);
294 heap_free(folderW);
295 return r;
298 path = msi_get_target_folder(package, folderW);
299 if (path)
300 r = msi_strncpyWtoA(path, -1, buf, sz, FALSE);
301 else
302 r = ERROR_DIRECTORY;
304 heap_free(folderW);
305 msiobj_release(&package->hdr);
306 return r;
309 /***********************************************************************
310 * MsiGetTargetPathW (MSI.@)
312 UINT WINAPI MsiGetTargetPathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
314 MSIPACKAGE *package;
315 const WCHAR *path;
316 UINT r;
318 TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
320 if (!folder)
321 return ERROR_INVALID_PARAMETER;
323 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
324 if (!package)
326 WCHAR *path = NULL;
327 MSIHANDLE remote;
329 if (!(remote = msi_get_remote(hinst)))
330 return ERROR_INVALID_HANDLE;
332 __TRY
334 r = remote_GetTargetPath(remote, folder, &path);
336 __EXCEPT(rpc_filter)
338 r = GetExceptionCode();
340 __ENDTRY
342 if (!r)
343 r = msi_strncpyW(path, -1, buf, sz);
345 midl_user_free(path);
346 return r;
349 path = msi_get_target_folder(package, folder);
350 if (path)
351 r = msi_strncpyW(path, -1, buf, sz);
352 else
353 r = ERROR_DIRECTORY;
355 msiobj_release(&package->hdr);
356 return r;
359 static WCHAR *get_source_root( MSIPACKAGE *package )
361 msi_set_sourcedir_props( package, FALSE );
362 return msi_dup_property( package->db, L"SourceDir" );
365 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
367 MSIFOLDER *f;
368 LPWSTR p, path = NULL, parent;
370 TRACE("working to resolve %s\n", debugstr_w(name));
372 if (!wcscmp( name, L"SourceDir" )) name = L"TARGETDIR";
373 if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
375 /* special resolving for root dir */
376 if (!wcscmp( name, L"TARGETDIR" ) && !f->ResolvedSource)
378 f->ResolvedSource = get_source_root( package );
380 if (folder) *folder = f;
381 if (f->ResolvedSource)
383 path = strdupW( f->ResolvedSource );
384 TRACE(" already resolved to %s\n", debugstr_w(path));
385 return path;
387 if (!f->Parent) return path;
388 parent = f->Parent;
389 TRACE(" ! parent is %s\n", debugstr_w(parent));
391 p = msi_resolve_source_folder( package, parent, NULL );
393 if (package->WordCount & msidbSumInfoSourceTypeCompressed)
394 path = get_source_root( package );
395 else if (package->WordCount & msidbSumInfoSourceTypeSFN)
396 path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
397 else
398 path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
400 TRACE("-> %s\n", debugstr_w(path));
401 f->ResolvedSource = strdupW( path );
402 msi_free( p );
404 return path;
407 /***********************************************************************
408 * MsiGetSourcePathA (MSI.@)
410 UINT WINAPI MsiGetSourcePathA(MSIHANDLE hinst, const char *folder, char *buf, DWORD *sz)
412 MSIPACKAGE *package;
413 WCHAR *path, *folderW;
414 UINT r;
416 TRACE("%s %p %p\n", debugstr_a(folder), buf, sz);
418 if (!folder)
419 return ERROR_INVALID_PARAMETER;
421 if (!(folderW = strdupAtoW(folder)))
422 return ERROR_OUTOFMEMORY;
424 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
425 if (!package)
427 WCHAR *path = NULL;
428 MSIHANDLE remote;
430 if (!(remote = msi_get_remote(hinst)))
432 heap_free(folderW);
433 return ERROR_INVALID_HANDLE;
436 __TRY
438 r = remote_GetSourcePath(remote, folderW, &path);
440 __EXCEPT(rpc_filter)
442 r = GetExceptionCode();
444 __ENDTRY
446 if (!r)
447 r = msi_strncpyWtoA(path, -1, buf, sz, TRUE);
449 midl_user_free(path);
450 heap_free(folderW);
451 return r;
454 path = msi_resolve_source_folder(package, folderW, NULL);
455 if (path)
456 r = msi_strncpyWtoA(path, -1, buf, sz, FALSE);
457 else
458 r = ERROR_DIRECTORY;
460 heap_free(path);
461 heap_free(folderW);
462 msiobj_release(&package->hdr);
463 return r;
466 /***********************************************************************
467 * MsiGetSourcePathW (MSI.@)
469 UINT WINAPI MsiGetSourcePathW(MSIHANDLE hinst, const WCHAR *folder, WCHAR *buf, DWORD *sz)
471 MSIPACKAGE *package;
472 WCHAR *path;
473 UINT r;
475 TRACE("%s %p %p\n", debugstr_w(folder), buf, sz);
477 if (!folder)
478 return ERROR_INVALID_PARAMETER;
480 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
481 if (!package)
483 WCHAR *path = NULL;
484 MSIHANDLE remote;
486 if (!(remote = msi_get_remote(hinst)))
487 return ERROR_INVALID_HANDLE;
489 __TRY
491 r = remote_GetSourcePath(remote, folder, &path);
493 __EXCEPT(rpc_filter)
495 r = GetExceptionCode();
497 __ENDTRY
499 if (!r)
500 r = msi_strncpyW(path, -1, buf, sz);
502 midl_user_free(path);
503 return r;
506 path = msi_resolve_source_folder(package, folder, NULL);
507 if (path)
508 r = msi_strncpyW(path, -1, buf, sz);
509 else
510 r = ERROR_DIRECTORY;
512 heap_free(path);
513 msiobj_release(&package->hdr);
514 return r;
517 /***********************************************************************
518 * MsiSetTargetPathA (MSI.@)
520 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
521 LPCSTR szFolderPath )
523 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
524 UINT rc = ERROR_OUTOFMEMORY;
526 if ( !szFolder || !szFolderPath )
527 return ERROR_INVALID_PARAMETER;
529 szwFolder = strdupAtoW(szFolder);
530 szwFolderPath = strdupAtoW(szFolderPath);
531 if (!szwFolder || !szwFolderPath)
532 goto end;
534 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
536 end:
537 msi_free(szwFolder);
538 msi_free(szwFolderPath);
540 return rc;
543 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
545 FolderList *fl;
546 MSIFOLDER *child;
547 WCHAR *target_path;
549 if (!(target_path = msi_normalize_path( path ))) return;
550 if (wcscmp( target_path, folder->ResolvedTarget ))
552 msi_free( folder->ResolvedTarget );
553 folder->ResolvedTarget = target_path;
554 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
556 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
558 child = fl->folder;
559 msi_resolve_target_folder( package, child->Directory, FALSE );
562 else msi_free( target_path );
565 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
567 DWORD attrib;
568 MSIFOLDER *folder;
569 MSIFILE *file;
571 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
573 attrib = msi_get_file_attributes( package, szFolderPath );
574 /* native MSI tests writeability by making temporary files at each drive */
575 if (attrib != INVALID_FILE_ATTRIBUTES &&
576 (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
578 return ERROR_FUNCTION_FAILED;
580 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
582 set_target_path( package, folder, szFolderPath );
584 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
586 const WCHAR *dir;
587 MSICOMPONENT *comp = file->Component;
589 if (!comp->Enabled || msi_is_global_assembly( comp )) continue;
591 dir = msi_get_target_folder( package, comp->Directory );
592 msi_free( file->TargetPath );
593 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
595 return ERROR_SUCCESS;
598 /***********************************************************************
599 * MsiSetTargetPathW (MSI.@)
601 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
602 LPCWSTR szFolderPath)
604 MSIPACKAGE *package;
605 UINT ret;
607 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
609 if ( !szFolder || !szFolderPath )
610 return ERROR_INVALID_PARAMETER;
612 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
613 if (!package)
615 MSIHANDLE remote;
617 if (!(remote = msi_get_remote(hInstall)))
618 return ERROR_INVALID_HANDLE;
620 __TRY
622 ret = remote_SetTargetPath(remote, szFolder, szFolderPath);
624 __EXCEPT(rpc_filter)
626 ret = GetExceptionCode();
628 __ENDTRY
630 return ret;
633 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
634 msiobj_release( &package->hdr );
635 return ret;
638 /***********************************************************************
639 * MsiGetMode (MSI.@)
641 * Returns an internal installer state (if it is running in a mode iRunMode)
643 * PARAMS
644 * hInstall [I] Handle to the installation
645 * hRunMode [I] Checking run mode
646 * MSIRUNMODE_ADMIN Administrative mode
647 * MSIRUNMODE_ADVERTISE Advertisement mode
648 * MSIRUNMODE_MAINTENANCE Maintenance mode
649 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
650 * MSIRUNMODE_LOGENABLED Log file is writing
651 * MSIRUNMODE_OPERATIONS Operations in progress??
652 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
653 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
654 * MSIRUNMODE_CABINET Files from cabinet are installed
655 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
656 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
657 * MSIRUNMODE_RESERVED11 Reserved
658 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
659 * MSIRUNMODE_ZAWENABLED Demand installation is supported
660 * MSIRUNMODE_RESERVED14 Reserved
661 * MSIRUNMODE_RESERVED15 Reserved
662 * MSIRUNMODE_SCHEDULED called from install script
663 * MSIRUNMODE_ROLLBACK called from rollback script
664 * MSIRUNMODE_COMMIT called from commit script
666 * RETURNS
667 * In the state: TRUE
668 * Not in the state: FALSE
671 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
673 MSIPACKAGE *package;
674 BOOL r = FALSE;
676 TRACE("%d %d\n", hInstall, iRunMode);
678 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
679 if (!package)
681 MSIHANDLE remote;
683 if (!(remote = msi_get_remote(hInstall)))
684 return FALSE;
686 __TRY
688 r = remote_GetMode(remote, iRunMode);
690 __EXCEPT(rpc_filter)
692 r = FALSE;
694 __ENDTRY
696 return r;
699 switch (iRunMode)
701 case MSIRUNMODE_ADMIN:
702 FIXME("no support for administrative installs\n");
703 break;
705 case MSIRUNMODE_ADVERTISE:
706 FIXME("no support for advertised installs\n");
707 break;
709 case MSIRUNMODE_WINDOWS9X:
710 if (GetVersion() & 0x80000000)
711 r = TRUE;
712 break;
714 case MSIRUNMODE_OPERATIONS:
715 case MSIRUNMODE_RESERVED11:
716 case MSIRUNMODE_RESERVED14:
717 case MSIRUNMODE_RESERVED15:
718 break;
720 case MSIRUNMODE_SCHEDULED:
721 r = package->scheduled_action_running;
722 break;
724 case MSIRUNMODE_ROLLBACK:
725 r = package->rollback_action_running;
726 break;
728 case MSIRUNMODE_COMMIT:
729 r = package->commit_action_running;
730 break;
732 case MSIRUNMODE_MAINTENANCE:
733 r = msi_get_property_int( package->db, L"Installed", 0 ) != 0;
734 break;
736 case MSIRUNMODE_ROLLBACKENABLED:
737 r = msi_get_property_int( package->db, L"RollbackDisabled", 0 ) == 0;
738 break;
740 case MSIRUNMODE_REBOOTATEND:
741 r = package->need_reboot_at_end;
742 break;
744 case MSIRUNMODE_REBOOTNOW:
745 r = package->need_reboot_now;
746 break;
748 case MSIRUNMODE_LOGENABLED:
749 r = (package->log_file != INVALID_HANDLE_VALUE);
750 break;
752 default:
753 FIXME("unimplemented run mode: %d\n", iRunMode);
754 r = TRUE;
757 msiobj_release( &package->hdr );
758 return r;
761 /***********************************************************************
762 * MsiSetMode (MSI.@)
764 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
766 MSIPACKAGE *package;
767 UINT r;
769 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
771 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
772 if (!package)
774 MSIHANDLE remote;
776 if (!(remote = msi_get_remote(hInstall)))
777 return FALSE;
779 __TRY
781 r = remote_SetMode(remote, iRunMode, fState);
783 __EXCEPT(rpc_filter)
785 r = GetExceptionCode();
787 __ENDTRY
789 return r;
792 switch (iRunMode)
794 case MSIRUNMODE_REBOOTATEND:
795 package->need_reboot_at_end = (fState != 0);
796 r = ERROR_SUCCESS;
797 break;
799 case MSIRUNMODE_REBOOTNOW:
800 package->need_reboot_now = (fState != 0);
801 r = ERROR_SUCCESS;
802 break;
804 default:
805 r = ERROR_ACCESS_DENIED;
808 msiobj_release( &package->hdr );
809 return r;
812 /***********************************************************************
813 * MsiSetFeatureStateA (MSI.@)
815 * According to the docs, when this is called it immediately recalculates
816 * all the component states as well
818 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
819 INSTALLSTATE iState)
821 LPWSTR szwFeature = NULL;
822 UINT rc;
824 szwFeature = strdupAtoW(szFeature);
826 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
828 msi_free(szwFeature);
830 return rc;
833 /* update component state based on a feature change */
834 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
836 INSTALLSTATE newstate;
837 ComponentList *cl;
839 newstate = feature->ActionRequest;
840 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
842 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
844 MSICOMPONENT *component = cl->component;
846 if (!component->Enabled) continue;
848 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
849 newstate, debugstr_w(component->Component), component->Installed,
850 component->Action, component->ActionRequest);
852 if (newstate == INSTALLSTATE_LOCAL)
854 component->Action = INSTALLSTATE_LOCAL;
855 component->ActionRequest = INSTALLSTATE_LOCAL;
857 else
859 ComponentList *clist;
860 MSIFEATURE *f;
862 component->hasLocalFeature = FALSE;
864 component->Action = newstate;
865 component->ActionRequest = newstate;
866 /* if any other feature wants it local we need to set it local */
867 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
869 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
870 f->ActionRequest != INSTALLSTATE_SOURCE )
872 continue;
874 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
876 if (clist->component == component &&
877 (f->ActionRequest == INSTALLSTATE_LOCAL ||
878 f->ActionRequest == INSTALLSTATE_SOURCE))
880 TRACE("Saved by %s\n", debugstr_w(f->Feature));
881 component->hasLocalFeature = TRUE;
883 if (component->Attributes & msidbComponentAttributesOptional)
885 if (f->Attributes & msidbFeatureAttributesFavorSource)
887 component->Action = INSTALLSTATE_SOURCE;
888 component->ActionRequest = INSTALLSTATE_SOURCE;
890 else
892 component->Action = INSTALLSTATE_LOCAL;
893 component->ActionRequest = INSTALLSTATE_LOCAL;
896 else if (component->Attributes & msidbComponentAttributesSourceOnly)
898 component->Action = INSTALLSTATE_SOURCE;
899 component->ActionRequest = INSTALLSTATE_SOURCE;
901 else
903 component->Action = INSTALLSTATE_LOCAL;
904 component->ActionRequest = INSTALLSTATE_LOCAL;
910 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
911 newstate, debugstr_w(component->Component), component->Installed,
912 component->Action, component->ActionRequest);
916 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
918 UINT rc = ERROR_SUCCESS;
919 MSIFEATURE *feature, *child;
921 TRACE("%s %i\n", debugstr_w(szFeature), iState);
923 feature = msi_get_loaded_feature( package, szFeature );
924 if (!feature)
925 return ERROR_UNKNOWN_FEATURE;
927 if (iState == INSTALLSTATE_ADVERTISED &&
928 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
929 return ERROR_FUNCTION_FAILED;
931 feature->ActionRequest = iState;
933 ACTION_UpdateComponentStates( package, feature );
935 /* update all the features that are children of this feature */
936 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
938 if (child->Feature_Parent && !wcscmp( szFeature, child->Feature_Parent ))
939 MSI_SetFeatureStateW(package, child->Feature, iState);
942 return rc;
945 /***********************************************************************
946 * MsiSetFeatureStateW (MSI.@)
948 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
949 INSTALLSTATE iState)
951 MSIPACKAGE* package;
952 UINT rc = ERROR_SUCCESS;
954 TRACE("%s %i\n",debugstr_w(szFeature), iState);
956 if (!szFeature)
957 return ERROR_UNKNOWN_FEATURE;
959 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
960 if (!package)
962 MSIHANDLE remote;
964 if (!(remote = msi_get_remote(hInstall)))
965 return ERROR_INVALID_HANDLE;
967 __TRY
969 rc = remote_SetFeatureState(remote, szFeature, iState);
971 __EXCEPT(rpc_filter)
973 rc = GetExceptionCode();
975 __ENDTRY
977 return rc;
980 rc = MSI_SetFeatureStateW(package,szFeature,iState);
982 msiobj_release( &package->hdr );
983 return rc;
986 /***********************************************************************
987 * MsiSetFeatureAttributesA (MSI.@)
989 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
991 UINT r;
992 WCHAR *featureW = NULL;
994 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
996 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
998 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
999 msi_free( featureW );
1000 return r;
1003 static DWORD unmap_feature_attributes( DWORD attrs )
1005 DWORD ret = 0;
1007 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
1008 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
1009 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
1010 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
1011 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
1012 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
1013 return ret;
1016 /***********************************************************************
1017 * MsiSetFeatureAttributesW (MSI.@)
1019 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
1021 MSIPACKAGE *package;
1022 MSIFEATURE *feature;
1023 WCHAR *costing;
1025 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
1027 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
1029 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1030 return ERROR_INVALID_HANDLE;
1032 costing = msi_dup_property( package->db, L"CostingComplete" );
1033 if (!costing || !wcscmp( costing, L"1" ))
1035 msi_free( costing );
1036 msiobj_release( &package->hdr );
1037 return ERROR_FUNCTION_FAILED;
1039 msi_free( costing );
1040 if (!(feature = msi_get_loaded_feature( package, name )))
1042 msiobj_release( &package->hdr );
1043 return ERROR_UNKNOWN_FEATURE;
1045 feature->Attributes = unmap_feature_attributes( attrs );
1046 msiobj_release( &package->hdr );
1047 return ERROR_SUCCESS;
1050 /***********************************************************************
1051 * MsiGetFeatureStateA (MSI.@)
1053 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
1054 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1056 LPWSTR szwFeature = NULL;
1057 UINT rc;
1059 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
1061 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
1062 msi_free( szwFeature);
1063 return rc;
1066 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
1067 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1069 MSIFEATURE *feature;
1071 feature = msi_get_loaded_feature(package,szFeature);
1072 if (!feature)
1073 return ERROR_UNKNOWN_FEATURE;
1075 if (piInstalled)
1076 *piInstalled = feature->Installed;
1078 if (piAction)
1079 *piAction = feature->ActionRequest;
1081 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
1083 return ERROR_SUCCESS;
1086 /***********************************************************************
1087 * MsiGetFeatureStateW (MSI.@)
1089 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
1090 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1092 MSIPACKAGE* package;
1093 UINT ret;
1095 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
1097 if (!szFeature)
1098 return ERROR_UNKNOWN_FEATURE;
1100 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1101 if (!package)
1103 MSIHANDLE remote;
1105 if (!(remote = msi_get_remote(hInstall)))
1106 return ERROR_INVALID_HANDLE;
1108 __TRY
1110 ret = remote_GetFeatureState(remote, szFeature, piInstalled, piAction);
1112 __EXCEPT(rpc_filter)
1114 ret = GetExceptionCode();
1116 __ENDTRY
1118 return ret;
1121 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1122 msiobj_release( &package->hdr );
1123 return ret;
1126 /***********************************************************************
1127 * MsiGetFeatureCostA (MSI.@)
1129 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1130 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1132 LPWSTR szwFeature = NULL;
1133 UINT rc;
1135 szwFeature = strdupAtoW(szFeature);
1137 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1139 msi_free(szwFeature);
1141 return rc;
1144 static INT feature_cost( MSIFEATURE *feature )
1146 INT cost = 0;
1147 ComponentList *cl;
1149 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
1151 cost += cl->component->Cost;
1153 return cost;
1156 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1157 INSTALLSTATE state, LPINT cost )
1159 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1161 *cost = 0;
1162 switch (tree)
1164 case MSICOSTTREE_CHILDREN:
1166 MSIFEATURE *child;
1168 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1170 if (child->ActionRequest == state)
1171 *cost += feature_cost( child );
1173 break;
1175 case MSICOSTTREE_PARENTS:
1177 const WCHAR *feature_parent = feature->Feature_Parent;
1178 for (;;)
1180 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1181 if (!parent)
1182 break;
1184 if (parent->ActionRequest == state)
1185 *cost += feature_cost( parent );
1187 feature_parent = parent->Feature_Parent;
1189 break;
1191 case MSICOSTTREE_SELFONLY:
1192 if (feature->ActionRequest == state)
1193 *cost = feature_cost( feature );
1194 break;
1196 default:
1197 WARN("unhandled cost tree %u\n", tree);
1198 break;
1201 *cost /= 512;
1202 return ERROR_SUCCESS;
1205 /***********************************************************************
1206 * MsiGetFeatureCostW (MSI.@)
1208 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1209 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1211 MSIPACKAGE *package;
1212 MSIFEATURE *feature;
1213 UINT ret;
1215 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1216 iCostTree, iState, piCost);
1218 if (!szFeature)
1219 return ERROR_INVALID_PARAMETER;
1221 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1222 if (!package)
1224 MSIHANDLE remote;
1226 if (!(remote = msi_get_remote(hInstall)))
1227 return ERROR_INVALID_HANDLE;
1229 __TRY
1231 ret = remote_GetFeatureCost(remote, szFeature, iCostTree, iState, piCost);
1233 __EXCEPT(rpc_filter)
1235 ret = GetExceptionCode();
1237 __ENDTRY
1239 return ret;
1242 if (!piCost)
1244 msiobj_release( &package->hdr );
1245 return ERROR_INVALID_PARAMETER;
1248 feature = msi_get_loaded_feature(package, szFeature);
1250 if (feature)
1251 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1252 else
1253 ret = ERROR_UNKNOWN_FEATURE;
1255 msiobj_release( &package->hdr );
1256 return ret;
1259 /***********************************************************************
1260 * MsiGetFeatureInfoA (MSI.@)
1262 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1263 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1265 UINT r;
1266 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1268 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1269 title_len, help, help_len);
1271 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1273 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1275 msi_free( featureW );
1276 return ERROR_OUTOFMEMORY;
1278 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1280 msi_free( featureW );
1281 msi_free( titleW );
1282 return ERROR_OUTOFMEMORY;
1284 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1285 if (r == ERROR_SUCCESS)
1287 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1288 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1290 msi_free( titleW );
1291 msi_free( helpW );
1292 msi_free( featureW );
1293 return r;
1296 static DWORD map_feature_attributes( DWORD attrs )
1298 DWORD ret = 0;
1300 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1301 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1302 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1303 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1304 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1305 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1306 return ret;
1309 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1310 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1312 UINT r = ERROR_SUCCESS;
1313 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1314 int len;
1316 if (!feature) return ERROR_UNKNOWN_FEATURE;
1317 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1318 if (title_len)
1320 if (feature->Title) len = lstrlenW( feature->Title );
1321 else len = 0;
1322 if (*title_len <= len)
1324 *title_len = len;
1325 if (title) r = ERROR_MORE_DATA;
1327 else if (title)
1329 if (feature->Title) lstrcpyW( title, feature->Title );
1330 else *title = 0;
1331 *title_len = len;
1334 if (help_len)
1336 if (feature->Description) len = lstrlenW( feature->Description );
1337 else len = 0;
1338 if (*help_len <= len)
1340 *help_len = len;
1341 if (help) r = ERROR_MORE_DATA;
1343 else if (help)
1345 if (feature->Description) lstrcpyW( help, feature->Description );
1346 else *help = 0;
1347 *help_len = len;
1350 return r;
1353 /***********************************************************************
1354 * MsiGetFeatureInfoW (MSI.@)
1356 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1357 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1359 UINT r;
1360 MSIPACKAGE *package;
1362 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1363 title_len, help, help_len);
1365 if (!feature) return ERROR_INVALID_PARAMETER;
1367 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1368 return ERROR_INVALID_HANDLE;
1370 /* features may not have been loaded yet */
1371 msi_load_all_components( package );
1372 msi_load_all_features( package );
1374 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1375 msiobj_release( &package->hdr );
1376 return r;
1379 /***********************************************************************
1380 * MsiSetComponentStateA (MSI.@)
1382 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1383 INSTALLSTATE iState)
1385 UINT rc;
1386 LPWSTR szwComponent = strdupAtoW(szComponent);
1388 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1390 msi_free(szwComponent);
1392 return rc;
1395 /***********************************************************************
1396 * MsiGetComponentStateA (MSI.@)
1398 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1399 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1401 LPWSTR szwComponent= NULL;
1402 UINT rc;
1404 szwComponent= strdupAtoW(szComponent);
1406 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1408 msi_free( szwComponent);
1410 return rc;
1413 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1414 INSTALLSTATE iState)
1416 MSICOMPONENT *comp;
1418 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1420 comp = msi_get_loaded_component(package, szComponent);
1421 if (!comp)
1422 return ERROR_UNKNOWN_COMPONENT;
1424 if (comp->Enabled)
1425 comp->Action = iState;
1427 return ERROR_SUCCESS;
1430 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1431 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1433 MSICOMPONENT *comp;
1435 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1436 piInstalled, piAction);
1438 comp = msi_get_loaded_component(package,szComponent);
1439 if (!comp)
1440 return ERROR_UNKNOWN_COMPONENT;
1442 if (piInstalled)
1444 if (comp->Enabled)
1445 *piInstalled = comp->Installed;
1446 else
1447 *piInstalled = INSTALLSTATE_UNKNOWN;
1450 if (piAction)
1452 if (comp->Enabled)
1453 *piAction = comp->Action;
1454 else
1455 *piAction = INSTALLSTATE_UNKNOWN;
1458 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1459 return ERROR_SUCCESS;
1462 /***********************************************************************
1463 * MsiSetComponentStateW (MSI.@)
1465 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1466 INSTALLSTATE iState)
1468 MSIPACKAGE* package;
1469 UINT ret;
1471 if (!szComponent)
1472 return ERROR_UNKNOWN_COMPONENT;
1474 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1475 if (!package)
1477 MSIHANDLE remote;
1479 if (!(remote = msi_get_remote(hInstall)))
1480 return ERROR_INVALID_HANDLE;
1482 __TRY
1484 ret = remote_SetComponentState(remote, szComponent, iState);
1486 __EXCEPT(rpc_filter)
1488 ret = GetExceptionCode();
1490 __ENDTRY
1492 return ret;
1495 ret = MSI_SetComponentStateW(package, szComponent, iState);
1496 msiobj_release(&package->hdr);
1497 return ret;
1500 /***********************************************************************
1501 * MsiGetComponentStateW (MSI.@)
1503 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1504 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1506 MSIPACKAGE* package;
1507 UINT ret;
1509 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1510 piInstalled, piAction);
1512 if (!szComponent)
1513 return ERROR_UNKNOWN_COMPONENT;
1515 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1516 if (!package)
1518 MSIHANDLE remote;
1520 if (!(remote = msi_get_remote(hInstall)))
1521 return ERROR_INVALID_HANDLE;
1523 __TRY
1525 ret = remote_GetComponentState(remote, szComponent, piInstalled, piAction);
1527 __EXCEPT(rpc_filter)
1529 ret = GetExceptionCode();
1531 __ENDTRY
1533 return ret;
1536 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1537 msiobj_release( &package->hdr );
1538 return ret;
1541 /***********************************************************************
1542 * MsiGetLanguage (MSI.@)
1544 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1546 MSIPACKAGE* package;
1547 LANGID langid;
1549 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1550 if (!package)
1552 MSIHANDLE remote;
1554 if (!(remote = msi_get_remote(hInstall)))
1555 return ERROR_INVALID_HANDLE;
1557 __TRY
1559 langid = remote_GetLanguage(remote);
1561 __EXCEPT(rpc_filter)
1563 langid = 0;
1565 __ENDTRY
1567 return langid;
1570 langid = msi_get_property_int( package->db, L"ProductLanguage", 0 );
1571 msiobj_release( &package->hdr );
1572 return langid;
1575 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1577 WCHAR level[6];
1578 int len;
1579 UINT r;
1581 TRACE("%p %i\n", package, iInstallLevel);
1583 if (iInstallLevel > 32767)
1584 return ERROR_INVALID_PARAMETER;
1586 if (iInstallLevel < 1)
1587 return MSI_SetFeatureStates( package );
1589 len = swprintf( level, ARRAY_SIZE(level), L"%d", iInstallLevel );
1590 r = msi_set_property( package->db, L"INSTALLLEVEL", level, len );
1591 if ( r == ERROR_SUCCESS )
1592 r = MSI_SetFeatureStates( package );
1594 return r;
1597 /***********************************************************************
1598 * MsiSetInstallLevel (MSI.@)
1600 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1602 MSIPACKAGE* package;
1603 UINT r;
1605 TRACE("%d %i\n", hInstall, iInstallLevel);
1607 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1608 if (!package)
1610 MSIHANDLE remote;
1612 if (!(remote = msi_get_remote(hInstall)))
1613 return ERROR_INVALID_HANDLE;
1615 __TRY
1617 r = remote_SetInstallLevel(remote, iInstallLevel);
1619 __EXCEPT(rpc_filter)
1621 r = GetExceptionCode();
1623 __ENDTRY
1625 return r;
1628 r = MSI_SetInstallLevel( package, iInstallLevel );
1630 msiobj_release( &package->hdr );
1632 return r;
1635 /***********************************************************************
1636 * MsiGetFeatureValidStatesW (MSI.@)
1638 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1639 LPDWORD pInstallState)
1641 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1642 FIXME("%d %s %p stub returning %d\n",
1643 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1645 return ERROR_SUCCESS;
1648 /***********************************************************************
1649 * MsiGetFeatureValidStatesA (MSI.@)
1651 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1652 LPDWORD pInstallState)
1654 UINT ret;
1655 LPWSTR szwFeature = strdupAtoW(szFeature);
1657 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1659 msi_free(szwFeature);
1661 return ret;