winecfg: Constrain DPI values to the commonly supported ones.
[wine.git] / dlls / msi / install.c
blob45c55375bfd741e8285f6a9eaa7a9b3e96da9b96
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;
648 if (!(remote = msi_get_remote(hInstall)))
649 return FALSE;
651 return remote_SetMode(remote, iRunMode, fState);
654 switch (iRunMode)
656 case MSIRUNMODE_REBOOTATEND:
657 package->need_reboot_at_end = (fState != 0);
658 r = ERROR_SUCCESS;
659 break;
661 case MSIRUNMODE_REBOOTNOW:
662 package->need_reboot_now = (fState != 0);
663 r = ERROR_SUCCESS;
664 break;
666 default:
667 r = ERROR_ACCESS_DENIED;
670 msiobj_release( &package->hdr );
671 return r;
674 /***********************************************************************
675 * MsiSetFeatureStateA (MSI.@)
677 * According to the docs, when this is called it immediately recalculates
678 * all the component states as well
680 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
681 INSTALLSTATE iState)
683 LPWSTR szwFeature = NULL;
684 UINT rc;
686 szwFeature = strdupAtoW(szFeature);
688 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
690 msi_free(szwFeature);
692 return rc;
695 /* update component state based on a feature change */
696 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
698 INSTALLSTATE newstate;
699 ComponentList *cl;
701 newstate = feature->ActionRequest;
702 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
704 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
706 MSICOMPONENT *component = cl->component;
708 if (!component->Enabled) continue;
710 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
711 newstate, debugstr_w(component->Component), component->Installed,
712 component->Action, component->ActionRequest);
714 if (newstate == INSTALLSTATE_LOCAL)
716 component->Action = INSTALLSTATE_LOCAL;
717 component->ActionRequest = INSTALLSTATE_LOCAL;
719 else
721 ComponentList *clist;
722 MSIFEATURE *f;
724 component->hasLocalFeature = FALSE;
726 component->Action = newstate;
727 component->ActionRequest = newstate;
728 /* if any other feature wants it local we need to set it local */
729 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
731 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
732 f->ActionRequest != INSTALLSTATE_SOURCE )
734 continue;
736 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
738 if (clist->component == component &&
739 (f->ActionRequest == INSTALLSTATE_LOCAL ||
740 f->ActionRequest == INSTALLSTATE_SOURCE))
742 TRACE("Saved by %s\n", debugstr_w(f->Feature));
743 component->hasLocalFeature = TRUE;
745 if (component->Attributes & msidbComponentAttributesOptional)
747 if (f->Attributes & msidbFeatureAttributesFavorSource)
749 component->Action = INSTALLSTATE_SOURCE;
750 component->ActionRequest = INSTALLSTATE_SOURCE;
752 else
754 component->Action = INSTALLSTATE_LOCAL;
755 component->ActionRequest = INSTALLSTATE_LOCAL;
758 else if (component->Attributes & msidbComponentAttributesSourceOnly)
760 component->Action = INSTALLSTATE_SOURCE;
761 component->ActionRequest = INSTALLSTATE_SOURCE;
763 else
765 component->Action = INSTALLSTATE_LOCAL;
766 component->ActionRequest = INSTALLSTATE_LOCAL;
772 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
773 newstate, debugstr_w(component->Component), component->Installed,
774 component->Action, component->ActionRequest);
778 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
780 UINT rc = ERROR_SUCCESS;
781 MSIFEATURE *feature, *child;
783 TRACE("%s %i\n", debugstr_w(szFeature), iState);
785 feature = msi_get_loaded_feature( package, szFeature );
786 if (!feature)
787 return ERROR_UNKNOWN_FEATURE;
789 if (iState == INSTALLSTATE_ADVERTISED &&
790 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
791 return ERROR_FUNCTION_FAILED;
793 feature->ActionRequest = iState;
795 ACTION_UpdateComponentStates( package, feature );
797 /* update all the features that are children of this feature */
798 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
800 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
801 MSI_SetFeatureStateW(package, child->Feature, iState);
804 return rc;
807 /***********************************************************************
808 * MsiSetFeatureStateW (MSI.@)
810 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
811 INSTALLSTATE iState)
813 MSIPACKAGE* package;
814 UINT rc = ERROR_SUCCESS;
816 TRACE("%s %i\n",debugstr_w(szFeature), iState);
818 if (!szFeature)
819 return ERROR_UNKNOWN_FEATURE;
821 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
822 if (!package)
824 MSIHANDLE remote;
826 if (!(remote = msi_get_remote(hInstall)))
827 return ERROR_INVALID_HANDLE;
829 return remote_SetFeatureState(remote, szFeature, iState);
832 rc = MSI_SetFeatureStateW(package,szFeature,iState);
834 msiobj_release( &package->hdr );
835 return rc;
838 /***********************************************************************
839 * MsiSetFeatureAttributesA (MSI.@)
841 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
843 UINT r;
844 WCHAR *featureW = NULL;
846 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
848 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
850 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
851 msi_free( featureW );
852 return r;
855 static DWORD unmap_feature_attributes( DWORD attrs )
857 DWORD ret = 0;
859 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
860 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
861 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
862 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
863 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
864 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
865 return ret;
868 /***********************************************************************
869 * MsiSetFeatureAttributesW (MSI.@)
871 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
873 MSIPACKAGE *package;
874 MSIFEATURE *feature;
875 WCHAR *costing;
877 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
879 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
881 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
882 return ERROR_INVALID_HANDLE;
884 costing = msi_dup_property( package->db, szCostingComplete );
885 if (!costing || !strcmpW( costing, szOne ))
887 msi_free( costing );
888 msiobj_release( &package->hdr );
889 return ERROR_FUNCTION_FAILED;
891 msi_free( costing );
892 if (!(feature = msi_get_loaded_feature( package, name )))
894 msiobj_release( &package->hdr );
895 return ERROR_UNKNOWN_FEATURE;
897 feature->Attributes = unmap_feature_attributes( attrs );
898 msiobj_release( &package->hdr );
899 return ERROR_SUCCESS;
902 /***********************************************************************
903 * MsiGetFeatureStateA (MSI.@)
905 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
906 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
908 LPWSTR szwFeature = NULL;
909 UINT rc;
911 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
913 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
914 msi_free( szwFeature);
915 return rc;
918 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
919 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
921 MSIFEATURE *feature;
923 feature = msi_get_loaded_feature(package,szFeature);
924 if (!feature)
925 return ERROR_UNKNOWN_FEATURE;
927 if (piInstalled)
928 *piInstalled = feature->Installed;
930 if (piAction)
931 *piAction = feature->ActionRequest;
933 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
935 return ERROR_SUCCESS;
938 /***********************************************************************
939 * MsiGetFeatureStateW (MSI.@)
941 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
942 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
944 MSIPACKAGE* package;
945 UINT ret;
947 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
949 if (!szFeature)
950 return ERROR_UNKNOWN_FEATURE;
952 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
953 if (!package)
955 MSIHANDLE remote;
957 if (!(remote = msi_get_remote(hInstall)))
958 return ERROR_INVALID_HANDLE;
960 /* FIXME: should use SEH */
961 if (!piInstalled || !piAction)
962 return RPC_X_NULL_REF_POINTER;
964 return remote_GetFeatureState(remote, szFeature, piInstalled, piAction);
967 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
968 msiobj_release( &package->hdr );
969 return ret;
972 /***********************************************************************
973 * MsiGetFeatureCostA (MSI.@)
975 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
976 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
978 LPWSTR szwFeature = NULL;
979 UINT rc;
981 szwFeature = strdupAtoW(szFeature);
983 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
985 msi_free(szwFeature);
987 return rc;
990 static INT feature_cost( MSIFEATURE *feature )
992 INT cost = 0;
993 ComponentList *cl;
995 LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
997 cost += cl->component->Cost;
999 return cost;
1002 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1003 INSTALLSTATE state, LPINT cost )
1005 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1007 *cost = 0;
1008 switch (tree)
1010 case MSICOSTTREE_CHILDREN:
1012 MSIFEATURE *child;
1014 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1016 if (child->ActionRequest == state)
1017 *cost += feature_cost( child );
1019 break;
1021 case MSICOSTTREE_PARENTS:
1023 const WCHAR *feature_parent = feature->Feature_Parent;
1024 for (;;)
1026 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1027 if (!parent)
1028 break;
1030 if (parent->ActionRequest == state)
1031 *cost += feature_cost( parent );
1033 feature_parent = parent->Feature_Parent;
1035 break;
1037 case MSICOSTTREE_SELFONLY:
1038 if (feature->ActionRequest == state)
1039 *cost = feature_cost( feature );
1040 break;
1042 default:
1043 WARN("unhandled cost tree %u\n", tree);
1044 break;
1047 *cost /= 512;
1048 return ERROR_SUCCESS;
1051 /***********************************************************************
1052 * MsiGetFeatureCostW (MSI.@)
1054 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1055 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1057 MSIPACKAGE *package;
1058 MSIFEATURE *feature;
1059 UINT ret;
1061 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1062 iCostTree, iState, piCost);
1064 if (!szFeature)
1065 return ERROR_INVALID_PARAMETER;
1067 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1068 if (!package)
1070 MSIHANDLE remote;
1072 if (!(remote = msi_get_remote(hInstall)))
1073 return ERROR_INVALID_HANDLE;
1075 /* FIXME: should use SEH */
1076 if (!piCost)
1077 return RPC_X_NULL_REF_POINTER;
1079 return remote_GetFeatureCost(remote, szFeature, iCostTree, iState, piCost);
1082 if (!piCost)
1084 msiobj_release( &package->hdr );
1085 return ERROR_INVALID_PARAMETER;
1088 feature = msi_get_loaded_feature(package, szFeature);
1090 if (feature)
1091 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1092 else
1093 ret = ERROR_UNKNOWN_FEATURE;
1095 msiobj_release( &package->hdr );
1096 return ret;
1099 /***********************************************************************
1100 * MsiGetFeatureInfoA (MSI.@)
1102 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1103 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1105 UINT r;
1106 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1108 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1109 title_len, help, help_len);
1111 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1113 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1115 msi_free( featureW );
1116 return ERROR_OUTOFMEMORY;
1118 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1120 msi_free( featureW );
1121 msi_free( titleW );
1122 return ERROR_OUTOFMEMORY;
1124 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1125 if (r == ERROR_SUCCESS)
1127 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1128 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1130 msi_free( titleW );
1131 msi_free( helpW );
1132 msi_free( featureW );
1133 return r;
1136 static DWORD map_feature_attributes( DWORD attrs )
1138 DWORD ret = 0;
1140 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1141 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1142 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1143 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1144 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1145 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1146 return ret;
1149 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1150 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1152 UINT r = ERROR_SUCCESS;
1153 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1154 int len;
1156 if (!feature) return ERROR_UNKNOWN_FEATURE;
1157 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1158 if (title_len)
1160 if (feature->Title) len = strlenW( feature->Title );
1161 else len = 0;
1162 if (*title_len <= len)
1164 *title_len = len;
1165 if (title) r = ERROR_MORE_DATA;
1167 else if (title)
1169 if (feature->Title) strcpyW( title, feature->Title );
1170 else *title = 0;
1171 *title_len = len;
1174 if (help_len)
1176 if (feature->Description) len = strlenW( feature->Description );
1177 else len = 0;
1178 if (*help_len <= len)
1180 *help_len = len;
1181 if (help) r = ERROR_MORE_DATA;
1183 else if (help)
1185 if (feature->Description) strcpyW( help, feature->Description );
1186 else *help = 0;
1187 *help_len = len;
1190 return r;
1193 /***********************************************************************
1194 * MsiGetFeatureInfoW (MSI.@)
1196 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1197 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1199 UINT r;
1200 MSIPACKAGE *package;
1202 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1203 title_len, help, help_len);
1205 if (!feature) return ERROR_INVALID_PARAMETER;
1207 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1208 return ERROR_INVALID_HANDLE;
1210 /* features may not have been loaded yet */
1211 msi_load_all_components( package );
1212 msi_load_all_features( package );
1214 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1215 msiobj_release( &package->hdr );
1216 return r;
1219 /***********************************************************************
1220 * MsiSetComponentStateA (MSI.@)
1222 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1223 INSTALLSTATE iState)
1225 UINT rc;
1226 LPWSTR szwComponent = strdupAtoW(szComponent);
1228 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1230 msi_free(szwComponent);
1232 return rc;
1235 /***********************************************************************
1236 * MsiGetComponentStateA (MSI.@)
1238 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1239 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1241 LPWSTR szwComponent= NULL;
1242 UINT rc;
1244 szwComponent= strdupAtoW(szComponent);
1246 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1248 msi_free( szwComponent);
1250 return rc;
1253 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1254 INSTALLSTATE iState)
1256 MSICOMPONENT *comp;
1258 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1260 comp = msi_get_loaded_component(package, szComponent);
1261 if (!comp)
1262 return ERROR_UNKNOWN_COMPONENT;
1264 if (comp->Enabled)
1265 comp->Action = iState;
1267 return ERROR_SUCCESS;
1270 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1271 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1273 MSICOMPONENT *comp;
1275 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1276 piInstalled, piAction);
1278 comp = msi_get_loaded_component(package,szComponent);
1279 if (!comp)
1280 return ERROR_UNKNOWN_COMPONENT;
1282 if (piInstalled)
1284 if (comp->Enabled)
1285 *piInstalled = comp->Installed;
1286 else
1287 *piInstalled = INSTALLSTATE_UNKNOWN;
1290 if (piAction)
1292 if (comp->Enabled)
1293 *piAction = comp->Action;
1294 else
1295 *piAction = INSTALLSTATE_UNKNOWN;
1298 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1299 return ERROR_SUCCESS;
1302 /***********************************************************************
1303 * MsiSetComponentStateW (MSI.@)
1305 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1306 INSTALLSTATE iState)
1308 MSIPACKAGE* package;
1309 UINT ret;
1311 if (!szComponent)
1312 return ERROR_UNKNOWN_COMPONENT;
1314 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1315 if (!package)
1317 MSIHANDLE remote;
1319 if (!(remote = msi_get_remote(hInstall)))
1320 return ERROR_INVALID_HANDLE;
1322 return remote_SetComponentState(remote, szComponent, iState);
1325 ret = MSI_SetComponentStateW(package, szComponent, iState);
1326 msiobj_release(&package->hdr);
1327 return ret;
1330 /***********************************************************************
1331 * MsiGetComponentStateW (MSI.@)
1333 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1334 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1336 MSIPACKAGE* package;
1337 UINT ret;
1339 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1340 piInstalled, piAction);
1342 if (!szComponent)
1343 return ERROR_UNKNOWN_COMPONENT;
1345 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1346 if (!package)
1348 MSIHANDLE remote;
1350 if (!(remote = msi_get_remote(hInstall)))
1351 return ERROR_INVALID_HANDLE;
1353 /* FIXME: should use SEH */
1354 if (!piInstalled || !piAction)
1355 return RPC_X_NULL_REF_POINTER;
1357 return remote_GetComponentState(remote, szComponent, piInstalled, piAction);
1360 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1361 msiobj_release( &package->hdr );
1362 return ret;
1365 /***********************************************************************
1366 * MsiGetLanguage (MSI.@)
1368 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1370 MSIPACKAGE* package;
1371 LANGID langid;
1373 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1374 if (!package)
1376 MSIHANDLE remote;
1378 if (!(remote = msi_get_remote(hInstall)))
1379 return ERROR_INVALID_HANDLE;
1381 return remote_GetLanguage(remote);
1384 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1385 msiobj_release( &package->hdr );
1386 return langid;
1389 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1391 static const WCHAR fmt[] = { '%','d',0 };
1392 WCHAR level[6];
1393 int len;
1394 UINT r;
1396 TRACE("%p %i\n", package, iInstallLevel);
1398 if (iInstallLevel > 32767)
1399 return ERROR_INVALID_PARAMETER;
1401 if (iInstallLevel < 1)
1402 return MSI_SetFeatureStates( package );
1404 len = sprintfW( level, fmt, iInstallLevel );
1405 r = msi_set_property( package->db, szInstallLevel, level, len );
1406 if ( r == ERROR_SUCCESS )
1407 r = MSI_SetFeatureStates( package );
1409 return r;
1412 /***********************************************************************
1413 * MsiSetInstallLevel (MSI.@)
1415 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1417 MSIPACKAGE* package;
1418 UINT r;
1420 TRACE("%d %i\n", hInstall, iInstallLevel);
1422 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1423 if (!package)
1425 MSIHANDLE remote;
1427 if (!(remote = msi_get_remote(hInstall)))
1428 return ERROR_INVALID_HANDLE;
1430 return remote_SetInstallLevel(remote, iInstallLevel);
1433 r = MSI_SetInstallLevel( package, iInstallLevel );
1435 msiobj_release( &package->hdr );
1437 return r;
1440 /***********************************************************************
1441 * MsiGetFeatureValidStatesW (MSI.@)
1443 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1444 LPDWORD pInstallState)
1446 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1447 FIXME("%d %s %p stub returning %d\n",
1448 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1450 return ERROR_SUCCESS;
1453 /***********************************************************************
1454 * MsiGetFeatureValidStatesA (MSI.@)
1456 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1457 LPDWORD pInstallState)
1459 UINT ret;
1460 LPWSTR szwFeature = strdupAtoW(szFeature);
1462 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1464 msi_free(szwFeature);
1466 return ret;